mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 16:23:01 +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.h"
|
||||||
#include "dos/dem.h"
|
#include "dos/dem.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
#include "himem.h"
|
||||||
|
|
||||||
#define XMS_DEVICE_NAME "XMSXXXX0"
|
#define XMS_DEVICE_NAME "XMSXXXX0"
|
||||||
#define XMS_BOP 0x52
|
#define XMS_BOP 0x52
|
||||||
|
@ -36,9 +37,117 @@ static const BYTE EntryProcedure[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static PDOS_DEVICE_NODE Node = NULL;
|
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 **********************************************************/
|
/* 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)
|
static VOID WINAPI XmsBopProcedure(LPWORD Stack)
|
||||||
{
|
{
|
||||||
switch (getAH())
|
switch (getAH())
|
||||||
|
@ -52,9 +161,85 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack)
|
||||||
break;
|
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:
|
default:
|
||||||
{
|
{
|
||||||
DPRINT1("XMS command AH = 0x%02X NOT IMPLEMENTED\n", getAH());
|
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)
|
VOID XmsInitialize(VOID)
|
||||||
{
|
{
|
||||||
|
RtlZeroMemory(HandleTable, sizeof(HandleTable));
|
||||||
|
RtlZeroMemory(BitmapBuffer, sizeof(BitmapBuffer));
|
||||||
|
RtlInitializeBitMap(&AllocBitmap, BitmapBuffer, XMS_BLOCKS);
|
||||||
|
|
||||||
Node = DosCreateDeviceEx(DOS_DEVATTR_IOCTL | DOS_DEVATTR_CHARACTER,
|
Node = DosCreateDeviceEx(DOS_DEVATTR_IOCTL | DOS_DEVATTR_CHARACTER,
|
||||||
XMS_DEVICE_NAME,
|
XMS_DEVICE_NAME,
|
||||||
sizeof(EntryProcedure));
|
sizeof(EntryProcedure));
|
||||||
|
|
|
@ -6,6 +6,32 @@
|
||||||
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
* 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 ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
BOOLEAN XmsGetDriverEntry(PDWORD Pointer);
|
BOOLEAN XmsGetDriverEntry(PDWORD Pointer);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue