You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3567 lines
130 KiB
3567 lines
130 KiB
PAGE ,132
|
|
TITLE DXINTR.ASM -- Dos Extender Interrupt Reflector
|
|
|
|
; Copyright (c) Microsoft Corporation 1988-1991. All Rights Reserved.
|
|
|
|
;****************************************************************
|
|
;* *
|
|
;* DXINTR.ASM - Dos Extender Interrupt Reflector *
|
|
;* *
|
|
;****************************************************************
|
|
;* *
|
|
;* Revision History: *
|
|
;* *
|
|
;* *
|
|
;* 09/13/90 earleh Fault handlers Ring 0 *
|
|
;* 09/06/90 earleh Fault handlers DPMI compliant *
|
|
;* PIC remapping no longer required *
|
|
;* 08/08/90 earleh DOSX and client privilege ring determined *
|
|
;* by equate in pmdefs.inc *
|
|
;* 05/09/90 jimmat Started VCPI changes. *
|
|
;* 04/02/90 jimmat Added PM Int 70h handler. *
|
|
;* 01/08/90 jimmat Don't allow nested PS/2 mouse interrupts *
|
|
;* (later removed!) *
|
|
;* 09/15/89 jimmat Support for 'Classic' HP Vectras which *
|
|
;* have 3 8259 interrupt controllers *
|
|
;* 07/28/89 jimmat Save A20 state when reflecting an int to *
|
|
;* protected mode, removed Int 30h handler *
|
|
;* that did code patch-ups, point debugger *
|
|
;* to faulting instruction, not Int 3. *
|
|
;* 07/13/89 jimmat Improved termination due to faults when *
|
|
;* not running under a debugger--also ifdef'd *
|
|
;* out code to dynamically fixup code seg *
|
|
;* references on GP faults *
|
|
;* 06/05/89 jimmat Ints 0h-1Fh are now vectored through a 2nd *
|
|
;* table. This allows Wdeb386 interaction *
|
|
;* more like Windows/386. *
|
|
;* 05/23/89 jimmat Added wParam & lParam to interrupt frame. *
|
|
;* 05/07/89 jimmat Added XMScontrol function to map protected *
|
|
;* mode XMS requests to real mode driver. *
|
|
;* 05/02/89 jimmat 8259 interrupt mask saved around changing *
|
|
;* of hardware interrupt base *
|
|
;* 04/24/89 jimmat Added support for PS/2 Int 15h/C2h/07 Set *
|
|
;* Pointing Device Handler Address function *
|
|
;* 04/12/89 jimmat Added PMIntr24 routine to support PM *
|
|
;* Critical Error Handlers *
|
|
;* 03/15/89 jimmat Added INT 31h LDT/heap interface a la *
|
|
;* Windows/386 *
|
|
;* 03/14/89 jimmat Changes to run child in ring 1 with LDT *
|
|
;* 02/24/89 (GeneA): fixed problem in IntEntryVideo and *
|
|
;* IntExitVideo for processing function 10h subfunction *
|
|
;* for reading and writing the VGA palette. *
|
|
;* 02/22/89 (GeneA): added handlers for Int 10h, Int 15h, and *
|
|
;* Int 33h. Added support for more general mechanism for *
|
|
;* handling interrupts require special servicing and *
|
|
;* allowing nesting of these interrupts. Allocation and *
|
|
;* deallocation of stack frames is supported to allow *
|
|
;* nested paths through the interrupt reflection code to *
|
|
;* a depth of 8. *
|
|
;* There is still a problem that if an interrupt handler *
|
|
;* is using a static buffer to transfer data, another *
|
|
;* interrupt that uses the same static buffer could come *
|
|
;* in and trash it. Solving the problem in a completely *
|
|
;* general way would require having a buffer allocation *
|
|
;* deallocation scheme for doing the transfers between *
|
|
;* real mode memory and protected mode memory. *
|
|
;* 02/14/89 (GeneA): added code in TrapGP to print error msg *
|
|
;* and quit when running a non-debugging version. *
|
|
;* 02/10/89 (GeneA): changed Dos Extender from small model to *
|
|
;* medium model. Added function LoaderTrap to handle *
|
|
;* loader interrupts when the program contains overlays. *
|
|
;* 11/20/88 (GeneA): changed both RM and PM interrupt reflector*
|
|
;* routines to pass the flags returned by the ISR back to *
|
|
;* the originator of the interrupt, rather than returning *
|
|
;* the original flags. *
|
|
;* 10/28/88 (GeneA): created *
|
|
; 18-Dec-1992 sudeepb Changed cli/sti to faster FCLI/FSTI
|
|
;* *
|
|
;****************************************************************
|
|
|
|
.286p
|
|
.287
|
|
|
|
; -------------------------------------------------------
|
|
; INCLUDE FILE DEFINITIONS
|
|
; -------------------------------------------------------
|
|
|
|
.xlist
|
|
.sall
|
|
include segdefs.inc
|
|
include gendefs.inc
|
|
include pmdefs.inc
|
|
include interupt.inc
|
|
ifdef WOW_x86
|
|
include vdmtib.inc
|
|
endif
|
|
.list
|
|
include intmac.inc
|
|
include stackchk.inc
|
|
include bop.inc
|
|
include dpmi.inc
|
|
|
|
; -------------------------------------------------------
|
|
; GENERAL SYMBOL DEFINITIONS
|
|
; -------------------------------------------------------
|
|
|
|
|
|
; -------------------------------------------------------
|
|
; EXTERNAL SYMBOL DEFINITIONS
|
|
; -------------------------------------------------------
|
|
|
|
extrn EnterRealMode:NEAR
|
|
extrn EnterProtectedMode:NEAR
|
|
extrn ParaToLinear:NEAR
|
|
externFP NSetSegmentDscr
|
|
ifdef NEC_98
|
|
extrn GetSegmentAddress:NEAR
|
|
endif ;NEC_98
|
|
extrn ParaToLDTSelector:NEAR
|
|
|
|
; -------------------------------------------------------
|
|
; DATA SEGMENT DEFINITIONS
|
|
; -------------------------------------------------------
|
|
|
|
DXDATA segment
|
|
|
|
extrn pmusrss:WORD
|
|
extrn pmusrsp:WORD
|
|
extrn npXfrBuf1:WORD
|
|
extrn rgbXfrBuf0:BYTE
|
|
extrn rgbXfrBuf1:BYTE
|
|
extrn lpfnXMSFunc:DWORD
|
|
extrn Int28Filter:WORD
|
|
extrn DpmiFlags:WORD
|
|
IFDEF WOW_x86
|
|
extrn FastBop:fword
|
|
ENDIF
|
|
|
|
;
|
|
; Variables used to store register values while mode switching.
|
|
|
|
public regUserSS, regUserSP, regUserFL, regUserAX, regUserDS
|
|
public regUserES
|
|
|
|
regUserSS dw ?
|
|
regUserSP dw ?
|
|
regUserCS dw ?
|
|
regUserIP dw ?
|
|
regUserFL dw ?
|
|
regUserAX dw ?
|
|
regUserDS dw ?
|
|
regUserES dw ?
|
|
pfnReturnAddr dw ?
|
|
|
|
Int28Count dw -1 ;Count of idle Int 28h's not reflected to RM
|
|
|
|
;
|
|
; Far pointer to the user's mouse callback function.
|
|
|
|
public lpfnUserMouseHandler
|
|
|
|
lpfnUserMouseHandler dd 0 ;Entry point to the users mouse handler
|
|
cbMouseState dw 0 ;size of mouse state buffer in bytes
|
|
|
|
|
|
; Far pointer to PS/2 Pointing device handler address
|
|
|
|
public lpfnUserPointingHandler
|
|
|
|
lpfnUserPointingHandler dd 0 ;Sel:Off to user's handler
|
|
|
|
align 2
|
|
|
|
if DEBUG
|
|
extrn StackGuard:WORD
|
|
endif
|
|
extrn pbReflStack:WORD
|
|
extrn bReflStack:WORD
|
|
;
|
|
; This buffer contains the original real mode interrupt vectors.
|
|
ifdef NEC_98
|
|
public rglpfnRmISR
|
|
endif ;NEC_98
|
|
|
|
align 2
|
|
rglpfnRmISR dd 256 dup (?)
|
|
|
|
; PMFaultVector is a table of selector:offsets for routines to process
|
|
; protected mode processor faults/traps/exceptions. If we don't handle
|
|
; the exception as an exception, we vector it through PMReservedEntryVector.
|
|
|
|
FltRtn macro off
|
|
dw DXPMCODE:off
|
|
dw 0
|
|
dw SEL_DXPMCODE or STD_RING
|
|
dw 0
|
|
endm
|
|
public PMFaultVector
|
|
|
|
align 4
|
|
|
|
PMFaultVector label DWORD
|
|
FltRtn PMFaultEntryVector+5*0h ; int 0
|
|
FltRtn PMFaultEntryVector+5*1h ; int 1
|
|
FltRtn PMFaultEntryVector+5*2h ; int 2
|
|
FltRtn PMFaultEntryVector+5*3h ; int 3
|
|
FltRtn PMFaultEntryVector+5*4h ; int 4
|
|
FltRtn PMFaultEntryVector+5*5h ; int 5
|
|
FltRtn PMFaultEntryVector+5*6h ; int 6
|
|
FltRtn PMFaultEntryVector+5*7h ; int 7
|
|
FltRtn PMFaultEntryVector+5*8h ; int 8
|
|
FltRtn PMFaultEntryVector+5*9h ; int 9
|
|
FltRtn PMFaultEntryVector+5*0Ah ; int a
|
|
FltRtn PMFaultEntryVector+5*0Bh ; int b
|
|
FltRtn PMFaultEntryVector+5*0Ch ; int c
|
|
FltRtn PMFaultEntryVector+5*0Dh ; int d
|
|
FltRtn PMFaultEntryVector+5*0Eh ; int e
|
|
FltRtn PMFaultEntryVector+5*0Fh ; int f
|
|
FltRtn PMFaultEntryVector+5*10h ; int 10h
|
|
FltRtn PMFaultEntryVector+5*11h ; int 11h
|
|
FltRtn PMFaultEntryVector+5*12h ; int 12h
|
|
FltRtn PMFaultEntryVector+5*13h ; int 13h
|
|
FltRtn PMFaultEntryVector+5*14h ; int 14h
|
|
FltRtn PMFaultEntryVector+5*15h ; int 15h
|
|
FltRtn PMFaultEntryVector+5*16h ; int 16h
|
|
FltRtn PMFaultEntryVector+5*17h ; int 17h
|
|
FltRtn PMFaultEntryVector+5*18h ; int 18h
|
|
FltRtn PMFaultEntryVector+5*19h ; int 19h
|
|
FltRtn PMFaultEntryVector+5*1Ah ; int 1ah
|
|
FltRtn PMFaultEntryVector+5*1Bh ; int 1bh
|
|
FltRtn PMFaultEntryVector+5*1Ch ; int 1ch
|
|
FltRtn PMFaultEntryVector+5*1Dh ; int 1Dh
|
|
FltRtn PMFaultEntryVector+5*1Eh ; int 1Eh
|
|
FltRtn PMFaultEntryVector+5*1Fh ; int 1Fh
|
|
|
|
|
|
extrn npEHStackLimit:word
|
|
extrn npEHStacklet:word
|
|
ifdef NEC_98
|
|
extrn fPCH98:BYTE
|
|
endif ;NEC_98
|
|
IFDEF WOW
|
|
public Wow16BitHandlers
|
|
Wow16BitHandlers dw 256 dup (0,0)
|
|
|
|
ENDIF
|
|
|
|
DXDATA ends
|
|
|
|
|
|
DXSTACK segment
|
|
|
|
public rgw0Stack, rgw2FStack
|
|
|
|
dw 64 dup (?) ; INT 2Fh handler stack
|
|
|
|
rgw2FStack label word
|
|
|
|
dw 64 dup (?) ; DOSX Ring -> Ring 0 transition stack
|
|
;
|
|
; Interrupts in the range 0-1fh cause a ring transition and leave
|
|
; an outer ring IRET frame right here.
|
|
;
|
|
Ring0_EH_DS dw ? ; place to put user DS
|
|
Ring0_EH_AX dw ? ; place to put user AX
|
|
Ring0_EH_BX dw ? ; place to put user BX
|
|
Ring0_EH_CX dw ? ; place to put user CX
|
|
Ring0_EH_BP dw ? ; place to put user BP
|
|
Ring0_EH_PEC dw ? ; lsw of error code for 386 page fault
|
|
; also near return to PMFaultEntryVector
|
|
Ring0_EH_EC dw ? ; error code passed to EH
|
|
Ring0_EH_IP dw ? ; interrupted code IP
|
|
Ring0_EH_EIP dw ? ; high half eip
|
|
Ring0_EH_CS dw ? ; interrupted code CS
|
|
dw ? ; high half of cs
|
|
Ring0_EH_Flags dw ? ; interrupted code flags
|
|
Ring0_EH_EFlags dw ? ; high half of flags
|
|
Ring0_EH_SP dw ? ; interrupted code SP
|
|
Rin0_EH_ESP dw ? ; high half of esp
|
|
Ring0_EH_SS dw ? ; interrupted code SS
|
|
dw ? ; high half of ss
|
|
rgw0Stack label word
|
|
|
|
dw 64 dup (?) ; stack for switching to ring0
|
|
public ResetStack
|
|
ResetStack label word
|
|
ifdef WOW_x86
|
|
dw 64 dup (?) ; wow stack for initial int field
|
|
public rgwWowStack
|
|
rgwWowStack label word
|
|
endif
|
|
|
|
DXSTACK ends
|
|
|
|
; -------------------------------------------------------
|
|
; CODE SEGMENT VARIABLES
|
|
; -------------------------------------------------------
|
|
|
|
DXCODE segment
|
|
|
|
extrn selDgroup:WORD
|
|
|
|
DXCODE ends
|
|
|
|
DXPMCODE segment
|
|
|
|
extrn selDgroupPM:WORD
|
|
extrn segDXCodePM:WORD
|
|
extrn RZCall:NEAR
|
|
extrn segDXDataPM:WORD
|
|
|
|
DXPMCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
page
|
|
subttl Protected Mode Interrupt Reflector
|
|
; -------------------------------------------------------
|
|
; PROTECTED MODE INTERRUPT REFLECTOR
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
; -------------------------------------------------------
|
|
; PMIntrEntryVector -- This table contains a vector of
|
|
; near jump instructions to the protected mode interrupt
|
|
; reflector. The protected mode interrupt descriptor
|
|
; table is initialized so that all interrupts jump to
|
|
; locations in this table, which transfers control to
|
|
; the interrupt reflection code for reflecting the
|
|
; interrupt to real mode.
|
|
|
|
StartBopTable macro
|
|
?intr = 0
|
|
endm
|
|
|
|
PMIntrBop macro
|
|
DPMIBOP ReflectIntrToV86
|
|
db ?intr
|
|
?intr = ?intr+1
|
|
endm
|
|
|
|
public PMIntrEntryVector
|
|
|
|
PMIntrEntryVector:
|
|
|
|
StartBopTable
|
|
rept 256
|
|
PMIntrBop
|
|
endm
|
|
|
|
|
|
FaultBop macro
|
|
DPMIBOP DpmiUnhandledException
|
|
db ?intr
|
|
?intr = ?intr+1
|
|
endm
|
|
|
|
public PMFaultEntryVector
|
|
|
|
; -------------------------------------------------------
|
|
; PMFaultEntryVector -- This table contains a vector of
|
|
; near jump instructions to the protected mode fault
|
|
; analyzer.
|
|
;
|
|
PMFaultEntryVector:
|
|
|
|
StartBopTable
|
|
rept 32
|
|
FaultBop
|
|
endm
|
|
|
|
assume ds:nothing,es:nothing,ss:nothing
|
|
|
|
public PMFaultHandlerIRET
|
|
PMFaultHandlerIRET:
|
|
DPMIBOP FaultHandlerIret
|
|
|
|
public PMFaultHandlerIRETD
|
|
PMFaultHandlerIRETD:
|
|
DPMIBOP FaultHandlerIretd
|
|
|
|
public PMIntHandlerIRET
|
|
PMIntHandlerIRET:
|
|
DPMIBOP IntHandlerIret
|
|
|
|
public PMIntHandlerIRETD
|
|
PMIntHandlerIRETD:
|
|
DPMIBOP IntHandlerIretd
|
|
|
|
public PMDosxIret
|
|
PMDosxIret:
|
|
iret
|
|
|
|
public PMDosxIretd
|
|
PMDosxIretd:
|
|
db 66h
|
|
iret
|
|
|
|
public HungAppExit
|
|
HungAppExit:
|
|
mov ax,4CFFh
|
|
int 21h
|
|
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl Real Mode Interrupt Reflector
|
|
page
|
|
; -------------------------------------------------------
|
|
; REAL MODE INTERRUPT REFLECTOR
|
|
; -------------------------------------------------------
|
|
|
|
DXCODE segment
|
|
assume cs:DXCODE
|
|
; -------------------------------------------------------
|
|
; RMIntrEntryVector -- This table contains a vector of
|
|
; near jump instructions to the real mode interrupt
|
|
; reflector. Real mode interrupts that have been hooked
|
|
; by the protected mode application have their vector
|
|
; set to entry the real mode reflector through this table.
|
|
|
|
public RMtoPMReflector
|
|
RMtoPMReflector:
|
|
DPMIBOP ReflectIntrToPM
|
|
|
|
public RMCallBackBop
|
|
RMCallBackBop proc far
|
|
DPMIBOP RMCallBackCall
|
|
ret ;finished!
|
|
|
|
RMCallBackBop endp
|
|
DXCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl INT 24h Critical Error Mapper
|
|
page
|
|
; -------------------------------------------------------
|
|
; DOS CRITICAL ERROR MAPPER
|
|
; -------------------------------------------------------
|
|
|
|
DXCODE segment
|
|
|
|
; -------------------------------------------------------
|
|
; RMDefaultInt24Handler -- Default action for a DOS critical
|
|
; error is to fail the call.
|
|
;
|
|
public RMDefaultInt24Handler
|
|
RMDefaultInt24Handler proc far
|
|
mov al,3
|
|
iret
|
|
RMDefaultInt24Handler endp
|
|
|
|
DXCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl INT 28h Idle Handler
|
|
page
|
|
; -------------------------------------------------------
|
|
; INT 28H IDLE HANDLER
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
; -------------------------------------------------------
|
|
; PMIntr28 -- Protected mode handler for Idle Int 28h calls.
|
|
; The purpose of this routine is simply to cut down on the
|
|
; number of protected mode to real mode switches by ignoring
|
|
; many of the Int 28h idle calls made by the Windows PM
|
|
; kernel.
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntr28
|
|
|
|
PMIntr28 proc near
|
|
|
|
|
|
cld
|
|
push ds ;address our DGROUP
|
|
mov ds,selDgroupPM
|
|
assume ds:DGROUP
|
|
|
|
cmp Int28Filter,0 ;are we passing any through?
|
|
jz @f
|
|
|
|
inc Int28Count ;should this one be reflected?
|
|
jz i28_reflect
|
|
@@:
|
|
pop ds
|
|
iret ; no, just ignore it
|
|
|
|
i28_reflect: ; yes, reset count and
|
|
push ax ; reflecto to real mode
|
|
mov ax,Int28Filter
|
|
neg ax
|
|
mov Int28Count,ax
|
|
pop ax
|
|
pop ds
|
|
assume ds:NOTHING
|
|
|
|
jmp PMIntrEntryVector + 5*28h
|
|
|
|
PMIntr28 endp
|
|
|
|
; -------------------------------------------------------
|
|
; PMIntr31 -- Service routine for the Protect Mode INT 31h
|
|
; services. These functions duplicate the
|
|
; Windows/386 VMM INT 31h services for protected
|
|
; mode applications. They were implemented to
|
|
; support a protect mode version of Windows/286.
|
|
;
|
|
; Input: Various registers
|
|
; Output: Various registers
|
|
; Errors:
|
|
; Uses: All registers preserved, other than return values
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntr31
|
|
|
|
PMIntr31 proc near
|
|
|
|
push ds
|
|
push ax
|
|
mov ax,SEL_DXDATA OR STD_RING
|
|
mov ds,ax
|
|
assume ds:DGROUP
|
|
pop ax
|
|
|
|
FBOP BOP_DPMI,Int31Entry,FastBop
|
|
int 3
|
|
; This BOP does an implicit IRET
|
|
|
|
PMIntr31 endp
|
|
|
|
|
|
; -------------------------------------------------------
|
|
subttl Ignore Interrupt Handlers
|
|
page
|
|
; -------------------------------------------------------
|
|
; IGNORE INTERRUPT HANDLER
|
|
; -------------------------------------------------------
|
|
|
|
; PMIntrIgnore -- Service routine for protected mode interrupts
|
|
; that should be ignored, and not reflected to real mode.
|
|
; Currently used for:
|
|
;
|
|
; Int 30h - used to be Win/386 Virtualize I/O, now
|
|
; unused but no int handler in real mode
|
|
; Int 41h - Wdeb386 interface, no int handler in
|
|
; real mode
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntrIgnore
|
|
|
|
PMIntrIgnore proc near
|
|
|
|
iret
|
|
|
|
PMIntrIgnore endp
|
|
|
|
; -------------------------------------------------------
|
|
|
|
public PMIntr19
|
|
PMIntr19 proc near
|
|
|
|
push offset DXPMCODE:Reboot
|
|
call RZCall
|
|
|
|
bpRebootIDT df 0
|
|
|
|
Reboot:
|
|
mov ax,40h
|
|
mov es,ax
|
|
mov word ptr es:[0072h],1234h
|
|
lidt bpRebootIDT
|
|
int 3
|
|
|
|
PMIntr19 endp
|
|
|
|
DXPMCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl XMS Driver Interface
|
|
page
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
; -------------------------------------------------------
|
|
; XMScontrol - This function implements a protected mode
|
|
; interface to a real mode XMS driver. Unlike other
|
|
; routines in this module, this routine is called by
|
|
; the user, not invoked via an INT instruction.
|
|
;
|
|
; Input: User's regs for XMS driver
|
|
; Output: regs from XMS driver
|
|
; Uses: none
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public XMScontrol
|
|
|
|
XMScontrol proc far
|
|
|
|
jmp short XMSentry ;'standard' XMS control function
|
|
nop ; just to be consistant
|
|
nop
|
|
nop
|
|
|
|
XMSentry:
|
|
|
|
; Modify the stack so it looks like we got here via an INT (except that
|
|
; we may still have interrupts enabled)
|
|
|
|
pushf
|
|
cld
|
|
|
|
push bp
|
|
mov bp,sp ;bp -> [BP] [FL] [IP] [CS]
|
|
push ax
|
|
push bx
|
|
|
|
mov ax,[bp+4]
|
|
mov bx,[bp+6]
|
|
xchg ax,[bp+2]
|
|
mov [bp+4],bx
|
|
mov [bp+6],ax ;bp -> [BP] [IP] [CS] [FL]
|
|
pop bx
|
|
pop ax
|
|
pop bp
|
|
|
|
; We don't support XMS function 0Bh (Move Extended Memory Block) because
|
|
; it requires mapping of data between hi/low memory. Maybe someday...
|
|
|
|
cmp ah,0Bh
|
|
jnz xms_2
|
|
xms_deny:
|
|
xor ax,ax ;if function 0Bh, return failure
|
|
mov bl,80h ; (ax = 0, bl = 80h-not implemented)
|
|
jmp short XMSret
|
|
xms_2:
|
|
|
|
; We are not really an Int handler, but close enough...
|
|
|
|
call EnterIntHandler ;build an interrupt stack frame
|
|
assume ds:DGROUP,es:DGROUP ; also sets up addressability
|
|
|
|
SwitchToRealMode
|
|
|
|
pop es ;load regs for driver
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING,ss:DGROUP
|
|
popa
|
|
npopf
|
|
|
|
call lpfnXMSFunc ;call real mode driver
|
|
|
|
pushf ;rebuild stack frame
|
|
FCLI
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
|
|
mov bp,sp ;restore stack frame pointer
|
|
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
|
|
call LeaveIntHandler
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
|
|
XMSret:
|
|
riret
|
|
|
|
XMScontrol endp
|
|
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl Special Interrupt Handler Routines
|
|
page
|
|
; -------------------------------------------------------
|
|
;
|
|
; The following sets of routines handle interrupts that
|
|
; are function call interfaces and require special servicing
|
|
; by the Dos Extender. These interrupts are such things as
|
|
; the mouse driver function call interrupt, various PC BIOS
|
|
; function call interrupts, etc. Note that INT 21h (the Dos
|
|
; function call interrupt) is not handled here. These
|
|
; interrupts typically require that register values be modified
|
|
; and parameter data be copied between real mode memory and
|
|
; extended memory. The following conventions are used for these
|
|
; interrupt function handler routines.
|
|
;
|
|
; A stack is allocated from the interrupt reflector stack for these
|
|
; routines to use. This allows nested servicing of interrupts.
|
|
; A stack frame is built in the allocated stack which contains the
|
|
; following information:
|
|
; original caller's stack address
|
|
; caller's original flags and general registers (in pusha form)
|
|
; caller's original segment registers (DS & ES)
|
|
; flags and general registers to be passed to interrupt routine
|
|
; (initially the same as caller's original values)
|
|
; segment registers (DS & ES) to be passed to interrupt routine
|
|
; (initially set to the Dos Extender data segment address)
|
|
; This stack frame is built by the routine EnterIntHandler, and its
|
|
; format is defined by the structure INTRSTACK. The stack frame is
|
|
; destroyed and the processor registers set up for return to the user
|
|
; by the function LeaveIntHandler.
|
|
;
|
|
; For each interrupt, there is an entry function and an exit function.
|
|
; The entry function performs any modifications to parameter values and
|
|
; data buffering necessary before the interrupt service routine is called.
|
|
; The exit function performs any data buffering and register value
|
|
; modifications after return from the interrupt service routine.
|
|
;
|
|
; There are two sets of general registers and two sets of segment
|
|
; registers (DS & ES) on the stack frame. One set of register values
|
|
; has member names of the form intUserXX. The values in these stack
|
|
; frame members will be passed to the interrupt service routine when
|
|
; it is called, and will be loaded with the register values returned
|
|
; by the interrupt service routine. The other set of registers values
|
|
; has member names of the form pmUserXX. These stack frame members
|
|
; contain the original values in the registers on entry from the
|
|
; user program that called the interrupt.
|
|
;
|
|
; When we return to the original caller, we want to pass back the
|
|
; general registers as returned by the interrupt routine (and possibly
|
|
; modified by the exit handler), and the same segment registers as
|
|
; on entry, unless the interrupt routine returns a value in a segment
|
|
; register. (in this case, there must be some code in the exit routine
|
|
; to handle this). This means that when we return to the caller, we
|
|
; return the general register values from the intUserXX set of stack
|
|
; frame members, but we return the segment registers from the pmUserXX
|
|
; set of frame members. By doing it this way, we don't have to do
|
|
; any work for the case where the interrupt subfuntion doesn't require
|
|
; any parameter manipulation. NOTE however, this means that when
|
|
; manipulating register values to be returned to the user, the segment
|
|
; registers are treated opposite to the way the general registers are
|
|
; treated. For general registers, to return a value to the user,
|
|
; store it in a intUserXX stack frame member. To return a segment
|
|
; value to the user, store it in a pmUserXX stack frame member.
|
|
;
|
|
; -------------------------------------------------------
|
|
subttl BIOS Video Interrupt (Int 10h) Service Routine
|
|
page
|
|
; -------------------------------------------------------
|
|
; BIOS VIDEO INTERRUPT (INT 10h) SERVICE ROUTINE
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
; -------------------------------------------------------
|
|
; PMIntrVideo - Entry point into interrupt reflector code
|
|
; for IBM PC Bios video (int 10h) calls.
|
|
;
|
|
; Input: normal registers for Bios calls
|
|
; Output: normal register returns for Bios calls
|
|
; Errors: normal Bios errors
|
|
; Uses: as per Bios calls
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntrVideo
|
|
|
|
PMIntrVideo:
|
|
|
|
ifdef NEC_98
|
|
cmp ah,40h
|
|
jb CRT_bios
|
|
cmp ah,4Fh ;4Bh-4Fh = Reserve
|
|
ja CRT_bios
|
|
jmp PMIntrGBIO
|
|
|
|
CRT_bios:
|
|
call EnterIntHandler ;build a stack frame and fix up the
|
|
cld ; return address so that the interrupt
|
|
;service routine will return to us.
|
|
;
|
|
; Perform fixups on the entry register values
|
|
|
|
call IntEntryVideo
|
|
@@:
|
|
; Execute the interrupt service routine
|
|
SwitchToRealMode
|
|
assume ss:DGROUP
|
|
pop es
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING
|
|
popa
|
|
call rglpfnRmISR[4*18h] ;execute the real mode interrupt routine
|
|
pushf
|
|
cli
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
mov bp,sp ;restore stack frame pointer
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
;
|
|
; Perform fixups on the return register values.
|
|
mov ax,[bp].pmUserAX ;get original function code
|
|
|
|
;; test fPCH98,0FFh
|
|
;; jz NotNPCVideoExit ;for PC-H98 modelxx
|
|
;; call IntExitVideoNPC ; "
|
|
;; jmp @f ; "
|
|
;;NotNPCVideoExit: ; "
|
|
call IntExitVideo
|
|
@@:
|
|
;
|
|
; And return to the original caller.
|
|
call LeaveIntHandler
|
|
|
|
iret
|
|
|
|
;/////////////////////////////////////////////////////////////////////////
|
|
; Nmode GRAPH BIOS
|
|
;/////////////////////////////////////////////////////////////////////////
|
|
; -------------------------------------------------------
|
|
; PMIntrGBIO
|
|
;--------------------------------------------------------
|
|
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntrGBIO
|
|
|
|
PMIntrGBIO:
|
|
|
|
call EnterIntHandler ;build a stack frame and fix up the
|
|
cld ; return address so that the interrupt
|
|
;service routine will return to us.
|
|
;
|
|
; Perform fixups on the entry register values
|
|
|
|
push ax
|
|
mov ax,[bp].pmUserDS
|
|
call GetSegmentAddress
|
|
shr dx,4
|
|
shl bx,12
|
|
or bx,dx ;bx now = seg of parent psp
|
|
mov [bp].intUserDS,bx
|
|
pop ax
|
|
;
|
|
; Execute the interrupt service routine
|
|
SwitchToRealMode
|
|
assume ss:DGROUP
|
|
pop es
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING
|
|
popa
|
|
call rglpfnRmISR[4*18h] ;execute the real mode interrupt routine
|
|
pushf
|
|
cli
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
|
|
mov ax,ss
|
|
mov ds,ax
|
|
mov es,ax
|
|
|
|
mov bp,sp ;restore stack frame pointer
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
;
|
|
; Perform fixups on the return register values.
|
|
mov ax,[bp].pmUserAX ;get original function code
|
|
push ax
|
|
mov ax,[bp].pmUserDS
|
|
mov [bp].intUserDS,ax
|
|
pop ax
|
|
;
|
|
; And return to the original caller.
|
|
call LeaveIntHandler
|
|
iret
|
|
else ;!NEC_98
|
|
call EnterIntHandler ;build a stack frame and fix up the
|
|
cld ; return address so that the interrupt
|
|
;service routine will return to us.
|
|
;
|
|
; Perform fixups on the entry register values
|
|
call IntEntryVideo
|
|
;
|
|
; Execute the interrupt service routine
|
|
SwitchToRealMode
|
|
assume ss:DGROUP
|
|
pop es
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING
|
|
popa
|
|
sub sp,8 ; make room for stack frame
|
|
push bp
|
|
mov bp,sp
|
|
push es
|
|
push ax
|
|
|
|
xor ax,ax
|
|
mov es,ax
|
|
mov [bp + 8],cs
|
|
mov word ptr [bp + 6],offset piv_10
|
|
mov ax,es:[10h*4]
|
|
mov [bp + 2],ax
|
|
mov ax,es:[10h*4 + 2]
|
|
mov [bp + 4],ax
|
|
pop ax
|
|
pop es
|
|
pop bp
|
|
retf
|
|
|
|
piv_10: pushf
|
|
FCLI
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
mov bp,sp ;restore stack frame pointer
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
;
|
|
; Perform fixups on the return register values.
|
|
mov ax,[bp].pmUserAX ;get original function code
|
|
call IntExitVideo
|
|
;
|
|
; And return to the original caller.
|
|
call LeaveIntHandler
|
|
|
|
riret
|
|
endif ;!NEC_98
|
|
|
|
; -------------------------------------------------------
|
|
; IntEntryVideo -- This routine performs any register
|
|
; fixups and data copying needed on entry to the
|
|
; PC BIOS video interrupt (Int 10h)
|
|
;
|
|
; Input: register values on stack frame
|
|
; Output: register values on stack frame
|
|
; Errors: none
|
|
; Uses: any registers modified,
|
|
; possibly modifies buffers rgbXfrBuf0 or rgbXfrBuf1
|
|
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntEntryVideo
|
|
|
|
IntEntryVideo:
|
|
|
|
ifdef NEC_98
|
|
;video mode
|
|
|
|
cmp ah,0Fh
|
|
jnz ienv10
|
|
mov cx,16
|
|
jmp ienv70
|
|
ienv10:
|
|
cmp ah,14h
|
|
jnz ienv20
|
|
jmp ienv80
|
|
ienv20:
|
|
cmp ah,1Fh
|
|
jnz ienv30
|
|
jmp ienv110
|
|
ienv30:
|
|
cmp ah,1Ah
|
|
jnz ienv40
|
|
test fPCH98,0FFh
|
|
jnz H98_FontWrite_N
|
|
mov cx,34
|
|
jmp ienv70
|
|
ienv40:
|
|
cmp ah,20h
|
|
jnz ienv90
|
|
test fPCH98,0FFh
|
|
jnz @f
|
|
mov cx,72
|
|
jmp ienv100
|
|
|
|
@@:
|
|
jmp H98_FontWrite_H
|
|
|
|
ienv70:
|
|
push ds
|
|
mov si,[bp].pmUserCX ;offset address
|
|
mov ds,[bp].pmUserBX ;segment address
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop ds
|
|
ienv80:
|
|
|
|
push ax
|
|
mov ax,segDXDataPM
|
|
mov [bp].intUserBX,ax ;segment address
|
|
pop ax
|
|
|
|
mov [bp].intUserCX,offset DGROUP:rgbXfrBuf1
|
|
ienv90:
|
|
ret
|
|
|
|
ienv100:
|
|
push ds
|
|
mov si,[bp].pmUserBX ;offset address
|
|
mov ds,[bp].pmUserDS ;segment address
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop ds
|
|
ienv110:
|
|
|
|
push ax
|
|
mov ax,segDXDataPM
|
|
mov [bp].intUserDS,ax ;segment address
|
|
|
|
pop ax
|
|
|
|
mov [bp].intUserBX,offset DGROUP:rgbXfrBuf1
|
|
ienv120:
|
|
ret
|
|
|
|
H98_FontWrite_N:
|
|
|
|
cmp dx,7601h
|
|
jb @f
|
|
cmp dx,767Fh
|
|
jna WUSKZEN
|
|
cmp dx,7701h
|
|
jb @f
|
|
cmp dx,777Fh
|
|
jna WUSKZEN
|
|
cmp dx,7801h
|
|
jb @f
|
|
cmp dx,783Fh
|
|
;;;;;;;; ja ienv35
|
|
jna WUSKZEN
|
|
jmp ienv35
|
|
|
|
WUSKZEN:
|
|
mov cx,34
|
|
jmp ienv70
|
|
|
|
@@:
|
|
jmp ienv40
|
|
|
|
ienv35:
|
|
cmp dx,7840h
|
|
jb @b
|
|
cmp dx,787Fh
|
|
jna WUSKHAN
|
|
cmp dx,7D01h
|
|
jb @b
|
|
cmp dx,7D7Fh
|
|
jna WUSKHAN
|
|
cmp dx,7E01h
|
|
jb @b
|
|
cmp dx,7E7Fh
|
|
;;;;;;;; ja @b
|
|
jna WUSKHAN
|
|
jmp @b
|
|
WUSKHAN:
|
|
mov cx,18
|
|
jmp ienv70
|
|
|
|
H98_FontWrite_H:
|
|
|
|
cmp dx,7601h
|
|
jb @f
|
|
cmp dx,767Fh
|
|
jna HWUSKZEN
|
|
cmp dx,7701h
|
|
jb @f
|
|
cmp dx,777Fh
|
|
jna HWUSKZEN
|
|
cmp dx,7801h
|
|
jb @f
|
|
cmp dx,783Fh
|
|
;;;;;;;; ja @f
|
|
jna HWUSKZEN
|
|
jmp ienv45
|
|
HWUSKZEN:
|
|
;;;;;;;; mov cx,74
|
|
mov cx,72
|
|
jmp ienv100
|
|
|
|
@@:
|
|
jmp ienv90
|
|
|
|
ienv45:
|
|
cmp dx,7840h
|
|
jb @f
|
|
cmp dx,787Fh
|
|
jna HWUSKHAN
|
|
cmp dx,7D01h
|
|
jb @f
|
|
cmp dx,7D7Fh
|
|
jna HWUSKHAN
|
|
cmp dx,7E01h
|
|
jb @f
|
|
cmp dx,7E7Fh
|
|
;;;;;;;; ja @f
|
|
jna HWUSKHAN
|
|
jmp @f
|
|
HWUSKHAN:
|
|
;;;;;;;; mov cx,50
|
|
mov cx,48
|
|
jmp ienv100
|
|
@@:
|
|
ret
|
|
else ;!NEC_98
|
|
cmp ah,10h
|
|
jnz ienv20
|
|
;
|
|
; Video palette control function. Check for subfunctions that require
|
|
; special actions.
|
|
ienv10: cmp al,2 ;update all palette registers?
|
|
jnz @F
|
|
mov cx,17 ;palette data is 17 bytes long
|
|
jmp short ienv70 ;go copy the data
|
|
;
|
|
@@: cmp al,9 ;read all palette registers
|
|
jz ienv72
|
|
;
|
|
cmp al,12h ;update video DAC color registers
|
|
jnz @F
|
|
mov cx,[bp].pmUserCX ;count of table entries is in caller CX
|
|
add cx,cx ;each entry is 3 bytes long
|
|
add cx,[bp].pmUserCX
|
|
jmp short ienv70 ;go copy the data down
|
|
|
|
@@: cmp al,17h ;read a block of video DAC registers
|
|
jz ienv72
|
|
;
|
|
jmp short ienv90
|
|
;
|
|
;
|
|
ienv20: cmp ah,11h
|
|
jnz ienv30
|
|
;
|
|
; Character generator interface function.
|
|
; NOTE: a number of subfunctions of function 11h need to have munging
|
|
; and data buffering performed. However, function 30h is the only
|
|
; one used by Codeview, so this is the only one currently implemented.
|
|
; For this one, nothing needs to be done on entry, only on exit.
|
|
jmp short ienv90
|
|
;
|
|
;
|
|
ienv30: cmp ah,1Bh
|
|
jnz ienv40
|
|
;
|
|
; Video BIOS functionality/state information.
|
|
; On entry, we need to fix up ES:DI to point to our buffer.
|
|
mov [bp].intUserDI,offset DGROUP:rgbXfrBuf0
|
|
jmp short ienv90
|
|
;
|
|
;
|
|
ienv40:
|
|
jmp short ienv90
|
|
;
|
|
; Copy the buffer from the user ES:DX to our transfer buffer and set
|
|
; the value to DX passed to the interrupt routine to point to our buffer.
|
|
ienv70: cld
|
|
jcxz ienv90
|
|
push ds
|
|
mov si,[bp].pmUserDX
|
|
mov ds,[bp].pmUserES
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop ds
|
|
;
|
|
ienv72: mov [bp].intUserDX,offset DGROUP:rgbXfrBuf1
|
|
jmp short ienv90
|
|
|
|
;
|
|
; All done
|
|
ienv90:
|
|
ret
|
|
endif ;!NEC_98
|
|
|
|
; -------------------------------------------------------
|
|
; IntExitVideo: This routine performs any register
|
|
; fixups and data copying needed on exit from the
|
|
; PC BIOS video interrupt (Int 10h).
|
|
;
|
|
; Input: register values on stack frame
|
|
; Output: register values on stack frame
|
|
; Errors: none
|
|
; Uses: any registers modified
|
|
; possibly modifies buffers rgbXfrBuf0 or rgbXfrBuf1
|
|
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntExitVideo
|
|
|
|
IntExitVideo:
|
|
|
|
ifdef NEC_98
|
|
;video mode
|
|
|
|
cmp ah,0Fh
|
|
jnz iexv10
|
|
jmp iexv80
|
|
iexv10:
|
|
cmp ah,14h
|
|
jnz iexv20
|
|
cmp dh,00h
|
|
jnz iexv11
|
|
mov cx,10
|
|
jmp iexv70
|
|
iexv11:
|
|
cmp dh,80h ;ANK(7*13)
|
|
jnz iexv12
|
|
mov cx,18
|
|
jmp iexv70
|
|
iexv12:
|
|
test fPCH98,0FFh
|
|
jnz @f
|
|
cmp dx,2920h
|
|
jb iexv13
|
|
cmp dx,297dh
|
|
ja iexvhan1
|
|
mov cx,18
|
|
jmp iexv70
|
|
|
|
iexvhan1:
|
|
cmp dx,2a20h
|
|
jb iexv13
|
|
cmp dx,2a5fh
|
|
ja iexv13
|
|
mov cx,18
|
|
jmp iexv70
|
|
|
|
@@:
|
|
jmp H98_FontRead_N
|
|
|
|
iexv13:
|
|
mov cx,34
|
|
jmp iexv70
|
|
|
|
iexv20:
|
|
cmp ah,1Fh
|
|
jnz iexv30
|
|
cmp dh,00h
|
|
jnz iexv21
|
|
mov cx,48
|
|
jmp iexv100
|
|
iexv21:
|
|
test fPCH98,0FFh
|
|
jnz @f
|
|
cmp dx,2920h
|
|
jb Hmode_han1
|
|
cmp dx,297dh
|
|
ja Hmode_han1
|
|
mov cx,48
|
|
jmp iexv100
|
|
|
|
Hmode_han1:
|
|
cmp dx,2a20h
|
|
jb iexv22
|
|
cmp dx,2a5fh
|
|
ja iexv22
|
|
mov cx,48
|
|
jmp iexv100
|
|
|
|
@@:
|
|
jmp H98_FontRead_H
|
|
|
|
iexv22:
|
|
mov cx,72
|
|
jmp iexv100
|
|
|
|
iexv30:
|
|
cmp ah,1Ah
|
|
jnz iexv40
|
|
jmp iexv80
|
|
|
|
iexv40:
|
|
cmp ah,20h
|
|
jnz iexv90
|
|
jmp iexv110
|
|
|
|
iexv70:
|
|
|
|
cld
|
|
push es
|
|
mov di,[bp].pmUserCX
|
|
mov es,[bp].pmUserBX
|
|
mov si,offset DGROUP:rgbXfrBuf1
|
|
rep movsb
|
|
pop es
|
|
;
|
|
; Restore the caller's CX
|
|
iexv80:
|
|
push ax
|
|
mov ax,[bp].pmUserBX ;BX regster restor
|
|
mov [bp].intUserBX,ax
|
|
;------------------------------------------------------------
|
|
mov ax,[bp].pmUserCX
|
|
mov [bp].intUserCX,ax
|
|
pop ax
|
|
iexv90:
|
|
ret
|
|
|
|
iexv100:
|
|
|
|
cld
|
|
push es
|
|
mov di,[bp].pmUserBX
|
|
mov es,[bp].pmUserDS
|
|
mov si,offset DGROUP:rgbXfrBuf1
|
|
rep movsb
|
|
pop es
|
|
;
|
|
; Restore the caller's CX
|
|
iexv110:
|
|
push ax
|
|
mov ax,[bp].pmUserDS ;BX regster restor
|
|
mov [bp].intUserDS,ax
|
|
;------------------------------------------------------------
|
|
mov ax,[bp].pmUserBX
|
|
mov [bp].intUserBX,ax
|
|
pop ax
|
|
iexv120:
|
|
ret
|
|
|
|
H98_FontRead_N:
|
|
|
|
cmp dx,2920h
|
|
jb iexvN15
|
|
cmp dx,297fh
|
|
jna iexvNhan
|
|
cmp dx,2a20h
|
|
jb iexvN15
|
|
cmp dx,2a7fh
|
|
jna iexvNhan
|
|
cmp dx,2b20h
|
|
jb iexvN15
|
|
cmp dx,2b7fh
|
|
jna iexvNhan
|
|
cmp dx,7840h
|
|
jb iexvN15
|
|
cmp dx,787fh
|
|
jna iexvNhan
|
|
cmp dx,7d01h
|
|
jb iexvN15
|
|
cmp dx,7d7fh
|
|
jna iexvNhan
|
|
cmp dx,7e01h
|
|
jb iexvN15
|
|
cmp dx,7e7fh
|
|
ja iexvN15
|
|
iexvNhan:
|
|
mov cx,18 ;16byte+2=18 ; jmp iexv70
|
|
|
|
iexvN15:
|
|
mov cx,34 ;32byte+2=34
|
|
jmp iexv70
|
|
|
|
H98_FontRead_H:
|
|
|
|
cmp dx,2920h
|
|
jb iexvN25
|
|
cmp dx,297fh
|
|
jna HiexvNhan
|
|
cmp dx,2a20h
|
|
jb iexvN25
|
|
cmp dx,2a7fh
|
|
jna HiexvNhan
|
|
cmp dx,2b20h
|
|
jb iexvN25
|
|
cmp dx,2b7fh
|
|
jna HiexvNhan
|
|
cmp dx,7840h
|
|
jb iexvN25
|
|
cmp dx,787fh
|
|
jna HiexvNhan
|
|
cmp dx,7d01h
|
|
jb iexvN25
|
|
cmp dx,7d7fh
|
|
jna HiexvNhan
|
|
cmp dx,7e01h
|
|
jb iexvN25
|
|
cmp dx,7e7fh
|
|
ja iexvN25
|
|
HiexvNhan:
|
|
;;;;;;;; mov cx,50 ;48byte+2=50
|
|
mov cx,48 ;48byte
|
|
;;;;;;;; jmp iexv70
|
|
jmp iexv100
|
|
|
|
iexvN25:
|
|
;;;;;;;; mov cx,74 ;72byte+2=74
|
|
mov cx,72 ;72byte
|
|
;;;;;;;; jmp iexv70
|
|
jmp iexv100
|
|
else ;!NEC_98
|
|
cmp ah,10h
|
|
jnz iexv20
|
|
;
|
|
; Palette control function.
|
|
cmp al,9 ;read palette data function
|
|
jnz @F
|
|
mov cx,17
|
|
jmp short iexv70
|
|
;
|
|
@@: cmp al,17h ;read video DAC registers
|
|
jnz @F
|
|
mov cx,[bp].pmUserCX ;each entry in table is 3 bytes long
|
|
add cx,cx
|
|
add cx,[bp].pmUserCX
|
|
jmp short iexv70
|
|
;
|
|
@@: jmp short iexv72
|
|
;
|
|
;
|
|
iexv20: cmp ah,11h
|
|
jnz iexv30
|
|
;
|
|
; Character generator interface function.
|
|
; NOTE: a number of subfunctions of function 11h need to have munging
|
|
; and data buffering performed. However, function 30h is the only
|
|
; one used by Codeview, so this is the only one currently implemented
|
|
cmp al,30h
|
|
jnz @F
|
|
mov ax,[bp].intUserES ;get the paragraph address returned by BIOS
|
|
mov bx,STD_DATA
|
|
call ParaToLDTSelector ;get a selector for that address
|
|
mov [bp].pmUserES,ax ;store the selector so that it will be
|
|
; returned to the caller
|
|
@@: jmp short iexv90
|
|
;
|
|
;
|
|
iexv30: cmp ah,1Bh
|
|
jnz iexv40
|
|
;
|
|
; Video BIOS functionality/state information.
|
|
; On exit, we need to fix up the pointer at the beginning of the
|
|
; data put in our buffer by the BIOS, and then transfer the buffer up
|
|
; to the user.
|
|
mov ax,word ptr rgbXfrBuf0[2] ;get segment of pointer to
|
|
; 'static functionallity table'
|
|
mov bx,STD_DATA
|
|
call ParaToLDTSelector ;convert paragraph to selector
|
|
mov word ptr rgbXfrBuf0[2],ax ;store back into table
|
|
push es
|
|
mov si,offset rgbXfrBuf0 ;pointer to our copy of the table
|
|
mov di,[bp].pmUserDI ;where the user wants it
|
|
mov [bp].intUserDi,di ;restore the DI returned to the user
|
|
mov es,[bp].pmUserES
|
|
mov cx,64 ;the table is 64 bytes long
|
|
cld
|
|
rep movsb ;copy the table to the user's buffer
|
|
pop es
|
|
|
|
jmp short iexv90
|
|
;
|
|
;
|
|
iexv40:
|
|
jmp short iexv90
|
|
|
|
;
|
|
; Copy data from our buffer to the caller's buffer pointed to by ES:DX
|
|
iexv70: cld
|
|
push es
|
|
mov di,[bp].pmUserDX
|
|
mov es,[bp].pmUserES
|
|
mov si,offset DGROUP:rgbXfrBuf1
|
|
rep movsb
|
|
pop es
|
|
;
|
|
; Restore the caller's DX
|
|
iexv72: mov ax,[bp].pmUserDX
|
|
mov [bp].intUserDX,ax
|
|
;
|
|
; All done
|
|
iexv90:
|
|
ret
|
|
endif ;!NEC_98
|
|
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl BIOS Misc. Interrupt (Int 15h) Service Routine
|
|
page
|
|
; -------------------------------------------------------
|
|
; BIOS MISC. INTERRUPT (INT 15h) SERVICE ROUTINE
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
; -------------------------------------------------------
|
|
; PMIntrMisc -- Entry point into the interrupt processing code
|
|
; for the BIOS misc functions interrupt (INT 15h).
|
|
;
|
|
; Input: normal registers for Bios calls
|
|
; Output: normal register returns for Bios calls
|
|
; Errors: normal Bios errors
|
|
; Uses: as per Bios calls
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntrMisc
|
|
|
|
PMIntrMisc:
|
|
;
|
|
call EnterIntHandler ;build a stack frame and fix up the
|
|
cld ; return address so that the interrupt
|
|
;service routine will return to us.
|
|
;
|
|
; Perform fixups on the entry register values
|
|
call IntEntryMisc
|
|
;
|
|
; Execute the interrupt service routine
|
|
SwitchToRealMode
|
|
assume ss:DGROUP
|
|
pop es
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING
|
|
popa
|
|
sub sp,8 ; make room for stack frame
|
|
push bp
|
|
mov bp,sp
|
|
push es
|
|
push ax
|
|
|
|
xor ax,ax
|
|
mov es,ax
|
|
mov [bp + 8],cs
|
|
mov word ptr [bp + 6],offset pim_10
|
|
mov ax,es:[15h*4]
|
|
mov [bp + 2],ax
|
|
mov ax,es:[15h*4 + 2]
|
|
mov [bp + 4],ax
|
|
pop ax
|
|
pop es
|
|
pop bp
|
|
retf
|
|
|
|
pim_10: pushf
|
|
FCLI
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
mov bp,sp ;restore stack frame pointer
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
;
|
|
; Perform fixups on the return register values.
|
|
mov ax,[bp].pmUserAX ;get original function code
|
|
call IntExitMisc
|
|
;
|
|
; And return to the original caller.
|
|
call LeaveIntHandler
|
|
riret
|
|
|
|
; -------------------------------------------------------
|
|
; MISC INTERRUPT SUPPORT ROUTINES
|
|
; -------------------------------------------------------
|
|
;
|
|
; IntEntryMisc -- This function performs data transfer
|
|
; and register translation on entry to the BIOS Misc.
|
|
; functions interrupt. (INT 15h).
|
|
;
|
|
; Input: AX - BIOS function being performed
|
|
; Output:
|
|
; Errors:
|
|
; Uses: All registers preserved
|
|
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntEntryMisc
|
|
|
|
IntEntryMisc:
|
|
|
|
ifdef NEC_98
|
|
push cx
|
|
cmp ah,90h ;SYSTEM BIOS BLOCK MOVE
|
|
jnz iemDMA1 ;yes = jmp
|
|
jmp iem70
|
|
iemDMA1:
|
|
cmp ah,0D5h ;DMA BIOS DMA
|
|
jnz iemDMA2 ;yes = jmp
|
|
mov cx,8 ;DMA_CBIOS
|
|
jmp iem70
|
|
iemDMA2:
|
|
cmp ah,0D6h ;DMA BIOS DMA
|
|
jnz iemROM1 ;yes = jmp
|
|
jmp iem80 ;Read JMP
|
|
iemROM1:
|
|
cmp ah,0D8h ;ROM
|
|
jnz iemROM2 ;yes = jmp
|
|
mov cx,4
|
|
jmp iem70
|
|
|
|
iemROM2:
|
|
cmp ah,0D9h ;ROM
|
|
jnz iem90 ;yes = jmp
|
|
mov cx,8 ;ROM BIOS
|
|
iem70:
|
|
push ds
|
|
mov si,[bp].pmUserBX ;offset address
|
|
mov ds,[bp].pmUserES ;segment address
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop ds
|
|
iem80:
|
|
push ax
|
|
mov ax,segDXDataPM
|
|
mov [bp].intUserES,ax ;segment address
|
|
pop ax
|
|
mov [bp].intUserBX,offset DGROUP:rgbXfrBuf1
|
|
iem90:
|
|
pop cx
|
|
ret
|
|
else ;!NEC_98
|
|
; Map requests to set the PS/2 Pointing Device Handler Address
|
|
|
|
cmp ax,0C207h ;PS/2 Set Pointing Device Handler adr?
|
|
jnz iem90
|
|
|
|
mov ax,[bp].pmUserBX ;User's ES:BX -> handler
|
|
mov word ptr lpfnUserPointingHandler,ax
|
|
mov ax,[bp].pmUserES
|
|
mov word ptr [lpfnUserPointingHandler+2],ax
|
|
|
|
mov ax,segDXCodePM ;pass BIOS address of our handler
|
|
mov [bp].intUserES,ax
|
|
mov ax,offset PointDeviceHandler
|
|
mov [bp].intUserBX,ax
|
|
|
|
iem90:
|
|
ret
|
|
endif ;!NEC_98
|
|
|
|
; -------------------------------------------------------
|
|
; IntExitMisc -- This function performs data transfer
|
|
; and register translation on exit from the BIOS Misc.
|
|
; Functions interrupt (INT 15h).
|
|
;
|
|
; Input: AX - BIOS function being performed
|
|
; Output:
|
|
; Errors:
|
|
; Uses: All registers preserved
|
|
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntExitMisc
|
|
|
|
IntExitMisc:
|
|
ifdef NEC_98
|
|
push cx
|
|
cmp ah,90h ;SYSTEM BIOS BLOCK MOVE
|
|
jnz ixmDMA1 ;yes = jmp
|
|
jmp ixm70
|
|
ixmDMA1:
|
|
cmp ah,0D5h ;DMA BIOS
|
|
jnz ixmDMA2 ;yes = jmp
|
|
jmp ixm70
|
|
ixmDMA2:
|
|
cmp ah,0D6h ;DMA BIOS DMA
|
|
jnz ixmROM1 ;yes = jmp
|
|
mov cx,16
|
|
jmp ixm80
|
|
ixmROM1:
|
|
cmp ah,0D8h ; ROM
|
|
jnz ixmROM2 ;yes = jmp
|
|
jmp ixm70
|
|
ixmROM2:
|
|
cmp ah,0D9h ; ROM
|
|
jnz ixm90
|
|
ixm70:
|
|
cld
|
|
push es
|
|
mov di,[bp].pmUserBX
|
|
mov es,[bp].pmUserES
|
|
mov si,offset DGROUP:rgbXfrBuf1
|
|
rep movsb
|
|
pop es
|
|
;
|
|
; Restore the caller's ES,BX
|
|
ixm80:
|
|
push ax
|
|
mov ax,[bp].pmUserES
|
|
mov [bp].intUserES,ax
|
|
mov ax,[bp].pmUserBX
|
|
mov [bp].intUserBX,ax
|
|
pop ax
|
|
ixm90:
|
|
pop cx
|
|
ret
|
|
else ;!NEC_98
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push dx
|
|
;
|
|
; Check for function 0C0h - Return System Configuration Parameters
|
|
cmp ah,0C0h
|
|
jnz ixmi30
|
|
test [bp].intUserFL,1 ;check if the bios call returned an error
|
|
jnz ixmi90 ;(carry flag set in returned flags)
|
|
;
|
|
; The BIOS call succeeded. This means that ES:BX points to a configuration
|
|
; vector. We need to fix up the segment to be a selector.
|
|
mov dx,[bp].intUserES
|
|
cmp dx,0F000h ;does it point to normal BIOS segment
|
|
jnz ixmi22
|
|
mov ax,SEL_BIOSCODE or STD_RING
|
|
jmp short ixmi24
|
|
|
|
ixmi22: call ParaToLinear
|
|
mov cx,0FFFFh
|
|
mov ax,SEL_USERSCR or STD_TBL_RING
|
|
cCall NSetSegmentDscr,<ax,bx,dx,0,cx,STD_DATA>
|
|
ixmi24: mov [bp].pmUserES,ax
|
|
jmp short ixmi90
|
|
|
|
; Chack for function 0C207h - PS/2 Set Pointing Device Handler Address
|
|
|
|
ixmi30:
|
|
cmp ax,0C207h
|
|
jne ixmi90
|
|
|
|
mov ax,[bp].pmUserBX ;restore user's BX
|
|
mov [bp].intUserBX,ax
|
|
|
|
; All done
|
|
ixmi90:
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
ret
|
|
endif ;!NEC_98
|
|
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl Mouse Function Interrupt (Int 33h) Service Routine
|
|
page
|
|
; -------------------------------------------------------
|
|
; MOUSE FUNCTION INTERRUPT (INT 33h) SERVICE ROUTINE
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
; -------------------------------------------------------
|
|
; PMIntrMouse - Entry point into interrupt reflector code
|
|
; for mouse driver (int 33h) calls.
|
|
;
|
|
; Input: normal registers for mouse calls
|
|
; Output: normal register returns for mouse calls
|
|
; Errors: normal mouse errors
|
|
; Uses: as per mouse calls
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntrMouse
|
|
|
|
PMIntrMouse:
|
|
;
|
|
call EnterIntHandler ;build a stack frame and fix up the
|
|
cld ; return address so that the interrupt
|
|
;service routine will return to us.
|
|
;
|
|
; Perform fixups on the entry register values
|
|
call IntEntryMouse
|
|
;
|
|
; Execute the interrupt service routine
|
|
SwitchToRealMode
|
|
assume ss:DGROUP
|
|
pop es
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING
|
|
popa
|
|
sub sp,8 ; make room for stack frame
|
|
push bp
|
|
mov bp,sp
|
|
push es
|
|
push ax
|
|
|
|
xor ax,ax
|
|
mov es,ax
|
|
mov [bp + 8],cs
|
|
mov word ptr [bp + 6],offset pimo_10
|
|
mov ax,es:[33h*4]
|
|
mov [bp + 2],ax
|
|
mov ax,es:[33h*4 + 2]
|
|
mov [bp + 4],ax
|
|
pop ax
|
|
pop es
|
|
pop bp
|
|
retf
|
|
|
|
pimo_10: pushf
|
|
FCLI
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
mov bp,sp ;restore stack frame pointer
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
;
|
|
; Perform fixups on the return register values.
|
|
mov ax,[bp].pmUserAX ;get original function code
|
|
call IntExitMouse
|
|
;
|
|
; And return to the original caller.
|
|
call LeaveIntHandler
|
|
riret
|
|
|
|
; -------------------------------------------------------
|
|
; MOUSE SUPPORT ROUTINES
|
|
; -------------------------------------------------------
|
|
|
|
; IntEntryMouse -- This function performs data transfer and
|
|
; register translation on entry to mouse driver functions.
|
|
; (INT 33h)
|
|
;
|
|
; Input: AX - mouse function being performed
|
|
; Output:
|
|
; Errors:
|
|
; Uses: NOTHING
|
|
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntEntryMouse
|
|
|
|
IntEntryMouse:
|
|
cld
|
|
push ax
|
|
push cx
|
|
push si
|
|
push di
|
|
;
|
|
cmp al,9 ;Set graphics cursor block?
|
|
jnz ment10
|
|
;
|
|
; The user is setting a graphics cursor. We need to copy the masks
|
|
; down to low memory so that the mouse driver can get at them and then
|
|
; fix up the pointer in DX.
|
|
mov cx,32
|
|
jmp short ment92
|
|
;
|
|
; Mouse interrupt handler establishment
|
|
ment10: cmp al,12 ;Set user defined interrupt subroutine ?
|
|
jnz ment20
|
|
;
|
|
; This command has the effect of causing a call to the address es:ds
|
|
; Whenever an event of one of the types specified by the mask in cx.
|
|
; The address es:dx must be saved in lpfnUserMouseHandler and the
|
|
; real mode address of MouseInterruptHandler substituted.
|
|
mov ax,[bp].pmUserDX ; Load users handler offset
|
|
mov word ptr lpfnUserMouseHandler,ax ; Store for future use
|
|
mov ax,[bp].pmUserES ; Load users handler segment value
|
|
mov word ptr lpfnUserMouseHandler + 2,ax ; Store for future use
|
|
mov ax,segDXCodePM ; Load real mode code segment value
|
|
mov [bp].intUserES,ax ; Store in real mode es register image
|
|
mov ax,offset MouseInterruptHandler ; Load handler offset
|
|
mov [bp].intUserDX,ax ; Store in real mode dx register image
|
|
jmp short ment99 ;Return
|
|
;
|
|
ment20: cmp al,20
|
|
jc ment99
|
|
jnz ment30
|
|
;
|
|
; This is the swap interrupt subroutine function. Not currently implemented
|
|
jmp short ment99
|
|
;
|
|
ment30: cmp al,22 ;Save mouse driver state?
|
|
jnz ment40
|
|
;
|
|
; This is the save mouse driver state function. We need to pass a pointer
|
|
; to the transer buffer down to the mouse driver.
|
|
mov ax,npXfrBuf1
|
|
mov [bp].intUserDX,ax
|
|
jmp short ment99
|
|
|
|
ment40: cmp al,23 ;Restore mouse driver state?
|
|
jnz ment99
|
|
;
|
|
; This is the restore mouse driver state function. We need to copy the
|
|
; mouse state buffer from the pm user location to the transfer buffer,
|
|
; and then pass the pointer to the transfer buffer on to the mouse driver.
|
|
mov cx,cbMouseState
|
|
jcxz ment99
|
|
;
|
|
; Transfer the data pointed to by the user ES:DX to the scratch buffer, and
|
|
; fix up the pointer that is passed on to the mouse driver.
|
|
ment92: mov si,[bp].pmUserDX
|
|
mov di,npXfrBuf1
|
|
mov [bp].intUserDX,di
|
|
push ds
|
|
mov ds,[bp].pmUserES
|
|
cld
|
|
rep movs word ptr [di],word ptr [si]
|
|
pop ds
|
|
;
|
|
ment99: pop di
|
|
pop si
|
|
pop cx
|
|
pop ax
|
|
ret
|
|
|
|
; -------------------------------------------------------
|
|
; IntExitMouse -- This function performs data transfer and
|
|
; register translation on exit from mouse driver functions.
|
|
; (INT 33h)
|
|
;
|
|
; Input: AX - mouse function being performed
|
|
; Output:
|
|
; Errors:
|
|
; Uses:
|
|
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntExitMouse
|
|
|
|
IntExitMouse:
|
|
cld
|
|
cmp al,21 ;get state buffer size?
|
|
jnz mxit20
|
|
;
|
|
; We need to remember the state buffer size, so that later we will know
|
|
; how many bytes to transfer when we do the save/restore state fucntions.
|
|
mov ax,[bp].intUserBX
|
|
mov cbMouseState,ax
|
|
return
|
|
;
|
|
mxit20: cmp al,22 ;Save mouse driver state?
|
|
jnz mxit30
|
|
;
|
|
; We need to restore the original values of ES:DX and transfer the mouse
|
|
; state data from the real mode buffer to the user's protected mode buffer.
|
|
mov cx,cbMouseState
|
|
jcxz mxit28
|
|
push es
|
|
mov si,npXfrBuf1
|
|
mov di,[bp].pmUserDX
|
|
mov [bp].intUserDX,di
|
|
mov es,[bp].pmUserES
|
|
rep movs byte ptr [di],byte ptr [si]
|
|
pop es
|
|
mxit28: return
|
|
;
|
|
mxit30: cmp al,23 ;Restore mouse driver state?
|
|
jnz mxit99
|
|
mov ax,[bp].pmUserDX
|
|
mov [bp].intUserDX,ax
|
|
;
|
|
mxit99: ret
|
|
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl PM Interrupt Support Routines
|
|
page
|
|
; -------------------------------------------------------
|
|
; PM INTERRUPT SUPPORT ROUTINES
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
; -------------------------------------------------------
|
|
; EnterIntHandler -- This routine will allocate a stack
|
|
; frame on the interrupt reflector stack and make
|
|
; a copy of the registers on the allocated stack.
|
|
;
|
|
; Note: This routine expects the current stack to contain a near
|
|
; return address and a normal [IP] [CS] [FL] interrupt stack
|
|
; frame. Don't have anything else on the stack before calling
|
|
; this routine!
|
|
;
|
|
; Note: This routine disables interrupts, and leaves them disabled.
|
|
; Most callers already have them disabled, so it doesn't
|
|
; really make a difference, except that this routine
|
|
; requires that they be disabled.
|
|
;
|
|
; Input: none
|
|
; Output: stack frame set up
|
|
; Errors: none
|
|
; Uses: all registers preserved
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public EnterIntHandler
|
|
|
|
EnterIntHandler proc near
|
|
|
|
FCLI ;we really want int's disabled (and
|
|
; XMScontrol doesn't do that)
|
|
push ds
|
|
mov ds,selDgroupPM ;save user's DS and address our DGROUP
|
|
assume ds:DGROUP
|
|
pop regUserDS
|
|
|
|
push bp
|
|
mov bp,sp ;bp -> [BP] [IP] [IP] [CS] [FL]
|
|
push word ptr [bp+8]
|
|
pop regUserFL ;user's flags before doing INT
|
|
pop bp
|
|
|
|
pop pfnReturnAddr ;near return to our immediate caller
|
|
|
|
mov regUserSS,ss ;save caller's stack address
|
|
mov regUserSP,sp
|
|
ASSERT_REFLSTK_OK
|
|
mov ss,selDgroupPM ;switch to interrupt reflector stack
|
|
mov sp,pbReflStack
|
|
sub pbReflStack,CB_STKFRAME ;adjust pointer to next stack frame
|
|
FIX_STACK
|
|
|
|
; Build the stack frame. The stack frame contains the following:
|
|
; dword & word parameter locations
|
|
; original caller's stack address
|
|
; caller's original flags and general registers (in pusha form)
|
|
; caller's original segment registers (DS & ES)
|
|
; flags and general registers to be passed to interrupt routine
|
|
; (initially the same as caller's original values)
|
|
; segment registers (DS & ES) to be passed to interrupt routine
|
|
; (initially set to the Dos Extender data segment address)
|
|
;
|
|
; The parameter words and then the caller's original register values go on top.
|
|
|
|
sub sp,8 ;space for a dd & 2 dw's
|
|
|
|
push regUserSP
|
|
push regUserSS
|
|
push regUserFL
|
|
pusha
|
|
push regUserDS
|
|
push es
|
|
|
|
; Now, put all of the general registers, and values for the segment
|
|
; registers to be passed to the interrupt service routine. We pass
|
|
; the Dos Extender data segment address to the interrupt routine.
|
|
|
|
push regUserFL
|
|
pusha
|
|
push segDXDataPM
|
|
push segDXDataPM
|
|
|
|
; And we are done.
|
|
|
|
mov bp,sp ;set up frame pointer
|
|
mov es,selDgroupPM
|
|
jmp pfnReturnAddr ;return to the caller.
|
|
|
|
EnterIntHandler endp
|
|
|
|
|
|
; -------------------------------------------------------
|
|
; LeaveIntHandler -- This routine will restore the user registers,
|
|
; release the stack frame, and restore the original user's stack
|
|
; for exit from an interrupt reflector routine.
|
|
;
|
|
; Note: Interrupts must be off when this routine is called.
|
|
;
|
|
; Input: none
|
|
; Output: none
|
|
; Errors: none
|
|
; Uses: All registers modified
|
|
|
|
assume ds:DGROUP,es:NOTHING,ss:NOTHING
|
|
public LeaveIntHandler
|
|
|
|
LeaveIntHandler proc near
|
|
|
|
FCLI
|
|
pop pfnReturnAddr
|
|
|
|
; The copy of the register values returned from the interrupt routine
|
|
; (and then possibly modified by the exit handler for the particular
|
|
; interrupt) are what gets returned to the caller. We discard the original
|
|
; register values saved on entry. (They were there so that the exit
|
|
; routine could refer to them if necessary)
|
|
|
|
add sp,4 ;skip over interrupt service routine's
|
|
; segment register values
|
|
popa ;restore general register values
|
|
pop regUserFL ;flags returned by interrupt routine
|
|
pop es ;get segment registers from pmUserES
|
|
pop regUserDS ; and pmUserDS
|
|
add sp,18 ;skip over the original user registers
|
|
; and flags
|
|
pop regUserSS ;original interrupted routine's stack
|
|
pop regUserSP
|
|
mov regUserAX,ax
|
|
|
|
; Switch back to the original user's stack.
|
|
|
|
ASSERT_REFLSTK_OK
|
|
ASSERT_CLI
|
|
CHECK_STACK
|
|
mov ss,regUserSS
|
|
mov sp,regUserSP
|
|
add pbReflStack,CB_STKFRAME
|
|
ASSERT_REFLSTK_OK
|
|
|
|
; We need to replace the image of the flags in the original int return
|
|
; address on the user's stack with the new flags returned from the interrupt
|
|
; service routine.
|
|
|
|
push bp
|
|
mov bp,sp ;stack -> BP IP CS FL
|
|
mov ax,regUserFL ;flags returned by interrupt service routine
|
|
and ax,0BFFFh ;clear the nested task flag
|
|
and [bp+6],0300h ;clear all but the interrupt and trace flags
|
|
; in the caller's original flags
|
|
or [bp+6],ax ;combine in the flags returned by the
|
|
; interrupt service routine. This will cause
|
|
; us to return to the original routine with
|
|
; interrupts on if they were on when the
|
|
; interrupt occured, or if the ISR returned
|
|
; with them on.
|
|
pop bp
|
|
|
|
; And now, return to the caller.
|
|
|
|
push pfnReturnAddr
|
|
mov ax,regUserAX
|
|
mov ds,regUserDS
|
|
assume ds:NOTHING
|
|
ret
|
|
|
|
LeaveIntHandler endp
|
|
|
|
; -------------------------------------------------------
|
|
|
|
DXPMCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl Mouse Interrupt Callback Function Handler
|
|
page
|
|
; -------------------------------------------------------
|
|
; MOUSE INTERRUPT CALLBACK FUNCTION HANDLER
|
|
; -------------------------------------------------------
|
|
|
|
DXCODE segment
|
|
assume cs:DXCODE
|
|
|
|
; -------------------------------------------------------
|
|
; MouseInterruptHandler -- This routine is the entry point for
|
|
; user requested mouse event interrupts. It switches the
|
|
; processor to protected mode and transfers control to the
|
|
; user protected mode mouse handling routine. When that
|
|
; completes, it switches back to real mode and returns control
|
|
; to the mouse driver.
|
|
; Entry to this routine will have been requested by an
|
|
; INT 33H code 12 with the real address of this routine
|
|
; substituted for the users entry point.
|
|
; The address of the user specified mouse handler as specified
|
|
; in the original INT 33H is stored in the variable
|
|
; lpfnUserMouseHandler.
|
|
;
|
|
; Input: none
|
|
; Output: none
|
|
; Errors: none
|
|
; Uses: The segment registers are explicitly preserved by
|
|
; this routine. Other registers are as preserved or
|
|
; modified by the users mouse handler.
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public MouseInterruptHandler
|
|
|
|
MouseInterruptHandler proc far
|
|
;
|
|
; On entry, the stack layout is:
|
|
; [2] CS - System mouse handler code segment
|
|
; [0] IP - System mouse handler return offset
|
|
;
|
|
|
|
push es
|
|
push ds
|
|
pushf
|
|
FCLI
|
|
cld
|
|
mov ds,selDgroup
|
|
assume ds:DGROUP
|
|
pop regUserFL
|
|
;
|
|
; Allocate a new stack frame, and then switch to the local stack
|
|
; frame.
|
|
mov regUserSP,sp ;save entry stack pointer so we can restore it
|
|
mov regUSerSS,ss ;save segment too
|
|
mov ss,selDgroup ;switch to our own stack frame
|
|
ASSERT_REFLSTK_OK
|
|
mov sp,pbReflStack
|
|
sub pbReflStack,CB_STKFRAME ;adjust pointer to next stack frame
|
|
FIX_STACK
|
|
;
|
|
; We are now running on our own stack, so we can switch into protected mode.
|
|
push ax ;preserve caller's AX
|
|
SwitchToProtectedMode
|
|
pop ax
|
|
;
|
|
; Build a far return frame on the stack so that the user's
|
|
; routine will return to us when it is finished.
|
|
push regUserSS ; save system mouse handler stack address
|
|
push regUserSP ; so we can restore it later
|
|
push ds
|
|
push cs
|
|
push offset mih50
|
|
;
|
|
; Build an IRET frame on the stack to use to transfer control to the
|
|
; user's protected mode routine
|
|
push regUserFL
|
|
push word ptr lpfnUserMouseHandler+2 ;push segment of user routine
|
|
push word ptr lpfnUserMouseHandler ;push offset of user routine
|
|
;
|
|
; At this point the interrupt reflector stack looks like this:
|
|
;
|
|
; [14] stack segment of original stack
|
|
; [12] stack pointer of original stack
|
|
; [10] real mode dos extender data segment
|
|
; [8] segment of return address back to here
|
|
; [6] offset of return address back here
|
|
; [4] Users flags
|
|
; [2] segment of user routine
|
|
; [0] offset of user routine
|
|
;
|
|
; Execute the users mouse handler
|
|
iret
|
|
;
|
|
; The users handler will return here after it is finsished.
|
|
mih50: FCLI
|
|
cld
|
|
pop ds
|
|
pop regUserSP
|
|
pop regUserSS
|
|
;
|
|
; Switch back to real mode.
|
|
push ax ;preserve AX
|
|
SwitchToRealMode
|
|
pop ax
|
|
CHECK_STACK
|
|
;
|
|
; Switch back to the original stack.
|
|
mov ss,regUserSS
|
|
mov sp,regUserSP
|
|
ASSERT_REFLSTK_OK
|
|
;
|
|
; Deallocate the stack frame that we are using.
|
|
add pbReflStack,CB_STKFRAME
|
|
ASSERT_REFLSTK_OK
|
|
;
|
|
; And return to the original interrupted program.
|
|
pop ds
|
|
pop es
|
|
|
|
ret
|
|
|
|
MouseInterruptHandler endp
|
|
|
|
; -------------------------------------------------------
|
|
|
|
DXCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl PS/2 Pointing Device Handler
|
|
page
|
|
; -------------------------------------------------------
|
|
; PS/2 POINTING DEVICE HANDLER
|
|
; -------------------------------------------------------
|
|
|
|
DXCODE segment
|
|
assume cs:DXCODE
|
|
|
|
ifndef NEC_98
|
|
; -------------------------------------------------------
|
|
; PointDeviceHandler -- This routine is the entry point for
|
|
; the PS/2 Pointing Device Handler. It switches the
|
|
; processor to protected mode and transfers control to the
|
|
; user pointing device handler. When that completes,
|
|
; it switches back to real mode and returns control to
|
|
; the PS/2 BIOS.
|
|
;
|
|
; Note: The BIOS calls us with interrutps enabled!
|
|
|
|
; Input: none
|
|
; Output: none
|
|
; Errors: none
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PointDeviceHandler
|
|
|
|
PointDeviceHandler proc far
|
|
|
|
; On entry, the stack layout is:
|
|
;
|
|
; [10] status
|
|
; [8] X coordinate
|
|
; [6] Y coordinate
|
|
; [4] Z coordinate
|
|
; [2] CS - PS/2 BIOS code segment
|
|
; [0] IP - PS/2 BIOS return offset
|
|
|
|
cld
|
|
push es ;save PS/2 BIOS ds/es on it's stack
|
|
push ds
|
|
|
|
mov ds,selDgroup ;addressability to DOSX DGROUP
|
|
push ds
|
|
pop es
|
|
assume ds:DGROUP,es:DGROUP
|
|
|
|
FCLI ;protect global regUserXX vars
|
|
|
|
; Allocate a new stack frame, and then switch to the local stack
|
|
; frame.
|
|
|
|
mov regUserSP,sp ;save entry stack pointer so we can restore it
|
|
mov regUSerSS,ss ;save segment too
|
|
ASSERT_REFLSTK_OK
|
|
mov ss,selDgroup ;switch to our own stack frame
|
|
mov sp,pbReflStack
|
|
sub pbReflStack,CB_STKFRAME ;adjust pointer to next stack frame
|
|
FIX_STACK
|
|
|
|
push regUserSS ;save PS/2 BIOS stack address
|
|
push regUserSP ; so we can restore it later
|
|
|
|
push SEL_DXDATA or STD_RING ;DOSX DS to be poped in PM
|
|
|
|
sub sp,4*2 ;temp save the general regs further down the
|
|
pusha ; stack, they'll get poped in a little while
|
|
|
|
; Copy PS/2 pointing device stack info to our (soon to be) protected mode stack
|
|
|
|
mov si,regUserSP ;PS/2 stack pointer
|
|
mov ds,regUserSS ;PS/2 stack segment
|
|
assume ds:NOTHING
|
|
|
|
FSTI ;no more references to global regUserXX vars
|
|
|
|
add si,4*2 ;skip over es,ds,cs,ip
|
|
mov di,sp ;loc for pointing device
|
|
add di,8*2 ; data on our stack
|
|
mov cx,4
|
|
cld
|
|
rep movsw
|
|
|
|
push es ;restore ds = DGROUP
|
|
pop ds
|
|
assume ds:DGROUP
|
|
|
|
; We are now running on our own stack, so we can switch into protected mode.
|
|
|
|
SwitchToProtectedMode ;disables interrupts again
|
|
FSTI ; but we don't want them disabled
|
|
|
|
popa ;restore general registers
|
|
|
|
; At this point the stack looks like this:
|
|
;
|
|
; [12] stack segment of original stack
|
|
; [10] stack pointer of original stack
|
|
; [8] protect mode dos extender data segment
|
|
; [6] status
|
|
; [4] X coordinate
|
|
; [2] Y coordinate
|
|
; [0] Z coordinate
|
|
|
|
; Execute the user's pointing device handler
|
|
|
|
call [lpfnUserPointingHandler]
|
|
|
|
; The users handler will return here after it is finsished.
|
|
|
|
pdh50:
|
|
cld
|
|
add sp,4*2 ;discard pointing device info
|
|
pop ds
|
|
|
|
FCLI ;protect global regUserXX vars
|
|
pop regUserSP
|
|
pop regUserSS
|
|
|
|
; Switch back to real mode.
|
|
|
|
push ax ;preserve AX
|
|
SwitchToRealMode
|
|
pop ax
|
|
|
|
; Switch back to the original stack.
|
|
|
|
CHECK_STACK
|
|
mov ss,regUserSS
|
|
mov sp,regUserSP
|
|
|
|
; Deallocate the stack frame that we are using.
|
|
|
|
ASSERT_REFLSTK_OK
|
|
add pbReflStack,CB_STKFRAME
|
|
ASSERT_REFLSTK_OK
|
|
|
|
; And return to the PS/2 BIOS
|
|
|
|
FSTI ;we came in with ints enabled
|
|
|
|
pop ds
|
|
pop es
|
|
|
|
ret
|
|
|
|
PointDeviceHandler endp
|
|
|
|
; -------------------------------------------------------
|
|
endif ;!NEC_98
|
|
;
|
|
; -------------------------------------------------------
|
|
subttl Utility Function Definitions
|
|
page
|
|
; -------------------------------------------------------
|
|
; UTILITY FUNCTION DEFINITIONS
|
|
; -------------------------------------------------------
|
|
;
|
|
; SaveRMIntrVectors -- This routine copies the current
|
|
; real mode interrupt vector table to the shadow
|
|
; vector table used by the interrupt reflector.
|
|
;
|
|
; Input: none
|
|
; Output: none
|
|
; Errors: none
|
|
; Uses; all registers preserved
|
|
;
|
|
; NOTE: This routine can only be called in REAL MODE.
|
|
|
|
assume ds:DGROUP,es:NOTHING,ss:NOTHING
|
|
public SaveRMIntrVectors
|
|
|
|
SaveRMIntrVectors:
|
|
push cx
|
|
push si
|
|
push di
|
|
push ds
|
|
push es
|
|
;
|
|
cld
|
|
push ds
|
|
pop es
|
|
xor cx,cx
|
|
mov si,cx
|
|
mov ds,cx
|
|
mov di,offset DGROUP:rglpfnRmISR
|
|
mov cx,2*256
|
|
rep movs word ptr [di],word ptr [si]
|
|
;
|
|
pop es
|
|
pop ds
|
|
pop di
|
|
pop si
|
|
pop cx
|
|
ret
|
|
|
|
; -------------------------------------------------------
|
|
; RestoreRMIntrVectors -- This routine copies the
|
|
; interrupt vectors from the real mode interrupt
|
|
; vector shadow table back down to the real interrupt
|
|
; vectors.
|
|
;
|
|
; Input: none
|
|
; Output: none
|
|
; Errors: none
|
|
; Uses; all registers preserved
|
|
;
|
|
; NOTE: This routine can only be called in REAL MODE.
|
|
|
|
assume ds:DGROUP,es:NOTHING,ss:NOTHING
|
|
public RestoreRMIntrVectors
|
|
|
|
RestoreRMIntrVectors:
|
|
push cx
|
|
push si
|
|
push di
|
|
push ds
|
|
push es
|
|
;
|
|
FCLI
|
|
cld
|
|
xor cx,cx
|
|
mov di,cx
|
|
mov es,cx
|
|
mov si,offset DGROUP:rglpfnRmISR
|
|
mov cx,2*256
|
|
rep movs word ptr [di],word ptr [si]
|
|
FSTI
|
|
;
|
|
pop es
|
|
pop ds
|
|
pop di
|
|
pop si
|
|
pop cx
|
|
ret
|
|
|
|
; -------------------------------------------------------
|
|
|
|
DXCODE ends
|
|
|
|
ifdef NEC_98
|
|
;
|
|
; -------------------------------------------------------
|
|
subttl INT D2h SOUND BIOS HANDRER
|
|
page
|
|
; -------------------------------------------------------
|
|
; PMIntrSound
|
|
;--------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntrSound
|
|
|
|
PMIntrSound:
|
|
|
|
call EnterIntHandler ;build a stack frame and fix up the
|
|
cld ; return address so that the interrupt
|
|
;service routine will return to us.
|
|
;
|
|
; Perform fixups on the entry register values
|
|
call IntEntrySD
|
|
;
|
|
; Execute the interrupt service routine
|
|
SwitchToRealMode
|
|
assume ss:DGROUP
|
|
pop es
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING
|
|
popa
|
|
call rglpfnRmISR[4*0D2h] ;execute the real mode interrupt routine
|
|
pushf
|
|
cli
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
mov bp,sp ;restore stack frame pointer
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
;
|
|
; Perform fixups on the return register values.
|
|
mov ax,[bp].pmUserAX ;get original function code
|
|
call IntExitSD
|
|
;
|
|
; And return to the original caller.
|
|
call LeaveIntHandler
|
|
|
|
iret
|
|
|
|
;--------------------------------------------------------
|
|
; IntEntrySD
|
|
;--------------------------------------------------------
|
|
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntEntrySD
|
|
|
|
IntEntrySD:
|
|
|
|
cmp ah,0 ;BIOS(INITIALIZE)
|
|
jnz ienSD10
|
|
mov bx,0 ;BIOS
|
|
mov si,bx
|
|
mov cx,2FFh ;(256) (512)
|
|
jmp ienSD50
|
|
ienSD10:
|
|
cmp ah,1 ;(PLAY)
|
|
jnz ienSD20
|
|
mov si,[bp].pmUserBX
|
|
mov cx,28
|
|
jmp ienSD50
|
|
ienSD20:
|
|
cmp ah,16h ;(SET PARA BLOCK)
|
|
jnz ienSD90
|
|
mov si,[bp].pmUserBX
|
|
cmp dl,0 ;00=WORD/01=BYTE?
|
|
jnz ienSD21 ;not 0 = JMP
|
|
mov cx,100 ;100
|
|
jmp ienSD50
|
|
ienSD21:
|
|
mov cx,51 ;51
|
|
ienSD50:
|
|
push ds
|
|
;;;; mov si,[bp].pmUserBX ;
|
|
mov ds,[bp].pmUserES ;
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
rep movsb
|
|
pop ds
|
|
|
|
push ax
|
|
mov ax,segDXDataPM
|
|
mov [bp].intUserES,ax ;segment address
|
|
pop ax
|
|
;------------------------------------------------------------
|
|
mov [bp].intUserBX,offset DGROUP:rgbXfrBuf1
|
|
ienSD90:
|
|
ret
|
|
|
|
;--------------------------------------------------------
|
|
; IntExitSD
|
|
;--------------------------------------------------------
|
|
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntExitSD
|
|
|
|
IntExitSD:
|
|
|
|
cmp ah,0 ;BIOS (INITIALIZE)
|
|
jnz iexSD10
|
|
jmp iexSD50
|
|
iexSD10:
|
|
cmp ah,1 ;(PLAY)
|
|
jnz iexSD20
|
|
jmp iexSD50
|
|
iexSD20:
|
|
cmp ah,16h ;(SET PARA BLOCK)
|
|
jnz iexSD90
|
|
iexSD50:
|
|
push ax
|
|
mov ax,[bp].pmUserES
|
|
mov [bp].intUserES,ax
|
|
;------------------------------------------------------------
|
|
mov ax,[bp].pmUserBX
|
|
mov [bp].intUserBX,ax
|
|
pop ax
|
|
iexSD90:
|
|
ret
|
|
|
|
DXPMCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl INT 1Ah PRINTER BIOS HANDRER
|
|
page
|
|
|
|
; 30h( ) 2K
|
|
; -------------------------------------------------------
|
|
; PMIntrPrinter
|
|
;--------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntrPrinter
|
|
|
|
PMIntrPrinter:
|
|
|
|
|
|
call EnterIntHandler ;build a stack frame and fix up the
|
|
cld ; return address so that the interrupt
|
|
;service routine will return to us.
|
|
;
|
|
; Perform fixups on the entry register values
|
|
call IntEntryPR
|
|
;
|
|
; Execute the interrupt service routine
|
|
SwitchToRealMode
|
|
assume ss:DGROUP
|
|
pop es
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING
|
|
popa
|
|
call rglpfnRmISR[4*1Ah] ;execute the real mode interrupt routine
|
|
pushf
|
|
cli
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
mov bp,sp ;restore stack frame pointer
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
;
|
|
; Perform fixups on the return register values.
|
|
mov ax,[bp].pmUserAX ;get original function code
|
|
call IntExitPR
|
|
;
|
|
; And return to the original caller.
|
|
call LeaveIntHandler
|
|
|
|
iret
|
|
|
|
;--------------------------------------------------------
|
|
; IntEntryPR
|
|
;--------------------------------------------------------
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntEntryPR
|
|
|
|
IntEntryPR:
|
|
|
|
cmp ah,30h ;
|
|
jnz ienPR20 ;90/08/24
|
|
mov cx,[bp].pmUserCX ;
|
|
cmp cx,2048 ;2K
|
|
jbe ienPR10 ;NO = jmp
|
|
mov cx,2048
|
|
mov [bp].intUserCX,cx
|
|
ienPR10:
|
|
push ds
|
|
mov si,[bp].pmUserBX ;offset address
|
|
mov ds,[bp].pmUserES ;segment address
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop ds
|
|
push ax
|
|
mov ax,segDXDataPM
|
|
mov [bp].intUserES,ax ;segment address
|
|
pop ax
|
|
;------------------------------------------------------------
|
|
mov [bp].intUserBX,offset DGROUP:rgbXfrBuf1
|
|
|
|
ienPR20:
|
|
ret
|
|
|
|
;--------------------------------------------------------
|
|
; IntExitPR
|
|
;--------------------------------------------------------
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntExitPR
|
|
|
|
IntExitPR:
|
|
|
|
cmp ah,30h
|
|
jnz iexPR20
|
|
mov cx,[bp].pmUserCX
|
|
cmp cx,2048
|
|
ja iexPR10 ;YES = jmp
|
|
push ax
|
|
mov ax,[bp].pmUserES
|
|
mov [bp].intUserES,ax
|
|
;------------------------------------------------------------
|
|
mov ax,[bp].pmUserBX ;offset address
|
|
mov [bp].intUserBX,ax
|
|
pop ax
|
|
ret
|
|
|
|
iexPR10:
|
|
push ax
|
|
mov ax,[bp].pmUserES
|
|
mov [bp].intUserES,ax
|
|
;------------------------------------------------------------
|
|
mov cx,2048
|
|
sub [bp].pmUserCX,cx
|
|
mov ax,[bp].pmUserCX
|
|
mov [bp].intUserCX,ax
|
|
pop ax
|
|
|
|
push bx
|
|
add [bp].pmUserBX,cx
|
|
mov bx,[bp].pmUserBX
|
|
mov [bp].intUserBX,bx
|
|
pop bx
|
|
iexPR20:
|
|
ret
|
|
|
|
;////////////////////////////////////////////////////////////
|
|
if 0
|
|
;////////////////////////////////////////////////////////////
|
|
IntEntryPR:
|
|
|
|
cmp ah,30h
|
|
jnz ienPR10
|
|
mov cx,[bp].pmUserCX
|
|
cmp cx,2048
|
|
ja ienPR10 ;YES = jmp
|
|
push ds
|
|
mov si,[bp].pmUserBX ;offset address
|
|
mov ds,[bp].pmUserES ;segment address
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop ds
|
|
push ax
|
|
mov ax,segDXDataPM
|
|
mov [bp].intUserES,ax ;segment address
|
|
pop ax
|
|
;------------------------------------------------------------
|
|
mov [bp].intUserBX,offset DGROUP:rgbXfrBuf1
|
|
ret
|
|
|
|
ienPR10:
|
|
push ds
|
|
mov si,[bp].pmUserBX ;offset address
|
|
mov ds,[bp].pmUserES ;segment address
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop ds
|
|
push ax
|
|
mov ax,segDXDataPM
|
|
mov [bp].intUserES,ax ;segment address
|
|
pop ax
|
|
;------------------------------------------------------------
|
|
push bx
|
|
mov bx,offset DGROUP:rgbXfrBuf1 ;
|
|
add bx,cx ;DGROUP:rgbXfrBuf1
|
|
mov [bp].intUserBX,bx ;
|
|
pop bx
|
|
ret
|
|
|
|
; push ds
|
|
; mov [bp].intUserES,ds ;segment address
|
|
; pop ds
|
|
;;------------------------------------------------------------
|
|
; mov bx,offset DGROUP:rgbXfrBuf1 ;
|
|
; add bx,cx ;
|
|
; mov [bp].intUserBX,bx ;
|
|
; ret
|
|
;
|
|
;--------------------------------------------------------
|
|
; IntExitPR
|
|
;--------------------------------------------------------
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntExitPR
|
|
|
|
IntExitPR:
|
|
|
|
cmp ah,30h
|
|
jnz iexPR10
|
|
mov ax,[bp].pmUserES
|
|
mov [bp].intUserES,ax
|
|
;------------------------------------------------------------
|
|
mov ax,[bp].pmUserBX ;
|
|
mov [bp].intUserBX,ax
|
|
iexPR10:
|
|
ret
|
|
;////////////////////////////////////////////////////////////
|
|
endif
|
|
;////////////////////////////////////////////////////////////
|
|
|
|
DXPMCODE ends
|
|
|
|
|
|
; -------------------------------------------------------
|
|
subttl INT 1Ch CALENDER/TIMER HANDRER
|
|
page
|
|
|
|
; -------------------------------------------------------
|
|
; PMIntrCalTi
|
|
;--------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntrCalTi
|
|
|
|
|
|
PMIntrCalTi:
|
|
|
|
call EnterIntHandler ;build a stack frame and fix up the
|
|
cld ; return address so that the interrupt
|
|
;service routine will return to us.
|
|
;
|
|
; Perform fixups on the entry register values
|
|
call IntEntryCT
|
|
;
|
|
; Execute the interrupt service routine
|
|
SwitchToRealMode
|
|
assume ss:DGROUP
|
|
pop es
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING
|
|
popa
|
|
call rglpfnRmISR[4*1Ch] ;execute the real mode interrupt routine
|
|
pushf
|
|
cli
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
mov bp,sp ;restore stack frame pointer
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
;
|
|
; Perform fixups on the return register values.
|
|
mov ax,[bp].pmUserAX ;get original function code
|
|
call IntExitCT
|
|
;
|
|
; And return to the original caller.
|
|
call LeaveIntHandler
|
|
|
|
iret
|
|
|
|
|
|
|
|
;--------------------------------------------------------
|
|
; IntEntryCT
|
|
;--------------------------------------------------------
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntEntryCT
|
|
|
|
IntEntryCT:
|
|
|
|
cmp ah,0 ;
|
|
jnz ienCT10
|
|
jmp ienCT80
|
|
ienCT10:
|
|
cmp ah,1 ;
|
|
jnz ienCT20
|
|
mov cx,6 ;
|
|
jmp ienCT70
|
|
ienCT20:
|
|
ienCT50:
|
|
|
|
push es
|
|
push ax
|
|
mov ax,40h
|
|
mov es,ax
|
|
; test byte ptr es:[501h],8h ;if Hmode
|
|
test byte ptr es:[101h],8h ;if Hmode
|
|
jz ienCT90
|
|
|
|
;; test fNHmode,0FFh
|
|
;; jz ienCT90 ;0=Nmode --->jmp
|
|
|
|
;--------------------- Hmode ----------------------
|
|
cmp ah,3
|
|
jnz ienCT30
|
|
mov cx,4
|
|
jmp ienCT70
|
|
ienCT30:
|
|
cmp ah,4
|
|
jnz ienCT40
|
|
mov cx,12
|
|
jmp ienCT70
|
|
ienCT40:
|
|
cmp ah,5
|
|
jnz ienCT90
|
|
mov cx,12
|
|
;--------------------- Hmode ----------------------
|
|
|
|
|
|
ienCT70:
|
|
push ds
|
|
mov si,[bp].pmUserBX ;offset address
|
|
mov ds,[bp].pmUserES ;segment address
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop ds
|
|
ienCT80:
|
|
push ax
|
|
mov ax,segDXDataPM
|
|
mov [bp].intUserES,ax ;segment address
|
|
pop ax
|
|
;------------------------------------------------------------
|
|
mov [bp].intUserBX,offset DGROUP:rgbXfrBuf1
|
|
ienCT90:
|
|
ret
|
|
|
|
;--------------------------------------------------------
|
|
; IntExitCT
|
|
;--------------------------------------------------------
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntExitCT
|
|
|
|
IntExitCT:
|
|
|
|
cmp ah,0
|
|
jnz iexCT10
|
|
mov cx,6
|
|
jmp iexCT70
|
|
iexCT10:
|
|
cmp ah,1
|
|
jnz iexCT20
|
|
jmp iexCT80
|
|
iexCT20:
|
|
|
|
iexCT50:
|
|
|
|
push es
|
|
push ax
|
|
mov ax,40h
|
|
mov es,ax
|
|
; test byte ptr es:[501h],8h ;if Hmode
|
|
test byte ptr es:[101h],8h ;if Hmode
|
|
jz iexCT90
|
|
|
|
;; test fNHmode,0FFh
|
|
;; jz iexCT90 ;0=Nmode --->jmp
|
|
|
|
;--------------------- Hmode ----------------------
|
|
cmp ah,3
|
|
jnz iexCT30
|
|
jmp iexCT80
|
|
iexCT30:
|
|
cmp ah,4
|
|
jnz iexCT40
|
|
jmp iexCT80
|
|
iexCT40:
|
|
cmp ah,5
|
|
jnz iexCT90
|
|
jmp iexCT80
|
|
;--------------------- Hmode ----------------------
|
|
|
|
iexCT70:
|
|
push es
|
|
mov di,[bp].pmUserBX ;offset address
|
|
mov es,[bp].pmUserES ;segment address
|
|
mov si,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop es
|
|
iexCT80:
|
|
push ax
|
|
|
|
mov ax,[bp].pmUserES
|
|
mov [bp].intUserES,ax
|
|
;------------------------------------------------------------
|
|
mov ax,[bp].pmUserBX
|
|
mov [bp].intUserBX,ax
|
|
pop ax
|
|
iexCT90:
|
|
ret
|
|
|
|
|
|
DXPMCODE ends
|
|
|
|
; -------------------------------------------------------
|
|
subttl INT DCh extended DOS HANDRER
|
|
page
|
|
|
|
; -------------------------------------------------------
|
|
; PMIntrExDos
|
|
;--------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntrExDos
|
|
|
|
PMIntrExDos:
|
|
|
|
call EnterIntHandler ;build a stack frame and fix up the
|
|
cld ; return address so that the interrupt
|
|
;service routine will return to us.
|
|
;
|
|
; Perform fixups on the entry register values
|
|
call IntEntryED
|
|
;
|
|
; Execute the interrupt service routine
|
|
SwitchToRealMode
|
|
assume ss:DGROUP
|
|
pop es
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING
|
|
popa
|
|
call rglpfnRmISR[4*0DCh] ;execute the real mode interrupt routine
|
|
pushf
|
|
cli
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
mov bp,sp ;restore stack frame pointer
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
;
|
|
; Perform fixups on the return register values.
|
|
; mov ax,[bp].pmUserAX ;get original function code
|
|
mov cx,[bp].pmUserCX ;get original function code
|
|
call IntExitED
|
|
;
|
|
; And return to the original caller.
|
|
call LeaveIntHandler
|
|
|
|
iret
|
|
|
|
;--------------------------------------------------------
|
|
; IntEntryED
|
|
;--------------------------------------------------------
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntEntryED
|
|
|
|
IntEntryED:
|
|
|
|
cmp cl,0Ch
|
|
jnz ienED10
|
|
jmp ienED80
|
|
ienED10:
|
|
;;; push cx
|
|
cmp cl,0Dh
|
|
jz ienED
|
|
jmp ienED20
|
|
ienED:
|
|
push cx
|
|
cmp ax,0
|
|
jnz ienED11
|
|
mov cx,386 ;386byte
|
|
jmp ienED70
|
|
ienED11:
|
|
cmp ax,0FFh
|
|
jnz ienED12
|
|
mov cx,786 ;786byte
|
|
jmp ienED70
|
|
ienED12:
|
|
cmp ax,1
|
|
jb ienED13
|
|
cmp ax,0Ah
|
|
ja ienED13
|
|
mov cx,160 ;16*10=160byte
|
|
jmp ienED70
|
|
ienED13:
|
|
cmp ax,0Bh
|
|
jb ienED14
|
|
cmp ax,14h
|
|
ja ienED14
|
|
mov cx,160 ;16*10=160byte
|
|
jmp ienED70
|
|
ienED14:
|
|
cmp ax,15h
|
|
jb ienED15
|
|
cmp ax,1Fh
|
|
ja ienED15
|
|
mov cx,66 ;6*11=66byte
|
|
jmp ienED70
|
|
ienED15:
|
|
cmp ax,20h
|
|
jb ienED16
|
|
cmp ax,24h
|
|
ja ienED16
|
|
mov cx,80 ;16*5=80byte
|
|
jmp ienED70
|
|
ienED16:
|
|
cmp ax,25h
|
|
jb ienED17
|
|
cmp ax,29h
|
|
ja ienED17
|
|
mov cx,80 ;16*5=80byte
|
|
jmp ienED70
|
|
ienED17:
|
|
cmp ax,2Ah
|
|
jb ienED18
|
|
cmp ax,38h
|
|
ja ienED18
|
|
mov cx,240 ;16*15=240byte
|
|
jmp ienED70
|
|
ienED18:
|
|
cmp ax,100h
|
|
jnz ienED20
|
|
mov cx,514 ;2+512=514byte
|
|
jmp ienED70
|
|
|
|
ienED20:
|
|
cmp cl,10h
|
|
jnz ienED90
|
|
cmp ah,1
|
|
jnz ienED90
|
|
|
|
moji_out:
|
|
mov si,dx
|
|
cmp byte ptr ds:[si],'$'
|
|
;;;;;;;; cmp byte ptr ds:[dx],'$'
|
|
jz ienED90
|
|
push ds
|
|
mov si,[bp].pmUserDX ;offset address
|
|
mov ds,[bp].pmUserDS ;segment address
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
movsb
|
|
pop ds
|
|
jmp moji_out
|
|
|
|
|
|
ienED70:
|
|
push ds
|
|
mov si,[bp].pmUserDX ;offset address
|
|
mov ds,[bp].pmUserDS ;segment address
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop ds
|
|
pop cx
|
|
ienED80:
|
|
;-----------
|
|
push ax
|
|
mov ax,segDXDataPM
|
|
mov [bp].intUserES,ax ;segment address
|
|
pop ax
|
|
;------------------------------------------------------------
|
|
mov [bp].intUserDX,offset DGROUP:rgbXfrBuf1
|
|
ienED90:
|
|
ret
|
|
|
|
|
|
;--------------------------------------------------------
|
|
; IntExitED
|
|
;--------------------------------------------------------
|
|
assume ds:DGROUP,es:DGROUP,ss:NOTHING
|
|
public IntExitED
|
|
|
|
IntExitED:
|
|
|
|
cmp cl,0Ch
|
|
jz iexED
|
|
jmp iexED10
|
|
iexED:
|
|
push cx
|
|
cmp ax,0
|
|
jnz iexED1
|
|
mov cx,386 ;386byte
|
|
jmp iexED70
|
|
iexED1:
|
|
cmp ax,0FFh
|
|
jnz iexED2
|
|
mov cx,786 ;786byte
|
|
jmp iexED70
|
|
iexED2:
|
|
cmp ax,1
|
|
jb iexED3
|
|
cmp ax,0Ah
|
|
ja iexED3
|
|
mov cx,160 ;16*10=160byte
|
|
jmp iexED70
|
|
iexED3:
|
|
cmp ax,0Bh
|
|
jb iexED4
|
|
cmp ax,14h
|
|
ja iexED4
|
|
mov cx,160 ;16*10=160byte
|
|
jmp iexED70
|
|
iexED4:
|
|
cmp ax,15h
|
|
jb iexED5
|
|
cmp ax,1Fh
|
|
ja iexED5
|
|
mov cx,66 ;6*11=66byte
|
|
jmp iexED70
|
|
iexED5:
|
|
cmp ax,20h
|
|
jb iexED6
|
|
cmp ax,24h
|
|
ja iexED6
|
|
mov cx,80 ;16*5=80byte
|
|
jmp iexED70
|
|
iexED6:
|
|
cmp ax,25h
|
|
jb iexED7
|
|
cmp ax,29h
|
|
ja iexED7
|
|
mov cx,80 ;16*5=80byte
|
|
jmp iexED70
|
|
iexED7:
|
|
cmp ax,2Ah
|
|
jb iexED8
|
|
cmp ax,38h
|
|
ja iexED8
|
|
mov cx,240 ;16*15=240byte
|
|
jmp iexED70
|
|
iexED8:
|
|
cmp ax,100h
|
|
jnz iexED10
|
|
mov cx,514 ;2+512=514byte
|
|
jmp iexED70
|
|
|
|
iexED10:
|
|
cmp cl,0Dh
|
|
jnz iexED20
|
|
jmp iexED80
|
|
iexED20:
|
|
cmp cl,10h
|
|
jnz iexED90
|
|
cmp ah,1
|
|
jnz iexED90
|
|
jmp iexED80
|
|
iexED70:
|
|
push ds
|
|
mov si,[bp].pmUserDX ;offset address
|
|
mov ds,[bp].pmUserDS ;segment address
|
|
mov di,offset DGROUP:rgbXfrBuf1
|
|
cld
|
|
rep movsb
|
|
pop ds
|
|
pop cx
|
|
iexED80:
|
|
push ax
|
|
;-----------
|
|
mov ax,[bp].pmUserDS
|
|
mov [bp].intUserDS,ax
|
|
;------------------------------------------------------------
|
|
mov ax,[bp].pmUserDX
|
|
mov [bp].intUserDX,ax
|
|
pop ax
|
|
iexED90:
|
|
ret
|
|
|
|
|
|
DXPMCODE ends
|
|
|
|
;/////////////////////////////////////////////////////////////////////////
|
|
; Hmode no GRAPH ha INT 1Dh(Graph BIOS) niyori byouga sareru.
|
|
; DOSX deha,
|
|
;/////////////////////////////////////////////////////////////////////////
|
|
; -------------------------------------------------------
|
|
; PMIntr GRAPH BIOS
|
|
;--------------------------------------------------------
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntrGraph
|
|
|
|
;///////////////////////////////////////////////////////////////////////
|
|
;; extrn fNHmode:BYTE ;NHmode
|
|
;///////////////////////////////////////////////////////////////////////
|
|
|
|
PMIntrGraph:
|
|
|
|
|
|
;; test fNHmode,0FFh
|
|
;; jz GBios_Nmode
|
|
call EnterIntHandler ;build a stack frame and fix up the
|
|
cld ; return address so that the interrupt
|
|
;service routine will return to us.
|
|
;
|
|
; Perform fixups on the entry register values
|
|
|
|
push ax
|
|
mov ax,[bp].pmUserDS
|
|
call GetSegmentAddress
|
|
shr dx,4
|
|
shl bx,12
|
|
or bx,dx ;bx now = seg of parent psp
|
|
mov [bp].intUserDS,bx
|
|
pop ax
|
|
|
|
|
|
;
|
|
; Execute the interrupt service routine
|
|
SwitchToRealMode
|
|
assume ss:DGROUP
|
|
pop es
|
|
pop ds
|
|
assume ds:NOTHING,es:NOTHING
|
|
popa
|
|
call rglpfnRmISR[4*1Dh] ;execute the real mode interrupt routine
|
|
pushf
|
|
cli
|
|
cld
|
|
pusha
|
|
push ds
|
|
push es
|
|
|
|
mov ax,ss
|
|
mov ds,ax
|
|
mov es,ax
|
|
|
|
mov bp,sp ;restore stack frame pointer
|
|
SwitchToProtectedMode
|
|
assume ds:DGROUP,es:DGROUP
|
|
;
|
|
; Perform fixups on the return register values.
|
|
mov ax,[bp].pmUserAX ;get original function code
|
|
;/////////////
|
|
push ax
|
|
mov ax,[bp].pmUserDS
|
|
mov [bp].intUserDS,ax
|
|
pop ax
|
|
;/////////////
|
|
;
|
|
; And return to the original caller.
|
|
call LeaveIntHandler
|
|
|
|
iret
|
|
|
|
|
|
DXPMCODE ends
|
|
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
assume ds:NOTHING,es:NOTHING,ss:NOTHING
|
|
public PMIntr11dummy
|
|
|
|
PMIntr11dummy proc near
|
|
|
|
and ax,0FFFDh
|
|
iret
|
|
|
|
PMIntr11dummy endp
|
|
DXPMCODE ends
|
|
|
|
endif ;NEC_98
|
|
DXPMCODE segment
|
|
assume cs:DXPMCODE
|
|
|
|
IFDEF WOW
|
|
|
|
public Wow32IntrRefl
|
|
Wow32IntrRefl label word
|
|
??intnum = 0
|
|
rept 256
|
|
push word ptr ??intnum
|
|
jmp Wow32Intr16Reflector
|
|
??intnum = ??intnum + 1
|
|
endm
|
|
;--------------------------------------------------------
|
|
;
|
|
; Wow32Intr16Reflector -- This routine reflects a 32 bit
|
|
; interrupt to a 16 bit handler. It switches to the
|
|
; dos extender stack to do so.
|
|
;
|
|
; Inputs: none
|
|
; Outputs: none
|
|
;
|
|
assume ds:nothing,es:nothing,ss:nothing
|
|
public Wow32Intr16Reflector
|
|
Wow32Intr16Reflector proc
|
|
.386p
|
|
push ebp
|
|
mov ebp,esp
|
|
push ds
|
|
push eax
|
|
push ebx
|
|
push edi
|
|
mov ax,ss
|
|
movzx eax,ax
|
|
lar eax,eax
|
|
test eax,(AB_BIG SHL 8)
|
|
jnz w32i16r10
|
|
|
|
movzx ebp,bp
|
|
w32i16r10:
|
|
|
|
;
|
|
; Get a frame on the dosx stack.
|
|
;
|
|
mov ax,selDgroupPM
|
|
mov ds,ax
|
|
assume ds:DGROUP
|
|
|
|
movzx ebx,pbReflStack
|
|
sub pbReflStack,CB_STKFRAME
|
|
|
|
;
|
|
; Build a frame on the stack
|
|
;
|
|
sub bx,30
|
|
mov eax, [ebp+6] ; eip
|
|
mov [bx+20], eax
|
|
mov eax, [ebp+10] ; cs
|
|
mov [bx+24], eax
|
|
|
|
mov [bx + 18],ss ; ss for stack switch back
|
|
mov eax,ebp
|
|
add eax,6 ; ebp, int number
|
|
mov [bx + 14],eax ; esp for stack switch back
|
|
mov ax,[ebp + 14] ; get flags
|
|
mov [bx + 12],ax
|
|
mov ax,cs
|
|
mov [bx + 10],ax
|
|
mov [bx + 8],offset DXPMCODE:w3216r30
|
|
mov eax,[ebp]
|
|
mov [bx],eax ; put ebp on other stack for pop
|
|
;
|
|
; Get handler
|
|
;
|
|
mov di,[ebp + 4] ; int number
|
|
shl di,2 ; al * 4
|
|
add di,offset DGROUP:Wow16BitHandlers
|
|
mov ax,[di]
|
|
mov [bx + 4],ax ; handler ip
|
|
mov ax,[di + 2]
|
|
mov [bx + 6],ax ; handler cs
|
|
|
|
;
|
|
; Set up for stack switch
|
|
;
|
|
push ds
|
|
push ebx
|
|
;
|
|
; Restore registers
|
|
;
|
|
mov ax,[ebp - 2]
|
|
mov ds,ax
|
|
mov eax,[ebp - 6]
|
|
mov ebx,[ebp - 10]
|
|
mov edi,[ebp - 14]
|
|
;
|
|
; Switch stacks, restore ebp, and call handler
|
|
;
|
|
lss esp,[ebp - 20]
|
|
pop ebp
|
|
retf
|
|
;
|
|
; N.B. i31_RMCall looks on the stack to get the original user stack pointer.
|
|
; if you change the stack frame the is passed to the 16 bit int
|
|
; handlers, that WILL break.
|
|
;
|
|
|
|
w3216r30:
|
|
;
|
|
; Switch stacks, deallocate frame from dosx stack and return
|
|
;
|
|
push ebx
|
|
push eax
|
|
push ds
|
|
lds ebx,[esp+10] ;get ss:esp
|
|
mov eax,[esp+16]
|
|
mov [ebx],eax ;eip
|
|
mov eax,[esp+20]
|
|
mov [ebx+4],eax ;cs
|
|
pop ds
|
|
pop eax
|
|
pop ebx
|
|
|
|
lss esp,[esp]
|
|
push ebx
|
|
|
|
|
|
pushfd
|
|
push eax
|
|
mov ax,ss
|
|
movzx eax,ax
|
|
lar eax,eax
|
|
test eax,(AB_BIG SHL 8) ; is the stack big?
|
|
jnz w32i16r40 ; jif yes, use 32bit operations
|
|
pop eax ; restore regs
|
|
popfd
|
|
|
|
rpushfd ; save flags, set virtual int bit
|
|
pop ebx
|
|
push ebp
|
|
movzx ebp, sp
|
|
mov [ebp + 16],ebx ; put flags on iret frame
|
|
pop ebp
|
|
push ds
|
|
mov bx,selDgroupPM
|
|
mov ds,bx
|
|
add pbReflStack,CB_STKFRAME
|
|
pop ds
|
|
pop ebx
|
|
riretd
|
|
|
|
w32i16r40: ; stack is big
|
|
pop eax ; restore regs
|
|
popfd
|
|
|
|
rpushfd32
|
|
pop ebx
|
|
mov [esp + 12],ebx
|
|
push ds
|
|
mov bx,selDgroupPM
|
|
mov ds,bx
|
|
add pbReflStack,CB_STKFRAME
|
|
pop ds
|
|
pop ebx
|
|
riretd32
|
|
|
|
.286p
|
|
Wow32Intr16Reflector endp
|
|
ENDIF
|
|
DXPMCODE ends
|
|
;
|
|
;****************************************************************
|
|
end
|