Author: hbelusca Date: Wed Aug 5 19:06:58 2015 New Revision: 68601
URL: http://svn.reactos.org/svn/reactos?rev=68601&view=rev Log: [NTVDM]: EMS functions. - Implement function 4Dh "Get All Handles Number of Pages", 54h "Get Handle Directory / Search for Named Handle / Get Total Number of Handles" - Fix the return error of few functions. - Start handling the "system handle" (special handle 0; see the specs for more details); WIP.
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.c trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.h
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.c [iso-8859-1] Wed Aug 5 19:06:58 2015 @@ -27,6 +27,7 @@ #define EMS_DEVICE_NAME "EMMXXXX0"
#define EMS_SEGMENT_SIZE ((EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE) >> 4) +#define EMS_SYSTEM_HANDLE 0
/* PRIVATE VARIABLES **********************************************************/
@@ -45,9 +46,9 @@
static VOID InitHandlesTable(VOID) { - ULONG i; - - for (i = 0; i < EMS_MAX_HANDLES; i++) + USHORT i; + + for (i = 0; i < ARRAYSIZE(HandleTable); i++) { HandleTable[i].Allocated = FALSE; HandleTable[i].PageCount = 0; @@ -59,22 +60,21 @@ static PEMS_HANDLE CreateHandle(PUSHORT Handle) { PEMS_HANDLE HandleEntry; - ULONG i; - - for (i = 0; i < EMS_MAX_HANDLES; i++) + USHORT i; + + /* Handle 0 is reserved (system handle) */ + for (i = 1; i < ARRAYSIZE(HandleTable); i++) { HandleEntry = &HandleTable[i]; if (!HandleEntry->Allocated) { *Handle = i; - break; - } - } - - if (i == EMS_MAX_HANDLES) return NULL; - HandleEntry->Allocated = TRUE; - - return HandleEntry; + HandleEntry->Allocated = TRUE; + return HandleEntry; + } + } + + return NULL; }
static VOID FreeHandle(PEMS_HANDLE HandleEntry) @@ -82,12 +82,12 @@ HandleEntry->Allocated = FALSE; HandleEntry->PageCount = 0; RtlZeroMemory(HandleEntry->Name, sizeof(HandleEntry->Name)); - // InitializeListHead(HandleEntry->PageList); + // InitializeListHead(&HandleEntry->PageList); }
static inline PEMS_HANDLE GetHandleRecord(USHORT Handle) { - if (Handle >= EMS_MAX_HANDLES) return NULL; + if (Handle >= ARRAYSIZE(HandleTable)) return NULL; return &HandleTable[Handle]; }
@@ -116,7 +116,9 @@ }
InitializeListHead(&HandleEntry->PageList); - FreeHandle(HandleEntry); + + if (Handle != EMS_SYSTEM_HANDLE) + FreeHandle(HandleEntry);
return EMS_STATUS_SUCCESS; } @@ -162,6 +164,57 @@ return EMS_STATUS_SUCCESS; }
+static UCHAR InitSystemHandle(USHORT NumPages) +{ + // + // FIXME: This is an adapted copy of EmsAlloc!! + // + + ULONG i, CurrentIndex = 0; + PEMS_HANDLE HandleEntry = &HandleTable[EMS_SYSTEM_HANDLE]; + + /* The system handle must never have been initialized before */ + ASSERT(!HandleEntry->Allocated); + + /* Now allocate it */ + 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(EMS_SYSTEM_HANDLE); + // FIXME: For this function (and EmsAlloc as well), + // use instead an internal function that just uses + // PEMS_HANDLE pointers instead. It's only in the + // EMS interrupt handler that we should do the + // unfolding. + 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 = EMS_SYSTEM_HANDLE; + InsertTailList(&HandleEntry->PageList, &PageTable[RunStart + i].Entry); + } + } + + return EMS_STATUS_SUCCESS; +} + static PEMS_PAGE GetLogicalPage(PEMS_HANDLE HandleEntry, USHORT LogicalPage) { PLIST_ENTRY Entry = HandleEntry->PageList.Flink; @@ -236,8 +289,10 @@ USHORT Handle; UCHAR Status = EmsAlloc(getBX(), &Handle);
+ if (Status == EMS_STATUS_SUCCESS) + setDX(Handle); + setAH(Status); - if (Status == EMS_STATUS_SUCCESS) setDX(Handle); break; }
@@ -266,14 +321,18 @@ /* Save Page Map */ case 0x47: { + // FIXME: This depends on an EMS handle given in DX RtlCopyMemory(MappingBackup, Mapping, sizeof(Mapping)); + setAH(EMS_STATUS_SUCCESS); break; }
/* Restore Page Map */ case 0x48: { + // FIXME: This depends on an EMS handle given in DX RtlCopyMemory(Mapping, MappingBackup, sizeof(Mapping)); + setAH(EMS_STATUS_SUCCESS); break; }
@@ -281,9 +340,9 @@ case 0x4B: { USHORT NumOpenHandles = 0; - ULONG i; - - for (i = 0; i < EMS_MAX_HANDLES; i++) + USHORT i; + + for (i = 0; i < ARRAYSIZE(HandleTable); i++) { if (HandleTable[i].Allocated) ++NumOpenHandles; @@ -307,6 +366,29 @@
setAH(EMS_STATUS_SUCCESS); setBX(HandleEntry->PageCount); + break; + } + + /* Get All Handles Number of Pages */ + case 0x4D: + { + PEMS_HANDLE_PAGE_INFO HandlePageInfo = (PEMS_HANDLE_PAGE_INFO)SEG_OFF_TO_PTR(getES(), getDI()); + USHORT NumOpenHandles = 0; + USHORT i; + + for (i = 0; i < ARRAYSIZE(HandleTable); i++) + { + if (HandleTable[i].Allocated) + { + HandlePageInfo->Handle = i; + HandlePageInfo->PageCount = HandleTable[i].PageCount; + ++HandlePageInfo; + ++NumOpenHandles; + } + } + + setAH(EMS_STATUS_SUCCESS); + setBX(NumOpenHandles); break; }
@@ -340,7 +422,99 @@ else { DPRINT1("Invalid subfunction %02X for EMS function AH = 53h\n", getAL()); - setAH(EMS_STATUS_UNKNOWN_FUNCTION); + setAH(EMS_STATUS_INVALID_SUBFUNCTION); + } + + break; + } + + /* Handle Directory functions */ + case 0x54: + { + if (getAL() == 0x00) + { + /* Get Handle Directory */ + + PEMS_HANDLE_DIR_ENTRY HandleDir = (PEMS_HANDLE_DIR_ENTRY)SEG_OFF_TO_PTR(getES(), getDI()); + USHORT NumOpenHandles = 0; + USHORT i; + + for (i = 0; i < ARRAYSIZE(HandleTable); i++) + { + if (HandleTable[i].Allocated) + { + HandleDir->Handle = i; + RtlCopyMemory(HandleDir->Name, + HandleTable[i].Name, + sizeof(HandleDir->Name)); + ++HandleDir; + ++NumOpenHandles; + } + } + + setAH(EMS_STATUS_SUCCESS); + setAL((UCHAR)NumOpenHandles); + } + else if (getAL() == 0x01) + { + /* Search for Named Handle */ + + PUCHAR HandleName = (PUCHAR)SEG_OFF_TO_PTR(getDS(), getSI()); + PEMS_HANDLE HandleFound = NULL; + USHORT i; + + for (i = 0; i < ARRAYSIZE(HandleTable); i++) + { + if (HandleTable[i].Allocated && + RtlCompareMemory(HandleName, + HandleTable[i].Name, + sizeof(HandleTable[i].Name)) != 0) + { + HandleFound = &HandleTable[i]; + break; + } + } + + /* Bail out if no handle was found */ + if (i >= ARRAYSIZE(HandleTable)) // HandleFound == NULL + { + setAH(EMS_STATUS_HANDLE_NOT_FOUND); + break; + } + + /* Return the handle number */ + setDX(i); + + /* Sanity check: Check whether the handle was unnamed */ + i = 0; + while ((i < sizeof(HandleFound->Name)) && (HandleFound->Name[i] == '\0')) + ++i; + + if (i >= sizeof(HandleFound->Name)) + { + setAH(EMS_STATUS_UNNAMED_HANDLE); + } + else + { + setAH(EMS_STATUS_SUCCESS); + } + } + else if (getAL() == 0x02) + { + /* + * Get Total Number of Handles + * + * This function retrieves the maximum number of handles + * (allocated or not) the memory manager supports, which + * a program may request. + */ + setAH(EMS_STATUS_SUCCESS); + setBX(ARRAYSIZE(HandleTable)); + } + else + { + DPRINT1("Invalid subfunction %02X for EMS function AH = 54h\n", getAL()); + setAH(EMS_STATUS_INVALID_SUBFUNCTION); }
break; @@ -436,15 +610,14 @@ { if (getAL() == 0x00) { + PEMS_MAPPABLE_PHYS_PAGE PageArray = (PEMS_MAPPABLE_PHYS_PAGE)SEG_OFF_TO_PTR(getES(), getDI()); ULONG i; - WORD Offset = getDI();
for (i = 0; i < EMS_PHYSICAL_PAGES; i++) { - *(PWORD)SEG_OFF_TO_PTR(getES(), Offset++) = - EMS_SEGMENT + i * (EMS_PAGE_SIZE >> 4); - - *(PWORD)SEG_OFF_TO_PTR(getES(), Offset++) = i; + PageArray->PageSegment = EMS_SEGMENT + i * (EMS_PAGE_SIZE >> 4); + PageArray->PageNumber = i; + ++PageArray; }
setAH(EMS_STATUS_SUCCESS); @@ -458,7 +631,7 @@ else { DPRINT1("Invalid subfunction %02X for EMS function AH = 58h\n", getAL()); - setAH(EMS_STATUS_UNKNOWN_FUNCTION); + setAH(EMS_STATUS_INVALID_SUBFUNCTION); }
break; @@ -490,7 +663,7 @@ else { DPRINT1("Invalid subfunction %02X for EMS function AH = 59h\n", getAL()); - setAH(EMS_STATUS_UNKNOWN_FUNCTION); + setAH(EMS_STATUS_INVALID_SUBFUNCTION); }
break; @@ -601,14 +774,31 @@ return FALSE; }
+ InitHandlesTable(); + /* + * FIXME: We should ensure that the system handle is associated + * with mapped pages from conventional memory. DosEmu seems to do + * it correctly. 384kB of memory mapped. + */ + if (InitSystemHandle(384/16) != EMS_STATUS_SUCCESS) + { + DPRINT1("Impossible to allocate pages for the system handle!\n"); + + RtlFreeHeap(RtlGetProcessHeap(), 0, EmsMemory); + EmsMemory = NULL; + RtlFreeHeap(RtlGetProcessHeap(), 0, PageTable); + PageTable = NULL; + RtlFreeHeap(RtlGetProcessHeap(), 0, BitmapBuffer); + BitmapBuffer = NULL; + + UmaDescRelease(EmsSegment); + return FALSE; + } + MemInstallFastMemoryHook((PVOID)TO_LINEAR(EmsSegment, 0), EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE, EmsReadMemory, EmsWriteMemory); - - // FIXME: The EMS driver MUST automatically initialize handle 0x0000 - // (operating system handle) as per the specification says! - InitHandlesTable();
/* Create the device */ Node = DosCreateDeviceEx(DOS_DEVATTR_IOCTL | DOS_DEVATTR_CHARACTER,
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.h [iso-8859-1] Wed Aug 5 19:06:58 2015 @@ -23,15 +23,19 @@ /* 16 MB of EMS memory */ #define EMS_TOTAL_PAGES 1024
-#define EMS_STATUS_SUCCESS 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 +#define EMS_STATUS_SUCCESS 0x00 +#define EMS_STATUS_INTERNAL_ERROR 0x80 +#define EMS_STATUS_INVALID_HANDLE 0x83 +#define EMS_STATUS_UNKNOWN_FUNCTION 0x84 +#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_INVALID_SUBFUNCTION 0x8F +#define EMS_STATUS_HANDLE_NOT_FOUND 0xA0 +#define EMS_STATUS_UNNAMED_HANDLE 0xA1 +#define EMS_STATUS_HANDLE_ALREADY_EXISTS 0xA1
typedef struct _EMS_HANDLE { @@ -49,6 +53,18 @@
#pragma pack(push, 1)
+typedef struct _EMS_HANDLE_PAGE_INFO +{ + USHORT Handle; + USHORT PageCount; +} EMS_HANDLE_PAGE_INFO, *PEMS_HANDLE_PAGE_INFO; + +typedef struct _EMS_HANDLE_DIR_ENTRY +{ + USHORT Handle; + UCHAR Name[8]; +} EMS_HANDLE_DIR_ENTRY, *PEMS_HANDLE_DIR_ENTRY; + typedef struct _EMS_COPY_DATA { ULONG RegionLength; @@ -61,6 +77,12 @@ USHORT DestOffset; USHORT DestSegment; } EMS_COPY_DATA, *PEMS_COPY_DATA; + +typedef struct _EMS_MAPPABLE_PHYS_PAGE +{ + USHORT PageSegment; + USHORT PageNumber; +} EMS_MAPPABLE_PHYS_PAGE, *PEMS_MAPPABLE_PHYS_PAGE;
typedef struct _EMS_HARDWARE_INFO {