310 lines
5.5 KiB
C
310 lines
5.5 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
mcsysint.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module implements the HAL routines to enable/disable system
|
||
|
interrupts.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
John Vert (jvert) 22-Jul-1991
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Forrest Foltz (forrestf) 27-Oct-2000
|
||
|
Ported from mcsysint.asm to mcsysint.c
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "halcmn.h"
|
||
|
|
||
|
BOOLEAN
|
||
|
HalBeginSystemInterrupt (
|
||
|
IN KIRQL Irql,
|
||
|
IN ULONG 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 processed
|
||
|
|
||
|
OldIrql- Location to return OldIrql
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
FALSE - Interrupt is spurious and should be ignored
|
||
|
|
||
|
TRUE - Interrupt successfully dismissed and Irql raised.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
UCHAR irq;
|
||
|
UCHAR isr;
|
||
|
PCHAR picPort;
|
||
|
ULONG mask;
|
||
|
PKPCR pcr;
|
||
|
|
||
|
irq = (UCHAR)(Vector - PRIMARY_VECTOR_BASE);
|
||
|
if (irq == 0x07) {
|
||
|
|
||
|
//
|
||
|
// Check to see if this is a spurious interrupt
|
||
|
//
|
||
|
|
||
|
WRITE_PORT_UCHAR(PIC1_PORT0,OCW3_READ_ISR);
|
||
|
IO_DELAY();
|
||
|
isr = READ_PORT_UCHAR(PIC1_PORT0);
|
||
|
IO_DELAY();
|
||
|
if ((isr & 0x8000) == 0) {
|
||
|
|
||
|
//
|
||
|
// This is a spurious interrupt
|
||
|
//
|
||
|
|
||
|
HalpEnableInterrupts();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Non-spurious interrupt, fall through to normal processing
|
||
|
//
|
||
|
|
||
|
} else if (irq == 0x0F) {
|
||
|
|
||
|
//
|
||
|
// Check to see if this is a spurious interrupt
|
||
|
//
|
||
|
|
||
|
WRITE_PORT_UCHAR(PIC2_PORT0,OCW3_READ_ISR);
|
||
|
IO_DELAY();
|
||
|
isr = READ_PORT_UCHAR(PIC2_PORT0);
|
||
|
IO_DELAY();
|
||
|
if ((isr & 0x8000) == 0) {
|
||
|
|
||
|
//
|
||
|
// This is a spurious interrupt. Dismiss the master PIC's
|
||
|
// irq2.
|
||
|
//
|
||
|
|
||
|
WRITE_PORT_UCHAR(PIC1_PORT0,PIC2_EOI);
|
||
|
IO_DELAY();
|
||
|
HalpEnableInterrupts();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Non-spurious interrupt, fall through to normal processing
|
||
|
//
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Store the old IRQL, raise IRQL to the requested level
|
||
|
//
|
||
|
|
||
|
pcr = KeGetPcr();
|
||
|
*OldIrql = pcr->Irql;
|
||
|
pcr->Irql = Irql;
|
||
|
|
||
|
//
|
||
|
// Mask off interrupts according to the supplied IRQL
|
||
|
//
|
||
|
|
||
|
mask = Halp8259MaskTable[Irql];
|
||
|
mask |= pcr->Idr;
|
||
|
SET_8259_MASK((USHORT)mask);
|
||
|
|
||
|
//
|
||
|
// Dismiss the interrupt
|
||
|
//
|
||
|
|
||
|
if (irq < 8) {
|
||
|
|
||
|
//
|
||
|
// Interrupt came from the master, send it a specific eoi.
|
||
|
//
|
||
|
|
||
|
WRITE_PORT_UCHAR(PIC1_PORT0,PIC1_EOI_MASK | irq);
|
||
|
IO_DELAY();
|
||
|
|
||
|
} else {
|
||
|
|
||
|
//
|
||
|
// Interrupt came from the slave, send the slave a non-specific EOI
|
||
|
// and send the master an irq-2 specific EOI
|
||
|
//
|
||
|
|
||
|
WRITE_PORT_UCHAR(PIC2_PORT0,OCW2_NON_SPECIFIC_EOI);
|
||
|
IO_DELAY();
|
||
|
WRITE_PORT_UCHAR(PIC1_PORT0,PIC2_EOI);
|
||
|
IO_DELAY();
|
||
|
}
|
||
|
|
||
|
PIC1DELAY();
|
||
|
|
||
|
HalpEnableInterrupts();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
HalDisableSystemInterrupt(
|
||
|
IN ULONG 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.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
USHORT mask;
|
||
|
UCHAR irq;
|
||
|
ULONG flags;
|
||
|
PKPCR pcr;
|
||
|
USHORT imr;
|
||
|
PUCHAR picPort;
|
||
|
|
||
|
irq = (UCHAR)(Vector - PRIMARY_VECTOR_BASE);
|
||
|
mask = 1 << irq;
|
||
|
|
||
|
flags = HalpDisableInterrupts();
|
||
|
pcr = KeGetPcr();
|
||
|
pcr->Idr |= mask;
|
||
|
|
||
|
//
|
||
|
// Mask the irq in the 8259.
|
||
|
//
|
||
|
|
||
|
mask |= GET_8259_MASK();
|
||
|
SET_8259_MASK(mask);
|
||
|
|
||
|
HalpRestoreInterrupts(flags);
|
||
|
}
|
||
|
|
||
|
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:
|
||
|
|
||
|
FALSE in the case of an invalid parameter, TRUE otherwise.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
UCHAR irq;
|
||
|
ULONG mask;
|
||
|
USHORT edgeLevel;
|
||
|
ULONG flags;
|
||
|
PKPCR pcr;
|
||
|
|
||
|
irq = (UCHAR)(Vector - PRIMARY_VECTOR_BASE);
|
||
|
if (Vector < PRIMARY_VECTOR_BASE || irq > HIGH_LEVEL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
mask = 1 << irq;
|
||
|
|
||
|
//
|
||
|
// Set the edge/level bit in the interrupt controller
|
||
|
//
|
||
|
|
||
|
edgeLevel = READ_PORT_USHORT_PAIR (EISA_EDGE_LEVEL0, EISA_EDGE_LEVEL1);
|
||
|
edgeLevel |= mask;
|
||
|
WRITE_PORT_USHORT_PAIR (EISA_EDGE_LEVEL0,
|
||
|
EISA_EDGE_LEVEL1,
|
||
|
(USHORT)edgeLevel);
|
||
|
IO_DELAY();
|
||
|
|
||
|
//
|
||
|
// Disable interrupts and mask off the corresponding bit in the Idr.
|
||
|
//
|
||
|
|
||
|
HalpDisableInterrupts();
|
||
|
|
||
|
pcr = KeGetPcr();
|
||
|
mask = ~mask & pcr->Idr;
|
||
|
pcr->Idr = mask;
|
||
|
|
||
|
//
|
||
|
// Get the PIC masks for the current Irql
|
||
|
//
|
||
|
|
||
|
mask |= Halp8259MaskTable[Irql];
|
||
|
SET_8259_MASK((USHORT)mask);
|
||
|
|
||
|
//
|
||
|
// Enable interrupts and return success
|
||
|
//
|
||
|
|
||
|
HalpEnableInterrupts();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|