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
|