2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: subsystems/mvdm/ntvdm/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)
10 /* INCLUDES *******************************************************************/
23 /* PRIVATE VARIABLES **********************************************************/
26 * This is the list of registered 32-bit Interrupt handlers.
28 static EMULATOR_INT32_PROC Int32Proc
[EMULATOR_MAX_INT32_NUM
] = { NULL
};
31 #define BOP_CONTROL 0xFF // Control BOP Handler
32 #define BOP_CONTROL_DEFFUNC 0x00 // Default Control BOP Function
33 #define BOP_CONTROL_INT32 0xFF // 32-bit Interrupt dispatcher
35 #define INT16_TRAMPOLINE_SIZE sizeof(ULONGLONG) // == TRAMPOLINE_SIZE
37 /* 16-bit generic interrupt code for calling a 32-bit interrupt handler */
38 static BYTE Int16To32
[] =
42 /* Push the value of the interrupt to be called */
43 0x6A, 0xFF, // push i (patchable to 0x6A, 0xIntNum)
47 /* The BOP Sequence */
49 BOP(BOP_CONTROL
), // Control BOP
50 BOP_CONTROL_INT32
, // 32-bit Interrupt dispatcher
52 0x73, 0x04, // jnc EXIT (offset +4)
58 0xEB, 0xF6, // jmp BOP_SEQ (offset -10)
61 0x44, 0x44, // inc sp, inc sp
64 C_ASSERT(sizeof(Int16To32
) == Int16To32StubSize
);
66 /* PUBLIC FUNCTIONS ***********************************************************/
68 static VOID WINAPI
Int32Dispatch(LPWORD Stack
)
70 /* Get the interrupt number */
71 BYTE IntNum
= LOBYTE(Stack
[STACK_INT_NUM
]);
73 /* Call the 32-bit Interrupt handler */
74 if (Int32Proc
[IntNum
] != NULL
)
75 Int32Proc
[IntNum
](Stack
);
77 DPRINT1("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum
, getAX());
80 static VOID WINAPI
ControlBop(LPWORD Stack
)
82 /* Get the Function Number and skip it */
83 BYTE FuncNum
= *(PBYTE
)SEG_OFF_TO_PTR(getCS(), getIP());
88 case BOP_CONTROL_INT32
:
93 // DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum);
94 DisplayMessage(L
"Unassigned Control BOP Function: 0x%02X", FuncNum
);
100 RegisterInt16(IN ULONG FarPtr
,
102 IN LPBYTE CallbackCode
,
103 IN SIZE_T CallbackSize
,
104 OUT PSIZE_T CodeSize OPTIONAL
)
106 /* Get a pointer to the IVT and set the corresponding entry (far pointer) */
107 LPDWORD IntVecTable
= (LPDWORD
)SEG_OFF_TO_PTR(0x0000, 0x0000);
108 IntVecTable
[IntNumber
] = FarPtr
;
110 /* Register the 16-bit callback */
111 return RegisterCallback16(FarPtr
,
118 RegisterInt32(IN ULONG FarPtr
,
120 IN EMULATOR_INT32_PROC IntHandler
,
121 OUT PSIZE_T CodeSize OPTIONAL
)
123 /* Array for holding our copy of the 16-bit interrupt callback */
124 BYTE IntCallback
[sizeof(Int16To32
)/sizeof(BYTE
)];
126 /* Check whether the 32-bit interrupt was already registered */
128 if (Int32Proc
[IntNumber
] != NULL
)
130 DPRINT1("RegisterInt32: Interrupt 0x%02X already registered!\n", IntNumber
);
135 /* Register the 32-bit interrupt handler */
136 Int32Proc
[IntNumber
] = IntHandler
;
138 /* Copy the generic 16-bit interrupt callback and patch it */
139 RtlCopyMemory(IntCallback
, Int16To32
, sizeof(Int16To32
));
140 IntCallback
[2] = IntNumber
;
142 /* Register the 16-bit interrupt callback */
143 return RegisterInt16(FarPtr
,
151 Int32Call(IN PCALLBACK16 Context
,
155 * TODO: This function has almost the same code as RunCallback16.
156 * Something that may be nice is to have a common interface to
157 * build the trampoline...
160 PUCHAR TrampolineBase
= (PUCHAR
)FAR_POINTER(Context
->TrampolineFarPtr
);
161 PUCHAR Trampoline
= TrampolineBase
;
162 UCHAR OldTrampoline
[INT16_TRAMPOLINE_SIZE
];
164 DPRINT("Int32Call(0x%02X)\n", IntNumber
);
166 ASSERT(Context
->TrampolineSize
== INT16_TRAMPOLINE_SIZE
);
168 /* Save the old trampoline */
169 ((PULONGLONG
)&OldTrampoline
)[0] = ((PULONGLONG
)TrampolineBase
)[0];
171 /* Build the generic entry-point for 16-bit calls */
172 if (IntNumber
== 0x03)
174 /* We are redefining for INT 03h */
175 *Trampoline
++ = 0xCC; // Call INT 03h
176 /** *Trampoline++ = 0x90; // nop **/
180 /* Normal interrupt */
181 *Trampoline
++ = 0xCD; // Call INT XXh
182 *Trampoline
++ = IntNumber
;
184 UnSimulate16(Trampoline
);
186 /* Perform the call */
187 Call16(HIWORD(Context
->TrampolineFarPtr
),
188 LOWORD(Context
->TrampolineFarPtr
));
190 /* Restore the old trampoline */
191 ((PULONGLONG
)TrampolineBase
)[0] = ((PULONGLONG
)&OldTrampoline
)[0];
194 VOID
InitializeInt32(VOID
)
196 /* Register the Control BOP */
197 RegisterBop(BOP_CONTROL
, ControlBop
);