- Implement and export VDDInstallIOHook and VDDDeInstallIOHook; rework EmulatorRead/WriteIo to take into account for different port handlers' sizes (byte, word, dword). Still WIP and may be subject to renamings... RegisterIoPort needs to be converted.
- Stubplement and export getIntelRegistersPointer.
- Export c_get/setXX functions which are aliases to get/setXX functions, for MIPS NTVDM compatibility.

svn path=/branches/ntvdm/; revision=61358
This commit is contained in:
Hermès Bélusca-Maïto 2013-12-23 18:17:29 +00:00
parent 8e9d50c603
commit da6f99a13c
6 changed files with 613 additions and 49 deletions

View file

@ -16,38 +16,281 @@
/* PRIVATE VARIABLES **********************************************************/ /* PRIVATE VARIABLES **********************************************************/
typedef struct _EMULATOR_IOPORT_HANDLER typedef struct _EMULATOR_IOPORT_HANDLERS
{ {
EMULATOR_IN_PROC In; /* For Windows compatibility only, not used internally */
EMULATOR_OUT_PROC Out; HANDLE hVdd; // == 0 if unused,
} EMULATOR_IOPORT_HANDLER, *PEMULATOR_IOPORT_HANDLER; // INVALID_HANDLE_VALUE if handled internally,
// a valid VDD handle if handled externally.
VDD_IO_HANDLERS VddIoHandlers;
/* We use internally these members */
// EMULATOR_IN_PROC In;
// EMULATOR_OUT_PROC Out;
EMULATOR_INB_PROC InB;
EMULATOR_INW_PROC InW;
EMULATOR_IND_PROC InD;
EMULATOR_INSB_PROC InsB;
EMULATOR_INSW_PROC InsW;
EMULATOR_INSD_PROC InsD;
EMULATOR_OUTB_PROC OutB;
EMULATOR_OUTW_PROC OutW;
EMULATOR_OUTD_PROC OutD;
EMULATOR_OUTSB_PROC OutsB;
EMULATOR_OUTSW_PROC OutsW;
EMULATOR_OUTSD_PROC OutsD;
} EMULATOR_IOPORT_HANDLERS, *PEMULATOR_IOPORT_HANDLERS;
/* /*
* This is the list of registered I/O Port handlers. * This is the list of registered I/O Port handlers.
*/ */
EMULATOR_IOPORT_HANDLER IoPortProc[EMULATOR_MAX_IOPORTS_NUM]; EMULATOR_IOPORT_HANDLERS IoPortProc[EMULATOR_MAX_IOPORTS_NUM] = {{NULL}};
/* PRIVATE FUNCTIONS **********************************************************/
static VOID
IOReadB(ULONG Port,
PUCHAR Buffer)
{
if (IoPortProc[Port].InB)
{
*Buffer = IoPortProc[Port].InB(Port);
}
else
{
/* Return an empty port byte value */
DPRINT1("Read from unknown port: 0x%X\n", Port);
*Buffer = 0xFF;
}
}
static VOID
IOReadStrB(ULONG Port,
PUCHAR Buffer,
ULONG Count)
{
if (IoPortProc[Port].InsB)
{
IoPortProc[Port].InsB(Port, Buffer, Count);
}
else
{
while (Count--)
{
IOReadB(Port, Buffer++);
}
}
}
static VOID
IOWriteB(ULONG Port,
PUCHAR Buffer)
{
if (IoPortProc[Port].OutB)
{
IoPortProc[Port].OutB(Port, *Buffer);
}
else
{
/* Do nothing */
DPRINT1("Write to unknown port: 0x%X\n", Port);
}
}
static VOID
IOWriteStrB(ULONG Port,
PUCHAR Buffer,
ULONG Count)
{
if (IoPortProc[Port].OutsB)
{
IoPortProc[Port].OutsB(Port, Buffer, Count);
}
else
{
while (Count--)
{
IOWriteB(Port, Buffer++);
}
}
}
static VOID
IOReadW(ULONG Port,
PUSHORT Buffer)
{
if (IoPortProc[Port].InW)
{
*Buffer = IoPortProc[Port].InW(Port);
}
else
{
UCHAR Low, High;
// FIXME: Is it ok on Little endian and Big endian ??
IOReadB(Port, &Low);
IOReadB(Port + sizeof(UCHAR), &High);
*Buffer = MAKEWORD(Low, High);
}
}
static VOID
IOReadStrW(ULONG Port,
PUSHORT Buffer,
ULONG Count)
{
if (IoPortProc[Port].InsW)
{
IoPortProc[Port].InsW(Port, Buffer, Count);
}
else
{
while (Count--)
{
IOReadW(Port, Buffer++);
}
}
}
static VOID
IOWriteW(ULONG Port,
PUSHORT Buffer)
{
if (IoPortProc[Port].OutW)
{
IoPortProc[Port].OutW(Port, *Buffer);
}
else
{
UCHAR Low, High;
// FIXME: Is it ok on Little endian and Big endian ??
Low = LOBYTE(*Buffer);
High = HIBYTE(*Buffer);
IOWriteB(Port, &Low);
IOWriteB(Port + sizeof(UCHAR), &High);
}
}
static VOID
IOWriteStrW(ULONG Port,
PUSHORT Buffer,
ULONG Count)
{
if (IoPortProc[Port].OutsW)
{
IoPortProc[Port].OutsW(Port, Buffer, Count);
}
else
{
while (Count--)
{
IOWriteW(Port, Buffer++);
}
}
}
static VOID
IOReadD(ULONG Port,
PULONG Buffer)
{
if (IoPortProc[Port].InD)
{
*Buffer = IoPortProc[Port].InD(Port);
}
else
{
USHORT Low, High;
// FIXME: Is it ok on Little endian and Big endian ??
IOReadW(Port, &Low);
IOReadW(Port + sizeof(USHORT), &High);
*Buffer = MAKELONG(Low, High);
}
}
static VOID
IOReadStrD(ULONG Port,
PULONG Buffer,
ULONG Count)
{
if (IoPortProc[Port].InsD)
{
IoPortProc[Port].InsD(Port, Buffer, Count);
}
else
{
while (Count--)
{
IOReadD(Port, Buffer++);
}
}
}
static VOID
IOWriteD(ULONG Port,
PULONG Buffer)
{
if (IoPortProc[Port].OutD)
{
IoPortProc[Port].OutD(Port, *Buffer);
}
else
{
USHORT Low, High;
// FIXME: Is it ok on Little endian and Big endian ??
Low = LOWORD(*Buffer);
High = HIWORD(*Buffer);
IOWriteW(Port, &Low);
IOWriteW(Port + sizeof(USHORT), &High);
}
}
static VOID
IOWriteStrD(ULONG Port,
PULONG Buffer,
ULONG Count)
{
if (IoPortProc[Port].OutsD)
{
IoPortProc[Port].OutsD(Port, Buffer, Count);
}
else
{
while (Count--)
{
IOWriteD(Port, Buffer++);
}
}
}
/* PUBLIC FUNCTIONS ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
VOID WINAPI RegisterIoPort(ULONG Port, VOID RegisterIoPort(ULONG Port,
EMULATOR_IN_PROC InHandler, EMULATOR_INB_PROC InHandler,
EMULATOR_OUT_PROC OutHandler) EMULATOR_OUTB_PROC OutHandler)
{ {
if (IoPortProc[Port].In == NULL) if (IoPortProc[Port].InB == NULL)
IoPortProc[Port].In = InHandler; IoPortProc[Port].InB = InHandler;
else else
DPRINT1("IoPortProc[0x%X].In already registered\n", Port); DPRINT1("IoPortProc[0x%X].InB already registered\n", Port);
if (IoPortProc[Port].Out == NULL) if (IoPortProc[Port].OutB == NULL)
IoPortProc[Port].Out = OutHandler; IoPortProc[Port].OutB = OutHandler;
else else
DPRINT1("IoPortProc[0x%X].Out already registered\n", Port); DPRINT1("IoPortProc[0x%X].OutB already registered\n", Port);
} }
VOID WINAPI UnregisterIoPort(ULONG Port) VOID UnregisterIoPort(ULONG Port)
{ {
IoPortProc[Port].In = NULL; IoPortProc[Port].InB = NULL;
IoPortProc[Port].Out = NULL; IoPortProc[Port].OutB = NULL;
} }
VOID WINAPI VOID WINAPI
@ -57,24 +300,73 @@ EmulatorReadIo(PFAST486_STATE State,
ULONG DataCount, ULONG DataCount,
UCHAR DataSize) UCHAR DataSize)
{ {
INT i, j;
LPBYTE Address = (LPBYTE)Buffer;
UNREFERENCED_PARAMETER(State); UNREFERENCED_PARAMETER(State);
for (i = 0; i < DataCount; i++) for (j = 0; j < DataSize; j++) if (DataSize == 0 || DataCount == 0) return;
{
ULONG CurrentPort = Port + j;
/* Call the IN Port handler */ if (DataSize == sizeof(UCHAR))
if (IoPortProc[CurrentPort].In != NULL) {
{ if (DataCount == 1)
*(Address++) = IoPortProc[CurrentPort].In(CurrentPort); IOReadB(Port, Buffer);
}
else else
IOReadStrB(Port, Buffer, DataCount);
}
else if (DataSize == sizeof(USHORT))
{
if (DataCount == 1)
IOReadW(Port, Buffer);
else
IOReadStrW(Port, Buffer, DataCount);
}
else if (DataSize == sizeof(ULONG))
{
if (DataCount == 1)
IOReadD(Port, Buffer);
else
IOReadStrD(Port, Buffer, DataCount);
}
else
{
PBYTE Address = (PBYTE)Buffer;
while (DataCount--)
{ {
DPRINT1("Read from unknown port: 0x%X\n", CurrentPort); ULONG CurrentPort = Port;
*(Address++) = 0xFF; // Empty port value ULONG Count;
UCHAR NewDataSize = DataSize;
/* Read dword */
Count = NewDataSize / sizeof(ULONG);
NewDataSize = NewDataSize % sizeof(ULONG);
while (Count--)
{
IOReadD(CurrentPort, (PULONG)Address);
CurrentPort += sizeof(ULONG);
Address += sizeof(ULONG);
}
/* Read word */
Count = NewDataSize / sizeof(USHORT);
NewDataSize = NewDataSize % sizeof(USHORT);
while (Count--)
{
IOReadW(CurrentPort, (PUSHORT)Address);
CurrentPort += sizeof(USHORT);
Address += sizeof(USHORT);
}
/* Read byte */
Count = NewDataSize / sizeof(UCHAR);
NewDataSize = NewDataSize % sizeof(UCHAR);
while (Count--)
{
IOReadB(CurrentPort, (PUCHAR)Address);
CurrentPort += sizeof(UCHAR);
Address += sizeof(UCHAR);
}
ASSERT(Count == 0);
ASSERT(NewDataSize == 0);
} }
} }
} }
@ -86,20 +378,174 @@ EmulatorWriteIo(PFAST486_STATE State,
ULONG DataCount, ULONG DataCount,
UCHAR DataSize) UCHAR DataSize)
{ {
INT i, j;
LPBYTE Address = (LPBYTE)Buffer;
UNREFERENCED_PARAMETER(State); UNREFERENCED_PARAMETER(State);
for (i = 0; i < DataCount; i++) for (j = 0; j < DataSize; j++) if (DataSize == 0 || DataCount == 0) return;
{
ULONG CurrentPort = Port + j;
/* Call the OUT Port handler */ if (DataSize == sizeof(UCHAR))
if (IoPortProc[CurrentPort].Out != NULL) {
IoPortProc[CurrentPort].Out(CurrentPort, *(Address++)); if (DataCount == 1)
IOWriteB(Port, Buffer);
else else
DPRINT1("Write to unknown port: 0x%X\n", CurrentPort); IOWriteStrB(Port, Buffer, DataCount);
}
else if (DataSize == sizeof(USHORT))
{
if (DataCount == 1)
IOWriteW(Port, Buffer);
else
IOWriteStrW(Port, Buffer, DataCount);
}
else if (DataSize == sizeof(ULONG))
{
if (DataCount == 1)
IOWriteD(Port, Buffer);
else
IOWriteStrD(Port, Buffer, DataCount);
}
else
{
PBYTE Address = (PBYTE)Buffer;
while (DataCount--)
{
ULONG CurrentPort = Port;
ULONG Count;
UCHAR NewDataSize = DataSize;
/* Write dword */
Count = NewDataSize / sizeof(ULONG);
NewDataSize = NewDataSize % sizeof(ULONG);
while (Count--)
{
IOWriteD(CurrentPort, (PULONG)Address);
CurrentPort += sizeof(ULONG);
Address += sizeof(ULONG);
}
/* Write word */
Count = NewDataSize / sizeof(USHORT);
NewDataSize = NewDataSize % sizeof(USHORT);
while (Count--)
{
IOWriteW(CurrentPort, (PUSHORT)Address);
CurrentPort += sizeof(USHORT);
Address += sizeof(USHORT);
}
/* Write byte */
Count = NewDataSize / sizeof(UCHAR);
NewDataSize = NewDataSize % sizeof(UCHAR);
while (Count--)
{
IOWriteB(CurrentPort, (PUCHAR)Address);
CurrentPort += sizeof(UCHAR);
Address += sizeof(UCHAR);
}
ASSERT(Count == 0);
ASSERT(NewDataSize == 0);
}
}
}
BOOL
WINAPI
VDDInstallIOHook(HANDLE hVdd,
WORD cPortRange,
PVDD_IO_PORTRANGE pPortRange,
PVDD_IO_HANDLERS IOhandler)
{
/* Check possible validity of the VDD handle */
if (hVdd == 0 || hVdd == INVALID_HANDLE_VALUE) return FALSE;
/* Loop for each range of I/O ports */
while (cPortRange--)
{
WORD i;
/* Register the range of I/O ports */
for (i = pPortRange->First; i <= pPortRange->Last; ++i)
{
/*
* Don't do anything if the I/O port is already
* handled internally or externally.
*/
if (IoPortProc[i].hVdd != 0)
{
DPRINT1("IoPortProc[0x%X] already registered\n", i);
continue;
}
/* Register wrt. the VDD */
IoPortProc[i].hVdd = hVdd;
/* Disable the internal handlers */
IoPortProc[i].InB = NULL;
IoPortProc[i].InW = NULL;
IoPortProc[i].InD = NULL;
IoPortProc[i].InsB = NULL;
IoPortProc[i].InsW = NULL;
IoPortProc[i].InsD = NULL;
IoPortProc[i].OutB = NULL;
IoPortProc[i].OutW = NULL;
IoPortProc[i].OutD = NULL;
IoPortProc[i].OutsB = NULL;
IoPortProc[i].OutsW = NULL;
IoPortProc[i].OutsD = NULL;
/* Save our handlers */
IoPortProc[i].VddIoHandlers = *IOhandler; // IOhandler[i]; ?????????
}
/* Go to next range */
++pPortRange;
}
return TRUE;
}
VOID
WINAPI
VDDDeInstallIOHook(HANDLE hVdd,
WORD cPortRange,
PVDD_IO_PORTRANGE pPortRange)
{
/* Check possible validity of the VDD handle */
if (hVdd == 0 || hVdd == INVALID_HANDLE_VALUE) return;
/* Loop for each range of I/O ports */
while (cPortRange--)
{
WORD i;
/* Unregister the range of I/O ports */
for (i = pPortRange->First; i <= pPortRange->Last; ++i)
{
/*
* Don't do anything if we don't own the I/O port.
*/
if (IoPortProc[i].hVdd != hVdd)
{
DPRINT1("IoPortProc[0x%X] owned by somebody else\n", i);
continue;
}
/*
* Put automagically all the fields to zero:
* the hVdd gets unregistered as well as all the handlers.
*/
// IoPortProc[i] = {NULL};
ZeroMemory(&IoPortProc[i], sizeof(IoPortProc[i]));
}
/* Go to next range */
++pPortRange;
} }
} }

View file

@ -16,14 +16,28 @@
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
typedef BYTE (WINAPI *EMULATOR_IN_PROC)(ULONG Port); typedef UCHAR (WINAPI *EMULATOR_INB_PROC)(ULONG Port);
typedef VOID (WINAPI *EMULATOR_OUT_PROC)(ULONG Port, BYTE Data); typedef USHORT (WINAPI *EMULATOR_INW_PROC)(ULONG Port);
typedef ULONG (WINAPI *EMULATOR_IND_PROC)(ULONG Port);
VOID WINAPI RegisterIoPort(ULONG Port, typedef VOID (WINAPI *EMULATOR_INSB_PROC)(ULONG Port, PUCHAR Buffer, ULONG Count);
EMULATOR_IN_PROC InHandler, typedef VOID (WINAPI *EMULATOR_INSW_PROC)(ULONG Port, PUSHORT Buffer, ULONG Count);
EMULATOR_OUT_PROC OutHandler); typedef VOID (WINAPI *EMULATOR_INSD_PROC)(ULONG Port, PULONG Buffer, ULONG Count);
VOID WINAPI UnregisterIoPort(ULONG Port); typedef VOID (WINAPI *EMULATOR_OUTB_PROC)(ULONG Port, UCHAR Data);
typedef VOID (WINAPI *EMULATOR_OUTW_PROC)(ULONG Port, USHORT Data);
typedef VOID (WINAPI *EMULATOR_OUTD_PROC)(ULONG Port, ULONG Data);
typedef VOID (WINAPI *EMULATOR_OUTSB_PROC)(ULONG Port, PUCHAR Buffer, ULONG Count);
typedef VOID (WINAPI *EMULATOR_OUTSW_PROC)(ULONG Port, PUSHORT Buffer, ULONG Count);
typedef VOID (WINAPI *EMULATOR_OUTSD_PROC)(ULONG Port, PULONG Buffer, ULONG Count);
VOID RegisterIoPort(ULONG Port,
EMULATOR_INB_PROC InHandler,
EMULATOR_OUTB_PROC OutHandler);
VOID UnregisterIoPort(ULONG Port);
VOID WINAPI EmulatorReadIo VOID WINAPI EmulatorReadIo
( (

View file

@ -21,8 +21,11 @@
#include <wingdi.h> #include <wingdi.h>
#include <wincon.h> #include <wincon.h>
#include <winnls.h> #include <winnls.h>
#include <winreg.h>
#include <winuser.h> #include <winuser.h>
#include <nt_vdd.h>
#include <debug.h> #include <debug.h>
/* DEFINES ********************************************************************/ /* DEFINES ********************************************************************/

View file

@ -31,7 +31,7 @@
@ stdcall getFS() @ stdcall getFS()
@ stdcall getGS() @ stdcall getGS()
@ stdcall getIF() @ stdcall getIF()
; @ stdcall getIntelRegistersPointer() @ stdcall getIntelRegistersPointer()
@ stdcall getIP() @ stdcall getIP()
@ stdcall getMSW() @ stdcall getMSW()
@ stdcall getOF() @ stdcall getOF()
@ -42,8 +42,6 @@
@ stdcall getSS() @ stdcall getSS()
@ stdcall getZF() @ stdcall getZF()
@ stdcall setAF(long) @ stdcall setAF(long)
@ stdcall setAH(long) @ stdcall setAH(long)
@ stdcall setAL(long) @ stdcall setAL(long)
@ -88,6 +86,96 @@
@ stdcall setZF(long) @ stdcall setZF(long)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; NTVDM CCPU MIPS exports ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ stdcall c_getAF() getAF
@ stdcall c_getAH() getAH
@ stdcall c_getAL() getAL
@ stdcall c_getAX() getAX
@ stdcall c_getBH() getBH
@ stdcall c_getBL() getBL
@ stdcall c_getBP() getBP
@ stdcall c_getBX() getBX
@ stdcall c_getCF() getCF
@ stdcall c_getCH() getCH
@ stdcall c_getCL() getCL
@ stdcall c_getCS() getCS
@ stdcall c_getCX() getCX
@ stdcall c_getDF() getDF
@ stdcall c_getDH() getDH
@ stdcall c_getDI() getDI
@ stdcall c_getDL() getDL
@ stdcall c_getDS() getDS
@ stdcall c_getDX() getDX
@ stdcall c_getEAX() getEAX
@ stdcall c_getEBP() getEBP
@ stdcall c_getEBX() getEBX
@ stdcall c_getECX() getECX
@ stdcall c_getEDI() getEDI
@ stdcall c_getEDX() getEDX
@ stdcall c_getEIP() getEIP
@ stdcall c_getES() getES
@ stdcall c_getESI() getESI
@ stdcall c_getESP() getESP
@ stdcall c_getFS() getFS
@ stdcall c_getGS() getGS
@ stdcall c_getIF() getIF
@ stdcall c_getIP() getIP
@ stdcall c_getMSW() getMSW
@ stdcall c_getOF() getOF
@ stdcall c_getPF() getPF
@ stdcall c_getSF() getSF
@ stdcall c_getSI() getSI
@ stdcall c_getSP() getSP
@ stdcall c_getSS() getSS
@ stdcall c_getZF() getZF
@ stdcall c_setAF(long) setAF
@ stdcall c_setAH(long) setAH
@ stdcall c_setAL(long) setAL
@ stdcall c_setAX(long) setAX
@ stdcall c_setBH(long) setBH
@ stdcall c_setBL(long) setBL
@ stdcall c_setBP(long) setBP
@ stdcall c_setBX(long) setBX
@ stdcall c_setCF(long) setCF
@ stdcall c_setCH(long) setCH
@ stdcall c_setCL(long) setCL
@ stdcall c_setCS(long) setCS
@ stdcall c_setCX(long) setCX
@ stdcall c_setDF(long) setDF
@ stdcall c_setDH(long) setDH
@ stdcall c_setDI(long) setDI
@ stdcall c_setDL(long) setDL
@ stdcall c_setDS(long) setDS
@ stdcall c_setDX(long) setDX
@ stdcall c_setEAX(long) setEAX
@ stdcall c_setEBP(long) setEBP
@ stdcall c_setEBX(long) setEBX
@ stdcall c_setECX(long) setECX
@ stdcall c_setEDI(long) setEDI
@ stdcall c_setEDX(long) setEDX
@ stdcall c_setEIP(long) setEIP
@ stdcall c_setES(long) setES
@ stdcall c_setESI(long) setESI
@ stdcall c_setESP(long) setESP
@ stdcall c_setFS(long) setFS
@ stdcall c_setGS(long) setGS
@ stdcall c_setIF(long) setIF
@ stdcall c_setIP(long) setIP
@ stdcall c_setMSW(long) setMSW
@ stdcall c_setOF(long) setOF
@ stdcall c_setPF(long) setPF
@ stdcall c_setSF(long) setSF
@ stdcall c_setSI(long) setSI
@ stdcall c_setSP(long) setSP
@ stdcall c_setSS(long) setSS
@ stdcall c_setZF(long) setZF
@ stdcall MGetVdmPointer(long long long) @ stdcall MGetVdmPointer(long long long)
@ stdcall Sim32pGetVDMPointer(long long) @ stdcall Sim32pGetVDMPointer(long long)
@ -95,3 +183,6 @@
;@ stdcall VdmFlushCache(long long long long) ; Not exported on x86 ;@ stdcall VdmFlushCache(long long long long) ; Not exported on x86
@ stdcall VdmMapFlat(long long long) @ stdcall VdmMapFlat(long long long)
;@ stdcall VdmUnmapFlat(long long ptr long) ; Not exported on x86 ;@ stdcall VdmUnmapFlat(long long ptr long) ; Not exported on x86
@ stdcall VDDInstallIOHook(long long ptr ptr)
@ stdcall VDDDeInstallIOHook(long long ptr)

View file

@ -37,6 +37,14 @@ VOID EmulatorSetStack(WORD Segment, DWORD Offset)
PVOID
WINAPI
getIntelRegistersPointer(VOID)
{
UNIMPLEMENTED;
return NULL;
}
ULONG ULONG
WINAPI WINAPI
getEAX(VOID) getEAX(VOID)

View file

@ -14,6 +14,8 @@
VOID EmulatorSetStack(WORD Segment, DWORD Offset); VOID EmulatorSetStack(WORD Segment, DWORD Offset);
PVOID WINAPI getIntelRegistersPointer(VOID);
ULONG WINAPI getEAX(VOID); ULONG WINAPI getEAX(VOID);
VOID WINAPI setEAX(ULONG); VOID WINAPI setEAX(ULONG);
USHORT WINAPI getAX(VOID); USHORT WINAPI getAX(VOID);