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