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