From 574f922049834b57658086ec75e4d21b1582e170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Mon, 17 Feb 2014 22:20:03 +0000 Subject: [PATCH] [NTVDM] - Remove an unneeded assignment (cmos.c) - Reorganize BIOS code: put our 32-bit bios in a dedicated directory; start to introduce a way to load other bioses (WIP). svn path=/branches/ntvdm/; revision=62235 --- subsystems/ntvdm/CMakeLists.txt | 5 +- subsystems/ntvdm/bios/bios.c | 362 +---------------- subsystems/ntvdm/bios/bios.h | 31 +- subsystems/ntvdm/bios/bios32/bios32.c | 381 ++++++++++++++++++ subsystems/ntvdm/bios/bios32/bios32.h | 131 ++++++ .../bios/{kbdbios.c => bios32/kbdbios32.c} | 12 +- .../bios/{kbdbios.h => bios32/kbdbios32.h} | 14 +- .../bios/{vidbios.c => bios32/vidbios32.c} | 12 +- .../bios/{vidbios.h => bios32/vidbios32.h} | 14 +- subsystems/ntvdm/hardware/cmos.c | 2 +- subsystems/ntvdm/ntvdm.c | 22 +- 11 files changed, 572 insertions(+), 414 deletions(-) create mode 100644 subsystems/ntvdm/bios/bios32/bios32.c create mode 100644 subsystems/ntvdm/bios/bios32/bios32.h rename subsystems/ntvdm/bios/{kbdbios.c => bios32/kbdbios32.c} (97%) rename subsystems/ntvdm/bios/{kbdbios.h => bios32/kbdbios32.h} (85%) rename subsystems/ntvdm/bios/{vidbios.c => bios32/vidbios32.c} (99%) rename subsystems/ntvdm/bios/{vidbios.h => bios32/vidbios32.h} (81%) diff --git a/subsystems/ntvdm/CMakeLists.txt b/subsystems/ntvdm/CMakeLists.txt index 1d182277062..278439733e9 100644 --- a/subsystems/ntvdm/CMakeLists.txt +++ b/subsystems/ntvdm/CMakeLists.txt @@ -6,9 +6,10 @@ include_directories( spec2def(ntvdm.exe ntvdm.spec) list(APPEND SOURCE + bios/bios32/bios32.c + bios/bios32/kbdbios32.c + bios/bios32/vidbios32.c bios/bios.c - bios/kbdbios.c - bios/vidbios.c hardware/cmos.c hardware/pic.c hardware/ps2.c diff --git a/subsystems/ntvdm/bios/bios.c b/subsystems/ntvdm/bios/bios.c index 3ab1be5fa31..b90a71f84da 100644 --- a/subsystems/ntvdm/bios/bios.c +++ b/subsystems/ntvdm/bios/bios.c @@ -2,379 +2,35 @@ * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine * FILE: bios.c - * PURPOSE: VDM BIOS - * PROGRAMMERS: Aleksandar Andrejevic + * PURPOSE: VDM BIOS Support Library + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ /* INCLUDES *******************************************************************/ #define NDEBUG -#include "emulator.h" #include "bios.h" -#include "io.h" -#include "hardware/cmos.h" -#include "hardware/pic.h" -#include "hardware/timer.h" - -#include "int32.h" - /* PRIVATE VARIABLES **********************************************************/ -PBIOS_DATA_AREA Bda; +static BOOLEAN Bios32Loaded = FALSE; /* PRIVATE FUNCTIONS **********************************************************/ -static VOID WINAPI BiosException(LPWORD Stack) -{ - /* Get the exception number and call the emulator API */ - BYTE ExceptionNumber = LOBYTE(Stack[STACK_INT_NUM]); - EmulatorException(ExceptionNumber, Stack); -} - -static VOID WINAPI BiosEquipmentService(LPWORD Stack) -{ - /* Return the equipment list */ - setAX(Bda->EquipmentList); -} - -static VOID WINAPI BiosGetMemorySize(LPWORD Stack) -{ - /* Return the conventional memory size in kB, typically 640 kB */ - setAX(Bda->MemorySize); -} - -static VOID WINAPI BiosMiscService(LPWORD Stack) -{ - switch (getAH()) - { - /* Wait */ - case 0x86: - { - /* - * Interval in microseconds in CX:DX - * See Ralf Brown: http://www.ctyme.com/intr/rb-1525.htm - * for more information. - */ - Sleep(MAKELONG(getDX(), getCX())); - - /* Clear CF */ - Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; - - break; - } - - /* Copy Extended Memory */ - case 0x87: - { - DWORD Count = (DWORD)getCX() * 2; - PFAST486_GDT_ENTRY Gdt = (PFAST486_GDT_ENTRY)SEG_OFF_TO_PTR(getES(), getSI()); - DWORD SourceBase = Gdt[2].Base + (Gdt[2].BaseMid << 16) + (Gdt[2].BaseHigh << 24); - DWORD SourceLimit = Gdt[2].Limit + (Gdt[2].LimitHigh << 16); - DWORD DestBase = Gdt[3].Base + (Gdt[3].BaseMid << 16) + (Gdt[3].BaseHigh << 24); - DWORD DestLimit = Gdt[3].Limit + (Gdt[3].LimitHigh << 16); - - /* Check for flags */ - if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF; - if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF; - - if ((Count > SourceLimit) || (Count > DestLimit)) - { - setAX(0x80); - Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; - - break; - } - - /* Copy */ - RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase), - (PVOID)((ULONG_PTR)BaseAddress + SourceBase), - Count); - - setAX(ERROR_SUCCESS); - Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; - break; - } - - /* Get Extended Memory Size */ - case 0x88: - { - UCHAR Low, High; - - /* - * Return the (usable) extended memory (after 1 MB) - * size in kB from CMOS. - */ - IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_LOW); - Low = IOReadB(CMOS_DATA_PORT); - IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_HIGH); - High = IOReadB(CMOS_DATA_PORT); - setAX(MAKEWORD(Low, High)); - - /* Clear CF */ - Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; - - break; - } - - default: - { - DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n", - getAH()); - } - } -} - -static VOID WINAPI BiosTimeService(LPWORD Stack) -{ - switch (getAH()) - { - case 0x00: - { - /* Set AL to 1 if midnight had passed, 0 otherwise */ - setAL(Bda->MidnightPassed ? 0x01 : 0x00); - - /* Return the tick count in CX:DX */ - setCX(HIWORD(Bda->TickCounter)); - setDX(LOWORD(Bda->TickCounter)); - - /* Reset the midnight flag */ - Bda->MidnightPassed = FALSE; - - break; - } - - case 0x01: - { - /* Set the tick count to CX:DX */ - Bda->TickCounter = MAKELONG(getDX(), getCX()); - - /* Reset the midnight flag */ - Bda->MidnightPassed = FALSE; - - break; - } - - default: - { - DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n", - getAH()); - } - } -} - -static VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack) -{ - /* Increase the system tick count */ - Bda->TickCounter++; -} - - -// From SeaBIOS -static VOID PicSetIRQMask(USHORT off, USHORT on) -{ - UCHAR pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8; - IOWriteB(PIC_MASTER_DATA, (IOReadB(PIC_MASTER_DATA) & ~pic1off) | pic1on); - IOWriteB(PIC_SLAVE_DATA , (IOReadB(PIC_SLAVE_DATA ) & ~pic2off) | pic2on); -} - -// From SeaBIOS -VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func) -{ - UCHAR vector; - - PicSetIRQMask(1 << hwirq, 0); - if (hwirq < 8) - vector = BIOS_PIC_MASTER_INT + hwirq; - else - vector = BIOS_PIC_SLAVE_INT + hwirq - 8; - - RegisterInt32(vector, func); -} - - -VOID PicIRQComplete(LPWORD Stack) -{ - /* Get the interrupt number */ - BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]); - - /* - * If this was a PIC IRQ, send an End-of-Interrupt to the PIC. - */ - - if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8) - { - /* It was an IRQ from the master PIC */ - IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI); - } - else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8) - { - /* It was an IRQ from the slave PIC */ - IOWriteB(PIC_SLAVE_CMD , PIC_OCW2_EOI); - IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI); - } -} - -static VOID WINAPI BiosHandleMasterPicIRQ(LPWORD Stack) -{ - BYTE IrqNumber; - - IOWriteB(PIC_MASTER_CMD, PIC_OCW3_READ_ISR /* == 0x0B */); - IrqNumber = IOReadB(PIC_MASTER_CMD); - - DPRINT("Master - IrqNumber = 0x%x\n", IrqNumber); - - PicIRQComplete(Stack); -} - -static VOID WINAPI BiosHandleSlavePicIRQ(LPWORD Stack) -{ - BYTE IrqNumber; - - IOWriteB(PIC_SLAVE_CMD, PIC_OCW3_READ_ISR /* == 0x0B */); - IrqNumber = IOReadB(PIC_SLAVE_CMD); - - DPRINT("Slave - IrqNumber = 0x%x\n", IrqNumber); - - PicIRQComplete(Stack); -} - -// Timer IRQ 0 -static VOID WINAPI BiosTimerIrq(LPWORD Stack) -{ - /* - * Perform the system timer interrupt. - * - * Do not call directly BiosSystemTimerInterrupt(Stack); - * because some programs may hook only BIOS_SYS_TIMER_INTERRUPT - * for their purpose... - */ - EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT); - PicIRQComplete(Stack); -} - - -static VOID BiosHwSetup(VOID) -{ - /* Initialize the master and the slave PICs (cascade mode) */ - IOWriteB(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4); - IOWriteB(PIC_SLAVE_CMD , PIC_ICW1 | PIC_ICW1_ICW4); - - /* - * Set the interrupt vector offsets for each PIC - * (base IRQs: 0x08-0x0F for IRQ 0-7, 0x70-0x77 for IRQ 8-15) - */ - IOWriteB(PIC_MASTER_DATA, BIOS_PIC_MASTER_INT); - IOWriteB(PIC_SLAVE_DATA , BIOS_PIC_SLAVE_INT ); - - /* Tell the master PIC that there is a slave PIC at IRQ 2 */ - IOWriteB(PIC_MASTER_DATA, 1 << 2); - /* Tell the slave PIC its cascade identity */ - IOWriteB(PIC_SLAVE_DATA , 2); - - /* Make sure both PICs are in 8086 mode */ - IOWriteB(PIC_MASTER_DATA, PIC_ICW4_8086); - IOWriteB(PIC_SLAVE_DATA , PIC_ICW4_8086); - - /* Clear the masks for both PICs */ - // IOWriteB(PIC_MASTER_DATA, 0x00); - // IOWriteB(PIC_SLAVE_DATA , 0x00); - /* Disable all IRQs */ - IOWriteB(PIC_MASTER_DATA, 0xFF); - IOWriteB(PIC_SLAVE_DATA , 0xFF); - - - /* Initialize PIT Counter 0 */ - IOWriteB(PIT_COMMAND_PORT, 0x34); - IOWriteB(PIT_DATA_PORT(0), 0x00); - IOWriteB(PIT_DATA_PORT(0), 0x00); - - /* Initialize PIT Counter 1 */ - IOWriteB(PIT_COMMAND_PORT, 0x74); - IOWriteB(PIT_DATA_PORT(1), 0x00); - IOWriteB(PIT_DATA_PORT(1), 0x00); - - /* Initialize PIT Counter 2 */ - IOWriteB(PIT_COMMAND_PORT, 0xB4); - IOWriteB(PIT_DATA_PORT(2), 0x00); - IOWriteB(PIT_DATA_PORT(2), 0x00); - - EnableHwIRQ(0, BiosTimerIrq); -} - /* PUBLIC FUNCTIONS ***********************************************************/ -/* - * The BIOS POST (Power On-Self Test) - */ -BOOLEAN BiosInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput) +BOOLEAN BiosInitialize(IN LPCWSTR BiosFileName, + IN HANDLE ConsoleInput, + IN HANDLE ConsoleOutput) { - UCHAR Low, High; - UCHAR i; - - /* Initialize the BDA */ - Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0); - Bda->EquipmentList = BIOS_EQUIPMENT_LIST; - - /* - * Retrieve the conventional memory size - * in kB from CMOS, typically 640 kB. - */ - IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_LOW); - Low = IOReadB(CMOS_DATA_PORT); - IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_HIGH); - High = IOReadB(CMOS_DATA_PORT); - Bda->MemorySize = MAKEWORD(Low, High); - - /* Initialize the 32-bit Interrupt system */ - InitializeInt32(BIOS_SEGMENT); - - /* Register the BIOS 32-bit Interrupts */ - - /* Initialize the exception vector interrupts to a default Exception handler */ - for (i = 0; i < 8; i++) - RegisterInt32(i, BiosException); - - /* Initialize HW vector interrupts to a default HW handler */ - for (i = BIOS_PIC_MASTER_INT; i < BIOS_PIC_MASTER_INT + 8; i++) - RegisterInt32(i, BiosHandleMasterPicIRQ); - for (i = BIOS_PIC_SLAVE_INT ; i < BIOS_PIC_SLAVE_INT + 8; i++) - RegisterInt32(i, BiosHandleSlavePicIRQ); - - /* Initialize software vector handlers */ - RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService ); - RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize ); - RegisterInt32(BIOS_MISC_INTERRUPT , BiosMiscService ); - RegisterInt32(BIOS_TIME_INTERRUPT , BiosTimeService ); - RegisterInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt); - - /* Some interrupts are in fact addresses to tables */ - ((PDWORD)BaseAddress)[0x1E] = (DWORD)NULL; - ((PDWORD)BaseAddress)[0x41] = (DWORD)NULL; - ((PDWORD)BaseAddress)[0x46] = (DWORD)NULL; - ((PDWORD)BaseAddress)[0x48] = (DWORD)NULL; - ((PDWORD)BaseAddress)[0x49] = (DWORD)NULL; - - /* Initialize platform hardware (PIC/PIT chips, ...) */ - BiosHwSetup(); - - /* Initialize the Keyboard BIOS */ - if (!KbdBiosInitialize(ConsoleInput)) return FALSE; - - /* Set the console input mode */ - SetConsoleMode(ConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT); - - /* Initialize the Video BIOS */ - if (!VidBiosInitialize(ConsoleOutput)) return FALSE; - - return TRUE; + Bios32Loaded = Bios32Initialize(ConsoleInput, ConsoleOutput); + return Bios32Loaded; } VOID BiosCleanup(VOID) { - VidBiosCleanup(); - KbdBiosCleanup(); + if (Bios32Loaded) Bios32Cleanup(); } /* EOF */ diff --git a/subsystems/ntvdm/bios/bios.h b/subsystems/ntvdm/bios/bios.h index cd0df097f2d..93e8660c7fb 100644 --- a/subsystems/ntvdm/bios/bios.h +++ b/subsystems/ntvdm/bios/bios.h @@ -2,8 +2,8 @@ * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine * FILE: bios.h - * PURPOSE: VDM BIOS - * PROGRAMMERS: Aleksandar Andrejevic + * PURPOSE: VDM BIOS Support Library + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ #ifndef _BIOS_H_ @@ -12,28 +12,18 @@ /* INCLUDES *******************************************************************/ #include "ntvdm.h" -#include "kbdbios.h" -#include "vidbios.h" +#include "bios32/bios32.h" /* DEFINES ********************************************************************/ #define ROM_AREA_START 0xE0000 #define ROM_AREA_END 0xFFFFF +#if 0 + #define BDA_SEGMENT 0x40 #define BIOS_SEGMENT 0xF000 -#define BIOS_PIC_MASTER_INT 0x08 -#define BIOS_PIC_SLAVE_INT 0x70 - -#define BIOS_EQUIPMENT_INTERRUPT 0x11 -#define BIOS_MEMORY_SIZE 0x12 -#define BIOS_MISC_INTERRUPT 0x15 -#define BIOS_TIME_INTERRUPT 0x1A -#define BIOS_SYS_TIMER_INTERRUPT 0x1C - -#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now - /* * BIOS Data Area at 0040:XXXX * @@ -112,16 +102,15 @@ typedef struct C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x133); +#endif + /* FUNCTIONS ******************************************************************/ extern PBIOS_DATA_AREA Bda; -/**HACK!!**/typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);/**HACK!!**/ - -VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func); -VOID PicIRQComplete(LPWORD Stack); - -BOOLEAN BiosInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput); +BOOLEAN BiosInitialize(IN LPCWSTR BiosFileName, + IN HANDLE ConsoleInput, + IN HANDLE ConsoleOutput); VOID BiosCleanup(VOID); #endif // _BIOS_H_ diff --git a/subsystems/ntvdm/bios/bios32/bios32.c b/subsystems/ntvdm/bios/bios32/bios32.c new file mode 100644 index 00000000000..e37536742d6 --- /dev/null +++ b/subsystems/ntvdm/bios/bios32/bios32.c @@ -0,0 +1,381 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bios32.c + * PURPOSE: VDM 32-bit BIOS + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "bios32.h" + +#include "io.h" +#include "hardware/cmos.h" +#include "hardware/pic.h" +#include "hardware/timer.h" + +#include "int32.h" + +/* PRIVATE VARIABLES **********************************************************/ + +PBIOS_DATA_AREA Bda; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static VOID WINAPI BiosException(LPWORD Stack) +{ + /* Get the exception number and call the emulator API */ + BYTE ExceptionNumber = LOBYTE(Stack[STACK_INT_NUM]); + EmulatorException(ExceptionNumber, Stack); +} + +static VOID WINAPI BiosEquipmentService(LPWORD Stack) +{ + /* Return the equipment list */ + setAX(Bda->EquipmentList); +} + +static VOID WINAPI BiosGetMemorySize(LPWORD Stack) +{ + /* Return the conventional memory size in kB, typically 640 kB */ + setAX(Bda->MemorySize); +} + +static VOID WINAPI BiosMiscService(LPWORD Stack) +{ + switch (getAH()) + { + /* Wait */ + case 0x86: + { + /* + * Interval in microseconds in CX:DX + * See Ralf Brown: http://www.ctyme.com/intr/rb-1525.htm + * for more information. + */ + Sleep(MAKELONG(getDX(), getCX())); + + /* Clear CF */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + break; + } + + /* Copy Extended Memory */ + case 0x87: + { + DWORD Count = (DWORD)getCX() * 2; + PFAST486_GDT_ENTRY Gdt = (PFAST486_GDT_ENTRY)SEG_OFF_TO_PTR(getES(), getSI()); + DWORD SourceBase = Gdt[2].Base + (Gdt[2].BaseMid << 16) + (Gdt[2].BaseHigh << 24); + DWORD SourceLimit = Gdt[2].Limit + (Gdt[2].LimitHigh << 16); + DWORD DestBase = Gdt[3].Base + (Gdt[3].BaseMid << 16) + (Gdt[3].BaseHigh << 24); + DWORD DestLimit = Gdt[3].Limit + (Gdt[3].LimitHigh << 16); + + /* Check for flags */ + if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF; + if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF; + + if ((Count > SourceLimit) || (Count > DestLimit)) + { + setAX(0x80); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + + break; + } + + /* Copy */ + RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase), + (PVOID)((ULONG_PTR)BaseAddress + SourceBase), + Count); + + setAX(ERROR_SUCCESS); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + break; + } + + /* Get Extended Memory Size */ + case 0x88: + { + UCHAR Low, High; + + /* + * Return the (usable) extended memory (after 1 MB) + * size in kB from CMOS. + */ + IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_LOW); + Low = IOReadB(CMOS_DATA_PORT); + IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_HIGH); + High = IOReadB(CMOS_DATA_PORT); + setAX(MAKEWORD(Low, High)); + + /* Clear CF */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + break; + } + + default: + { + DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n", + getAH()); + } + } +} + +static VOID WINAPI BiosTimeService(LPWORD Stack) +{ + switch (getAH()) + { + case 0x00: + { + /* Set AL to 1 if midnight had passed, 0 otherwise */ + setAL(Bda->MidnightPassed ? 0x01 : 0x00); + + /* Return the tick count in CX:DX */ + setCX(HIWORD(Bda->TickCounter)); + setDX(LOWORD(Bda->TickCounter)); + + /* Reset the midnight flag */ + Bda->MidnightPassed = FALSE; + + break; + } + + case 0x01: + { + /* Set the tick count to CX:DX */ + Bda->TickCounter = MAKELONG(getDX(), getCX()); + + /* Reset the midnight flag */ + Bda->MidnightPassed = FALSE; + + break; + } + + default: + { + DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n", + getAH()); + } + } +} + +static VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack) +{ + /* Increase the system tick count */ + Bda->TickCounter++; +} + + +// From SeaBIOS +static VOID PicSetIRQMask(USHORT off, USHORT on) +{ + UCHAR pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8; + IOWriteB(PIC_MASTER_DATA, (IOReadB(PIC_MASTER_DATA) & ~pic1off) | pic1on); + IOWriteB(PIC_SLAVE_DATA , (IOReadB(PIC_SLAVE_DATA ) & ~pic2off) | pic2on); +} + +// From SeaBIOS +VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func) +{ + UCHAR vector; + + PicSetIRQMask(1 << hwirq, 0); + if (hwirq < 8) + vector = BIOS_PIC_MASTER_INT + hwirq; + else + vector = BIOS_PIC_SLAVE_INT + hwirq - 8; + + RegisterInt32(vector, func); +} + + +VOID PicIRQComplete(LPWORD Stack) +{ + /* Get the interrupt number */ + BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]); + + /* + * If this was a PIC IRQ, send an End-of-Interrupt to the PIC. + */ + + if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8) + { + /* It was an IRQ from the master PIC */ + IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI); + } + else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8) + { + /* It was an IRQ from the slave PIC */ + IOWriteB(PIC_SLAVE_CMD , PIC_OCW2_EOI); + IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI); + } +} + +static VOID WINAPI BiosHandleMasterPicIRQ(LPWORD Stack) +{ + BYTE IrqNumber; + + IOWriteB(PIC_MASTER_CMD, PIC_OCW3_READ_ISR /* == 0x0B */); + IrqNumber = IOReadB(PIC_MASTER_CMD); + + DPRINT("Master - IrqNumber = 0x%x\n", IrqNumber); + + PicIRQComplete(Stack); +} + +static VOID WINAPI BiosHandleSlavePicIRQ(LPWORD Stack) +{ + BYTE IrqNumber; + + IOWriteB(PIC_SLAVE_CMD, PIC_OCW3_READ_ISR /* == 0x0B */); + IrqNumber = IOReadB(PIC_SLAVE_CMD); + + DPRINT("Slave - IrqNumber = 0x%x\n", IrqNumber); + + PicIRQComplete(Stack); +} + +// Timer IRQ 0 +static VOID WINAPI BiosTimerIrq(LPWORD Stack) +{ + /* + * Perform the system timer interrupt. + * + * Do not call directly BiosSystemTimerInterrupt(Stack); + * because some programs may hook only BIOS_SYS_TIMER_INTERRUPT + * for their purpose... + */ + EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT); + PicIRQComplete(Stack); +} + + +static VOID BiosHwSetup(VOID) +{ + /* Initialize the master and the slave PICs (cascade mode) */ + IOWriteB(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4); + IOWriteB(PIC_SLAVE_CMD , PIC_ICW1 | PIC_ICW1_ICW4); + + /* + * Set the interrupt vector offsets for each PIC + * (base IRQs: 0x08-0x0F for IRQ 0-7, 0x70-0x77 for IRQ 8-15) + */ + IOWriteB(PIC_MASTER_DATA, BIOS_PIC_MASTER_INT); + IOWriteB(PIC_SLAVE_DATA , BIOS_PIC_SLAVE_INT ); + + /* Tell the master PIC that there is a slave PIC at IRQ 2 */ + IOWriteB(PIC_MASTER_DATA, 1 << 2); + /* Tell the slave PIC its cascade identity */ + IOWriteB(PIC_SLAVE_DATA , 2); + + /* Make sure both PICs are in 8086 mode */ + IOWriteB(PIC_MASTER_DATA, PIC_ICW4_8086); + IOWriteB(PIC_SLAVE_DATA , PIC_ICW4_8086); + + /* Clear the masks for both PICs */ + // IOWriteB(PIC_MASTER_DATA, 0x00); + // IOWriteB(PIC_SLAVE_DATA , 0x00); + /* Disable all IRQs */ + IOWriteB(PIC_MASTER_DATA, 0xFF); + IOWriteB(PIC_SLAVE_DATA , 0xFF); + + + /* Initialize PIT Counter 0 */ + IOWriteB(PIT_COMMAND_PORT, 0x34); + IOWriteB(PIT_DATA_PORT(0), 0x00); + IOWriteB(PIT_DATA_PORT(0), 0x00); + + /* Initialize PIT Counter 1 */ + IOWriteB(PIT_COMMAND_PORT, 0x74); + IOWriteB(PIT_DATA_PORT(1), 0x00); + IOWriteB(PIT_DATA_PORT(1), 0x00); + + /* Initialize PIT Counter 2 */ + IOWriteB(PIT_COMMAND_PORT, 0xB4); + IOWriteB(PIT_DATA_PORT(2), 0x00); + IOWriteB(PIT_DATA_PORT(2), 0x00); + + EnableHwIRQ(0, BiosTimerIrq); +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * The BIOS POST (Power On-Self Test) + */ +BOOLEAN Bios32Initialize(IN HANDLE ConsoleInput, + IN HANDLE ConsoleOutput) +{ + UCHAR Low, High; + UCHAR i; + + /* Initialize the BDA */ + Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0); + Bda->EquipmentList = BIOS_EQUIPMENT_LIST; + + /* + * Retrieve the conventional memory size + * in kB from CMOS, typically 640 kB. + */ + IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_LOW); + Low = IOReadB(CMOS_DATA_PORT); + IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_HIGH); + High = IOReadB(CMOS_DATA_PORT); + Bda->MemorySize = MAKEWORD(Low, High); + + /* Initialize the 32-bit Interrupt system */ + InitializeInt32(BIOS_SEGMENT); + + /* Register the BIOS 32-bit Interrupts */ + + /* Initialize the exception vector interrupts to a default Exception handler */ + for (i = 0; i < 8; i++) + RegisterInt32(i, BiosException); + + /* Initialize HW vector interrupts to a default HW handler */ + for (i = BIOS_PIC_MASTER_INT; i < BIOS_PIC_MASTER_INT + 8; i++) + RegisterInt32(i, BiosHandleMasterPicIRQ); + for (i = BIOS_PIC_SLAVE_INT ; i < BIOS_PIC_SLAVE_INT + 8; i++) + RegisterInt32(i, BiosHandleSlavePicIRQ); + + /* Initialize software vector handlers */ + RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService ); + RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize ); + RegisterInt32(BIOS_MISC_INTERRUPT , BiosMiscService ); + RegisterInt32(BIOS_TIME_INTERRUPT , BiosTimeService ); + RegisterInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt); + + /* Some interrupts are in fact addresses to tables */ + ((PDWORD)BaseAddress)[0x1E] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x41] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x46] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x48] = (DWORD)NULL; + ((PDWORD)BaseAddress)[0x49] = (DWORD)NULL; + + /* Initialize platform hardware (PIC/PIT chips, ...) */ + BiosHwSetup(); + + /* Initialize the Keyboard BIOS */ + if (!KbdBios32Initialize(ConsoleInput)) return FALSE; + + /* Set the console input mode */ + SetConsoleMode(ConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT); + + /* Initialize the Video BIOS */ + if (!VidBios32Initialize(ConsoleOutput)) return FALSE; + + return TRUE; +} + +VOID Bios32Cleanup(VOID) +{ + VidBios32Cleanup(); + KbdBios32Cleanup(); +} + +/* EOF */ diff --git a/subsystems/ntvdm/bios/bios32/bios32.h b/subsystems/ntvdm/bios/bios32/bios32.h new file mode 100644 index 00000000000..ba1f69bba12 --- /dev/null +++ b/subsystems/ntvdm/bios/bios32/bios32.h @@ -0,0 +1,131 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bios32.h + * PURPOSE: VDM 32-bit BIOS + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _BIOS32_H_ +#define _BIOS32_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" +#include "kbdbios32.h" +#include "vidbios32.h" + +/* DEFINES ********************************************************************/ + +#define BIOS_PIC_MASTER_INT 0x08 +#define BIOS_PIC_SLAVE_INT 0x70 + +#define BIOS_EQUIPMENT_INTERRUPT 0x11 +#define BIOS_MEMORY_SIZE 0x12 +#define BIOS_MISC_INTERRUPT 0x15 +#define BIOS_TIME_INTERRUPT 0x1A +#define BIOS_SYS_TIMER_INTERRUPT 0x1C + +#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now + + +#define ROM_AREA_START 0xE0000 +#define ROM_AREA_END 0xFFFFF + +#define BDA_SEGMENT 0x40 +#define BIOS_SEGMENT 0xF000 + +/* + * BIOS Data Area at 0040:XXXX + * + * See: http://webpages.charter.net/danrollins/techhelp/0093.HTM + * and: http://www.bioscentral.com/misc/bda.htm + * for more information. + */ +#pragma pack(push, 1) +typedef struct +{ + WORD SerialPorts[4]; // 0x00 + WORD ParallelPorts[3]; // 0x08 + WORD EbdaSegment; // 0x0e - ParallelPort in PC/XT + WORD EquipmentList; // 0x10 + BYTE Reserved0; // 0x12 - Errors in PCjr infrared keyboard link + WORD MemorySize; // 0x13 + WORD Reserved1; // 0x15 - Scratch pad for manufacturing error tests + WORD KeybdShiftFlags; // 0x17 + BYTE AlternateKeypad; // 0x19 + WORD KeybdBufferHead; // 0x1a + WORD KeybdBufferTail; // 0x1c + WORD KeybdBuffer[BIOS_KBD_BUFFER_SIZE]; // 0x1e + BYTE DriveRecalibrate; // 0x3e + BYTE DriveMotorStatus; // 0x3f + BYTE MotorShutdownCounter; // 0x40 + BYTE LastDisketteOperation; // 0x41 + BYTE Reserved2[7]; // 0x42 + BYTE VideoMode; // 0x49 + WORD ScreenColumns; // 0x4a + WORD VideoPageSize; // 0x4c + WORD VideoPageOffset; // 0x4e + WORD CursorPosition[BIOS_MAX_PAGES]; // 0x50 + BYTE CursorEndLine; // 0x60 + BYTE CursorStartLine; // 0x61 + BYTE VideoPage; // 0x62 + WORD CrtBasePort; // 0x63 + BYTE CrtModeControl; // 0x65 + BYTE CrtColorPaletteMask; // 0x66 + BYTE CassetteData[5]; // 0x67 + DWORD TickCounter; // 0x6c + BYTE MidnightPassed; // 0x70 + BYTE BreakFlag; // 0x71 + WORD SoftReset; // 0x72 + BYTE LastDiskOperation; // 0x74 + BYTE NumDisks; // 0x75 + BYTE DriveControlByte; // 0x76 + BYTE DiskPortOffset; // 0x77 + BYTE LptTimeOut[4]; // 0x78 + BYTE ComTimeOut[4]; // 0x7c + WORD KeybdBufferStart; // 0x80 + WORD KeybdBufferEnd; // 0x82 + BYTE ScreenRows; // 0x84 + WORD CharacterHeight; // 0x85 + BYTE EGAFlags[2]; // 0x87 + BYTE VGAFlags[2]; // 0x89 + DWORD Reserved3; // 0x8b + BYTE Reserved4; // 0x8f + BYTE Reserved5[2]; // 0x90 + BYTE Reserved6[2]; // 0x92 + BYTE Reserved7[2]; // 0x94 + WORD Reserved8; // 0x96 + DWORD Reserved9; // 0x98 + DWORD Reserved10; // 0x9c + DWORD Reserved11[2]; // 0xa0 + DWORD EGAPtr; // 0xa8 + BYTE Reserved12[68]; // 0xac + BYTE Reserved13[16]; // 0xf0 + + DWORD Reserved14; // 0x100 + BYTE Reserved15[12]; // 0x104 + BYTE Reserved16[17]; // 0x110 + BYTE Reserved17[15]; // 0x121 + BYTE Reserved18[3]; // 0x130 +} BIOS_DATA_AREA, *PBIOS_DATA_AREA; +#pragma pack(pop) + +C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x133); + +/* FUNCTIONS ******************************************************************/ + +extern PBIOS_DATA_AREA Bda; + +/**HACK!!**/typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);/**HACK!!**/ + +VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func); +VOID PicIRQComplete(LPWORD Stack); + +BOOLEAN Bios32Initialize(IN HANDLE ConsoleInput, + IN HANDLE ConsoleOutput); +VOID Bios32Cleanup(VOID); + +#endif // _BIOS32_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/bios/kbdbios.c b/subsystems/ntvdm/bios/bios32/kbdbios32.c similarity index 97% rename from subsystems/ntvdm/bios/kbdbios.c rename to subsystems/ntvdm/bios/bios32/kbdbios32.c index e1049b98c83..6444004eaff 100644 --- a/subsystems/ntvdm/bios/kbdbios.c +++ b/subsystems/ntvdm/bios/bios32/kbdbios32.c @@ -1,8 +1,8 @@ /* * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine - * FILE: kbdbios.c - * PURPOSE: VDM Keyboard BIOS + * FILE: kbdbios32.c + * PURPOSE: VDM Keyboard 32-bit BIOS * PROGRAMMERS: Aleksandar Andrejevic */ @@ -11,8 +11,8 @@ #define NDEBUG #include "emulator.h" -// #include "kbdbios.h" -#include "bios.h" +// #include "kbdbios32.h" +#include "bios32.h" #include "io.h" #include "hardware/ps2.h" @@ -261,7 +261,7 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack) /* PUBLIC FUNCTIONS ***********************************************************/ -BOOLEAN KbdBiosInitialize(HANDLE ConsoleInput) +BOOLEAN KbdBios32Initialize(HANDLE ConsoleInput) { /* Initialize the BDA */ Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer); @@ -283,7 +283,7 @@ BOOLEAN KbdBiosInitialize(HANDLE ConsoleInput) return TRUE; } -VOID KbdBiosCleanup(VOID) +VOID KbdBios32Cleanup(VOID) { } diff --git a/subsystems/ntvdm/bios/kbdbios.h b/subsystems/ntvdm/bios/bios32/kbdbios32.h similarity index 85% rename from subsystems/ntvdm/bios/kbdbios.h rename to subsystems/ntvdm/bios/bios32/kbdbios32.h index efa53c899c0..46590d84635 100644 --- a/subsystems/ntvdm/bios/kbdbios.h +++ b/subsystems/ntvdm/bios/bios32/kbdbios32.h @@ -1,13 +1,13 @@ /* * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine - * FILE: kbdbios.h - * PURPOSE: VDM Keyboard BIOS + * FILE: kbdbios32.h + * PURPOSE: VDM Keyboard 32-bit BIOS * PROGRAMMERS: Aleksandar Andrejevic */ -#ifndef _KBDBIOS_H_ -#define _KBDBIOS_H_ +#ifndef _KBDBIOS32_H_ +#define _KBDBIOS32_H_ /* INCLUDES *******************************************************************/ @@ -41,9 +41,9 @@ WORD BiosPeekCharacter(VOID); WORD BiosGetCharacter(VOID); -BOOLEAN KbdBiosInitialize(HANDLE ConsoleInput); -VOID KbdBiosCleanup(VOID); +BOOLEAN KbdBios32Initialize(HANDLE ConsoleInput); +VOID KbdBios32Cleanup(VOID); -#endif // _KBDBIOS_H_ +#endif // _KBDBIOS32_H_ /* EOF */ diff --git a/subsystems/ntvdm/bios/vidbios.c b/subsystems/ntvdm/bios/bios32/vidbios32.c similarity index 99% rename from subsystems/ntvdm/bios/vidbios.c rename to subsystems/ntvdm/bios/bios32/vidbios32.c index 0e2bb623698..4734f10497b 100644 --- a/subsystems/ntvdm/bios/vidbios.c +++ b/subsystems/ntvdm/bios/bios32/vidbios32.c @@ -1,8 +1,8 @@ /* * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine - * FILE: vidbios.c - * PURPOSE: VDM Video BIOS + * FILE: vidbios32.c + * PURPOSE: VDM Video 32-bit BIOS * PROGRAMMERS: Aleksandar Andrejevic */ @@ -11,8 +11,8 @@ #define NDEBUG #include "emulator.h" -// #include "vidbios.h" -#include "bios.h" +// #include "vidbios32.h" +#include "bios32.h" #include "io.h" #include "hardware/vga.h" @@ -1533,7 +1533,7 @@ static VOID WINAPI VidBiosVideoService(LPWORD Stack) /* PUBLIC FUNCTIONS ***********************************************************/ -BOOLEAN VidBiosInitialize(HANDLE ConsoleOutput) +BOOLEAN VidBios32Initialize(HANDLE ConsoleOutput) { /* Some interrupts are in fact addresses to tables */ ((PDWORD)BaseAddress)[0x1D] = (DWORD)NULL; @@ -1567,7 +1567,7 @@ BOOLEAN VidBiosInitialize(HANDLE ConsoleOutput) return TRUE; } -VOID VidBiosCleanup(VOID) +VOID VidBios32Cleanup(VOID) { } diff --git a/subsystems/ntvdm/bios/vidbios.h b/subsystems/ntvdm/bios/bios32/vidbios32.h similarity index 81% rename from subsystems/ntvdm/bios/vidbios.h rename to subsystems/ntvdm/bios/bios32/vidbios32.h index 5ac36036c1a..23fee947557 100644 --- a/subsystems/ntvdm/bios/vidbios.h +++ b/subsystems/ntvdm/bios/bios32/vidbios32.h @@ -1,13 +1,13 @@ /* * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine - * FILE: vidbios.h - * PURPOSE: VDM Video BIOS + * FILE: vidbios32.h + * PURPOSE: VDM Video 32-bit BIOS * PROGRAMMERS: Aleksandar Andrejevic */ -#ifndef _VIDBIOS_H_ -#define _VIDBIOS_H_ +#ifndef _VIDBIOS32_H_ +#define _VIDBIOS32_H_ /* INCLUDES *******************************************************************/ @@ -38,9 +38,9 @@ enum VOID VidBiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page); -BOOLEAN VidBiosInitialize(HANDLE BiosConsoleOutput); -VOID VidBiosCleanup(VOID); +BOOLEAN VidBios32Initialize(HANDLE BiosConsoleOutput); +VOID VidBios32Cleanup(VOID); -#endif // _VIDBIOS_H_ +#endif // _VIDBIOS32_H_ /* EOF */ diff --git a/subsystems/ntvdm/hardware/cmos.c b/subsystems/ntvdm/hardware/cmos.c index 3bf34b530fa..4f86467249b 100644 --- a/subsystems/ntvdm/hardware/cmos.c +++ b/subsystems/ntvdm/hardware/cmos.c @@ -416,7 +416,7 @@ VOID CmosInitialize(VOID) if (hCmosRam != INVALID_HANDLE_VALUE) { - BOOL Success = FALSE; + BOOL Success; /* Attempt to fill the CMOS memory with the RAM file */ SetLastError(0); // For debugging purposes diff --git a/subsystems/ntvdm/ntvdm.c b/subsystems/ntvdm/ntvdm.c index 23a4b45de28..6dfe67a9d81 100644 --- a/subsystems/ntvdm/ntvdm.c +++ b/subsystems/ntvdm/ntvdm.c @@ -22,10 +22,10 @@ #include "resource.h" /* - * Activate this line if you want to be able to test NTVDM with: + * Activate this line if you want to run NTVDM in standalone mode with: * ntvdm.exe */ -#define TESTING +#define STANDALONE /* VARIABLES ******************************************************************/ @@ -364,15 +364,14 @@ VOID ConsoleCleanup(VOID) INT wmain(INT argc, WCHAR *argv[]) { +#ifndef STANDALONE + wprintf(L"\nReactOS Virtual DOS Machine\n\n" + L"OS integration (BaseVDM) unimplemented\n"); + return 0; +#else + CHAR CommandLine[DOS_CMDLINE_LENGTH]; -#ifndef TESTING - UNREFERENCED_PARAMETER(argc); - UNREFERENCED_PARAMETER(argv); - - /* The DOS command line must be ASCII */ - WideCharToMultiByte(CP_ACP, 0, GetCommandLine(), -1, CommandLine, sizeof(CommandLine), NULL, NULL); -#else if (argc == 2 && argv[1] != NULL) { WideCharToMultiByte(CP_ACP, 0, argv[1], -1, CommandLine, sizeof(CommandLine), NULL, NULL); @@ -383,7 +382,6 @@ INT wmain(INT argc, WCHAR *argv[]) L"Usage: NTVDM \n"); return 0; } -#endif DPRINT1("\n\n\nNTVDM - Starting '%s'...\n\n\n", CommandLine); @@ -402,7 +400,7 @@ INT wmain(INT argc, WCHAR *argv[]) } /* Initialize the system BIOS */ - if (!BiosInitialize(ConsoleInput, ConsoleOutput)) + if (!BiosInitialize(NULL, ConsoleInput, ConsoleOutput)) { wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n"); goto Cleanup; @@ -436,6 +434,8 @@ Cleanup: DPRINT1("\n\n\nNTVDM - Exiting...\n\n\n"); return 0; + +#endif } /* EOF */