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/…
==============================================================================
--- 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/…
==============================================================================
--- 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
{