- Move all the hardware initialization to EmulatorInitialize (since emulator.c can be viewed as support functions for emulating a PC motherboard) --> PS2 and VGA go there.
- Break bios.c into bios.c and kbdbios.c (the keyboard bios module) (according to the IBM documentation as well as other emulator sources or SeaBIOS or...).
- Move Exception handling from int32.c to emulator.c, because it's something tight to the emulator, not to the interrupt system by itself (yet it happens that INT 00h to 07h are commonly set to some exception handlers). In the bios.c, initialize those vectors with the default exception handler.
- Handling IRQs is done fully in bios.c now: introduce PicSetIRQMask and EnableHwIRQ helper functions (adapted from their equivalents from SeaBIOS) that allows the bios to set (and activate in the PIC) a given IRQ with its corresponding handler. Also introduce PicIRQComplete that serves as a PIC IRQ completer (i.e. sends the EOI to the right PIC(s)).
- Continuing on that, at the moment I set dumb default PIC IRQ handlers for IRQ 08h - 0Fh and IRQ 70h - 77h).
- By default I disable all the IRQs; there are then set on-demand with EnableHwIRQ.
- Rework the POST (aka. BiosInitialize function):
  * the memory size is now get from the CMOS (as well as the extended memory size via INT 12h, AH=88h),
  * then we initialize the interrupts,
  * then platform hardware (ie. the chips) are initialized,
  * and finally the keyboard and video bioses.
- As said before, move memory sizes into the CMOS.
- Simplify video bios initialization.

svn path=/branches/ntvdm/; revision=61796
This commit is contained in:
Hermès Bélusca-Maïto 2014-01-25 00:21:51 +00:00
parent 3c273ca1a9
commit 6ddfa7d2b8
13 changed files with 643 additions and 459 deletions

View file

@ -7,6 +7,7 @@ spec2def(ntvdm.exe ntvdm.spec)
list(APPEND SOURCE
bios/bios.c
bios/kbdbios.c
bios/vidbios.c
hardware/cmos.c
hardware/pic.c

View file

@ -14,74 +14,23 @@
#include "bios.h"
#include "io.h"
#include "hardware/cmos.h"
#include "hardware/pic.h"
#include "hardware/ps2.h"
#include "hardware/timer.h"
#include "int32.h"
#include "registers.h"
/* PRIVATE VARIABLES **********************************************************/
PBIOS_DATA_AREA Bda;
static BYTE BiosKeyboardMap[256];
/* PRIVATE FUNCTIONS **********************************************************/
static BOOLEAN BiosKbdBufferPush(WORD Data)
static VOID WINAPI BiosException(LPWORD Stack)
{
/* Get the location of the element after the tail */
WORD NextElement = Bda->KeybdBufferTail + sizeof(WORD);
/* Wrap it around if it's at or beyond the end */
if (NextElement >= Bda->KeybdBufferEnd) NextElement = Bda->KeybdBufferStart;
/* If it's full, fail */
if (NextElement == Bda->KeybdBufferHead) return FALSE;
/* Put the value in the queue */
*((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferTail)) = Data;
Bda->KeybdBufferTail += sizeof(WORD);
/* Check if we are at, or have passed, the end of the buffer */
if (Bda->KeybdBufferTail >= Bda->KeybdBufferEnd)
{
/* Return it to the beginning */
Bda->KeybdBufferTail = Bda->KeybdBufferStart;
}
/* Return success */
return TRUE;
}
static BOOLEAN BiosKbdBufferTop(LPWORD Data)
{
/* If it's empty, fail */
if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
/* Otherwise, get the value and return success */
*Data = *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferHead));
return TRUE;
}
static BOOLEAN BiosKbdBufferPop(VOID)
{
/* If it's empty, fail */
if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
/* Remove the value from the queue */
Bda->KeybdBufferHead += sizeof(WORD);
/* Check if we are at, or have passed, the end of the buffer */
if (Bda->KeybdBufferHead >= Bda->KeybdBufferEnd)
{
/* Return it to the beginning */
Bda->KeybdBufferHead = Bda->KeybdBufferStart;
}
/* Return success */
return TRUE;
/* 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)
@ -135,8 +84,17 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
/* Get Extended Memory Size */
case 0x88:
{
/* Return the number of KB of RAM after 1 MB */
setAX((MAX_ADDRESS - 0x100000) / 1024);
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;
@ -152,88 +110,6 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
}
}
static VOID WINAPI BiosKeyboardService(LPWORD Stack)
{
switch (getAH())
{
/* Wait for keystroke and read */
case 0x00:
/* Wait for extended keystroke and read */
case 0x10: // FIXME: Temporarily do the same as INT 16h, 00h
{
/* Read the character (and wait if necessary) */
setAX(BiosGetCharacter());
break;
}
/* Get keystroke status */
case 0x01:
/* Get extended keystroke status */
case 0x11: // FIXME: Temporarily do the same as INT 16h, 01h
{
WORD Data = BiosPeekCharacter();
if (Data != 0xFFFF)
{
/* There is a character, clear ZF and return it */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
setAX(Data);
}
else
{
/* No character, set ZF */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
}
break;
}
/* Get shift status */
case 0x02:
{
/* Return the lower byte of the keyboard shift status word */
setAL(LOBYTE(Bda->KeybdShiftFlags));
break;
}
/* Reserved */
case 0x04:
{
DPRINT1("BIOS Function INT 16h, AH = 0x04 is RESERVED\n");
break;
}
/* Push keystroke */
case 0x05:
{
/* Return 0 if success, 1 if failure */
setAL(BiosKbdBufferPush(getCX()) == FALSE);
break;
}
/* Get extended shift status */
case 0x12:
{
/*
* Be careful! The returned word is similar to Bda->KeybdShiftFlags
* but the high byte is organized differently:
* the bytes 2 and 3 of the high byte are not the same...
*/
WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF);
/* Return the extended keyboard shift status word */
setAX(KeybdShiftFlags);
break;
}
default:
{
DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n",
getAH());
}
}
}
static VOID WINAPI BiosTimeService(LPWORD Stack)
{
switch (getAH())
@ -278,206 +154,201 @@ static VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
Bda->TickCounter++;
}
/* PUBLIC FUNCTIONS ***********************************************************/
WORD BiosPeekCharacter(VOID)
// From SeaBIOS
static VOID PicSetIRQMask(USHORT off, USHORT on)
{
WORD CharacterData = 0;
/* Get the key from the queue, but don't remove it */
if (BiosKbdBufferTop(&CharacterData)) return CharacterData;
else return 0xFFFF;
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);
}
WORD BiosGetCharacter(VOID)
// From SeaBIOS
VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func)
{
WORD CharacterData = 0;
UCHAR vector;
/* Check if there is a key available */
if (BiosKbdBufferTop(&CharacterData))
{
/* A key was available, remove it from the queue */
BiosKbdBufferPop();
}
PicSetIRQMask(1 << hwirq, 0);
if (hwirq < 8)
vector = BIOS_PIC_MASTER_INT + hwirq;
else
{
/* No key available. Set the handler CF to repeat the BOP */
setCF(1);
// CharacterData = 0xFFFF;
}
vector = BIOS_PIC_SLAVE_INT + hwirq - 8;
return CharacterData;
RegisterInt32(vector, func);
}
BOOLEAN BiosInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
VOID PicIRQComplete(LPWORD Stack)
{
/* Initialize the BDA */
Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0);
Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
/*
* Conventional memory size is 640 kB,
* see: http://webpages.charter.net/danrollins/techhelp/0184.HTM
* and see Ralf Brown: http://www.ctyme.com/intr/rb-0598.htm
* for more information.
*/
Bda->MemorySize = 0x0280;
Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
Bda->KeybdBufferHead = Bda->KeybdBufferTail = 0;
/* Initialize the 32-bit Interrupt system */
InitializeInt32(BIOS_SEGMENT);
/* Register the BIOS 32-bit Interrupts */
RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService );
RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize );
RegisterInt32(BIOS_MISC_INTERRUPT , BiosMiscService );
RegisterInt32(BIOS_KBD_INTERRUPT , BiosKeyboardService );
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;
/* Initialize the Video BIOS */
if (!VidBiosInitialize(ConsoleOutput)) return FALSE;
/* Set the console input mode */
SetConsoleMode(ConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
/* Initialize PS2 */
PS2Initialize(ConsoleInput);
/* Get the interrupt number */
BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
/*
* The POST (Power On-Self Test)
* If this was a PIC IRQ, send an End-of-Interrupt to the PIC.
*/
/* Initialize the master and the slave PICs */
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);
DPRINT1("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);
DPRINT1("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 offsets */
/*
* 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 there is a slave at IRQ 2 */
/* 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 /* | PIC_ICW4_AEOI */);
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);
// IOWriteB(PIC_MASTER_DATA, 0x00);
// IOWriteB(PIC_SLAVE_DATA , 0x00);
/* Disable all IRQs */
IOWriteB(PIC_MASTER_DATA, 0xFF);
IOWriteB(PIC_SLAVE_DATA , 0xFF);
/* Initialize the PIT */
IOWriteB(PIT_COMMAND_PORT, 0x34);
IOWriteB(PIT_DATA_PORT(0), 0x00);
IOWriteB(PIT_DATA_PORT(0), 0x00);
EnableHwIRQ(0, BiosTimerIrq);
}
/* PUBLIC FUNCTIONS ***********************************************************/
/*
* The BIOS POST (Power On-Self Test)
*/
BOOLEAN BiosInitialize(HANDLE ConsoleInput, 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;
}
VOID BiosCleanup(VOID)
{
PS2Cleanup();
VidBiosCleanup();
}
VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack)
{
switch (IrqNumber)
{
/* PIT IRQ */
case 0:
{
/* Perform the system timer interrupt */
EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT);
break;
}
/* Keyboard IRQ */
case 1:
{
BYTE ScanCode, VirtualKey;
WORD Character;
/* Get the scan code and virtual key code */
ScanCode = IOReadB(PS2_DATA_PORT);
VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
/* Check if this is a key press or release */
if (!(ScanCode & (1 << 7)))
{
/* Key press */
if (VirtualKey == VK_NUMLOCK ||
VirtualKey == VK_CAPITAL ||
VirtualKey == VK_SCROLL ||
VirtualKey == VK_INSERT)
{
/* For toggle keys, toggle the lowest bit in the keyboard map */
BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
}
/* Set the highest bit */
BiosKeyboardMap[VirtualKey] |= (1 << 7);
/* Find out which character this is */
Character = 0;
if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0)
{
/* Not ASCII */
Character = 0;
}
/* Push it onto the BIOS keyboard queue */
BiosKbdBufferPush(MAKEWORD(Character, ScanCode));
}
else
{
/* Key release, unset the highest bit */
BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
}
/* Clear the keyboard flags */
Bda->KeybdShiftFlags = 0;
/* Set the appropriate flags based on the state */
if (BiosKeyboardMap[VK_RSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RSHIFT;
if (BiosKeyboardMap[VK_LSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
if (BiosKeyboardMap[VK_CONTROL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CTRL;
if (BiosKeyboardMap[VK_MENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_ALT;
if (BiosKeyboardMap[VK_SCROLL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL_ON;
if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK_ON;
if (BiosKeyboardMap[VK_CAPITAL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK_ON;
if (BiosKeyboardMap[VK_INSERT] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT_ON;
if (BiosKeyboardMap[VK_RMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RALT;
if (BiosKeyboardMap[VK_LMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LALT;
if (BiosKeyboardMap[VK_SNAPSHOT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SYSRQ;
if (BiosKeyboardMap[VK_PAUSE] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_PAUSE;
if (BiosKeyboardMap[VK_SCROLL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL;
if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK;
if (BiosKeyboardMap[VK_CAPITAL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK;
if (BiosKeyboardMap[VK_INSERT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT;
break;
}
}
/* Send End-of-Interrupt to the PIC */
if (IrqNumber >= 8) IOWriteB(PIC_SLAVE_CMD, PIC_OCW2_EOI);
IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI);
KbdBiosCleanup();
}
/* EOF */

View file

@ -12,6 +12,7 @@
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
#include "kbdbios.h"
#include "vidbios.h"
/* DEFINES ********************************************************************/
@ -28,29 +29,10 @@
#define BIOS_EQUIPMENT_INTERRUPT 0x11
#define BIOS_MEMORY_SIZE 0x12
#define BIOS_MISC_INTERRUPT 0x15
#define BIOS_KBD_INTERRUPT 0x16
#define BIOS_TIME_INTERRUPT 0x1A
#define BIOS_SYS_TIMER_INTERRUPT 0x1C
#define BIOS_KBD_BUFFER_SIZE 16
#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now
#define BDA_KBDFLAG_RSHIFT (1 << 0)
#define BDA_KBDFLAG_LSHIFT (1 << 1)
#define BDA_KBDFLAG_CTRL (1 << 2)
#define BDA_KBDFLAG_ALT (1 << 3)
#define BDA_KBDFLAG_SCROLL_ON (1 << 4)
#define BDA_KBDFLAG_NUMLOCK_ON (1 << 5)
#define BDA_KBDFLAG_CAPSLOCK_ON (1 << 6)
#define BDA_KBDFLAG_INSERT_ON (1 << 7)
#define BDA_KBDFLAG_RALT (1 << 8)
#define BDA_KBDFLAG_LALT (1 << 9)
#define BDA_KBDFLAG_SYSRQ (1 << 10)
#define BDA_KBDFLAG_PAUSE (1 << 11)
#define BDA_KBDFLAG_SCROLL (1 << 12)
#define BDA_KBDFLAG_NUMLOCK (1 << 13)
#define BDA_KBDFLAG_CAPSLOCK (1 << 14)
#define BDA_KBDFLAG_INSERT (1 << 15)
#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now
/*
* BIOS Data Area at 0040:XXXX
@ -134,12 +116,13 @@ C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x133);
extern PBIOS_DATA_AREA Bda;
WORD BiosPeekCharacter(VOID);
WORD BiosGetCharacter(VOID);
/**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);
VOID BiosCleanup(VOID);
VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack);
#endif // _BIOS_H_

View file

@ -0,0 +1,290 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: kbdbios.c
* PURPOSE: VDM Keyboard BIOS
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
// #include "kbdbios.h"
#include "bios.h"
#include "io.h"
#include "hardware/ps2.h"
#include "int32.h"
/* PRIVATE VARIABLES **********************************************************/
static BYTE BiosKeyboardMap[256];
/* PRIVATE FUNCTIONS **********************************************************/
static BOOLEAN BiosKbdBufferPush(WORD Data)
{
/* Get the location of the element after the tail */
WORD NextElement = Bda->KeybdBufferTail + sizeof(WORD);
/* Wrap it around if it's at or beyond the end */
if (NextElement >= Bda->KeybdBufferEnd) NextElement = Bda->KeybdBufferStart;
/* If it's full, fail */
if (NextElement == Bda->KeybdBufferHead) return FALSE;
/* Put the value in the queue */
*((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferTail)) = Data;
Bda->KeybdBufferTail += sizeof(WORD);
/* Check if we are at, or have passed, the end of the buffer */
if (Bda->KeybdBufferTail >= Bda->KeybdBufferEnd)
{
/* Return it to the beginning */
Bda->KeybdBufferTail = Bda->KeybdBufferStart;
}
/* Return success */
return TRUE;
}
static BOOLEAN BiosKbdBufferTop(LPWORD Data)
{
/* If it's empty, fail */
if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
/* Otherwise, get the value and return success */
*Data = *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferHead));
return TRUE;
}
static BOOLEAN BiosKbdBufferPop(VOID)
{
/* If it's empty, fail */
if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
/* Remove the value from the queue */
Bda->KeybdBufferHead += sizeof(WORD);
/* Check if we are at, or have passed, the end of the buffer */
if (Bda->KeybdBufferHead >= Bda->KeybdBufferEnd)
{
/* Return it to the beginning */
Bda->KeybdBufferHead = Bda->KeybdBufferStart;
}
/* Return success */
return TRUE;
}
WORD BiosPeekCharacter(VOID)
{
WORD CharacterData = 0;
/* Get the key from the queue, but don't remove it */
if (BiosKbdBufferTop(&CharacterData)) return CharacterData;
else return 0xFFFF;
}
WORD BiosGetCharacter(VOID)
{
WORD CharacterData = 0;
/* Check if there is a key available */
if (BiosKbdBufferTop(&CharacterData))
{
/* A key was available, remove it from the queue */
BiosKbdBufferPop();
}
else
{
/* No key available. Set the handler CF to repeat the BOP */
setCF(1);
// CharacterData = 0xFFFF;
}
return CharacterData;
}
static VOID WINAPI BiosKeyboardService(LPWORD Stack)
{
switch (getAH())
{
/* Wait for keystroke and read */
case 0x00:
/* Wait for extended keystroke and read */
case 0x10: // FIXME: Temporarily do the same as INT 16h, 00h
{
/* Read the character (and wait if necessary) */
setAX(BiosGetCharacter());
break;
}
/* Get keystroke status */
case 0x01:
/* Get extended keystroke status */
case 0x11: // FIXME: Temporarily do the same as INT 16h, 01h
{
WORD Data = BiosPeekCharacter();
if (Data != 0xFFFF)
{
/* There is a character, clear ZF and return it */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
setAX(Data);
}
else
{
/* No character, set ZF */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
}
break;
}
/* Get shift status */
case 0x02:
{
/* Return the lower byte of the keyboard shift status word */
setAL(LOBYTE(Bda->KeybdShiftFlags));
break;
}
/* Reserved */
case 0x04:
{
DPRINT1("BIOS Function INT 16h, AH = 0x04 is RESERVED\n");
break;
}
/* Push keystroke */
case 0x05:
{
/* Return 0 if success, 1 if failure */
setAL(BiosKbdBufferPush(getCX()) == FALSE);
break;
}
/* Get extended shift status */
case 0x12:
{
/*
* Be careful! The returned word is similar to Bda->KeybdShiftFlags
* but the high byte is organized differently:
* the bytes 2 and 3 of the high byte are not the same...
*/
WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF);
/* Return the extended keyboard shift status word */
setAX(KeybdShiftFlags);
break;
}
default:
{
DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n",
getAH());
}
}
}
// Keyboard IRQ 1
static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
{
BYTE ScanCode, VirtualKey;
WORD Character;
/* Get the scan code and virtual key code */
ScanCode = IOReadB(PS2_DATA_PORT);
VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
/* Check if this is a key press or release */
if (!(ScanCode & (1 << 7)))
{
/* Key press */
if (VirtualKey == VK_NUMLOCK ||
VirtualKey == VK_CAPITAL ||
VirtualKey == VK_SCROLL ||
VirtualKey == VK_INSERT)
{
/* For toggle keys, toggle the lowest bit in the keyboard map */
BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
}
/* Set the highest bit */
BiosKeyboardMap[VirtualKey] |= (1 << 7);
/* Find out which character this is */
Character = 0;
if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0)
{
/* Not ASCII */
Character = 0;
}
/* Push it onto the BIOS keyboard queue */
BiosKbdBufferPush(MAKEWORD(Character, ScanCode));
}
else
{
/* Key release, unset the highest bit */
BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
}
/* Clear the keyboard flags */
Bda->KeybdShiftFlags = 0;
/* Set the appropriate flags based on the state */
if (BiosKeyboardMap[VK_RSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RSHIFT;
if (BiosKeyboardMap[VK_LSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
if (BiosKeyboardMap[VK_CONTROL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CTRL;
if (BiosKeyboardMap[VK_MENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_ALT;
if (BiosKeyboardMap[VK_SCROLL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL_ON;
if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK_ON;
if (BiosKeyboardMap[VK_CAPITAL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK_ON;
if (BiosKeyboardMap[VK_INSERT] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT_ON;
if (BiosKeyboardMap[VK_RMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RALT;
if (BiosKeyboardMap[VK_LMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LALT;
if (BiosKeyboardMap[VK_SNAPSHOT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SYSRQ;
if (BiosKeyboardMap[VK_PAUSE] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_PAUSE;
if (BiosKeyboardMap[VK_SCROLL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL;
if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK;
if (BiosKeyboardMap[VK_CAPITAL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK;
if (BiosKeyboardMap[VK_INSERT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT;
PicIRQComplete(Stack);
}
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN KbdBiosInitialize(HANDLE ConsoleInput)
{
/* Initialize the BDA */
Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
Bda->KeybdBufferHead = Bda->KeybdBufferTail = 0;
/* Register the BIOS 32-bit Interrupts */
/* Initialize software vector handlers */
RegisterInt32(BIOS_KBD_INTERRUPT, BiosKeyboardService);
/* Set up the HW vector interrupts */
EnableHwIRQ(1, BiosKeyboardIrq);
// EnableHwIRQ(12, BiosMouseIrq);
/* Set the console input mode */
// SetConsoleMode(ConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
return TRUE;
}
VOID KbdBiosCleanup(VOID)
{
}
/* EOF */

View file

@ -0,0 +1,49 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: kbdbios.h
* PURPOSE: VDM Keyboard BIOS
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
#ifndef _KBDBIOS_H_
#define _KBDBIOS_H_
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
/* DEFINES ********************************************************************/
#define BIOS_KBD_INTERRUPT 0x16
#define BIOS_KBD_BUFFER_SIZE 16
#define BDA_KBDFLAG_RSHIFT (1 << 0)
#define BDA_KBDFLAG_LSHIFT (1 << 1)
#define BDA_KBDFLAG_CTRL (1 << 2)
#define BDA_KBDFLAG_ALT (1 << 3)
#define BDA_KBDFLAG_SCROLL_ON (1 << 4)
#define BDA_KBDFLAG_NUMLOCK_ON (1 << 5)
#define BDA_KBDFLAG_CAPSLOCK_ON (1 << 6)
#define BDA_KBDFLAG_INSERT_ON (1 << 7)
#define BDA_KBDFLAG_RALT (1 << 8)
#define BDA_KBDFLAG_LALT (1 << 9)
#define BDA_KBDFLAG_SYSRQ (1 << 10)
#define BDA_KBDFLAG_PAUSE (1 << 11)
#define BDA_KBDFLAG_SCROLL (1 << 12)
#define BDA_KBDFLAG_NUMLOCK (1 << 13)
#define BDA_KBDFLAG_CAPSLOCK (1 << 14)
#define BDA_KBDFLAG_INSERT (1 << 15)
/* FUNCTIONS ******************************************************************/
WORD BiosPeekCharacter(VOID);
WORD BiosGetCharacter(VOID);
BOOLEAN KbdBiosInitialize(HANDLE ConsoleInput);
VOID KbdBiosCleanup(VOID);
#endif // _KBDBIOS_H_
/* EOF */

View file

@ -18,7 +18,6 @@
#include "hardware/vga.h"
#include "int32.h"
#include "registers.h"
/* MACROS *********************************************************************/
@ -32,8 +31,6 @@
/* PRIVATE VARIABLES **********************************************************/
static HANDLE VidBiosConsoleOutput = INVALID_HANDLE_VALUE;
/*
* VGA Register Configurations for BIOS Video Modes
* The configurations come from DOSBox.
@ -1537,8 +1534,6 @@ static VOID WINAPI VidBiosVideoService(LPWORD Stack)
BOOLEAN VidBiosInitialize(HANDLE ConsoleOutput)
{
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
/* Some interrupts are in fact addresses to tables */
((PDWORD)BaseAddress)[0x1D] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x1F] = (DWORD)NULL;
@ -1546,25 +1541,24 @@ BOOLEAN VidBiosInitialize(HANDLE ConsoleOutput)
((PDWORD)BaseAddress)[0x43] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x44] = (DWORD)NULL;
/* Save the default BIOS console output handle for cleanup */
if (ConsoleOutput == INVALID_HANDLE_VALUE) return FALSE;
VidBiosConsoleOutput = ConsoleOutput;
/* Initialize VGA */
if (!VgaInitialize(ConsoleOutput)) return FALSE;
/* Set the default video mode */
VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
GetConsoleScreenBufferInfo(ConsoleOutput, &ConsoleInfo);
/* Set some screen properties if the console output handle is valid */
if (ConsoleOutput != INVALID_HANDLE_VALUE)
{
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
/* Copy console data into VGA memory */
VidBiosCopyTextConsoleToVgaMemory(ConsoleOutput, &ConsoleInfo.dwSize);
GetConsoleScreenBufferInfo(ConsoleOutput, &ConsoleInfo);
/* Update the cursor position for the current page */
VidBiosSetCursorPosition(ConsoleInfo.dwCursorPosition.Y,
ConsoleInfo.dwCursorPosition.X,
Bda->VideoPage);
/* Copy console data into VGA memory */
VidBiosCopyTextConsoleToVgaMemory(ConsoleOutput, &ConsoleInfo.dwSize);
/* Update the cursor position for the current page */
VidBiosSetCursorPosition(ConsoleInfo.dwCursorPosition.Y,
ConsoleInfo.dwCursorPosition.X,
Bda->VideoPage);
}
/* Register the BIOS 32-bit Interrupts */
RegisterInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
@ -1574,8 +1568,6 @@ BOOLEAN VidBiosInitialize(HANDLE ConsoleOutput)
VOID VidBiosCleanup(VOID)
{
/* Restore the old screen buffer */
SetConsoleActiveScreenBuffer(VidBiosConsoleOutput);
}
/* EOF */

View file

@ -15,6 +15,7 @@
#include "bios/bios.h"
#include "hardware/cmos.h"
#include "hardware/pic.h"
#include "hardware/ps2.h"
#include "hardware/speaker.h"
#include "hardware/timer.h"
#include "hardware/vga.h"
@ -22,7 +23,6 @@
#include "bop.h"
#include "vddsup.h"
#include "io.h"
#include "registers.h"
/* PRIVATE VARIABLES **********************************************************/
@ -32,6 +32,18 @@ BOOLEAN VdmRunning = TRUE;
static BOOLEAN A20Line = FALSE;
LPCWSTR ExceptionName[] =
{
L"Division By Zero",
L"Debug",
L"Unexpected Error",
L"Breakpoint",
L"Integer Overflow",
L"Bound Range Exceeded",
L"Invalid Opcode",
L"FPU Not Available"
};
/* BOP Identifiers */
#define BOP_DEBUGGER 0x56 // Break into the debugger from a 16-bit app
@ -115,7 +127,7 @@ VOID WINAPI EmulatorDebugBreak(LPWORD Stack)
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN EmulatorInitialize(VOID)
BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
{
/* Allocate memory for the 16-bit address space */
BaseAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_ADDRESS);
@ -148,6 +160,16 @@ BOOLEAN EmulatorInitialize(VOID)
CmosInitialize();
SpeakerInitialize();
/* Initialize the PS2 port */
PS2Initialize(ConsoleInput);
/* Set the console input mode */
// SetConsoleMode(ConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
/* Initialize the VGA */
// if (!VgaInitialize(ConsoleOutput)) return FALSE;
VgaInitialize(ConsoleOutput);
/* Register the DebugBreak BOP */
RegisterBop(BOP_DEBUGGER, EmulatorDebugBreak);
@ -159,6 +181,9 @@ BOOLEAN EmulatorInitialize(VOID)
VOID EmulatorCleanup(VOID)
{
// VgaCleanup();
PS2Cleanup();
SpeakerCleanup();
CmosCleanup();
// PitCleanup();
@ -170,6 +195,40 @@ VOID EmulatorCleanup(VOID)
if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
}
VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack)
{
WORD CodeSegment, InstructionPointer;
PBYTE Opcode;
ASSERT(ExceptionNumber < 8);
/* Get the CS:IP */
InstructionPointer = Stack[STACK_IP];
CodeSegment = Stack[STACK_CS];
Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer);
/* Display a message to the user */
DisplayMessage(L"Exception: %s occured at %04X:%04X\n"
L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
ExceptionName[ExceptionNumber],
CodeSegment,
InstructionPointer,
Opcode[0],
Opcode[1],
Opcode[2],
Opcode[3],
Opcode[4],
Opcode[5],
Opcode[6],
Opcode[7],
Opcode[8],
Opcode[9]);
/* Stop the VDM */
VdmRunning = FALSE;
return;
}
// FIXME: This function assumes 16-bit mode!!!
VOID EmulatorExecute(WORD Segment, WORD Offset)
{

View file

@ -105,7 +105,9 @@ UCHAR WINAPI EmulatorIntAcknowledge
PFAST486_STATE State
);
BOOLEAN EmulatorInitialize(VOID);
VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack);
BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput);
VOID EmulatorExecute(WORD Segment, WORD Offset);
VOID EmulatorInterrupt(BYTE Number);
VOID EmulatorInterruptSignal(VOID);

View file

@ -12,8 +12,8 @@
#include "emulator.h"
#include "cmos.h"
#include "io.h"
#include "bios/bios.h"
#include "pic.h"
/* PRIVATE VARIABLES **********************************************************/
@ -138,18 +138,6 @@ BYTE CmosReadData(VOID)
return Value;
}
case CMOS_REG_BASE_MEMORY_LOW:
return Bda->MemorySize & 0xFF;
case CMOS_REG_BASE_MEMORY_HIGH:
return Bda->MemorySize >> 8;
case CMOS_REG_EXT_MEMORY_LOW:
return ((MAX_ADDRESS - 0x100000) / 1024) & 0xFF;
case CMOS_REG_EXT_MEMORY_HIGH:
return ((MAX_ADDRESS - 0x100000) / 1024) >> 8;
case CMOS_REG_STATUS_A:
case CMOS_REG_STATUS_B:
case CMOS_REG_STATUS_D:
@ -295,6 +283,26 @@ VOID CmosWriteData(BYTE Value)
// Status registers C and D are read-only
break;
/* Is the following correct? */
case CMOS_REG_EXT_MEMORY_LOW:
case CMOS_REG_ACTUAL_EXT_MEMORY_LOW:
{
/* Sync EMS and UMS */
CmosMemory.Regs[CMOS_REG_EXT_MEMORY_LOW] =
CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_LOW] = Value;
break;
}
/* Is the following correct? */
case CMOS_REG_EXT_MEMORY_HIGH:
case CMOS_REG_ACTUAL_EXT_MEMORY_HIGH:
{
/* Sync EMS and UMS */
CmosMemory.Regs[CMOS_REG_EXT_MEMORY_HIGH] =
CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_HIGH] = Value;
break;
}
default:
{
CmosMemory.Regs[SelectedRegister] = Value;
@ -309,6 +317,7 @@ VOID CmosWriteData(BYTE Value)
BYTE WINAPI CmosReadPort(ULONG Port)
{
ASSERT(Port == CMOS_DATA_PORT);
return CmosReadData();
}
@ -430,6 +439,23 @@ VOID CmosInitialize(VOID)
CmosMemory.Diagnostics = 0x00; // Diagnostics must not find any errors.
CmosMemory.ShutdownStatus = 0x00;
/* Memory settings */
/*
* Conventional memory size is 640 kB,
* see: http://webpages.charter.net/danrollins/techhelp/0184.HTM
* and see Ralf Brown: http://www.ctyme.com/intr/rb-0598.htm
* for more information.
*/
CmosMemory.Regs[CMOS_REG_BASE_MEMORY_LOW ] = LOBYTE(0x0280);
CmosMemory.Regs[CMOS_REG_BASE_MEMORY_HIGH] = HIBYTE(0x0280);
CmosMemory.Regs[CMOS_REG_EXT_MEMORY_LOW] =
CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_LOW] = LOBYTE((MAX_ADDRESS - 0x100000) / 1024);
CmosMemory.Regs[CMOS_REG_EXT_MEMORY_HIGH] =
CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_HIGH] = HIBYTE((MAX_ADDRESS - 0x100000) / 1024);
/* Register the I/O Ports */
RegisterIoPort(CMOS_ADDRESS_PORT, NULL , CmosWritePort);
RegisterIoPort(CMOS_DATA_PORT , CmosReadPort, CmosWritePort);

View file

@ -63,11 +63,13 @@ typedef enum _CMOS_REGISTERS
CMOS_REG_STATUS_D,
CMOS_REG_DIAGNOSTICS,
CMOS_REG_SHUTDOWN_STATUS,
CMOS_REG_BASE_MEMORY_LOW = 0x15,
CMOS_REG_BASE_MEMORY_HIGH = 0x16,
CMOS_REG_EXT_MEMORY_LOW = 0x17,
CMOS_REG_EXT_MEMORY_HIGH = 0x18,
CMOS_REG_MAX = 0x40
CMOS_REG_BASE_MEMORY_LOW = 0x15,
CMOS_REG_BASE_MEMORY_HIGH = 0x16,
CMOS_REG_EXT_MEMORY_LOW = 0x17,
CMOS_REG_EXT_MEMORY_HIGH = 0x18,
CMOS_REG_ACTUAL_EXT_MEMORY_LOW = 0x30,
CMOS_REG_ACTUAL_EXT_MEMORY_HIGH = 0x31,
CMOS_REG_MAX = 0x40
} CMOS_REGISTERS, *PCMOS_REGISTERS;
/*

View file

@ -14,7 +14,6 @@
#include "vga.h"
#include "io.h"
#include "bios/bios.h"
/* PRIVATE VARIABLES **********************************************************/

View file

@ -15,23 +15,9 @@
#include "int32.h"
#include "bop.h"
#include "bios/bios.h"
#include "registers.h"
/* PRIVATE VARIABLES **********************************************************/
LPCWSTR ExceptionName[] =
{
L"Division By Zero",
L"Debug",
L"Unexpected Error",
L"Breakpoint",
L"Integer Overflow",
L"Bound Range Exceeded",
L"Invalid Opcode",
L"FPU Not Available"
};
/*
* This is the list of registered 32-bit Interrupt handlers.
*/
@ -46,86 +32,10 @@ EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL };
/* PUBLIC FUNCTIONS ***********************************************************/
VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack)
{
WORD CodeSegment, InstructionPointer;
PBYTE Opcode;
ASSERT(ExceptionNumber < 8);
/* Get the CS:IP */
InstructionPointer = Stack[STACK_IP];
CodeSegment = Stack[STACK_CS];
Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer);
/* Display a message to the user */
DisplayMessage(L"Exception: %s occured at %04X:%04X\n"
L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
ExceptionName[ExceptionNumber],
CodeSegment,
InstructionPointer,
Opcode[0],
Opcode[1],
Opcode[2],
Opcode[3],
Opcode[4],
Opcode[5],
Opcode[6],
Opcode[7],
Opcode[8],
Opcode[9]);
/* Stop the VDM */
VdmRunning = FALSE;
return;
}
#if 0
VOID WINAPI IrqDispatch(BYTE IrqNumber, LPWORD Stack)
{
/* Check if this was an PIC IRQ */
if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
{
/* It was an IRQ from the master PIC */
BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack);
}
else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
{
/* It was an IRQ from the slave PIC */
BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack);
}
return;
}
#endif
VOID WINAPI Int32Dispatch(LPWORD Stack)
{
BYTE IntNum;
/* Get the interrupt number */
IntNum = LOBYTE(Stack[STACK_INT_NUM]);
/* Check if this was an exception */
if (IntNum < 8)
{
Exception(IntNum, Stack);
return;
}
/* Check if this was an PIC IRQ */
if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
{
/* It was an IRQ from the master PIC */
BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack);
return;
}
else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
{
/* It was an IRQ from the slave PIC */
BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack);
return;
}
BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
/* Call the 32-bit Interrupt handler */
if (Int32Proc[IntNum] != NULL)

View file

@ -55,7 +55,7 @@ BOOL WINAPI ConsoleCtrlHandler(DWORD ControlType)
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
{
/* Perform interrupt 0x23 */
/* Call INT 23h */
EmulatorInterrupt(0x23);
break;
}
@ -202,7 +202,7 @@ INT wmain(INT argc, WCHAR *argv[])
}
/* Initialize the emulator */
if (!EmulatorInitialize())
if (!EmulatorInitialize(ConsoleInput, ConsoleOutput))
{
wprintf(L"FATAL: Failed to initialize the emulator\n");
goto Cleanup;