diff options
Diffstat (limited to 'private/mvdm/v86/monitor/i386/monitor.c')
-rw-r--r-- | private/mvdm/v86/monitor/i386/monitor.c | 1135 |
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; +} |