📄 _pmsmx.asm
字号:
iret ; Return from interruptcprocend;----------------------------------------------------------------------------; 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_chainPrevTimerifdef 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 retelse SWAPSTK TmStack ; Swap back to previous stack pushf ; Save state of interrupt flag pushf ; Push flags on stack to simulate interruptifdef 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 retendifcprocend; 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%endmacroelsemacro DELAY jmp short $+2 jmp short $+2 jmp short $+2endmmacro IODELAYN N rept N DELAY endmendmendif;----------------------------------------------------------------------------; 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 interruptcprocend;----------------------------------------------------------------------------; 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 eaxelse pushfifdef USE_NASM call far dword [_PM_prevKey]else call [_PM_prevKey]endifendif jmp @@Exitcprocend;----------------------------------------------------------------------------; 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_chainPrevKeyifdef 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 retelse; 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 interruptifdef USE_NASM call far dword [_PM_prevKey]else call [_PM_prevKey]endif SWAPSTK KyStack ; Swap back to C stack again retendifcprocend;----------------------------------------------------------------------------; 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 eaxelse pushfifdef USE_NASM call far dword [_PM_prevKey15]else call [_PM_prevKey15]endifendif@@Exit: pop es pop ds retf 4cprocend;----------------------------------------------------------------------------; 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 + -