- 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
This commit is contained in:
Hermès Bélusca-Maïto 2014-02-17 22:20:03 +00:00
parent c64a03a80f
commit 574f922049
11 changed files with 572 additions and 414 deletions

View file

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

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
* 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 */

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
* 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_

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
*/
/* 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 */

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
*/
#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 */

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
*/
@ -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)
{
}

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
*/
#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 */

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
*/
@ -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)
{
}

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
*/
#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 */

View file

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

View file

@ -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 <program>
*/
#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 <executable>\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 */