From 4fb7f6e1d79cd98fcf7f6a9ed887d78cdd011f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Tue, 26 Nov 2013 20:20:51 +0000 Subject: [PATCH] [NTVDM] - Move some PS/2 initialization from bios.c to ps2.c - NULLify interrupt entries which are in fact pointers to data tables. - Add a framework for adding I/O port handlers. svn path=/branches/ntvdm/; revision=61107 --- subsystems/ntvdm/CMakeLists.txt | 1 + subsystems/ntvdm/bios.c | 20 +++- subsystems/ntvdm/cmos.c | 19 ++++ subsystems/ntvdm/cmos.h | 7 -- subsystems/ntvdm/dos.c | 4 +- subsystems/ntvdm/emulator.c | 192 +------------------------------- subsystems/ntvdm/emulator.h | 18 --- subsystems/ntvdm/io.c | 100 +++++++++++++++++ subsystems/ntvdm/io.h | 47 ++++++++ subsystems/ntvdm/ntvdm.c | 21 +++- subsystems/ntvdm/ntvdm.h | 6 + subsystems/ntvdm/pic.c | 54 ++++++++- subsystems/ntvdm/pic.h | 3 +- subsystems/ntvdm/ps2.c | 44 +++++++- subsystems/ntvdm/ps2.h | 8 +- subsystems/ntvdm/registers.c | 2 +- subsystems/ntvdm/speaker.c | 97 +++++++++------- subsystems/ntvdm/timer.c | 48 ++++++++ subsystems/ntvdm/timer.h | 5 +- subsystems/ntvdm/vga.c | 28 ++++- subsystems/ntvdm/vga.h | 5 +- 21 files changed, 445 insertions(+), 284 deletions(-) create mode 100644 subsystems/ntvdm/io.c create mode 100644 subsystems/ntvdm/io.h diff --git a/subsystems/ntvdm/CMakeLists.txt b/subsystems/ntvdm/CMakeLists.txt index 45bf971d23d..076c2c8b4cf 100644 --- a/subsystems/ntvdm/CMakeLists.txt +++ b/subsystems/ntvdm/CMakeLists.txt @@ -10,6 +10,7 @@ list(APPEND SOURCE dos.c emulator.c int32.c + io.c pic.c ps2.c registers.c diff --git a/subsystems/ntvdm/bios.c b/subsystems/ntvdm/bios.c index 183cebaba74..25294bcae23 100644 --- a/subsystems/ntvdm/bios.c +++ b/subsystems/ntvdm/bios.c @@ -28,7 +28,6 @@ static BYTE BiosKeyboardMap[256]; static HANDLE BiosConsoleInput = INVALID_HANDLE_VALUE; static HANDLE BiosConsoleOutput = INVALID_HANDLE_VALUE; static CONSOLE_SCREEN_BUFFER_INFO BiosSavedBufferInfo; -static HANDLE InputThread = NULL; /* * VGA Register Configurations for BIOS Video Modes @@ -486,6 +485,18 @@ BOOLEAN BiosInitialize(VOID) RegisterInt32(BIOS_TIME_INTERRUPT , BiosTimeService ); RegisterInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt); + /* Some interrupts are in fact addresses to tables */ + ((PDWORD)BaseAddress)[0x1D] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x1E] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x1F] = (DWORD)NULL; + + ((PDWORD)BaseAddress)[0x41] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x43] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x44] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x46] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x48] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x49] = (DWORD)NULL; + /* Get the input handle to the real console, and check for success */ BiosConsoleInput = CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE, @@ -537,8 +548,8 @@ BOOLEAN BiosInitialize(VOID) /* Set the console input mode */ SetConsoleMode(BiosConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT); - /* Start the input thread */ - InputThread = CreateThread(NULL, 0, &InputThreadProc, BiosConsoleInput, 0, NULL); + /* Initialize PS2 */ + PS2Initialize(BiosConsoleInput); /* Initialize the PIC */ PicWriteCommand(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4); @@ -569,8 +580,7 @@ BOOLEAN BiosInitialize(VOID) VOID BiosCleanup(VOID) { - /* Close the input thread handle */ - if (InputThread != NULL) CloseHandle(InputThread); + PS2Cleanup(); /* Restore the old screen buffer */ SetConsoleActiveScreenBuffer(BiosConsoleOutput); diff --git a/subsystems/ntvdm/cmos.c b/subsystems/ntvdm/cmos.c index 4b8a7f0d2a4..a49a57bc8b6 100644 --- a/subsystems/ntvdm/cmos.c +++ b/subsystems/ntvdm/cmos.c @@ -10,7 +10,9 @@ #define NDEBUG +#include "emulator.h" #include "cmos.h" +#include "io.h" #include "bios.h" #include "pic.h" @@ -305,6 +307,19 @@ VOID CmosWriteData(BYTE Value) SelectedRegister = CMOS_REG_STATUS_D; } +BYTE WINAPI CmosReadPort(ULONG Port) +{ + return CmosReadData(); +} + +VOID WINAPI CmosWritePort(ULONG Port, BYTE Data) +{ + if (Port == CMOS_ADDRESS_PORT) + CmosWriteAddress(Data); + else if (Port == CMOS_DATA_PORT) + CmosWriteData(Data); +} + DWORD RtcGetTicksPerSecond(VOID) { BYTE RateSelect = CmosMemory.StatusRegB & 0x0F; @@ -415,6 +430,10 @@ BOOLEAN CmosInitialize(VOID) CmosMemory.Diagnostics = 0x00; // Diagnostics must not find any errors. CmosMemory.ShutdownStatus = 0x00; + /* Register the I/O Ports */ + RegisterIoPort(CMOS_ADDRESS_PORT, NULL , CmosWritePort); + RegisterIoPort(CMOS_DATA_PORT , CmosReadPort, CmosWritePort); + return TRUE; } diff --git a/subsystems/ntvdm/cmos.h b/subsystems/ntvdm/cmos.h index 0e8d5f0c388..401cd08122d 100644 --- a/subsystems/ntvdm/cmos.h +++ b/subsystems/ntvdm/cmos.h @@ -39,10 +39,6 @@ #define CMOS_DEFAULT_STA 0x26 #define CMOS_DEFAULT_STB CMOS_STB_24HOUR -/* BCD-Binary conversion */ -#define BINARY_TO_BCD(x) (((x / 10) << 4) | (x % 10)) -#define BCD_TO_BINARY(x) (((x >> 4) * 10) + (x & 0x0F)) - #define WRITE_CMOS_DATA(Cmos, Value) \ ((Cmos).StatusRegB & CMOS_STB_BINARY) ? (Value) : BCD_TO_BINARY(Value) @@ -129,9 +125,6 @@ C_ASSERT(sizeof(CMOS_MEMORY) == 0x40); /* FUNCTIONS ******************************************************************/ BOOLEAN IsNmiEnabled(VOID); -VOID CmosWriteAddress(BYTE Value); -BYTE CmosReadData(VOID); -VOID CmosWriteData(BYTE Value); DWORD RtcGetTicksPerSecond(VOID); VOID RtcPeriodicTick(VOID); VOID RtcTimeUpdate(VOID); diff --git a/subsystems/ntvdm/dos.c b/subsystems/ntvdm/dos.c index 0a9de21a1f5..35e4c6fa26e 100644 --- a/subsystems/ntvdm/dos.c +++ b/subsystems/ntvdm/dos.c @@ -2580,7 +2580,9 @@ BOOLEAN DosInitialize(VOID) /* Register the DOS 32-bit Interrupts */ RegisterInt32(0x20, DosInt20h ); RegisterInt32(0x21, DosInt21h ); - RegisterInt32(0x23, DosBreakInterrupt); +// RegisterInt32(0x22, DosInt22h ); // Termination + RegisterInt32(0x23, DosBreakInterrupt); // Ctrl-C / Ctrl-Break +// RegisterInt32(0x24, DosInt24h ); // Critical Error RegisterInt32(0x2F, DosInt2Fh ); return TRUE; diff --git a/subsystems/ntvdm/emulator.c b/subsystems/ntvdm/emulator.c index 2dc3181ac9d..22617c57fac 100644 --- a/subsystems/ntvdm/emulator.c +++ b/subsystems/ntvdm/emulator.c @@ -11,16 +11,12 @@ #define NDEBUG #include "emulator.h" -#include "cmos.h" #include "bios.h" #include "bop.h" +#include "io.h" #include "registers.h" -#include "dos.h" -#include "speaker.h" #include "vga.h" #include "pic.h" -#include "ps2.h" -#include "timer.h" /* PRIVATE VARIABLES **********************************************************/ @@ -87,192 +83,6 @@ VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffe } } -VOID WINAPI EmulatorReadIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize) -{ - INT i, j; - LPBYTE Address = (LPBYTE)Buffer; - - UNREFERENCED_PARAMETER(State); - - for (i = 0; i < DataCount; i++) for (j = 0; j < DataSize; j++) - { - ULONG CurrentPort = Port + j; - - switch (CurrentPort) - { - case PIC_MASTER_CMD: - case PIC_SLAVE_CMD: - { - *(Address++) = PicReadCommand(CurrentPort); - break; - } - - case PIC_MASTER_DATA: - case PIC_SLAVE_DATA: - { - *(Address++) = PicReadData(CurrentPort); - break; - } - - case PIT_DATA_PORT(0): - case PIT_DATA_PORT(1): - case PIT_DATA_PORT(2): - { - *(Address++) = PitReadData(CurrentPort - PIT_DATA_PORT(0)); - break; - } - - case PS2_CONTROL_PORT: - { - *(Address++) = KeyboardReadStatus(); - break; - } - - case PS2_DATA_PORT: - { - *(Address++) = KeyboardReadData(); - break; - } - - case CMOS_DATA_PORT: - { - *(Address++) = CmosReadData(); - break; - } - - case SPEAKER_CONTROL_PORT: - { - *(Address++) = SpeakerReadStatus(); - break; - } - - case VGA_AC_WRITE: - case VGA_AC_READ: - case VGA_SEQ_INDEX: - case VGA_SEQ_DATA: - case VGA_DAC_READ_INDEX: - case VGA_DAC_WRITE_INDEX: - case VGA_DAC_DATA: - case VGA_MISC_READ: - case VGA_MISC_WRITE: - case VGA_CRTC_INDEX: - case VGA_CRTC_DATA: - case VGA_GC_INDEX: - case VGA_GC_DATA: - case VGA_STAT_MONO: - case VGA_STAT_COLOR: - { - *(Address++) = VgaReadPort(CurrentPort); - break; - } - - default: - { - DPRINT1("Read from unknown port: 0x%X\n", CurrentPort); - } - } - } -} - -VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize) -{ - INT i, j; - LPBYTE Address = (LPBYTE)Buffer; - - UNREFERENCED_PARAMETER(State); - - for (i = 0; i < DataCount; i++) for (j = 0; j < DataSize; j++) - { - ULONG CurrentPort = Port + j; - - switch (CurrentPort) - { - case PIT_COMMAND_PORT: - { - PitWriteCommand(*(Address++)); - break; - } - - case PIT_DATA_PORT(0): - case PIT_DATA_PORT(1): - case PIT_DATA_PORT(2): - { - PitWriteData(CurrentPort - PIT_DATA_PORT(0), *(Address++)); - break; - } - - case PIC_MASTER_CMD: - case PIC_SLAVE_CMD: - { - PicWriteCommand(CurrentPort, *(Address++)); - break; - } - - case PIC_MASTER_DATA: - case PIC_SLAVE_DATA: - { - PicWriteData(CurrentPort, *(Address++)); - break; - } - - case PS2_CONTROL_PORT: - { - KeyboardWriteCommand(*(Address++)); - break; - } - - case PS2_DATA_PORT: - { - KeyboardWriteData(*(Address++)); - break; - } - - case CMOS_ADDRESS_PORT: - { - CmosWriteAddress(*(Address++)); - break; - } - - case CMOS_DATA_PORT: - { - CmosWriteData(*(Address++)); - break; - } - - case SPEAKER_CONTROL_PORT: - { - SpeakerWriteCommand(*(Address++)); - break; - } - - case VGA_AC_WRITE: - case VGA_AC_READ: - case VGA_SEQ_INDEX: - case VGA_SEQ_DATA: - case VGA_DAC_READ_INDEX: - case VGA_DAC_WRITE_INDEX: - case VGA_DAC_DATA: - case VGA_MISC_READ: - case VGA_MISC_WRITE: - case VGA_CRTC_INDEX: - case VGA_CRTC_DATA: - case VGA_GC_INDEX: - case VGA_GC_DATA: - case VGA_STAT_MONO: - case VGA_STAT_COLOR: - { - VgaWritePort(CurrentPort, *(Address++)); - break; - } - - default: - { - DPRINT1("Write to unknown port: 0x%X\n", CurrentPort); - } - } - } -} - UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State) { UNREFERENCED_PARAMETER(State); diff --git a/subsystems/ntvdm/emulator.h b/subsystems/ntvdm/emulator.h index d0b4e490a75..d7c3835e2a6 100644 --- a/subsystems/ntvdm/emulator.h +++ b/subsystems/ntvdm/emulator.h @@ -79,24 +79,6 @@ VOID WINAPI EmulatorWriteMemory ULONG Size ); -VOID WINAPI EmulatorReadIo -( - PFAST486_STATE State, - ULONG Port, - PVOID Buffer, - ULONG DataCount, - UCHAR DataSize -); - -VOID WINAPI EmulatorWriteIo -( - PFAST486_STATE State, - ULONG Port, - PVOID Buffer, - ULONG DataCount, - UCHAR DataSize -); - UCHAR WINAPI EmulatorIntAcknowledge ( PFAST486_STATE State diff --git a/subsystems/ntvdm/io.c b/subsystems/ntvdm/io.c new file mode 100644 index 00000000000..7ce0cbf29af --- /dev/null +++ b/subsystems/ntvdm/io.c @@ -0,0 +1,100 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: io.c + * PURPOSE: I/O Port Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "io.h" + +/* PRIVATE VARIABLES **********************************************************/ + +typedef struct _EMULATOR_IOPORT_HANDLER +{ + EMULATOR_IN_PROC In; + EMULATOR_OUT_PROC Out; +} EMULATOR_IOPORT_HANDLER, *PEMULATOR_IOPORT_HANDLER; + +/* + * This is the list of registered I/O Port handlers. + */ +EMULATOR_IOPORT_HANDLER IoPortProc[EMULATOR_MAX_IOPORTS_NUM]; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID WINAPI RegisterIoPort(ULONG Port, + EMULATOR_IN_PROC InHandler, + EMULATOR_OUT_PROC OutHandler) +{ + if (IoPortProc[Port].In == NULL) + IoPortProc[Port].In = InHandler; + else + DPRINT1("IoPortProc[%d].In already registered\n", Port); + + if (IoPortProc[Port].Out == NULL) + IoPortProc[Port].Out = OutHandler; + else + DPRINT1("IoPortProc[%d].Out already registered\n", Port); +} + +VOID WINAPI +EmulatorReadIo(PFAST486_STATE State, + ULONG Port, + PVOID Buffer, + ULONG DataCount, + UCHAR DataSize) +{ + INT i, j; + LPBYTE Address = (LPBYTE)Buffer; + + UNREFERENCED_PARAMETER(State); + + for (i = 0; i < DataCount; i++) for (j = 0; j < DataSize; j++) + { + ULONG CurrentPort = Port + j; + + /* Call the IN Port handler */ + if (IoPortProc[CurrentPort].In != NULL) + { + *(Address++) = IoPortProc[CurrentPort].In(CurrentPort); + } + else + { + DPRINT1("Read from unknown port: 0x%X\n", CurrentPort); + *(Address++) = 0xFF; // Empty port value + } + } +} + +VOID WINAPI +EmulatorWriteIo(PFAST486_STATE State, + ULONG Port, + PVOID Buffer, + ULONG DataCount, + UCHAR DataSize) +{ + INT i, j; + LPBYTE Address = (LPBYTE)Buffer; + + UNREFERENCED_PARAMETER(State); + + for (i = 0; i < DataCount; i++) for (j = 0; j < DataSize; j++) + { + ULONG CurrentPort = Port + j; + + /* Call the OUT Port handler */ + if (IoPortProc[CurrentPort].Out != NULL) + IoPortProc[CurrentPort].Out(CurrentPort, *(Address++)); + else + DPRINT1("Write to unknown port: 0x%X\n", CurrentPort); + } +} + +/* EOF */ diff --git a/subsystems/ntvdm/io.h b/subsystems/ntvdm/io.h new file mode 100644 index 00000000000..115b91005e0 --- /dev/null +++ b/subsystems/ntvdm/io.h @@ -0,0 +1,47 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: io.c + * PURPOSE: I/O Port Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _IO_H_ +#define _IO_H_ + +/* DEFINES ********************************************************************/ + +#define EMULATOR_MAX_IOPORTS_NUM 0x10000 + +/* FUNCTIONS ******************************************************************/ + +typedef BYTE (WINAPI *EMULATOR_IN_PROC)(ULONG Port); +typedef VOID (WINAPI *EMULATOR_OUT_PROC)(ULONG Port, BYTE Data); + +VOID WINAPI RegisterIoPort(ULONG Port, + EMULATOR_IN_PROC InHandler, + EMULATOR_OUT_PROC OutHandler); + +VOID WINAPI EmulatorReadIo +( + PFAST486_STATE State, + ULONG Port, + PVOID Buffer, + ULONG DataCount, + UCHAR DataSize +); + +VOID WINAPI EmulatorWriteIo +( + PFAST486_STATE State, + ULONG Port, + PVOID Buffer, + ULONG DataCount, + UCHAR DataSize +); + + +#endif // _IO_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/ntvdm.c b/subsystems/ntvdm/ntvdm.c index 36e602feabe..4605469decb 100644 --- a/subsystems/ntvdm/ntvdm.c +++ b/subsystems/ntvdm/ntvdm.c @@ -103,6 +103,7 @@ INT wmain(INT argc, WCHAR *argv[]) DPRINT1("\n\n\nNTVDM - Starting '%s'...\n\n\n", CommandLine); + /* Initialize the emulator */ if (!EmulatorInitialize()) { wprintf(L"FATAL: Failed to initialize the CPU emulator\n"); @@ -116,6 +117,20 @@ INT wmain(INT argc, WCHAR *argv[]) goto Cleanup; } + /* Initialize the PIC */ + if (!PicInitialize()) + { + wprintf(L"FATAL: Failed to initialize the PIC.\n"); + goto Cleanup; + } + + /* Initialize the PIT */ + if (!PitInitialize()) + { + wprintf(L"FATAL: Failed to initialize the PIT.\n"); + goto Cleanup; + } + /* Initialize the CMOS */ if (!CmosInitialize()) { @@ -123,6 +138,9 @@ INT wmain(INT argc, WCHAR *argv[]) goto Cleanup; } + /* Initialize the PC Speaker */ + SpeakerInitialize(); + /* Initialize the system BIOS */ if (!BiosInitialize()) { @@ -130,9 +148,6 @@ INT wmain(INT argc, WCHAR *argv[]) goto Cleanup; } - /* Initialize the PC Speaker */ - SpeakerInitialize(); - /* Initialize the VDM DOS kernel */ if (!DosInitialize()) { diff --git a/subsystems/ntvdm/ntvdm.h b/subsystems/ntvdm/ntvdm.h index 073d6998511..c057413e4ce 100644 --- a/subsystems/ntvdm/ntvdm.h +++ b/subsystems/ntvdm/ntvdm.h @@ -27,6 +27,7 @@ /* DEFINES ********************************************************************/ +/* Basic Memory Management */ #define TO_LINEAR(seg, off) (((seg) << 4) + (off)) #define MAX_SEGMENT 0xFFFF #define MAX_OFFSET 0xFFFF @@ -38,6 +39,11 @@ #define SEG_OFF_TO_PTR(seg, off) \ (PVOID)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), (off))) +/* BCD-Binary conversion */ +#define BINARY_TO_BCD(x) ((((x) / 1000) << 12) + (((x) / 100) << 8) + (((x) / 10) << 4) + ((x) % 10)) +#define BCD_TO_BINARY(x) (((x) >> 12) * 1000 + ((x) >> 8) * 100 + ((x) >> 4) * 10 + ((x) & 0x0F)) + +/* Processor speed */ #define STEPS_PER_CYCLE 256 /* FUNCTIONS ******************************************************************/ diff --git a/subsystems/ntvdm/pic.c b/subsystems/ntvdm/pic.c index de7a0a119b5..ffe2c5271ed 100644 --- a/subsystems/ntvdm/pic.c +++ b/subsystems/ntvdm/pic.c @@ -10,8 +10,9 @@ #define NDEBUG -#include "pic.h" #include "emulator.h" +#include "io.h" +#include "pic.h" /* PRIVATE VARIABLES **********************************************************/ @@ -152,6 +153,46 @@ VOID PicWriteData(BYTE Port, BYTE Value) Pic->Initialization = FALSE; } +BYTE WINAPI PicReadPort(ULONG Port) +{ + switch (Port) + { + case PIC_MASTER_CMD: + case PIC_SLAVE_CMD: + { + return PicReadCommand(Port); + } + + case PIC_MASTER_DATA: + case PIC_SLAVE_DATA: + { + return PicReadData(Port); + } + } + + return 0; +} + +VOID WINAPI PicWritePort(ULONG Port, BYTE Data) +{ + switch (Port) + { + case PIC_MASTER_CMD: + case PIC_SLAVE_CMD: + { + PicWriteCommand(Port, Data); + break; + } + + case PIC_MASTER_DATA: + case PIC_SLAVE_DATA: + { + PicWriteData(Port, Data); + break; + } + } +} + VOID PicInterruptRequest(BYTE Number) { BYTE i; @@ -249,4 +290,15 @@ BYTE PicGetInterrupt(VOID) else return MasterPic.IntOffset + 7; } +BOOLEAN PicInitialize(VOID) +{ + /* Register the I/O Ports */ + RegisterIoPort(PIC_MASTER_CMD , PicReadPort, PicWritePort); + RegisterIoPort(PIC_SLAVE_CMD , PicReadPort, PicWritePort); + RegisterIoPort(PIC_MASTER_DATA, PicReadPort, PicWritePort); + RegisterIoPort(PIC_SLAVE_DATA , PicReadPort, PicWritePort); + + return TRUE; +} + /* EOF */ diff --git a/subsystems/ntvdm/pic.h b/subsystems/ntvdm/pic.h index ef60b61137b..2ff7ed7ef13 100644 --- a/subsystems/ntvdm/pic.h +++ b/subsystems/ntvdm/pic.h @@ -47,12 +47,11 @@ typedef struct _PIC /* FUNCTIONS ******************************************************************/ -BYTE PicReadCommand(BYTE Port); VOID PicWriteCommand(BYTE Port, BYTE Value); -BYTE PicReadData(BYTE Port); VOID PicWriteData(BYTE Port, BYTE Value); VOID PicInterruptRequest(BYTE Number); BYTE PicGetInterrupt(VOID); +BOOLEAN PicInitialize(VOID); #endif // _PIC_H_ diff --git a/subsystems/ntvdm/ps2.c b/subsystems/ntvdm/ps2.c index 03ff0182c39..13c9406da41 100644 --- a/subsystems/ntvdm/ps2.c +++ b/subsystems/ntvdm/ps2.c @@ -10,8 +10,9 @@ #define NDEBUG -#include "ps2.h" #include "emulator.h" +#include "io.h" +#include "ps2.h" #include "pic.h" /* PRIVATE VARIABLES **********************************************************/ @@ -24,6 +25,8 @@ static BYTE KeyboardData = 0, KeyboardResponse = 0; static BOOLEAN KeyboardReadResponse = FALSE, KeyboardWriteResponse = FALSE; static BYTE KeyboardConfig = PS2_DEFAULT_CONFIG; +static HANDLE InputThread = NULL; + /* PRIVATE FUNCTIONS **********************************************************/ static BOOLEAN KeyboardQueuePush(BYTE ScanCode) @@ -265,6 +268,24 @@ VOID KeyboardWriteData(BYTE Data) // TODO: Implement PS/2 device commands } +BYTE WINAPI PS2ReadPort(ULONG Port) +{ + if (Port == PS2_CONTROL_PORT) + return KeyboardReadStatus(); + else if (Port == PS2_DATA_PORT) + return KeyboardReadData(); + else + return 0; +} + +VOID WINAPI PS2WritePort(ULONG Port, BYTE Data) +{ + if (Port == PS2_CONTROL_PORT) + KeyboardWriteCommand(Data); + else if (Port == PS2_DATA_PORT) + KeyboardWriteData(Data); +} + DWORD WINAPI InputThreadProc(LPVOID Parameter) { INT i; @@ -325,4 +346,25 @@ DWORD WINAPI InputThreadProc(LPVOID Parameter) return 0; } +BOOLEAN PS2Initialize(HANDLE ConsoleInput) +{ + /* Start the input thread */ + InputThread = CreateThread(NULL, 0, &InputThreadProc, ConsoleInput, 0, NULL); + + // if (InputThread == NULL) return FALSE; + + /* Register the I/O Ports */ + RegisterIoPort(PS2_CONTROL_PORT, PS2ReadPort, PS2WritePort); + RegisterIoPort(PS2_DATA_PORT , PS2ReadPort, PS2WritePort); + + return TRUE; +} + +VOID PS2Cleanup(VOID) +{ + /* Close the input thread handle */ + if (InputThread != NULL) CloseHandle(InputThread); + InputThread = NULL; +} + /* EOF */ diff --git a/subsystems/ntvdm/ps2.h b/subsystems/ntvdm/ps2.h index 67799a67b2c..e152e2bd510 100644 --- a/subsystems/ntvdm/ps2.h +++ b/subsystems/ntvdm/ps2.h @@ -25,10 +25,12 @@ /* FUNCTIONS ******************************************************************/ BYTE KeyboardReadStatus(); -VOID KeyboardWriteCommand(BYTE Command); +//VOID KeyboardWriteCommand(BYTE Command); BYTE KeyboardReadData(); -VOID KeyboardWriteData(BYTE Data); -DWORD WINAPI InputThreadProc(LPVOID Parameter); +//VOID KeyboardWriteData(BYTE Data); + +BOOLEAN PS2Initialize(HANDLE ConsoleInput); +VOID PS2Cleanup(VOID); #endif // _PS2_H_ diff --git a/subsystems/ntvdm/registers.c b/subsystems/ntvdm/registers.c index c8ab49cdf5e..d8b634cfa35 100644 --- a/subsystems/ntvdm/registers.c +++ b/subsystems/ntvdm/registers.c @@ -668,7 +668,7 @@ VOID CDECL setMSW(USHORT Value) { - /* Set the lowest word (8 bits) */ + /* Set the lower 16 bits (Machine Status Word) of CR0 */ EmulatorContext.ControlRegisters[FAST486_REG_CR0] &= 0xFFFF0000; EmulatorContext.ControlRegisters[FAST486_REG_CR0] |= Value & 0xFFFF; } diff --git a/subsystems/ntvdm/speaker.c b/subsystems/ntvdm/speaker.c index 2499a7cdd26..84a81322975 100644 --- a/subsystems/ntvdm/speaker.c +++ b/subsystems/ntvdm/speaker.c @@ -10,8 +10,9 @@ #define NDEBUG -#include "speaker.h" #include "emulator.h" +#include "speaker.h" +#include "io.h" #include "timer.h" /* Extra PSDK/NDK Headers */ @@ -29,48 +30,8 @@ HANDLE hBeep = NULL; /* PUBLIC FUNCTIONS ***********************************************************/ -VOID SpeakerInitialize(VOID) -{ - NTSTATUS Status; - UNICODE_STRING BeepDevice; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - - /* Adapted from kernel32:Beep() */ - - // - // On TS systems, we need to Load Winsta.dll and call WinstationBeepOpen - // after doing a GetProcAddress for it - // - - /* Open the device */ - RtlInitUnicodeString(&BeepDevice, L"\\Device\\Beep"); - InitializeObjectAttributes(&ObjectAttributes, &BeepDevice, 0, NULL, NULL); - Status = NtCreateFile(&hBeep, - FILE_READ_DATA | FILE_WRITE_DATA, - &ObjectAttributes, - &IoStatusBlock, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN_IF, - 0, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to open Beep driver, Status 0x%08lx\n", Status); - } -} - -VOID SpeakerCleanup(VOID) -{ - NtClose(hBeep); -} - BYTE SpeakerReadStatus(VOID) { - // DPRINT1("SpeakerReadStatus() == 0x%x\n", Port61hState); return Port61hState; } @@ -79,8 +40,6 @@ VOID SpeakerWriteCommand(BYTE Value) BOOLEAN IsConnectedToPITChannel2; UCHAR SpeakerData; - // DPRINT1("SpeakerWriteCommand(0x%x)\n", Value); - Port61hState = Value; IsConnectedToPITChannel2 = ((Port61hState & 0x01) != 0); SpeakerData = (Port61hState & 0x02); @@ -162,4 +121,56 @@ VOID SpeakerWriteCommand(BYTE Value) } } +BYTE WINAPI SpeakerReadPort(ULONG Port) +{ + return SpeakerReadStatus(); +} + +VOID WINAPI SpeakerWritePort(ULONG Port, BYTE Data) +{ + SpeakerWriteCommand(Data); +} + +VOID SpeakerInitialize(VOID) +{ + NTSTATUS Status; + UNICODE_STRING BeepDevice; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + + /* Adapted from kernel32:Beep() */ + + // + // On TS systems, we need to Load Winsta.dll and call WinstationBeepOpen + // after doing a GetProcAddress for it + // + + /* Open the device */ + RtlInitUnicodeString(&BeepDevice, L"\\Device\\Beep"); + InitializeObjectAttributes(&ObjectAttributes, &BeepDevice, 0, NULL, NULL); + Status = NtCreateFile(&hBeep, + FILE_READ_DATA | FILE_WRITE_DATA, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to open Beep driver, Status 0x%08lx\n", Status); + } + + /* Register the I/O Ports */ + RegisterIoPort(SPEAKER_CONTROL_PORT, SpeakerReadPort, SpeakerWritePort); +} + +VOID SpeakerCleanup(VOID) +{ + NtClose(hBeep); +} + /* EOF */ diff --git a/subsystems/ntvdm/timer.c b/subsystems/ntvdm/timer.c index 29d20d58b9f..1cdceafdf55 100644 --- a/subsystems/ntvdm/timer.c +++ b/subsystems/ntvdm/timer.c @@ -10,6 +10,8 @@ #define NDEBUG +#include "emulator.h" +#include "io.h" #include "timer.h" #include "pic.h" @@ -147,6 +149,41 @@ VOID PitWriteData(BYTE Channel, BYTE Value) } } +static BYTE WINAPI PitReadPort(ULONG Port) +{ + switch (Port) + { + case PIT_DATA_PORT(0): + case PIT_DATA_PORT(1): + case PIT_DATA_PORT(2): + { + return PitReadData(Port - PIT_DATA_PORT(0)); + } + } + + return 0; +} + +static VOID WINAPI PitWritePort(ULONG Port, BYTE Data) +{ + switch (Port) + { + case PIT_COMMAND_PORT: + { + PitWriteCommand(Data); + break; + } + + case PIT_DATA_PORT(0): + case PIT_DATA_PORT(1): + case PIT_DATA_PORT(2): + { + PitWriteData(Port - PIT_DATA_PORT(0), Data); + break; + } + } +} + VOID PitDecrementCount(DWORD Count) { INT i; @@ -311,4 +348,15 @@ DWORD PitGetResolution(VOID) return PIT_BASE_FREQUENCY / MinReloadValue; } +BOOLEAN PitInitialize(VOID) +{ + /* Register the I/O Ports */ + RegisterIoPort(PIT_COMMAND_PORT, NULL , PitWritePort); + RegisterIoPort(PIT_DATA_PORT(0), PitReadPort, PitWritePort); + RegisterIoPort(PIT_DATA_PORT(1), PitReadPort, PitWritePort); + RegisterIoPort(PIT_DATA_PORT(2), PitReadPort, PitWritePort); + + return TRUE; +} + /* EOF */ diff --git a/subsystems/ntvdm/timer.h b/subsystems/ntvdm/timer.h index 3fbd4a7a762..4572263e598 100644 --- a/subsystems/ntvdm/timer.h +++ b/subsystems/ntvdm/timer.h @@ -2,7 +2,7 @@ * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine * FILE: timer.h - * PURPOSE: Programmable Interval Timer emulation (header file) + * PURPOSE: Programmable Interval Timer emulation * PROGRAMMERS: Aleksandar Andrejevic */ @@ -48,10 +48,11 @@ extern PPIT_CHANNEL PitChannel2; // Needed for PC Speaker /* FUNCTIONS ******************************************************************/ VOID PitWriteCommand(BYTE Value); -BYTE PitReadData(BYTE Channel); VOID PitWriteData(BYTE Channel, BYTE Value); + VOID PitDecrementCount(DWORD Count); DWORD PitGetResolution(VOID); +BOOLEAN PitInitialize(VOID); #endif // _TIMER_H_ diff --git a/subsystems/ntvdm/vga.c b/subsystems/ntvdm/vga.c index 4609e3d417f..9d04d184b2c 100644 --- a/subsystems/ntvdm/vga.c +++ b/subsystems/ntvdm/vga.c @@ -10,7 +10,10 @@ #define NDEBUG +#include "emulator.h" #include "vga.h" + +#include "io.h" #include "bios.h" /* PRIVATE VARIABLES **********************************************************/ @@ -1082,9 +1085,9 @@ VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size) } } -BYTE VgaReadPort(WORD Port) +BYTE WINAPI VgaReadPort(ULONG Port) { - DPRINT("VgaReadPort: Port 0x%04X\n", Port); + DPRINT("VgaReadPort: Port 0x%08X\n", Port); switch (Port) { @@ -1181,9 +1184,9 @@ BYTE VgaReadPort(WORD Port) return 0; } -VOID VgaWritePort(WORD Port, BYTE Data) +VOID WINAPI VgaWritePort(ULONG Port, BYTE Data) { - DPRINT("VgaWritePort: Port 0x%04X, Data 0x%02X\n", Port, Data); + DPRINT("VgaWritePort: Port 0x%08X, Data 0x%02X\n", Port, Data); switch (Port) { @@ -1353,6 +1356,23 @@ BOOLEAN VgaInitialize(HANDLE TextHandle) Address += ScanlineSize; } + /* Register the I/O Ports */ + RegisterIoPort(VGA_AC_WRITE , VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_AC_READ , VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_SEQ_INDEX, VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_SEQ_DATA , VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_DAC_READ_INDEX , VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_DAC_WRITE_INDEX, VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_DAC_DATA , VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_MISC_READ , VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_MISC_WRITE, VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_CRTC_INDEX, VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_CRTC_DATA , VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_GC_INDEX, VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_GC_DATA , VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_STAT_MONO , VgaReadPort, VgaWritePort); + RegisterIoPort(VGA_STAT_COLOR, VgaReadPort, VgaWritePort); + /* Return success */ return TRUE; } diff --git a/subsystems/ntvdm/vga.h b/subsystems/ntvdm/vga.h index 4686a04439e..a89895e6f81 100644 --- a/subsystems/ntvdm/vga.h +++ b/subsystems/ntvdm/vga.h @@ -199,12 +199,13 @@ VOID VgaRefreshDisplay(VOID); VOID VgaHorizontalRetrace(VOID); VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size); VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size); -BYTE VgaReadPort(WORD Port); -VOID VgaWritePort(WORD Port, BYTE Data); VOID VgaClearMemory(VOID); VOID VgaResetPalette(VOID); BOOLEAN VgaInitialize(HANDLE TextHandle); +BYTE WINAPI VgaReadPort(ULONG Port); +VOID WINAPI VgaWritePort(ULONG Port, BYTE Data); + #endif // _VGA_H_ /* EOF */