d61625148a832bce473a85ca0c1b96bee2b56640
[reactos.git] / subsystems / ntvdm / int32.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: int32.c
5 * PURPOSE: 32-bit Interrupt Handlers
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 // #define NDEBUG
13
14 #include "emulator.h"
15 #include "int32.h"
16
17 #include "bop.h"
18
19 /* PRIVATE VARIABLES **********************************************************/
20
21 /*
22 * This is the list of registered 32-bit Interrupt handlers.
23 */
24 EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL };
25
26 /* BOP Identifiers */
27 #define BOP_CONTROL 0xFF // Control BOP Handler
28 #define BOP_CONTROL_DEFFUNC 0x00 // Default Control BOP Function
29
30 /* 32-bit Interrupt dispatcher function code for the Control BOP Handler */
31 #define BOP_CONTROL_INT32 0xFF
32
33 /* PUBLIC FUNCTIONS ***********************************************************/
34
35 VOID WINAPI Int32Dispatch(LPWORD Stack)
36 {
37 /* Get the interrupt number */
38 BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
39
40 /* Call the 32-bit Interrupt handler */
41 if (Int32Proc[IntNum] != NULL)
42 Int32Proc[IntNum](Stack);
43 else
44 DPRINT("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum, getAX());
45 }
46
47 VOID WINAPI ControlBop(LPWORD Stack)
48 {
49 /* Get the Function Number and skip it */
50 BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
51 setIP(getIP() + 1);
52
53 if (FuncNum == BOP_CONTROL_INT32)
54 Int32Dispatch(Stack);
55 else
56 DPRINT("Unassigned Control BOP Function: 0x%02X\n", FuncNum);
57 }
58
59 VOID InitializeInt32(WORD BiosSegment)
60 {
61 LPDWORD IntVecTable = (LPDWORD)BaseAddress;
62 LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BiosSegment, 0);
63 USHORT i;
64 WORD BopSeqOffset, Offset = 0;
65
66 /* Generate ISR stubs and fill the IVT */
67 for (i = 0x00; i <= 0xFF; i++)
68 {
69 Offset = INT_HANDLER_OFFSET + (i << 4);
70 IntVecTable[i] = MAKELONG(Offset, BiosSegment);
71
72 BiosCode[Offset++] = 0xFA; // cli
73
74 BiosCode[Offset++] = 0x6A; // push i
75 BiosCode[Offset++] = (UCHAR)i;
76
77 BiosCode[Offset++] = 0x6A; // push 0
78 BiosCode[Offset++] = 0x00;
79
80 BopSeqOffset = COMMON_STUB_OFFSET - (Offset + 3);
81
82 BiosCode[Offset++] = 0xE9; // jmp near BOP_SEQ
83 BiosCode[Offset++] = LOBYTE(BopSeqOffset);
84 BiosCode[Offset++] = HIBYTE(BopSeqOffset);
85 }
86
87 /* Write the common stub code */
88 Offset = COMMON_STUB_OFFSET;
89
90 // BOP_SEQ:
91 BiosCode[Offset++] = 0xF8; // clc
92
93 BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
94 BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
95 BiosCode[Offset++] = BOP_CONTROL; // Control BOP
96 BiosCode[Offset++] = BOP_CONTROL_INT32; // 32-bit Interrupt dispatcher
97
98 BiosCode[Offset++] = 0x73; // jnc EXIT (offset +4)
99 BiosCode[Offset++] = 0x04;
100
101 BiosCode[Offset++] = 0xFB; // sti
102
103 // HACK: The following instruction should be HLT!
104 BiosCode[Offset++] = 0x90; // nop
105
106 BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -11)
107 BiosCode[Offset++] = 0xF5;
108
109 // EXIT:
110 BiosCode[Offset++] = 0x83; // add sp, 4
111 BiosCode[Offset++] = 0xC4;
112 BiosCode[Offset++] = 0x04;
113
114 BiosCode[Offset++] = 0xCF; // iret
115
116 /* Register the Control BOP */
117 RegisterBop(BOP_CONTROL, ControlBop);
118 }
119
120 VOID RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler)
121 {
122 Int32Proc[IntNumber] = IntHandler;
123 }
124
125 /* EOF */