summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halx86/i386/ixsysint.asm
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halx86/i386/ixsysint.asm
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/halx86/i386/ixsysint.asm')
-rw-r--r--private/ntos/nthals/halx86/i386/ixsysint.asm582
1 files changed, 582 insertions, 0 deletions
diff --git a/private/ntos/nthals/halx86/i386/ixsysint.asm b/private/ntos/nthals/halx86/i386/ixsysint.asm
new file mode 100644
index 000000000..e73b40f24
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixsysint.asm
@@ -0,0 +1,582 @@
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; ixsysint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to enable/disable system
+; interrupts.
+;
+;Author:
+;
+; John Vert (jvert) 22-Jul-1991
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+ .list
+
+ extrn KiI8259MaskTable:DWORD
+ EXTRNP _KeBugCheck,1,IMPORT
+
+ifdef IRQL_METRICS
+ extrn HalPostponedIntCount:dword
+endif
+ extrn _PciIsaIrq:dword
+ extrn SWInterruptHandlerTable:dword
+ extrn HalpHardwareInterruptLevel:proc
+
+;
+; Constants used to initialize CMOS/Real Time Clock
+;
+
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+
+;
+; Macros to Read/Write/Reset CMOS to initialize RTC
+;
+
+; CMOS_READ
+;
+; Description: This macro read a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; Return: (AL) = data
+;
+
+CMOS_READ MACRO
+ OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
+ IODelay ; I/O DELAY
+ IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
+ IODelay ; I/O DELAY
+ENDM
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+align dword
+;
+; HalDismissSystemInterrupt does an indirect jump through this table so it
+; can quickly execute specific code for different interrupts.
+;
+ public HalpSpecialDismissTable
+HalpSpecialDismissTable label dword
+ dd offset FLAT:HalpDismissNormal ; irq 0
+ dd offset FLAT:HalpDismissNormal ; irq 1
+ dd offset FLAT:HalpDismissNormal ; irq 2
+ dd offset FLAT:HalpDismissNormal ; irq 3
+ dd offset FLAT:HalpDismissNormal ; irq 4
+ dd offset FLAT:HalpDismissNormal ; irq 5
+ dd offset FLAT:HalpDismissNormal ; irq 6
+ dd offset FLAT:HalpDismissIrq07 ; irq 7
+ dd offset FLAT:HalpDismissNormal ; irq 8
+ dd offset FLAT:HalpDismissNormal ; irq 9
+ dd offset FLAT:HalpDismissNormal ; irq A
+ dd offset FLAT:HalpDismissNormal ; irq B
+ dd offset FLAT:HalpDismissNormal ; irq C
+ dd offset FLAT:HalpDismissIrq0d ; irq D
+ dd offset FLAT:HalpDismissNormal ; irq E
+ dd offset FLAT:HalpDismissIrq0f ; irq F
+ dd offset FLAT:HalpDismissNormal ; irq 10
+ dd offset FLAT:HalpDismissNormal ; irq 11
+ dd offset FLAT:HalpDismissNormal ; irq 12
+ dd offset FLAT:HalpDismissNormal ; irq 13
+ dd offset FLAT:HalpDismissNormal ; irq 14
+ dd offset FLAT:HalpDismissNormal ; irq 15
+ dd offset FLAT:HalpDismissNormal ; irq 16
+ dd offset FLAT:HalpDismissNormal ; irq 17
+ dd offset FLAT:HalpDismissNormal ; irq 18
+ dd offset FLAT:HalpDismissNormal ; irq 19
+ dd offset FLAT:HalpDismissNormal ; irq 1A
+ dd offset FLAT:HalpDismissNormal ; irq 1B
+ dd offset FLAT:HalpDismissNormal ; irq 1C
+ dd offset FLAT:HalpDismissNormal ; irq 1D
+ dd offset FLAT:HalpDismissNormal ; irq 1E
+ dd offset FLAT:HalpDismissNormal ; irq 1F
+ dd offset FLAT:HalpDismissNormal ; irq 20
+ dd offset FLAT:HalpDismissNormal ; irq 21
+ dd offset FLAT:HalpDismissNormal ; irq 22
+ dd offset FLAT:HalpDismissNormal ; irq 23
+
+ public HalpSpecialDismissLevelTable
+HalpSpecialDismissLevelTable label dword
+ dd offset FLAT:HalpDismissLevel ; irq 0
+ dd offset FLAT:HalpDismissLevel ; irq 1
+ dd offset FLAT:HalpDismissLevel ; irq 2
+ dd offset FLAT:HalpDismissLevel ; irq 3
+ dd offset FLAT:HalpDismissLevel ; irq 4
+ dd offset FLAT:HalpDismissLevel ; irq 5
+ dd offset FLAT:HalpDismissLevel ; irq 6
+ dd offset FLAT:HalpDismissIrq07Level ; irq 7
+ dd offset FLAT:HalpDismissLevel ; irq 8
+ dd offset FLAT:HalpDismissLevel ; irq 9
+ dd offset FLAT:HalpDismissLevel ; irq A
+ dd offset FLAT:HalpDismissLevel ; irq B
+ dd offset FLAT:HalpDismissLevel ; irq C
+ dd offset FLAT:HalpDismissIrq0dLevel ; irq D
+ dd offset FLAT:HalpDismissLevel ; irq E
+ dd offset FLAT:HalpDismissIrq0fLevel ; irq F
+
+_DATA ENDS
+
+_TEXT$01 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;BOOLEAN
+;HalBeginSystemInterrupt(
+; IN KIRQL Irql
+; IN CCHAR Vector,
+; OUT PKIRQL OldIrql
+; )
+;
+;
+;
+;Routine Description:
+;
+; This routine is used to dismiss the specified vector number. It is called
+; before any interrupt service routine code is executed.
+;
+; N.B. This routine does NOT preserve EAX or EBX
+;
+; On a UP machine the interrupt dismissed at BeginSystemInterrupt time.
+; This is fine since the irql is being raise to mask it off.
+; HalEndSystemInterrupt is simply a LowerIrql request.
+;
+;
+;Arguments:
+;
+; Irql - Supplies the IRQL to raise to
+;
+; Vector - Supplies the vector of the interrupt to be dismissed
+;
+; OldIrql- Location to return OldIrql
+;
+;
+;Return Value:
+;
+; FALSE - Interrupt is spurious and should be ignored
+;
+; TRUE - Interrupt successfully dismissed and Irql raised.
+;
+;--
+align dword
+HbsiIrql equ byte ptr [esp+4]
+HbsiVector equ byte ptr [esp+8]
+HbsiOldIrql equ dword ptr [esp+12]
+
+cPublicProc _HalBeginSystemInterrupt ,3
+.FPO ( 0, 3, 0, 0, 0, 0 )
+ xor ecx, ecx
+ mov cl, HbsiVector ; (ecx) = System Vector
+ sub ecx, PRIMARY_VECTOR_BASE ; (ecx) = 8259 IRQ #
+if DBG
+ cmp ecx, 1fh
+ jbe hbsi00
+ int 3
+hbsi00:
+
+endif
+ jmp HalpSpecialDismissTable[ecx*4]
+
+HalpDismissIrq0f:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC2_PORT0, al
+ IODelay ; delay
+ in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissNormal ; No, this is NOT a spurious int,
+ ; go do the normal interrupt stuff
+HalpIrq0fSpurious:
+;
+; This is a spurious interrupt.
+; Because the slave PIC is cascaded to irq2 of master PIC, we need to
+; dismiss the interupt on master PIC's irq2.
+;
+
+ mov al, PIC2_EOI ; Specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ mov eax,0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq07:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC1_PORT0, al
+ IODelay ; delay
+ in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz HalpDismissNormal ; No, so this is NOT a spurious int
+ mov eax, 0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq0d:
+;
+; Clear the NPX busy latch.
+;
+
+ xor al,al
+ out I386_80387_BUSY_PORT, al
+
+align 4
+HalpDismissNormal:
+;
+; Raise IRQL to requested level
+;
+ xor ebx,ebx
+ mov al, HbsiIrql ; (al) = New irql
+ ; (ecx) = IRQ #
+ mov bl, PCR[PcIrql] ; (ebx) = Current Irql
+
+;
+; Now we check to make sure the Irql of this interrupt > current Irql.
+; If it is not, we dismiss it as spurious and set the appropriate bit
+; in the IRR so we can dispatch the interrupt when Irql is lowered
+;
+ cmp al, bl
+ jbe Hdsi300
+
+ mov PCR[PcIrql], al ; set new Irql
+ mov edx, HbsiOldIrql ; save current irql to OldIrql variable
+ mov byte ptr [edx], bl
+
+;
+; Dismiss interrupt.
+;
+ mov eax, ecx ; (eax) = IRQ #
+ cmp eax, 8 ; EOI to master or slave?
+ jae short Hbsi100 ; EIO to both master and slave
+
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalBeginSystemInterrupt
+
+align 4
+Hbsi100:
+ add al, OCW2_SPECIFIC_EOI - 8 ; specific eoi to slave
+ out PIC2_PORT0, al
+
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalBeginSystemInterrupt
+
+align 4
+Hdsi300:
+;
+; An interrupt has come in at a lower Irql, so we dismiss it as spurious and
+; set the appropriate bit in the IRR so that KeLowerIrql knows to dispatch
+; it when Irql is lowered.
+;
+; (ecx) = 8259 IRQ#
+; (al) = New Irql
+; (ebx) = Current Irql
+;
+
+ mov eax, 1
+ add ecx, 4 ; (ecx) = Irq # + 4
+ shl eax, cl
+ or PCR[PcIRR], eax
+
+;
+; Raise Irql to prevent it from happening again
+;
+
+;
+; Get the PIC masks for Irql
+;
+
+ mov eax, KiI8259MaskTable[ebx*4]
+ or eax, PCR[PcIDR]
+;
+; Write the new interrupt mask register back to the 8259
+;
+ SET_8259_MASK
+
+Hbsi390:
+
+ifdef IRQL_METRICS
+ lock inc HalPostponedIntCount
+endif
+
+ xor eax, eax ; return FALSE, spurious interrupt
+ stdRET _HalBeginSystemInterrupt
+
+
+HalpDismissIrq0fLevel:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC2_PORT0, al
+ IODelay ; delay
+ in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissLevel ; No, this is NOT a spurious int,
+ ; go do the normal interrupt stuff
+ jmp HalpIrq0fSpurious
+
+HalpDismissIrq07Level:
+;
+; Check to see if this is a spurious interrupt
+;
+ mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
+ out PIC1_PORT0, al
+ IODelay ; delay
+ in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
+ test al, 10000000B ; Is In-Service register set?
+ jnz short HalpDismissLevel ; No, so this is NOT a spurious int
+ mov eax, 0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq0dLevel:
+;
+; Clear the NPX busy latch.
+;
+
+ xor al,al
+ out I386_80387_BUSY_PORT, al
+
+align 4
+HalpDismissLevel:
+;
+; Mask this level interrupt off
+; (ecx) = 8259 IRQ#
+;
+ mov al, HbsiIrql ; (al) = New irql
+ mov eax, KiI8259MaskTable[eax*4] ; get 8259's masks
+ or eax, PCR[PcIDR] ; mask disabled irqs
+ SET_8259_MASK ; send mask to 8259s
+;
+; The SWInterruptHandler for this vector has been set to a NOP.
+; Set the vector's IRR so that Lower Irql will clear the 8259 mask for this
+; Irq when the irql is lowered below this level.
+;
+ mov eax, ecx ; (eax) = Irq #
+ mov ebx, 1
+ add ecx, 4 ; (ecx) = Irq # + 4
+ shl ebx, cl
+ or PCR[PcIRR], ebx
+
+;
+; Dismiss interrupt. Current interrupt is already masked off.
+; Then check to make sure the Irql of this interrupt > current Irql.
+; If it is not, we dismiss it as spurious - since this is a level interrupt
+; when the 8259's are unmasked the interrupt will reoccur
+;
+ mov cl, HbsiIrql
+ mov bl, PCR[PcIrql]
+ mov edx, HbsiOldIrql
+
+ cmp eax, 8 ; EOI to master or slave?
+ jae short Hbsi450 ; EIO to both master and slave
+
+ or al, PIC1_EOI_MASK ; create specific eoi mask for master
+ out PIC1_PORT0, al ; dismiss the interrupt
+
+ cmp cl, bl
+ jbe short Hbsi390 ; Spurious?
+
+ mov PCR[PcIrql], cl ; raise to new irql
+ mov byte ptr [edx], bl ; return old irql
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalBeginSystemInterrupt
+
+align 4
+Hbsi450:
+ add al, OCW2_SPECIFIC_EOI - 8 ; specific eoi to slave
+ out PIC2_PORT0, al
+ mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
+ out PIC1_PORT0, al ; send irq2 specific eoi to master
+
+ cmp cl, bl
+ jbe Hbsi390 ; Spurious?
+
+ mov PCR[PcIrql], cl ; raise to new irql
+ mov byte ptr [edx], bl ; return old irql
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalBeginSystemInterrupt
+
+stdENDP _HalBeginSystemInterrupt
+
+
+;++
+;VOID
+;HalDisableSystemInterrupt(
+; IN CCHAR Vector,
+; IN KIRQL Irql
+; )
+;
+;
+;
+;Routine Description:
+;
+; Disables a system interrupt.
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be disabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be disabled
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalDisableSystemInterrupt ,2
+.FPO ( 0, 2, 0, 0, 0, 0 )
+
+;
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
+ sub ecx, PRIMARY_VECTOR_BASE ; (ecx) = 8259 irq #
+ mov edx, 1
+ shl edx, cl ; (ebx) = bit in IMR to disable
+ cli
+ or PCR[PcIDR], edx
+ xor eax, eax
+
+;
+; Get the current interrupt mask register from the 8259
+;
+ in al, PIC2_PORT1
+ shl eax, 8
+ in al, PIC1_PORT1
+;
+; Mask off the interrupt to be disabled
+;
+ or eax, edx
+;
+; Write the new interrupt mask register back to the 8259
+;
+ out PIC1_PORT1, al
+ shr eax, 8
+ out PIC2_PORT1, al
+ PIC2DELAY
+
+ sti
+ stdRET _HalDisableSystemInterrupt
+
+stdENDP _HalDisableSystemInterrupt
+
+;++
+;
+;BOOLEAN
+;HalEnableSystemInterrupt(
+; IN ULONG Vector,
+; IN KIRQL Irql,
+; IN KINTERRUPT_MODE InterruptMode
+; )
+;
+;
+;Routine Description:
+;
+; Enables a system interrupt
+;
+;Arguments:
+;
+; Vector - Supplies the vector of the interrupt to be enabled
+;
+; Irql - Supplies the interrupt level of the interrupt to be enabled.
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalEnableSystemInterrupt ,3
+.FPO ( 0, 3, 0, 0, 0, 0 )
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = vector
+ sub ecx, PRIMARY_VECTOR_BASE
+ jc hes_error
+ cmp ecx, CLOCK2_LEVEL
+ jnc hes_error
+
+;
+; If this interrupt is mapped through ISA via the PCI bus then it's
+; a level interrupt - treat it as such.
+;
+ bt _PciIsaIrq, ecx
+ jnc short @f
+
+;
+; It's OK to treat a level interrupt as an edge interrupt (just a performance
+; slow-down), but it's not OK to treat an edge interrupt as a level interrupt.
+; if the driver didn't say it's level, treat it as an edge
+;
+
+ mov al, [esp+12]
+ cmp al, 0
+ jnz short @f
+
+ mov SWInterruptHandlerTable+4*4[ecx*4], offset HalpHardwareInterruptLevel
+
+ mov edx, HalpSpecialDismissLevelTable[ecx*4]
+ mov HalpSpecialDismissTable[ecx*4], edx
+
+@@:
+ mov eax, 1
+ shl eax, cl ; (ebx) = bit in IMR to enable
+ not eax
+
+ cli
+ and PCR[PcIDR], eax
+
+;
+; Get the PIC masks for Irql 0
+;
+ mov eax, KiI8259MaskTable[0]
+ or eax, PCR[PcIDR]
+;
+; Write the new interrupt mask register back to the 8259
+;
+ SET_8259_MASK
+
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalEnableSystemInterrupt
+
+hes_error:
+if DBG
+ int 3
+endif
+ xor eax, eax ; FALSE
+ stdRET _HalEnableSystemInterrupt
+
+stdENDP _HalEnableSystemInterrupt
+
+
+_TEXT$01 ENDS
+
+ END