mirror of
https://github.com/reactos/reactos.git
synced 2025-05-10 12:23:25 +00:00
[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. svn path=/trunk/; revision=67457
This commit is contained in:
parent
2351ed3e6e
commit
a8c3b4f1d9
3 changed files with 146 additions and 43 deletions
|
@ -1036,7 +1036,6 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
{
|
{
|
||||||
/* Append it to the buffer */
|
/* Append it to the buffer */
|
||||||
InputBuffer->Buffer[Count] = Character;
|
InputBuffer->Buffer[Count] = Character;
|
||||||
Count++; /* Carriage returns are also counted */
|
|
||||||
|
|
||||||
/* Check if this is a special character */
|
/* Check if this is a special character */
|
||||||
if (Character < 0x20 && Character != 0x0A && Character != 0x0D)
|
if (Character < 0x20 && Character != 0x0A && Character != 0x0D)
|
||||||
|
@ -1051,10 +1050,11 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Character == '\r') break;
|
if (Character == '\r') break;
|
||||||
|
Count++; /* Carriage returns are NOT counted */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the length */
|
/* Update the length */
|
||||||
InputBuffer->Length = Count;
|
InputBuffer->Length = Count - 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,15 @@
|
||||||
/* BOP Identifiers */
|
/* BOP Identifiers */
|
||||||
#define BOP_XMS 0x52
|
#define BOP_XMS 0x52
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
RtlFindLastBackwardRunClear
|
||||||
|
(
|
||||||
|
IN PRTL_BITMAP BitMapHeader,
|
||||||
|
IN ULONG FromIndex,
|
||||||
|
OUT PULONG StartingRunIndex
|
||||||
|
);
|
||||||
|
|
||||||
/* PRIVATE VARIABLES **********************************************************/
|
/* PRIVATE VARIABLES **********************************************************/
|
||||||
|
|
||||||
static const BYTE EntryProcedure[] = {
|
static const BYTE EntryProcedure[] = {
|
||||||
|
@ -180,6 +189,9 @@ static CHAR XmsAlloc(WORD Size, PWORD Handle)
|
||||||
{
|
{
|
||||||
BYTE i;
|
BYTE i;
|
||||||
PXMS_HANDLE HandleEntry;
|
PXMS_HANDLE HandleEntry;
|
||||||
|
DWORD CurrentIndex = 0;
|
||||||
|
ULONG RunStart;
|
||||||
|
ULONG RunSize;
|
||||||
|
|
||||||
if (Size > FreeBlocks) return XMS_STATUS_OUT_OF_MEMORY;
|
if (Size > FreeBlocks) return XMS_STATUS_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
@ -195,20 +207,64 @@ static CHAR XmsAlloc(WORD Size, PWORD Handle)
|
||||||
|
|
||||||
if (i == XMS_MAX_HANDLES) return XMS_STATUS_OUT_OF_HANDLES;
|
if (i == XMS_MAX_HANDLES) return XMS_STATUS_OUT_OF_HANDLES;
|
||||||
|
|
||||||
HandleEntry->Handle = i + 1;
|
/* Optimize blocks */
|
||||||
HandleEntry->LockCount = 0;
|
for (i = 0; i < XMS_MAX_HANDLES; i++)
|
||||||
HandleEntry->Size = Size;
|
{
|
||||||
FreeBlocks -= Size;
|
/* Skip free and locked blocks */
|
||||||
|
if (HandleEntry->Handle == 0 || HandleEntry->LockCount > 0) continue;
|
||||||
|
|
||||||
return XMS_STATUS_SUCCESS;
|
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)
|
||||||
|
{
|
||||||
|
RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart);
|
||||||
|
if (RunSize == 0) break;
|
||||||
|
|
||||||
|
if (RunSize >= HandleEntry->Size)
|
||||||
|
{
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
return XMS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep searching */
|
||||||
|
CurrentIndex = RunStart + RunSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return XMS_STATUS_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CHAR XmsFree(WORD Handle)
|
static CHAR XmsFree(WORD Handle)
|
||||||
{
|
{
|
||||||
|
DWORD BlockNumber;
|
||||||
PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
|
PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
|
||||||
|
|
||||||
if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE;
|
if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE;
|
||||||
if (HandleEntry->LockCount) return XMS_STATUS_LOCKED;
|
if (HandleEntry->LockCount) return XMS_STATUS_LOCKED;
|
||||||
|
|
||||||
|
BlockNumber = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE;
|
||||||
|
RtlClearBits(&AllocBitmap, BlockNumber, HandleEntry->Size);
|
||||||
|
|
||||||
HandleEntry->Handle = 0;
|
HandleEntry->Handle = 0;
|
||||||
FreeBlocks += HandleEntry->Size;
|
FreeBlocks += HandleEntry->Size;
|
||||||
|
|
||||||
|
@ -217,57 +273,27 @@ static CHAR XmsFree(WORD Handle)
|
||||||
|
|
||||||
static CHAR XmsLock(WORD Handle, PDWORD Address)
|
static CHAR XmsLock(WORD Handle, PDWORD Address)
|
||||||
{
|
{
|
||||||
DWORD CurrentIndex = 0;
|
|
||||||
PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
|
PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
|
||||||
|
|
||||||
if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE;
|
if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE;
|
||||||
if (HandleEntry->LockCount == 0xFF) return XMS_STATUS_LOCK_OVERFLOW;
|
if (HandleEntry->LockCount == 0xFF) return XMS_STATUS_LOCK_OVERFLOW;
|
||||||
|
|
||||||
if (HandleEntry->LockCount)
|
/* Increment the lock count */
|
||||||
{
|
HandleEntry->LockCount++;
|
||||||
/* Just increment the lock count */
|
*Address = HandleEntry->Address;
|
||||||
HandleEntry->LockCount++;
|
|
||||||
return XMS_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (CurrentIndex < XMS_BLOCKS)
|
return XMS_STATUS_SUCCESS;
|
||||||
{
|
|
||||||
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)
|
static CHAR XmsUnlock(WORD Handle)
|
||||||
{
|
{
|
||||||
DWORD BlockNumber;
|
|
||||||
PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
|
PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
|
||||||
|
|
||||||
if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE;
|
if (HandleEntry == NULL) return XMS_STATUS_INVALID_HANDLE;
|
||||||
if (!HandleEntry->LockCount) return XMS_STATUS_NOT_LOCKED;
|
if (!HandleEntry->LockCount) return XMS_STATUS_NOT_LOCKED;
|
||||||
|
|
||||||
/* Decrement the lock count and exit early if it's still locked */
|
/* Decrement the lock count */
|
||||||
if (--HandleEntry->LockCount) return XMS_STATUS_SUCCESS;
|
HandleEntry->LockCount--;
|
||||||
|
|
||||||
BlockNumber = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE;
|
|
||||||
RtlClearBits(&AllocBitmap, BlockNumber, HandleEntry->Size);
|
|
||||||
|
|
||||||
return XMS_STATUS_SUCCESS;
|
return XMS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -391,6 +417,68 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack)
|
||||||
break;
|
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 */
|
/* Lock Extended Memory Block */
|
||||||
case 0x0C:
|
case 0x0C:
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
#define XMS_STATUS_OUT_OF_MEMORY 0xA0
|
#define XMS_STATUS_OUT_OF_MEMORY 0xA0
|
||||||
#define XMS_STATUS_OUT_OF_HANDLES 0xA1
|
#define XMS_STATUS_OUT_OF_HANDLES 0xA1
|
||||||
#define XMS_STATUS_INVALID_HANDLE 0xA2
|
#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_NOT_LOCKED 0xAA
|
||||||
#define XMS_STATUS_LOCKED 0xAB
|
#define XMS_STATUS_LOCKED 0xAB
|
||||||
#define XMS_STATUS_LOCK_OVERFLOW 0xAC
|
#define XMS_STATUS_LOCK_OVERFLOW 0xAC
|
||||||
|
@ -33,6 +37,17 @@ typedef struct _XMS_HANDLE
|
||||||
DWORD Address;
|
DWORD Address;
|
||||||
} XMS_HANDLE, *PXMS_HANDLE;
|
} 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 ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
BOOLEAN XmsGetDriverEntry(PDWORD Pointer);
|
BOOLEAN XmsGetDriverEntry(PDWORD Pointer);
|
||||||
|
|
Loading…
Reference in a new issue