summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halsnip/mips/r4intdsp.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halsnip/mips/r4intdsp.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/halsnip/mips/r4intdsp.c')
-rw-r--r--private/ntos/nthals/halsnip/mips/r4intdsp.c1307
1 files changed, 1307 insertions, 0 deletions
diff --git a/private/ntos/nthals/halsnip/mips/r4intdsp.c b/private/ntos/nthals/halsnip/mips/r4intdsp.c
new file mode 100644
index 000000000..08f79fb39
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/r4intdsp.c
@@ -0,0 +1,1307 @@
+//#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 :-)
+}
+
+
+
+