1308 lines
45 KiB
C
1308 lines
45 KiB
C
//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/r4intdsp.c,v 1.9 1996/02/23 17:55:12 pierre Exp $")
|
||
|
||
/*++
|
||
|
||
Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
|
||
|
||
Module Name:
|
||
|
||
r4intdsp.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the HalpXxx routines which are important to
|
||
handle the Interrupts on the SNI machines.
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
#include "SNIregs.h"
|
||
#include "mpagent.h"
|
||
#include "eisa.h"
|
||
#include "pci.h"
|
||
|
||
//
|
||
// Define the context structure for use by the interrupt routine.
|
||
//
|
||
|
||
typedef BOOLEAN (*PSECONDARY_DISPATCH)(
|
||
PVOID InterruptRoutine
|
||
);
|
||
|
||
typedef BOOLEAN (*PINT0_DISPATCH)(
|
||
PKINTERRUPT Interupt,
|
||
PVOID ServiceContext
|
||
);
|
||
|
||
extern VOID HalpSendIpi(IN ULONG pcpumask, IN ULONG msg_data);
|
||
|
||
KINTERRUPT HalpInt0Interrupt; // Interrupt Object for SC machines (centralised interrupt)
|
||
KINTERRUPT HalpInt3Interrupt; // Interrupt Object for IT3 tower multipro
|
||
|
||
ULONG HalpTargetRetryCnt=0; // Counter for pci error ( initiator receives target retry)
|
||
ULONG HalpSingleEccCounter = 0; // Single Ecc Error Counter (for RM200/RM300)
|
||
|
||
extern VOID
|
||
HalpReadPCIConfig (
|
||
IN ULONG BusNumber,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
);
|
||
|
||
extern VOID
|
||
HalpWritePCIConfig (
|
||
IN ULONG BusNumber,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
);
|
||
|
||
extern BOOLEAN
|
||
HalpPciEisaDispatch(
|
||
IN PKINTERRUPT Interrupt,
|
||
IN PVOID ServiceContext
|
||
) ;
|
||
|
||
extern BOOLEAN
|
||
HalpPciEisaSBDispatch(
|
||
IN PKINTERRUPT Interrupt,
|
||
IN PVOID ServiceContext
|
||
) ;
|
||
|
||
extern BOOLEAN HalpESC_SB;
|
||
|
||
BOOLEAN
|
||
HalpCreateIntPciStructures (
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the structures necessary for Int0-handling
|
||
and connects the intermediate interrupt dispatcher.
|
||
Also the structures necessary for PCI tower Int3 (MAUI interrupt)
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
If the second level interrupt dispatcher are connected, then a value of
|
||
TRUE is returned. Otherwise, a value of FALSE is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PVOID InterruptSourceRegister;
|
||
PINT0_DISPATCH (DispatchRoutine);
|
||
PKSPIN_LOCK pSpinLock;
|
||
|
||
switch (HalpMainBoard) {
|
||
case M8150 : InterruptSourceRegister = (PVOID)PCI_TOWER_INTERRUPT_SOURCE_REGISTER;
|
||
DispatchRoutine = HalpPciTowerInt0Dispatch;
|
||
pSpinLock = (PKSPIN_LOCK)NULL;
|
||
break;
|
||
|
||
default: InterruptSourceRegister = (PVOID)PCI_INTERRUPT_SOURCE_REGISTER;
|
||
DispatchRoutine = HalpPciInt0Dispatch;
|
||
pSpinLock = &HalpInterruptLock;
|
||
}
|
||
|
||
KeInitializeInterrupt( &HalpInt0Interrupt,
|
||
DispatchRoutine,
|
||
InterruptSourceRegister,
|
||
(PKSPIN_LOCK)pSpinLock,
|
||
INT0_LEVEL,
|
||
INT0_LEVEL, //INT0_LEVEL,
|
||
INT0_LEVEL, //Synchr. Level
|
||
LevelSensitive,
|
||
FALSE, // only one Intobject ispossible for int0
|
||
0, // processor number
|
||
FALSE // floating point registers
|
||
// and pipe line are not
|
||
// saved before calling
|
||
// the service routine
|
||
);
|
||
|
||
|
||
if (!KeConnectInterrupt( &HalpInt0Interrupt )) {
|
||
|
||
//
|
||
// this is the central Interrupt for the SNI SecondLevel Cache Machines
|
||
//
|
||
|
||
HalDisplayString("Failed to connect Int0!\n");
|
||
return(FALSE);
|
||
}
|
||
|
||
|
||
|
||
return (TRUE);
|
||
}
|
||
|
||
|
||
|
||
BOOLEAN
|
||
HalpCreateIntPciMAUIStructures (
|
||
CCHAR Number
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the structures necessary
|
||
for PCI tower Int3 (MAUI interrupt)
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
If the second level interrupt dispatcher are connected, then a value of
|
||
TRUE is returned. Otherwise, a value of FALSE is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PVOID InterruptSourceRegister;
|
||
|
||
InterruptSourceRegister = (PVOID)PCI_TOWER_INTERRUPT_SOURCE_REGISTER;
|
||
|
||
KeInitializeInterrupt( &HalpInt3Interrupt,
|
||
HalpPciTowerInt3Dispatch,
|
||
InterruptSourceRegister,
|
||
(PKSPIN_LOCK)&HalpInterruptLock,
|
||
INT6_LEVEL,
|
||
INT6_LEVEL, //INT6_LEVEL,
|
||
INT6_LEVEL, //Synchr. Level
|
||
LevelSensitive,
|
||
FALSE, // only one Intobject ispossible for int0
|
||
Number, // processor number
|
||
FALSE // floating point registers
|
||
// and pipe line are not
|
||
// saved before calling
|
||
// the service routine
|
||
);
|
||
|
||
|
||
if (!KeConnectInterrupt( &HalpInt3Interrupt )) {
|
||
|
||
//
|
||
// this is the central Interrupt for the SNI SecondLevel Cache Machines
|
||
//
|
||
|
||
HalDisplayString("Failed to connect Int3!\n");
|
||
return(FALSE);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
BOOLEAN
|
||
HalpPciInt0Dispatch (
|
||
IN PKINTERRUPT Interrupt,
|
||
IN PVOID ServiceContext
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
This routine handles the central INT0 Interrupt on an SNI PCI Desktop or Minitower
|
||
To decide which interrupt, read the Interrupt Source Register
|
||
|
||
We have to manage priorities by software.
|
||
|
||
Arguments:
|
||
|
||
Interrupt - Supplies a pointer to the interrupt object.
|
||
|
||
ServiceContext - Supplies a pointer to the Interrupt
|
||
Source register.
|
||
|
||
|
||
Return Value:
|
||
|
||
A BOOLEAN value, TRUE if the interrupt is OK,
|
||
otherwise FALSE for unknown interrupts
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR IntSource;
|
||
UCHAR MaStatus;
|
||
ULONG Itpend;
|
||
|
||
BOOLEAN SCSIresult, NETresult, result;
|
||
|
||
if (HalpCheckSpuriousInt(0x400)) return(FALSE);
|
||
|
||
|
||
IntSource = READ_REGISTER_UCHAR(ServiceContext);
|
||
|
||
IntSource ^= PCI_INTERRUPT_MASK; // XOR the low active bits with 1 gives 1
|
||
// and XOR the high active with 0 gives 1
|
||
|
||
if ( IntSource & PCI_EISA_MASK) { // EISA Interrupt
|
||
|
||
if (HalpESC_SB)
|
||
result = HalpPciEisaSBDispatch( NULL, // InterruptObject (unused)
|
||
(PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
|
||
);
|
||
else
|
||
result = HalpPciEisaDispatch( NULL, // InterruptObject (unused)
|
||
(PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
|
||
);
|
||
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(result);
|
||
}
|
||
|
||
//
|
||
// look for SCSI Interrupts
|
||
//
|
||
|
||
if ( IntSource & PCI_SCSI_MASK){
|
||
SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI_VECTOR])(
|
||
PCR->InterruptRoutine[SCSI_VECTOR]
|
||
);
|
||
#if DBG
|
||
if(!SCSIresult) DebugPrint(("Got an invalid SCSI interrupt !\n"));
|
||
#endif
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(SCSIresult);
|
||
|
||
}
|
||
|
||
//
|
||
// PCI interrupts
|
||
//
|
||
|
||
if ( IntSource & PCI_INTA_MASK){
|
||
int i;
|
||
for (i=INTA_VECTOR;i<HalpIntAMax;++i)
|
||
((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
|
||
PCR->InterruptRoutine[i]
|
||
);
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(TRUE);
|
||
}
|
||
|
||
if ( IntSource & PCI_INTB_MASK){
|
||
int i;
|
||
for (i=INTB_VECTOR;i<HalpIntBMax;++i)
|
||
((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
|
||
PCR->InterruptRoutine[i]
|
||
);
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(TRUE);
|
||
}
|
||
|
||
if ( IntSource & PCI_INTC_MASK){
|
||
int i;
|
||
for (i=INTC_VECTOR;i<HalpIntCMax;++i)
|
||
((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
|
||
PCR->InterruptRoutine[i]
|
||
);
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(TRUE);
|
||
}
|
||
|
||
if ( IntSource & PCI_INTD_MASK){
|
||
int i;
|
||
for (i=INTD_VECTOR;i<HalpIntDMax;++i)
|
||
((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
|
||
PCR->InterruptRoutine[i]
|
||
);
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(TRUE);
|
||
}
|
||
|
||
//
|
||
// look for an Ethernet Interrupt
|
||
//
|
||
|
||
if ( IntSource & PCI_NET_MASK){
|
||
NETresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[NET_LEVEL])(
|
||
PCR->InterruptRoutine[NET_LEVEL]
|
||
);
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(NETresult);
|
||
}
|
||
|
||
//
|
||
// Other interrupts => look in MSR register
|
||
//
|
||
|
||
if ( IntSource & PCI_INT2_MASK) {
|
||
|
||
MaStatus = READ_REGISTER_UCHAR(PCI_MSR_ADDR);
|
||
if (HalpMainBoard == DesktopPCI) {
|
||
MaStatus ^= PCI_MSR_MASK_D;
|
||
} else {
|
||
MaStatus ^= PCI_MSR_MASK_MT;
|
||
}
|
||
|
||
//
|
||
// look for an ASIC interrupt
|
||
//
|
||
|
||
if ( MaStatus & PCI_MSR_ASIC_MASK){
|
||
|
||
Itpend = READ_REGISTER_ULONG(PCI_ITPEND_REGISTER);
|
||
|
||
if ( Itpend & (PCI_ASIC_ECCERROR | PCI_ASIC_TRPERROR)) {
|
||
|
||
ULONG ErrAddr, AsicErrAddr, Syndrome, ErrStatus, irqsel;
|
||
|
||
AsicErrAddr = ErrAddr = READ_REGISTER_ULONG(PCI_ERRADDR_REGISTER);
|
||
Syndrome = READ_REGISTER_ULONG(PCI_SYNDROME_REGISTER);
|
||
Syndrome &= 0xff; // only 8 lower bits are significant
|
||
ErrStatus = READ_REGISTER_ULONG(PCI_ERRSTATUS_REGISTER);
|
||
|
||
if (ErrStatus & PCI_MEMSTAT_PARERR) {
|
||
// Parity error (PCI_ASIC <-> CPU)
|
||
irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
|
||
WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
|
||
(irqsel & 0x70000)); // PARERR it not routed
|
||
ErrAddr = HalpFindEccAddr(AsicErrAddr,(PVOID)PCI_ERRSTATUS_REGISTER,(PVOID)PCI_MEMSTAT_PARERR);
|
||
|
||
if (ErrAddr == -1) ErrAddr = AsicErrAddr;
|
||
|
||
#if DBG
|
||
DebugPrint(("pci_memory_error : errstatus=0x%x Add error=0x%x syndrome=0x%x \n",
|
||
ErrStatus,ErrAddr,Syndrome));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 1;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PARITY ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
|
||
#endif
|
||
}
|
||
|
||
if (ErrStatus & PCI_MEMSTAT_ECCERR) {
|
||
// ECC error (PCI_ASIC <-> Memory access)
|
||
AsicErrAddr &= 0xfffffff8;
|
||
irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
|
||
WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
|
||
(irqsel & 0xe000)); // ECC it not routed
|
||
ErrAddr = HalpFindEccAddr(AsicErrAddr,(PVOID)PCI_ERRSTATUS_REGISTER,(PVOID)PCI_MEMSTAT_ECCERR);
|
||
|
||
if (ErrAddr == -1) ErrAddr = AsicErrAddr;
|
||
|
||
if (ErrStatus & PCI_MEMSTAT_ECCSINGLE) {
|
||
// HalSweepDcacheRange(0x80000000,2*(PCR->FirstLevelDcacheSize)); // to avoid data_coherency_exception
|
||
// HalSweepIcacheRange(0x80000000,2*(PCR->FirstLevelIcacheSize)); // to avoid data_coherency_exception
|
||
if (HalpProcessorId == MPAGENT)
|
||
HalpMultiPciEccCorrector(ErrAddr,ErrAddr >> PAGE_SHIFT,4);
|
||
else
|
||
HalpPciEccCorrector(ErrAddr,ErrAddr >> PAGE_SHIFT,4);
|
||
// HalSweepDcacheRange(0x80000000,2*(PCR->FirstLevelDcacheSize)); // to avoid data_coherency_exception
|
||
// HalSweepIcacheRange(0x80000000,2*(PCR->FirstLevelIcacheSize)); // to avoid data_coherency_exception
|
||
|
||
WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER, irqsel); // restore routage ECC
|
||
|
||
if (ErrAddr == READ_REGISTER_ULONG(PCI_ERRADDR_REGISTER)) {
|
||
Syndrome = READ_REGISTER_ULONG(PCI_SYNDROME_REGISTER);
|
||
ErrStatus = READ_REGISTER_ULONG(PCI_ERRSTATUS_REGISTER);
|
||
KeStallExecutionProcessor(100);
|
||
}
|
||
|
||
// We use SNI_PRIVATE_VECTOR to transmit parameters to the RM300 equivalent DCU' driver
|
||
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved=0;
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis=FLAG_ECC_ERROR;
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorSimmNum=HalpComputeNum((UCHAR *)ErrAddr);
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorAddress=ErrAddr;
|
||
|
||
// Call the 'RM300 equivalent DCU' driver to log the ECC error in event viewer
|
||
|
||
result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
|
||
PCR->InterruptRoutine[DCU_VECTOR]
|
||
));
|
||
++HalpSingleEccCounter;
|
||
if (HalpSingleEccCounter > 0xffff) {
|
||
#if DBG
|
||
HalpSingleEccCounter = 0;
|
||
DebugPrint(("Memory Read Error Counter Overflow\n"));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 2;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "ECC SINGLE ERROR COUNTER OVERFLOW\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
|
||
#endif
|
||
}
|
||
|
||
} else {
|
||
|
||
#if DBG
|
||
// UNIX => PANIC
|
||
DebugPrint(("pci_ecc_error : errstatus=0x%x Add error=0x%x syndrome=0x%x \n",
|
||
ErrStatus,ErrAddr,Syndrome));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 3;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "UNCORRECTABLE ECC ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
|
||
#endif
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
if ( Itpend & PCI_ASIC_IOTIMEOUT ) {
|
||
|
||
ULONG ioadtimeout2, iomemconf;
|
||
|
||
ioadtimeout2 = READ_REGISTER_ULONG(PCI_IOADTIMEOUT2_REGISTER);
|
||
iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
|
||
WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
|
||
(iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT)));
|
||
// reenable timeout
|
||
WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
|
||
#if DBG
|
||
DebugPrint(("pci_timeout_error : adresse=0x%x \n",ioadtimeout2));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 4;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI TIMEOUT ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ioadtimeout2,0,0);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
//
|
||
// Pb NMI because of cirrus chip which generates a parity which is understood by the ASIC
|
||
// like an error and transmit as an NMI EISA.
|
||
//
|
||
|
||
if (MaStatus & PCI_MSR_NMI) {
|
||
|
||
UCHAR DataByte;
|
||
|
||
DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus);
|
||
|
||
if (((PNMI_STATUS) &DataByte)->ParityNmi == 1) {
|
||
|
||
DebugPrint(("Parity error from system memory\n"));
|
||
|
||
// reset NMI interrupt
|
||
((PNMI_STATUS) &DataByte)->DisableEisaParity = 1;
|
||
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
|
||
|
||
((PNMI_STATUS) &DataByte)->DisableEisaParity = 0;
|
||
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
|
||
}
|
||
|
||
DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
|
||
|
||
if (((PNMI_EXTENDED_CONTROL) &DataByte)->PendingBusMasterTimeout == 1) {
|
||
|
||
DebugPrint(("EISA Bus Master timeout\n"));
|
||
|
||
// reset NMI interrupt
|
||
|
||
((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 0;
|
||
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
|
||
|
||
((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 1;
|
||
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// look for an PushButton Interrupt and simply dismiss it
|
||
//
|
||
|
||
if ( MaStatus & PCI_MSR_PB_MASK){
|
||
DebugPrint(("Interrupt - PushButton\n"));
|
||
WRITE_REGISTER_ULONG( PCI_CSRSTBP_ADDR ,0x0); // reset debug intr
|
||
#if DBG
|
||
DbgBreakPoint();
|
||
#endif
|
||
KeStallExecutionProcessor(500000); // sleep 0.5 sec
|
||
}
|
||
|
||
//
|
||
// look for an OverTemperature Interrupt and simply dismiss it
|
||
//
|
||
|
||
if ( MaStatus & PCI_MSR_TEMP_MASK){
|
||
|
||
DebugPrint(("Interrupt - Temperature\n"));
|
||
|
||
// we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
|
||
// the 'RM300 equivalent DCU' driver
|
||
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= MaStatus;
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //no ECC error
|
||
result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
|
||
PCR->InterruptRoutine[DCU_VECTOR]
|
||
));
|
||
|
||
// if DCU driver not installed, Reset interrupt + auto-rearm
|
||
|
||
READ_REGISTER_ULONG( PCI_CLR_TMP_ADDR);
|
||
|
||
}
|
||
|
||
//
|
||
// look for an power off
|
||
//
|
||
|
||
if ( MaStatus & PCI_MSR_POFF_MASK){
|
||
|
||
// we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
|
||
// the 'RM300 equivalent DCU' driver
|
||
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= MaStatus;
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
|
||
result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
|
||
PCR->InterruptRoutine[DCU_VECTOR]
|
||
));
|
||
|
||
// if DCU driver not installed, Reset interrupt + auto-rearm
|
||
|
||
WRITE_REGISTER_ULONG( PCI_CLRPOFF_ADDR,0);
|
||
}
|
||
|
||
//
|
||
// look for an power management
|
||
//
|
||
|
||
if ( MaStatus & PCI_MSR_PMGNT_MASK){
|
||
|
||
// we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
|
||
// the 'RM300 equivalent DCU' driver
|
||
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= MaStatus;
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
|
||
result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
|
||
PCR->InterruptRoutine[DCU_VECTOR]
|
||
));
|
||
|
||
// if DCU driver not installed, Reset interrupt + auto-rearm
|
||
|
||
WRITE_REGISTER_ULONG( PCI_PWDN_ADDR,0); // power down
|
||
}
|
||
}
|
||
|
||
HalpCheckSpuriousInt(0x00);
|
||
return (TRUE); // perhaps one of the interrupts was pending :-)
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
HalpPciTowerInt0Dispatch (
|
||
IN PKINTERRUPT Interrupt,
|
||
IN PVOID ServiceContext
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
This routine handles the central INT0 Interrupt on an SNI PCI tower
|
||
To decide which interrupt, read the Interrupt Source Register
|
||
|
||
We have to manage priorities by software.
|
||
|
||
Arguments:
|
||
|
||
Interrupt - Supplies a pointer to the interrupt object.
|
||
|
||
ServiceContext - Supplies a pointer to the Interrupt
|
||
Source register.
|
||
|
||
|
||
Return Value:
|
||
|
||
A BOOLEAN value, TRUE if the interrupt is OK,
|
||
otherwise FALSE for unknown interrupts
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG IntSource;
|
||
BOOLEAN SCSIresult, result;
|
||
|
||
if (HalpCheckSpuriousInt(0x400)) return(FALSE);
|
||
|
||
IntSource = READ_REGISTER_ULONG(ServiceContext);
|
||
|
||
|
||
|
||
if ( IntSource & PCI_TOWER_EISA_MASK) { // EISA Interrupt
|
||
if (HalpESC_SB)
|
||
result = HalpPciEisaSBDispatch( NULL, // InterruptObject (unused)
|
||
(PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
|
||
);
|
||
else
|
||
result = HalpPciEisaDispatch( NULL, // InterruptObject (unused)
|
||
(PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
|
||
);
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(result);
|
||
}
|
||
|
||
//
|
||
// look for SCSI Interrupts
|
||
//
|
||
|
||
if ( IntSource & PCI_TOWER_SCSI1_MASK){
|
||
|
||
|
||
|
||
SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI1_VECTOR])(
|
||
PCR->InterruptRoutine[SCSI1_VECTOR]
|
||
);
|
||
#if DBG
|
||
if(!SCSIresult) DebugPrint(("Got an invalid SCSI 1 interrupt !\n"));
|
||
#endif
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(SCSIresult);
|
||
|
||
}
|
||
if ( IntSource & PCI_TOWER_SCSI2_MASK){
|
||
SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI2_VECTOR])(
|
||
PCR->InterruptRoutine[SCSI2_VECTOR]
|
||
);
|
||
#if DBG
|
||
if(!SCSIresult) DebugPrint(("Got an invalid SCSI 2 interrupt !\n"));
|
||
#endif
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(SCSIresult);
|
||
|
||
}
|
||
//
|
||
// PCI interrupts
|
||
//
|
||
|
||
if ( IntSource & PCI_TOWER_INTA_MASK){
|
||
int i;
|
||
for (i=INTA_VECTOR;i<HalpIntAMax;++i)
|
||
((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
|
||
PCR->InterruptRoutine[i]
|
||
);
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(TRUE);
|
||
}
|
||
|
||
if ( IntSource & PCI_TOWER_INTB_MASK){
|
||
int i;
|
||
for (i=INTB_VECTOR;i<HalpIntBMax;++i)
|
||
((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
|
||
PCR->InterruptRoutine[i]
|
||
);
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(TRUE);
|
||
}
|
||
|
||
if ( IntSource & PCI_TOWER_INTC_MASK){
|
||
int i;
|
||
for (i=INTC_VECTOR;i<HalpIntCMax;++i)
|
||
((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
|
||
PCR->InterruptRoutine[i]
|
||
);
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(TRUE);
|
||
}
|
||
|
||
if ( IntSource & PCI_TOWER_INTD_MASK){
|
||
int i;
|
||
for (i=INTD_VECTOR;i<HalpIntDMax;++i)
|
||
((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
|
||
PCR->InterruptRoutine[i]
|
||
);
|
||
HalpCheckSpuriousInt(0x00);
|
||
return(TRUE);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
HalpCheckSpuriousInt(0x00);
|
||
return (TRUE); // perhaps one of the interrupts was pending :-)
|
||
}
|
||
|
||
|
||
|
||
BOOLEAN
|
||
HalpPciTowerInt3Dispatch (
|
||
IN PKINTERRUPT Interrupt,
|
||
IN PVOID ServiceContext
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
This routine handles the MAUI-INT4 Interrupt on an SNI PCI tower :
|
||
- DCU interrupt (extra_timer,...)
|
||
- MPBus error
|
||
- Memory error
|
||
- PCI error
|
||
|
||
To decide which interrupt, read the Interrupt Source Register
|
||
|
||
We have to manage priorities by software.
|
||
|
||
Arguments:
|
||
|
||
Interrupt - Supplies a pointer to the interrupt object.
|
||
|
||
ServiceContext - Supplies a pointer to the Interrupt
|
||
Source register.
|
||
|
||
|
||
Return Value:
|
||
|
||
A BOOLEAN value, TRUE if the interrupt is OK,
|
||
otherwise FALSE for unknown interrupts
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG IntSource;
|
||
ULONG mem_addr,status;
|
||
ULONG status0,status1;
|
||
BOOLEAN result;
|
||
|
||
|
||
if (HalpCheckSpuriousInt(0x2000)) return(FALSE);
|
||
|
||
|
||
IntSource = READ_REGISTER_ULONG(ServiceContext);
|
||
|
||
|
||
//
|
||
// look if a DCU_INDICATE interrupt occured
|
||
//
|
||
//
|
||
|
||
if (IntSource & PCI_TOWER_D_INDICATE_MASK){
|
||
|
||
|
||
status = READ_REGISTER_ULONG(PCI_TOWER_INDICATE);
|
||
|
||
//
|
||
// look if extra timer interrupt
|
||
//
|
||
|
||
if (status & PCI_TOWER_DI_EXTRA_TIMER){
|
||
|
||
HalpClockInterruptPciTower();
|
||
return(TRUE);
|
||
}
|
||
|
||
DebugPrint(("DCU_INDICATE interrupt\n"));
|
||
//
|
||
// look for an PushButton Interrupt and simply dismiss it
|
||
//
|
||
|
||
|
||
if ( status & PCI_TOWER_DI_PB_MASK){
|
||
|
||
DebugPrint(("Interrupt - PushButton\n"));
|
||
|
||
#if DBG
|
||
DbgBreakPoint();
|
||
#endif
|
||
KeStallExecutionProcessor(500000); // sleep 0.5 sec
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
|
||
//The reading of DCU_INDICATE register clears the interrupt sources
|
||
// --> we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
|
||
// the DCU driver
|
||
result = TRUE;
|
||
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= status;
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
|
||
result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
|
||
PCR->InterruptRoutine[DCU_VECTOR]
|
||
));
|
||
|
||
// if DCU driver not installed, reset EISA_NMI interrupt if necessary
|
||
|
||
if (status & PCI_TOWER_DI_EISA_NMI)
|
||
{
|
||
UCHAR DataByte;
|
||
|
||
DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus);
|
||
|
||
|
||
if (((PNMI_STATUS) &DataByte)->ParityNmi == 1)
|
||
{
|
||
DebugPrint(("Parity error from system memory\n"));
|
||
|
||
//reset NMI interrupt //
|
||
|
||
((PNMI_STATUS) &DataByte)->DisableEisaParity = 1;
|
||
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
|
||
|
||
((PNMI_STATUS) &DataByte)->DisableEisaParity = 0;
|
||
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
|
||
}
|
||
|
||
|
||
DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
|
||
|
||
if (((PNMI_EXTENDED_CONTROL) &DataByte)->PendingBusMasterTimeout == 1)
|
||
{
|
||
DebugPrint(("EISA Bus Master timeout\n"));
|
||
|
||
//reset NMI interrupt //
|
||
|
||
((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 0;
|
||
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
|
||
|
||
((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 1;
|
||
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
|
||
}
|
||
}
|
||
|
||
return (result);
|
||
}
|
||
|
||
//
|
||
// look if a DCU_ERROR interrupt occured
|
||
//
|
||
//
|
||
|
||
if (IntSource & PCI_TOWER_D_ERROR_MASK){
|
||
|
||
status = 0;
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= 0;
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
|
||
result =(((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
|
||
PCR->InterruptRoutine[DCU_VECTOR]
|
||
));
|
||
// read DCU_ERROR register to clear interrupt source if DCU driver not installed
|
||
READ_REGISTER_ULONG(PCI_TOWER_DCU_ERROR);
|
||
return (result);
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// look if MP_BUS error
|
||
//
|
||
|
||
|
||
if (IntSource & PCI_TOWER_MP_BUS_MASK){
|
||
|
||
|
||
status = READ_REGISTER_ULONG(PCI_TOWER_MP_BUS_ERROR_STATUS);
|
||
mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MP_BUS_ERROR_ADDR);
|
||
|
||
// Clear MP_Bus interrupt
|
||
|
||
WRITE_REGISTER_ULONG (ServiceContext,IntSource);
|
||
|
||
|
||
if (IntSource & PCI_TOWER_C_PARITY_MASK){
|
||
|
||
#if DBG
|
||
DebugPrint(("MP_Bus Parity Error : MPBusErrorStatus = 0x%x MPBusErrorAddress = 0x%x \n",
|
||
status,mem_addr));
|
||
//DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 5;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MP_BUS PARITY ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
|
||
#endif
|
||
}
|
||
|
||
if (IntSource & PCI_TOWER_C_REGSIZE){
|
||
#if DBG
|
||
DebugPrint(("MP_Bus Register Size Error : MPBusErrorStatus = 0x%x \n",
|
||
status));
|
||
DbgBreakPoint();
|
||
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 6;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MP_BUS REGISTER SIZE ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,0,0);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
//
|
||
// look if Memory error
|
||
//
|
||
if (IntSource & PCI_TOWER_M_ECC_MASK){
|
||
|
||
|
||
mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MEM_ERROR_ADDR)& MEM_ADDR_MASK;
|
||
|
||
// correct ECC error
|
||
HalpMultiPciEccCorrector(mem_addr ,mem_addr >> PAGE_SHIFT,4);
|
||
|
||
IntSource = READ_REGISTER_ULONG(PCI_TOWER_GEN_INTERRUPT);
|
||
if (IntSource & PCI_TOWER_M_ECC_MASK){
|
||
|
||
mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MEM_ERROR_ADDR)& MEM_ADDR_MASK;
|
||
KeStallExecutionProcessor(100);
|
||
}
|
||
// We use SNI_PRIVATE_VECTOR to transmit parameters to DCU driver
|
||
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved=0;
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis=FLAG_ECC_ERROR;
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorSimmNum=HalpComputeNum((UCHAR *)mem_addr);
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorAddress= mem_addr ;
|
||
|
||
// Call the 'DCU' driver to log the ECC error in event viewer
|
||
|
||
result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
|
||
PCR->InterruptRoutine[DCU_VECTOR]
|
||
));
|
||
|
||
|
||
}
|
||
|
||
if (IntSource & PCI_TOWER_M_ADDR_MASK){
|
||
|
||
mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MEM_ERROR_ADDR);
|
||
#if DBG
|
||
DebugPrint(("Memory Address Error : MemErrorAddr = 0x%x \n",mem_addr));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 7;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MEMORY ADDRESS ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,mem_addr,0,0);
|
||
#endif
|
||
}
|
||
|
||
if (IntSource & PCI_TOWER_M_SLT_MASK){
|
||
|
||
ULONG MemControl2,MemConf;
|
||
|
||
MemControl2 = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_2);
|
||
MemConf = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONFIG);
|
||
#if DBG
|
||
DebugPrint(("Memory slot Error : MemControl2 = 0x%x, MemConf = 0x%x \n",MemControl2,MemConf));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 8;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MEMORY SLOT ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,MemControl2,MemConf,0);
|
||
#endif
|
||
}
|
||
|
||
if (IntSource & PCI_TOWER_M_CFG_MASK){
|
||
|
||
ULONG MemControl2,MemConf;
|
||
|
||
MemControl2 = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_2);
|
||
MemConf = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONFIG);
|
||
#if DBG
|
||
DebugPrint(("Memory Config Error : MemControl2 = 0x%x, MemConf = 0x%x \n",MemControl2,MemConf));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 9;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MEMORY CONFIG ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,MemControl2,MemConf,0);
|
||
#endif
|
||
}
|
||
|
||
|
||
if (IntSource & PCI_TOWER_M_RC_MASK){
|
||
|
||
// reset error counter
|
||
WRITE_REGISTER_ULONG (PCI_TOWER_MEM_CONTROL_1, (READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_1) & ERROR_COUNTER_MASK) | ERROR_COUNTER_INITVALUE);
|
||
|
||
#if DBG
|
||
DebugPrint(("Memory Read Error Counter Overflow\n"));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 2;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "ECC SINGLE ERROR COUNTER OVERFLOW\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,0,0,0);
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// look if PCI interrupt
|
||
//
|
||
if (IntSource & PCI_TOWER_P_ERROR_MASK){
|
||
ULONG PciDataInt,PciData;
|
||
|
||
DebugPrint(("PCI interrupt \n"));
|
||
|
||
|
||
PciDataInt = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
|
||
|
||
status = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
|
||
|
||
|
||
// First Initiator interrupt
|
||
|
||
if (status & PI_INITF){
|
||
|
||
PciData = PCI_TOWER_INITIATOR_ADDR_OFFSET | 0x80000000;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
|
||
|
||
mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
|
||
|
||
// Reset interrupt with write-1-to-clear bit Initiator_Interrupts
|
||
status0 = PI_INITF;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
|
||
WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
|
||
|
||
if (status & PI_REC_TARGET_RETRY)
|
||
HalpTargetRetryCnt++;
|
||
else {
|
||
|
||
#if DBG
|
||
DebugPrint(("PCI Iniatiator interrupt error : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
|
||
mem_addr,status));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 10;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI INITIATOR INTERRUPT ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
// First Target interrupt
|
||
|
||
if (status & PI_TARGF){
|
||
PciData = PCI_TOWER_TARGET_ADDR_OFFSET | 0x80000000;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
|
||
|
||
mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
|
||
|
||
// Reset interrupt with write-1-to-clear bit Target_Interrupts
|
||
status0 = PI_TARGF;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
|
||
WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
|
||
|
||
|
||
#if DBG
|
||
DebugPrint(("PCI Target interrupt error : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
|
||
mem_addr,status));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 11;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI TARGET INTERRUPT ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
|
||
#endif
|
||
|
||
}
|
||
|
||
// First parity error
|
||
|
||
if (status & PI_PARF){
|
||
|
||
// Reset interrupt with write-1-to-clear bit Parity_Interrupts
|
||
status0 = PI_PARF;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
|
||
WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
|
||
|
||
PciData = PCI_TOWER_PAR_0_OFFSET | 0x80000000;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
|
||
|
||
status0 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
|
||
|
||
PciData = PCI_TOWER_PAR_1_OFFSET | 0x80000000;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
|
||
|
||
status1 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
|
||
|
||
#if DBG
|
||
DebugPrint(("PCI Parity interrupt error : Parity_0 register = 0x%x , Parity_1 register = 0x%x\n",
|
||
status0,status1));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 12;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI PARITY INTERRUPT ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status0,status1,0);
|
||
#endif
|
||
|
||
}
|
||
|
||
|
||
// Multiple Initiator interrupts
|
||
|
||
if (status & PI_INITM){
|
||
|
||
PciData = PCI_TOWER_TARGET_ADDR_OFFSET | 0x80000000;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
|
||
|
||
mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
|
||
// Reset interrupt with write-1-to-clear bit Multiple Initiator_Interrupts
|
||
status0 = PI_INITM;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
|
||
WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
|
||
|
||
|
||
|
||
if (!(status & PI_REC_TARGET_RETRY)) {
|
||
#if DBG
|
||
DebugPrint(("Multiple PCI Iniatiator interrupt : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
|
||
mem_addr,status));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 13;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MULTIPLE PCI INITIATOR ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
// Multiple Target interrupts
|
||
|
||
if (status & PI_TARGM){
|
||
|
||
PciData = PCI_TOWER_TARGET_ADDR_OFFSET | 0x80000000;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
|
||
|
||
mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
|
||
|
||
// Reset interrupt with write-1-to-clear bit Multiple Target_interrupts
|
||
status0 = PI_TARGM;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
|
||
WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
|
||
|
||
|
||
|
||
#if DBG
|
||
DebugPrint(("Multiple PCI Target interrupt : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
|
||
mem_addr,status));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 14;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MULTIPLE PCI TARGET ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
|
||
#endif
|
||
|
||
}
|
||
|
||
// Multiple Parity interrupts
|
||
|
||
if (status & PI_PARM){
|
||
|
||
// Reset interrupt with write-1-to-clear bit Multiple Parity_Interrupts
|
||
status0 = PI_PARM;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
|
||
WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
|
||
|
||
PciData = PCI_TOWER_PAR_0_OFFSET | 0x80000000;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
|
||
|
||
status0 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
|
||
|
||
PciData = PCI_TOWER_PAR_1_OFFSET | 0x80000000;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
|
||
|
||
status1 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
|
||
|
||
|
||
#if DBG
|
||
DebugPrint(("Multiple PCI Parity interrupt : Parity_0 register = 0x%x , Parity_1 register = 0x%x\n",
|
||
status0,status1));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 15;
|
||
HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MULTIPLE PCI PARITY ERROR\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status0,status1,0);
|
||
#endif
|
||
|
||
}
|
||
//reenable PCI interrupt
|
||
status &= MASK_INT;
|
||
WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
|
||
WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status));
|
||
|
||
}
|
||
HalpCheckSpuriousInt(0x00);
|
||
return (TRUE); // perhaps one of the interrupts was pending :-)
|
||
}
|
||
|
||
|
||
|
||
|