- Increase the maximum number of EMS handles to the maximum permitted by the specification (ie. 255 handles)
- Zero out EMS handles names.
- EMS status are always returned in the AH register!
- Implement functions 4Bh "Get Number of Opened Handles" and 4Ch "Get Handle Number of Pages"
- Remove an hardcoded value.
- Cosmetic change: rename EMS_STATUS_OK to EMS_STATUS_SUCCESS to comply with the name convention used also in XMS, etc...

svn path=/trunk/; revision=68600
This commit is contained in:
Hermès Bélusca-Maïto 2015-08-05 15:12:46 +00:00
parent 7f132c17b0
commit f4853ceb55
2 changed files with 72 additions and 38 deletions

View file

@ -4,6 +4,9 @@
* FILE: emsdrv.c * FILE: emsdrv.c
* PURPOSE: DOS EMS Driver * PURPOSE: DOS EMS Driver
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* DOCUMENTATION: Official specification:
* LIM EMS v4.0: http://www.phatcode.net/res/218/files/limems40.txt
*/ */
/* INCLUDES *******************************************************************/ /* INCLUDES *******************************************************************/
@ -48,6 +51,7 @@ static VOID InitHandlesTable(VOID)
{ {
HandleTable[i].Allocated = FALSE; HandleTable[i].Allocated = FALSE;
HandleTable[i].PageCount = 0; HandleTable[i].PageCount = 0;
RtlZeroMemory(HandleTable[i].Name, sizeof(HandleTable[i].Name));
InitializeListHead(&HandleTable[i].PageList); InitializeListHead(&HandleTable[i].PageList);
} }
} }
@ -77,6 +81,8 @@ static VOID FreeHandle(PEMS_HANDLE HandleEntry)
{ {
HandleEntry->Allocated = FALSE; HandleEntry->Allocated = FALSE;
HandleEntry->PageCount = 0; HandleEntry->PageCount = 0;
RtlZeroMemory(HandleEntry->Name, sizeof(HandleEntry->Name));
// InitializeListHead(HandleEntry->PageList);
} }
static inline PEMS_HANDLE GetHandleRecord(USHORT Handle) static inline PEMS_HANDLE GetHandleRecord(USHORT Handle)
@ -110,10 +116,9 @@ static UCHAR EmsFree(USHORT Handle)
} }
InitializeListHead(&HandleEntry->PageList); InitializeListHead(&HandleEntry->PageList);
FreeHandle(HandleEntry); FreeHandle(HandleEntry);
return EMS_STATUS_OK; return EMS_STATUS_SUCCESS;
} }
static UCHAR EmsAlloc(USHORT NumPages, PUSHORT Handle) static UCHAR EmsAlloc(USHORT NumPages, PUSHORT Handle)
@ -154,7 +159,7 @@ static UCHAR EmsAlloc(USHORT NumPages, PUSHORT Handle)
} }
} }
return EMS_STATUS_OK; return EMS_STATUS_SUCCESS;
} }
static PEMS_PAGE GetLogicalPage(PEMS_HANDLE HandleEntry, USHORT LogicalPage) static PEMS_PAGE GetLogicalPage(PEMS_HANDLE HandleEntry, USHORT LogicalPage)
@ -186,7 +191,7 @@ static UCHAR EmsMap(USHORT Handle, UCHAR PhysicalPage, USHORT LogicalPage)
{ {
/* Unmap */ /* Unmap */
Mapping[PhysicalPage] = NULL; Mapping[PhysicalPage] = NULL;
return EMS_STATUS_OK; return EMS_STATUS_SUCCESS;
} }
PageEntry = GetLogicalPage(HandleEntry, LogicalPage); PageEntry = GetLogicalPage(HandleEntry, LogicalPage);
@ -194,7 +199,7 @@ static UCHAR EmsMap(USHORT Handle, UCHAR PhysicalPage, USHORT LogicalPage)
Mapping[PhysicalPage] = (PVOID)((ULONG_PTR)EmsMemory Mapping[PhysicalPage] = (PVOID)((ULONG_PTR)EmsMemory
+ ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE); + ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE);
return EMS_STATUS_OK; return EMS_STATUS_SUCCESS;
} }
static VOID WINAPI EmsIntHandler(LPWORD Stack) static VOID WINAPI EmsIntHandler(LPWORD Stack)
@ -204,22 +209,22 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
/* Get Manager Status */ /* Get Manager Status */
case 0x40: case 0x40:
{ {
setAH(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
break; break;
} }
/* Get Page Frame Segment */ /* Get Page Frame Segment */
case 0x41: case 0x41:
{ {
setAH(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
setBX(EmsSegment); setBX(EmsSegment);
break; break;
} }
/* Get Number of Pages */ /* Get Number of Unallocated Pages */
case 0x42: case 0x42:
{ {
setAH(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
setBX(RtlNumberOfClearBits(&AllocBitmap)); setBX(RtlNumberOfClearBits(&AllocBitmap));
setDX(EmsTotalPages); setDX(EmsTotalPages);
break; break;
@ -232,7 +237,7 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
UCHAR Status = EmsAlloc(getBX(), &Handle); UCHAR Status = EmsAlloc(getBX(), &Handle);
setAH(Status); setAH(Status);
if (Status == EMS_STATUS_OK) setDX(Handle); if (Status == EMS_STATUS_SUCCESS) setDX(Handle);
break; break;
} }
@ -253,7 +258,7 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
/* Get EMM Version */ /* Get EMM Version */
case 0x46: case 0x46:
{ {
setAH(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
setAL(EMS_VERSION_NUM); setAL(EMS_VERSION_NUM);
break; break;
} }
@ -272,6 +277,39 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
break; break;
} }
/* Get Number of Opened Handles */
case 0x4B:
{
USHORT NumOpenHandles = 0;
ULONG i;
for (i = 0; i < EMS_MAX_HANDLES; i++)
{
if (HandleTable[i].Allocated)
++NumOpenHandles;
}
setAH(EMS_STATUS_SUCCESS);
setBX(NumOpenHandles);
break;
}
/* Get Handle Number of Pages */
case 0x4C:
{
PEMS_HANDLE HandleEntry = GetHandleRecord(getDX());
if (!ValidateHandle(HandleEntry))
{
setAH(EMS_STATUS_INVALID_HANDLE);
break;
}
setAH(EMS_STATUS_SUCCESS);
setBX(HandleEntry->PageCount);
break;
}
/* Get/Set Handle Name */ /* Get/Set Handle Name */
case 0x53: case 0x53:
{ {
@ -279,7 +317,7 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
if (!ValidateHandle(HandleEntry)) if (!ValidateHandle(HandleEntry))
{ {
setAL(EMS_STATUS_INVALID_HANDLE); setAH(EMS_STATUS_INVALID_HANDLE);
break; break;
} }
@ -289,7 +327,7 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
RtlCopyMemory(SEG_OFF_TO_PTR(getES(), getDI()), RtlCopyMemory(SEG_OFF_TO_PTR(getES(), getDI()),
HandleEntry->Name, HandleEntry->Name,
sizeof(HandleEntry->Name)); sizeof(HandleEntry->Name));
setAH(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
} }
else if (getAL() == 0x01) else if (getAL() == 0x01)
{ {
@ -297,7 +335,7 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
RtlCopyMemory(HandleEntry->Name, RtlCopyMemory(HandleEntry->Name,
SEG_OFF_TO_PTR(getDS(), getSI()), SEG_OFF_TO_PTR(getDS(), getSI()),
sizeof(HandleEntry->Name)); sizeof(HandleEntry->Name));
setAH(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
} }
else else
{ {
@ -321,18 +359,16 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
{ {
/* Expanded memory */ /* Expanded memory */
HandleEntry = GetHandleRecord(Data->SourceHandle); HandleEntry = GetHandleRecord(Data->SourceHandle);
if (!ValidateHandle(HandleEntry)) if (!ValidateHandle(HandleEntry))
{ {
setAL(EMS_STATUS_INVALID_HANDLE); setAH(EMS_STATUS_INVALID_HANDLE);
break; break;
} }
PageEntry = GetLogicalPage(HandleEntry, Data->SourceSegment); PageEntry = GetLogicalPage(HandleEntry, Data->SourceSegment);
if (!PageEntry) if (!PageEntry)
{ {
setAL(EMS_STATUS_INV_LOGICAL_PAGE); setAH(EMS_STATUS_INV_LOGICAL_PAGE);
break; break;
} }
@ -350,18 +386,16 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
{ {
/* Expanded memory */ /* Expanded memory */
HandleEntry = GetHandleRecord(Data->DestHandle); HandleEntry = GetHandleRecord(Data->DestHandle);
if (!ValidateHandle(HandleEntry)) if (!ValidateHandle(HandleEntry))
{ {
setAL(EMS_STATUS_INVALID_HANDLE); setAH(EMS_STATUS_INVALID_HANDLE);
break; break;
} }
PageEntry = GetLogicalPage(HandleEntry, Data->DestSegment); PageEntry = GetLogicalPage(HandleEntry, Data->DestSegment);
if (!PageEntry) if (!PageEntry)
{ {
setAL(EMS_STATUS_INV_LOGICAL_PAGE); setAH(EMS_STATUS_INV_LOGICAL_PAGE);
break; break;
} }
@ -393,7 +427,7 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
RtlMoveMemory(DestPtr, SourcePtr, Data->RegionLength); RtlMoveMemory(DestPtr, SourcePtr, Data->RegionLength);
} }
setAL(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
break; break;
} }
@ -413,12 +447,12 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
*(PWORD)SEG_OFF_TO_PTR(getES(), Offset++) = i; *(PWORD)SEG_OFF_TO_PTR(getES(), Offset++) = i;
} }
setAH(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
setCX(EMS_PHYSICAL_PAGES); setCX(EMS_PHYSICAL_PAGES);
} }
else if (getAL() == 0x01) else if (getAL() == 0x01)
{ {
setAH(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
setCX(EMS_PHYSICAL_PAGES); setCX(EMS_PHYSICAL_PAGES);
} }
else else
@ -444,12 +478,12 @@ static VOID WINAPI EmsIntHandler(LPWORD Stack)
HardwareInfo->DmaRegisterSets = 0; HardwareInfo->DmaRegisterSets = 0;
HardwareInfo->DmaChannelOperation = 0; HardwareInfo->DmaChannelOperation = 0;
setAH(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
} }
else if (getAL() == 0x01) else if (getAL() == 0x01)
{ {
/* Same as function AH = 42h */ /* Same as function AH = 42h */
setAH(EMS_STATUS_OK); setAH(EMS_STATUS_SUCCESS);
setBX(RtlNumberOfClearBits(&AllocBitmap)); setBX(RtlNumberOfClearBits(&AllocBitmap));
setDX(EmsTotalPages); setDX(EmsTotalPages);
} }
@ -517,7 +551,6 @@ static WORD NTAPI EmsDrvDispatchIoctlRead(PDOS_DEVICE_NODE Device, DWORD Buffer,
{ {
// TODO: NOT IMPLEMENTED // TODO: NOT IMPLEMENTED
UNIMPLEMENTED; UNIMPLEMENTED;
return DOS_DEVSTAT_DONE; return DOS_DEVSTAT_DONE;
} }
@ -532,8 +565,6 @@ BOOLEAN EmsDrvInitialize(USHORT Segment, ULONG TotalPages)
Size = EMS_SEGMENT_SIZE; // Size in paragraphs Size = EMS_SEGMENT_SIZE; // Size in paragraphs
if (!UmaDescReserve(&EmsSegment, &Size)) return FALSE; if (!UmaDescReserve(&EmsSegment, &Size)) return FALSE;
InitHandlesTable();
EmsTotalPages = TotalPages; EmsTotalPages = TotalPages;
BitmapBuffer = RtlAllocateHeap(RtlGetProcessHeap(), BitmapBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
@ -575,16 +606,18 @@ BOOLEAN EmsDrvInitialize(USHORT Segment, ULONG TotalPages)
EmsReadMemory, EmsReadMemory,
EmsWriteMemory); EmsWriteMemory);
// FIXME: The EMS driver MUST automatically initialize handle 0x0000
// (operating system handle) as per the specification says!
InitHandlesTable();
/* Create the device */ /* Create the device */
Node = DosCreateDeviceEx(DOS_DEVATTR_IOCTL | DOS_DEVATTR_CHARACTER, Node = DosCreateDeviceEx(DOS_DEVATTR_IOCTL | DOS_DEVATTR_CHARACTER,
EMS_DEVICE_NAME, EMS_DEVICE_NAME,
32); Int16To32StubSize);
Node->IoctlReadRoutine = EmsDrvDispatchIoctlRead; Node->IoctlReadRoutine = EmsDrvDispatchIoctlRead;
RegisterInt32(MAKELONG(sizeof(DOS_DRIVER) + DEVICE_CODE_SIZE, HIWORD(Node->Driver)), RegisterInt32(DEVICE_PRIVATE_AREA(Node->Driver),
EMS_INTERRUPT_NUM, EMS_INTERRUPT_NUM, EmsIntHandler, NULL);
EmsIntHandler,
NULL);
return TRUE; return TRUE;
} }

View file

@ -14,7 +14,8 @@
#define EMS_VERSION_NUM 0x40 #define EMS_VERSION_NUM 0x40
#define EMS_INTERRUPT_NUM 0x67 #define EMS_INTERRUPT_NUM 0x67
#define EMS_SEGMENT 0xD000 // Default segment #define EMS_SEGMENT 0xD000 // Default segment
#define EMS_MAX_HANDLES 16 // Specification: Operating system handle 0x0000; user handles from 0x0001 to 0x00FE
#define EMS_MAX_HANDLES 255
#define EMS_PAGE_BITS 14 #define EMS_PAGE_BITS 14
#define EMS_PAGE_SIZE (1 << EMS_PAGE_BITS) #define EMS_PAGE_SIZE (1 << EMS_PAGE_BITS)
#define EMS_PHYSICAL_PAGES 4 #define EMS_PHYSICAL_PAGES 4
@ -22,7 +23,7 @@
/* 16 MB of EMS memory */ /* 16 MB of EMS memory */
#define EMS_TOTAL_PAGES 1024 #define EMS_TOTAL_PAGES 1024
#define EMS_STATUS_OK 0x00 #define EMS_STATUS_SUCCESS 0x00
#define EMS_STATUS_INTERNAL_ERROR 0x80 #define EMS_STATUS_INTERNAL_ERROR 0x80
#define EMS_STATUS_INVALID_HANDLE 0x83 #define EMS_STATUS_INVALID_HANDLE 0x83
#define EMS_STATUS_NO_MORE_HANDLES 0x85 #define EMS_STATUS_NO_MORE_HANDLES 0x85