Author: aandrejevic
Date: Mon Apr 27 03:37:24 2015
New Revision: 67457
URL:
http://svn.reactos.org/svn/reactos?rev=67457&view=rev
Log:
[NTVDM]
- In INT 21h, AH = 0Ah, the final carriage return is not counted.
- Implement XMS function 0Bh (Move Extended Memory Block).
- The driver must preserve the contents of unlocked Extended Memory Blocks (EMBs),
so move the bitmap setting/clearing code into XmsAlloc and XmsFree.
- Make XmsAlloc optimize memory blocks by moving them around, except it can't
move locked blocks.
Modified:
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c
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/dos.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] Mon Apr 27
03:37:24 2015
@@ -1036,7 +1036,6 @@
{
/* Append it to the buffer */
InputBuffer->Buffer[Count] = Character;
- Count++; /* Carriage returns are also counted */
/* Check if this is a special character */
if (Character < 0x20 && Character != 0x0A &&
Character != 0x0D)
@@ -1051,10 +1050,11 @@
}
if (Character == '\r') break;
+ Count++; /* Carriage returns are NOT counted */
}
/* Update the length */
- InputBuffer->Length = Count;
+ InputBuffer->Length = Count - 1;
break;
}
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] Mon Apr 27
03:37:24 2015
@@ -25,6 +25,15 @@
/* BOP Identifiers */
#define BOP_XMS 0x52
+
+ULONG
+NTAPI
+RtlFindLastBackwardRunClear
+(
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG FromIndex,
+ OUT PULONG StartingRunIndex
+);
/* PRIVATE VARIABLES **********************************************************/
@@ -180,6 +189,9 @@
{
BYTE i;
PXMS_HANDLE HandleEntry;
+ DWORD CurrentIndex = 0;
+ ULONG RunStart;
+ ULONG RunSize;
if (Size > FreeBlocks) return XMS_STATUS_OUT_OF_MEMORY;
@@ -195,55 +207,43 @@
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)
+ /* Optimize blocks */
+ for (i = 0; i < XMS_MAX_HANDLES; i++)
{
- /* Just increment the lock count */
- HandleEntry->LockCount++;
- return XMS_STATUS_SUCCESS;
+ /* Skip free and locked blocks */
+ if (HandleEntry->Handle == 0 || HandleEntry->LockCount > 0) continue;
+
+ CurrentIndex = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE;
+
+ /* Check if there is any free space before this block */
+ RunSize = RtlFindLastBackwardRunClear(&AllocBitmap, CurrentIndex,
&RunStart);
+ if (RunSize == 0) break;
+
+ /* Move this block back */
+ RtlMoveMemory((PVOID)REAL_TO_PHYS(HandleEntry->Address - RunSize *
XMS_BLOCK_SIZE),
+ (PVOID)REAL_TO_PHYS(HandleEntry->Address),
+ RunSize * XMS_BLOCK_SIZE);
+
+ /* Update the address */
+ HandleEntry->Address -= RunSize * XMS_BLOCK_SIZE;
}
while (CurrentIndex < XMS_BLOCKS)
{
- ULONG RunStart;
- ULONG RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex,
&RunStart);
+ RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex,
&RunStart);
if (RunSize == 0) break;
if (RunSize >= HandleEntry->Size)
{
- /* Lock it here */
- HandleEntry->LockCount++;
+ /* Allocate it here */
+ HandleEntry->Handle = i + 1;
+ HandleEntry->LockCount = 0;
+ HandleEntry->Size = Size;
HandleEntry->Address = XMS_ADDRESS + RunStart * XMS_BLOCK_SIZE;
+ FreeBlocks -= Size;
RtlSetBits(&AllocBitmap, RunStart, RunSize);
- *Address = HandleEntry->Address;
+
return XMS_STATUS_SUCCESS;
}
@@ -251,23 +251,49 @@
CurrentIndex = RunStart + RunSize;
}
- /* Can't find any suitable range */
- return XMS_STATUS_CANNOT_LOCK;
-}
-
-static CHAR XmsUnlock(WORD Handle)
+ return XMS_STATUS_OUT_OF_MEMORY;
+}
+
+static CHAR XmsFree(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;
+ if (HandleEntry->LockCount) return XMS_STATUS_LOCKED;
BlockNumber = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE;
RtlClearBits(&AllocBitmap, BlockNumber, HandleEntry->Size);
+
+ HandleEntry->Handle = 0;
+ FreeBlocks += HandleEntry->Size;
+
+ return XMS_STATUS_SUCCESS;
+}
+
+static CHAR XmsLock(WORD Handle, PDWORD Address)
+{
+ PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
+
+ if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE;
+ if (HandleEntry->LockCount == 0xFF) return XMS_STATUS_LOCK_OVERFLOW;
+
+ /* Increment the lock count */
+ HandleEntry->LockCount++;
+ *Address = HandleEntry->Address;
+
+ return XMS_STATUS_SUCCESS;
+}
+
+static CHAR XmsUnlock(WORD Handle)
+{
+ 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 */
+ HandleEntry->LockCount--;
return XMS_STATUS_SUCCESS;
}
@@ -391,6 +417,68 @@
break;
}
+ /* Move Extended Memory Block */
+ case 0x0B:
+ {
+ PVOID SourceAddress, DestAddress;
+ PXMS_COPY_DATA CopyData = (PXMS_COPY_DATA)SEG_OFF_TO_PTR(getDS(), getSI());
+
+ if (CopyData->SourceHandle)
+ {
+ PXMS_HANDLE Entry = GetHandleRecord(CopyData->SourceHandle);
+ if (!Entry)
+ {
+ setAX(0);
+ setBL(XMS_STATUS_BAD_SRC_HANDLE);
+ break;
+ }
+
+ if (CopyData->SourceOffset >= Entry->Size * XMS_BLOCK_SIZE)
+ {
+ setAX(0);
+ setBL(XMS_STATUS_BAD_SRC_OFFSET);
+ }
+
+ SourceAddress = (PVOID)REAL_TO_PHYS(Entry->Address +
CopyData->SourceOffset);
+ }
+ else
+ {
+ /* The offset is actually a 16-bit segment:offset pointer */
+ SourceAddress = SEG_OFF_TO_PTR(HIWORD(CopyData->SourceOffset),
+ LOWORD(CopyData->SourceOffset));
+ }
+
+ if (CopyData->DestHandle)
+ {
+ PXMS_HANDLE Entry = GetHandleRecord(CopyData->DestHandle);
+ if (!Entry)
+ {
+ setAX(0);
+ setBL(XMS_STATUS_BAD_DEST_HANDLE);
+ break;
+ }
+
+ if (CopyData->DestOffset >= Entry->Size * XMS_BLOCK_SIZE)
+ {
+ setAX(0);
+ setBL(XMS_STATUS_BAD_DEST_OFFSET);
+ }
+
+ DestAddress = (PVOID)REAL_TO_PHYS(Entry->Address +
CopyData->DestOffset);
+ }
+ else
+ {
+ /* The offset is actually a 16-bit segment:offset pointer */
+ DestAddress = SEG_OFF_TO_PTR(HIWORD(CopyData->DestOffset),
+ LOWORD(CopyData->DestOffset));
+ }
+
+ setAX(1);
+ setBL(XMS_STATUS_SUCCESS);
+ RtlMoveMemory(DestAddress, SourceAddress, CopyData->Count);
+ break;
+ }
+
/* Lock Extended Memory Block */
case 0x0C:
{
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] Mon Apr 27
03:37:24 2015
@@ -20,6 +20,10 @@
#define XMS_STATUS_OUT_OF_MEMORY 0xA0
#define XMS_STATUS_OUT_OF_HANDLES 0xA1
#define XMS_STATUS_INVALID_HANDLE 0xA2
+#define XMS_STATUS_BAD_SRC_HANDLE 0xA3
+#define XMS_STATUS_BAD_DEST_HANDLE 0xA4
+#define XMS_STATUS_BAD_SRC_OFFSET 0xA5
+#define XMS_STATUS_BAD_DEST_OFFSET 0xA6
#define XMS_STATUS_NOT_LOCKED 0xAA
#define XMS_STATUS_LOCKED 0xAB
#define XMS_STATUS_LOCK_OVERFLOW 0xAC
@@ -33,6 +37,17 @@
DWORD Address;
} XMS_HANDLE, *PXMS_HANDLE;
+#pragma pack(push, 1)
+typedef struct _XMS_COPY_DATA
+{
+ DWORD Count;
+ WORD SourceHandle;
+ DWORD SourceOffset;
+ WORD DestHandle;
+ DWORD DestOffset;
+} XMS_COPY_DATA, *PXMS_COPY_DATA;
+#pragma pack(pop)
+
/* FUNCTIONS ******************************************************************/
BOOLEAN XmsGetDriverEntry(PDWORD Pointer);