[NTVDM]
[reactos.git] / reactos / 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 //
62 // WARNING WARNING!!
63 //
64 // If you modify the code stubs here, think also
65 // about updating them in callback.c too!!
66 //
67
68 LPDWORD IntVecTable = (LPDWORD)BaseAddress;
69 LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BiosSegment, 0);
70 USHORT i;
71 WORD BopSeqOffset, Offset = 0;
72
73 /* Generate ISR stubs and fill the IVT */
74 for (i = 0x00; i <= 0xFF; i++)
75 {
76 Offset = INT_HANDLER_OFFSET + (i << 4);
77 IntVecTable[i] = MAKELONG(Offset, BiosSegment);
78
79 BiosCode[Offset++] = 0xFA; // cli
80
81 BiosCode[Offset++] = 0x6A; // push i
82 BiosCode[Offset++] = (UCHAR)i;
83
84 BopSeqOffset = COMMON_STUB_OFFSET - (Offset + 3);
85
86 BiosCode[Offset++] = 0xE9; // jmp near BOP_SEQ
87 BiosCode[Offset++] = LOBYTE(BopSeqOffset);
88 BiosCode[Offset++] = HIBYTE(BopSeqOffset);
89 }
90
91 /* Write the common stub code */
92 Offset = COMMON_STUB_OFFSET;
93
94 // BOP_SEQ:
95 BiosCode[Offset++] = 0xF8; // clc
96
97 BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
98 BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
99 BiosCode[Offset++] = BOP_CONTROL; // Control BOP
100 BiosCode[Offset++] = BOP_CONTROL_INT32; // 32-bit Interrupt dispatcher
101
102 BiosCode[Offset++] = 0x73; // jnc EXIT (offset +4)
103 BiosCode[Offset++] = 0x04;
104
105 BiosCode[Offset++] = 0xFB; // sti
106
107 // HACK: The following instruction should be HLT!
108 BiosCode[Offset++] = 0x90; // nop
109
110 BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -11)
111 BiosCode[Offset++] = 0xF5;
112
113 // EXIT:
114 BiosCode[Offset++] = 0x44; // inc sp
115 BiosCode[Offset++] = 0x44; // inc sp
116
117 BiosCode[Offset++] = 0xCF; // iret
118
119 /* Register the Control BOP */
120 RegisterBop(BOP_CONTROL, ControlBop);
121 }
122
123 VOID RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler)
124 {
125 Int32Proc[IntNumber] = IntHandler;
126 }
127
128 /* EOF */