📄 _pmsmx.asm
字号:
iret ; Return from interrupt
cprocend
;----------------------------------------------------------------------------
; PM_chainPrevTimer - Chain to previous timer interrupt and return
;----------------------------------------------------------------------------
; Chains to the previous timer interrupt routine and returns control
; back to the high level interrupt handler.
;----------------------------------------------------------------------------
cprocstart PM_chainPrevTimer
ifdef TNT
push eax
push ebx
push ecx
pushfd ; Push flags on stack to simulate interrupt
mov ax,250Eh ; Call real mode procedure function
mov ebx,[_PM_prevRealTimer]
mov ecx,1 ; Copy real mode flags to real mode stack
int 21h ; Call the real mode code
popfd
pop ecx
pop ebx
pop eax
ret
else
SWAPSTK TmStack ; Swap back to previous stack
pushf ; Save state of interrupt flag
pushf ; Push flags on stack to simulate interrupt
ifdef USE_NASM
call far dword [_PM_prevTimer]
else
call [_PM_prevTimer]
endif
popf ; Restore state of interrupt flag
SWAPSTK TmStack ; Swap back to C stack again
ret
endif
cprocend
; Macro to delay briefly to ensure that enough time has elapsed between
; successive I/O accesses so that the device being accessed can respond
; to both accesses even on a very fast PC.
ifdef USE_NASM
%macro DELAY 0
jmp short $+2
jmp short $+2
jmp short $+2
%endmacro
%macro IODELAYN 1
%rep %1
DELAY
%endrep
%endmacro
else
macro DELAY
jmp short $+2
jmp short $+2
jmp short $+2
endm
macro IODELAYN N
rept N
DELAY
endm
endm
endif
;----------------------------------------------------------------------------
; PM_rtcISR - Real time clock interrupt subroutine dispatcher
;----------------------------------------------------------------------------
; Hardware interrupt handler for the timer interrupt, to dispatch control
; to high level C based subroutines. We save the state of all registers
; in this routine, and switch to a local stack. Interrupts are *off*
; when we call the user code.
;
; NOTE: This routine switches to a local stack before calling any C code,
; and hence is _not_ re-entrant. Make sure your C code executes as
; quickly as possible, since a timer overrun will simply hang the
; system.
;----------------------------------------------------------------------------
cprocfar _PM_rtcISR
push ds ; Save value of DS
push es
pushad ; Save _all_ extended registers
cld ; Clear direction flag
; Clear priority interrupt controller and re-enable interrupts so we
; dont lock things up for long.
mov al,20h
out 0A0h,al
out 020h,al
; Clear real-time clock timeout
in al,70h ; Read CMOS index register
push _ax ; and save for later
IODELAYN 3
mov al,0Ch
out 70h,al
IODELAYN 5
in al,71h
; Call the C interrupt handler function
LOAD_DS ; Load DS register
cmp [BYTE RtcInside],1 ; Check for mutual exclusion
je @@Exit
mov [BYTE RtcInside],1
sti ; Re-enable interrupts
NEWSTK RtcStack ; Switch to local stack
call [CPTR _PM_rtcHandler]
RESTSTK RtcStack ; Restore previous stack
mov [BYTE RtcInside],0
@@Exit: pop _ax
out 70h,al ; Restore CMOS index register
popad ; Restore all extended registers
pop es
pop ds
iret ; Return from interrupt
cprocend
;----------------------------------------------------------------------------
; PM_keyISR - keyboard interrupt subroutine dispatcher
;----------------------------------------------------------------------------
; Hardware interrupt handler for the keyboard interrupt, to dispatch control
; to high level C based subroutines. We save the state of all registers
; in this routine, and switch to a local stack. Interrupts are *off*
; when we call the user code.
;
; NOTE: This routine switches to a local stack before calling any C code,
; and hence is _not_ re-entrant. However we ensure within this routine
; mutual exclusion to the keyboard handling routine.
;----------------------------------------------------------------------------
cprocfar _PM_keyISR
push ds ; Save value of DS
push es
pushad ; Save _all_ extended registers
cld ; Clear direction flag
LOAD_DS ; Load DS register
cmp [BYTE KyInside],1 ; Check for mutual exclusion
je @@Reissued
mov [BYTE KyInside],1
NEWSTK KyStack ; Switch to local stack
call [CPTR _PM_keyHandler] ; Call C code
RESTSTK KyStack ; Restore previous stack
mov [BYTE KyInside],0
@@Exit: popad ; Restore all extended registers
pop es
pop ds
iret ; Return from interrupt
; When the BIOS keyboard handler needs to change the SHIFT status lights
; on the keyboard, in the process of doing this the keyboard controller
; re-issues another interrupt, while the current handler is still executing.
; If we recieve another interrupt while still handling the current one,
; then simply chain directly to the previous handler.
;
; Note that for most DOS extenders, the real mode interrupt handler that we
; install takes care of this for us.
@@Reissued:
ifdef TNT
push eax
push ebx
push ecx
pushfd ; Push flags on stack to simulate interrupt
mov ax,250Eh ; Call real mode procedure function
mov ebx,[_PM_prevRealKey]
mov ecx,1 ; Copy real mode flags to real mode stack
int 21h ; Call the real mode code
popfd
pop ecx
pop ebx
pop eax
else
pushf
ifdef USE_NASM
call far dword [_PM_prevKey]
else
call [_PM_prevKey]
endif
endif
jmp @@Exit
cprocend
;----------------------------------------------------------------------------
; PM_chainPrevkey - Chain to previous key interrupt and return
;----------------------------------------------------------------------------
; Chains to the previous key interrupt routine and returns control
; back to the high level interrupt handler.
;----------------------------------------------------------------------------
cprocstart PM_chainPrevKey
ifdef TNT
push eax
push ebx
push ecx
pushfd ; Push flags on stack to simulate interrupt
mov ax,250Eh ; Call real mode procedure function
mov ebx,[_PM_prevRealKey]
mov ecx,1 ; Copy real mode flags to real mode stack
int 21h ; Call the real mode code
popfd
pop ecx
pop ebx
pop eax
ret
else
; YIKES! For some strange reason, when execution returns from the
; previous keyboard handler, interrupts are re-enabled!! Since we expect
; interrupts to remain off during the duration of our handler, this can
; cause havoc. However our stack macros always turn off interrupts, so they
; will be off when we exit this routine. Obviously there is a tiny weeny
; window when interrupts will be enabled, but there is nothing we can
; do about this.
SWAPSTK KyStack ; Swap back to previous stack
pushf ; Push flags on stack to simulate interrupt
ifdef USE_NASM
call far dword [_PM_prevKey]
else
call [_PM_prevKey]
endif
SWAPSTK KyStack ; Swap back to C stack again
ret
endif
cprocend
;----------------------------------------------------------------------------
; PM_key15ISR - Int 15h keyboard interrupt subroutine dispatcher
;----------------------------------------------------------------------------
; This routine gets called if we have been called to handle the Int 15h
; keyboard interrupt callout from real mode.
;
; Entry: AX - Hardware scan code to process
; Exit: AX - Hardware scan code to process (0 to ignore)
;----------------------------------------------------------------------------
cprocfar _PM_key15ISR
push ds
push es
LOAD_DS
cmp ah,4Fh
jnz @@NotOurs ; Quit if not keyboard callout
pushad
cld ; Clear direction flag
xor ah,ah ; AX := scan code
NEWSTK Ky15Stack ; Switch to local stack
push _ax
call [CPTR _PM_key15Handler] ; Call C code
_add sp,2,4
RESTSTK Ky15Stack ; Restore previous stack
test ax,ax
jz @@1
stc ; Set carry to process as normal
jmp @@2
@@1: clc ; Clear carry to ignore scan code
@@2: popad
jmp @@Exit ; We are done
@@NotOurs:
ifdef TNT
push eax
push ebx
push ecx
pushfd ; Push flags on stack to simulate interrupt
mov ax,250Eh ; Call real mode procedure function
mov ebx,[_PM_prevRealKey15]
mov ecx,1 ; Copy real mode flags to real mode stack
int 21h ; Call the real mode code
popfd
pop ecx
pop ebx
pop eax
else
pushf
ifdef USE_NASM
call far dword [_PM_prevKey15]
else
call [_PM_prevKey15]
endif
endif
@@Exit: pop es
pop ds
retf 4
cprocend
;----------------------------------------------------------------------------
; PM_breakISR - Control Break interrupt subroutine dispatcher
;----------------------------------------------------------------------------
; Hardware interrupt handler for the Ctrl-Break interrupt. We simply set
; the Ctrl-Break flag to a 1 and leave (note that this is accessed through
; a far pointer, as it may well be located in conventional memory).
;----------------------------------------------------------------------------
cprocfar _PM_breakISR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -