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/mouse32.c
|
||||||
dos/dem.c
|
dos/dem.c
|
||||||
clock.c
|
clock.c
|
||||||
|
ems.c
|
||||||
emulator.c
|
emulator.c
|
||||||
int32.c
|
int32.c
|
||||||
io.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/sound/speaker.h"
|
||||||
#include "hardware/pit.h"
|
#include "hardware/pit.h"
|
||||||
#include "hardware/video/vga.h"
|
#include "hardware/video/vga.h"
|
||||||
|
#include "ems.h"
|
||||||
|
|
||||||
#include "vddsup.h"
|
#include "vddsup.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
@ -619,6 +620,9 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
|
||||||
/* Initialize I/O ports */
|
/* Initialize I/O ports */
|
||||||
/* Initialize RAM */
|
/* Initialize RAM */
|
||||||
|
|
||||||
|
/* Initialize EMS */
|
||||||
|
EmsInitialize();
|
||||||
|
|
||||||
/* Initialize the CPU */
|
/* Initialize the CPU */
|
||||||
|
|
||||||
/* Initialize the internal clock */
|
/* Initialize the internal clock */
|
||||||
|
|
Loading…
Reference in a new issue