📄 _pmsmx.asm
字号:
;****************************************************************************;*;* SciTech OS Portability Manager Library;*;* ========================================================================;*;* The contents of this file are subject to the SciTech MGL Public;* License Version 1.0 (the "License"); you may not use this file;* except in compliance with the License. You may obtain a copy of;* the License at http://www.scitechsoft.com/mgl-license.txt;*;* Software distributed under the License is distributed on an;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or;* implied. See the License for the specific language governing;* rights and limitations under the License.;*;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.;*;* The Initial Developer of the Original Code is SciTech Software, Inc.;* All Rights Reserved.;*;* ========================================================================;*;* Language: 80386 Assembler, TASM 4.0 or NASM;* Environment: 32-bit SMX embedded systems development;*;* Description: Low level assembly support for the PM library specific to;* SMX interrupt handling.;*;**************************************************************************** IDEALinclude "scitech.mac" ; Memory model macrosheader _pmsmx ; Set up memory model; Define the size of our local stacks. For real mode code they cant be; that big, but for 32 bit protected mode code we can make them nice and; large so that complex C functions can be used.MOUSE_STACK EQU 4096TIMER_STACK EQU 4096KEY_STACK EQU 1024INT10_STACK EQU 1024ifdef USE_NASM; Macro to load DS and ES registers with correct value.%imacro LOAD_DS 0 mov ds,[cs:_PM_savedDS] mov es,[cs:_PM_savedDS]%endmacro; Note that interrupts we disable interrupts during the following stack; %imacro for correct operation, but we do not enable them again. Normally; these %imacros are used within interrupt handlers so interrupts should; already be off. We turn them back on explicitly later if the user code; needs them to be back on.; Macro to switch to a new local stack.%imacro NEWSTK 1 cli mov [seg_%1],ss mov [ptr_%1],_sp mov [TempSeg],ds mov ss,[TempSeg] mov _sp,offset %1%endmacro; %imacro to switch back to the old stack.%imacro RESTSTK 1 cli mov ss,[seg_%1] mov _sp,[ptr_%1]%endmacro; %imacro to swap the current stack with the one saved away.%imacro SWAPSTK 1 cli mov ax,ss xchg ax,[seg_%1] mov ss,ax xchg _sp,[ptr_%1]%endmacroelse; Macro to load DS and ES registers with correct value.MACRO LOAD_DS mov ds,[cs:_PM_savedDS] mov es,[cs:_PM_savedDS]ENDM; Note that interrupts we disable interrupts during the following stack; macro for correct operation, but we do not enable them again. Normally; these macros are used within interrupt handlers so interrupts should; already be off. We turn them back on explicitly later if the user code; needs them to be back on.; Macro to switch to a new local stack.MACRO NEWSTK stkname cli mov [seg_&stkname&],ss mov [ptr_&stkname&],_sp mov [TempSeg],ds mov ss,[TempSeg] mov _sp,offset stknameENDM; Macro to switch back to the old stack.MACRO RESTSTK stkname cli mov ss,[seg_&stkname&] mov _sp,[ptr_&stkname&]ENDM; Macro to swap the current stack with the one saved away.MACRO SWAPSTK stkname cli mov ax,ss xchg ax,[seg_&stkname&] mov ss,ax xchg _sp,[ptr_&stkname&]ENDMendifbegdataseg _pmsmx cextern _PM_savedDS,USHORT cextern _PM_critHandler,CPTR cextern _PM_breakHandler,CPTR cextern _PM_timerHandler,CPTR cextern _PM_rtcHandler,CPTR cextern _PM_keyHandler,CPTR cextern _PM_key15Handler,CPTR cextern _PM_mouseHandler,CPTR cextern _PM_int10Handler,CPTR cextern _PM_ctrlCPtr,DPTR cextern _PM_ctrlBPtr,DPTR cextern _PM_critPtr,DPTR cextern _PM_prevTimer,FCPTR cextern _PM_prevRTC,FCPTR cextern _PM_prevKey,FCPTR cextern _PM_prevKey15,FCPTR cextern _PM_prevBreak,FCPTR cextern _PM_prevCtrlC,FCPTR cextern _PM_prevCritical,FCPTR cextern _PM_prevRealTimer,ULONG cextern _PM_prevRealRTC,ULONG cextern _PM_prevRealKey,ULONG cextern _PM_prevRealKey15,ULONG cextern _PM_prevRealInt10,ULONGcpublic _PM_pmsmxDataStart; Allocate space for all of the local stacks that we need. These stacks; are not very large, but should be large enough for most purposes; (generally you want to handle these interrupts quickly, simply storing; the information for later and then returning). If you need bigger; stacks then change the appropriate value in here. ALIGN 4 dclb MOUSE_STACK ; Space for local stack (small)MsStack: ; Stack starts at end!ptr_MsStack DUINT 0 ; Place to store old stack offsetseg_MsStack dw 0 ; Place to store old stack segment ALIGN 4 dclb INT10_STACK ; Space for local stack (small)Int10Stack: ; Stack starts at end!ptr_Int10Stack DUINT 0 ; Place to store old stack offsetseg_Int10Stack dw 0 ; Place to store old stack segment ALIGN 4 dclb TIMER_STACK ; Space for local stack (small)TmStack: ; Stack starts at end!ptr_TmStack DUINT 0 ; Place to store old stack offsetseg_TmStack dw 0 ; Place to store old stack segment ALIGN 4 dclb TIMER_STACK ; Space for local stack (small)RtcStack: ; Stack starts at end!ptr_RtcStack DUINT 0 ; Place to store old stack offsetseg_RtcStack dw 0 ; Place to store old stack segmentRtcInside dw 0 ; Are we still handling current interrupt ALIGN 4 dclb KEY_STACK ; Space for local stack (small)KyStack: ; Stack starts at end!ptr_KyStack DUINT 0 ; Place to store old stack offsetseg_KyStack dw 0 ; Place to store old stack segmentKyInside dw 0 ; Are we still handling current interrupt ALIGN 4 dclb KEY_STACK ; Space for local stack (small)Ky15Stack: ; Stack starts at end!ptr_Ky15Stack DUINT 0 ; Place to store old stack offsetseg_Ky15Stack dw 0 ; Place to store old stack segmentTempSeg dw 0 ; Place to store stack segmentcpublic _PM_pmsmxDataEndenddataseg _pmsmxbegcodeseg _pmsmx ; Start of code segmentcpublic _PM_pmsmxCodeStart;----------------------------------------------------------------------------; PM_mouseISR - Mouse interrupt subroutine dispatcher;----------------------------------------------------------------------------; Interrupt subroutine called by the mouse driver upon interrupts, to; dispatch control to high level C based subroutines. Interrupts are on; when we call the user code.;; It is _extremely_ important to save the state of the extended registers; as these may well be trashed by the routines called from here and not; restored correctly by the mouse interface module.;; NOTE: This routine switches to a local stack before calling any C code,; and hence is _not_ re-entrant. For mouse handlers this is not a; problem, as the mouse driver arbitrates calls to the user mouse; handler for us.;; Entry: AX - Condition mask giving reason for call; BX - Mouse button state; CX - Horizontal cursor coordinate; DX - Vertical cursor coordinate; SI - Horizontal mickey value; DI - Vertical mickey value;;----------------------------------------------------------------------------cprocfar _PM_mouseISR push ds ; Save value of DS push es pushad ; Save _all_ extended registers cld ; Clear direction flag LOAD_DS ; Load DS register NEWSTK MsStack ; Switch to local stack; Call the installed high level C code routine clrhi dx ; Clear out high order values clrhi cx clrhi bx clrhi ax sgnhi si sgnhi di push _di push _si push _dx push _cx push _bx push _ax sti ; Enable interrupts call [CPTR _PM_mouseHandler] _add sp,12,24 RESTSTK MsStack ; Restore previous stack popad ; Restore all extended registers pop es pop ds ret ; We are done!!cprocend;----------------------------------------------------------------------------; PM_timerISR - Timer 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_timerISR push ds ; Save value of DS push es pushad ; Save _all_ extended registers cld ; Clear direction flag LOAD_DS ; Load DS register NEWSTK TmStack ; Switch to local stack call [CPTR _PM_timerHandler] RESTSTK TmStack ; Restore previous stack popad ; Restore all extended registers pop es pop ds
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -