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/CMakeLists.txt?rev=67339&r1=67338&r2=67339&view=diff
==============================================================================
--- 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/bios32/bios32.c?rev=67339&r1=67338&r2=67339&view=diff
==============================================================================
--- 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/bios32/bios32.h?rev=67339&r1=67338&r2=67339&view=diff
==============================================================================
--- 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/bios32/ems.c?rev=67338
==============================================================================
--- 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/bios32/ems.h?rev=67338
==============================================================================
--- 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/dem.c?rev=67339&r1=67338&r2=67339&view=diff
==============================================================================
--- 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/dem.h?rev=67339&r1=67338&r2=67339&view=diff
==============================================================================
--- 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/dos32krnl/device.c?rev=67339&r1=67338&r2=67339&view=diff
==============================================================================
--- 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/dos32krnl/device.h?rev=67339&r1=67338&r2=67339&view=diff
==============================================================================
--- 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/dos32krnl/dos.c?rev=67339&r1=67338&r2=67339&view=diff
==============================================================================
--- 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/dos32krnl/dos.h?rev=67339&r1=67338&r2=67339&view=diff
==============================================================================
--- 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/dos32krnl/emsdrv.c?rev=67339&r1=67338&r2=67339&view=diff
==============================================================================
--- 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/dos32krnl/emsdrv.h?rev=67339
==============================================================================
--- 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/dos32krnl/himem.c?rev=67339
==============================================================================
--- 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/dos32krnl/himem.h?rev=67339
==============================================================================
--- 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


Reply via email to