457 lines
8.9 KiB
C
457 lines
8.9 KiB
C
/*++
|
||
|
||
Copyright (c) 1993 Digital Equipment Corporation
|
||
|
||
Module Name:
|
||
|
||
sbsysint.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the HAL enable/disable system interrupt, and
|
||
request interprocessor interrupt routines for the Sable system.
|
||
|
||
Author:
|
||
|
||
Joe Notarangelo 29-Oct-1993
|
||
Steve Jenness 29-Oct-1993
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
#include "axp21064.h"
|
||
#include "siintsup.h"
|
||
#include "lyintsup.h"
|
||
#include "xiintsup.h"
|
||
|
||
//
|
||
// Define reference to the builtin device interrupt enables.
|
||
//
|
||
|
||
extern USHORT HalpBuiltinInterruptEnable;
|
||
|
||
|
||
VOID
|
||
HalDisableSystemInterrupt (
|
||
IN ULONG Vector,
|
||
IN KIRQL Irql
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine disables the specified system interrupt.
|
||
|
||
Arguments:
|
||
|
||
Vector - Supplies the vector of the system interrupt that is disabled.
|
||
|
||
Irql - Supplies the IRQL of the interrupting source.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Irq;
|
||
KIRQL OldIrql;
|
||
|
||
//
|
||
// Raise IRQL to the highest level and acquire the system interrupt
|
||
// lock.
|
||
//
|
||
|
||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||
|
||
KiAcquireSpinLock(&HalpSystemInterruptLock);
|
||
|
||
//
|
||
// If the vector is a performance counter vector or one of the internal
|
||
// device vectors then disable the interrupt for the 21064.
|
||
//
|
||
|
||
switch( Vector ){
|
||
|
||
//
|
||
// Performance counter 0 interrupt (internal to 21064)
|
||
//
|
||
|
||
case PC0_VECTOR:
|
||
case PC0_SECONDARY_VECTOR:
|
||
|
||
HalpDisable21064PerformanceInterrupt( PC0_VECTOR );
|
||
|
||
break;
|
||
|
||
//
|
||
// Performance counter 1 interrupt (internal to 21064)
|
||
//
|
||
|
||
case PC1_VECTOR:
|
||
case PC1_SECONDARY_VECTOR:
|
||
|
||
HalpDisable21064PerformanceInterrupt( PC1_VECTOR );
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
if( Irql == DEVICE_LEVEL ){
|
||
|
||
if( HalpLynxPlatform ){
|
||
|
||
HalpDisableLynxSioInterrupt( Vector );
|
||
|
||
} else {
|
||
|
||
HalpDisableSableSioInterrupt( Vector );
|
||
|
||
}
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Release the system interrupt lock and restore the IRWL.
|
||
//
|
||
|
||
KiReleaseSpinLock(&HalpSystemInterruptLock);
|
||
|
||
KeLowerIrql(OldIrql);
|
||
}
|
||
|
||
BOOLEAN
|
||
HalEnableSystemInterrupt (
|
||
IN ULONG Vector,
|
||
IN KIRQL Irql,
|
||
IN KINTERRUPT_MODE InterruptMode
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine enables the specified system interrupt.
|
||
|
||
Arguments:
|
||
|
||
Vector - Supplies the vector of the system interrupt that is enabled.
|
||
|
||
Irql - Supplies the IRQL of the interrupting source.
|
||
|
||
InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
|
||
Latched.
|
||
|
||
Return Value:
|
||
|
||
TRUE if the system interrupt was enabled
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOLEAN Enabled = FALSE;
|
||
ULONG Irq;
|
||
KIRQL OldIrql;
|
||
|
||
//
|
||
// Raise IRQL to the highest level.
|
||
//
|
||
|
||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||
|
||
//
|
||
// If the vector is a performance counter vector or one of the
|
||
// internal device vectors then perform 21064-specific enable.
|
||
//
|
||
|
||
switch (Vector) {
|
||
|
||
//
|
||
// Performance counter 0 (internal to 21064)
|
||
//
|
||
|
||
case PC0_VECTOR:
|
||
case PC0_SECONDARY_VECTOR:
|
||
|
||
HalpEnable21064PerformanceInterrupt( PC0_VECTOR, Irql );
|
||
Enabled = TRUE;
|
||
break;
|
||
|
||
//
|
||
// Performance counter 1 (internal to 21064)
|
||
//
|
||
|
||
case PC1_VECTOR:
|
||
case PC1_SECONDARY_VECTOR:
|
||
|
||
HalpEnable21064PerformanceInterrupt( PC1_VECTOR, Irql );
|
||
Enabled = TRUE;
|
||
break;
|
||
|
||
default:
|
||
|
||
if( HalpLynxPlatform ){
|
||
|
||
Enabled = HalpEnableLynxSioInterrupt( Vector, InterruptMode );
|
||
|
||
} else {
|
||
|
||
Enabled = HalpEnableSableSioInterrupt( Vector, InterruptMode );
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Lower IRQL to the previous level.
|
||
//
|
||
|
||
KeLowerIrql(OldIrql);
|
||
|
||
return Enabled;
|
||
}
|
||
|
||
ULONG
|
||
HalpGetSystemInterruptVector(
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN ULONG BusInterruptLevel,
|
||
IN ULONG BusInterruptVector,
|
||
OUT PKIRQL Irql,
|
||
OUT PKAFFINITY Affinity
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns the system interrupt vector and IRQL level
|
||
corresponding to the specified bus interrupt level and/or vector. The
|
||
system interrupt vector and IRQL are suitable for use in a subsequent call
|
||
to KeInitializeInterrupt.
|
||
|
||
// We only use InterfaceType, and BusInterruptLevel. BusInterruptVector
|
||
for ISA and EISA are the same as the InterruptLevel, so ignore.
|
||
|
||
Arguments:
|
||
|
||
BusHandler - Registered BUSHANDLER for the target configuration space
|
||
|
||
RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
|
||
request.
|
||
|
||
BusInterruptLevel - Supplies the bus specific interrupt level.
|
||
|
||
BusInterruptVector - Supplies the bus specific interrupt vector.
|
||
|
||
Irql - Returns the system request priority.
|
||
|
||
Affinity - Returns the affinity for the requested vector
|
||
|
||
Return Value:
|
||
|
||
Returns the system interrupt vector corresponding to the specified device.
|
||
|
||
--*/
|
||
|
||
{
|
||
INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
|
||
ULONG BusNumber = BusHandler->BusNumber;
|
||
ULONG Vector;
|
||
|
||
//
|
||
// Handle the special internal bus defined for the processor itself
|
||
// and used to control the performance counters in the 21064.
|
||
//
|
||
|
||
if( InterfaceType == ProcessorInternal ) {
|
||
|
||
Vector = HalpGet21064PerformanceVector( BusInterruptLevel, Irql );
|
||
|
||
if( Vector != 0 ){
|
||
|
||
//
|
||
// Success
|
||
//
|
||
|
||
*Affinity = HalpActiveProcessors;
|
||
return Vector;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Unrecognized processor interrupt.
|
||
//
|
||
|
||
*Irql = 0;
|
||
*Affinity = 0;
|
||
return 0;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Handle Isa/Eisa bus and Internal devices.
|
||
//
|
||
// N.B. The bus interrupt level is the actual E/ISA signal name for
|
||
// option boards while the bus interrupt level is the actual
|
||
// interrupt vector number for internal devices. The interrupt
|
||
// vectors for internal devices are specified in the firmware
|
||
// configuration and are agreed upon between the firmware and this
|
||
// code.
|
||
//
|
||
|
||
if( (InterfaceType == Internal) ||
|
||
(InterfaceType == Isa) ||
|
||
(InterfaceType == PCIBus) ||
|
||
(InterfaceType == Eisa) ){
|
||
|
||
if( HalpLynxPlatform ){
|
||
|
||
return HalpGetLynxSioInterruptVector(
|
||
BusHandler,
|
||
RootHandler,
|
||
BusInterruptLevel,
|
||
BusInterruptVector,
|
||
Irql,
|
||
Affinity
|
||
);
|
||
|
||
} else {
|
||
|
||
return HalpGetSableSioInterruptVector(
|
||
BusHandler,
|
||
RootHandler,
|
||
BusInterruptLevel,
|
||
BusInterruptVector,
|
||
Irql,
|
||
Affinity
|
||
);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// Not an interface supported on Alpha systems
|
||
//
|
||
|
||
*Irql = 0;
|
||
*Affinity = 0;
|
||
return(0);
|
||
|
||
}
|
||
|
||
VOID
|
||
HalRequestIpi (
|
||
IN ULONG Mask
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine requests an interprocessor interrupt on a set of processors.
|
||
|
||
Arguments:
|
||
|
||
Mask - Supplies the set of processors that are sent an interprocessor
|
||
interrupt.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
SABLE_IPIR_CSR Ipir;
|
||
extern PSABLE_CPU_CSRS HalpSableCpuCsrs[HAL_MAXIMUM_PROCESSOR+1];
|
||
|
||
//
|
||
// Set up to request an interprocessor interrupt.
|
||
//
|
||
|
||
Ipir.all = 0;
|
||
Ipir.RequestInterrupt = 1;
|
||
|
||
//
|
||
// N.B. Sable supports up to 4 processors only.
|
||
//
|
||
// N.B. A read-modify-write is not performed on the Ipir register
|
||
// which implies that the value of the request halt interrupt
|
||
// bit may be lost. Currently, this is not an important
|
||
// consideration because that feature is not being used.
|
||
// If later it is used than more consideration must be given
|
||
// to the possibility of losing the bit.
|
||
//
|
||
|
||
//
|
||
// The request mask is specified as a mask of the logical processors
|
||
// that must receive IPI requests. HalpSableCpuCsrs[] contains the
|
||
// CPU CSRs address for the logical processors.
|
||
//
|
||
|
||
//
|
||
// Request an IPI for processor 0 if requested.
|
||
//
|
||
|
||
if( Mask & HAL_CPU0_MASK ){
|
||
|
||
WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU0]->Ipir), Ipir.all );
|
||
|
||
}
|
||
|
||
//
|
||
// Request an IPI for processor 1 if requested.
|
||
//
|
||
|
||
if( Mask & HAL_CPU1_MASK ){
|
||
|
||
WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU1]->Ipir), Ipir.all );
|
||
|
||
}
|
||
|
||
//
|
||
// Request an IPI for processor 2 if requested.
|
||
//
|
||
|
||
if( Mask & HAL_CPU2_MASK ){
|
||
|
||
WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU2]->Ipir), Ipir.all );
|
||
|
||
}
|
||
|
||
//
|
||
// Request an IPI for processor 3 if requested.
|
||
//
|
||
|
||
if( Mask & HAL_CPU3_MASK ){
|
||
|
||
WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU3]->Ipir), Ipir.all );
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
return;
|
||
}
|