913 lines
20 KiB
C
913 lines
20 KiB
C
/*++
|
||
|
||
Copyright (c) 1995 Digital Equipment Corporation
|
||
|
||
Module Name:
|
||
|
||
xiintsup.c
|
||
|
||
Abstract:
|
||
|
||
This module provides interrupt support for the Sable/Gamma/Lynx
|
||
External I/O module.
|
||
|
||
Author:
|
||
|
||
Dave Richarda 1-June-1995
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#ifdef XIO_PASS1
|
||
|
||
#include "halp.h"
|
||
#include "eisa.h"
|
||
#include "sableref.h"
|
||
#include "xiintsup.h"
|
||
|
||
//
|
||
// External I/O 8259 Mask registers.
|
||
//
|
||
|
||
UCHAR XioMasterInterruptMask;
|
||
UCHAR XioSlaveInterruptMask;
|
||
|
||
//
|
||
// Define the context structure for use by interrupt service routines.
|
||
//
|
||
|
||
typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
|
||
PKINTERRUPT InterruptObject
|
||
);
|
||
|
||
extern ULONG HalpProcessors;
|
||
|
||
|
||
ULONG
|
||
HalpGetXioInterruptVector(
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN ULONG BusInterruptLevel,
|
||
IN ULONG BusInterruptVector,
|
||
OUT PKIRQL Irql,
|
||
OUT PKAFFINITY Affinity
|
||
)
|
||
{
|
||
if( HalpXioPresent ){
|
||
|
||
switch( BusInterruptLevel ){
|
||
|
||
case XioPciSlot0AVector:
|
||
case XioPciSlot0BVector:
|
||
case XioPciSlot0CVector:
|
||
case XioPciSlot0DVector:
|
||
case XioPciSlot1AVector:
|
||
case XioPciSlot1BVector:
|
||
case XioPciSlot1CVector:
|
||
case XioPciSlot1DVector:
|
||
|
||
*Irql = PCI_DEVICE_LEVEL;
|
||
|
||
if( HalpProcessors > 1 ){
|
||
*Affinity = HAL_CPU1_MASK;
|
||
} else {
|
||
*Affinity = HAL_CPU0_MASK;
|
||
}
|
||
|
||
return( SABLE_VECTORS + BusInterruptLevel );
|
||
|
||
}
|
||
}
|
||
|
||
//
|
||
// The caller specified a bus level not support by this platform.
|
||
//
|
||
|
||
*Irql = 0;
|
||
*Affinity = 0;
|
||
return(0);
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
HalpInitializeXioInterrupts(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine does the following:
|
||
(1) initializes the Xio 8259 interrupt registers
|
||
(2) initializes structures necessary for EISA operations
|
||
(3) connects the intermediate interrupt dispatcher.
|
||
(4) initializes the EISA interrupt controller.
|
||
|
||
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.
|
||
|
||
--*/
|
||
{
|
||
UCHAR DataByte;
|
||
|
||
//
|
||
// Initialize the Xio interrupt controllers. The interrupt structure
|
||
// is one master interrupt controller with 1 cascaded slave controller.
|
||
// Proceed through each control word programming each of the controllers.
|
||
//
|
||
|
||
//
|
||
// Write control word 1 for each of the controllers, indicate
|
||
// that initialization is in progress and the control word 4 will
|
||
// be used.
|
||
//
|
||
|
||
DataByte = 0;
|
||
((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
|
||
// ((PINITIALIZATION_COMMAND_1) &DataByte)->LevelTriggeredMode = 1;
|
||
DataByte |= 0x04;
|
||
((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterControl,
|
||
DataByte
|
||
);
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveControl,
|
||
DataByte
|
||
);
|
||
|
||
//
|
||
// Write control word 2 for each of the controllers, set the base
|
||
// interrupt vector for each controller.
|
||
//
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
|
||
XioMasterBaseVector
|
||
);
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
|
||
XioSlaveBaseVector
|
||
);
|
||
|
||
//
|
||
// The third initialization control word set the controls for slave mode.
|
||
// The master ICW3 uses bit position and the slave ICW3 uses a numeric.
|
||
//
|
||
|
||
DataByte = (1 << (XioSlaveCascadeVector & ~XioMasterBaseVector) );
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
|
||
DataByte
|
||
);
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
|
||
(XioSlaveCascadeVector & ~XioMasterBaseVector)
|
||
);
|
||
|
||
//
|
||
// The fourth initialization control word is used to specify normal
|
||
// end-of-interrupt mode and not special-fully-nested mode.
|
||
//
|
||
|
||
DataByte = 0;
|
||
((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
|
||
#ifdef XIO_AEOI
|
||
((PINITIALIZATION_COMMAND_4) &DataByte)->AutoEndOfInterruptMode = 1;
|
||
#endif
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
|
||
DataByte
|
||
);
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
|
||
DataByte
|
||
);
|
||
|
||
//
|
||
// Disable all of the interrupts except the slave interrupts to the
|
||
// master controller.
|
||
//
|
||
|
||
XioMasterInterruptMask =
|
||
(UCHAR)( ~(1 << (XioSlaveCascadeVector & ~XioMasterBaseVector)) );
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
|
||
XioMasterInterruptMask
|
||
);
|
||
|
||
XioSlaveInterruptMask = 0xFF;
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
|
||
XioSlaveInterruptMask
|
||
);
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
HalpXioDispatch(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is entered as a result of an interrupt being generated
|
||
via the vector that is directly connected XIO device interrupt.
|
||
|
||
This routine is responsible for determining the
|
||
source of the interrupt, performing the secondary dispatch and
|
||
acknowledging the interrupt in the 8259 controllers.
|
||
|
||
N.B. This interrupt is directly connected and therefore, no argument
|
||
values are defined.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Returns the value returned from the second level routine.
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR interruptVector;
|
||
BOOLEAN returnValue;
|
||
USHORT IdtIndex;
|
||
UCHAR InService;
|
||
PULONG DispatchCode;
|
||
PKINTERRUPT InterruptObject;
|
||
|
||
//
|
||
// Acknowledge the Interrupt controller and receive the returned
|
||
// interrupt vector.
|
||
//
|
||
|
||
interruptVector = READ_REGISTER_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS)
|
||
XIO_INTERRUPT_CSRS_QVA)->InterruptAcknowledge
|
||
);
|
||
|
||
//
|
||
// If we get a passive release, send a non-specific end of interrupt
|
||
// command and return TRUE, indicating that we processed the interrupt.
|
||
//
|
||
|
||
switch( interruptVector ){
|
||
|
||
case XioMasterPassiveReleaseVector:
|
||
|
||
#ifdef XIO_AEOI
|
||
|
||
//
|
||
// If the passive release vector has not been enabled, then we can
|
||
// dismiss it now.
|
||
//
|
||
|
||
if( XioMasterInterruptMask & 0x80 ){
|
||
return TRUE;
|
||
}
|
||
|
||
#else // XIO_AEOI
|
||
|
||
//
|
||
// Read the "in-service" mask.
|
||
//
|
||
|
||
WRITE_PORT_UCHAR( &((PSABLE_INTERRUPT_CSRS)SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
|
||
0x0B
|
||
);
|
||
|
||
InService = READ_PORT_UCHAR(
|
||
&((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl
|
||
);
|
||
|
||
if( (InService & 0x80) == 0 ){
|
||
|
||
//
|
||
// Send end of interrupt to clear the passive release in the
|
||
// master controller.
|
||
//
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterControl,
|
||
NONSPECIFIC_END_OF_INTERRUPT
|
||
);
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
#endif // XIO_AEOI
|
||
|
||
break;
|
||
|
||
case XioSlavePassiveReleaseVector:
|
||
|
||
#ifdef XIO_AEOI
|
||
|
||
//
|
||
// If the passive release vector has not been enabled, then we can
|
||
// dismiss it now.
|
||
//
|
||
|
||
if( XioSlaveInterruptMask & 0x80 ){
|
||
return TRUE;
|
||
}
|
||
|
||
#else // XIO_AEOI
|
||
|
||
//
|
||
// Read the "in-service" mask.
|
||
//
|
||
|
||
WRITE_PORT_UCHAR( &((PSABLE_INTERRUPT_CSRS)SABLE_INTERRUPT_CSRS_QVA)->SlaveControl,
|
||
0x0B
|
||
);
|
||
|
||
InService = READ_PORT_UCHAR(
|
||
&((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->SlaveControl
|
||
);
|
||
|
||
if( (InService & 0x80) == 0 ){
|
||
|
||
//
|
||
// Send end of interrupt to clear the passive release in the
|
||
// slave controller.
|
||
//
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveControl,
|
||
NONSPECIFIC_END_OF_INTERRUPT
|
||
);
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
#endif // XIO_AEOI
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Dispatch to the secondary interrupt service routine.
|
||
//
|
||
|
||
IdtIndex = interruptVector + SABLE_VECTORS;
|
||
DispatchCode = (PULONG)PCR->InterruptRoutine[IdtIndex];
|
||
InterruptObject = CONTAINING_RECORD(DispatchCode,
|
||
KINTERRUPT,
|
||
DispatchCode);
|
||
|
||
returnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
|
||
|
||
#ifndef XIO_AEOI
|
||
|
||
//
|
||
// Dismiss the interrupt in the 8259 interrupt controllers.
|
||
// If this is a cascaded interrupt then the interrupt must be dismissed in
|
||
// both controllers.
|
||
//
|
||
|
||
if( (interruptVector & XioSlaveBaseVector) == XioSlaveBaseVector ){
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveControl,
|
||
NONSPECIFIC_END_OF_INTERRUPT
|
||
);
|
||
|
||
}
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterControl,
|
||
NONSPECIFIC_END_OF_INTERRUPT
|
||
);
|
||
|
||
#endif // XIO_AEOI
|
||
|
||
return(returnValue);
|
||
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
HalpDisableXioInterrupt(
|
||
IN ULONG Vector
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function Disables the External IO specified interrupt.
|
||
|
||
Arguments:
|
||
|
||
Vector - Supplies the vector of the Xio interrupt that is Disabled.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Interrupt;
|
||
|
||
if( (Vector >= SABLE_VECTORS + XioMasterBaseVector) &&
|
||
(Vector <= SABLE_VECTORS + XioSlavePassiveReleaseVector) ){
|
||
|
||
//
|
||
// Calculate the Xio relative interrupt vector.
|
||
//
|
||
|
||
Vector -= SABLE_VECTORS;
|
||
|
||
//
|
||
// Compute the interrupt within the interrupt controller.
|
||
//
|
||
|
||
Interrupt = Vector & 0x7;
|
||
|
||
//
|
||
// Enable the interrupt for the appropriate interrupt controller.
|
||
//
|
||
|
||
if( (Vector & XioSlaveBaseVector) == XioSlaveBaseVector ){
|
||
|
||
XioSlaveInterruptMask |= (UCHAR) (1 << Interrupt);
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
|
||
XioSlaveInterruptMask
|
||
);
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
BOOLEAN
|
||
HalpEnableXioInterrupt(
|
||
IN ULONG Vector,
|
||
IN KINTERRUPT_MODE InterruptMode
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function enables the Xio specified interrupt in the
|
||
appropriate 8259 interrupt controllers. It also supports the
|
||
edge/level control for EISA bus interrupts. By default, all interrupts
|
||
are edge detected (and latched).
|
||
|
||
Arguments:
|
||
|
||
Vector - Supplies the vector of the Xio interrupt that is enabled.
|
||
|
||
InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
|
||
Latched (Edge).
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Interrupt;
|
||
|
||
if( (Vector >= SABLE_VECTORS + XioMasterBaseVector) &&
|
||
(Vector <= SABLE_VECTORS + XioSlavePassiveReleaseVector) ){
|
||
|
||
//
|
||
// Calculate the Xio relative interrupt vector.
|
||
//
|
||
|
||
Vector -= SABLE_VECTORS;
|
||
|
||
//
|
||
// Compute the interrupt within the interrupt controller.
|
||
//
|
||
|
||
Interrupt = Vector & 0x7;
|
||
|
||
//
|
||
// Enable the interrupt for the appropriate interrupt controller.
|
||
//
|
||
|
||
if( (Vector & XioSlaveBaseVector) == XioSlaveBaseVector ){
|
||
|
||
XioSlaveInterruptMask &= (UCHAR) ~(1 << Interrupt);
|
||
|
||
WRITE_PORT_UCHAR(
|
||
&((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
|
||
XioSlaveInterruptMask
|
||
);
|
||
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
#endif // XIO_PASS1
|
||
|
||
#ifdef XIO_PASS2
|
||
|
||
#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
|
||
);
|
||
|
||
extern ULONG HalpProcessors;
|
||
|
||
//
|
||
// Cached copies of the corresponding ICIC register(s).
|
||
//
|
||
|
||
ICIC_MASK_REGISTER XioIcIcMaskRegister;
|
||
|
||
|
||
ULONG
|
||
HalpGetXioInterruptVector(
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN ULONG BusInterruptLevel,
|
||
IN ULONG BusInterruptVector,
|
||
OUT PKIRQL Irql,
|
||
OUT PKAFFINITY Affinity
|
||
)
|
||
{
|
||
if( HalpXioPresent ){
|
||
|
||
switch( BusInterruptLevel ){
|
||
|
||
//
|
||
// Handle Vectors for PCI devices.
|
||
//
|
||
|
||
case XioPciSlot0AVector:
|
||
case XioPciSlot0BVector:
|
||
case XioPciSlot0CVector:
|
||
case XioPciSlot0DVector:
|
||
case XioPciSlot1AVector:
|
||
case XioPciSlot1BVector:
|
||
case XioPciSlot1CVector:
|
||
case XioPciSlot1DVector:
|
||
case XioPciSlot2AVector:
|
||
case XioPciSlot2BVector:
|
||
case XioPciSlot2CVector:
|
||
case XioPciSlot2DVector:
|
||
case XioPciSlot3AVector:
|
||
case XioPciSlot3BVector:
|
||
case XioPciSlot3CVector:
|
||
case XioPciSlot3DVector:
|
||
case XioPciSlot4AVector:
|
||
case XioPciSlot4BVector:
|
||
case XioPciSlot4CVector:
|
||
case XioPciSlot4DVector:
|
||
case XioPciSlot5AVector:
|
||
case XioPciSlot5BVector:
|
||
case XioPciSlot5CVector:
|
||
case XioPciSlot5DVector:
|
||
case XioPciSlot6AVector:
|
||
case XioPciSlot6BVector:
|
||
case XioPciSlot6CVector:
|
||
case XioPciSlot6DVector:
|
||
case XioPciSlot7AVector:
|
||
case XioPciSlot7BVector:
|
||
case XioPciSlot7CVector:
|
||
case XioPciSlot7DVector:
|
||
|
||
*Irql = DEVICE_LEVEL;
|
||
|
||
if( HalpProcessors > 1 ){
|
||
*Affinity = HAL_CPU1_MASK;
|
||
} else {
|
||
*Affinity = HAL_CPU0_MASK;
|
||
}
|
||
|
||
return( BusInterruptLevel );
|
||
|
||
}
|
||
}
|
||
|
||
*Irql = 0;
|
||
*Affinity = 0;
|
||
return 0;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
HalpInitializeXioInterrupts(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the ICIC on the Standard I/O module.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
TRUE.
|
||
|
||
--*/
|
||
|
||
{
|
||
T2_ICE Ice;
|
||
ICIC_ELCR_REGISTER XioIcIcElcrRegister;
|
||
|
||
//
|
||
// 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)(T4_CSRS_QVA))->Ice,
|
||
Ice.all );
|
||
|
||
//
|
||
// Initialize the ICIC Mask Register.
|
||
//
|
||
|
||
XioIcIcMaskRegister = (ULONGLONG)-1;
|
||
|
||
WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcMaskRegister,
|
||
XioIcIcMaskRegister );
|
||
|
||
//
|
||
// Initialize the ICIC Edge/Level Control Register.
|
||
//
|
||
|
||
XioIcIcElcrRegister =
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot4AVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot4BVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot4CVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot4DVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot5AVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot5BVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot5CVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot5DVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot6AVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot6BVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot6CVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot6DVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot7AVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot7BVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot7CVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot7DVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot7DVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot0AVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot0BVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot0CVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot0DVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot1AVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot1BVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot1CVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot1DVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot2AVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot2BVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot2CVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot2DVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot3AVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot3BVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot3CVector - XioBaseVector)) |
|
||
((ICIC_ELCR_REGISTER)1 << (XioPciSlot3DVector - XioBaseVector));
|
||
|
||
WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcElcrRegister,
|
||
XioIcIcElcrRegister );
|
||
|
||
//
|
||
// Initialize the ICIC EISA Register.
|
||
//
|
||
|
||
WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcEisaRegister, (ULONGLONG)0 );
|
||
|
||
//
|
||
// Initialize the ICIC Mode Register.
|
||
//
|
||
|
||
WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcModeRegister, (ULONGLONG)0 );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
HalpXioDispatch(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine dispatches interrupts received by the External 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)(T4_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[XioBaseVector + Var.Vector];
|
||
InterruptObject = CONTAINING_RECORD(DispatchCode,
|
||
KINTERRUPT,
|
||
DispatchCode);
|
||
|
||
ReturnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
|
||
|
||
//
|
||
// Send an SEOI.
|
||
//
|
||
|
||
WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Var, Var.Vector );
|
||
|
||
return(ReturnValue);
|
||
}
|
||
|
||
VOID
|
||
HalpDisableXioInterrupt(
|
||
IN ULONG Vector
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine disables interrupts associated with the External I/O
|
||
ICIC.
|
||
|
||
Arguments:
|
||
|
||
Vector - The vector of the interrupt to disable.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONGLONG IrqMask;
|
||
|
||
if( (Vector >= XioBaseVector) &&
|
||
(Vector <= XioPciSlot3DVector) ){
|
||
|
||
//
|
||
// Compute the IRQ mask.
|
||
//
|
||
|
||
IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - XioBaseVector);
|
||
|
||
//
|
||
// Mask the interrupt.
|
||
//
|
||
|
||
XioIcIcMaskRegister |= IrqMask;
|
||
|
||
//
|
||
// Update the ICIC Mask Register.
|
||
//
|
||
|
||
WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcMaskRegister,
|
||
XioIcIcMaskRegister );
|
||
|
||
}
|
||
}
|
||
|
||
BOOLEAN
|
||
HalpEnableXioInterrupt(
|
||
IN ULONG Vector,
|
||
IN KINTERRUPT_MODE InterruptMode
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine enables interrupts associated with the External 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. (Ignored)
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONGLONG IrqMask;
|
||
|
||
if( (Vector >= XioBaseVector) &&
|
||
(Vector <= XioPciSlot3DVector) ){
|
||
|
||
//
|
||
// Compute the IRQ mask.
|
||
//
|
||
|
||
IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - XioBaseVector);
|
||
|
||
//
|
||
// Un-mask the interrupt.
|
||
//
|
||
|
||
XioIcIcMaskRegister &= ~IrqMask;
|
||
|
||
//
|
||
// Update the ICIC Mask Register.
|
||
//
|
||
|
||
WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcMaskRegister,
|
||
XioIcIcMaskRegister );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
#endif // XIO_PASS2
|