Author: aandrejevic
Date: Wed Apr 22 03:10:11 2015
New Revision: 67340
URL:
http://svn.reactos.org/svn/reactos?rev=67340&view=rev
Log:
[NTVDM]
Implement basic XMS functions.
Modified:
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c [iso-8859-1] Wed Apr 22
03:10:11 2015
@@ -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,8 +37,116 @@
};
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)
{
@@ -52,9 +161,85 @@
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 @@
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));
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h [iso-8859-1] Wed Apr 22
03:10:11 2015
@@ -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);