summaryrefslogtreecommitdiffstats
path: root/board/MAI/bios_emulator/scitech/src/pm/ntdrv/_irq.asm
diff options
context:
space:
mode:
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/pm/ntdrv/_irq.asm')
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/_irq.asm288
1 files changed, 288 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/_irq.asm b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/_irq.asm
new file mode 100644
index 0000000000..11824a0afc
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/_irq.asm
@@ -0,0 +1,288 @@
+;****************************************************************************
+;*
+;* 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 Windows NT device driver
+;*
+;* Description: Low level assembly support for the PM library specific to
+;* Windows NT device drivers.
+;*
+;****************************************************************************
+
+ IDEAL
+
+include "scitech.mac" ; Memory model macros
+
+header _irq ; Set up memory model
+
+begdataseg _irq
+
+ cextern _PM_rtcHandler,CPTR
+ cextern _PM_prevRTC,FCPTR
+
+RtcInside dw 0 ; Are we still handling current interrupt
+sidtBuf df 0 ; Buffer for sidt instruction
+
+enddataseg _irq
+
+begcodeseg _irq ; Start of code segment
+
+cpublic _PM_irqCodeStart
+
+; 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
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+; If we enable interrupts and call into any C based interrupt handling code,
+; we need to setup a bunch of important information for the NT kernel. The
+; code below takes care of this housekeeping for us (see Undocumented NT for
+; details). If we don't do this housekeeping and interrupts are enabled,
+; the kernel will become very unstable and crash within 10 seconds or so.
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ pushad
+ pushfd
+ push fs
+
+ mov ebx,00000030h
+ mov fs,bx
+ sub esp,50h
+ mov ebp,esp
+
+; Setup the exception frame to NULL
+
+ mov ebx,[DWORD cs:0FFDFF000h]
+ mov [DWORD ds:0FFDFF000h], 0FFFFFFFFh
+ mov [DWORD ebp],ebx
+
+; Save away the existing KSS ebp
+
+ mov esi,[DWORD cs:0FFDFF124h]
+ mov ebx,[DWORD esi+00000128h]
+ mov [DWORD ebp+4h],ebx
+ mov [DWORD esi+00000128h],ebp
+
+; Save away the kernel time and the thread mode (kernel/user)
+
+ mov edi,[DWORD esi+00000137h]
+ mov [DWORD ebp+8h],edi
+
+; Set the thread mode (kernel/user) based on the code selector
+
+ mov ebx,[DWORD ebp+7Ch]
+ and ebx,01
+ mov [BYTE esi+00000137h],bl
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+; End of special interrupt Prolog code
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+; 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 eax ; and save for later
+ IODELAYN 3
+ mov al,0Ch
+ out 70h,al
+ IODELAYN 5
+ in al,71h
+
+; Call the C interrupt handler function
+
+ cmp [BYTE RtcInside],1 ; Check for mutual exclusion
+ je @@Exit
+ mov [BYTE RtcInside],1
+ sti ; Enable interrupts
+ cld ; Clear direction flag for C code
+ call [CPTR _PM_rtcHandler]
+ cli ; Disable interrupts on exit!
+ mov [BYTE RtcInside],0
+
+@@Exit: pop eax
+ out 70h,al ; Restore CMOS index register
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+; Start of special epilog code to restore stuff on exit from handler
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+; Restore the KSS ebp
+
+ mov esi,[DWORD cs:0FFDFF124h]
+ mov ebx,[DWORD ebp+4]
+ mov [DWORD esi+00000128h],ebx
+
+; Restore the exception frame
+
+ mov ebx,[DWORD ebp]
+ mov [DWORD fs:00000000],ebx
+
+; Restore the thread mode
+
+ mov ebx,[DWORD ebp+8h]
+ mov esi,[DWORD fs:00000124h]
+ mov [BYTE esi+00000137h],bl
+ add esp, 50h
+ pop fs
+ popfd
+ popad
+
+; Return from interrupt
+
+ iret
+
+cprocend
+
+cpublic _PM_irqCodeEnd
+
+;----------------------------------------------------------------------------
+; void _PM_getISR(int irq,PMFARPTR *handler);
+;----------------------------------------------------------------------------
+; Function to return the specific IRQ handler direct from the IDT.
+;----------------------------------------------------------------------------
+cprocstart _PM_getISR
+
+ ARG idtEntry:UINT, handler:DPTR
+
+ enter_c 0
+ mov ecx,[handler] ; Get address of handler to fill in
+ sidt [sidtBuf] ; Get IDTR register into sidtBuf
+ mov eax,[DWORD sidtBuf+2] ; Get address of IDT into EAX
+ mov ebx,[idtEntry]
+ lea eax,[eax+ebx*8] ; Get entry in the IDT
+ movzx edx,[WORD eax+6] ; Get high order 16-bits
+ shl edx,16 ; Move into top 16-bits of address
+ mov dx,[WORD eax] ; Get low order 16-bits
+ mov [DWORD ecx],edx ; Store linear address of handler
+ mov dx,[WORD eax+2] ; Get selector value
+ mov [WORD ecx+4],dx ; Store selector value
+ leave_c
+ ret
+
+cprocend _PM_getISR
+
+;----------------------------------------------------------------------------
+; void _PM_setISR(int irq,void *handler);
+;----------------------------------------------------------------------------
+; Function to set the specific IRQ handler direct in the IDT.
+;----------------------------------------------------------------------------
+cprocstart _PM_setISR
+
+ ARG irq:UINT, handler:CPTR
+
+ enter_c 0
+ mov ecx,[handler] ; Get address of new handler
+ mov dx,cs ; Get selector for new handler
+ sidt [sidtBuf] ; Get IDTR register into sidtBuf
+ mov eax,[DWORD sidtBuf+2] ; Get address of IDT into EAX
+ mov ebx,[idtEntry]
+ lea eax,[eax+ebx*8] ; Get entry in the IDT
+ cli
+ mov [WORD eax+2],dx ; Store code segment selector
+ mov [WORD eax],cx ; Store low order bits of handler
+ shr ecx,16
+ mov [WORD eax+6],cx ; Store high order bits of handler
+ sti
+ leave_c
+ ret
+
+cprocend _PM_setISR
+
+;----------------------------------------------------------------------------
+; void _PM_restoreISR(int irq,PMFARPTR *handler);
+;----------------------------------------------------------------------------
+; Function to set the specific IRQ handler direct in the IDT.
+;----------------------------------------------------------------------------
+cprocstart _PM_restoreISR
+
+ ARG irq:UINT, handler:CPTR
+
+ enter_c 0
+ mov ecx,[handler]
+ mov dx,[WORD ecx+4] ; Get selector for old handler
+ mov ecx,[DWORD ecx] ; Get address of old handler
+ sidt [sidtBuf] ; Get IDTR register into sidtBuf
+ mov eax,[DWORD sidtBuf+2] ; Get address of IDT into EAX
+ mov ebx,[idtEntry]
+ lea eax,[eax+ebx*8] ; Get entry in the IDT
+ cli
+ mov [WORD eax+2],dx ; Store code segment selector
+ mov [WORD eax],cx ; Store low order bits of handler
+ shr ecx,16
+ mov [WORD eax+6],cx ; Store high order bits of handler
+ sti
+ leave_c
+ ret
+
+cprocend _PM_restoreISR
+
+endcodeseg _irq
+
+ END ; End of module
+
OpenPOWER on IntegriCloud