Author: aandrejevic Date: Tue Apr 21 22:48:28 2015 New Revision: 67339
URL: http://svn.reactos.org/svn/reactos?rev=67339&view=rev Log: [NTVDM] - Move the EMS code from the BIOS to the DOS driver where it belongs. - Expand the DOS device API with a new function, DosCreateDeviceEx, which will allow 32-bit DOS driver to reserve private memory. - For each DOS device, create an entry in guest memory so that 16-bit code can call 32-bit DOS drivers directly. - Implement an XMS driver stub that uses the above. - Arch, that's not how the DOS driver strategy routine works, you need to give it the request in ES:BX which it will store somewhere, and then call the interrupt routine.
Added: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.h (with props) trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c (with props) trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h (with props) Removed: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/ems.c trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/ems.h Modified: trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/bios32.c trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/bios32.h trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.h trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.c trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.c
Modified: trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/CMake... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -10,7 +10,6 @@ bios/bios32/kbdbios32.c bios/bios32/vidbios32.c bios/bios32/moubios32.c - bios/bios32/ems.c bios/bios.c bios/kbdbios.c bios/rom.c @@ -34,6 +33,7 @@ dos/dos32krnl/dos.c dos/dos32krnl/dosfiles.c dos/dos32krnl/emsdrv.c + dos/dos32krnl/himem.c dos/dos32krnl/memory.c dos/mouse32.c dos/dem.c
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/bios32.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios/... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/bios32.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/bios32.c [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -26,8 +26,6 @@ #include "kbdbios32.h" #include "vidbios32.h" #include "moubios32.h" - -#include "ems.h"
#include "io.h" #include "hardware/cmos.h" @@ -665,13 +663,6 @@
SearchAndInitRoms(&BiosContext);
- /* Initialize EMS */ - if (!EmsInitialize(EMS_TOTAL_PAGES)) - { - DPRINT1("Could not initialize EMS. EMS will not be available.\n" - "Try reducing the number of EMS pages.\n"); - } - /* * End of the 32-bit POST portion. We then fall back into 16-bit where * the rest of the POST code is executed, typically calling INT 19h @@ -733,7 +724,6 @@
VOID Bios32Cleanup(VOID) { - EmsCleanup(); MouseBios32Cleanup(); VidBios32Cleanup(); KbdBios32Cleanup();
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/bios32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios/... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/bios32.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/bios32.h [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -21,9 +21,6 @@ // #define BIOS_TIME_INTERRUPT 0x1A // #define BIOS_SYS_TIMER_INTERRUPT 0x1C
-/* 16 MB of EMS memory */ -#define EMS_TOTAL_PAGES 1024 - /* FUNCTIONS ******************************************************************/
BOOLEAN Bios32Initialize(VOID);
Removed: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/ems.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios/... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/ems.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/ems.c (removed) @@ -1,422 +0,0 @@ -/* - * COPYRIGHT: GPLv2+ - See COPYING in the top level directory - * PROJECT: ReactOS Virtual DOS Machine - * FILE: ems.c - * PURPOSE: Expanded Memory Support - * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> - */ - -/* INCLUDES *******************************************************************/ - -#define NDEBUG - -#include "ntvdm.h" -#include "emulator.h" -#include "bios/bios32/bios32p.h" -#include "ems.h" -#include "memory.h" - -/* PRIVATE VARIABLES **********************************************************/ - -static RTL_BITMAP AllocBitmap; -static PULONG BitmapBuffer = NULL; -static PEMS_PAGE PageTable = NULL; -static EMS_HANDLE HandleTable[EMS_MAX_HANDLES]; -static PVOID Mapping[EMS_PHYSICAL_PAGES] = { NULL }; -static ULONG EmsTotalPages = 0; -static PVOID EmsMemory = NULL; - -/* PRIVATE FUNCTIONS **********************************************************/ - -static USHORT EmsFree(USHORT Handle) -{ - PLIST_ENTRY Entry; - PEMS_HANDLE HandleEntry = &HandleTable[Handle]; - - if (Handle >= EMS_MAX_HANDLES || !HandleEntry->Allocated) - { - return EMS_STATUS_INVALID_HANDLE; - } - - for (Entry = HandleEntry->PageList.Flink; - Entry != &HandleEntry->PageList; - Entry = Entry->Flink) - { - PEMS_PAGE PageEntry = (PEMS_PAGE)CONTAINING_RECORD(Entry, EMS_PAGE, Entry); - ULONG PageNumber = ARRAY_INDEX(PageEntry, PageTable); - - /* Free the page */ - RtlClearBits(&AllocBitmap, PageNumber, 1); - } - - HandleEntry->Allocated = FALSE; - HandleEntry->PageCount = 0; - InitializeListHead(&HandleEntry->PageList); - - return EMS_STATUS_OK; -} - -static UCHAR EmsAlloc(USHORT NumPages, PUSHORT Handle) -{ - ULONG i, CurrentIndex = 0; - PEMS_HANDLE HandleEntry; - - if (NumPages == 0) return EMS_STATUS_ZERO_PAGES; - - for (i = 0; i < EMS_MAX_HANDLES; i++) - { - HandleEntry = &HandleTable[i]; - if (!HandleEntry->Allocated) - { - *Handle = i; - break; - } - } - - if (i == EMS_MAX_HANDLES) return EMS_STATUS_NO_MORE_HANDLES; - HandleEntry->Allocated = TRUE; - - while (HandleEntry->PageCount < NumPages) - { - ULONG RunStart; - ULONG RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart); - - if (RunSize == 0) - { - /* Free what's been allocated already and report failure */ - EmsFree(*Handle); - return EMS_STATUS_INSUFFICIENT_PAGES; - } - else if ((HandleEntry->PageCount + RunSize) > NumPages) - { - /* We don't need the entire run */ - RunSize = NumPages - HandleEntry->PageCount; - } - - CurrentIndex = RunStart + RunSize; - HandleEntry->PageCount += RunSize; - RtlSetBits(&AllocBitmap, RunStart, RunSize); - - for (i = 0; i < RunSize; i++) - { - PageTable[RunStart + i].Handle = *Handle; - InsertTailList(&HandleEntry->PageList, &PageTable[RunStart + i].Entry); - } - } - - return EMS_STATUS_OK; -} - -static PEMS_PAGE GetLogicalPage(PEMS_HANDLE Handle, USHORT LogicalPage) -{ - PLIST_ENTRY Entry = Handle->PageList.Flink; - - while (LogicalPage) - { - if (Entry == &Handle->PageList) return NULL; - LogicalPage--; - Entry = Entry->Flink; - } - - return (PEMS_PAGE)CONTAINING_RECORD(Entry, EMS_PAGE, Entry); -} - -static USHORT EmsMap(USHORT Handle, UCHAR PhysicalPage, USHORT LogicalPage) -{ - PEMS_PAGE PageEntry; - PEMS_HANDLE HandleEntry = &HandleTable[Handle]; - - if (PhysicalPage >= EMS_PHYSICAL_PAGES) return EMS_STATUS_INV_PHYSICAL_PAGE; - if (LogicalPage == 0xFFFF) - { - /* Unmap */ - Mapping[PhysicalPage] = NULL; - return EMS_STATUS_OK; - } - - if (Handle >= EMS_MAX_HANDLES || !HandleEntry->Allocated) return EMS_STATUS_INVALID_HANDLE; - - PageEntry = GetLogicalPage(HandleEntry, LogicalPage); - if (!PageEntry) return EMS_STATUS_INV_LOGICAL_PAGE; - - Mapping[PhysicalPage] = (PVOID)((ULONG_PTR)EmsMemory - + ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE); - return EMS_STATUS_OK; -} - -static VOID WINAPI EmsIntHandler(LPWORD Stack) -{ - switch (getAH()) - { - /* Get Manager Status */ - case 0x40: - { - setAH(EMS_STATUS_OK); - break; - } - - /* Get Page Frame Segment */ - case 0x41: - { - setAH(EMS_STATUS_OK); - setBX(EMS_SEGMENT); - break; - } - - /* Get Number Of Pages */ - case 0x42: - { - setAH(EMS_STATUS_OK); - setBX(RtlNumberOfClearBits(&AllocBitmap)); - setDX(EmsTotalPages); - break; - } - - /* Get Handle And Allocate Memory */ - case 0x43: - { - USHORT Handle; - UCHAR Status = EmsAlloc(getBX(), &Handle); - - setAH(Status); - if (Status == EMS_STATUS_OK) setDX(Handle); - break; - } - - /* Map Memory */ - case 0x44: - { - setAH(EmsMap(getDX(), getAL(), getBX())); - break; - } - - /* Release Handle And Memory */ - case 0x45: - { - setAH(EmsFree(getDX())); - break; - } - - /* Get EMM Version */ - case 0x46: - { - setAH(EMS_STATUS_OK); - setAL(EMS_VERSION_NUM); - break; - } - - /* Move/Exchange Memory */ - case 0x57: - { - PUCHAR SourcePtr, DestPtr; - PEMS_HANDLE HandleEntry; - PEMS_PAGE PageEntry; - BOOLEAN Exchange = getAL(); - PEMS_COPY_DATA Data = (PEMS_COPY_DATA)SEG_OFF_TO_PTR(getDS(), getSI()); - - if (Data->SourceType) - { - /* Expanded memory */ - HandleEntry = &HandleTable[Data->SourceHandle]; - - if (Data->SourceHandle >= EMS_MAX_HANDLES || !HandleEntry->Allocated) - { - setAL(EMS_STATUS_INVALID_HANDLE); - break; - } - - PageEntry = GetLogicalPage(HandleEntry, Data->SourceSegment); - - if (!PageEntry) - { - setAL(EMS_STATUS_INV_LOGICAL_PAGE); - break; - } - - SourcePtr = (PUCHAR)((ULONG_PTR)EmsMemory - + ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE - + Data->SourceOffset); - } - else - { - /* Conventional memory */ - SourcePtr = (PUCHAR)SEG_OFF_TO_PTR(Data->SourceSegment, Data->SourceOffset); - } - - if (Data->DestType) - { - /* Expanded memory */ - HandleEntry = &HandleTable[Data->DestHandle]; - - if (Data->SourceHandle >= EMS_MAX_HANDLES || !HandleEntry->Allocated) - { - setAL(EMS_STATUS_INVALID_HANDLE); - break; - } - - PageEntry = GetLogicalPage(HandleEntry, Data->DestSegment); - - if (!PageEntry) - { - setAL(EMS_STATUS_INV_LOGICAL_PAGE); - break; - } - - DestPtr = (PUCHAR)((ULONG_PTR)EmsMemory - + ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE - + Data->DestOffset); - } - else - { - /* Conventional memory */ - DestPtr = (PUCHAR)SEG_OFF_TO_PTR(Data->DestSegment, Data->DestOffset); - } - - if (Exchange) - { - ULONG i; - - /* Exchange */ - for (i = 0; i < Data->RegionLength; i++) - { - UCHAR Temp = DestPtr[i]; - DestPtr[i] = SourcePtr[i]; - SourcePtr[i] = Temp; - } - } - else - { - /* Move */ - RtlMoveMemory(DestPtr, SourcePtr, Data->RegionLength); - } - - setAL(EMS_STATUS_OK); - break; - } - - default: - { - DPRINT1("EMS function AH = %02X NOT IMPLEMENTED\n", getAH()); - setAH(EMS_STATUS_UNKNOWN_FUNCTION); - break; - } - } -} - -static VOID NTAPI EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size) -{ - ULONG i; - ULONG RelativeAddress = Address - TO_LINEAR(EMS_SEGMENT, 0); - ULONG FirstPage = RelativeAddress / EMS_PAGE_SIZE; - ULONG LastPage = (RelativeAddress + Size - 1) / EMS_PAGE_SIZE; - ULONG Offset, Length; - - for (i = FirstPage; i <= LastPage; i++) - { - Offset = (i == FirstPage) ? RelativeAddress & (EMS_PAGE_SIZE - 1) : 0; - Length = ((i == LastPage) - ? (RelativeAddress + Size - (LastPage << EMS_PAGE_BITS)) - : EMS_PAGE_SIZE) - Offset; - - if (Mapping[i]) RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)Mapping[i] + Offset), Length); - Buffer = (PVOID)((ULONG_PTR)Buffer + Length); - } -} - -static BOOLEAN NTAPI EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size) -{ - ULONG i; - ULONG RelativeAddress = Address - TO_LINEAR(EMS_SEGMENT, 0); - ULONG FirstPage = RelativeAddress / EMS_PAGE_SIZE; - ULONG LastPage = (RelativeAddress + Size - 1) / EMS_PAGE_SIZE; - ULONG Offset, Length; - - for (i = FirstPage; i <= LastPage; i++) - { - Offset = (i == FirstPage) ? RelativeAddress & (EMS_PAGE_SIZE - 1) : 0; - Length = ((i == LastPage) - ? (RelativeAddress + Size - (LastPage << EMS_PAGE_BITS)) - : EMS_PAGE_SIZE) - Offset; - - if (Mapping[i]) RtlCopyMemory((PVOID)((ULONG_PTR)Mapping[i] + Offset), Buffer, Length); - Buffer = (PVOID)((ULONG_PTR)Buffer + Length); - } - - return TRUE; -} - -/* PUBLIC FUNCTIONS ***********************************************************/ - -BOOLEAN EmsInitialize(ULONG TotalPages) -{ - ULONG i; - - for (i = 0; i < EMS_MAX_HANDLES; i++) - { - HandleTable[i].Allocated = FALSE; - HandleTable[i].PageCount = 0; - InitializeListHead(&HandleTable[i].PageList); - } - - EmsTotalPages = TotalPages; - BitmapBuffer = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - ((TotalPages + 31) / 32) * sizeof(ULONG)); - if (BitmapBuffer == NULL) return FALSE; - - RtlInitializeBitMap(&AllocBitmap, BitmapBuffer, TotalPages); - - PageTable = (PEMS_PAGE)RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - TotalPages * sizeof(EMS_PAGE)); - if (PageTable == NULL) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, BitmapBuffer); - BitmapBuffer = NULL; - - return FALSE; - } - - EmsMemory = (PVOID)RtlAllocateHeap(RtlGetProcessHeap(), 0, TotalPages * EMS_PAGE_SIZE); - if (EmsMemory == NULL) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, PageTable); - PageTable = NULL; - RtlFreeHeap(RtlGetProcessHeap(), 0, BitmapBuffer); - BitmapBuffer = NULL; - - return FALSE; - } - - MemInstallFastMemoryHook((PVOID)TO_LINEAR(EMS_SEGMENT, 0), - EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE, - EmsReadMemory, - EmsWriteMemory); - - RegisterBiosInt32(EMS_INTERRUPT_NUM, EmsIntHandler); - return TRUE; -} - -VOID EmsCleanup(VOID) -{ - MemRemoveFastMemoryHook((PVOID)TO_LINEAR(EMS_SEGMENT, 0), - EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE); - - if (EmsMemory) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, EmsMemory); - EmsMemory = NULL; - } - - if (PageTable) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, PageTable); - PageTable = NULL; - } - - if (BitmapBuffer) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, BitmapBuffer); - BitmapBuffer = NULL; - } -}
Removed: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/ems.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios/... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/ems.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/ems.h (removed) @@ -1,69 +0,0 @@ -/* - * COPYRIGHT: GPLv2+ - See COPYING in the top level directory - * PROJECT: ReactOS Virtual DOS Machine - * FILE: ems.h - * PURPOSE: Expanded Memory Support - * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> - */ - -#ifndef _EMS_H_ -#define _EMS_H_ - -/* DEFINITIONS ****************************************************************/ - -#define EMS_VERSION_NUM 0x04 -#define EMS_INTERRUPT_NUM 0x67 -#define EMS_SEGMENT 0xD000 -#define EMS_MAX_HANDLES 16 -#define EMS_PAGE_BITS 14 -#define EMS_PAGE_SIZE (1 << EMS_PAGE_BITS) -#define EMS_PHYSICAL_PAGES 4 - -#define EMS_STATUS_OK 0x00 -#define EMS_STATUS_INTERNAL_ERROR 0x80 -#define EMS_STATUS_INVALID_HANDLE 0x83 -#define EMS_STATUS_NO_MORE_HANDLES 0x85 -#define EMS_STATUS_INSUFFICIENT_PAGES 0x88 -#define EMS_STATUS_ZERO_PAGES 0x89 -#define EMS_STATUS_INV_LOGICAL_PAGE 0x8A -#define EMS_STATUS_INV_PHYSICAL_PAGE 0x8B -#define EMS_STATUS_UNKNOWN_FUNCTION 0x8F - -typedef struct _EMS_HANDLE -{ - BOOLEAN Allocated; - USHORT PageCount; - LIST_ENTRY PageList; -} EMS_HANDLE, *PEMS_HANDLE; - -typedef struct _EMS_PAGE -{ - LIST_ENTRY Entry; - USHORT Handle; -} EMS_PAGE, *PEMS_PAGE; - -#pragma pack(push, 1) - -typedef struct _EMS_COPY_DATA -{ - ULONG RegionLength; - UCHAR SourceType; - USHORT SourceHandle; - USHORT SourceOffset; - USHORT SourceSegment; - UCHAR DestType; - USHORT DestHandle; - USHORT DestOffset; - USHORT DestSegment; -} EMS_COPY_DATA, *PEMS_COPY_DATA; - -#pragma pack(pop) - -/* FUNCTIONS ******************************************************************/ - -BOOLEAN EmsInitialize(ULONG TotalPages); -VOID EmsCleanup(VOID); - -#endif // _EMS_H_ - -/* EOF */
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -19,6 +19,7 @@ #include "utils.h"
#include "dem.h" +#include "dos/dos32krnl/device.h" #include "cpu/bop.h"
#include "bios/bios.h" @@ -27,14 +28,6 @@ /* PRIVATE VARIABLES **********************************************************/
/**/extern BYTE CurrentDrive;/**/ - -/* DEFINES ********************************************************************/ - -/* BOP Identifiers */ -#define BOP_LOAD_DOS 0x2B // DOS Loading and Initializing BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file. -#define BOP_START_DOS 0x2C // DOS Starting BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file. -#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS) -#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
/* PRIVATE FUNCTIONS **********************************************************/
@@ -86,6 +79,20 @@ EmulatorTerminate(); }
+ break; + } + + /* Call 32-bit Driver Strategy Routine */ + case BOP_DRV_STRATEGY: + { + DeviceStrategyBop(); + break; + } + + /* Call 32-bit Driver Interrupt Routine */ + case BOP_DRV_INTERRUPT: + { + DeviceInterruptBop(); break; }
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.h [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -16,6 +16,14 @@ /* INCLUDES *******************************************************************/
#include "dos32krnl/dos.h" + +/* DEFINES ********************************************************************/ + +/* BOP Identifiers */ +#define BOP_LOAD_DOS 0x2B // DOS Loading and Initializing BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file. +#define BOP_START_DOS 0x2C // DOS Starting BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file. +#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS) +#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
/* FUNCTIONS ******************************************************************/
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.c [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -12,6 +12,7 @@
#include "ntvdm.h" #include "emulator.h" +#include "cpu/bop.h" #include "device.h"
#include "dos.h" @@ -20,27 +21,54 @@
/* PRIVATE VARIABLES **********************************************************/
+static const BYTE StrategyRoutine[] = { + LOBYTE(EMULATOR_BOP), + HIBYTE(EMULATOR_BOP), + BOP_DOS, + BOP_DRV_STRATEGY, + 0xCB // retf +}; + +static const BYTE InterruptRoutine[] = { + LOBYTE(EMULATOR_BOP), + HIBYTE(EMULATOR_BOP), + BOP_DOS, + BOP_DRV_INTERRUPT, + 0xCB // retf +}; + +C_ASSERT((sizeof(StrategyRoutine) + sizeof(InterruptRoutine)) == DEVICE_CODE_SIZE); + static LIST_ENTRY DeviceList = { &DeviceList, &DeviceList }; +static DWORD FirstDriver = 0xFFFFFFFF; +static PDOS_REQUEST_HEADER DeviceRequest;
/* PRIVATE FUNCTIONS **********************************************************/
static VOID DosCallDriver(DWORD Driver, PDOS_REQUEST_HEADER Request) { PDOS_DRIVER DriverBlock = (PDOS_DRIVER)FAR_POINTER(Driver); - PDOS_REQUEST_HEADER RemoteRequest; - - /* Call the strategy routine first */ - Call16(HIWORD(Driver), DriverBlock->StrategyRoutine); - RemoteRequest = (PDOS_REQUEST_HEADER)SEG_OFF_TO_PTR(getES(), getBX()); + PDOS_REQUEST_HEADER RemoteRequest = FAR_POINTER(REQUEST_LOCATION); + WORD ES = getES(); + WORD BX = getBX(); + + /* Set ES:BX to the location of the request */ + setES(HIWORD(REQUEST_LOCATION)); + setBX(LOWORD(REQUEST_LOCATION));
/* Copy the request structure to ES:BX */ RtlMoveMemory(RemoteRequest, Request, Request->RequestLength);
- /* Call the interrupt routine */ + /* Call the strategy routine, and then the interrupt routine */ + Call16(HIWORD(Driver), DriverBlock->StrategyRoutine); Call16(HIWORD(Driver), DriverBlock->InterruptRoutine);
/* Get the request structure from ES:BX */ - RtlMoveMemory(Request, RemoteRequest, RemoteRequest->RequestLength); + RtlMoveMemory(Request, RemoteRequest, Request->RequestLength); + + /* Restore ES:BX */ + setES(ES); + setBX(BX); }
static inline WORD NTAPI DosDriverReadInternal(PDOS_DEVICE_NODE DeviceNode, @@ -183,41 +211,65 @@ return Request.Header.Status; }
-/* PUBLIC FUNCTIONS ***********************************************************/ - -PDOS_DEVICE_NODE DosGetDevice(LPCSTR DeviceName) -{ - PLIST_ENTRY i; - PDOS_DEVICE_NODE Node; - ANSI_STRING DeviceNameString; - - RtlInitAnsiString(&DeviceNameString, DeviceName); - - for (i = DeviceList.Flink; i != &DeviceList; i = i->Flink) - { - Node = CONTAINING_RECORD(i, DOS_DEVICE_NODE, Entry); - if (RtlEqualString(&Node->Name, &DeviceNameString, TRUE)) return Node; - } - - return NULL; -} - -PDOS_DEVICE_NODE DosCreateDevice(WORD Attributes, PCHAR DeviceName) +static VOID DosAddDriver(DWORD Driver) +{ + PDOS_DRIVER LastDriver; + + if (LOWORD(FirstDriver) == 0xFFFF) + { + /* This is the first driver */ + FirstDriver = Driver; + return; + } + + /* The list isn't empty, so find the last driver in it */ + LastDriver = (PDOS_DRIVER)FAR_POINTER(FirstDriver); + while (LOWORD(LastDriver->Link) != 0xFFFF) + { + LastDriver = (PDOS_DRIVER)FAR_POINTER(LastDriver->Link); + } + + /* Add the new driver to the list */ + LastDriver->Link = Driver; +} + +static VOID DosRemoveDriver(DWORD Driver) +{ + DWORD CurrentDriver = FirstDriver; + + if (FirstDriver == Driver) + { + /* Update the first driver */ + FirstDriver = ((PDOS_DRIVER)FAR_POINTER(FirstDriver))->Link; + return; + } + + while (LOWORD(CurrentDriver) != 0xFFFF) + { + PDOS_DRIVER DriverHeader = (PDOS_DRIVER)FAR_POINTER(CurrentDriver); + + if (DriverHeader->Link == Driver) + { + /* Remove it from the list */ + DriverHeader->Link = ((PDOS_DRIVER)FAR_POINTER(DriverHeader->Link))->Link; + return; + } + + CurrentDriver = DriverHeader->Link; + } +} + +static PDOS_DEVICE_NODE DosCreateDeviceNode(DWORD Driver) { BYTE i; - PDOS_DEVICE_NODE Node; - - /* Make sure this is a character device */ - if (!(Attributes & DOS_DEVATTR_CHARACTER)) - { - DPRINT1("ERROR: Block devices are not supported.\n"); - return FALSE; - } - - Node = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*Node)); + PDOS_DRIVER DriverHeader = (PDOS_DRIVER)FAR_POINTER(Driver); + PDOS_DEVICE_NODE Node = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(*Node)); if (Node == NULL) return NULL;
- Node->DeviceAttributes = Attributes; + Node->Driver = Driver; + Node->DeviceAttributes = DriverHeader->DeviceAttributes;
/* Initialize the name string */ Node->Name.Buffer = Node->NameBuffer; @@ -225,8 +277,8 @@
for (i = 0; i < MAX_DEVICE_NAME; i++) { - if (DeviceName[i] == '\0' || DeviceName[i] == ' ') break; - Node->Name.Buffer[i] = DeviceName[i]; + if (DriverHeader->DeviceName[i] == ' ') break; + Node->Name.Buffer[i] = DriverHeader->DeviceName[i]; }
Node->Name.Length = i; @@ -235,10 +287,266 @@ return Node; }
+/* PUBLIC FUNCTIONS ***********************************************************/ + +PDOS_DEVICE_NODE DosGetDevice(LPCSTR DeviceName) +{ + PLIST_ENTRY i; + DWORD CurrentDriver = FirstDriver; + ANSI_STRING DeviceNameString; + + RtlInitAnsiString(&DeviceNameString, DeviceName); + + while (LOWORD(CurrentDriver) != 0xFFFF) + { + PDOS_DEVICE_NODE Node; + PDOS_DRIVER DriverHeader = (PDOS_DRIVER)FAR_POINTER(CurrentDriver); + + /* Get the device node for this driver */ + for (i = DeviceList.Flink; i != &DeviceList; i = i->Flink) + { + Node = CONTAINING_RECORD(i, DOS_DEVICE_NODE, Entry); + if (Node->Driver == CurrentDriver) break; + } + + if (i == &DeviceList) + { + DPRINT1("The driver at %04X:%04X has no associated device node. " + "Installing automagically.\n", + HIWORD(CurrentDriver), + LOWORD(CurrentDriver)); + + /* Create the device node */ + Node = DosCreateDeviceNode(CurrentDriver); + Node->IoctlReadRoutine = DosDriverDispatchIoctlRead; + Node->ReadRoutine = DosDriverDispatchRead; + Node->PeekRoutine = DosDriverDispatchPeek; + Node->InputStatusRoutine = DosDriverDispatchInputStatus; + Node->FlushInputRoutine = DosDriverDispatchFlushInput; + Node->IoctlWriteRoutine = DosDriverDispatchIoctlWrite; + Node->WriteRoutine = DosDriverDispatchWrite; + Node->OutputStatusRoutine = DosDriverDispatchOutputStatus; + Node->FlushOutputRoutine = DosDriverDispatchFlushOutput; + Node->OpenRoutine = DosDriverDispatchOpen; + Node->CloseRoutine = DosDriverDispatchClose; + Node->OutputUntilBusyRoutine = DosDriverDispatchOutputUntilBusy; + } + + if (RtlEqualString(&Node->Name, &DeviceNameString, TRUE)) return Node; + CurrentDriver = DriverHeader->Link; + } + + return NULL; +} + +PDOS_DEVICE_NODE DosCreateDeviceEx(WORD Attributes, PCHAR DeviceName, WORD PrivateDataSize) +{ + BYTE i; + WORD Segment; + PDOS_DRIVER DriverHeader; + PDOS_DEVICE_NODE Node; + + /* Make sure this is a character device */ + if (!(Attributes & DOS_DEVATTR_CHARACTER)) + { + DPRINT1("ERROR: Block devices are not supported.\n"); + return NULL; + } + + /* Create a driver header for this device */ + Segment = DosAllocateMemory(sizeof(DOS_DRIVER) + 10 + PrivateDataSize, NULL); + if (Segment == 0) return NULL; + + /* Fill the header with data */ + DriverHeader = SEG_OFF_TO_PTR(Segment, 0); + DriverHeader->Link = 0xFFFFFFFF; + DriverHeader->DeviceAttributes = Attributes; + DriverHeader->StrategyRoutine = sizeof(DOS_DRIVER); + DriverHeader->InterruptRoutine = sizeof(DOS_DRIVER) + sizeof(StrategyRoutine); + + RtlFillMemory(DriverHeader->DeviceName, MAX_DEVICE_NAME, ' '); + for (i = 0; i < MAX_DEVICE_NAME; i++) + { + if (DeviceName[i] == '\0' || DeviceName[i] == ' ') break; + DriverHeader->DeviceName[i] = DeviceName[i]; + } + + /* Write the routines */ + RtlMoveMemory(SEG_OFF_TO_PTR(Segment, DriverHeader->StrategyRoutine), + StrategyRoutine, + sizeof(StrategyRoutine)); + RtlMoveMemory(SEG_OFF_TO_PTR(Segment, DriverHeader->StrategyRoutine), + InterruptRoutine, + sizeof(InterruptRoutine)); + + /* Create the node */ + Node = DosCreateDeviceNode(MAKELONG(0, Segment)); + if (Node == NULL) + { + DosFreeMemory(Segment); + return NULL; + } + + DosAddDriver(Node->Driver); + return Node; +} + +PDOS_DEVICE_NODE DosCreateDevice(WORD Attributes, PCHAR DeviceName) +{ + /* Call the extended API */ + return DosCreateDeviceEx(Attributes, DeviceName, 0); +} + VOID DosDeleteDevice(PDOS_DEVICE_NODE DeviceNode) { + DosRemoveDriver(DeviceNode->Driver); + + ASSERT(LOWORD(DeviceNode->Driver) == 0); + DosFreeMemory(HIWORD(DeviceNode->Driver)); + RemoveEntryList(&DeviceNode->Entry); RtlFreeHeap(RtlGetProcessHeap(), 0, DeviceNode); +} + +VOID DeviceStrategyBop(VOID) +{ + /* Save ES:BX */ + DeviceRequest = (PDOS_REQUEST_HEADER)SEG_OFF_TO_PTR(getES(), getBX()); +} + +VOID DeviceInterruptBop(VOID) +{ + PLIST_ENTRY i; + PDOS_DEVICE_NODE Node; + DWORD DriverAddress = (getCS() << 4) + getIP() - sizeof(DOS_DRIVER) - 9; + + /* Get the device node for this driver */ + for (i = DeviceList.Flink; i != &DeviceList; i = i->Flink) + { + Node = CONTAINING_RECORD(i, DOS_DEVICE_NODE, Entry); + if (TO_LINEAR(HIWORD(Node->Driver), LOWORD(Node->Driver)) == DriverAddress) break; + } + + if (i == &DeviceList) + { + DPRINT1("Device interrupt BOP from an unknown location.\n"); + return; + } + + switch (DeviceRequest->CommandCode) + { + case DOS_DEVCMD_IOCTL_READ: + { + PDOS_IOCTL_RW_REQUEST Request = (PDOS_IOCTL_RW_REQUEST)DeviceRequest; + + DeviceRequest->Status = Node->IoctlReadRoutine( + Node, + Request->BufferPointer, + &Request->Length + ); + + break; + } + + case DOS_DEVCMD_READ: + { + PDOS_RW_REQUEST Request = (PDOS_RW_REQUEST)DeviceRequest; + + DeviceRequest->Status = Node->ReadRoutine( + Node, + Request->BufferPointer, + &Request->Length + ); + + break; + } + + case DOS_DEVCMD_PEEK: + { + PDOS_PEEK_REQUEST Request = (PDOS_PEEK_REQUEST)DeviceRequest; + DeviceRequest->Status = Node->PeekRoutine(Node, &Request->Character); + break; + } + + case DOS_DEVCMD_INSTAT: + { + DeviceRequest->Status = Node->InputStatusRoutine(Node); + break; + } + + case DOS_DEVCMD_FLUSH_INPUT: + { + DeviceRequest->Status = Node->FlushInputRoutine(Node); + break; + } + + case DOS_DEVCMD_IOCTL_WRITE: + { + PDOS_IOCTL_RW_REQUEST Request = (PDOS_IOCTL_RW_REQUEST)DeviceRequest; + + DeviceRequest->Status = Node->IoctlWriteRoutine( + Node, + Request->BufferPointer, + &Request->Length + ); + + break; + } + + case DOS_DEVCMD_WRITE: + { + PDOS_RW_REQUEST Request = (PDOS_RW_REQUEST)DeviceRequest; + + DeviceRequest->Status = Node->WriteRoutine(Node, + Request->BufferPointer, + &Request->Length + ); + + break; + } + + case DOS_DEVCMD_OUTSTAT: + { + DeviceRequest->Status = Node->OutputStatusRoutine(Node); + break; + } + + case DOS_DEVCMD_FLUSH_OUTPUT: + { + DeviceRequest->Status = Node->FlushOutputRoutine(Node); + break; + } + + case DOS_DEVCMD_OPEN: + { + DeviceRequest->Status = Node->OpenRoutine(Node); + break; + } + + case DOS_DEVCMD_CLOSE: + { + DeviceRequest->Status = Node->CloseRoutine(Node); + break; + } + + case DOS_DEVCMD_OUTPUT_BUSY: + { + PDOS_OUTPUT_BUSY_REQUEST Request = (PDOS_OUTPUT_BUSY_REQUEST)DeviceRequest; + + DeviceRequest->Status = Node->OutputUntilBusyRoutine( + Node, + Request->BufferPointer, + &Request->Length + ); + + break; + } + + default: + { + DPRINT1("Unknown device command code: %u\n", DeviceRequest->CommandCode); + } + } }
DWORD DosLoadDriver(LPCSTR DriverFile) @@ -334,10 +642,8 @@ goto Next; }
- /* Create the device */ - DeviceNode = DosCreateDevice(DriverHeader->DeviceAttributes, - DriverHeader->DeviceName); - DeviceNode->Driver = Driver; + /* Create the device node */ + DeviceNode = DosCreateDeviceNode(Driver); DeviceNode->IoctlReadRoutine = DosDriverDispatchIoctlRead; DeviceNode->ReadRoutine = DosDriverDispatchRead; DeviceNode->PeekRoutine = DosDriverDispatchPeek; @@ -351,6 +657,7 @@ DeviceNode->CloseRoutine = DosDriverDispatchClose; DeviceNode->OutputUntilBusyRoutine = DosDriverDispatchOutputUntilBusy;
+ DosAddDriver(Driver); DriversLoaded++;
Next:
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -12,6 +12,12 @@ /* DEFINITIONS ****************************************************************/
#define MAX_DEVICE_NAME 8 +#define REQUEST_LOCATION 0x00700100 // 0070:0100 +#define DEVICE_CODE_SIZE 10 +#define DEVICE_PRIVATE_AREA(Driver) (Driver + sizeof(DOS_DRIVER) + DEVICE_CODE_SIZE) + +#define BOP_DRV_STRATEGY 0x42 +#define BOP_DRV_INTERRUPT 0x43
#define DOS_DEVATTR_STDIN (1 << 0) #define DOS_DEVATTR_STDOUT (1 << 1) @@ -80,6 +86,7 @@ struct _DOS_DEVICE_NODE { LIST_ENTRY Entry; + DWORD Driver; WORD DeviceAttributes; ANSI_STRING Name; CHAR NameBuffer[MAX_DEVICE_NAME]; @@ -95,7 +102,6 @@ PDOS_DEVICE_GENERIC_ROUTINE OpenRoutine; PDOS_DEVICE_GENERIC_ROUTINE CloseRoutine; PDOS_DEVICE_IO_ROUTINE OutputUntilBusyRoutine; - DWORD Driver; };
#pragma pack(push, 1) @@ -190,7 +196,16 @@
PDOS_DEVICE_NODE DosGetDevice(LPCSTR DeviceName); PDOS_DEVICE_NODE DosCreateDevice(WORD Attributes, PCHAR DeviceName); +PDOS_DEVICE_NODE DosCreateDeviceEx +( + WORD Attributes, + PCHAR DeviceName, + WORD PrivateDataSize +); VOID DosDeleteDevice(PDOS_DEVICE_NODE DeviceNode); +VOID DeviceStrategyBop(VOID); +VOID DeviceInterruptBop(VOID); +DWORD DosLoadDriver(LPCSTR DriverFile);
#endif // _DEVICE_H_
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- 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] Tue Apr 21 22:48:28 2015 @@ -20,11 +20,14 @@ #include "dos/dem.h" #include "device.h" #include "memory.h" +#include "himem.h"
#include "bios/bios.h"
#include "io.h" #include "hardware/ps2.h" + +#include "emsdrv.h"
/* PRIVATE VARIABLES **********************************************************/
@@ -2934,9 +2937,39 @@
VOID WINAPI DosInt2Fh(LPWORD Stack) { - DPRINT1("DOS Internal System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n", - getAH(), getAL()); - Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + switch (getAH()) + { + /* Extended Memory Specification */ + case 0x43: + { + DWORD DriverEntry; + if (!XmsGetDriverEntry(&DriverEntry)) break; + + if (getAL() == 0x00) + { + /* The driver is loaded */ + setAL(0x80); + } + else if (getAL() == 0x10) + { + setES(HIWORD(DriverEntry)); + setBX(LOWORD(DriverEntry)); + } + else + { + DPRINT1("Unknown DOS XMS Function: INT 0x2F, AH = 43h, AL = %xh\n", getAL()); + } + + break; + } + + default: + { + DPRINT1("DOS Internal System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n", + getAH(), getAL()); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + } + } }
BOOLEAN DosKRNLInitialize(VOID) @@ -3003,12 +3036,6 @@ DosSystemFileTable[i].Type = DOS_SFT_ENTRY_NONE; DosSystemFileTable[i].RefCount = 0; } - - /* Load the EMS driver */ - EmsDrvInitialize(); - - /* Load the CON driver */ - ConDrvInitialize();
#endif
@@ -3024,6 +3051,19 @@ RegisterDosInt32(0x29, DosFastConOut ); // DOS 2+ Fast Console Output RegisterDosInt32(0x2F, DosInt2Fh );
+ /* Load the EMS driver */ + if (!EmsDrvInitialize(EMS_TOTAL_PAGES)) + { + DPRINT1("Could not initialize EMS. EMS will not be available.\n" + "Try reducing the number of EMS pages.\n"); + } + + /* Load the XMS driver (HIMEM) */ + XmsInitialize(); + + /* Load the CON driver */ + ConDrvInitialize(); + return TRUE; }
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -49,6 +49,9 @@ #define DOS_CHAR_ATTRIBUTE 0x07 #define DOS_PROGRAM_NAME_TAG 0x0001 #define DEFAULT_JFT_SIZE 20 + +/* 16 MB of EMS memory */ +#define EMS_TOTAL_PAGES 1024
typedef enum { @@ -198,8 +201,6 @@ VOID DosPrintCharacter(WORD FileHandle, CHAR Character);
BOOLEAN DosBIOSInitialize(VOID); -VOID EmsDrvInitialize(VOID); -VOID EmsDrvCleanup(VOID); VOID ConDrvInitialize(VOID); VOID ConDrvCleanup(VOID);
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.c [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -11,18 +11,347 @@ #define NDEBUG
#include "ntvdm.h" +#include "emulator.h"
#include "dos.h" #include "dos/dem.h" #include "device.h"
+#include "../../memory.h" +#include "emsdrv.h" + #define EMS_DEVICE_NAME "EMMXXXX0"
/* PRIVATE VARIABLES **********************************************************/
static PDOS_DEVICE_NODE Node; +static RTL_BITMAP AllocBitmap; +static PULONG BitmapBuffer = NULL; +static PEMS_PAGE PageTable = NULL; +static EMS_HANDLE HandleTable[EMS_MAX_HANDLES]; +static PVOID Mapping[EMS_PHYSICAL_PAGES] = { NULL }; +static ULONG EmsTotalPages = 0; +static PVOID EmsMemory = NULL;
/* PRIVATE FUNCTIONS **********************************************************/ + +static USHORT EmsFree(USHORT Handle) +{ + PLIST_ENTRY Entry; + PEMS_HANDLE HandleEntry = &HandleTable[Handle]; + + if (Handle >= EMS_MAX_HANDLES || !HandleEntry->Allocated) + { + return EMS_STATUS_INVALID_HANDLE; + } + + for (Entry = HandleEntry->PageList.Flink; + Entry != &HandleEntry->PageList; + Entry = Entry->Flink) + { + PEMS_PAGE PageEntry = (PEMS_PAGE)CONTAINING_RECORD(Entry, EMS_PAGE, Entry); + ULONG PageNumber = ARRAY_INDEX(PageEntry, PageTable); + + /* Free the page */ + RtlClearBits(&AllocBitmap, PageNumber, 1); + } + + HandleEntry->Allocated = FALSE; + HandleEntry->PageCount = 0; + InitializeListHead(&HandleEntry->PageList); + + return EMS_STATUS_OK; +} + +static UCHAR EmsAlloc(USHORT NumPages, PUSHORT Handle) +{ + ULONG i, CurrentIndex = 0; + PEMS_HANDLE HandleEntry; + + if (NumPages == 0) return EMS_STATUS_ZERO_PAGES; + + for (i = 0; i < EMS_MAX_HANDLES; i++) + { + HandleEntry = &HandleTable[i]; + if (!HandleEntry->Allocated) + { + *Handle = i; + break; + } + } + + if (i == EMS_MAX_HANDLES) return EMS_STATUS_NO_MORE_HANDLES; + HandleEntry->Allocated = TRUE; + + while (HandleEntry->PageCount < NumPages) + { + ULONG RunStart; + ULONG RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart); + + if (RunSize == 0) + { + /* Free what's been allocated already and report failure */ + EmsFree(*Handle); + return EMS_STATUS_INSUFFICIENT_PAGES; + } + else if ((HandleEntry->PageCount + RunSize) > NumPages) + { + /* We don't need the entire run */ + RunSize = NumPages - HandleEntry->PageCount; + } + + CurrentIndex = RunStart + RunSize; + HandleEntry->PageCount += RunSize; + RtlSetBits(&AllocBitmap, RunStart, RunSize); + + for (i = 0; i < RunSize; i++) + { + PageTable[RunStart + i].Handle = *Handle; + InsertTailList(&HandleEntry->PageList, &PageTable[RunStart + i].Entry); + } + } + + return EMS_STATUS_OK; +} + +static PEMS_PAGE GetLogicalPage(PEMS_HANDLE Handle, USHORT LogicalPage) +{ + PLIST_ENTRY Entry = Handle->PageList.Flink; + + while (LogicalPage) + { + if (Entry == &Handle->PageList) return NULL; + LogicalPage--; + Entry = Entry->Flink; + } + + return (PEMS_PAGE)CONTAINING_RECORD(Entry, EMS_PAGE, Entry); +} + +static USHORT EmsMap(USHORT Handle, UCHAR PhysicalPage, USHORT LogicalPage) +{ + PEMS_PAGE PageEntry; + PEMS_HANDLE HandleEntry = &HandleTable[Handle]; + + if (PhysicalPage >= EMS_PHYSICAL_PAGES) return EMS_STATUS_INV_PHYSICAL_PAGE; + if (LogicalPage == 0xFFFF) + { + /* Unmap */ + Mapping[PhysicalPage] = NULL; + return EMS_STATUS_OK; + } + + if (Handle >= EMS_MAX_HANDLES || !HandleEntry->Allocated) return EMS_STATUS_INVALID_HANDLE; + + PageEntry = GetLogicalPage(HandleEntry, LogicalPage); + if (!PageEntry) return EMS_STATUS_INV_LOGICAL_PAGE; + + Mapping[PhysicalPage] = (PVOID)((ULONG_PTR)EmsMemory + + ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE); + return EMS_STATUS_OK; +} + +static VOID WINAPI EmsIntHandler(LPWORD Stack) +{ + switch (getAH()) + { + /* Get Manager Status */ + case 0x40: + { + setAH(EMS_STATUS_OK); + break; + } + + /* Get Page Frame Segment */ + case 0x41: + { + setAH(EMS_STATUS_OK); + setBX(EMS_SEGMENT); + break; + } + + /* Get Number Of Pages */ + case 0x42: + { + setAH(EMS_STATUS_OK); + setBX(RtlNumberOfClearBits(&AllocBitmap)); + setDX(EmsTotalPages); + break; + } + + /* Get Handle And Allocate Memory */ + case 0x43: + { + USHORT Handle; + UCHAR Status = EmsAlloc(getBX(), &Handle); + + setAH(Status); + if (Status == EMS_STATUS_OK) setDX(Handle); + break; + } + + /* Map Memory */ + case 0x44: + { + setAH(EmsMap(getDX(), getAL(), getBX())); + break; + } + + /* Release Handle And Memory */ + case 0x45: + { + setAH(EmsFree(getDX())); + break; + } + + /* Get EMM Version */ + case 0x46: + { + setAH(EMS_STATUS_OK); + setAL(EMS_VERSION_NUM); + break; + } + + /* Move/Exchange Memory */ + case 0x57: + { + PUCHAR SourcePtr, DestPtr; + PEMS_HANDLE HandleEntry; + PEMS_PAGE PageEntry; + BOOLEAN Exchange = getAL(); + PEMS_COPY_DATA Data = (PEMS_COPY_DATA)SEG_OFF_TO_PTR(getDS(), getSI()); + + if (Data->SourceType) + { + /* Expanded memory */ + HandleEntry = &HandleTable[Data->SourceHandle]; + + if (Data->SourceHandle >= EMS_MAX_HANDLES || !HandleEntry->Allocated) + { + setAL(EMS_STATUS_INVALID_HANDLE); + break; + } + + PageEntry = GetLogicalPage(HandleEntry, Data->SourceSegment); + + if (!PageEntry) + { + setAL(EMS_STATUS_INV_LOGICAL_PAGE); + break; + } + + SourcePtr = (PUCHAR)((ULONG_PTR)EmsMemory + + ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE + + Data->SourceOffset); + } + else + { + /* Conventional memory */ + SourcePtr = (PUCHAR)SEG_OFF_TO_PTR(Data->SourceSegment, Data->SourceOffset); + } + + if (Data->DestType) + { + /* Expanded memory */ + HandleEntry = &HandleTable[Data->DestHandle]; + + if (Data->SourceHandle >= EMS_MAX_HANDLES || !HandleEntry->Allocated) + { + setAL(EMS_STATUS_INVALID_HANDLE); + break; + } + + PageEntry = GetLogicalPage(HandleEntry, Data->DestSegment); + + if (!PageEntry) + { + setAL(EMS_STATUS_INV_LOGICAL_PAGE); + break; + } + + DestPtr = (PUCHAR)((ULONG_PTR)EmsMemory + + ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE + + Data->DestOffset); + } + else + { + /* Conventional memory */ + DestPtr = (PUCHAR)SEG_OFF_TO_PTR(Data->DestSegment, Data->DestOffset); + } + + if (Exchange) + { + ULONG i; + + /* Exchange */ + for (i = 0; i < Data->RegionLength; i++) + { + UCHAR Temp = DestPtr[i]; + DestPtr[i] = SourcePtr[i]; + SourcePtr[i] = Temp; + } + } + else + { + /* Move */ + RtlMoveMemory(DestPtr, SourcePtr, Data->RegionLength); + } + + setAL(EMS_STATUS_OK); + break; + } + + default: + { + DPRINT1("EMS function AH = %02X NOT IMPLEMENTED\n", getAH()); + setAH(EMS_STATUS_UNKNOWN_FUNCTION); + break; + } + } +} + +static VOID NTAPI EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size) +{ + ULONG i; + ULONG RelativeAddress = Address - TO_LINEAR(EMS_SEGMENT, 0); + ULONG FirstPage = RelativeAddress / EMS_PAGE_SIZE; + ULONG LastPage = (RelativeAddress + Size - 1) / EMS_PAGE_SIZE; + ULONG Offset, Length; + + for (i = FirstPage; i <= LastPage; i++) + { + Offset = (i == FirstPage) ? RelativeAddress & (EMS_PAGE_SIZE - 1) : 0; + Length = ((i == LastPage) + ? (RelativeAddress + Size - (LastPage << EMS_PAGE_BITS)) + : EMS_PAGE_SIZE) - Offset; + + if (Mapping[i]) RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)Mapping[i] + Offset), Length); + Buffer = (PVOID)((ULONG_PTR)Buffer + Length); + } +} + +static BOOLEAN NTAPI EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size) +{ + ULONG i; + ULONG RelativeAddress = Address - TO_LINEAR(EMS_SEGMENT, 0); + ULONG FirstPage = RelativeAddress / EMS_PAGE_SIZE; + ULONG LastPage = (RelativeAddress + Size - 1) / EMS_PAGE_SIZE; + ULONG Offset, Length; + + for (i = FirstPage; i <= LastPage; i++) + { + Offset = (i == FirstPage) ? RelativeAddress & (EMS_PAGE_SIZE - 1) : 0; + Length = ((i == LastPage) + ? (RelativeAddress + Size - (LastPage << EMS_PAGE_BITS)) + : EMS_PAGE_SIZE) - Offset; + + if (Mapping[i]) RtlCopyMemory((PVOID)((ULONG_PTR)Mapping[i] + Offset), Buffer, Length); + Buffer = (PVOID)((ULONG_PTR)Buffer + Length); + } + + return TRUE; +} +
WORD NTAPI EmsDrvDispatchIoctlRead(PDOS_DEVICE_NODE Device, DWORD Buffer, PWORD Length) { @@ -34,17 +363,85 @@
/* PUBLIC FUNCTIONS ***********************************************************/
-VOID EmsDrvInitialize(VOID) -{ +BOOLEAN EmsDrvInitialize(ULONG TotalPages) +{ + ULONG i; + + for (i = 0; i < EMS_MAX_HANDLES; i++) + { + HandleTable[i].Allocated = FALSE; + HandleTable[i].PageCount = 0; + InitializeListHead(&HandleTable[i].PageList); + } + + EmsTotalPages = TotalPages; + BitmapBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + ((TotalPages + 31) / 32) * sizeof(ULONG)); + if (BitmapBuffer == NULL) return FALSE; + + RtlInitializeBitMap(&AllocBitmap, BitmapBuffer, TotalPages); + + PageTable = (PEMS_PAGE)RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + TotalPages * sizeof(EMS_PAGE)); + if (PageTable == NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, BitmapBuffer); + BitmapBuffer = NULL; + + return FALSE; + } + + EmsMemory = (PVOID)RtlAllocateHeap(RtlGetProcessHeap(), 0, TotalPages * EMS_PAGE_SIZE); + if (EmsMemory == NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, PageTable); + PageTable = NULL; + RtlFreeHeap(RtlGetProcessHeap(), 0, BitmapBuffer); + BitmapBuffer = NULL; + + return FALSE; + } + + MemInstallFastMemoryHook((PVOID)TO_LINEAR(EMS_SEGMENT, 0), + EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE, + EmsReadMemory, + EmsWriteMemory); + + RegisterDosInt32(EMS_INTERRUPT_NUM, EmsIntHandler); + /* Create the device */ - Node = DosCreateDevice(DOS_DEVATTR_IOCTL - | DOS_DEVATTR_CHARACTER, + Node = DosCreateDevice(DOS_DEVATTR_IOCTL | DOS_DEVATTR_CHARACTER, EMS_DEVICE_NAME); Node->IoctlReadRoutine = EmsDrvDispatchIoctlRead; + + return TRUE; }
VOID EmsDrvCleanup(VOID) { /* Delete the device */ DosDeleteDevice(Node); -} + + MemRemoveFastMemoryHook((PVOID)TO_LINEAR(EMS_SEGMENT, 0), + EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE); + + if (EmsMemory) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, EmsMemory); + EmsMemory = NULL; + } + + if (PageTable) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, PageTable); + PageTable = NULL; + } + + if (BitmapBuffer) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, BitmapBuffer); + BitmapBuffer = NULL; + } +}
Added: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.h (added) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.h [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -0,0 +1,67 @@ +/* + * COPYRIGHT: GPLv2+ - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: emsdrv.h + * PURPOSE: DOS EMS Driver + * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + */ + +#ifndef _EMSDRV_H_ +#define _EMSDRV_H_ + +/* DEFINITIONS ****************************************************************/ + +#define EMS_VERSION_NUM 0x04 +#define EMS_INTERRUPT_NUM 0x67 +#define EMS_SEGMENT 0xD000 +#define EMS_MAX_HANDLES 16 +#define EMS_PAGE_BITS 14 +#define EMS_PAGE_SIZE (1 << EMS_PAGE_BITS) +#define EMS_PHYSICAL_PAGES 4 + +#define EMS_STATUS_OK 0x00 +#define EMS_STATUS_INTERNAL_ERROR 0x80 +#define EMS_STATUS_INVALID_HANDLE 0x83 +#define EMS_STATUS_NO_MORE_HANDLES 0x85 +#define EMS_STATUS_INSUFFICIENT_PAGES 0x88 +#define EMS_STATUS_ZERO_PAGES 0x89 +#define EMS_STATUS_INV_LOGICAL_PAGE 0x8A +#define EMS_STATUS_INV_PHYSICAL_PAGE 0x8B +#define EMS_STATUS_UNKNOWN_FUNCTION 0x8F + +typedef struct _EMS_HANDLE +{ + BOOLEAN Allocated; + USHORT PageCount; + LIST_ENTRY PageList; +} EMS_HANDLE, *PEMS_HANDLE; + +typedef struct _EMS_PAGE +{ + LIST_ENTRY Entry; + USHORT Handle; +} EMS_PAGE, *PEMS_PAGE; + +#pragma pack(push, 1) + +typedef struct _EMS_COPY_DATA +{ + ULONG RegionLength; + UCHAR SourceType; + USHORT SourceHandle; + USHORT SourceOffset; + USHORT SourceSegment; + UCHAR DestType; + USHORT DestHandle; + USHORT DestOffset; + USHORT DestSegment; +} EMS_COPY_DATA, *PEMS_COPY_DATA; + +#pragma pack(pop) + +#endif + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN EmsDrvInitialize(ULONG TotalPages); +VOID EmsDrvCleanup(VOID);
Propchange: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/emsdrv.h ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c (added) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -0,0 +1,89 @@ +/* + * COPYRIGHT: GPLv2+ - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: himem.c + * PURPOSE: DOS XMS Driver + * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "ntvdm.h" +#include "emulator.h" +#include "cpu/bop.h" + +#include "dos.h" +#include "dos/dem.h" +#include "device.h" + +#define XMS_DEVICE_NAME "XMSXXXX0" +#define XMS_BOP 0x52 + +/* PRIVATE VARIABLES **********************************************************/ + +static const BYTE EntryProcedure[] = { + 0xEB, // jmp short +0x03 + 0x03, + 0x90, // nop + 0x90, // nop + 0x90, // nop + LOBYTE(EMULATOR_BOP), + HIBYTE(EMULATOR_BOP), + XMS_BOP, + 0xCB // retf +}; + +static PDOS_DEVICE_NODE Node = NULL; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static VOID WINAPI XmsBopProcedure(LPWORD Stack) +{ + switch (getAH()) + { + /* Get XMS Version */ + case 0x00: + { + setAX(0x0300); /* XMS version 3.0 */ + setDX(0x0001); /* HMA present */ + + break; + } + + default: + { + DPRINT1("XMS command AH = 0x%02X NOT IMPLEMENTED\n", getAH()); + } + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN XmsGetDriverEntry(PDWORD Pointer) +{ + if (Node == NULL) return FALSE; + *Pointer = DEVICE_PRIVATE_AREA(Node->Driver); + return TRUE; +} + +VOID XmsInitialize(VOID) +{ + Node = DosCreateDeviceEx(DOS_DEVATTR_IOCTL | DOS_DEVATTR_CHARACTER, + XMS_DEVICE_NAME, + sizeof(EntryProcedure)); + + RegisterBop(XMS_BOP, XmsBopProcedure); + + /* Copy the entry routine to the device private area */ + RtlMoveMemory(FAR_POINTER(DEVICE_PRIVATE_AREA(Node->Driver)), + EntryProcedure, + sizeof(EntryProcedure)); +} + +VOID XmsCleanup(VOID) +{ + RegisterBop(XMS_BOP, NULL); + DosDeleteDevice(Node); +}
Propchange: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h (added) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h [iso-8859-1] Tue Apr 21 22:48:28 2015 @@ -0,0 +1,13 @@ +/* + * COPYRIGHT: GPLv2+ - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: himem.h + * PURPOSE: DOS XMS Driver + * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + */ + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN XmsGetDriverEntry(PDWORD Pointer); +VOID XmsInitialize(VOID); +VOID XmsCleanup(VOID);
Propchange: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/himem.h ------------------------------------------------------------------------------ svn:eol-style = native