518 lines
12 KiB
C
518 lines
12 KiB
C
/*++
|
||
|
||
Copyright (c) 1995 Digital Equipment Corporation
|
||
|
||
Module Name:
|
||
|
||
lyintsup.c
|
||
|
||
Abstract:
|
||
|
||
This module provides interrupt support for the Lynx family
|
||
Standard I/O board.
|
||
|
||
Author:
|
||
|
||
Dave Richards 31-May-1995
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
#include "t2.h"
|
||
#include "icic.h"
|
||
#include "xiintsup.h"
|
||
|
||
//
|
||
// Define the context structure for use by interrupt service routines.
|
||
//
|
||
|
||
typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
|
||
PKINTERRUPT InterruptObject
|
||
);
|
||
|
||
//
|
||
// Cached copies of the corresponding ICIC registers.
|
||
//
|
||
|
||
ICIC_ELCR_REGISTER LynxIcIcElcrRegister;
|
||
ICIC_MASK_REGISTER LynxIcIcMaskRegister;
|
||
|
||
|
||
ULONG
|
||
HalpGetLynxSioInterruptVector(
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN ULONG BusInterruptLevel,
|
||
IN ULONG BusInterruptVector,
|
||
OUT PKIRQL Irql,
|
||
OUT PKAFFINITY Affinity
|
||
)
|
||
{
|
||
*Irql = DEVICE_LEVEL;
|
||
*Affinity = HAL_CPU0_MASK;
|
||
|
||
switch( BusInterruptLevel ){
|
||
|
||
case EisaInterruptLevel3:
|
||
return( LynxEisaIrq3Vector );
|
||
|
||
case EisaInterruptLevel4:
|
||
return( LynxEisaIrq4Vector );
|
||
|
||
case EisaInterruptLevel5:
|
||
return( LynxEisaIrq5Vector );
|
||
|
||
case EisaInterruptLevel6:
|
||
return( LynxEisaIrq6Vector );
|
||
|
||
case EisaInterruptLevel7:
|
||
return( LynxEisaIrq7Vector );
|
||
|
||
case EisaInterruptLevel9:
|
||
return( LynxEisaIrq9Vector );
|
||
|
||
case EisaInterruptLevel10:
|
||
return( LynxEisaIrq10Vector );
|
||
|
||
case EisaInterruptLevel11:
|
||
return( LynxEisaIrq11Vector );
|
||
|
||
case EisaInterruptLevel12:
|
||
return( LynxEisaIrq12Vector );
|
||
|
||
case EisaInterruptLevel14:
|
||
return( LynxEisaIrq14Vector );
|
||
|
||
case EisaInterruptLevel15:
|
||
return( LynxEisaIrq15Vector );
|
||
|
||
//
|
||
// Handle Vectors for the Internal bus devices.
|
||
//
|
||
|
||
case LynxMouseVector:
|
||
case LynxKeyboardVector:
|
||
case LynxFloppyVector:
|
||
case LynxSerialPort1Vector:
|
||
case LynxParallelPortVector:
|
||
case LynxSerialPort0Vector:
|
||
case LynxI2cVector:
|
||
|
||
//
|
||
// Handle Vectors for PCI devices.
|
||
//
|
||
|
||
case LynxScsi0Vector:
|
||
case LynxScsi1Vector:
|
||
case LynxPciSlot0AVector:
|
||
case LynxPciSlot0BVector:
|
||
case LynxPciSlot0CVector:
|
||
case LynxPciSlot0DVector:
|
||
case LynxPciSlot1AVector:
|
||
case LynxPciSlot1BVector:
|
||
case LynxPciSlot1CVector:
|
||
case LynxPciSlot1DVector:
|
||
case LynxPciSlot2AVector:
|
||
case LynxPciSlot2BVector:
|
||
case LynxPciSlot2CVector:
|
||
case LynxPciSlot2DVector:
|
||
case LynxPciSlot3AVector:
|
||
case LynxPciSlot3BVector:
|
||
case LynxPciSlot3CVector:
|
||
case LynxPciSlot3DVector:
|
||
case LynxPciSlot4AVector:
|
||
case LynxPciSlot4BVector:
|
||
case LynxPciSlot4CVector:
|
||
case LynxPciSlot4DVector:
|
||
case LynxPciSlot5AVector:
|
||
case LynxPciSlot5BVector:
|
||
case LynxPciSlot5CVector:
|
||
case LynxPciSlot5DVector:
|
||
case LynxPciSlot6AVector:
|
||
case LynxPciSlot6BVector:
|
||
case LynxPciSlot6CVector:
|
||
case LynxPciSlot6DVector:
|
||
case LynxPciSlot7AVector:
|
||
case LynxPciSlot7BVector:
|
||
case LynxPciSlot7CVector:
|
||
case LynxPciSlot7DVector:
|
||
|
||
return( BusInterruptLevel );
|
||
|
||
default:
|
||
|
||
#if defined(XIO_PASS1) || defined(XIO_PASS2)
|
||
|
||
return HalpGetXioInterruptVector(
|
||
BusHandler,
|
||
RootHandler,
|
||
BusInterruptLevel,
|
||
BusInterruptVector,
|
||
Irql,
|
||
Affinity
|
||
);
|
||
|
||
#else
|
||
|
||
*Irql = 0;
|
||
*Affinity = 0;
|
||
return 0;
|
||
|
||
#endif
|
||
|
||
}
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
HalpInitializeLynxSioInterrupts(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the ICIC on the Standard I/O module.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
TRUE.
|
||
|
||
--*/
|
||
|
||
{
|
||
T2_ICE Ice;
|
||
ICIC_EISA_REGISTER LynxIcIcEisaRegister;
|
||
|
||
//
|
||
// Initialize the interface between the T3/T4 and the ICIC.
|
||
//
|
||
|
||
Ice.all = 0;
|
||
Ice.EisaFlushAddress = 0x542;
|
||
Ice.IcEnable = 1;
|
||
Ice.HalfSpeedEnable = 0;
|
||
|
||
WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Ice,
|
||
Ice.all );
|
||
|
||
//
|
||
// Initialize the ICIC Mask Register.
|
||
//
|
||
|
||
LynxIcIcMaskRegister = (ULONGLONG)-1;
|
||
|
||
WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcMaskRegister,
|
||
LynxIcIcMaskRegister );
|
||
|
||
//
|
||
// Initialize the ICIC Edge/Level Control Register.
|
||
//
|
||
|
||
LynxIcIcElcrRegister =
|
||
((ICIC_ELCR_REGISTER)1 << (LynxScsi0Vector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxScsi1Vector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4AVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4BVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4CVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4DVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5AVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5BVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5CVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5DVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6AVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6BVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6CVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6DVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7AVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7BVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7CVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7DVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7DVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0AVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0BVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0CVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0DVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1AVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1BVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1CVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1DVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2AVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2BVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2CVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2DVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3AVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3BVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3CVector - LynxBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3DVector - LynxBaseVector));
|
||
|
||
WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcElcrRegister,
|
||
LynxIcIcElcrRegister );
|
||
|
||
//
|
||
// Initialize the ICIC EISA Register.
|
||
//
|
||
|
||
LynxIcIcEisaRegister =
|
||
(1 << (LynxEisaIrq3Vector - LynxBaseVector)) |
|
||
(1 << (LynxEisaIrq4Vector - LynxBaseVector)) |
|
||
(1 << (LynxEisaIrq5Vector - LynxBaseVector)) |
|
||
(1 << (LynxEisaIrq6Vector - LynxBaseVector)) |
|
||
(1 << (LynxEisaIrq7Vector - LynxBaseVector)) |
|
||
(1 << (LynxEisaIrq9Vector - LynxBaseVector)) |
|
||
(1 << (LynxEisaIrq10Vector - LynxBaseVector)) |
|
||
(1 << (LynxEisaIrq11Vector - LynxBaseVector)) |
|
||
(1 << (LynxEisaIrq12Vector - LynxBaseVector)) |
|
||
(1 << (LynxEisaIrq14Vector - LynxBaseVector)) |
|
||
(1 << (LynxEisaIrq15Vector - LynxBaseVector));
|
||
|
||
WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcEisaRegister,
|
||
LynxIcIcEisaRegister );
|
||
|
||
//
|
||
// Initialize the ICIC Mode Register.
|
||
//
|
||
|
||
WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcModeRegister, (ULONGLONG)0 );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN
|
||
HalpLynxSioDispatch(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine dispatches interrupts received by the Standard I/O
|
||
ICIC.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
A boolean value indicating whether the interrupt was handled by
|
||
the FLIH/SLIH.
|
||
|
||
--*/
|
||
|
||
{
|
||
T2_VAR Var;
|
||
PULONG DispatchCode;
|
||
PKINTERRUPT InterruptObject;
|
||
BOOLEAN ReturnValue;
|
||
|
||
//
|
||
// Get the interrupt vector.
|
||
//
|
||
|
||
Var.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Var );
|
||
|
||
//
|
||
// If this is a passive release, ignore the interrupt.
|
||
//
|
||
|
||
if( Var.PassiveRelease == 1 ){
|
||
|
||
return(TRUE);
|
||
|
||
}
|
||
|
||
//
|
||
// Dispatch to the secondary interrupt service routine.
|
||
//
|
||
|
||
DispatchCode = (PULONG)PCR->InterruptRoutine[LynxBaseVector + Var.Vector];
|
||
InterruptObject = CONTAINING_RECORD(DispatchCode,
|
||
KINTERRUPT,
|
||
DispatchCode);
|
||
|
||
ReturnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
|
||
|
||
//
|
||
// Send an SEOI.
|
||
//
|
||
|
||
WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Var, Var.Vector );
|
||
|
||
return(ReturnValue);
|
||
}
|
||
|
||
VOID
|
||
HalpDisableLynxSioInterrupt(
|
||
IN ULONG Vector
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine disables interrupts associated with the Standard I/O
|
||
ICIC.
|
||
|
||
Arguments:
|
||
|
||
Vector - The vector of the interrupt to disable.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONGLONG IrqMask;
|
||
|
||
if( (Vector >= LynxBaseVector) &&
|
||
(Vector <= LynxPciSlot3DVector) ){
|
||
|
||
//
|
||
// Compute the IRQ mask.
|
||
//
|
||
|
||
IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - LynxBaseVector);
|
||
|
||
//
|
||
// Mask the interrupt.
|
||
//
|
||
|
||
LynxIcIcMaskRegister |= IrqMask;
|
||
|
||
//
|
||
// Update the ICIC Mask Register.
|
||
//
|
||
|
||
WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcMaskRegister,
|
||
LynxIcIcMaskRegister );
|
||
|
||
} else {
|
||
|
||
#if defined(XIO_PASS1) || defined(XIO_PASS2)
|
||
|
||
HalpDisableXioInterrupt( Vector );
|
||
|
||
#endif
|
||
|
||
}
|
||
}
|
||
|
||
BOOLEAN
|
||
HalpEnableLynxSioInterrupt(
|
||
IN ULONG Vector,
|
||
IN KINTERRUPT_MODE InterruptMode
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine enables interrupts associated with the Standard I/O
|
||
ICIC.
|
||
|
||
Arguments:
|
||
|
||
Vector - The vector of the interrupt to enable.
|
||
|
||
InterruptMode - An indication of whether the interrupt should
|
||
be edge-triggered/level-sensitive.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONGLONG IrqMask;
|
||
|
||
if( (Vector >= LynxBaseVector) &&
|
||
(Vector <= LynxPciSlot3DVector) ){
|
||
|
||
//
|
||
// Compute the IRQ mask.
|
||
//
|
||
|
||
IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - LynxBaseVector);
|
||
|
||
//
|
||
// For EISA interrupts InterruptMode indicates whether the interrupt
|
||
// is level sensitive (active low) or edge-triggered (low-to-high).
|
||
// We use this information to update the Edge/Level Control Register
|
||
// bit for this IRQ.
|
||
//
|
||
|
||
switch( Vector ){
|
||
|
||
case LynxEisaIrq3Vector:
|
||
case LynxEisaIrq4Vector:
|
||
case LynxEisaIrq5Vector:
|
||
case LynxEisaIrq6Vector:
|
||
case LynxEisaIrq7Vector:
|
||
case LynxEisaIrq9Vector:
|
||
case LynxEisaIrq10Vector:
|
||
case LynxEisaIrq11Vector:
|
||
case LynxEisaIrq12Vector:
|
||
case LynxEisaIrq14Vector:
|
||
case LynxEisaIrq15Vector:
|
||
|
||
//
|
||
// Set/Clear the ELCR bit (as appropriate).
|
||
//
|
||
|
||
if( InterruptMode == LevelSensitive ){
|
||
LynxIcIcElcrRegister |= IrqMask;
|
||
} else {
|
||
LynxIcIcElcrRegister &= ~IrqMask;
|
||
}
|
||
|
||
//
|
||
// Update the ICIC Edge/Level Control Register.
|
||
//
|
||
|
||
WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcElcrRegister,
|
||
LynxIcIcElcrRegister );
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Un-mask the interrupt.
|
||
//
|
||
|
||
LynxIcIcMaskRegister &= ~IrqMask;
|
||
|
||
//
|
||
// Update the ICIC Mask Register.
|
||
//
|
||
|
||
WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcMaskRegister,
|
||
LynxIcIcMaskRegister );
|
||
|
||
return TRUE;
|
||
|
||
} else {
|
||
|
||
#if defined(XIO_PASS1) || defined(XIO_PASS2)
|
||
|
||
return HalpEnableXioInterrupt( Vector, InterruptMode );
|
||
|
||
#endif
|
||
|
||
}
|
||
|
||
return FALSE;
|
||
}
|