mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:12:59 +00:00
[NTVDM]
Implement basic XMS functions. svn path=/trunk/; revision=67340
This commit is contained in:
parent
274901555c
commit
25840ba03f
2 changed files with 215 additions and 0 deletions
|
@ -17,6 +17,7 @@
|
|||
#include "dos.h"
|
||||
#include "dos/dem.h"
|
||||
#include "device.h"
|
||||
#include "himem.h"
|
||||
|
||||
#define XMS_DEVICE_NAME "XMSXXXX0"
|
||||
#define XMS_BOP 0x52
|
||||
|
@ -36,9 +37,117 @@ static const BYTE EntryProcedure[] = {
|
|||
};
|
||||
|
||||
static PDOS_DEVICE_NODE Node = NULL;
|
||||
static XMS_HANDLE HandleTable[XMS_MAX_HANDLES];
|
||||
static WORD FreeBlocks = XMS_BLOCKS;
|
||||
static RTL_BITMAP AllocBitmap;
|
||||
static ULONG BitmapBuffer[(XMS_BLOCKS + 31) / 32];
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static inline PXMS_HANDLE GetHandleRecord(WORD Handle)
|
||||
{
|
||||
PXMS_HANDLE Entry = &HandleTable[Handle - 1];
|
||||
if (Handle == 0 || Handle >= XMS_MAX_HANDLES) return NULL;
|
||||
|
||||
return Entry->Size ? Entry : NULL;
|
||||
}
|
||||
|
||||
static CHAR XmsAlloc(WORD Size, PWORD Handle)
|
||||
{
|
||||
BYTE i;
|
||||
PXMS_HANDLE HandleEntry;
|
||||
|
||||
if (Size > FreeBlocks) return XMS_STATUS_OUT_OF_MEMORY;
|
||||
|
||||
for (i = 0; i < XMS_MAX_HANDLES; i++)
|
||||
{
|
||||
HandleEntry = &HandleTable[i];
|
||||
if (HandleEntry->Handle == 0)
|
||||
{
|
||||
*Handle = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == XMS_MAX_HANDLES) return XMS_STATUS_OUT_OF_HANDLES;
|
||||
|
||||
HandleEntry->Handle = i + 1;
|
||||
HandleEntry->LockCount = 0;
|
||||
HandleEntry->Size = Size;
|
||||
FreeBlocks -= Size;
|
||||
|
||||
return XMS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static CHAR XmsFree(WORD Handle)
|
||||
{
|
||||
PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
|
||||
if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE;
|
||||
if (HandleEntry->LockCount) return XMS_STATUS_LOCKED;
|
||||
|
||||
HandleEntry->Handle = 0;
|
||||
FreeBlocks += HandleEntry->Size;
|
||||
|
||||
return XMS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static CHAR XmsLock(WORD Handle, PDWORD Address)
|
||||
{
|
||||
DWORD CurrentIndex = 0;
|
||||
PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
|
||||
|
||||
if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE;
|
||||
if (HandleEntry->LockCount == 0xFF) return XMS_STATUS_LOCK_OVERFLOW;
|
||||
|
||||
if (HandleEntry->LockCount)
|
||||
{
|
||||
/* Just increment the lock count */
|
||||
HandleEntry->LockCount++;
|
||||
return XMS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
while (CurrentIndex < XMS_BLOCKS)
|
||||
{
|
||||
ULONG RunStart;
|
||||
ULONG RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart);
|
||||
if (RunSize == 0) break;
|
||||
|
||||
if (RunSize >= HandleEntry->Size)
|
||||
{
|
||||
/* Lock it here */
|
||||
HandleEntry->LockCount++;
|
||||
HandleEntry->Address = XMS_ADDRESS + RunStart * XMS_BLOCK_SIZE;
|
||||
|
||||
RtlSetBits(&AllocBitmap, RunStart, RunSize);
|
||||
*Address = HandleEntry->Address;
|
||||
return XMS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Keep searching */
|
||||
CurrentIndex = RunStart + RunSize;
|
||||
}
|
||||
|
||||
/* Can't find any suitable range */
|
||||
return XMS_STATUS_CANNOT_LOCK;
|
||||
}
|
||||
|
||||
static CHAR XmsUnlock(WORD Handle)
|
||||
{
|
||||
DWORD BlockNumber;
|
||||
PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
|
||||
|
||||
if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE;
|
||||
if (!HandleEntry->LockCount) return XMS_STATUS_NOT_LOCKED;
|
||||
|
||||
/* Decrement the lock count and exit early if it's still locked */
|
||||
if (--HandleEntry->LockCount) return XMS_STATUS_SUCCESS;
|
||||
|
||||
BlockNumber = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE;
|
||||
RtlClearBits(&AllocBitmap, BlockNumber, HandleEntry->Size);
|
||||
|
||||
return XMS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID WINAPI XmsBopProcedure(LPWORD Stack)
|
||||
{
|
||||
switch (getAH())
|
||||
|
@ -52,9 +161,85 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Query Free Extended Memory */
|
||||
case 0x08:
|
||||
{
|
||||
setAX(FreeBlocks);
|
||||
setDX(XMS_BLOCKS);
|
||||
setBL(XMS_STATUS_SUCCESS);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Allocate Extended Memory Block */
|
||||
case 0x09:
|
||||
{
|
||||
WORD Handle;
|
||||
CHAR Result = XmsAlloc(getDX(), &Handle);
|
||||
|
||||
if (Result >= 0)
|
||||
{
|
||||
setAX(1);
|
||||
setDX(Handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
setAX(0);
|
||||
setBL(Result);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Free Extended Memory Block */
|
||||
case 0x0A:
|
||||
{
|
||||
CHAR Result = XmsFree(getDX());
|
||||
|
||||
setAX(Result >= 0);
|
||||
setBL(Result);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Lock Extended Memory Block */
|
||||
case 0x0C:
|
||||
{
|
||||
DWORD Address;
|
||||
CHAR Result = XmsLock(getDX(), &Address);
|
||||
|
||||
if (Result >= 0)
|
||||
{
|
||||
setAX(1);
|
||||
|
||||
/* Store the LINEAR address in DX:BX */
|
||||
setDX(HIWORD(Address));
|
||||
setBX(LOWORD(Address));
|
||||
}
|
||||
else
|
||||
{
|
||||
setAX(0);
|
||||
setBL(Result);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unlock Extended Memory Block */
|
||||
case 0x0D:
|
||||
{
|
||||
CHAR Result = XmsUnlock(getDX());
|
||||
|
||||
setAX(Result >= 0);
|
||||
setBL(Result);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
DPRINT1("XMS command AH = 0x%02X NOT IMPLEMENTED\n", getAH());
|
||||
setBL(XMS_STATUS_NOT_IMPLEMENTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +255,10 @@ BOOLEAN XmsGetDriverEntry(PDWORD Pointer)
|
|||
|
||||
VOID XmsInitialize(VOID)
|
||||
{
|
||||
RtlZeroMemory(HandleTable, sizeof(HandleTable));
|
||||
RtlZeroMemory(BitmapBuffer, sizeof(BitmapBuffer));
|
||||
RtlInitializeBitMap(&AllocBitmap, BitmapBuffer, XMS_BLOCKS);
|
||||
|
||||
Node = DosCreateDeviceEx(DOS_DEVATTR_IOCTL | DOS_DEVATTR_CHARACTER,
|
||||
XMS_DEVICE_NAME,
|
||||
sizeof(EntryProcedure));
|
||||
|
|
|
@ -6,6 +6,32 @@
|
|||
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
||||
*/
|
||||
|
||||
/* DEFINITIONS ****************************************************************/
|
||||
|
||||
#define XMS_ADDRESS 0x110000
|
||||
#define XMS_BLOCKS 0x37C0
|
||||
#define XMS_BLOCK_SIZE 1024
|
||||
#define XMS_MAX_HANDLES 16
|
||||
|
||||
#define XMS_STATUS_SUCCESS 0x00
|
||||
#define XMS_STATUS_NOT_IMPLEMENTED 0x80
|
||||
#define XMS_STATUS_HMA_IN_USE 0x91
|
||||
#define XMS_STATUS_OUT_OF_MEMORY 0xA0
|
||||
#define XMS_STATUS_OUT_OF_HANDLES 0xA1
|
||||
#define XMS_STATUS_INVALID_HANDLE 0xA2
|
||||
#define XMS_STATUS_NOT_LOCKED 0xAA
|
||||
#define XMS_STATUS_LOCKED 0xAB
|
||||
#define XMS_STATUS_LOCK_OVERFLOW 0xAC
|
||||
#define XMS_STATUS_CANNOT_LOCK 0xAD
|
||||
|
||||
typedef struct _XMS_HANDLE
|
||||
{
|
||||
BYTE Handle;
|
||||
BYTE LockCount;
|
||||
WORD Size;
|
||||
DWORD Address;
|
||||
} XMS_HANDLE, *PXMS_HANDLE;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
BOOLEAN XmsGetDriverEntry(PDWORD Pointer);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue