2020-09-30 17:12:29 +02:00

518 lines
12 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
}