mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1110 lines
36 KiB
1110 lines
36 KiB
title "Irql Processing"
|
|
;++
|
|
;
|
|
; Copyright (c) 1989 Microsoft Corporation
|
|
; Copyright (c) 1992 AST Research Inc.
|
|
;
|
|
; Module Name:
|
|
;
|
|
; astirql.asm
|
|
;
|
|
; Abstract:
|
|
;
|
|
; ASTMP IRQL
|
|
;
|
|
; This module implements the code necessary to raise and lower i386
|
|
; Irql and dispatch software interrupts with the AST MP hardware.
|
|
;
|
|
; Author:
|
|
;
|
|
; Shie-Lin Tzong (shielint) 8-Jan-1990
|
|
;
|
|
; Environment:
|
|
;
|
|
; Kernel mode only.
|
|
;
|
|
; Revision History:
|
|
;
|
|
; Quang Phan (v-quangp) 15-Dec-92
|
|
; Implemented the fast SetLocalInterruptMask in Raise/LowerIrql.
|
|
; Removed spinlock in Raise/LowerIrql routines.
|
|
;
|
|
; Quang Phan (v-quangp) 24-Jul-1992
|
|
; Converted to AST MP hardware.
|
|
;
|
|
; John Vert (jvert) 27-Nov-1991
|
|
; Moved from kernel into HAL
|
|
;
|
|
;--
|
|
|
|
.386p
|
|
.xlist
|
|
include hal386.inc
|
|
include callconv.inc
|
|
include mac386.inc
|
|
include i386\ix8259.inc
|
|
include i386\kimacro.inc
|
|
include i386\astebi2.inc
|
|
include i386\astmp.inc
|
|
.list
|
|
|
|
|
|
EXTRNP _KeBugCheck,1,IMPORT
|
|
|
|
extrn _HalpApcInterrupt:NEAR
|
|
extrn _HalpDispatchInterrupt:NEAR
|
|
extrn _HalpApcInterrupt2ndEntry:NEAR
|
|
extrn _HalpDispatchInterrupt2ndEntry:NEAR
|
|
extrn _KiUnexpectedInterrupt:NEAR
|
|
extrn _HalpBusType:DWORD
|
|
extrn _EBI2_CallTab:DWORD
|
|
extrn _EBI2_MMIOTable:DWORD
|
|
extrn _EBI2_Lock:DWORD
|
|
extrn HalpIRQLtoEBIIntNumber:DWORD
|
|
extrn _EBI2_revision:DWORD
|
|
EXTRNP _DisplPanel,1
|
|
EXTRNP Kei386EoiHelper,0,IMPORT
|
|
EXTRNP _KiDispatchInterrupt,0,IMPORT
|
|
;
|
|
; Interrupt flag bit maks for EFLAGS
|
|
;
|
|
EFLAGS_IF equ 200H
|
|
EFLAGS_SHIFT equ 9
|
|
;
|
|
;
|
|
; IRQL level of hardware interrupts
|
|
;
|
|
HARDWARE_LEVEL equ 12
|
|
|
|
_DATA SEGMENT DWORD PUBLIC 'DATA'
|
|
;
|
|
;;;;;;;;;;;;;;;;
|
|
;
|
|
; Information for irq, irql and mask (EBI2) translation
|
|
;
|
|
;System System Bus
|
|
;IRQL EBI Vector IRQ Common use Name
|
|
;----- --- ------ ------ ---------- ----
|
|
; 00 LOW_LEV
|
|
; 01 APC_LEVEL
|
|
; 02 25 ??? LSI DPC_LEVEL
|
|
; 03 WAKE_LEVEL
|
|
; 04
|
|
; 05
|
|
; 06
|
|
; 07
|
|
; 08
|
|
; 09
|
|
; 10
|
|
; 11
|
|
; 12 7 PVB+7 EISA IRQ7 LPT1
|
|
; 13 6 PVB+6 EISA IRQ6 Flpy
|
|
; 14 5 PVB+5 EISA IRQ5 LPT2
|
|
; 15 4 PVB+4 EISA IRQ4 COM1
|
|
; 16 3 PVB+3 EISA IRQ3 COM2
|
|
; 17 15 PVB+15 EISA IRQ15
|
|
; 18 14 PVB+14 EISA IRQ14 AT disk
|
|
; 19 13 PVB+13 EISA IRQ13
|
|
; 20 12 PVB+12 EISA IRQ12
|
|
; 21 11 PVB+11 EISA IRQ11
|
|
; 22 10 PVB+10 EISA IRQ10
|
|
; 23 9 PVB+9 EISA IRQ9
|
|
; 24 8 PVB+8 EISA IRQ8
|
|
; 25 2 PVB+9 EISA IRQ2 (IRQ chaining)
|
|
; 26 1 PVB+1 EISA IRQ1 Kbd
|
|
; 27 0 PVB+0 EISA IRQ8 RTC PROFILE_LEVEL
|
|
; 28 8 PVB EISA IRQ0 CLOCK2_LEVEL
|
|
; 29 26 PVB+26 IPI IPI_LEVELx
|
|
; 30 24 PVB+24 SPI POWER_LEVEL
|
|
; 31 HIGH_LEVEL
|
|
;
|
|
;
|
|
; Notes:
|
|
; 1. PVB: PRIMARY_VECTOR_BASE = 30h (PIC1BASE = 30h, PIC2BASE = 38h)
|
|
;
|
|
;;;;;;;;;;;;;;;;
|
|
;
|
|
; CCHAR HalpIRQLtoEBIBitMask[32]; This array is used to get the value
|
|
; for the EBI bitmask from the KIRQL.
|
|
Public _HalpIRQLtoEBIBitMask
|
|
align 4
|
|
_HalpIRQLtoEBIBitMask Label Byte
|
|
dd 0 ;IRQL 0 (Unused Mask)
|
|
dd 0 ;IRQL 1
|
|
dd 1 SHL (IRQ_25) ;IRQL 2 (EBI IRQ-25)
|
|
dd 0 ;IRQL 3
|
|
dd 0 ;IRQL 4
|
|
dd 0 ;IRQL 5
|
|
dd 0 ;IRQL 6
|
|
dd 0 ;IRQL 7
|
|
dd 0 ;IRQL 8
|
|
dd 0 ;IRQL 9
|
|
dd 0 ;IRQL 10
|
|
dd 0 ;IRQL 11
|
|
dd 1 SHL (IRQ_7) ;IRQL 12
|
|
dd 1 SHL (IRQ_6) ;IRQL 13
|
|
dd 1 SHL (IRQ_5) ;IRQL 14
|
|
dd 1 SHL (IRQ_4) ;IRQL 15
|
|
dd 1 SHL (IRQ_3) ;IRQL 16
|
|
dd 1 SHL (IRQ_15) ;IRQL 17
|
|
dd 1 SHL (IRQ_14) ;IRQL 18
|
|
dd 1 SHL (IRQ_13) ;IRQL 19
|
|
dd 1 SHL (IRQ_12) ;IRQL 20
|
|
dd 1 SHL (IRQ_11) ;IRQL 21
|
|
dd 1 SHL (IRQ_10) ;IRQL 22
|
|
dd 1 SHL (IRQ_9) ;IRQL 23
|
|
dd 1 SHL (IRQ_8) ;IRQL 24
|
|
dd 1 SHL (IRQ_2) ;IRQL 25
|
|
dd 1 SHL (IRQ_1) ;IRQL 26
|
|
dd 1 SHL (IRQ_8) ;IRQL 27 (IRQ-8) (Profile clock)
|
|
dd 0 ;IRQL 28 (IRQ-0) (clock)
|
|
dd 1 SHL (IRQ_26) ;IRQL 29 (IPI-0)
|
|
dd 1 SHL (IRQ_24) ;IRQL 30 (SPI-0)
|
|
dd 0 ;IRQL 31
|
|
;
|
|
; CCHAR HalpIRQLtoVector[36]; this array is used to get the interrupt
|
|
; vector used for a given KIRQL, zero
|
|
; means no vector is used for the KIRQL
|
|
Public _HalpIRQLtoVector
|
|
_HalpIRQLtoVector Label Byte
|
|
; ;IRQL
|
|
db 0 ;0
|
|
db 0 ;1 APC_LEVEL
|
|
db 0 ;2 DISPATCH_LEVEL
|
|
db 0 ;3 WAKE_LEVEL
|
|
db 0 ;4
|
|
db 0 ;5
|
|
db 0 ;6
|
|
db 0 ;7
|
|
db 0 ;8
|
|
db 0 ;9
|
|
db 0 ;10
|
|
db 0 ;11
|
|
db PRIMARY_VECTOR_BASE+7 ;12 irq7
|
|
db PRIMARY_VECTOR_BASE+6 ;13 irq6
|
|
db PRIMARY_VECTOR_BASE+5 ;14 irq5
|
|
db PRIMARY_VECTOR_BASE+4 ;15 irq4
|
|
db PRIMARY_VECTOR_BASE+3 ;16 irq3
|
|
db PRIMARY_VECTOR_BASE+15 ;17 irq15
|
|
db PRIMARY_VECTOR_BASE+14 ;18 irq14
|
|
db PRIMARY_VECTOR_BASE+13 ;19 irq13
|
|
db PRIMARY_VECTOR_BASE+12 ;20 irq12
|
|
db PRIMARY_VECTOR_BASE+11 ;21 irq11
|
|
db PRIMARY_VECTOR_BASE+10 ;22 irq10
|
|
db PRIMARY_VECTOR_BASE+9 ;23 irq9
|
|
db PRIMARY_VECTOR_BASE+8 ;24 irq8
|
|
db 0 ;25 irq2 (used for chaining)
|
|
db PRIMARY_VECTOR_BASE+1 ;26 irq1
|
|
db PRIMARY_VECTOR_BASE+8 ;27 irq8 PROFILE_LEVEL
|
|
db PRIMARY_VECTOR_BASE ;28 irq0 CLOCK2_LEVEL
|
|
db PRIMARY_VECTOR_BASE+26 ;29 IPI_LEVEL
|
|
db PRIMARY_VECTOR_BASE+24 ;30 POWER_LEVEL (SPI)
|
|
db 0 ;prevent CPL 0 enable changes ;HIGH_LEVEL
|
|
db 0, 0, 0, 0 ;four extra levels for good luck
|
|
|
|
;
|
|
; CCHAR HalpBusIntToIRQL[16]; this array is used to get the IRQL
|
|
; from the the Bus Interrupt number
|
|
Public _HalpBusIntToIRQL
|
|
_HalpBusIntToIRQL Label Byte
|
|
; IRQL ;Bus Interrupt number
|
|
db CLOCK2_LEVEL ;0
|
|
db PROFILE_LEVEL-1 ;1
|
|
db 0 ;2
|
|
db PROFILE_LEVEL-11 ;3
|
|
db PROFILE_LEVEL-12 ;4
|
|
db PROFILE_LEVEL-13 ;5
|
|
db PROFILE_LEVEL-14 ;6
|
|
db PROFILE_LEVEL-15 ;7
|
|
db PROFILE_LEVEL-3 ;8
|
|
db PROFILE_LEVEL-4 ;9
|
|
db PROFILE_LEVEL-5 ;10
|
|
db PROFILE_LEVEL-6 ;11
|
|
db PROFILE_LEVEL-7 ;12
|
|
db PROFILE_LEVEL-8 ;13
|
|
db PROFILE_LEVEL-9 ;14
|
|
db PROFILE_LEVEL-10 ;15
|
|
|
|
;
|
|
;Translation table from Irql to EBI interrupt bit mask. This table is
|
|
;used for setting the processor interrupt level (irql)
|
|
;
|
|
public KiEBI2IntMaskTable
|
|
KiEBI2IntMaskTable label dword
|
|
align 4
|
|
|
|
; ILS <--- irqs ----->
|
|
; PSP
|
|
; III 11.. ..10
|
|
; ... 54 ..
|
|
; vvv vv vv
|
|
;
|
|
dd 00000000000000000000000000000000B ; irql 0
|
|
dd 00000000000000000000000000000000B ; irql 1
|
|
dd 00000000000000000000000000000000B ; irql 2
|
|
dd 00000000000000000000000000000000B ; irql 3
|
|
dd 00000000000000000000000000000000B ; irql 4
|
|
dd 00000010000000000000000000000000B ; irql 5
|
|
dd 00000010000000000000000000000000B ; irql 6
|
|
dd 00000010000000000000000000000000B ; irql 7
|
|
dd 00000010000000000000000000000000B ; irql 8
|
|
dd 00000010000000000000000000000000B ; irql 9
|
|
dd 00000010000000000000000000000000B ; irql 10
|
|
dd 00000010000000000000000000000000B ; irql 11
|
|
dd 00000010000000000000000010000000B ; irql 12 irq7
|
|
dd 00000010000000000000000011000000B ; irql 13 irq6
|
|
dd 00000010000000000000000011100000B ; irql 14 irq5
|
|
dd 00000010000000000000000011110000B ; irql 15 irq4
|
|
dd 00000010000000000000000011111000B ; irql 16 irq3
|
|
dd 00000010000000001000000011111000B ; irql 17 irq15
|
|
dd 00000010000000001100000011111000B ; irql 18 irq14
|
|
dd 00000010000000001110000011111000B ; irql 19 irq13
|
|
dd 00000010000000001111000011111000B ; irql 20 irq12
|
|
dd 00000010000000001111100011111000B ; irql 21 irq11
|
|
dd 00000010000000001111110011111000B ; irql 22 irq10
|
|
dd 00000010000000001111111011111000B ; irql 23 irq9
|
|
dd 00000010000000001111111111111010B ; irql 24 irq8
|
|
dd 00000010000000001111111011111000B ; irql 25 irq2
|
|
dd 00000010000000001111111011111010B ; irql 26 irq1
|
|
dd 00000010000000001111111111111010B ; irql 27 irq8 (Profile)
|
|
dd 00000010000000001111111111111011B ; irql 28 irq0
|
|
dd 00000110000000001111111111111011B ; irql 29 ipi
|
|
dd 00000111000000001111111111111011B ; irql 30 spi
|
|
dd 00000111000000001111111111111011B ; irql 31
|
|
;
|
|
; 10987654321098765432109876543210- ; bit position
|
|
;
|
|
align 4
|
|
;
|
|
; The following tables define the addresses of software interrupt routers
|
|
; Use this table if there is NO machine state frame on stack already
|
|
;
|
|
public SWInterruptHandlerTable
|
|
SWInterruptHandlerTable label dword
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
|
|
dd offset FLAT:_HalpApcInterrupt ; irql 1
|
|
dd offset FLAT:_HalpDispatchInterrupt ; irql 2
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 3
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 4
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 5
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 6
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 7
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 8
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 9
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 10
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 11
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 12
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 13
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 14
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 15
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 16
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 17
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 18
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 19
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 20
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 21
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 22
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 23
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 24
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 25
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 26
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 27
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 28
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 29)
|
|
|
|
public ASTSWInterruptHandlerTable
|
|
ASTSWInterruptHandlerTable label dword
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
|
|
dd offset FLAT:_HalpApcInterrupt ; irql 1
|
|
dd offset FLAT:_ASTDispatchInterrupt ; irql 2
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 3
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 4
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 5
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 6
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 7
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 8
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 9
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 10
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 11
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 12
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 13
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 14
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 15
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 16
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 17
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 18
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 19
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 20
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 21
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 22
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 23
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 24
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 25
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 26
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 27
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 28
|
|
dd offset FLAT:_KiUnexpectedInterrupt ; irql 29)
|
|
;
|
|
; The following table picks up the highest pending software irq level
|
|
; from software irr
|
|
;
|
|
|
|
public SWInterruptLookUpTable
|
|
SWInterruptLookUpTable label byte
|
|
db 0 ; SWIRR=0, so highest pending SW irql= 0
|
|
db 0 ; SWIRR=1, so highest pending SW irql= 0
|
|
db 1 ; SWIRR=2, so highest pending SW irql= 1
|
|
db 1 ; SWIRR=3, so highest pending SW irql= 1
|
|
db 2 ; SWIRR=4, so highest pending SW irql= 2
|
|
db 2 ; SWIRR=5, so highest pending SW irql= 2
|
|
db 2 ; SWIRR=6, so highest pending SW irql= 2
|
|
db 2 ; SWIRR=7, so highest pending SW irql= 2
|
|
db 3 ; SWIRR=8, so highest pending SW irql= 3
|
|
db 3 ; SWIRR=9, so highest pending SW irql= 3
|
|
db 3 ; SWIRR=A, so highest pending SW irql= 3
|
|
db 3 ; SWIRR=B, so highest pending SW irql= 3
|
|
db 3 ; SWIRR=C, so highest pending SW irql= 3
|
|
db 3 ; SWIRR=D, so highest pending SW irql= 3
|
|
db 3 ; SWIRR=E, so highest pending SW irql= 3
|
|
db 3 ; SWIRR=F, so highest pending SW irql= 3
|
|
|
|
db 4 ; SWIRR=10, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=11, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=12, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=13, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=14, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=15, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=16, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=17, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=18, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=19, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=1A, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=1B, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=1C, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=1D, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=1E, so highest pending SW irql= 4
|
|
db 4 ; SWIRR=1F, so highest pending SW irql= 4
|
|
|
|
|
|
public EBI2_ProcIntHandle
|
|
public EBI2_maskInfo
|
|
EBI2_maskInfo dd 8 dup(0)
|
|
EBI2_ProcIntHandle dd 0
|
|
|
|
|
|
|
|
|
|
_DATA ENDS
|
|
|
|
page ,132
|
|
subttl "Raise Irql"
|
|
|
|
_TEXT SEGMENT DWORD PUBLIC 'CODE'
|
|
ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
|
|
;++
|
|
;
|
|
; KIRQL
|
|
; FASTCALL
|
|
; KfRaiseIrql (
|
|
; IN KIRQL NewIrql
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is used to raise IRQL to the specified value.
|
|
; Also, a mask will be used to mask off all the lower lever 8259
|
|
; interrupts.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; (ecx) = NewIrql - the new irql to be raised to
|
|
;
|
|
; Return Value:
|
|
;
|
|
; OldIrql - the addr of a variable which old irql should be stored
|
|
;
|
|
;--
|
|
|
|
; equates for accessing arguments
|
|
; since eflags and iret addr are pushed into stack, all the arguments
|
|
; offset by 8 bytes
|
|
;
|
|
|
|
cPublicFastCall KfRaiseIrql,1
|
|
cPublicFpo 0,1
|
|
|
|
pushfd
|
|
cli
|
|
movzx eax,cl ; get new irql value
|
|
movzx ecx,byte ptr fs:PcIrql ; get current irql
|
|
|
|
if DBG
|
|
cmp cl,al ; old > new?
|
|
jbe short Kri99 ; no, we're OK
|
|
push eax ; put new irql where we can find it
|
|
push ecx ; put old irql where we can find it
|
|
mov byte ptr fs:PcIrql,0 ; avoid recursive error
|
|
stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL>
|
|
Kri99:
|
|
endif
|
|
mov fs:PcIrql, al ; set the new irql
|
|
cmp al,HARDWARE_LEVEL ; software level?
|
|
jb short kri10 ; go skip setting 8259 hardware
|
|
|
|
;
|
|
;Disable interrupt locally. Depending on type of hardware this function
|
|
;will jump to the appropriate code that was setup priviously via the
|
|
;PcrEBI2SetLocalIntMaskFunction pointer
|
|
;
|
|
mov eax,KiEBI2IntMaskTable[eax*4] ;get ebi2 bitmask (eax=irql)
|
|
or eax,fs:PcIDR ;mask off irq which disabled
|
|
jmp dword ptr fs:[PcHal.PcrEBI2RaiseIrqlFunction]
|
|
|
|
|
|
;----------------------------
|
|
;
|
|
;Code for using direct hardware access (32-bit interface hw)
|
|
;
|
|
KriDirectAccessIntMask32:
|
|
|
|
mov edx,fs:PcHal.PcrEBI2portAddress0
|
|
mov dword ptr [edx], eax
|
|
mov eax, dword ptr [edx] ;flush write buffer
|
|
;
|
|
;
|
|
; Note: It is very important that we set the old irql AFTER we raised to
|
|
; the new irql. Otherwise, if there is an interrupt that comes in between
|
|
; and the OldIrql is not a local variable, the caller will get the wrong
|
|
; OldIrql. The bottom line is the raising irql and returning old irql has
|
|
; to be atomic to the caller.
|
|
|
|
kri10:
|
|
mov eax, ecx ; (al) = OldIrql
|
|
popfd ; restore flags (including interrupts)
|
|
|
|
fstRET KfRaiseIrql
|
|
|
|
|
|
|
|
;----------------------------
|
|
;
|
|
;Code for using direct hardware access (8-bit interface hw)
|
|
;
|
|
KriDirectAccessIntMask8:
|
|
|
|
mov edx,fs:PcHal.PcrEBI2portAddress0
|
|
mov byte ptr [edx], al
|
|
mov edx,fs:PcHal.PcrEBI2portAddress1
|
|
mov byte ptr [edx], ah
|
|
shr eax,24 ;get mask bit 24-31
|
|
mov edx,fs:PcHal.PcrEBI2portAddress3
|
|
mov byte ptr [edx], al
|
|
mov al, byte ptr [edx] ;flush write buffer
|
|
|
|
mov eax, ecx ; (al) = OldIrql
|
|
popfd ; restore flags (including interrupts)
|
|
|
|
fstRET KfRaiseIrql
|
|
|
|
|
|
|
|
;----------------------------
|
|
;
|
|
;Code for using RegisterEBI2 Call
|
|
;eax=intMask
|
|
;
|
|
KriRegSetLocalIntMask:
|
|
|
|
push esi
|
|
push ecx
|
|
mov esi,fs:PcHal.PcrEBI2ProcInterruptHandle
|
|
lea edx, _EBI2_CallTab
|
|
call [edx]+RegSetLocalIntMask
|
|
pop esi ;restore esi
|
|
pop eax
|
|
|
|
popfd ; restore flags (including interrupts)
|
|
fstRET KfRaiseIrql
|
|
|
|
fstENDP KfRaiseIrql
|
|
|
|
|
|
page ,132
|
|
subttl "Lower irql"
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; FASTCALL
|
|
; KfLowerIrql (
|
|
; IN KIRQL NewIrql
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is used to lower IRQL to the specified value.
|
|
; The IRQL and PIRQL will be updated accordingly. Also, this
|
|
; routine checks to see if any software interrupt should be
|
|
; generated. The following condition will cause software
|
|
; interrupt to be simulated:
|
|
; any software interrupt which has higher priority than
|
|
; current IRQL's is pending.
|
|
;
|
|
; NOTE: This routine simulates software interrupt as long as
|
|
; any pending SW interrupt level is higher than the current
|
|
; IRQL, even when interrupts are disabled.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; (cl) = NewIrql - the new irql to be set.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
|
|
|
|
cPublicFastCall KfLowerIrql,1
|
|
pushfd ; save caller's eflags
|
|
cli
|
|
movzx ecx, cl ; get new irql value
|
|
mov al, fs:PcIrql ; get old irql value
|
|
|
|
if DBG
|
|
cmp cl,al
|
|
jbe short Kli99
|
|
push ecx ; new irql for debugging
|
|
push fs:PcIrql ; old irql for debugging
|
|
mov byte ptr fs:PcIrql,HIGH_LEVEL ; avoid recursive error
|
|
stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL>
|
|
Kli99:
|
|
endif
|
|
cmp al,HARDWARE_LEVEL ; see if hardware was masked
|
|
jb short Soft_Ints
|
|
|
|
|
|
;
|
|
;Disable interrupt locally. Depending on type of hardware this function
|
|
;will jump to the appropriate code that was setup priviously via the
|
|
;PcrEBI2SetLocalIntMaskFunction pointer
|
|
;
|
|
mov eax,KiEBI2IntMaskTable[ecx*4] ;get ebi2 bitmask (eax=irql)
|
|
jmp dword ptr fs:[PcHal.PcrEBI2LowerIrqlFunction]
|
|
|
|
|
|
;----------------------------
|
|
;
|
|
;Code for using direct hardware access (32-bit interface hw)
|
|
;
|
|
KliDirectAccessIntMask32:
|
|
|
|
or eax,fs:PcIDR ;mask off irq which disabled
|
|
mov edx,fs:PcHal.PcrEBI2portAddress0
|
|
mov dword ptr [edx], eax
|
|
mov eax, dword ptr [edx] ;flush write buffer
|
|
|
|
Soft_Ints:
|
|
mov fs:PcIrql, cl ; save new IRQL
|
|
Kli02a:
|
|
mov edx, fs:dword ptr PcIRR
|
|
and edx,0Eh ; mask for valid IRR bits
|
|
jnz short Kli09a ; jump if yes
|
|
|
|
Kli08a:
|
|
popfd ; restore flags, including ints
|
|
fstRET KfLowerIrql ; RETURN
|
|
|
|
Kli09a:
|
|
movzx eax, SWInterruptLookUpTable[edx]
|
|
;
|
|
;When we come to Kli10a, (eax) = soft interrupt index
|
|
;
|
|
Kli10a:
|
|
cmp al, fs:PcIrql ; compare with current IRQL
|
|
jna short Kli08a ; jump if higher priority
|
|
|
|
call ASTSWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
|
|
; to the appropriate handler
|
|
jmp short Kli02a ; check for another
|
|
|
|
|
|
|
|
;----------------------------
|
|
;
|
|
;Code for using direct hardware access (8-bit interface hw)
|
|
;
|
|
KliDirectAccessIntMask8:
|
|
|
|
or eax,fs:PcIDR ;mask off irq which disabled
|
|
mov edx,fs:PcHal.PcrEBI2portAddress0
|
|
mov byte ptr [edx], al
|
|
mov edx,fs:PcHal.PcrEBI2portAddress1
|
|
mov byte ptr [edx], ah
|
|
shr eax,24 ;get mask bit 24-31
|
|
mov edx,fs:PcHal.PcrEBI2portAddress3
|
|
mov byte ptr [edx], al
|
|
mov al, byte ptr [edx] ;flush write buffer
|
|
|
|
mov fs:PcIrql, cl ; save new IRQL
|
|
Kli02:
|
|
mov edx, fs:dword ptr PcIRR
|
|
and edx,0Eh ; mask for valid IRR bits
|
|
jnz short Kli09 ; jump if yes
|
|
|
|
Kli08:
|
|
popfd ; restore flags, including ints
|
|
fstRET KfLowerIrql ; RETURN
|
|
|
|
Kli09:
|
|
movzx eax, SWInterruptLookUpTable[edx]
|
|
;
|
|
;When we come to Kli10, (eax) = soft interrupt index
|
|
;
|
|
Kli10:
|
|
cmp al, fs:PcIrql ; compare with current IRQL
|
|
jna short Kli08 ; jump if higher priority
|
|
|
|
call ASTSWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
|
|
; to the appropriate handler
|
|
jmp short Kli02 ; check for another
|
|
|
|
|
|
;----------------------------
|
|
;
|
|
;Code for using RegisterEBI2 Call
|
|
;eax=intMask
|
|
;
|
|
KliRegSetLocalIntMask:
|
|
|
|
or eax,fs:PcIDR ;mask off irq which disabled
|
|
push esi
|
|
mov esi,fs:PcHal.PcrEBI2ProcInterruptHandle
|
|
lea edx, _EBI2_CallTab
|
|
call [edx]+RegSetLocalIntMask
|
|
pop esi
|
|
|
|
mov fs:PcIrql, cl ; save new IRQL
|
|
Kli02b:
|
|
mov edx, fs:dword ptr PcIRR
|
|
and edx,0Eh ; mask for valid IRR bits
|
|
jnz short Kli09b ; jump if yes
|
|
|
|
Kli08b:
|
|
popfd ; restore flags, including ints
|
|
fstRET KfLowerIrql ; RETURN
|
|
|
|
Kli09b:
|
|
movzx eax, SWInterruptLookUpTable[edx]
|
|
;
|
|
;When we come to Kli10b, (eax) = soft interrupt index
|
|
;
|
|
Kli10b:
|
|
cmp al, fs:PcIrql ; compare with current IRQL
|
|
jna short Kli08b ; jump if higher priority
|
|
|
|
call ASTSWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
|
|
; to the appropriate handler
|
|
jmp short Kli02b ; check for another
|
|
fstENDP KfLowerIrql
|
|
|
|
cPublicProc _HalpEndSoftwareInterrupt,1
|
|
cPublicFpo 1,0
|
|
mov ecx, [esp+4]
|
|
fstCall KfLowerIrql
|
|
stdRet _HalpEndSoftwareInterrupt
|
|
stdENDP _HalpEndSoftwareInterrupt
|
|
|
|
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; HalpEndSystemInterrupt
|
|
; IN KIRQL NewIrql,
|
|
; IN ULONG Vector
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is used to lower IRQL to the specified value.
|
|
; The IRQL and PIRQL will be updated accordingly. Also, this
|
|
; routine checks to see if any software interrupt should be
|
|
; generated. The following condition will cause software
|
|
; interrupt to be simulated:
|
|
; any software interrupt which has higher priority than
|
|
; current IRQL's is pending.
|
|
;
|
|
; NOTE: This routine simulates software interrupt as long as
|
|
; any pending SW interrupt level is higher than the current
|
|
; IRQL, even when interrupts are disabled.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; NewIrql - the new irql to be set.
|
|
;
|
|
; Vector - Vector number of the interrupt
|
|
;
|
|
; Note that esp+8 is the beginning of interrupt/trap frame and upon
|
|
; entering to this routine the interrupts are off.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
HeiNewIrql equ byte ptr [esp + 4]
|
|
HeiVector equ byte ptr [esp + 8]
|
|
|
|
cPublicProc _HalEndSystemInterrupt,2
|
|
|
|
lea eax, _EBI2_Lock
|
|
EndIntAcquire:
|
|
cli
|
|
ACQUIRE_SPINLOCK eax, EndIntSpin
|
|
;
|
|
movzx eax, HeiVector
|
|
; to EOI
|
|
sub eax, PRIMARY_VECTOR_BASE ; get EBI2 Interrupt number
|
|
push eax ; EOI the interrupt
|
|
CALL_EBI2 MaskableIntEOI,2
|
|
|
|
if DBG
|
|
or eax, eax
|
|
je EOI_OK
|
|
DisplPanel HalEndSystemInterruptEnter
|
|
EOI_OK:
|
|
endif ;DBG
|
|
;
|
|
lea eax, _EBI2_Lock
|
|
EndIntRelease:
|
|
RELEASE_SPINLOCK eax
|
|
|
|
mov ecx, dword ptr HeiNewIrql
|
|
fstCall KfLowerIrql
|
|
stdRet _HalEndSystemInterrupt
|
|
|
|
EndIntSpin:
|
|
SPIN_ON_SPINLOCK eax, EndIntAcquire
|
|
|
|
|
|
stdENDP _HalEndSystemInterrupt
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; ASTDispatchInterrupt(
|
|
; VOID
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This is HalpDispatchInterrupt from IXSWINT.ASM. It's a pre-ship
|
|
; fix for a stack overflow condition found on an AST machine.
|
|
; This function assumes that the caller will re-check for a DPC
|
|
; interrupt and loop, whereas the normal HalpDispatchInterrupt calls
|
|
; lowerirql.
|
|
;
|
|
; Arguments:
|
|
; Return Value:
|
|
;--
|
|
|
|
ENTER_DR_ASSIST ahdpi_a, ahdpi_t
|
|
|
|
align dword
|
|
public _ASTDispatchInterrupt
|
|
_ASTDispatchInterrupt proc
|
|
;
|
|
; Create IRET frame on stack
|
|
;
|
|
pop eax
|
|
pushfd
|
|
push cs
|
|
push eax
|
|
|
|
;
|
|
; Save machine state on trap frame
|
|
;
|
|
|
|
ENTER_INTERRUPT ahdpi_a, ahdpi_t
|
|
.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME )
|
|
|
|
; Save previous IRQL and set new priority level
|
|
|
|
push PCR[PcIrql] ; save previous IRQL
|
|
mov byte ptr PCR[PcIrql], DISPATCH_LEVEL; set new irql
|
|
btr dword ptr PCR[PcIRR], DISPATCH_LEVEL; clear the pending bit in IRR
|
|
|
|
;
|
|
; Now it is safe to enable interrupt to allow higher priority interrupt
|
|
; to come in.
|
|
;
|
|
|
|
sti
|
|
|
|
;
|
|
; Go do Dispatch Interrupt processing
|
|
;
|
|
stdCall _KiDispatchInterrupt
|
|
|
|
;
|
|
; Do interrupt exit processing
|
|
;
|
|
cli
|
|
pop eax ; saved irql
|
|
mov PCR[PcIrql], al ; restore it
|
|
|
|
SPURIOUS_INTERRUPT_EXIT ; exit interrupt without EOI
|
|
; (return to loop in LowerIrql)
|
|
_ASTDispatchInterrupt endp
|
|
|
|
page ,132
|
|
subttl "Specific Raise irql functions"
|
|
;++
|
|
;
|
|
; VOID
|
|
; KIRQL
|
|
; KeRaiseIrqlToDpcLevel (
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is used to raise IRQL to DPC level.
|
|
; The APIC TPR is used to block all lower-priority HW interrupts.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; Return Value:
|
|
;
|
|
; OldIrql - the addr of a variable which old irql should be stored
|
|
;
|
|
;--
|
|
|
|
cPublicProc _KeRaiseIrqlToDpcLevel,0
|
|
|
|
mov ecx, DISPATCH_LEVEL
|
|
jmp @KfRaiseIrql
|
|
|
|
stdENDP _KeRaiseIrqlToDpcLevel
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; KIRQL
|
|
; KeRaiseIrqlToSynchLevel (
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is used to raise IRQL to SYNC level.
|
|
; The APIC TPR is used to block all lower-priority HW interrupts.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; Return Value:
|
|
;
|
|
; OldIrql - the addr of a variable which old irql should be stored
|
|
;
|
|
;--
|
|
|
|
cPublicProc _KeRaiseIrqlToSynchLevel,0
|
|
|
|
mov ecx, SYNCH_LEVEL
|
|
jmp @KfRaiseIrql
|
|
|
|
stdENDP _KeRaiseIrqlToSynchLevel
|
|
|
|
|
|
page ,132
|
|
subttl "Get current irql"
|
|
|
|
;++
|
|
;
|
|
; KIRQL
|
|
; KeGetCurrentIrql (VOID)
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine returns to current IRQL.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; The current IRQL.
|
|
;
|
|
;--
|
|
|
|
cPublicProc _KeGetCurrentIrql,0
|
|
movzx eax, byte ptr fs:PcIrql ; Current irql is in the PCR
|
|
stdRET _KeGetCurrentIrql
|
|
stdENDP _KeGetCurrentIrql
|
|
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; HalpDisableAllInterrupts (VOID)
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is called during a system crash. The hal needs all
|
|
; interrupts disabled.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None - all interrupts are masked off
|
|
;
|
|
;--
|
|
|
|
cPublicProc _HalpDisableAllInterrupts,0
|
|
|
|
;
|
|
; Raising to HIGH_LEVEL disables interrupts for the ast HAL
|
|
;
|
|
|
|
mov ecx, HIGH_LEVEL
|
|
fstCall KfRaiseIrql
|
|
stdRET _HalpDisableAllInterrupts
|
|
|
|
stdENDP _HalpDisableAllInterrupts
|
|
|
|
|
|
|
|
;++
|
|
;
|
|
; EBI2_InitLocalMaskFunctionPtr
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is called during processor initialization (P1).
|
|
; It will setup the data structure used by RaiseIrql and LowerIrql.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None
|
|
;
|
|
;--
|
|
|
|
|
|
Public EBI2_InitLocalIntFunctions
|
|
EBI2_InitLocalIntFunctions Proc
|
|
|
|
;
|
|
; Get EBI2 Revision#. This version of HAL requires EBI2 rev >= 2.9
|
|
; If 2.9 then use RegSetLocalIntMask; Else, use directly access hw
|
|
; to set LocalIntMask.
|
|
;
|
|
lea eax, _EBI2_revision
|
|
cmp [eax].major,2
|
|
jb EBI2_InitLocalIntRet
|
|
|
|
cmp [eax].minor,9
|
|
jb EBI2_InitLocalIntRet
|
|
;
|
|
; Get Processor's Interrupt handler for each processor
|
|
;
|
|
mov eax,offset EBI2_ProcIntHandle
|
|
push eax
|
|
mov eax,fs:PcHal.PcrEBI2ProcessorID
|
|
push eax ; push the processor number
|
|
CALL_EBI2 GetProcIntHandle,3
|
|
or eax, eax
|
|
jnz EBI2_InitLocalIntRet
|
|
mov eax,EBI2_ProcIntHandle
|
|
mov dword ptr fs:PcHal.PcrEBI2ProcInterruptHandle,eax ;save int hdlr
|
|
|
|
;
|
|
;Set function pointer for Raise and Lower Irql functions to use
|
|
;RegSetLocalIntMask as default
|
|
;
|
|
mov eax,offset FLAT:KriRegSetLocalIntMask
|
|
mov fs:PcHal.PcrEBI2RaiseIrqlFunction,eax
|
|
|
|
mov eax,offset FLAT:KliRegSetLocalIntMask
|
|
mov fs:PcHal.PcrEBI2LowerIrqlFunction,eax
|
|
;
|
|
;Check for Rev.minor >= 10. If it is then use direct hardware access
|
|
;to set LocalIntMask.
|
|
;
|
|
lea eax, _EBI2_revision
|
|
cmp [eax].minor,10
|
|
jb EBI2_InitLocalIntRet2
|
|
|
|
;
|
|
; Get Processor's LocalMaskInfo for each processor
|
|
;
|
|
mov eax,fs:PcHal.PcrEBI2ProcessorID
|
|
push eax ; push the processor number
|
|
mov eax,offset EBI2_maskInfo
|
|
push eax
|
|
CALL_EBI2 GetLocalIntMaskInfo,3
|
|
or eax, eax
|
|
jnz EBI2_InitLocalIntRet
|
|
mov eax,EBI2_MaskInfo.portAddress0
|
|
mov dword ptr fs:PcHal.PcrEBI2portAddress0,eax
|
|
mov eax,EBI2_MaskInfo.portAddress1
|
|
mov dword ptr fs:PcHal.PcrEBI2portAddress1,eax
|
|
mov eax,EBI2_MaskInfo.portAddress2
|
|
mov dword ptr fs:PcHal.PcrEBI2portAddress2,eax
|
|
mov eax,EBI2_MaskInfo.portAddress3
|
|
mov dword ptr fs:PcHal.PcrEBI2portAddress3,eax
|
|
|
|
mov eax,EBI2_MaskInfo.flags
|
|
and eax,PORT_TYPE_MASK
|
|
cmp eax,PORT_TYPE_MEMORY
|
|
jne short EBI2_InitLocalIntRet ;else set error exit
|
|
|
|
mov eax,EBI2_MaskInfo.flags
|
|
and eax,PORT_WIDTH_MASK
|
|
cmp eax,THIRTY_TWO_BIT_PORT
|
|
je short EBI2_ILIF32
|
|
cmp eax,EIGHT_BIT_PORTS
|
|
je short EBI2_ILIF08
|
|
jmp short EBI2_InitLocalIntRet ;else set error exit
|
|
|
|
EBI2_ILIF08:
|
|
;
|
|
;Set function pointer for Raise and Lower Irql to use
|
|
;direct hw access for setting LocalIntMask (8-bit hw).
|
|
;
|
|
mov eax,offset FLAT:KriDirectAccessIntMask8
|
|
mov fs:PcHal.PcrEBI2RaiseIrqlFunction,eax
|
|
|
|
mov eax,offset FLAT:KliDirectAccessIntMask8
|
|
mov fs:PcHal.PcrEBI2LowerIrqlFunction,eax
|
|
jmp short EBI2_InitLocalIntRet2
|
|
|
|
EBI2_ILIF32:
|
|
;
|
|
;Set function pointer for Raise and Lower Irql to use
|
|
;direct hw access for setting LocalIntMask. (32-bit hw)
|
|
;
|
|
mov eax,offset FLAT:KriDirectAccessIntMask32
|
|
mov fs:PcHal.PcrEBI2RaiseIrqlFunction,eax
|
|
|
|
mov eax,offset FLAT:KliDirectAccessIntMask32
|
|
mov fs:PcHal.PcrEBI2LowerIrqlFunction,eax
|
|
|
|
|
|
EBI2_InitLocalIntRet2:
|
|
xor eax,eax ;return status
|
|
|
|
EBI2_InitLocalIntRet:
|
|
ret
|
|
|
|
EBI2_InitLocalIntFunctions Endp
|
|
|
|
|
|
_TEXT ends
|
|
end
|