[NTVDM] Improve the PCH situation.
[reactos.git] / reactos / 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 #include "ntvdm.h"
19
20 #define NDEBUG
21 #include <debug.h>
22
23 /* PRIVATE VARIABLES **********************************************************/
24
25 static BYTE Yield[] =
26 {
27 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
28 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // 13x nop
29 BOP(BOP_UNSIMULATE), // UnSimulate16 BOP
30 };
31 C_ASSERT(sizeof(Yield) == 16 * sizeof(BYTE));
32
33 /* PUBLIC FUNCTIONS ***********************************************************/
34
35 VOID
36 InitializeContextEx(IN PCALLBACK16 Context,
37 IN ULONG TrampolineSize,
38 IN USHORT Segment,
39 IN USHORT Offset)
40 {
41 Context->TrampolineFarPtr = MAKELONG(Offset, Segment);
42 Context->TrampolineSize = max(TRAMPOLINE_SIZE, TrampolineSize);
43 Context->Segment = Segment;
44 Context->NextOffset = Offset + Context->TrampolineSize;
45 }
46
47 VOID
48 InitializeContext(IN PCALLBACK16 Context,
49 IN USHORT Segment,
50 IN USHORT Offset)
51 {
52 InitializeContextEx(Context,
53 TRAMPOLINE_SIZE,
54 Segment,
55 Offset);
56 }
57
58 VOID
59 Call16(IN USHORT Segment,
60 IN USHORT Offset)
61 {
62 /* Save CS:IP */
63 USHORT OrgCS = getCS();
64 USHORT OrgIP = getIP();
65
66 /* Set the new CS:IP */
67 setCS(Segment);
68 setIP(Offset);
69
70 DPRINT("Call16(%04X:%04X)\n", Segment, Offset);
71
72 /* Start CPU simulation */
73 CpuSimulate();
74
75 /* Restore CS:IP */
76 setCS(OrgCS);
77 setIP(OrgIP);
78 }
79
80 VOID
81 RunCallback16(IN PCALLBACK16 Context,
82 IN ULONG FarPtr)
83 {
84 PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr);
85 PUCHAR Trampoline = TrampolineBase;
86 UCHAR OldTrampoline[TRAMPOLINE_SIZE];
87
88 /* Save the old trampoline */
89 ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0];
90
91 DPRINT("RunCallback16(0x%p)\n", FarPtr);
92
93 /* Build the generic entry-point for 16-bit far calls */
94 *Trampoline++ = 0x9A; // Call far seg:off
95 *(PULONG)Trampoline = FarPtr;
96 Trampoline += sizeof(ULONG);
97 UnSimulate16(Trampoline);
98
99 /* Perform the call */
100 Call16(HIWORD(Context->TrampolineFarPtr),
101 LOWORD(Context->TrampolineFarPtr));
102
103 /* Restore the old trampoline */
104 ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0];
105 }
106
107 ULONG
108 RegisterCallback16(IN ULONG FarPtr,
109 IN LPBYTE CallbackCode,
110 IN SIZE_T CallbackSize,
111 OUT PSIZE_T CodeSize OPTIONAL)
112 {
113 LPBYTE CodeStart = (LPBYTE)FAR_POINTER(FarPtr);
114 LPBYTE Code = CodeStart;
115
116 SIZE_T OurCodeSize = CallbackSize;
117
118 if (CallbackCode == NULL) CallbackSize = 0;
119
120 if (CallbackCode)
121 {
122 /* 16-bit interrupt code */
123 RtlCopyMemory(Code, CallbackCode, CallbackSize);
124 Code += CallbackSize;
125 }
126
127 /* Return the real size of the code if needed */
128 if (CodeSize) *CodeSize = OurCodeSize; // == (ULONG_PTR)Code - (ULONG_PTR)CodeStart;
129
130 // /* Return the entry-point address for 32-bit calls */
131 // return (ULONG_PTR)(CodeStart + CallbackSize);
132 return OurCodeSize;
133 }
134
135 /* EOF */