Begin implementing Expanded Memory Space (EMS) support.


svn path=/trunk/; revision=66596
This commit is contained in:
Aleksandar Andrejevic 2015-03-07 00:43:17 +00:00
parent 005645416e
commit 3b4c8c96b6
4 changed files with 292 additions and 0 deletions

View file

@ -33,6 +33,7 @@ list(APPEND SOURCE
dos/mouse32.c
dos/dem.c
clock.c
ems.c
emulator.c
int32.c
io.c

View 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);
}

View 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 */

View file

@ -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 */