//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxerror.c,v 1.3 1996/05/15 08:13:24 pierre Exp $") /*-- Copyright (c) 1991 Microsoft Corporation Module Name: xxerror.c Abstract: This module implements the management of errors (KeBugCheckEx, HalpBusError) Environment: Kernel mode only. --*/ #include "halp.h" #include "string.h" // // Messages for CacheError routine // UCHAR HalpErrCacheMsg[] = "\nCACHE ERROR\n"; UCHAR HalpParityErrMsg[] = "\nPARITY ERROR\n"; UCHAR HalpAddrErrMsg[] = "Address in error not found\n"; ULONG HalpCacheErrFirst = 0; ULONG HalpKeBugCheck0; ULONG HalpKeBugCheck1; ULONG HalpKeBugCheck2; ULONG HalpKeBugCheck3; ULONG HalpKeBugCheck4; VOID HalpBugCheckCallback ( IN PVOID Buffer, IN ULONG Length ); // // Define bug check information buffer and callback record. // HALP_BUGCHECK_BUFFER HalpBugCheckBuffer; KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord; UCHAR HalpComponentId[] = "hal.dll"; // // Define BugCheck Number and BugCheck Additional Message // ULONG HalpBugCheckNumber = (ULONG)(-1); PUCHAR HalpBugCheckMessage[] = { "MP_Agent fatal error\n", // #0 "ASIC PCI TRANSFER ERROR\n", // #1 "ECC SINGLE ERROR COUNTER OVERFLOW\n", // #2 "UNCORRECTABLE ECC ERROR\n", // #3 "PCI TIMEOUT ERROR\n", // #4 "MP_BUS PARITY ERROR\n", // #5 "MP_BUS REGISTER SIZE ERROR\n", // #6 "MEMORY ADDRESS ERROR\n", // #7 "MEMORY SLOT ERROR\n", // #8 "MEMORY CONFIG ERROR\n", // #9 "PCI INITIATOR INTERRUPT ERROR\n", // #10 "PCI TARGET INTERRUPT ERROR\n", // #11 "PCI PARITY INTERRUPT ERROR\n", // #12 "MULTIPLE PCI INITIATOR ERROR\n", // #13 "MULTIPLE PCI TARGET ERROR\n", // #14 "MULTIPLE PCI PARITY ERROR\n", // #15 "DATA_BUS_ERROR\n", // #16 "INSTRUCTION_BUS_ERROR\n", // #17 "PARITY ERROR\n", // #18 "CACHE ERROR\n" // #19 }; VOID HalpBugCheckCallback ( IN PVOID Buffer, IN ULONG Length ) /*++ Routine Description: This function is called when a bug check occurs. Its function is to dump the state of the memory error registers into a bug check buffer. Arguments: Buffer - Supplies a pointer to the bug check buffer. Length - Supplies the length of the bug check buffer in bytes. Return Value: None. --*/ { PHALP_BUGCHECK_BUFFER DumpBuffer; PUCHAR p,q; if (HalpBugCheckNumber == -1) return; // that is not a HAL bugcheck ... // // Capture the failed memory address and diagnostic registers. // DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer; DumpBuffer->Par0 = HalpKeBugCheck0; DumpBuffer->Par1 = HalpKeBugCheck1; DumpBuffer->Par2 = HalpKeBugCheck2; DumpBuffer->Par3 = HalpKeBugCheck3; DumpBuffer->Par4 = HalpKeBugCheck4; DumpBuffer->MainBoard = HalpMainBoard; p = DumpBuffer->TEXT;q = HalpBugCheckMessage[HalpBugCheckNumber]; while (*q) *p++ = *q++; return; } BOOLEAN HalpBusError ( IN PEXCEPTION_RECORD ExceptionRecord, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame, IN PVOID VirtualAddress, IN PHYSICAL_ADDRESS PhysicalAddress ) /*++ Routine Description: This function provides the default bus error handling routine for NT. N.B. There is no return from this routine. Arguments: ExceptionRecord - Supplies a pointer to an exception record. ExceptionFrame - Supplies a pointer to an exception frame. TrapFrame - Supplies a pointer to a trap frame. VirtualAddress - Supplies the virtual address of the bus error. PhysicalAddress - Supplies the physical address of the bus error. Return Value: None. --*/ { KIRQL OldIrql; UCHAR IntSource; UCHAR MaStatus; ULONG Itpend; KeRaiseIrql(HIGH_LEVEL, &OldIrql); KiAcquireSpinLock(&HalpInterruptLock); if (HalpIsTowerPci){ // stop the extra-timer WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_CMD_REG,0); HalpPciTowerInt3Dispatch(&HalpInt3Interrupt,(PVOID)PCI_TOWER_INTERRUPT_SOURCE_REGISTER); }else{ IntSource = READ_REGISTER_UCHAR(PCI_INTERRUPT_SOURCE_REGISTER); 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_INT2_MASK) { MaStatus = READ_REGISTER_UCHAR(PCI_MSR_ADDR); if (HalpMainBoard == DesktopPCI) { MaStatus ^= PCI_MSR_MASK_D; } else { MaStatus ^= PCI_MSR_MASK_MT; }//(HalpMainBoard == DesktopPCI) // // 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 AsicErrAddr, ErrAddr, Syndrome, ErrStatus; ErrAddr = READ_REGISTER_ULONG(PCI_ERRADDR_REGISTER); Syndrome = READ_REGISTER_ULONG(PCI_SYNDROME_REGISTER); ErrStatus = READ_REGISTER_ULONG(PCI_ERRSTATUS_REGISTER); if (ErrStatus & PCI_MEMSTAT_PARERR) { // Parity error (PCI_ASIC <-> CPU) #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_PARERR) if (ErrStatus & PCI_MEMSTAT_ECCERR) { AsicErrAddr &= 0xfffffff8; ErrAddr = HalpFindEccAddr(AsicErrAddr,(PVOID)PCI_ERRSTATUS_REGISTER,(PVOID)PCI_MEMSTAT_ECCERR); if (ErrAddr == -1) ErrAddr = AsicErrAddr; #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 (ErrStatus & PCI_MEMSTAT_ECCERR) } //if ( Itpend & (PCI_ASIC_ECCERROR | PCI_ASIC_TRPERROR)) }//if ( MaStatus & PCI_MSR_ASIC_MASK) }//if ( IntSource & PCI_INT2_MASK) }//if (HalpIsTowerPci) // arrive here if no interruption found HalpDisableInterrupts(); // for the MATROX boards... HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode HalDisplayString("\n"); HalpClearVGADisplay(); if (( ExceptionRecord->ExceptionCode & DATA_BUS_ERROR ) == DATA_BUS_ERROR) { HalpBugCheckNumber = 16; HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "DATA_BUS_ERROR\n" } else { HalpBugCheckNumber = 17; HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "INSTRUCTION_BUS_ERROR\n" } HalpKeBugCheckEx(ExceptionRecord->ExceptionCode , HalpBugCheckNumber, (ULONG)VirtualAddress, (ULONG)PhysicalAddress.LowPart, 0); KiReleaseSpinLock(&HalpInterruptLock); KeLowerIrql(OldIrql); return FALSE; }