summaryrefslogtreecommitdiffstats
path: root/private/mvdm/v86/monitor/i386/monitor.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/v86/monitor/i386/monitor.c')
-rw-r--r--private/mvdm/v86/monitor/i386/monitor.c1135
1 files changed, 1135 insertions, 0 deletions
diff --git a/private/mvdm/v86/monitor/i386/monitor.c b/private/mvdm/v86/monitor/i386/monitor.c
new file mode 100644
index 000000000..fded8dac0
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/monitor.c
@@ -0,0 +1,1135 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ Monitor.c
+Abstract:
+
+ This module is the user mode portion of the x86 monitor
+
+Author:
+
+ Dave Hastings (daveh) 16 Mar 1991
+
+Environment:
+
+ User mode only
+
+Revision History:
+ Sudeep Bharati (sudeepb) 31-Dec-1991
+
+ Converted all register manipulation interfaces to functions
+ from macros. This is to make ntvdm an exe as well as a dll,
+ and these register oriented routines are exported from ntvdm
+ for WOW32 and other installable VDDs.
+
+ Dave Hastings (daveh) 18-Apr-1992
+
+ Split into multiple files. Track current monitor thread by
+ Teb pointer. Register initial thread.
+
+ Sudeep Bharati (sudeepb) 22-Sep-1992
+
+ Added Page Fault Handling For installable VDD support
+
+--*/
+
+
+#include "monitorp.h"
+
+
+//
+// Internal functions
+//
+
+VOID
+EventVdmIo(
+ VOID
+ );
+
+VOID
+EventVdmStringIo(
+ VOID
+ );
+
+VOID
+EventVdmMemAccess(
+ VOID
+ );
+
+VOID
+EventVdmIntAck(
+ VOID
+ );
+
+VOID
+EventVdmBop(
+ VOID
+ );
+
+VOID
+EventVdmError(
+ VOID
+ );
+
+VOID
+EventVdmIrq13(
+ VOID
+ );
+
+VOID
+CreateProfile(
+ VOID
+ );
+
+VOID
+StartProfile(
+ VOID
+ );
+
+VOID
+StopProfile(
+ VOID
+ );
+
+VOID
+AnalyzeProfile(
+ VOID
+ );
+
+// [LATER] how do you prevent a struct from straddling a page boundary?
+VDM_TIB VdmTib;
+
+ULONG IntelBase; // base memory address
+ULONG VdmSize; // Size of memory in VDM
+ULONG IntelMSW; // Msw value (no msw in context)
+ULONG VdmDebugLevel; // used to control debugging
+PVOID CurrentMonitorTeb; // thread that is currently executing instructions.
+ULONG InitialBreakpoint = FALSE; // if set, breakpoint at end of cpu_init
+ULONG InitialVdmTibFlags = 0; // VdmTib flags picked up from here
+CONTEXT InitialContext; // Initial context for all threads
+BOOLEAN DebugContextActive = FALSE;
+ULONG VdmFeatureBits = 0; // bit to indicate special features
+
+extern PVOID NTVDMpLockPrefixTable;
+
+IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // GlobalFlagsClear
+ 0, // GlobalFlagsSet
+ 0, // CriticalSectionTimeout (milliseconds)
+ 0, // DeCommitFreeBlockThreshold
+ 0, // DeCommitTotalFreeThreshold
+ &NTVDMpLockPrefixTable, // LockPrefixTable, defined in FASTPM.ASM
+ 0, 0, 0, 0, 0, 0, 0 // Reserved
+};
+
+// Bop dispatch table
+
+extern void (*BIOS[])();
+
+BOOLEAN ContinueExecution;
+
+//
+// Event Dispatch table
+//
+
+VOID (*EventDispatch[VdmMaxEvent])(VOID) = {
+ EventVdmIo,
+ EventVdmStringIo,
+ EventVdmMemAccess,
+ EventVdmIntAck,
+ EventVdmBop,
+ EventVdmError,
+ EventVdmIrq13
+ };
+
+// Debug control flags
+BOOLEAN fShowBop = FALSE;
+#if DBG
+BOOLEAN fBreakInDebugger = FALSE;
+LONG NumTasks = -1;
+#endif
+
+
+
+EXPORT
+VOID
+cpu_init(
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to prepare the IEU for instruction simulation.
+ It will set the Intel registers to thier initial value, and perform
+ any implementation specific initialization necessary.
+
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ NTSTATUS Status;
+
+ IntelMSW = 0x0; // bugbug use correct value for ET and MP
+ InitialVdmTibFlags |= RM_BIT_MASK;
+
+ VdmTib.VdmContext.SegGs = 0;
+ VdmTib.VdmContext.SegFs = 0;
+ VdmTib.VdmContext.SegEs = 0;
+ VdmTib.VdmContext.SegDs = 0;
+ VdmTib.VdmContext.SegCs = 0;
+ VdmTib.VdmContext.Eip = 0xFFF0L;
+ VdmTib.VdmContext.EFlags = 0x02L | EFLAGS_INTERRUPT_MASK;
+
+ VdmTib.MonitorContext.SegDs = KGDT_R3_DATA | RPL_MASK;
+ VdmTib.MonitorContext.SegEs = KGDT_R3_DATA | RPL_MASK;
+ VdmTib.MonitorContext.SegGs = 0;
+ VdmTib.MonitorContext.SegFs = KGDT_R3_TEB | RPL_MASK;
+
+ VdmTib.PrinterInfo.prt_State = NULL;
+ VdmTib.PrinterInfo.prt_Control = NULL;
+ VdmTib.PrinterInfo.prt_Status = NULL;
+ VdmTib.PrinterInfo.prt_HostState = NULL;
+ ASSERT(VDM_NUMBER_OF_LPT == 3);
+
+ VdmTib.PrinterInfo.prt_Mode[0] =
+ VdmTib.PrinterInfo.prt_Mode[1] =
+ VdmTib.PrinterInfo.prt_Mode[2] = PRT_MODE_NO_SIMULATION;
+
+ VdmTib.Size = sizeof(VDM_TIB);
+
+ //
+ // Find out if we are running with IOPL. We call the kernel
+ // rather than checking the registry ourselves, so that we can
+ // insure that both the kernel and ntvdm.exe agree. If they didn't,
+ // it would result in unnecssary trapping instructions. Whether or
+ // not Vdms run with IOPL only changes on reboot
+ //
+ Status = NtVdmControl(VdmFeatures, &VdmFeatureBits);
+
+#if DBG
+ if (!NT_SUCCESS(Status)) {
+ DbgPrint(
+ "NTVDM: Could not find out whether to use IOPL, %lx\n",
+ Status
+ );
+ }
+#endif
+
+ //
+ // If we have fast v86 mode IF emulation set the bit that tells
+ // the 16 bit IF macros they know.
+ //
+ if (VdmFeatureBits & V86_VIRTUAL_INT_EXTENSIONS) {
+ InitialVdmTibFlags |= RI_BIT_MASK;
+ }
+
+ *pNtVDMState = InitialVdmTibFlags;
+
+ // Switch the npx back to 80 bit mode. Win32 apps start with
+ // 64-bit precision for compatibility across platforms, but
+ // DOS and Win16 apps expect 80 bit precision.
+ //
+
+ _asm fninit;
+
+ //
+ // We setup the InitialContext structure with the correct floating
+ // point and debug register configuration, and cpu_createthread
+ // uses this context to configure each 16-bit thread's floating
+ // point and debug registers.
+ //
+
+ InitialContext.ContextFlags = CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS;
+
+ Status = NtGetContextThread(
+ NtCurrentThread(),
+ &InitialContext
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("NtVdm terminating : Could not get float/debug context for\n"
+ " initial thread, status %lx\n", Status);
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+
+
+ //
+ //
+ // Turn OFF em bit so that dos apps will work correctly.
+ //
+ // On machines without 387's the floating point flag will have been
+ // cleared.
+ //
+
+ InitialContext.ContextFlags = CONTEXT_FLOATING_POINT;
+ InitialContext.FloatSave.Cr0NpxState &= ~0x6; // CR0_EM | CR0_MP
+
+ //
+ // Do the rest of thread initialization
+ //
+ cpu_createthread( NtCurrentThread() );
+
+ InterruptInit();
+
+ if (InitialBreakpoint) {
+ DbgBreakPoint();
+ }
+
+}
+
+EXPORT
+VOID
+cpu_terminate(
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ InterruptTerminate();
+}
+
+EXPORT
+VOID
+cpu_simulate(
+ )
+
+/*++
+
+Routine Description:
+
+ This routine causes the simulation of intel instructions to start.
+
+Arguments:
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ NTSTATUS Status;
+ VDMEVENTINFO OldEventInfo;
+ CONTEXT OldMonitorContext;
+
+ OldEventInfo = VdmTib.EventInfo;
+ OldMonitorContext = VdmTib.MonitorContext;
+
+ ContinueExecution = TRUE;
+
+ CurrentMonitorTeb = NtCurrentTeb();
+
+ VdmTib.VdmContext.ContextFlags = CONTEXT_FULL;
+
+ while (ContinueExecution) {
+
+ ASSERT(CurrentMonitorTeb == NtCurrentTeb());
+ ASSERT(InterlockedIncrement(&NumTasks) == 0);
+
+ if (*pNtVDMState & VDM_INTERRUPT_PENDING) {
+ DispatchInterrupts();
+ }
+
+ // translate MSW bits into EFLAGS
+ if ( getMSW() & MSW_PE ) {
+ VdmTib.VdmContext.EFlags &= ~EFLAGS_V86_MASK;
+ Status = FastEnterPm();
+ } else {
+ VdmTib.VdmContext.EFlags |= EFLAGS_V86_MASK;
+ Status = NtVdmControl(VdmStartExecution,NULL);
+ }
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("NTVDM: Could not start execution\n");
+#endif
+ return;
+ }
+
+ ASSERT(InterlockedDecrement(&NumTasks) < 0);
+
+#if DBG
+ if (fBreakInDebugger) {
+ fBreakInDebugger = 0;
+ DbgBreakPoint();
+ }
+#endif
+
+ // Translate Eflags value
+ ASSERT ((!((VdmTib.VdmContext.EFlags & EFLAGS_V86_MASK) &&
+ (getMSW() & MSW_PE))));
+
+ if ( VdmTib.VdmContext.EFlags & EFLAGS_V86_MASK ) {
+ VdmTib.VdmContext.EFlags &= ~EFLAGS_V86_MASK;
+ }
+
+ // bugbug does cs:eip wrap cause some kind of fault?
+ VdmTib.VdmContext.Eip += VdmTib.EventInfo.InstructionSize;
+
+ if (VdmTib.EventInfo.Event >= VdmMaxEvent) {
+#if DBG
+ DbgPrint("NTVDM: Unknown event type\n");
+ DbgBreakPoint();
+#endif
+ ContinueExecution = FALSE;
+ continue;
+ }
+
+ (*EventDispatch[VdmTib.EventInfo.Event])();
+
+ }
+
+
+ // set this back to true incase we are nested
+ ContinueExecution = TRUE;
+
+ //
+ // Restore the old Vdm tib info. This is necessary for the for the
+ // case where the application thread is suspended, and a host simulate is
+ // performed from another thread
+ //
+
+ VdmTib.EventInfo = OldEventInfo;
+ VdmTib.MonitorContext = OldMonitorContext;
+}
+
+
+VOID
+host_unsimulate(
+ )
+
+/*++
+
+Routine Description:
+
+ This routine causes execution of instructions in a VDM to stop.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ContinueExecution = FALSE;
+
+}
+
+
+VOID
+EventVdmIo(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function calls the appropriate io simulation routine.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if (VdmTib.EventInfo.IoInfo.Size == 1) {
+ if (VdmTib.EventInfo.IoInfo.Read) {
+ inb(VdmTib.EventInfo.IoInfo.PortNumber,(half_word *)&(VdmTib.VdmContext.Eax));
+ } else {
+ outb(VdmTib.EventInfo.IoInfo.PortNumber,getAL());
+ }
+ } else if (VdmTib.EventInfo.IoInfo.Size == 2) {
+ if (VdmTib.EventInfo.IoInfo.Read) {
+ inw(VdmTib.EventInfo.IoInfo.PortNumber,(word *)&(VdmTib.VdmContext.Eax));
+ } else {
+ outw(VdmTib.EventInfo.IoInfo.PortNumber,getAX());
+ }
+ }
+#if DBG
+ else {
+ DbgPrint(
+ "NtVdm: Unimplemented IO size %d\n",
+ VdmTib.EventInfo.IoInfo.Size
+ );
+ DbgBreakPoint();
+ }
+#endif
+}
+
+VOID
+EventVdmStringIo(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function calls the appropriate io simulation routine.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVDMSTRINGIOINFO pvsio;
+ PUSHORT pIndexRegister;
+ USHORT Index;
+
+ // WARNING no 32 bit address support
+
+ pvsio = &VdmTib.EventInfo.StringIoInfo;
+
+ if (pvsio->Size == 1) {
+ if (pvsio->Read) {
+ insb((io_addr)pvsio->PortNumber,
+ (half_word *)Sim32GetVDMPointer(pvsio->Address, 1, ISPESET),
+ (word)pvsio->Count
+ );
+ pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Edi;
+ } else {
+ outsb((io_addr)pvsio->PortNumber,
+ (half_word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET),
+ (word)pvsio->Count
+ );
+ pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Esi;
+ }
+ } else if (pvsio->Size == 2) {
+ if (pvsio->Read) {
+ insw((io_addr)pvsio->PortNumber,
+ (word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET),
+ (word)pvsio->Count
+ );
+ pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Edi;
+ } else {
+ outsw((io_addr)pvsio->PortNumber,
+ (word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET),
+ (word)pvsio->Count
+ );
+ pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Esi;
+ }
+ } else {
+#if DBG
+ DbgPrint(
+ "NtVdm: Unimplemented IO size %d\n",
+ VdmTib.EventInfo.IoInfo.Size
+ );
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+ if (getDF()) {
+ Index = *pIndexRegister - (USHORT)(pvsio->Count * pvsio->Size);
+ }
+ else {
+ Index = *pIndexRegister + (USHORT)(pvsio->Count * pvsio->Size);
+ }
+
+ *pIndexRegister = Index;
+
+ if (pvsio->Rep) {
+ (USHORT)VdmTib.VdmContext.Ecx = 0;
+ }
+
+
+}
+
+VOID
+EventVdmIntAck(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called each time we have returned to monitor context
+ to dispatch interrupts. Its function is to check for AutoEoi and call
+ the ica to do a nonspecific eoi, when the ica adapter is in AEOI mode.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ int line;
+ int adapter;
+
+ if (VdmTib.EventInfo.IntAckInfo) {
+ if (VdmTib.EventInfo.IntAckInfo & VDMINTACK_SLAVE)
+ adapter = 1;
+ else
+ adapter = 0;
+ line = -1;
+
+ host_ica_lock();
+ ica_eoi(adapter,
+ &line,
+ (int)(VdmTib.EventInfo.IntAckInfo & VDMINTACK_RAEOIMASK)
+ );
+ host_ica_unlock();
+ }
+}
+
+
+VOID
+EventVdmBop(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine dispatches to the appropriate bop handler
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if (VdmTib.EventInfo.BopNumber > MAX_BOP) {
+#if DBG
+ DbgPrint(
+ "NtVdm: Invalid BOP %lx\n",
+ VdmTib.EventInfo.BopNumber
+ );
+#endif
+ ContinueExecution = FALSE;
+ } else {
+#if DBG
+ if (fShowBop) {
+ DbgPrint("Ntvdm cpu_simulate : bop dispatch %x,%x\n",
+ VdmTib.EventInfo.BopNumber,
+ (ULONG)(*((UCHAR *)Sim32GetVDMPointer(
+ (VdmTib.VdmContext.SegCs << 16) | VdmTib.VdmContext.Eip,
+ 1,
+ ISPESET)))
+ );
+ }
+#endif
+ (*BIOS[VdmTib.EventInfo.BopNumber])();
+ CurrentMonitorTeb = NtCurrentTeb();
+ }
+}
+
+VOID
+EventVdmError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine prints a message(debug only), and exits the vdm
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+#if DBG
+ DbgPrint(
+ "NtVdm: Error code %lx\n",
+ VdmTib.EventInfo.ErrorStatus
+ );
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ ContinueExecution = FALSE;
+}
+
+VOID
+EventVdmIrq13(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine simulates an IRQ 13 to the vdm
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if (!IRQ13BeingHandled) {
+ IRQ13BeingHandled = TRUE;
+ ica_hw_interrupt(
+ ICA_SLAVE,
+ 5,
+ 1
+ );
+ }
+}
+
+
+VOID
+EventVdmMemAccess(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine will call the page fault handler routine which
+ is common to both x86 and mips.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ // RWMode is 0 if read fault or 1 if write fault.
+
+ DispatchPageFault(
+ VdmTib.EventInfo.FaultInfo.FaultAddr,
+ VdmTib.EventInfo.FaultInfo.RWMode
+ );
+ CurrentMonitorTeb = NtCurrentTeb();
+}
+
+// Get and Set routines for intel registers.
+
+ULONG getEAX (VOID) { return (VdmTib.VdmContext.Eax); }
+USHORT getAX (VOID) { return ((USHORT)(VdmTib.VdmContext.Eax)); }
+UCHAR getAL (VOID) { return ((BYTE)(VdmTib.VdmContext.Eax)); }
+UCHAR getAH (VOID) { return ((BYTE)(VdmTib.VdmContext.Eax >> 8)); }
+ULONG getEBX (VOID) { return (VdmTib.VdmContext.Ebx); }
+USHORT getBX (VOID) { return ((USHORT)(VdmTib.VdmContext.Ebx)); }
+UCHAR getBL (VOID) { return ((BYTE)(VdmTib.VdmContext.Ebx)); }
+UCHAR getBH (VOID) { return ((BYTE)(VdmTib.VdmContext.Ebx >> 8)); }
+ULONG getECX (VOID) { return (VdmTib.VdmContext.Ecx); }
+USHORT getCX (VOID) { return ((USHORT)(VdmTib.VdmContext.Ecx)); }
+UCHAR getCL (VOID) { return ((BYTE)(VdmTib.VdmContext.Ecx)); }
+UCHAR getCH (VOID) { return ((BYTE)(VdmTib.VdmContext.Ecx >> 8)); }
+ULONG getEDX (VOID) { return (VdmTib.VdmContext.Edx); }
+USHORT getDX (VOID) { return ((USHORT)(VdmTib.VdmContext.Edx)); }
+UCHAR getDL (VOID) { return ((BYTE)(VdmTib.VdmContext.Edx)); }
+UCHAR getDH (VOID) { return ((BYTE)(VdmTib.VdmContext.Edx >> 8)); }
+ULONG getESP (VOID) { return (VdmTib.VdmContext.Esp); }
+USHORT getSP (VOID) { return ((USHORT)VdmTib.VdmContext.Esp); }
+ULONG getEBP (VOID) { return (VdmTib.VdmContext.Ebp); }
+USHORT getBP (VOID) { return ((USHORT)VdmTib.VdmContext.Ebp); }
+ULONG getESI (VOID) { return (VdmTib.VdmContext.Esi); }
+USHORT getSI (VOID) { return ((USHORT)VdmTib.VdmContext.Esi); }
+ULONG getEDI (VOID) { return (VdmTib.VdmContext.Edi); }
+USHORT getDI (VOID) { return ((USHORT)VdmTib.VdmContext.Edi); }
+ULONG getEIP (VOID) { return (VdmTib.VdmContext.Eip); }
+USHORT getIP (VOID) { return ((USHORT)VdmTib.VdmContext.Eip); }
+USHORT getCS (VOID) { return ((USHORT)VdmTib.VdmContext.SegCs); }
+USHORT getSS (VOID) { return ((USHORT)VdmTib.VdmContext.SegSs); }
+USHORT getDS (VOID) { return ((USHORT)VdmTib.VdmContext.SegDs); }
+USHORT getES (VOID) { return ((USHORT)VdmTib.VdmContext.SegEs); }
+USHORT getFS (VOID) { return ((USHORT)VdmTib.VdmContext.SegFs); }
+USHORT getGS (VOID) { return ((USHORT)VdmTib.VdmContext.SegGs); }
+ULONG getCF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_CARRY) ? 1 : 0); }
+ULONG getPF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_PARITY) ? 1 : 0); }
+ULONG getAF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_AUXILIARY) ? 1 : 0); }
+ULONG getZF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_ZERO) ? 1 : 0); }
+ULONG getSF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_SIGN) ? 1 : 0); }
+ULONG getTF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_TRAP) ? 1 : 0); }
+ULONG getIF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_INTERRUPT) ? 1 : 0); }
+ULONG getDF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_DIRECTION) ? 1 : 0); }
+ULONG getOF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_OVERFLOW) ? 1 : 0); }
+USHORT getMSW (VOID) { return ((USHORT)IntelMSW); }
+USHORT getSTATUS(VOID){ return (USHORT)VdmTib.VdmContext.EFlags; }
+ULONG getEFLAGS(VOID) { return VdmTib.VdmContext.EFlags; }
+USHORT getFLAGS(VOID) { return (USHORT)VdmTib.VdmContext.EFlags; }
+
+VOID setEAX (ULONG val) {
+ VdmTib.VdmContext.Eax = val;
+}
+
+VOID setAX (USHORT val) {
+ VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setAH (UCHAR val) {
+ VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFF00FF) |
+ ((ULONG)(val << 8) & 0x0000FF00);
+}
+
+VOID setAL (UCHAR val) {
+ VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFFFF00) |
+ ((ULONG)val & 0x000000FF);
+}
+
+VOID setEBX (ULONG val) {
+ VdmTib.VdmContext.Ebx = val ;
+}
+
+VOID setBX (USHORT val) {
+ VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setBH (UCHAR val) {
+ VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFF00FF) |
+ ((ULONG)(val << 8) & 0x0000FF00);
+}
+
+VOID setBL (UCHAR val) {
+ VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFFFF00) |
+ ((ULONG)val & 0x000000FF);
+}
+
+VOID setECX (ULONG val) {
+ VdmTib.VdmContext.Ecx = val ;
+}
+
+VOID setCX (USHORT val) {
+ VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setCH (UCHAR val) {
+ VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFF00FF) |
+ ((ULONG)(val << 8) & 0x0000FF00);
+}
+
+VOID setCL (UCHAR val) {
+ VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFFFF00) |
+ ((ULONG)val & 0x000000FF);
+}
+
+VOID setEDX (ULONG val) {
+ VdmTib.VdmContext.Edx = val ;
+}
+
+VOID setDX (USHORT val) {
+ VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setDH (UCHAR val) {
+ VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFF00FF) |
+ ((ULONG)(val << 8) & 0x0000FF00);
+}
+
+VOID setDL (UCHAR val) {
+ VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFFFF00) |
+ ((ULONG)val & 0x000000FF);
+}
+
+VOID setESP (ULONG val) {
+ VdmTib.VdmContext.Esp = val ;
+}
+
+VOID setSP (USHORT val) {
+ VdmTib.VdmContext.Esp = (VdmTib.VdmContext.Esp & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setEBP (ULONG val) {
+ VdmTib.VdmContext.Ebp = val;
+}
+
+VOID setBP (USHORT val) {
+ VdmTib.VdmContext.Ebp = (VdmTib.VdmContext.Ebp & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setESI (ULONG val) {
+ VdmTib.VdmContext.Esi = val ;
+}
+
+VOID setSI (USHORT val) {
+ VdmTib.VdmContext.Esi = (VdmTib.VdmContext.Esi & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+VOID setEDI (ULONG val) {
+ VdmTib.VdmContext.Edi = val ;
+}
+
+VOID setDI (USHORT val) {
+ VdmTib.VdmContext.Edi = (VdmTib.VdmContext.Edi & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setEIP (ULONG val) {
+ VdmTib.VdmContext.Eip = val ;
+}
+
+VOID setIP (USHORT val) {
+ VdmTib.VdmContext.Eip = (VdmTib.VdmContext.Eip & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setCS (USHORT val) {
+ VdmTib.VdmContext.SegCs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setSS (USHORT val) {
+ VdmTib.VdmContext.SegSs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setDS (USHORT val) {
+ VdmTib.VdmContext.SegDs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setES (USHORT val) {
+ VdmTib.VdmContext.SegEs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setFS (USHORT val) {
+ VdmTib.VdmContext.SegFs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setGS (USHORT val) {
+ VdmTib.VdmContext.SegGs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setCF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_CARRY) |
+ (((ULONG)val << FLG_CARRY_BIT) & FLG_CARRY);
+}
+
+VOID setPF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_PARITY) |
+ (((ULONG)val << FLG_PARITY_BIT) & FLG_PARITY);
+}
+
+VOID setAF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_AUXILIARY) |
+ (((ULONG)val << FLG_AUXILIARY_BIT) & FLG_AUXILIARY);
+}
+
+VOID setZF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_ZERO) |
+ (((ULONG)val << FLG_ZERO_BIT) & FLG_ZERO);
+}
+
+VOID setSF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_SIGN) |
+ (((ULONG)val << FLG_SIGN_BIT) & FLG_SIGN);
+}
+
+VOID setIF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_INTERRUPT) |
+ (((ULONG)val << FLG_INTERRUPT_BIT) & FLG_INTERRUPT);
+}
+
+VOID setDF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_DIRECTION) |
+ (((ULONG)val << FLG_DIRECTION_BIT) & FLG_DIRECTION);
+}
+
+VOID setOF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_OVERFLOW) |
+ (((ULONG)val << FLG_OVERFLOW_BIT) & FLG_OVERFLOW);
+}
+
+VOID setMSW (USHORT val) {
+ IntelMSW = val ;
+}
+
+VOID setSTATUS(USHORT val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & 0xFFFF0000) | val;
+}
+//
+// The following is a private register function
+//
+
+ULONG getPE(){
+ return((IntelMSW & MSW_PE) ? 1 : 0);
+}
+
+
+PX86CONTEXT
+getIntelRegistersPointer(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Return Address on Intel Registers for WOW Fast Access
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Pointer to Intel Registers x86 Context Record
+
+
+--*/
+{
+ return &(VdmTib.VdmContext);
+}
+
+
+
+BOOLEAN MonitorInitializePrinterInfo(
+ WORD Ports,
+ PWORD PortTable,
+ PUCHAR State,
+ PUCHAR Control,
+ PUCHAR Status,
+ PUCHAR HostState)
+{
+ int i;
+
+ ASSERT (Ports == 3);
+ ASSERT (Status != NULL);
+
+ // only do this if the structure has not been initialized -- meaning
+ // the pointers can be set once.
+ if (NULL == VdmTib.PrinterInfo.prt_Status) {
+
+ VdmTib.PrinterInfo.prt_PortAddr[0] = PortTable[0];
+ VdmTib.PrinterInfo.prt_PortAddr[1] = PortTable[1];
+ VdmTib.PrinterInfo.prt_PortAddr[2] = PortTable[2];
+
+ VdmTib.PrinterInfo.prt_Handle[0] =
+ VdmTib.PrinterInfo.prt_Handle[1] =
+ VdmTib.PrinterInfo.prt_Handle[2] = NULL;
+
+
+ // primarily for dongle
+ VdmTib.PrinterInfo.prt_BytesInBuffer[0] =
+ VdmTib.PrinterInfo.prt_BytesInBuffer[1] =
+ VdmTib.PrinterInfo.prt_BytesInBuffer[2] = 0;
+
+ // primarily for simulating printer status read in kernel
+ VdmTib.PrinterInfo.prt_State = State;
+ VdmTib.PrinterInfo.prt_Control = Control;
+ VdmTib.PrinterInfo.prt_Status = Status;
+ VdmTib.PrinterInfo.prt_HostState = HostState;
+
+
+ // deal with mode carefully. VDD may have hooked printer ports
+ // before we get here. If the mode is undefined, we can
+ // safely initialize it to our default, otherwise, just leave
+ // it alone.
+ for (i = 0; i < 3; i++) {
+ if (PRT_MODE_NO_SIMULATION == VdmTib.PrinterInfo.prt_Mode[i])
+ VdmTib.PrinterInfo.prt_Mode[i] = PRT_MODE_SIMULATE_STATUS_PORT;
+ }
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+BOOLEAN MonitorEnablePrinterDirectAccess(WORD adapter, HANDLE handle, BOOLEAN Enable)
+{
+ ASSERT(VDM_NUMBER_OF_LPT > adapter);
+ if (Enable) {
+ // if the adapter has been allocated by a third party VDD,
+ // can't do direct io.
+ if (PRT_MODE_VDD_CONNECTED != VdmTib.PrinterInfo.prt_Mode[adapter]) {
+ VdmTib.PrinterInfo.prt_Mode[adapter] = PRT_MODE_DIRECT_IO;
+ VdmTib.PrinterInfo.prt_Handle[adapter] = handle;
+ // NtVdmControl(VdmPrinterDirectIoOpen, &adapter);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ else {
+ // disabling direct i/o. reset it back to status port simulation
+ if (VdmTib.PrinterInfo.prt_Handle[adapter] == handle) {
+ NtVdmControl(VdmPrinterDirectIoClose, &adapter);
+ VdmTib.PrinterInfo.prt_Mode[adapter] = PRT_MODE_SIMULATE_STATUS_PORT;
+ VdmTib.PrinterInfo.prt_Handle[adapter] = NULL;
+ VdmTib.PrinterInfo.prt_BytesInBuffer[adapter] = 0;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+}
+
+BOOLEAN MonitorVddConnectPrinter(WORD Adapter, HANDLE hVdd, BOOLEAN Connect)
+{
+ if (VDM_NUMBER_OF_LPT <= Adapter)
+ return FALSE;
+ if (Connect) {
+ VdmTib.PrinterInfo.prt_Mode[Adapter] = PRT_MODE_VDD_CONNECTED;
+ VdmTib.PrinterInfo.prt_Handle[Adapter] = hVdd;
+ return TRUE;
+ }
+ else {
+ if (hVdd == VdmTib.PrinterInfo.prt_Handle[Adapter]) {
+ VdmTib.PrinterInfo.prt_Mode[Adapter] = PRT_MODE_SIMULATE_STATUS_PORT;
+ VdmTib.PrinterInfo.prt_Handle[Adapter] = NULL;
+ return TRUE;
+ }
+ else return FALSE;
+ }
+}
+
+BOOLEAN MonitorPrinterWriteData(WORD Adapter, BYTE Value)
+{
+ USHORT BytesInBuffer;
+
+ ASSERT(VDM_NUMBER_OF_LPT > Adapter);
+ BytesInBuffer = VdmTib.PrinterInfo.prt_BytesInBuffer[Adapter];
+ VdmTib.PrinterInfo.prt_Buffer[Adapter][BytesInBuffer] = Value;
+ VdmTib.PrinterInfo.prt_BytesInBuffer[Adapter]++;
+
+ return TRUE;
+}