[NTVDM]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 9 Nov 2013 22:15:40 +0000 (22:15 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 9 Nov 2013 22:15:40 +0000 (22:15 +0000)
Start my work on modularizing registration of "32-bit" interrupts, i.e.
interrupts that are implemented in 32-bit mode, but are stubbed with 16-bit
code (so that 16-bit apps can call them).
The 16-bit stub code uses a BOP call to our Control BOP function (BOP 0xFF) which
can handle in theory many sub-functions (as the BOP 0x58 documented here: http://www.ragestorm.net/tutorial?id=27)
specified as an additional BYTE in the call:
0xC4 0xC4 bop_code <optional_bop_subfunction>
Here, for calling 32-bit interrupts we use our BOP 0xFF, subfunction 0xFF.
The final aim would be to generate the 16-bit stub code when one calls the RegisterInt32 helper function
(contrary to what's happening now, that is, the 16-bit stub code is generated for all of the interrupts
at BIOS initialization time, and we use it for BIOS and DOS interrupts).

svn path=/branches/ntvdm/; revision=60907

subsystems/ntvdm/bios.c
subsystems/ntvdm/bios.h
subsystems/ntvdm/bop.c
subsystems/ntvdm/bop.h
subsystems/ntvdm/dos.c
subsystems/ntvdm/dos.h
subsystems/ntvdm/emulator.c
subsystems/ntvdm/emulator.h

index 44803f1..b105465 100644 (file)
 
 #define NDEBUG
 
-#include "bios.h"
 #include "emulator.h"
+#include "bop.h"
+
+#include "bios.h"
 #include "vga.h"
 #include "pic.h"
 #include "ps2.h"
@@ -461,7 +463,7 @@ BOOLEAN BiosInitialize(VOID)
 {
     USHORT i;
     WORD Offset = 0;
-    LPWORD IntVecTable = (LPWORD)BaseAddress;
+    LPDWORD IntVecTable = (LPDWORD)BaseAddress;
     LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0);
 
     /* Initialize the BDA */
@@ -480,8 +482,7 @@ BOOLEAN BiosInitialize(VOID)
     /* Generate ISR stubs and fill the IVT */
     for (i = 0x00; i <= 0xFF; i++)
     {
-        IntVecTable[i * 2] = Offset;
-        IntVecTable[i * 2 + 1] = BIOS_SEGMENT;
+        IntVecTable[i] = MAKELONG(Offset, BIOS_SEGMENT);
 
         BiosCode[Offset++] = 0xFB; // sti
 
@@ -494,9 +495,10 @@ BOOLEAN BiosInitialize(VOID)
 // BOP_SEQ:
         BiosCode[Offset++] = 0xF8; // clc
 
-        BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
+        BiosCode[Offset++] = LOBYTE(EMULATOR_BOP);  // BOP sequence
         BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
-        BiosCode[Offset++] = EMULATOR_INT_BOP;
+        BiosCode[Offset++] = EMULATOR_CTRL_BOP;     // Control BOP
+        BiosCode[Offset++] = CTRL_BOP_INT32;        // 32-bit Interrupt dispatcher
 
         BiosCode[Offset++] = 0x73; // jnc EXIT (offset +3)
         BiosCode[Offset++] = 0x03;
@@ -504,8 +506,8 @@ BOOLEAN BiosInitialize(VOID)
         // HACK: The following instruction should be HLT!
         BiosCode[Offset++] = 0x90; // nop
 
-        BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -9)
-        BiosCode[Offset++] = 0xF7;
+        BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -10)
+        BiosCode[Offset++] = 0xF6;
 
 // EXIT:
         BiosCode[Offset++] = 0x83; // add sp, 4
@@ -514,6 +516,12 @@ BOOLEAN BiosInitialize(VOID)
 
         BiosCode[Offset++] = 0xCF; // iret
     }
+    RegisterInt32(BIOS_VIDEO_INTERRUPT    , BiosVideoService        );
+    RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService    );
+    RegisterInt32(BIOS_MEMORY_SIZE        , BiosGetMemorySize       );
+    RegisterInt32(BIOS_KBD_INTERRUPT      , BiosKeyboardService     );
+    RegisterInt32(BIOS_TIME_INTERRUPT     , BiosTimeService         );
+    RegisterInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt);
 
     /* Get the input handle to the real console, and check for success */
     BiosConsoleInput = CreateFileW(L"CONIN$",
@@ -818,7 +826,7 @@ VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
     BiosSetCursorPosition(Row, Column, Page);
 }
 
-VOID BiosVideoService(LPWORD Stack)
+VOID WINAPI BiosVideoService(LPWORD Stack)
 {
     switch (getAH())
     {
@@ -1194,19 +1202,19 @@ VOID BiosVideoService(LPWORD Stack)
     }
 }
 
-VOID BiosEquipmentService(LPWORD Stack)
+VOID WINAPI BiosEquipmentService(LPWORD Stack)
 {
     /* Return the equipment list */
     setAX(Bda->EquipmentList);
 }
 
-VOID BiosGetMemorySize(LPWORD Stack)
+VOID WINAPI BiosGetMemorySize(LPWORD Stack)
 {
     /* Return the conventional memory size in kB, typically 640 kB */
     setAX(Bda->MemorySize);
 }
 
-VOID BiosKeyboardService(LPWORD Stack)
+VOID WINAPI BiosKeyboardService(LPWORD Stack)
 {
     switch (getAH())
     {
@@ -1288,7 +1296,7 @@ VOID BiosKeyboardService(LPWORD Stack)
     }
 }
 
-VOID BiosTimeService(LPWORD Stack)
+VOID WINAPI BiosTimeService(LPWORD Stack)
 {
     switch (getAH())
     {
@@ -1326,7 +1334,7 @@ VOID BiosTimeService(LPWORD Stack)
     }
 }
 
-VOID BiosSystemTimerInterrupt(LPWORD Stack)
+VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
 {
     /* Increase the system tick count */
     Bda->TickCounter++;
index 7fb2c16..e89292d 100644 (file)
@@ -159,13 +159,6 @@ WORD BiosPeekCharacter(VOID);
 WORD BiosGetCharacter(VOID);
 VOID BiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page);
 VOID BiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page);
-VOID BiosVideoService(LPWORD Stack);
-VOID BiosEquipmentService(LPWORD Stack);
-VOID BiosGetMemorySize(LPWORD Stack);
-VOID BiosKeyboardService(LPWORD Stack);
-VOID BiosTimeService(LPWORD Stack);
-VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack);
-VOID BiosSystemTimerInterrupt(LPWORD Stack);
 VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page);
 BOOLEAN BiosScrollWindow(
     INT Direction,
@@ -175,6 +168,15 @@ BOOLEAN BiosScrollWindow(
     BYTE FillAttribute
 );
 
+VOID WINAPI BiosVideoService(LPWORD Stack);
+VOID WINAPI BiosEquipmentService(LPWORD Stack);
+VOID WINAPI BiosGetMemorySize(LPWORD Stack);
+VOID WINAPI BiosKeyboardService(LPWORD Stack);
+VOID WINAPI BiosTimeService(LPWORD Stack);
+VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack);
+
+VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack);
+
 #endif // _BIOS_H_
 
 /* EOF */
index f12ffd1..a96d3d8 100644 (file)
 #define NDEBUG
 
 #include "emulator.h"
-#include "bios.h"
 #include "bop.h"
+
+#include "bios.h"
 #include "dos.h"
-//#include "vga.h"
-//#include "pic.h"
-//#include "ps2.h"
-//#include "timer.h"
 #include "registers.h"
 
 LPCWSTR ExceptionName[] =
@@ -33,6 +30,9 @@ LPCWSTR ExceptionName[] =
     L"FPU Not Available"
 };
 
+/*
+ * This is the list of registered BOP handlers.
+ */
 EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM] =
 {
     NULL,
@@ -293,6 +293,271 @@ EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM] =
     ControlBop
 };
 
+/*
+ * This is the list of registered 32-bit Interrupt handlers.
+ */
+EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT_NUM] =
+{
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+
+
 VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack)
 {
     WORD CodeSegment, InstructionPointer;
@@ -344,11 +609,7 @@ VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack)
     // return;
 // }
 
-// VOID WINAPI BiosInt(BYTE IntNumber, LPWORD Stack)
-// {
-// }
-
-VOID WINAPI IntDispatch(LPWORD Stack)
+VOID WINAPI Int32Dispatch(LPWORD Stack)
 {
     BYTE IntNum;
 
@@ -376,77 +637,48 @@ VOID WINAPI IntDispatch(LPWORD Stack)
         return;
     }
 
-    switch (IntNum)
-    {
-        case BIOS_VIDEO_INTERRUPT:
-        {
-            /* This is the video BIOS interrupt, call the BIOS */
-            BiosVideoService(Stack);
-            break;
-        }
-        case BIOS_EQUIPMENT_INTERRUPT:
-        {
-            /* This is the BIOS "get equipment" command, call the BIOS */
-            BiosEquipmentService(Stack);
-            break;
-        }
-        case BIOS_MEMORY_SIZE:
-        {
-            /* This is the BIOS "get memory size" command, call the BIOS */
-            BiosGetMemorySize(Stack);
-            break;
-        }
-        case BIOS_KBD_INTERRUPT:
-        {
-            /* This is the keyboard BIOS interrupt, call the BIOS */
-            BiosKeyboardService(Stack);
-            break;
-        }
-        case BIOS_TIME_INTERRUPT:
-        {
-            /* This is the time BIOS interrupt, call the BIOS */
-            BiosTimeService(Stack);
-            break;
-        }
-        case BIOS_SYS_TIMER_INTERRUPT:
-        {
-            /* BIOS timer update */
-            BiosSystemTimerInterrupt(Stack);
-            break;
-        }
-        case 0x20:
-        {
-            DosInt20h(Stack);
-            break;
-        }
-        case 0x21:
-        {
-            DosInt21h(Stack);
-            break;
-        }
-        case 0x23:
-        {
-            DosBreakInterrupt(Stack);
-            break;
-        }
-        case 0x2F:
-        {
-            DPRINT1("DOS System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
-                    getAH(), getAL());
-            Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
-            break;
-        }
-        default:
-        {
-            DPRINT1("Unhandled interrupt: 0x%02X\n", IntNum);
-            break;
-        }
-    }
+    /* Call the 32-bit Interrupt handler */
+    if (Int32Proc[IntNum] != NULL)
+        Int32Proc[IntNum](Stack);
+    else
+        DPRINT1("Unhandled 32-bit interrupt: 0x%02X\n", IntNum);
 }
 
 VOID WINAPI ControlBop(LPWORD Stack)
 {
-    IntDispatch(Stack);
+    /* Get the Function Number and skip it */
+    BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
+    setIP(getIP() + 1);
+
+    if (FuncNum == CTRL_BOP_INT32)
+        Int32Dispatch(Stack);
+    else
+        DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum);
+}
+
+
+VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler)
+{
+    Int32Proc[IntNumber] = IntHandler;
+}
+
+VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
+{
+    WORD StackSegment, StackPointer;
+    LPWORD Stack;
+
+    /* Get the SS:SP */
+    StackSegment = State->SegmentRegs[FAST486_REG_SS].Selector;
+    StackPointer = State->GeneralRegs[FAST486_REG_ESP].LowWord;
+
+    /* Get the stack */
+    Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer);
+
+    /* Call the BOP handler */
+    if (BopProc[BopCode] != NULL)
+        BopProc[BopCode](Stack);
+    else
+        DPRINT1("Invalid BOP code: 0x%02X\n", BopCode);
 }
 
 /* EOF */
index 61a45eb..12ebf27 100644 (file)
@@ -7,10 +7,33 @@
  *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
  */
 
-typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack);
+#ifndef _BOP_H_
+#define _BOP_H_
+
+/* DEFINES ********************************************************************/
+
+/* BOP Identifiers */
+#define EMULATOR_BOP            0xC4C4
+
+#define EMULATOR_CTRL_BOP       0xFF    // Control BOP Handler
+         #define CTRL_BOP_DEFLT 0x00    // Default Control BOP Function
+         #define CTRL_BOP_INT32 0xFF    // 32-bit Interrupt dispatcher
+
+#define EMULATOR_MAX_BOP_NUM    0xFF + 1
 
-extern EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM];
+/* 32-bit Interrupt Identifiers */
+#define EMULATOR_MAX_INT_NUM    0xFF + 1
+
+/* FUNCTIONS ******************************************************************/
+
+typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack);
+typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);
 
 VOID WINAPI ControlBop(LPWORD Stack);
 
+VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler);
+VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode);
+
+#endif // _BOP_H_
+
 /* EOF */
index f56ed76..027ea3e 100644 (file)
 
 #define NDEBUG
 
+#include "emulator.h"
+#include "bop.h"
+
 #include "dos.h"
 #include "bios.h"
-#include "emulator.h"
 
 #include "registers.h"
 
@@ -1393,13 +1395,13 @@ BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle)
     }
 }
 
-VOID DosInt20h(LPWORD Stack)
+VOID WINAPI DosInt20h(LPWORD Stack)
 {
     /* This is the exit interrupt */
     DosTerminateProcess(Stack[STACK_CS], 0);
 }
 
-VOID DosInt21h(LPWORD Stack)
+VOID WINAPI DosInt21h(LPWORD Stack)
 {
     BYTE Character;
     SYSTEMTIME SystemTime;
@@ -2415,13 +2417,20 @@ VOID DosInt21h(LPWORD Stack)
     }
 }
 
-VOID DosBreakInterrupt(LPWORD Stack)
+VOID WINAPI DosBreakInterrupt(LPWORD Stack)
 {
     UNREFERENCED_PARAMETER(Stack);
 
     VdmRunning = FALSE;
 }
 
+VOID WINAPI DosInt2Fh(LPWORD Stack)
+{
+    DPRINT1("DOS System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
+            getAH(), getAL());
+    Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+}
+
 BOOLEAN DosInitialize(VOID)
 {
     BYTE i;
@@ -2561,6 +2570,12 @@ BOOLEAN DosInitialize(VOID)
     DosSystemFileTable[1] = GetStdHandle(STD_OUTPUT_HANDLE);
     DosSystemFileTable[2] = GetStdHandle(STD_ERROR_HANDLE);
 
+    /* Register the DOS-32 Interrupts */
+    RegisterInt32(0x20, DosInt20h        );
+    RegisterInt32(0x21, DosInt21h        );
+    RegisterInt32(0x23, DosBreakInterrupt);
+    RegisterInt32(0x2F, DosInt2Fh        );
+
     return TRUE;
 }
 
index 880ac66..0ec0d83 100644 (file)
@@ -136,9 +136,12 @@ VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode);
 CHAR DosReadCharacter(VOID);
 VOID DosPrintCharacter(CHAR Character);
 BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle);
-VOID DosInt20h(LPWORD Stack);
-VOID DosInt21h(LPWORD Stack);
-VOID DosBreakInterrupt(LPWORD Stack);
+
+VOID WINAPI DosInt20h(LPWORD Stack);
+VOID WINAPI DosInt21h(LPWORD Stack);
+VOID WINAPI DosBreakInterrupt(LPWORD Stack);
+VOID WINAPI DosInt2Fh(LPWORD Stack);
+
 BOOLEAN DosInitialize(VOID);
 
 #endif // _DOS_H_
index 42dc841..742112c 100644 (file)
@@ -272,24 +272,6 @@ VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULON
     }
 }
 
-VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
-{
-    WORD StackSegment, StackPointer;
-    LPWORD Stack;
-
-    /* Get the SS:SP */
-    StackSegment = State->SegmentRegs[FAST486_REG_SS].Selector;
-    StackPointer = State->GeneralRegs[FAST486_REG_ESP].LowWord;
-
-    /* Get the stack */
-    Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer);
-
-    if (BopProc[BopCode] != NULL)
-        BopProc[BopCode](Stack);
-    else
-        DPRINT1("Invalid BOP code %u\n", BopCode);
-}
-
 UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
 {
     UNREFERENCED_PARAMETER(State);
index 877f01e..742079e 100644 (file)
@@ -120,12 +120,6 @@ VOID WINAPI EmulatorWriteIo
     UCHAR DataSize
 );
 
-VOID WINAPI EmulatorBiosOperation
-(
-    PFAST486_STATE State,
-    UCHAR BopCode
-);
-
 UCHAR WINAPI EmulatorIntAcknowledge
 (
     PFAST486_STATE State