|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
dpmi32.c
Abstract:
This function contains common code such as the dpmi dispatcher, and handling for the initialization of the dos extender.
Author:
Dave Hastings (daveh) 24-Nov-1992
Revision History:
Neil Sandlin (neilsa) 31-Jul-1995 - Updates for the 486 emulator
--*/ #include "precomp.h"
#pragma hdrstop
#include "softpc.h"
#include <intapi.h>
//
// DPMI dispatch table
//
VOID (*DpmiDispatchTable[MAX_DPMI_BOP_FUNC])(VOID) = { DpmiInitDosxRM, // 0
DpmiInitDosx, // 1
DpmiInitLDT, // 2
DpmiGetFastBopEntry, // 3
DpmiInitIDT, // 4
DpmiInitExceptionHandlers, // 5
DpmiInitApp, // 6
DpmiTerminateApp, // 7
DpmiDpmiInUse, // 8
DpmiDpmiNoLongerInUse, // 9
switch_to_protected_mode, // 10 (DPMISwitchToProtectedMode)
switch_to_real_mode, // 11 (DPMISwitchToRealMode)
DpmiSetAltRegs, // 12
DpmiIntHandlerIret16, // 13
DpmiIntHandlerIret32, // 14
DpmiFaultHandlerIret16, // 15
DpmiFaultHandlerIret32, // 16
DpmiUnhandledExceptionHandler, // 17
DpmiRMCallBackCall, // 18
DpmiReflectIntrToPM, // 19
DpmiReflectIntrToV86, // 20
DpmiInitPmStackInfo, // 21
DpmiVcdPmSvcCall32, // 22
DpmiSetDescriptorEntry, // 23
DpmiResetLDTUserBase, // 24
DpmiXlatInt21Call, // 25
DpmiInt31Entry, // 26
DpmiInt31Call, // 27
DpmiHungAppIretAndExit // 28
};
VOID DpmiDispatch( VOID ) /*++
Routine Description:
This function dispatches to the appropriate subfunction
Arguments:
None
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; ULONG Index; static USHORT NestLevel = 0;
Index = *(PUCHAR)VdmMapFlat(getCS(), getIP(), getMODE());
setIP((getIP() + 1)); // take care of subfn.
DBGTRACE(VDMTR_TYPE_DPMI | DPMI_DISPATCH_ENTRY, NestLevel++, Index);
if (Index >= MAX_DPMI_BOP_FUNC) { //BUGBUG IMHO, we should fatal exit here
#if DBG
DbgPrint("NtVdm: Invalid DPMI BOP %lx\n", Index); #endif
return; }
(*DpmiDispatchTable[Index])();
DBGTRACE(VDMTR_TYPE_DPMI | DPMI_DISPATCH_EXIT, --NestLevel, Index); }
#if 0 // This probably is for private debugging only
VOID DpmiIllegalFunction( VOID ) /*++
Routine Description:
This routine ignores any Dpmi bops that are not implemented on a particular platform. It is called through the DpmiDispatchTable by #define'ing individual entries to this function. See dpmidata.h and dpmidatr.h.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; char szFormat[] = "NtVdm: Invalid DPMI BOP from CS:IP %4.4x:%4.4x (%s mode), could be i386 dosx.exe.\n"; char szMsg[sizeof(szFormat)+64];
wsprintf( szMsg, szFormat, (int)getCS(), (int)getIP(), (getMSW() & MSW_PE) ? "prot" : "real" );
OutputDebugString(szMsg); } #endif
VOID DpmiInitDosxRM( VOID ) /*++
Routine Description:
This routine handles the RM initialization bop for the dos extender. It get the addresses of the structures that the dos extender and 32 bit code share.
Arguments:
None
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PDOSX_RM_INIT_INFO pdi;
ASSERT(!(getMSW() & MSW_PE));
pdi = (PDOSX_RM_INIT_INFO) VdmMapFlat(getDS(), getSI(), VDM_V86);
DosxStackFrameSize = pdi->StackFrameSize;
RmBopFe = pdi->RmBopFe; PmBopFe = pdi->PmBopFe;
DosxStackSegment = pdi->StackSegment; DosxRmCodeSegment = pdi->RmCodeSegment; DosxRmCodeSelector = pdi->RmCodeSelector;
DosxFaultHandlerIret = pdi->pFaultHandlerIret; DosxFaultHandlerIretd = pdi->pFaultHandlerIretd; DosxIntHandlerIret = pdi->pIntHandlerIret; DosxIntHandlerIretd = pdi->pIntHandlerIretd; DosxIret = pdi->pIret; DosxIretd = pdi->pIretd; DosxRMReflector = pdi->RMReflector;
RMCallBackBopOffset = pdi->RMCallBackBopOffset; RMCallBackBopSeg = pdi->RMCallBackBopSeg; PMReflectorSeg = pdi->PMReflectorSeg;
DosxRmSaveRestoreState= pdi->RmSaveRestoreState; DosxPmSaveRestoreState= pdi->PmSaveRestoreState; DosxRmRawModeSwitch = pdi->RmRawModeSwitch; DosxPmRawModeSwitch = pdi->PmRawModeSwitch;
DosxVcdPmSvcCall = pdi->VcdPmSvcCall; DosxMsDosApi = pdi->MsDosApi; DosxXmsControl = pdi->XmsControl;
DosxHungAppExit = pdi->HungAppExit;
//
// Load the temporary LDT info (updated in DpmiInitLDT())
//
Ldt = VdmMapFlat(pdi->InitialLDTSeg, 0, VDM_V86); LdtMaxSel = pdi->InitialLDTSize;
#ifdef _X86_
//
// On x86 platforms, return the fast bop address
//
GetFastBopEntryAddress(&((PVDM_TIB)NtCurrentTeb()->Vdm)->VdmContext); #endif
}
VOID DpmiInitDosx( VOID ) /*++
Routine Description:
This routine handles the PM initialization bop for the dos extender. It get the addresses of the structures that the dos extender and 32 bit code share.
Note: These values are initialized here since they are FLAT pointers, and are thus not easily computed at the time of InitDosxRM.
Arguments:
None
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PDOSX_INIT_INFO pdi;
ASSERT((getMSW() & MSW_PE));
pdi = (PDOSX_INIT_INFO) VdmMapFlat(getDS(), getSI(), VDM_PM);
SmallXlatBuffer = Sim32GetVDMPointer(pdi->pSmallXlatBuffer, 4, TRUE); LargeXlatBuffer = Sim32GetVDMPointer(pdi->pLargeXlatBuffer, 4, TRUE); DosxDtaBuffer = Sim32GetVDMPointer(pdi->pDtaBuffer, 4, TRUE);
DosxStackFramePointer = (PWORD16)((PULONG)Sim32GetVDMPointer( pdi->pStackFramePointer, 4, TRUE));
}
VOID DpmiInitApp( VOID ) /*++
Routine Description:
This routine handles any necessary 32 bit initialization for extended applications.
Arguments:
None.
Return Value:
None.
Notes:
This function contains a number of 386 specific things. Since we are likely to expand the 32 bit portions of DPMI in the future, this makes more sense than duplicating the common portions another file.
--*/ { DECLARE_LocalVdmContext; PWORD16 Data;
Data = (PWORD16) VdmMapFlat(getSS(), getSP(), VDM_PM);
// Only 1 bit defined in dpmi
CurrentAppFlags = getAX() & DPMI_32BIT; #ifdef _X86_
((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.Flags = CurrentAppFlags; if (CurrentAppFlags & DPMI_32BIT) { *pNtVDMState |= VDM_32BIT_APP; } #endif
DpmiInitRegisterSize();
CurrentDta = Sim32GetVDMPointer( *(PDWORD16)(Data), 1, TRUE );
CurrentDosDta = (PUCHAR) NULL;
CurrentDtaOffset = *Data; CurrentDtaSelector = *(Data + 1); CurrentPSPSelector = *(Data + 2); CurrentPSPXmem = 0; }
VOID DpmiTerminateApp( VOID ) /*++
Routine Description:
This routine handles any necessary 32 bit destruction for extended applications.
Arguments:
None.
Return Value:
None.
Notes:
--*/ { DECLARE_LocalVdmContext;
DpmiFreeAppXmem(getDX()); CurrentPSPXmem = 0; // DpmiFreeAppXmem should also zero it
CurrentPSPSelector = getCX(); // indicate no running app
}
VOID DpmiEnableIntHooks( VOID )
/*++
Routine Description:
This routine is called very early on in NTVDM initialization. It gives the dpmi code a chance to do some startup stuff before any client code has run.
This is not called via bop.
Arguments:
None
Return Value:
None.
--*/
{ #ifndef _X86_
IntelBase = (ULONG) VdmMapFlat(0, 0, VDM_V86); VdmInstallHardwareIntHandler(DpmiHwIntHandler); VdmInstallSoftwareIntHandler(DpmiSwIntHandler); VdmInstallFaultHandler(DpmiFaultHandler); #endif // _X86_
}
#ifdef DBCS
VOID DpmiSwitchToDosxStack( VOID ) { DECLARE_LocalVdmContext;
SWITCH_TO_DOSX_RMSTACK(); } VOID DpmiSwitchFromDosxStack( VOID ) { DECLARE_LocalVdmContext;
SWITCH_FROM_DOSX_RMSTACK(); } #endif
|