00c89799897e1b99c1815b308e35762c128a7a7a
[reactos.git] / subsystems / mvdm / ntvdm / cpu / callback.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: subsystems/mvdm/ntvdm/cpu/callback.c
5 * PURPOSE: 16 and 32-bit Callbacks Support
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 /******************************************************************************\
11 | WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
12 |
13 | Callbacks support supposes implicitly that the callbacks are used
14 | in the SAME thread as the CPU thread, otherwise messing in parallel
15 | with the CPU registers is 100% prone to bugs!!
16 \******************************************************************************/
17
18 /* INCLUDES *******************************************************************/
19
20 #include "ntvdm.h"
21
22 #define NDEBUG
23 #include <debug.h>
24
25 #include "emulator.h"
26 #include "callback.h"
27
28 #include "cpu.h"
29 #include "bop.h"
30 #include <isvbop.h>
31
32 /* PRIVATE VARIABLES **********************************************************/
33
34 static BYTE Yield[] =
35 {
36 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
37 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // 13x nop
38 BOP(BOP_UNSIMULATE), // UnSimulate16 BOP
39 };
40 C_ASSERT(sizeof(Yield) == 16 * sizeof(BYTE));
41
42 /* PUBLIC FUNCTIONS ***********************************************************/
43
44 VOID
45 InitializeContextEx(IN PCALLBACK16 Context,
46 IN ULONG TrampolineSize,
47 IN USHORT Segment,
48 IN USHORT Offset)
49 {
50 Context->TrampolineFarPtr = MAKELONG(Offset, Segment);
51 Context->TrampolineSize = max(TRAMPOLINE_SIZE, TrampolineSize);
52 Context->Segment = Segment;
53 Context->NextOffset = Offset + Context->TrampolineSize;
54 }
55
56 VOID
57 InitializeContext(IN PCALLBACK16 Context,
58 IN USHORT Segment,
59 IN USHORT Offset)
60 {
61 InitializeContextEx(Context,
62 TRAMPOLINE_SIZE,
63 Segment,
64 Offset);
65 }
66
67 VOID
68 Call16(IN USHORT Segment,
69 IN USHORT Offset)
70 {
71 /* Save CS:IP */
72 USHORT OrgCS = getCS();
73 USHORT OrgIP = getIP();
74
75 /* Set the new CS:IP */
76 setCS(Segment);
77 setIP(Offset);
78
79 DPRINT("Call16(%04X:%04X)\n", Segment, Offset);
80
81 /* Start CPU simulation */
82 CpuSimulate();
83
84 /* Restore CS:IP */
85 setCS(OrgCS);
86 setIP(OrgIP);
87 }
88
89 VOID
90 RunCallback16(IN PCALLBACK16 Context,
91 IN ULONG FarPtr)
92 {
93 PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr);
94 PUCHAR Trampoline = TrampolineBase;
95 UCHAR OldTrampoline[TRAMPOLINE_SIZE];
96
97 /* Save the old trampoline */
98 ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0];
99
100 DPRINT("RunCallback16(0x%p)\n", FarPtr);
101
102 /* Build the generic entry-point for 16-bit far calls */
103 *Trampoline++ = 0x9A; // Call far seg:off
104 *(PULONG)Trampoline = FarPtr;
105 Trampoline += sizeof(ULONG);
106 UnSimulate16(Trampoline);
107
108 /* Perform the call */
109 Call16(HIWORD(Context->TrampolineFarPtr),
110 LOWORD(Context->TrampolineFarPtr));
111
112 /* Restore the old trampoline */
113 ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0];
114 }
115
116 ULONG
117 RegisterCallback16(IN ULONG FarPtr,
118 IN LPBYTE CallbackCode,
119 IN SIZE_T CallbackSize,
120 OUT PSIZE_T CodeSize OPTIONAL)
121 {
122 LPBYTE CodeStart = (LPBYTE)FAR_POINTER(FarPtr);
123 LPBYTE Code = CodeStart;
124
125 SIZE_T OurCodeSize = CallbackSize;
126
127 if (CallbackCode == NULL) CallbackSize = 0;
128
129 if (CallbackCode)
130 {
131 /* 16-bit interrupt code */
132 RtlCopyMemory(Code, CallbackCode, CallbackSize);
133 Code += CallbackSize;
134 }
135
136 /* Return the real size of the code if needed */
137 if (CodeSize) *CodeSize = OurCodeSize; // == (ULONG_PTR)Code - (ULONG_PTR)CodeStart;
138
139 // /* Return the entry-point address for 32-bit calls */
140 // return (ULONG_PTR)(CodeStart + CallbackSize);
141 return OurCodeSize;
142 }
143
144 /* EOF */