Author: aandrejevic Date: Sat Mar 7 00:43:17 2015 New Revision: 66596
URL: http://svn.reactos.org/svn/reactos?rev=66596&view=rev Log: [NTVDM] Begin implementing Expanded Memory Space (EMS) support.
Added: trunk/reactos/subsystems/mvdm/ntvdm/ems.c (with props) trunk/reactos/subsystems/mvdm/ntvdm/ems.h (with props) Modified: trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt trunk/reactos/subsystems/mvdm/ntvdm/emulator.c
Modified: trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/CMake... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt [iso-8859-1] Sat Mar 7 00:43:17 2015 @@ -33,6 +33,7 @@ dos/mouse32.c dos/dem.c clock.c + ems.c emulator.c int32.c io.c
Added: trunk/reactos/subsystems/mvdm/ntvdm/ems.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/ems.c... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/ems.c (added) +++ trunk/reactos/subsystems/mvdm/ntvdm/ems.c [iso-8859-1] Sat Mar 7 00:43:17 2015 @@ -0,0 +1,231 @@ +/* + * COPYRIGHT: GPLv2+ - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: ems.c + * PURPOSE: Expanded Memory Support + * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "bios/bios32/bios32p.h" +#include <ndk/rtltypes.h> +#include <ndk/rtlfuncs.h> +#include "ems.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static RTL_BITMAP AllocBitmap; +static ULONG BitmapBuffer[(EMS_TOTAL_PAGES + sizeof(ULONG) - 1) / sizeof(ULONG)]; +static EMS_PAGE PageTable[EMS_TOTAL_PAGES]; +static EMS_HANDLE HandleTable[EMS_MAX_HANDLES]; +static PVOID Mapping[EMS_PHYSICAL_PAGES] = { NULL }; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static USHORT EmsFree(USHORT Handle) +{ + PLIST_ENTRY Entry; + PEMS_HANDLE HandleEntry = &HandleTable[Handle]; + + if (Handle >= EMS_MAX_HANDLES || !HandleEntry->Allocated) + { + return EMS_STATUS_INVALID_HANDLE; + } + + for (Entry = HandleEntry->PageList.Flink; + Entry != &HandleEntry->PageList; + Entry = Entry->Flink) + { + PEMS_PAGE PageEntry = (PEMS_PAGE)CONTAINING_RECORD(Entry, EMS_PAGE, Entry); + ULONG PageNumber = (ULONG)(((ULONG_PTR)PageEntry - (ULONG_PTR)PageTable) / sizeof(EMS_PAGE)); + + /* Free the page */ + RtlClearBits(&AllocBitmap, PageNumber, 1); + } + + HandleEntry->Allocated = FALSE; + HandleEntry->PageCount = 0; + InitializeListHead(&HandleEntry->PageList); + + return EMS_STATUS_OK; +} + +static UCHAR EmsAlloc(USHORT NumPages, PUSHORT Handle) +{ + ULONG i, CurrentIndex = 0; + PEMS_HANDLE HandleEntry; + + if (NumPages == 0) return EMS_STATUS_ZERO_PAGES; + + for (i = 0; i < EMS_MAX_HANDLES; i++) + { + HandleEntry = &HandleTable[i]; + if (!HandleEntry->Allocated) + { + *Handle = i; + break; + } + } + + if (i == EMS_MAX_HANDLES) return EMS_STATUS_NO_MORE_HANDLES; + HandleEntry->Allocated = TRUE; + + while (HandleEntry->PageCount < NumPages) + { + ULONG RunStart; + ULONG RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart); + + if (RunSize == 0) + { + /* Free what's been allocated already and report failure */ + EmsFree(*Handle); + return EMS_STATUS_INSUFFICIENT_PAGES; + } + else if ((HandleEntry->PageCount + RunSize) > NumPages) + { + /* We don't need the entire run */ + RunSize = NumPages - HandleEntry->PageCount; + } + + CurrentIndex = RunStart + RunSize; + HandleEntry->PageCount += RunSize; + RtlSetBits(&AllocBitmap, RunStart, RunSize); + + for (i = 0; i < RunSize; i++) + { + PageTable[RunStart + i].Handle = *Handle; + InsertTailList(&HandleEntry->PageList, &PageTable[RunStart + i].Entry); + } + } + + return EMS_STATUS_OK; +} + +static USHORT EmsMap(USHORT Handle, UCHAR PhysicalPage, USHORT LogicalPage) +{ + PLIST_ENTRY Entry; + PEMS_PAGE PageEntry; + PEMS_HANDLE HandleEntry = &HandleTable[Handle]; + ULONG PageNumber; + + if (PhysicalPage >= EMS_PHYSICAL_PAGES) return EMS_STATUS_INV_PHYSICAL_PAGE; + if (LogicalPage == 0xFFFF) + { + /* Unmap */ + Mapping[PhysicalPage] = NULL; + return EMS_STATUS_OK; + } + + if (Handle >= EMS_MAX_HANDLES || !HandleEntry->Allocated) return EMS_STATUS_INVALID_HANDLE; + + Entry = HandleEntry->PageList.Flink; + while (LogicalPage) + { + if (Entry == &HandleEntry->PageList) break; + + LogicalPage--; + Entry = Entry->Flink; + } + + if (Entry == &HandleEntry->PageList) return EMS_STATUS_INV_LOGICAL_PAGE; + + PageEntry = (PEMS_PAGE)CONTAINING_RECORD(Entry, EMS_PAGE, Entry); + PageNumber = (ULONG)(((ULONG_PTR)PageEntry - (ULONG_PTR)PageTable) / sizeof(EMS_PAGE)); + Mapping[PhysicalPage] = (PVOID)(EMS_ADDRESS + PageNumber * EMS_PAGE_SIZE); + + return EMS_STATUS_OK; +} + +static VOID WINAPI EmsIntHandler(LPWORD Stack) +{ + switch (getAH()) + { + /* Get Manager Status */ + case 0x40: + { + setAH(EMS_STATUS_OK); + break; + } + + /* Get Page Frame Segment */ + case 0x41: + { + setAH(EMS_STATUS_OK); + setBX(EMS_SEGMENT); + break; + } + + /* Get Number Of Pages */ + case 0x42: + { + setAH(EMS_STATUS_OK); + setBX(RtlNumberOfClearBits(&AllocBitmap)); + setDX(EMS_TOTAL_PAGES); + break; + } + + /* Get Handle And Allocate Memory */ + case 0x43: + { + USHORT Handle; + UCHAR Status = EmsAlloc(getBX(), &Handle); + + setAH(Status); + if (Status == EMS_STATUS_OK) setDX(Handle); + break; + } + + /* Map Memory */ + case 0x44: + { + setAH(EmsMap(getDX(), getAL(), getBX())); + break; + } + + /* Release Handle And Memory */ + case 0x45: + { + setAH(EmsFree(getDX())); + break; + } + + default: + { + DPRINT1("EMS function AH = %02X NOT IMPLEMENTED\n", getAH()); + setAH(EMS_STATUS_UNKNOWN_FUNCTION); + break; + } + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size) +{ + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; +} + +VOID EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size) +{ + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; +} + +VOID EmsInitialize(VOID) +{ + ULONG i; + RtlInitializeBitMap(&AllocBitmap, BitmapBuffer, EMS_TOTAL_PAGES); + + for (i = 0; i < EMS_MAX_HANDLES; i++) + { + HandleTable[i].Allocated = FALSE; + HandleTable[i].PageCount = 0; + InitializeListHead(&HandleTable[i].PageList); + } + + RegisterBiosInt32(EMS_INTERRUPT_NUM, EmsIntHandler); +}
Propchange: trunk/reactos/subsystems/mvdm/ntvdm/ems.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/subsystems/mvdm/ntvdm/ems.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/ems.h... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/ems.h (added) +++ trunk/reactos/subsystems/mvdm/ntvdm/ems.h [iso-8859-1] Sat Mar 7 00:43:17 2015 @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: GPLv2+ - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: ems.h + * PURPOSE: Expanded Memory Support + * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + */ + +#ifndef _EMS_H_ +#define _EMS_H_ + +/* DEFINITIONS ****************************************************************/ + +#define EMS_INTERRUPT_NUM 0x67 +#define EMS_SEGMENT 0xE000 +#define EMS_MAX_HANDLES 16 +#define EMS_TOTAL_PAGES 256 +#define EMS_PAGE_BITS 14 +#define EMS_PAGE_SIZE (1 << EMS_PAGE_BITS) +#define EMS_ADDRESS 0xA00000 +#define EMS_PHYSICAL_PAGES 4 +#define EMS_START_ADDRESS (EMS_SEGMENT << 4) +#define EMS_END_ADDRESS (EMS_START_ADDRESS + EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE) + +#define EMS_STATUS_OK 0x00 +#define EMS_STATUS_INTERNAL_ERROR 0x80 +#define EMS_STATUS_INVALID_HANDLE 0x83 +#define EMS_STATUS_NO_MORE_HANDLES 0x85 +#define EMS_STATUS_INSUFFICIENT_PAGES 0x88 +#define EMS_STATUS_ZERO_PAGES 0x89 +#define EMS_STATUS_INV_LOGICAL_PAGE 0x8A +#define EMS_STATUS_INV_PHYSICAL_PAGE 0x8B +#define EMS_STATUS_UNKNOWN_FUNCTION 0x8F + +typedef struct _EMS_HANDLE +{ + BOOLEAN Allocated; + USHORT PageCount; + LIST_ENTRY PageList; +} EMS_HANDLE, *PEMS_HANDLE; + +typedef struct _EMS_PAGE +{ + LIST_ENTRY Entry; + USHORT Handle; +} EMS_PAGE, *PEMS_PAGE; + +/* FUNCTIONS ******************************************************************/ + +VOID EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size); +VOID EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size); +VOID EmsInitialize(VOID); + +#endif // _EMS_H_ + +/* EOF */
Propchange: trunk/reactos/subsystems/mvdm/ntvdm/ems.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/subsystems/mvdm/ntvdm/emulator.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/emula... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/emulator.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/emulator.c [iso-8859-1] Sat Mar 7 00:43:17 2015 @@ -30,6 +30,7 @@ #include "hardware/sound/speaker.h" #include "hardware/pit.h" #include "hardware/video/vga.h" +#include "ems.h"
#include "vddsup.h" #include "io.h" @@ -619,6 +620,9 @@ /* Initialize I/O ports */ /* Initialize RAM */
+ /* Initialize EMS */ + EmsInitialize(); + /* Initialize the CPU */
/* Initialize the internal clock */