mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
[NTVDM]
Begin implementing Expanded Memory Space (EMS) support. svn path=/trunk/; revision=66596
This commit is contained in:
parent
005645416e
commit
3b4c8c96b6
4 changed files with 292 additions and 0 deletions
|
@ -33,6 +33,7 @@ list(APPEND SOURCE
|
|||
dos/mouse32.c
|
||||
dos/dem.c
|
||||
clock.c
|
||||
ems.c
|
||||
emulator.c
|
||||
int32.c
|
||||
io.c
|
||||
|
|
231
reactos/subsystems/mvdm/ntvdm/ems.c
Normal file
231
reactos/subsystems/mvdm/ntvdm/ems.c
Normal file
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* 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 "bios/bios32/bios32p.h"
|
||||
#include <ndk/rtltypes.h>
|
||||
#include <ndk/rtlfuncs.h>
|
||||
#include "ems.h"
|
||||
|
||||
/* PRIVATE VARIABLES **********************************************************/
|
||||
|
||||
static RTL_BITMAP AllocBitmap;
|
||||
static ULONG BitmapBuffer[(EMS_TOTAL_PAGES + sizeof(ULONG) - 1) / sizeof(ULONG)];
|
||||
static EMS_PAGE PageTable[EMS_TOTAL_PAGES];
|
||||
static EMS_HANDLE HandleTable[EMS_MAX_HANDLES];
|
||||
static PVOID Mapping[EMS_PHYSICAL_PAGES] = { 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 = (ULONG)(((ULONG_PTR)PageEntry - (ULONG_PTR)PageTable) / sizeof(EMS_PAGE));
|
||||
|
||||
/* 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 USHORT EmsMap(USHORT Handle, UCHAR PhysicalPage, USHORT LogicalPage)
|
||||
{
|
||||
PLIST_ENTRY Entry;
|
||||
PEMS_PAGE PageEntry;
|
||||
PEMS_HANDLE HandleEntry = &HandleTable[Handle];
|
||||
ULONG PageNumber;
|
||||
|
||||
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;
|
||||
|
||||
Entry = HandleEntry->PageList.Flink;
|
||||
while (LogicalPage)
|
||||
{
|
||||
if (Entry == &HandleEntry->PageList) break;
|
||||
|
||||
LogicalPage--;
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
|
||||
if (Entry == &HandleEntry->PageList) return EMS_STATUS_INV_LOGICAL_PAGE;
|
||||
|
||||
PageEntry = (PEMS_PAGE)CONTAINING_RECORD(Entry, EMS_PAGE, Entry);
|
||||
PageNumber = (ULONG)(((ULONG_PTR)PageEntry - (ULONG_PTR)PageTable) / sizeof(EMS_PAGE));
|
||||
Mapping[PhysicalPage] = (PVOID)(EMS_ADDRESS + PageNumber * 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(EMS_TOTAL_PAGES);
|
||||
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;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
DPRINT1("EMS function AH = %02X NOT IMPLEMENTED\n", getAH());
|
||||
setAH(EMS_STATUS_UNKNOWN_FUNCTION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
VOID EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
// TODO: NOT IMPLEMENTED
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size)
|
||||
{
|
||||
// TODO: NOT IMPLEMENTED
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID EmsInitialize(VOID)
|
||||
{
|
||||
ULONG i;
|
||||
RtlInitializeBitMap(&AllocBitmap, BitmapBuffer, EMS_TOTAL_PAGES);
|
||||
|
||||
for (i = 0; i < EMS_MAX_HANDLES; i++)
|
||||
{
|
||||
HandleTable[i].Allocated = FALSE;
|
||||
HandleTable[i].PageCount = 0;
|
||||
InitializeListHead(&HandleTable[i].PageList);
|
||||
}
|
||||
|
||||
RegisterBiosInt32(EMS_INTERRUPT_NUM, EmsIntHandler);
|
||||
}
|
56
reactos/subsystems/mvdm/ntvdm/ems.h
Normal file
56
reactos/subsystems/mvdm/ntvdm/ems.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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_INTERRUPT_NUM 0x67
|
||||
#define EMS_SEGMENT 0xE000
|
||||
#define EMS_MAX_HANDLES 16
|
||||
#define EMS_TOTAL_PAGES 256
|
||||
#define EMS_PAGE_BITS 14
|
||||
#define EMS_PAGE_SIZE (1 << EMS_PAGE_BITS)
|
||||
#define EMS_ADDRESS 0xA00000
|
||||
#define EMS_PHYSICAL_PAGES 4
|
||||
#define EMS_START_ADDRESS (EMS_SEGMENT << 4)
|
||||
#define EMS_END_ADDRESS (EMS_START_ADDRESS + EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE)
|
||||
|
||||
#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;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size);
|
||||
VOID EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size);
|
||||
VOID EmsInitialize(VOID);
|
||||
|
||||
#endif // _EMS_H_
|
||||
|
||||
/* EOF */
|
|
@ -30,6 +30,7 @@
|
|||
#include "hardware/sound/speaker.h"
|
||||
#include "hardware/pit.h"
|
||||
#include "hardware/video/vga.h"
|
||||
#include "ems.h"
|
||||
|
||||
#include "vddsup.h"
|
||||
#include "io.h"
|
||||
|
@ -619,6 +620,9 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
|
|||
/* Initialize I/O ports */
|
||||
/* Initialize RAM */
|
||||
|
||||
/* Initialize EMS */
|
||||
EmsInitialize();
|
||||
|
||||
/* Initialize the CPU */
|
||||
|
||||
/* Initialize the internal clock */
|
||||
|
|
Loading…
Reference in a new issue