/*++ Copyright (c) 1990 Microsoft Corporation Copyright (c) 1992, 1993 Digital Equipment Corporation Module Name: lxintsup.c Abstract: The module provides the interrupt support for LX3 Author: Eric Rehm (DEC) 29-December-1993 Revision History: Rewritten from ebintsup.c to lx3intsup. --*/ #include "halp.h" #include "eisa.h" #include "ebsgdma.h" #include "lx3.h" #include "pcrtc.h" extern BOOLEAN SioCStep; #ifdef IDLE_PROCESSOR ULONG HalpInterruptReceived; BOOLEAN PreHalpSioDispatch( VOID ); #endif // // Declare the interrupt handler for the PCI and ISA bus. // BOOLEAN HalpSioDispatch( VOID ); // // The following is the interrupt object used for DMA controller interrupts. // DMA controller interrupts occur when a memory parity error occurs or a // programming error occurs to the DMA controller. // KINTERRUPT HalpEisaNmiInterrupt; // // The following function initializes NMI handling. // VOID HalpInitializeNMI( VOID ); // // The following function is called when an ISA NMI occurs. // BOOLEAN HalHandleNMI( IN PKINTERRUPT Interrupt, IN PVOID ServiceContext ); BOOLEAN HalpInitializePCIInterrupts ( VOID ) /*++ Routine Description: This routine initializes the structures necessary for ISA & PCI operations and connects the intermediate interrupt dispatcher. Arguments: None. Return Value: If the second level interrupt dispatcher is connected, then a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { KIRQL oldIrql; // // Initialize the EISA NMI interrupt. // HalpInitializeNMI(); // // Directly connect the ISA interrupt dispatcher to the level for // ISA bus interrupt. // // N.B. This vector is reserved for exclusive use by the HAL (see // interrupt initialization. // #ifdef IDLE_PROCESSOR PCR->InterruptRoutine[PIC_VECTOR] = PreHalpSioDispatch; #else PCR->InterruptRoutine[PIC_VECTOR] = HalpSioDispatch; #endif HalEnableSystemInterrupt(PIC_VECTOR, ISA_DEVICE_LEVEL, LevelSensitive); // // Intitialize interrupt controller // KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql); // // Initialize the PCI-ISA bridge interrupt controller // HalpInitializeSioInterrupts(); // // Restore IRQL level. // KeLowerIrql(oldIrql); // // Initialize the DMA mode registers to a default value. // Disable all of the DMA channels except channel 4 which is the // cascade of channels 0-3. // WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask, 0x0F ); WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask, 0x0E ); return(TRUE); } VOID HalpInitializeNMI( VOID ) /*++ Routine Description: This function is called to intialize SIO NMI interrupts. Arguments: None. Return Value: None. --*/ { UCHAR DataByte; // // Initialize the SIO NMI interrupt. // KeInitializeInterrupt( &HalpEisaNmiInterrupt, HalHandleNMI, NULL, NULL, EISA_NMI_VECTOR, EISA_NMI_LEVEL, EISA_NMI_LEVEL, LevelSensitive, FALSE, 0, FALSE ); // // Don't fail if the interrupt cannot be connected. // KeConnectInterrupt( &HalpEisaNmiInterrupt ); // // Clear the Eisa NMI disable bit. This bit is the high order of the // NMI enable register. // DataByte = 0; WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, DataByte ); } BOOLEAN HalHandleNMI( IN PKINTERRUPT Interrupt, IN PVOID ServiceContext ) /*++ Routine Description: This function is called when an EISA NMI occurs. It print the appropriate status information and bugchecks. Arguments: Interrupt - Supplies a pointer to the interrupt object ServiceContext - Bug number to call bugcheck with. Return Value: Returns TRUE. --*/ { UCHAR StatusByte; #ifdef IDLE_PROCESSOR // // Clear interrupt flag // HalpInterruptReceived = 0; #endif StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus); if (StatusByte & 0x80) { HalDisplayString ("NMI: Parity Check / Parity Error\n"); } if (StatusByte & 0x40) { HalDisplayString ("NMI: Channel Check / IOCHK\n"); } // // This is an Sio machine, no extnded nmi information, so just do it. // KeBugCheck(NMI_HARDWARE_FAILURE); return(TRUE); } UCHAR HalpAcknowledgeEisaInterrupt( PVOID ServiceContext ) /*++ Routine Description: Acknowledge the EISA interrupt from the programmable interrupt controller. Return the vector number of the highest priority pending interrupt. Arguments: ServiceContext - Service context of the interrupt service supplies a pointer to the EISA interrupt acknowledge register. Return Value: Return the value of the highest priority pending interrupt. --*/ { UCHAR InterruptVector; #ifdef IDLE_PROCESSOR // // Clear interrupt flag // HalpInterruptReceived = 0; #endif // // Read the interrupt vector from the PIC. // InterruptVector = READ_PORT_UCHAR(ServiceContext); return( InterruptVector ); } VOID HalpAcknowledgeClockInterrupt( VOID ) /*++ Routine Description: Acknowledge the clock interrupt from the interval timer. The interval timer for EB66 comes from the Dallas real-time clock. Arguments: None. Return Value: None. --*/ { #ifdef IDLE_PROCESSOR // // Clear interrupt flag // HalpInterruptReceived = 0; #endif // // Acknowledge the clock interrupt by reading the control register C of // the Real Time Clock. // HalpReadClockRegister( RTC_CONTROL_REGISTERC ); return; } #ifdef IDLE_PROCESSOR BOOLEAN PreHalpSioDispatch( VOID ) /*++ Routine Description: Acknowledge the PCI interrupt by clearing the interrupt flag, then dispatch to the real PCI/SIO interrupt handler Arguments: None. Return Value: None. --*/ { // // Clear interrupt flag // HalpInterruptReceived = 0; return HalpSioDispatch(); } #endif