441 lines
7.2 KiB
C
441 lines
7.2 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1994 Digital Equipment Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
ev5int.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the support routines to control DECchip 21164
|
|||
|
interrupts.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Joe Notarangelo 20-Jul-1994
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "halp.h"
|
|||
|
#include "axp21164.h"
|
|||
|
|
|||
|
//
|
|||
|
// Function prototype.
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
HalpCachePcrValues(
|
|||
|
ULONG InterruptMask
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpInitialize21164Interrupts(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the data structures for the 21164
|
|||
|
interrupt routines.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PIMSK_21164 InterruptMask;
|
|||
|
PBOOLEAN InterruptsStarted;
|
|||
|
|
|||
|
//
|
|||
|
// Set up the standard correspondence of NT IRQLs to EV5 IPLs.
|
|||
|
// It is possible that some machines may need a different correspondence
|
|||
|
// then the one below - HALs that change this table do so at their
|
|||
|
// own risk.
|
|||
|
//
|
|||
|
// NT IRQL EV5 IPL
|
|||
|
// ------- -------
|
|||
|
// PASSIVE_LEVEL 0
|
|||
|
// APC_LEVEL 1
|
|||
|
// DISPATCH_LEVEL 2
|
|||
|
// DEVICE_LEVEL 20
|
|||
|
// DEVICE_HIGH_LEVEL 21
|
|||
|
// CLOCK_LEVEL 22
|
|||
|
// IPI_LEVEL 23
|
|||
|
// HIGH_LEVEL 31
|
|||
|
//
|
|||
|
|
|||
|
PCR->IrqlTable[PASSIVE_LEVEL] = EV5_IPL0;
|
|||
|
PCR->IrqlTable[APC_LEVEL] = EV5_IPL1;
|
|||
|
PCR->IrqlTable[DISPATCH_LEVEL] = EV5_IPL2;
|
|||
|
PCR->IrqlTable[DEVICE_LEVEL] = EV5_IPL20;
|
|||
|
PCR->IrqlTable[DEVICE_HIGH_LEVEL] = EV5_IPL21;
|
|||
|
PCR->IrqlTable[CLOCK_LEVEL] = EV5_IPL22;
|
|||
|
PCR->IrqlTable[IPI_LEVEL] = EV5_IPL23;
|
|||
|
PCR->IrqlTable[HIGH_LEVEL] = EV5_IPL31;
|
|||
|
|
|||
|
//
|
|||
|
// Define the default set of disables (masks) for the EV5 interrupt
|
|||
|
// pins INT0 - INT3. All interrupts are enabled by default and may
|
|||
|
// be disabled by the interface: HalpDisable21164HardwareInterrupt().
|
|||
|
//
|
|||
|
|
|||
|
InterruptMask = (PIMSK_21164)(&PCR->IrqlMask[0]);
|
|||
|
|
|||
|
InterruptMask->all = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Indicate that interrupts have not been started yet.
|
|||
|
//
|
|||
|
|
|||
|
InterruptsStarted = (PBOOLEAN)(&PCR->IrqlMask[1]);
|
|||
|
*InterruptsStarted = FALSE;
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpStart21164Interrupts(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function starts interrupt dispatching on the current 21164.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PIMSK_21164 InterruptMask;
|
|||
|
PBOOLEAN InterruptsStarted;
|
|||
|
|
|||
|
//
|
|||
|
// Issue the initpcr call pal to alert the PALcode that it can
|
|||
|
// begin taking interrupts, pass the disable mask for the hardware
|
|||
|
// interrupts.
|
|||
|
//
|
|||
|
|
|||
|
InterruptMask = (PIMSK_21164)(&PCR->IrqlMask);
|
|||
|
HalpCachePcrValues( InterruptMask->all );
|
|||
|
|
|||
|
//
|
|||
|
// Indicate that interrupts have been started yet.
|
|||
|
//
|
|||
|
|
|||
|
InterruptsStarted = (PBOOLEAN)(&PCR->IrqlMask[1]);
|
|||
|
*InterruptsStarted = TRUE;
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#if 0 // used ??
|
|||
|
|
|||
|
VOID
|
|||
|
HalpEnable21164HardwareInterrupt(
|
|||
|
IN ULONG Irq
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Clear the mask value for the desired Irq pin so that interrupts
|
|||
|
are enabled from that pin.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Irq - Supplies the interrupt pin number to be enabled.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PIMSK_21164 InterruptMask;
|
|||
|
PBOOLEAN InterruptsStarted;
|
|||
|
KIRQL OldIrql;
|
|||
|
|
|||
|
//
|
|||
|
// Raise Irql to HIGH_LEVEL to prevent any interrupts.
|
|||
|
//
|
|||
|
|
|||
|
KeRaiseIrql( HIGH_LEVEL, &OldIrql );
|
|||
|
|
|||
|
//
|
|||
|
// Clear the mask value for the desired Irq pin.
|
|||
|
//
|
|||
|
|
|||
|
InterruptMask = (PIMSK_21164)(&PCR->IrqlMask);
|
|||
|
|
|||
|
switch( Irq ){
|
|||
|
|
|||
|
case Irq0:
|
|||
|
|
|||
|
InterruptMask->Irq0Mask = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case Irq1:
|
|||
|
|
|||
|
InterruptMask->Irq1Mask = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case Irq2:
|
|||
|
|
|||
|
InterruptMask->Irq2Mask = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case Irq3:
|
|||
|
|
|||
|
InterruptMask->Irq3Mask = 0;
|
|||
|
break;
|
|||
|
|
|||
|
} //end switch (Irq)
|
|||
|
|
|||
|
//
|
|||
|
// Set the new masks in the PALcode.
|
|||
|
//
|
|||
|
|
|||
|
InterruptsStarted = (PBOOLEAN)(&PCR->IrqlMask[1]);
|
|||
|
if( *InterruptsStarted == TRUE ){
|
|||
|
HalpCachePcrValues( InterruptMask->all );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Lower Irql to the previous level and return.
|
|||
|
//
|
|||
|
|
|||
|
KeLowerIrql( OldIrql );
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpDisable21164HardwareInterrupt(
|
|||
|
IN ULONG Irq
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Set the mask value for the desired Irq pin so that interrupts
|
|||
|
are disabled from that pin.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Irq - Supplies the interrupt pin number to be disabled.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PIMSK_21164 InterruptMask;
|
|||
|
PBOOLEAN InterruptsStarted;
|
|||
|
KIRQL OldIrql;
|
|||
|
|
|||
|
//
|
|||
|
// Raise Irql to HIGH_LEVEL to prevent any interrupts.
|
|||
|
//
|
|||
|
|
|||
|
KeRaiseIrql( HIGH_LEVEL, &OldIrql );
|
|||
|
|
|||
|
//
|
|||
|
// Set the mask value for the desired Irq pin.
|
|||
|
//
|
|||
|
|
|||
|
InterruptMask = (PIMSK_21164)(&PCR->IrqlMask);
|
|||
|
|
|||
|
switch( Irq ){
|
|||
|
|
|||
|
case Irq0:
|
|||
|
|
|||
|
InterruptMask->Irq0Mask = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case Irq1:
|
|||
|
|
|||
|
InterruptMask->Irq1Mask = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case Irq2:
|
|||
|
|
|||
|
InterruptMask->Irq2Mask = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case Irq3:
|
|||
|
|
|||
|
InterruptMask->Irq3Mask = 1;
|
|||
|
break;
|
|||
|
|
|||
|
} //end switch (Irq)
|
|||
|
|
|||
|
//
|
|||
|
// Set the new masks in the PALcode, if interrupts have been started.
|
|||
|
//
|
|||
|
|
|||
|
InterruptsStarted = (PBOOLEAN)(&PCR->IrqlMask[1]);
|
|||
|
if( *InterruptsStarted == TRUE ){
|
|||
|
HalpCachePcrValues( InterruptMask->all );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Lower Irql to the previous level and return.
|
|||
|
//
|
|||
|
|
|||
|
KeLowerIrql( OldIrql );
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#endif // Used ??
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpGet21164PerformanceVector(
|
|||
|
IN ULONG BusInterruptLevel,
|
|||
|
OUT PKIRQL Irql
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function returns the system interrupt vector and IRQL level
|
|||
|
corresponding to the specified performance counter interrupt.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BusInterruptLevel - Supplies the performance counter number.
|
|||
|
|
|||
|
Irql - Returns the system request priority.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the system interrupt vector corresponding to the specified device.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Handle the special internal bus defined for the processor itself
|
|||
|
// and used to control the performance counters in the 21164.
|
|||
|
//
|
|||
|
|
|||
|
*Irql = PROFILE_LEVEL;
|
|||
|
|
|||
|
switch( BusInterruptLevel ){
|
|||
|
|
|||
|
//
|
|||
|
// Performance Counter 0
|
|||
|
//
|
|||
|
|
|||
|
case 0:
|
|||
|
|
|||
|
return PC0_SECONDARY_VECTOR;
|
|||
|
|
|||
|
//
|
|||
|
// Performance Counter 1
|
|||
|
//
|
|||
|
|
|||
|
case 1:
|
|||
|
|
|||
|
return PC1_SECONDARY_VECTOR;
|
|||
|
|
|||
|
//
|
|||
|
// Performance Counter 2
|
|||
|
//
|
|||
|
|
|||
|
case 2:
|
|||
|
|
|||
|
return PC2_SECONDARY_VECTOR;
|
|||
|
|
|||
|
} //end switch( BusInterruptLevel )
|
|||
|
|
|||
|
//
|
|||
|
// Unrecognized.
|
|||
|
//
|
|||
|
|
|||
|
*Irql = 0;
|
|||
|
return 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpGet21164CorrectableVector(
|
|||
|
IN ULONG BusInterruptLevel,
|
|||
|
OUT PKIRQL Irql
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function returns the system interrupt vector and IRQL level
|
|||
|
corresponding to the specified correctable interrupt.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BusInterruptLevel - Supplies the performance counter number.
|
|||
|
|
|||
|
Irql - Returns the system request priority.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the system interrupt vector corresponding to the specified device.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// Get the correctable interrupt vector.
|
|||
|
//
|
|||
|
|
|||
|
if (BusInterruptLevel == 5) {
|
|||
|
|
|||
|
//
|
|||
|
// Correctable error interrupt was sucessfully recognized.
|
|||
|
//
|
|||
|
|
|||
|
*Irql = DEVICE_HIGH_LEVEL;
|
|||
|
return CORRECTABLE_VECTOR;
|
|||
|
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Unrecognized.
|
|||
|
//
|
|||
|
|
|||
|
*Irql = 0;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|