⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _pmsmx.asm

📁 BIOS emulator and interface to Realmode X86 Emulator Library Can emulate a PCI Graphic Controller V
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;****************************************************************************;*;*					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		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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -