|
|
PAGE ,132 TITLE DXSTRT.ASM -- Dos Extender Startup Code
; Copyright (c) Microsoft Corporation 1988-1991. All Rights Reserved.
;**************************************************************** ;* * ;* DXSTRT.ASM - Dos Extender Startup Code * ;* * ;**************************************************************** ;* * ;* Module Description: * ;* * ;* This module contains the executive initialization code for * ;* the Dos Extender. The module DXBOOT.ASM contains the code * ;* specific to starting up the Dos Extender. The module * ;* DXINIT.ASM contains the code specific to starting up the * ;* child program of the Dos Extender. The code in these * ;* two modules is discarded at the end of the initialization. * ;* The code in this module calls the initialization routines * ;* in the other to init modules, and then performs the final * ;* juggling of things to throw away the low memory init code, * ;* and transfer control to start up the child program. * ;* * ;**************************************************************** ;* Revision History: * ;* * ;* 01/09/91 amitc At exit time Co-Processor being reset * ;* 08/08/90 earleh DOSX and client privilege ring determined * ;* by equate in pmdefs.inc * ;* 12/08/89 jimmat Added call to reenable EMM driver. * ;* 08/29/89 jimmat Restores Int 2Fh vector at exit * ;* 08/20/89 jimmat Removed A20 code, since HIMEM version 2.07 * ;* A20 code now works properly. * ;* 06/28/89 jimmat Now calls OEM layer instead of NetMapper * ;* 06/16/89 jimmat Implemented Windows/386 startup/exit Int * ;* 2Fh calls and ifdef'd combined EXE code * ;* 05/17/89 jimmat ChildTerminationHandler sets its SS:SP * ;* 04/18/89 jimmat Added calls to init/term NetBIOS mapper * ;* 03/28/89 jimmat Incorporated bug fix from GeneA related * ;* to nested GP faults in ChildTermHandler * ;* 03/11/89 jimmat Added support for TSS & LDT * ;* 03/07/89 jimmat converted to use WDEB386 * ;* 02/27/89 (GeneA): shrink initial memory block size on entry * ;* 02/25/89 (GeneA): added support for combined exe file where * ;* the Dos Extender and the child reside in the same exe * ;* file. * ;* 02/17/89 (GeneA): fixed error termination code for startup * ;* errors that occur while in protected mode * ;* 02/14/89 (GeneA): added code to reduce size of real mode * ;* code segment to throw away initialization code. * ;* 01/31/89 (GeneA): created by copying code from the old * ;* DXINIT.ASM * ;* 18-Dec-1992 sudeepb Changed cli/sti to faster FCLI/FSTI ;****************************************************************
.286p
; ------------------------------------------------------- ; INCLUDE FILE DEFINITIONS ; -------------------------------------------------------
.sall .xlist include segdefs.inc include gendefs.inc include pmdefs.inc
include hostdata.inc include dpmi.inc include intmac.inc .list
; ------------------------------------------------------- ; GENERAL SYMBOL DEFINITIONS ; -------------------------------------------------------
WIN386_INIT equ 1605h ;Win/386 startup Int 2Fh WIN386_EXIT equ 1606h ;Win/386 shutdown Int 2Fh
WIN386_DOSX equ 0001h ;Win/386 init/exit really DOSX flag
; ------------------------------------------------------- ; EXTERNAL SYMBOL DEFINITIONS ; -------------------------------------------------------
extrn InitDosExtender:NEAR extrn RestoreRMIntrVectors:NEAR extrn SaveRMIntrVectors:NEAR extrn EnterRealMode:NEAR extrn EnterProtectedMode:NEAR extrn InitializeOEM:NEAR extrn TerminateOEM:NEAR externNP NSetSegmentAccess extrn DupSegmentDscr:NEAR
extrn EMMEnable:NEAR
ifdef WOW_x86 externFP NSetSegmentDscr else externFP NSetGDTSegmentDscr ENDIF; WOW_x86
extrn PMIntr19:NEAR extrn PMIntr13:NEAR extrn PMIntr31:NEAR extrn PMIntr28:NEAR extrn PMIntr25:NEAR extrn PMIntr26:NEAR extrn PMIntr4B:NEAR extrn PMIntrDos:NEAR extrn PMIntrMisc:NEAR extrn PMIntrVideo:NEAR extrn PMIntrMouse:NEAR extrn PMIntrIgnore:NEAR extrn PMIntrEntryVector:NEAR extrn PMFaultEntryVector:NEAR ifdef NEC_98 ; extrn PMIntr11dummy:NEAR extrn PMIntrPrinter:NEAR extrn PMIntrCalTi:NEAR extrn PMIntrGraph:NEAR endif ;NEC_98 ;
; ------------------------------------------------------- ; DATA SEGMENT DEFINITIONS ; -------------------------------------------------------
; -------------------------------------------------------
DXDATA segment extrn A20EnableCount:WORD extrn lpfnUserMouseHandler:DWORD extrn lpfnUserPointingHandler:DWORD extrn f286_287:BYTE
extrn cDPMIClients:WORD extrn selCurrentHostData:WORD extrn segCurrentHostData:WORD
ifdef WOW_x86 extrn FastBop:fword endif extrn DpmiFlags:WORD
org 0
public rgwStack,npEHStackLimit,npEHStacklet, selEHStack, ; ; Pmode fault handler stack used during initialization only. ; dw 80h dup (?) rgwStack label word
; ; This is the stack area used while running in the interrupt reflector. ; This is divided up into a number of stack frames to allow reentrant ; execution of the interrupt reflector. The stack pointer pbReflStack ; indicates the current stack frame to use. Each entry into the interrupt ; reflector decrements this variable by the size of the stack frame, and ; each exit from the interrupt reflector increments it.
C_STKFRAME = 36 CB_REFLSTACK = C_STKFRAME * CB_STKFRAME
if DEBUG ;-------------------------------------------------------- public StackGuard StackGuard dw 1022h ;unlikely value to check for stk overrun endif ;--------------------------------------------------------
public pbReflStack,bReflStack if DBG bReflStack db CB_REFLSTACK dup (0AAh) else bReflStack db CB_REFLSTACK dup (?) endif
;---------------------------------------------------------------------------- ; The following stack is used for hw interrupts while booting where ; the kernel or ntvdm switches the stack before an interrupt is reflected. ;---------------------------------------------------------------------------- CB_HWINTRSTACK = 1000h if DBG bHwIntrStack db CB_HWINTRSTACK dup (0AAh) else bHwIntrStack db CB_HWINTRSTACK dup (?) endif public pbHwIntrStack pbHwIntrStack dw bHwIntrStack + CB_HWINTRSTACK
pbReflStack dw bReflStack + CB_REFLSTACK
npEHStackLimit dw offset DGROUP:rgwStack npEHStacklet dw offset DGROUP:rgwStack selEHStack dw 0
public cdscGDTMax, selGDTFree, segGDT, selGDT
cdscGDTMax dw CDSCGDTDEFAULT
selGDTFree dw ? ;head of list of free descriptors in GDT
segGDT dw 0 ;real mode paragraph address of the GDT ; This variable always stores the real mode ; paragraph address
selGDT dw 0 ;current mode segment/selector for the GDT ; segment. This variable holds the real ; mode paragraph address during initialization ; and then holds the protected mode selector ; when running in protected mode.
public bpGDT, bpGDTcb, bpGDTbase
bpGDT label fword bpGDTcb dw ? bpGDTbase dd ?
public segIDT, selIDT
segIDT dw 0 selIDT dw 0
public bpIDT, bpIDTcb, bpIDTbase
bpIDT label fword bpIDTcb dw ? bpIDTbase dd ?
public bpRmIVT
bpRmIVT dq 0FFFFh ;This is the segment descriptor for the real ; mode interrupt vector table.
public lpfnXMSFunc
lpfnXMSFunc dd 0 ;far pointer to XMS memory driver entry point
public idCpuType
idCpuType dw 0
public segPSP, selPSP
segPSP dw ? ;segment address of Dos Extender PSP selPSP dw ? ;selector for Dos Extender PSP ; code during processing of GP faults
public selPSPChild, segPSPChild
segPSPChild dw ? ;real mode segment address of child's PSP ; note the following in 1, so that in low mem heap management, we can use ; selPSPChild to mark the owner of the memory. selPSPChild dw 1 ;selector of child program's PSP
public DtaSegment, DtaOffset, DtaSelector DtaSegment dw 0 DtaSelector dw 0 DtaOffset dw 0
public regChildSP, regChildSS, regChildIP, regChildCS
regChildSP dw ? ;initial user stack pointer from exe file regChildSS dw ? ;initial user stack segment from exe file regChildIP dw ? ;initial user program counter from exe file regChildCS dw ? ;initial user code segment from exe file
public hmemDOSX
hmemDOSX dw 0
IFDEF ROM public segDXCode, segDXData
segDXCode dw ? ;holds real mode paragraph address ; of the code segment segDXData dw ? ;holds real mode paragraph address ; of the data segment ENDIF
ifdef NEC_98 public fPCH98
fPCH98 db 0 ;NZ if running on a Micro Channel system
public fNHmode
fNHmode db 0 ;NZ if running on a Hmode system endif ;!NEC_98 public fFaultAbort, ExitCode
fFaultAbort db 0 ;NZ if terminating due to unrecoverable fault ExitCode db 0FFh ;exit code to use when terminating fQuitting db 0
fEMbit db 0FFh ;MSW EM bit at startup (FF = not checked yet)
public fUsingHMA fUsingHMA db 0
; The one and only Task State Segment is here (it's too small to allocate ; a block for it in extended memory)
public sysTSS
sysTSS TSS286 <>
; After initialization is complete, the following buffers (rgbXfrBuf0 and ; rgbXfrBuf1) are used to transfer data between real mode address space ; and protected mode address space during the processing of various interrupt ; function calls. During the initialization process, these buffers are also ; used as temporary work space as described below: ; CheckCPUType uses the first 6 bytes of rgbXfrBuf0 as scratch space. ; The functions for moving the Dos Extender protected mode code segment ; and the GDT and IDT use rgbXfrBuf0 as buffer space for building a ; parameter block. The child loading code in DXINIT.ASM uses the buffer ; RELOC_BUFFER for holding the base part of the file name (name.exe portion) ; of the child exe file while determining the complete path to the child ; in the case where the child name is specified on the command line. Note, ; this buffer is also used for holding sectors from the relocation table ; while loading the program, but that occurs after the child exe file name ; has been determined. ; The child loading code in DXINIT.ASM also uses rgbXfrBuf1 to hold several ; buffers as well. The locations and purposes of these buffers are ; described in GENDEFS.INC. All of the buffers are defined with equates ; named EXEC_????? ; ; The file search logic in DXFIND.ASM assumes some parameters are setup in ; the rgbXfrBuf1 file name buffers. Some of the code was moved from ; DXINIT.ASM to DXFIND.ASM.
public rgbXfrBuf0, rgbXfrBuf1 public npXfrBuf0, npXfrBuf1
align 2
rgbXfrBuf0 db CB_XFRBUF0 dup (?) rgbXfrBuf1 db CB_XFRBUF1 dup (?)
npXfrBuf0 dw offset DGROUP:rgbXfrBuf0 npXfrBuf1 dw offset DGROUP:rgbXfrBuf1
DtaBuffer dw 128 dup (0) ; used as the dta for PM if dta changed
; Parameter block for passing to DOS EXEC call to run the child ; program. ; public exec_par_blk
exec_par_blk dw 0 cmd_off dw OFFSET EXEC_CMNDLINE cmd_seg dw DXDATA dw OFFSET EXEC_FCB0 fcb1_seg dw DXDATA dw OFFSET EXEC_FCB1 fcb2_seg dw DXDATA
; The following variables are used during reading the relocation table ; from the exe file and relocating the child program.
public fhExeFile public clpRelocItem public plpRelocItem
fhExeFile dw ? ;DOS file handle for the exe file clpRelocItem dw ? ;number of relocation items in the exe file plpRelocItem dw ? ;pointer to next relocation item in the table
szDebugHello label byte if DEBUG db 'DOSX: Beginning protected mode initialization.',13,10,0 endif db 0
FreeMem dw 0
DXDATA ends
; ------------------------------------------------------- page ; ------------------------------------------------------- ; CODE SEGMENT VARIABLES ; -------------------------------------------------------
DXCODE segment
extrn CodeEnd:NEAR extrn ER_DXINIT:BYTE extrn ER_REALMEM:BYTE extrn RMDefaultInt24Handler:FAR
public segDXCode, segDXData, selDgroup
segDXCode dw ? ;holds the real mode paragraph address ; of the code segment segDXData dw ? ;holds the real mode paragraph address ; of the data segment
selDgroup dw ? ;holds the paragraph address/selector for ; DGROUP depending on the current mode
public PrevInt2FHandler
PrevInt2FHandler dd ? ;previous real mode Int 2F handler
DXCODE ends
DXPMCODE segment
extrn CodeEndPM:NEAR
org 0
public selDgroupPM, segDXCodePM, segDXDataPM
selDgroupPM dw ? ;This variable always contains the ; data segment selector segDXCodePM dw ? ;This variable contains the paragraph ; address of the real mode code segment segDXDataPM dw ? ;This variable contains the paragraph ; address of the data segment externFP NSetSegmentDscr
DXPMCODE ends
; -------------------------------------------------------
BeginLowSegment
; ------------------------------------------------------- ; DOS EXTENDER ENTRY FUNCTION ; ------------------------------------------------------- ; ; This is the program entry point for the Dos Extender. This ; function decides if the Dos Extender is being run as a single ; time operation to extend a single program, or if it is being ; run as a TSR to wait for programs to request its services ; later on. ;
assume ds:PSPSEG,es:PSPSEG,ss:NOTHING public start
start:
; Set up the initial segment registers.
mov ax,DGROUP mov ds,ax assume ds:DGROUP
mov segPSP,es ;save the PSP segment address
mov ss,ax mov sp,offset DGROUP:rgwStack assume ss:DGROUP
; ; Set up the INT 24h handler. The default INT 24h handler fails the ; system call in progress, for DPMI compatibility. ;
push ds mov ax,cs mov ds,ax mov dx,offset DXCODE:RMDefaultInt24Handler mov ax,2524h int 21h pop ds
; Issue the Win/386 startup Int 2Fh (almost) first thing
push ds
mov ax,WIN386_INIT ;gives other PM software a chance xor bx,bx ; to disable itself, release XMS, etc. mov cx,bx mov si,bx mov ds,bx mov es,bx assume ds:NOTHING, es:NOTHING mov dx,WIN386_DOSX mov di,DXVERSION int 2Fh
pop ax ;restore ds/es DGROUP addressability mov ds,ax mov es,ax assume ds:DGROUP, es:DGROUP
jcxz Allow_Startup ;if cx still == 0, keep going (we ignore ; all the other possible return values)
mov ExitCode,2 ; otherwise we should abort now jmp RealModeCleanUp
Allow_Startup:
; Initialize the Dos Extender
call InitDosExtender ;NOTE: passes data to InitChildProgram jnc @F ; in rgbXfrBuf1 -- don't overwrite it! jmp strt88 @@:
; Save the state of the MSW EM bit (Emulate Math coprocessor), and turn ; it off (win87em wants it off).
ifndef WOW_x86 smsw ax
out1 <What to do about this?>
test al,01h ;in V86 mode? jnz @f ; can't do the lmsw if so
push ax and al,04h mov fEMbit,al pop ax and al,not 04h lmsw ax @@: endif ; WOW_x86 ; Switch the machine into protected mode.
FCLI call SaveRMIntrVectors
SwitchToProtectedMode
public DXPMInit DXPMInit LABEL BYTE
if DEBUG Trace_Out "*******************************************************************************" Trace_Out "*******************************************************************************" Trace_Out "**** ****" Trace_Out "**** THIS IS A DEBUG RELEASE THIS IS A DEBUG RELEASE ****" Trace_Out "**** ****" Trace_Out "*******************************************************************************" Trace_Out "*******************************************************************************" endif
assume ds:DGROUP,es:NOTHING
mov ax,SEL_IDT or STD_RING mov selIDT,ax mov ax,SEL_LDT_ALIAS OR STD_RING mov selGDT,ax
; Initialize the LDT now that we are in protected mode. First, set the ; contents to zero.
mov es,selGDT ; actually LDT assume es:NOTHING mov cx,cdscGDTMax IFDEF WOW mov di,GDT_SIZE sub cx,di ENDIF shl cx,2 ; CX = words in LDT segment xor ax,ax ; AX = 0 IFNDEF WOW mov di,ax ENDIF cld rep stosw ; CX = 0
dec cx ; CX = 0FFFFh
push ax push cx mov ax,es ; LDT selector lsl cx,ax ; LDT size mov di,SEL_USER and SELECTOR_INDEX DPMIBOP InitLDT pop cx pop ax
; ; Set the two scratch selectors to 64k data starting at zero. Actual ; addresses set as used. ; cCall NSetSegmentDscr,<SEL_SCR0,ax,ax,ax,cx,STD_DATA> cCall NSetSegmentDscr,<SEL_SCR1,ax,ax,ax,cx,STD_DATA> ifndef WOW_x86 mov dx,40h*16 cCall NSetGDTSegmentDscr,<040h,ax,dx,ax,cx,STD_DATA> endif
; Bop to initialize 32 bit support.
push es mov ax,SEL_DXCODE OR STD_RING mov es,ax assume es:DXCODE mov di, sp ;original stack offset
push ds push offset DGROUP:DtaBuffer push ds push offset DGROUP:pbReflStack push ds push offset DGROUP:rgbXfrBuf1 push ds push offset DGROUP:rgbXfrBuf0
mov si,sp ;pass stack offset FBOP BOP_DPMI,InitDosx,FastBop mov sp, di ;restore stack pop es assume es:nothing
call AllocateExceptionStack FSTI ;don't need ints disabled
; Shrink the size of our real mode code segment to throw away init code.
SwitchToRealMode
mov bx,(offset CodeEnd) + 15 shr bx,4 add bx,segDXCode sub bx,segPSP push es mov es,segPSP dossvc 4Ah pop es
call DetermineFreeMemory mov FreeMem,bx SwitchToProtectedMode
; Initialize the OEM layer. This can allocate DOS memory, so it goes ; after the final program shrink.
call InitializeOEM ;currently initializes NetBIOS mapper
if1 %OUT InitializeOEM can fail!!!!!
endif
FBOP BOP_DPMI,ResetLDTUserBase,FastBop
; Exec the child application
SwitchToRealMode FSTI ;; bugbug hack ...... williamh ;; turn off A20 line before we terminate and keep resident. cmp A20EnableCount, 0 jz A20IsOff @@: xmssvc 6 dec A20EnableCount jnz @B A20IsOff:
mov ax,segPSP mov es,ax assume es:nothing mov ax,es:[2ch] mov es,ax dossvc 49h ; free env block
call DetermineFreeMemory mov dx,(offset CodeEnd) + 15 shr dx,4 add dx,FreeMem sub dx,bx add dx,segDXCode sub dx,segPSP mov al,0 dossvc 31h ; tsr. help: int 3 ; should never get here jmp help
lea bx, exec_par_blk lea dx, EXEC_PROGNAME xor al, al dossvc 4bh
; If we get here, the EXEC failed for some reason!
mov bx,offset DXCODE:ER_REALMEM ;assume insufficient memory xchg ax,bx cmp bx,8 ;is it really? jz strt88 mov ax,offset DXCODE:ER_DXINIT ;no, use generic msg
strt88: mov ExitCode,1 ;return NZ exit code
mov dx,cs ;pass msg ptr in DX:AX (ax already set)
push cs ;fake a far call so no fixup push offset DXCODE:RealModeCleanUp ; needed -- return to clean up jmp near ptr DisplayErrorMsg
; ------------------------------------------------------- ; ChildTerminationHandler -- This routine receives control ; when the child program running under the Dos Extender ; terminates. It will free all resources being used by ; the child. If we were not running TSR, then the Dos ; Extender will complete cleaning up and terminate itself. ; ; Input: none ; Output: none ; Errors: none ; Uses:
assume ds:NOTHING,es:NOTHING,ss:NOTHING
public DosxTerminationHandler DosxTerminationHandler:
mov ds,selDgroup mov es,selDgroup mov ss,selDgroup ;make sure we know where the mov sp,offset DGROUP:rgwStack ; stack is when we get here
assume ds:DGROUP,es:DGROUP
; Check if we are already in the middle of a termination sequence and ; bail out if so. This will prevent us from hanging up in an infinite ; loop if we get a GP fault while we are quitting.
cmp fQuitting,0 jz @f jmp chtm90 @@: mov fQuitting,1
; Terminate the OEM layer
call TerminateOEM ;current term's NetBIOS mapper & low net heap
; Make sure that no interrupt vectors still point to us.
call RestoreRMIntrVectors
; if this is a 80286 & 80287 configuration, we should reset the Co-Processor.
cmp [f286_287],0 ;286 and 287 config ? jz CTH_Not286And287 ;no.
; reset the 80287 Co-Processor to make sure that it gets out of protected ; mode.
xor al,al ;need to out 0 out 0F1H,al ;reset the coprocessor
CTH_Not286And287:
; If we're aborting due to a processor fault, do some extra clean-up on ; the mouse (just to be nice). If this is a normal termination, we leave ; it up to the child to save/restore the mouse state.
test fFaultAbort,0FFh jz normal_exit
; Check if the mouse driver callback function has been set, and ; reset the mouse driver if so.
mov ax,word ptr lpfnUserMouseHandler or ax,word ptr lpfnUserMouseHandler+2 jz @F xor ax,ax int 33h @@:
; Check if the PS/2 Pointing Device Handler Address has been set and ; disable it if so.
ifndef NEC_98 mov ax,word ptr lpfnUserPointingHandler or ax,word ptr lpfnUserPointingHandler+2 jz @f mov ax,0C200h xor bh,bh int 15h @@: endif ;!NEC_98
; Hmmm, we have HP mouse code in dxhpbios.asm, but no clean up here...
normal_exit:
; Release the extended memory heap.
; call ReleaseXmemHeap
; Release the space being used for the descriptor tables and ; the protected mode code segment.
; ; If we have allocated an extended memory block, then free it. ; If we have allocated the HMA, then free it. ; mov dx,hmemDOSX or dx,dx jz @F xmssvc 0Dh xmssvc 0Ah @@: cmp fUsingHMA,0 je @F xmssvc 2 @@:
; Clean up after real mode code (and possible real mode incomplete ; initialization) -- restore real mode interrupt vectors.
chtm90: RealModeCleanUp:
; Disable A20 if it was left enabled (normally 1 on 386 systems, 0 on 286)
mov cx,A20EnableCount jcxz A20Okay @@: xmssvc 6 loop @b A20Okay:
; Restore the MSW EM bit (Emulate Math coprocessor) to its initial state ifndef WOW_x86 inc fEMbit ;if fEMbit = FF, we never got far 'nuff to jz @f ; change it dec fEMbit
smsw ax test al,01h ;in V86 mode? jnz @f ; can't do the lmsw if so or al,fEMbit lmsw ax @@: endif ; Make sure DOS knows that the DOS extender is the current process
mov bx,segPSP dossvc 50h
; Reenable a friendly EMM driver if we disabled it at startup
call EMMEnable
; Restore real mode interrupt vectors
push ds
lds dx,PrevInt2FHandler ;Int 2Fh handler assume ds:NOTHING
mov ax,ds ;may not have gotten far enough to or ax,dx ; set interrupt vectors, so make jz @f ; sure before resotring.
mov ax,252Fh int 21h
@@: pop ds assume ds:DGROUP
; We have cleaned up after ourselves, so now we can quit.
mov ax,WIN386_EXIT ;use Win/386 exit Int 2Fh to tell any mov dx,WIN386_DOSX ; interested parties that we are int 2Fh ; terminating
mov al,ExitCode ;exit the extender with either the exit cmp al,0FFH ; status from the child, or a status jnz @f ; that we have forced dossvc 4Dh ;get child exit status if we haven't forced it @@: ifdef NEC_98 push ax push es ; Dec IN_BIOS(0:456) mov ax, 0040h mov es, ax test byte ptr es:[0], 20h ; check suspend/redume jz @f dec byte ptr es:[056h] ; for Y55 @@: pop es pop ax endif ;NEC_98 dossvc 4Ch ;say goodnight Gracy...
; ------------------------------------------------------- ; ChildTerminationHandler -- ; Input: none ; Output: none ; Errors: none ; Uses:
assume ds:NOTHING,es:NOTHING,ss:NOTHING public ChildTerminationHandler
ChildTerminationHandler: sub sp,4 ; room for far ret push ds push es pusha mov si,ss mov di,sp
mov ds,selDgroup mov es,selDgroup mov ss,selDgroup ;make sure we know where the
mov sp,offset DGROUP:rgwStack ; stack is when we get here
assume ds:DGROUP,es:DGROUP
;bugbug less than zero? dec cDPMIClients
test DpmiFlags,DPMI_32BIT jz cth05
; ; Return the stack frame used by the Wow32Intr16 interrupt handler ; add pbReflStack,CB_STKFRAME cth05: cmp cDPMIClients,0 jne cth20
SwitchToProtectedMode
mov dx, selPspChild mov cx, 0 ; No parent FBOP BOP_DPMI,TerminateApp,FastBop
; ; Reset the exception stack pointer to indicate free'd memory ; mov selEHStack,0
; ; Give back the xms memory ; FCLI
call ReInitIdt push 0 pop es call ReInitGdt FBOP BOP_DPMI,DpmiNoLongerInUse,FastBop
SwitchToRealMode
cth20: mov ax,[SegCurrentHostData] mov es,ax mov ax,es:[HdSegParent] mov [SegCurrentHostData],ax mov ax,es:[HdSelParent] mov [SelCurrentHostData],ax mov ax,es:[HdPSPParent] mov dx, selPspChild ; save outging psp in dx mov SelPSPChild,ax ; set new psp
cmp CDPMIClients, 0 je short @f
push es ; We need to preserve es. The SwitchToRealMode ; somehow trashes es. (bug?) push dx push ax
; free xmem allocated to this client
SwitchToProtectedMode pop cx pop dx FBOP BOP_DPMI,TerminateApp,FastBop SwitchToRealMode pop es @@: mov ax,word ptr es:[HdPspTerminate + 2] mov bx,word ptr es:[HdPspTerminate] mov cx,segPSPChild mov ds,cx assume ds:nothing ; ; Restore termination vector (app may think it knows what's here) ; mov ds:[0ah],bx mov ds:[0ch],ax xor cx,cx mov ds,cx ; ; Restore int 22 vector (terminate) Just in case ; mov ds:[22h * 4],bx mov ds:[22h * 4 + 2],ax mov es,si mov es:[di+20],bx mov es:[di+22],ax mov ss,si mov sp,di popa pop es pop ds retf
; ------------------------------------------------------- ; DisplayErrorMsg -- Display an error message on the screen. We set the ; video adapter to a text mode so the msg is visable (and gets rid ; of any bizarre mode that others may have set (like WIN.COM)). ; ; Note: This routine can be executed in real OR protected mode, so ; don't do anything mode specific--keep is short and sweet. ; ; Input: AX - offset of msg to display ; DX - segment of msg to display ; Output: None. ; Uses: AX, DX modified, all else preserved
assume ds:NOTHING, es:NOTHING public DisplayErrorMsg
DisplayErrorMsg proc far
push ds ;save current DS push ax ;save msg offset
; Set a text mode (normally 3, but possibly 7)
ifdef NEC_98 mov ah,41h ; int 18h mov ah,0Ch ; int 18h else ;!NEC_98 mov ax,0003h ;set video mode 3 int 10h mov ah,0Fh ;get video mode int 10h cmp al,03h ;did we change to 3? jz @f mov ax,0007h ;no, must be mode 7 int 10h @@: endif ;!NEC_98
; Display the msg
mov ds,dx pop dx dossvc 9
pop ds
ret
DisplayErrorMsg endp
; ------------------------------------------------------- ; DetermineFreeMemory -- Determine how much memory is free ; ; Input: none ; Output: bx = #paragraphs free memory ; Uses: bx ; assume ds:dgroup,es:nothing public DetermineFreeMemory
DetermineFreeMemory proc near push ax mov bx,0ffffh ; allocate all of memory dossvc 48h jnc @f
pop ax ret
;bugbug report error @@: mov bx,0ffffh pop ax ret DetermineFreeMemory endp EndLowSegment
DXPMCODE segment assume cs:DXPMCODE ;-------------------------------------------------------- ; ReInitIdt -- Set Idt entries back to default values ; ; Input: none ; Output: none ; uses: none ; assume ds:dgroup,es:nothing public ReInitIdt
ReInitIdt proc near
push bx push cx push dx push si push di push es mov ax,SEL_IDT OR STD_RING mov es,ax
; Fill the IDT with interrupt gates that point to the fault handler and ; interrupt reflector entry vector.
xor di,di
mov dx,offset DXPMCODE:PmIntrEntryVector mov cx,256 iidt23: mov es:[di].offDest,dx mov es:[di].selDest,SEL_DXPMCODE or STD_RING mov es:[di].cwParam,0 mov es:[di].arbGate,STD_TRAP ; BUGBUG- int gates not set up mov es:[di].rsvdGate,0 add dx,5 add di,8 loop iidt23
; Now, fix up the ones that don't point to the interrupt reflector. IFDEF WOW_x86 mov es:[1h*8].offDest,offset PMIntrIgnore mov es:[3h*8].offDest,offset PMIntrIgnore ifdef NEC_98 mov es:[11h*8].offDest,offset PMIntr11dummy mov es:[18h*8].offDest,offset PMIntrVideo mov es:[1ah*8].offDest,offset PMIntrPrinter mov es:[1bh*8].offDest,offset PMIntr13 mov es:[1ch*8].offDest,offset PMIntrCalTi mov es:[1dh*8].offDest,offset PMIntrGraph mov es:[1fh*8].offDest,offset PMIntrMisc else ;!NEC_98 mov es:[10h*8].offDest,offset PMIntrVideo mov es:[13h*8].offDest,offset PMIntr13 mov es:[15h*8].offDest,offset PMIntrMisc mov es:[19h*8].offDest,offset PMIntr19 endif ;!NEC_98 ENDIF
mov es:[21h*8].offDest,offset DXPMCODE:PMIntrDos mov es:[25h*8].offDest,offset DXPMCODE:PMIntr25 mov es:[26h*8].offDest,offset DXPMCODE:PMIntr26 mov es:[28h*8].offDest,offset DXPMCODE:PMIntr28 mov es:[30h*8].offDest,offset DXPMCODE:PMIntrIgnore mov es:[31h*8].offDest,offset DXPMCODE:PMIntr31 mov es:[33h*8].offDest,offset DXPMCODE:PMIntrMouse mov es:[41h*8].offDest,offset DXPMCODE:PMIntrIgnore
ifndef WOW_x86 mov es:[4Bh*8].offDest,offset DXPMCODE:PMIntr4B ifdef NEC_98 ; Sound BIOS Int D2h handler mov es:[0D2h*8].offDest,offset DXPMCODE:PMIntrSound
; extended DOS Int DCh handler (KANA/KANJI) mov es:[0DCh*8].offDest,offset DXPMCODE:PMIntrExDos endif ;!NEC_98 endif ; ; Set up the IDT, and dpmi32 state ; mov ax,es ; Idt selector mov bx,VDM_INT_16 DPMIBOP InitIDT
mov ax,5 ; handler increment mov cx,SEL_DXPMCODE OR STD_RING mov dx,offset DXPMCODE:PmFaultEntryVector
DPMIBOP InitExceptionHandlers
IFDEF WOW_x86 ; make the stacks 16 bit again
cCall NSetSegmentAccess,<selDgroupPM,STD_DATA> cCall NSetSegmentAccess,<selEHStack,STD_DATA> ENDIF ; All done
iidt90: pop es pop di pop si pop dx pop cx pop bx ret ReInitIdt endp
assume ds:DGROUP,es:NOTHING public ReInitGdt ReInitGdt proc near
push ax push cx push di
mov ax,selGDT ; LDT selector lsl cx,ax ; LDT size mov di,SEL_USER and SELECTOR_INDEX DPMIBOP InitLDT
pop di pop cx pop ax ret ReInitGdt endp
;-------------------------------------------------------- ; AllocateExceptionStack -- Get space for exception handler ; ; Input: none ; Output: none ; carry set on error ; uses: AX, BX, CX, DX, SI, DI ; assume ds:dgroup,es:nothing public AllocateExceptionStack AllocateExceptionStack proc near
cmp selEHStack, 0 ;have we allocated one already jnz aes_ok ;yes, return no carry
xor bx,bx mov dx,bx mov cx,1000h ;length of block mov ax, 501h push ds FBOP BOP_DPMI, Int31Call, FastBop jc @F
mov ax, SEL_USER_STACK or STD_RING mov selEHStack,ax
cCall NSetSegmentDscr,<ax,bx,cx,0,0fffh,STD_DATA> mov ax,selEHStack
mov cx,1000h ;reload length dec cx and cx,0fffeh ; Make sure SP is WORD aligned mov npEHStackLimit,cx
;; mark the stack with 0DEADh mov bx, cx push ds mov ds,ax sub bx,2 mov word ptr [bx],0DEADh pop ds mov npEHStacklet, bx
push es mov ax, selEHStack mov es, ax mov bx, npEHStackLimit DPMIBOP InitPmStackInfo pop es
aes_ok: clc @@: ret
AllocateExceptionStack endp
DXPMCODE ends
;****************************************************************
end start
|