NT4/private/ntos/nthals/halalpha/ciaerr.c
2020-09-30 17:12:29 +02:00

1643 lines
45 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1994 Digital Equipment Corporation
Module Name:
ciaerr.c
Abstract:
This module implements error handling functions for the CIA ASIC.
Author:
Joe Notarangelo 26-Jul-1994
Environment:
Kernel mode
Revision History:
--*/
#include "halp.h"
#include "cia.h"
#include "stdio.h"
//
// Externals and globals.
//
//
// Declare the extern variable UncorrectableError declared in
// inithal.c.
//
extern PERROR_FRAME PUncorrectableError;
extern ULONG HalDisablePCIParityChecking;
ULONG CiaCorrectedErrors = 0;
//
// Define the context structure for use by interrupt service routines.
//
typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
PKINTERRUPT InterruptObject,
PVOID ServiceContext
);
//
// Function prototypes.
//
VOID
HalpSetMachineCheckEnables(
IN BOOLEAN DisableMachineChecks,
IN BOOLEAN DisableProcessorCorrectables,
IN BOOLEAN DisableSystemCorrectables
);
VOID
HalpUpdateMces(
IN BOOLEAN ClearMachineCheck,
IN BOOLEAN ClearCorrectableError
);
//
// Allocate a flag that indicates when a PCI Master Abort is expected.
// PCI Master Aborts are signaled on configuration reads to non-existent
// PCI slots. A non-zero value indicates that a Master Abort is expected.
//
ULONG HalpMasterAbortExpected = 0;
VOID
HalpInitializeCiaMachineChecks(
IN BOOLEAN ReportCorrectableErrors,
IN BOOLEAN PciParityChecking
)
/*++
Routine Description:
This routine initializes machine check handling for a CIA-based
system by clearing all pending errors in the CIA registers and
enabling correctable errors according to the callers specification.
Arguments:
ReportCorrectableErrors - Supplies a boolean value which specifies
if correctable error reporting should be
enabled.
Return Value:
None.
--*/
{
CIA_CONTROL CiaControl;
CIA_ERR CiaError;
CIA_ERR_MASK CiaErrMask;
//
// Clear any pending error bits in the CIA_ERR register:
//
CiaError.all = 0; // Clear all bits
CiaError.CorErr = 1; // Correctable error
CiaError.UnCorErr = 1; // Uncorrectable error
CiaError.CpuPe = 1; // Ev5 bus parity error
CiaError.MemNem = 1; // Nonexistent memory error
CiaError.PciSerr = 1; // PCI bus serr detected
CiaError.PciPerr = 1; // PCI bus perr detected
CiaError.PciAddrPe = 1; // PCI bus address parity error
CiaError.RcvdMasAbt = 1; // Pci Master Abort
CiaError.RcvdTarAbt = 1; // Pci Target Abort
CiaError.PaPteInv = 1; // Invalid Pte
CiaError.FromWrtErr = 1; // Invalid write to flash rom
CiaError.IoaTimeout = 1; // Io Timeout occurred
CiaError.LostCorErr = 1; // Lost correctable error
CiaError.LostUnCorErr = 1; // Lost uncorrectable error
CiaError.LostCpuPe = 1; // Lost Ev5 bus parity error
CiaError.LostMemNem = 1; // Lost Nonexistent memory error
CiaError.LostPciPerr = 1; // Lost PCI bus perr detected
CiaError.LostPciAddrPe = 1; // Lost PCI bus address parity error
CiaError.LostRcvdMasAbt = 1; // Lost Pci Master Abort
CiaError.LostRcvdTarAbt = 1; // Lost Pci Target Abort
CiaError.LostPaPteInv = 1; // Lost Invalid Pte
CiaError.LostFromWrtErr = 1; // Lost Invalid write to flash rom
CiaError.LostIoaTimeout = 1; // Lost Io Timeout occurred
CiaError.ErrValid = 1; // Self explanatory
WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
CiaError.all
);
//
// Set the Mask Bits in the CIA_MASK register:
//
CiaErrMask.all = 0; // Clear all bits
CiaErrMask.UnCorErr = 1; // Enable Uncorrectable error
CiaErrMask.CpuPe = 1; // Enable Ev5 bus parity error
CiaErrMask.MemNem = 1; // Enable Nonexistent memory error
CiaErrMask.PciSerr = 1; // Enable PCI bus serr detected
CiaErrMask.RcvdMasAbt = 1; // Enable Pci Master Abort
CiaErrMask.RcvdTarAbt = 1; // Enable Pci Target Abort
CiaErrMask.PaPteInv = 1; // Enable Invalid Pte
CiaErrMask.FromWrtErr = 1; // Enable Invalid write to flash rom
CiaErrMask.IoaTimeout = 1; // Enable Io Timeout occurred
//
// Determine PCI parity checking.
//
CiaControl.all = READ_CIA_REGISTER(
&((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl );
if (PciParityChecking == FALSE) {
CiaControl.AddrPeEn = 0; // Disable PCI address parity checking
CiaControl.PerrEn = 0; // Disable PCI data parity checking
CiaErrMask.PciPerr = 0; // Disable PCI bus perr detected
CiaErrMask.PciAddrPe = 0; // Disable PCI bus address parity error
} else {
CiaControl.AddrPeEn = PciParityChecking;
CiaControl.PerrEn = PciParityChecking;
CiaErrMask.PciPerr = PciParityChecking;
CiaErrMask.PciAddrPe = PciParityChecking;
}
CiaErrMask.CorErr = (ReportCorrectableErrors == TRUE);
WRITE_CIA_REGISTER( &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl,
CiaControl.all
);
WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask,
CiaErrMask.all
);
//
// Set the machine check enables within the EV5.
//
if( ReportCorrectableErrors == TRUE ){
HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
} else {
HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
}
return;
}
#define MAX_ERROR_STRING 128
BOOLEAN
HalpCiaUncorrectableError(
VOID
)
/*++
Routine Description:
Read the CIA error register and determine if an uncorrectable error
is latched in the error bits.
Arguments:
None.
Return Value:
TRUE is returned if an uncorrectable error has been detected. FALSE
is returned otherwise.
--*/
{
CIA_ERR CiaError;
CiaError.all = READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr );
//
// If no error is valid then an uncorrectable error was not detected.
//
if( CiaError.ErrValid == 0 ){
return FALSE;
}
//
// Check each of the individual uncorrectable error bits, if any is set
// then return TRUE.
//
if( (CiaError.UnCorErr == 1) ||
(CiaError.CpuPe == 1) ||
(CiaError.MemNem == 1) ||
(CiaError.PciSerr == 1) ||
(CiaError.PciPerr == 1) ||
(CiaError.PciAddrPe == 1) ||
(CiaError.RcvdMasAbt == 1) ||
(CiaError.RcvdTarAbt == 1) ||
(CiaError.PaPteInv == 1) ||
(CiaError.FromWrtErr == 1) ||
(CiaError.IoaTimeout == 1) ){
return TRUE;
}
//
// None of the uncorrectable error conditions were detected.
//
return FALSE;
}
VOID
HalpBuildCiaConfigurationFrame(
PCIA_CONFIGURATION pConfiguration
)
{
pConfiguration->CiaRev = READ_CIA_REGISTER(
&((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaRevision );
pConfiguration->CiaCtrl = READ_CIA_REGISTER(
&((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl );
pConfiguration->Mcr = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mcr );
pConfiguration->Mba0 = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba0 );
pConfiguration->Mba2 = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba2 );
pConfiguration->Mba4 = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba4 );
pConfiguration->Mba6 = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba6 );
pConfiguration->Mba8 = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba8 );
pConfiguration->MbaA = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaA );
pConfiguration->MbaC = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaC );
pConfiguration->MbaE = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaE );
pConfiguration->Tmg0 = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg0 );
pConfiguration->Tmg1 = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg1 );
pConfiguration->Tmg2 = READ_CIA_REGISTER(
&((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg2 );
}
VOID
HalpCiaReportFatalError(
VOID
)
/*++
Routine Description:
This function reports and interprets a fatal hardware error
detected by the CIA chipset. It is assumed that HalGetDisplayOwnership()
has been called prior to this function.
Arguments:
None.
Return Value:
None.
--*/
{
UCHAR OutBuffer[ MAX_ERROR_STRING ];
CIA_ERR CiaError;
CIA_STAT CiaStat;
CIA_SYN CiaSyn;
CIA_CONTROL CiaControl;
CIA_MEM_ERR0 MemErr0;
CIA_MEM_ERR1 MemErr1;
CIA_PCI_ERR0 PciErr0;
CIA_PCI_ERR1 PciErr1;
CIA_PCI_ERR2 PciErr2;
CIA_CPU_ERR0 CpuErr0;
CIA_CPU_ERR1 CpuErr1;
PUNCORRECTABLE_ERROR uncorr = NULL;
PCIA_UNCORRECTABLE_FRAME ciauncorr = NULL;
PEXTENDED_ERROR PExtErr;
//
// We will Build the uncorrectable error frame as we read
// the registers to report the error to the blue screen.
// We generate the extended error frame as we generate
// extended messages to print to the screen.
//
if(PUncorrectableError){
uncorr = (PUNCORRECTABLE_ERROR)
&PUncorrectableError->UncorrectableFrame;
ciauncorr = (PCIA_UNCORRECTABLE_FRAME)
PUncorrectableError->UncorrectableFrame.RawSystemInformation;
PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
}
if(uncorr){
uncorr->Flags.ProcessorInformationValid = 1;
HalpGetProcessorInfo(&uncorr->ReportingProcessor);
}
if(ciauncorr)
HalpBuildCiaConfigurationFrame(&ciauncorr->Configuration);
//
// Read the CIA Error register and decode its contents:
//
CiaError.all = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr
);
if(ciauncorr)
ciauncorr->CiaErr = CiaError.all ;
//
// Read the rest of the error registers and then unlock them by
// writing to CIA_ERR
//
CiaStat.all = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaStat
);
CiaSyn.all = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaSyn
);
MemErr0.all = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr0
);
MemErr1.all = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr1
);
PciErr0.all = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr0
);
PciErr1.PciAddress = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr1
);
PciErr2.PciAddress = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2
);
CpuErr0.all = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr0
);
CpuErr1.all = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr1
);
CiaControl.all = READ_CIA_REGISTER(
&((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl);
if(ciauncorr){
ciauncorr->CiaStat = CiaStat.all;
ciauncorr->CiaSyn = CiaSyn.all;
ciauncorr->MemErr0 = MemErr0.all;
ciauncorr->MemErr1 = MemErr1.all;
ciauncorr->PciErr0 = PciErr0.all;
ciauncorr->PciErr1 = PciErr1.PciAddress;
ciauncorr->PciErr2 = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2
);
ciauncorr->CpuErr0 = CpuErr0.all;
ciauncorr->CpuErr1 = CpuErr1.all;
ciauncorr->ErrMask = (ULONG)READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask
);
}
WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
CiaError.all
);
sprintf( OutBuffer, "CIA_CTRL : %08x\n", CiaControl.all );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
sprintf( OutBuffer, "CIA_ERR : %08x\n", CiaError.all );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
sprintf( OutBuffer, "CIA_STAT : %08x\n", CiaStat.all );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
sprintf( OutBuffer, "CIA_SYN : %08x\n", CiaSyn.all );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
sprintf( OutBuffer, "PCI_ERR0 : %08x\n", PciErr0.all );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
sprintf( OutBuffer, "PCI_ERR1 : %08x\n", PciErr1.PciAddress );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
sprintf( OutBuffer, "PCI_ERR2 : %08x\n", PciErr2.PciAddress );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
sprintf( OutBuffer, "CPU_ERR0 : %08x\n", CpuErr0.all );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
sprintf( OutBuffer, "CPU_ERR1 : %08x\n", CpuErr1.all );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
sprintf( OutBuffer, "MEM_ERR0 : %08x\n", MemErr0.all );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
sprintf( OutBuffer, "MEM_ERR1 : %08x\n", MemErr1.all );
HalDisplayString( OutBuffer );
DbgPrint( OutBuffer );
//
// If no valid error then no interpretation.
//
if ( CiaError.ErrValid == 0 ){
return; // No CIA error detected
}
//
// Interpret any detected errors:
//
if ( CiaError.UnCorErr == 1 ){
sprintf( OutBuffer,
"CIA Uncorrectable ECC error, Addr=%x%x, Cmd=%x\n",
CpuErr1.Addr34_32, // bits 34:32
CpuErr0.Addr, // bits 31:4
CpuErr1.Cmd
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
}
} else if ( CiaError.CpuPe == 1 ){
sprintf( OutBuffer,
"EV5 bus parity error, Addr=%x%x, Cmd=%x\n",
CpuErr1.Addr34_32, // bits 34:32
CpuErr0.Addr, // bits 31:4
CpuErr1.Cmd
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
}
} else if ( CiaError.MemNem == 1 ){
sprintf( OutBuffer,
"CIA Access to non-existent memory, Source=%s, Addr=%x%x\n",
MemErr1.MemPortSrc == 1 ? "DMA" : "CPU",
MemErr1.MemPortSrc == 1 ? 0 : MemErr1.Addr33_32,
MemErr1.MemPortSrc == 1 ? PciErr1.PciAddress : MemErr0.Addr31_4
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
}
} else if ( CiaError.PciSerr == 1 ){
sprintf( OutBuffer,
"PCI bus SERR detected, Cmd=%x, Window=%d, Addr=%x\n",
PciErr0.Cmd,
PciErr0.Window,
PciErr1.PciAddress
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
uncorr->Flags.AddressSpace = IO_SPACE;
uncorr->Flags.PhysicalAddressValid = 1;
uncorr->PhysicalAddress = PciErr1.PciAddress;
uncorr->Flags.ExtendedErrorValid = 1;
PExtErr->IoError.Interface = PCIBus;
PExtErr->IoError.BusNumber = 0;
PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
}
} else if ( CiaError.PciPerr == 1 ){
sprintf( OutBuffer,
"PCI bus Data Parity error, Cmd=%x, Window=%d, Addr=%x\n",
PciErr0.Cmd,
PciErr0.Window,
PciErr1.PciAddress
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
uncorr->Flags.AddressSpace = IO_SPACE;
uncorr->Flags.PhysicalAddressValid = 1;
uncorr->PhysicalAddress = PciErr1.PciAddress;
uncorr->Flags.ExtendedErrorValid = 1;
PExtErr->IoError.Interface = PCIBus;
PExtErr->IoError.BusNumber = 0;
PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
}
} else if ( CiaError.PciAddrPe == 1 ){
sprintf( OutBuffer,
"Pci bus Address Parity error, Cmd=%x, Window=%x, Addr=%x\n",
PciErr0.Cmd,
PciErr0.Window,
PciErr1.PciAddress
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
uncorr->Flags.AddressSpace = IO_SPACE;
uncorr->Flags.PhysicalAddressValid = 1;
uncorr->PhysicalAddress = PciErr1.PciAddress;
uncorr->Flags.ExtendedErrorValid = 1;
PExtErr->IoError.Interface = PCIBus;
PExtErr->IoError.BusNumber = 0;
PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
}
} else if ( CiaError.RcvdMasAbt == 1 ){
sprintf( OutBuffer,
"PCI Master abort occurred, Cmd=%x, Window=%x, Addr=%x\n",
PciErr0.Cmd,
PciErr0.Window,
PciErr1.PciAddress
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
uncorr->Flags.AddressSpace = IO_SPACE;
uncorr->Flags.PhysicalAddressValid = 1;
uncorr->PhysicalAddress = PciErr1.PciAddress;
uncorr->Flags.ExtendedErrorValid = 1;
PExtErr->IoError.Interface = PCIBus;
PExtErr->IoError.BusNumber = 0;
PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
}
} else if ( CiaError.RcvdTarAbt == 1 ){
sprintf( OutBuffer,
"PCI Target abort occurred, Cmd=%x, Window=%x, Addr=%x\n",
PciErr0.Cmd,
PciErr0.Window,
PciErr1.PciAddress
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
uncorr->Flags.AddressSpace = IO_SPACE;
uncorr->Flags.PhysicalAddressValid = 1;
uncorr->PhysicalAddress = PciErr1.PciAddress;
uncorr->Flags.ExtendedErrorValid = 1;
PExtErr->IoError.Interface = PCIBus;
PExtErr->IoError.BusNumber = 0;
PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
}
} else if ( CiaError.PaPteInv == 1 ){
sprintf( OutBuffer,
"Invalid Scatter/Gather PTE, Cmd=%x, Window=%x, Addr=%x\n",
PciErr0.Cmd,
PciErr0.Window,
PciErr1.PciAddress
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
uncorr->Flags.AddressSpace = IO_SPACE;
uncorr->Flags.PhysicalAddressValid = 1;
uncorr->PhysicalAddress = PciErr1.PciAddress;
uncorr->Flags.ExtendedErrorValid = 1;
PExtErr->IoError.Interface = PCIBus;
PExtErr->IoError.BusNumber = 0;
PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
}
} else if ( CiaError.FromWrtErr == 1 ){
sprintf( OutBuffer,
"Write to Flash ROM with FROM_WRT_EN clear"
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
}
} else if ( CiaError.IoaTimeout == 1){
sprintf( OutBuffer,
"PCI bus I/O timeout occurred, Cmd=%x, Window=%x, Addr=%x\n",
PciErr0.Cmd,
PciErr0.Window,
PciErr1.PciAddress
);
if(uncorr){
uncorr->Flags.ErrorStringValid = 1;
strcpy( uncorr->ErrorString, OutBuffer);
uncorr->Flags.AddressSpace = IO_SPACE;
uncorr->Flags.PhysicalAddressValid = 1;
uncorr->PhysicalAddress = PciErr1.PciAddress;
uncorr->Flags.ExtendedErrorValid = 1;
PExtErr->IoError.Interface = PCIBus;
PExtErr->IoError.BusNumber = 0;
PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress;
}
}
//
// Output the detected error message:
//
HalDisplayString( "\n" );
HalDisplayString( OutBuffer );
#if HALDBG
DbgPrint( OutBuffer );
#endif
//
// Check for lost errors and output message if any occurred:
//
if ( (CiaError.all & CIA_ERR_LOST_MASK) != 0 ){
HalDisplayString("\nCIA Lost errors were detected\n\n");
}
return; // Fatal error detected
}
BOOLEAN
HalpCiaMachineCheck(
IN PEXCEPTION_RECORD ExceptionRecord,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame
)
/*++
Routine Description:
This routine is given control when an hard error is acknowledged
by the CIA chipset. The routine is given the chance to
correct and dismiss the error.
Arguments:
ExceptionRecord - Supplies a pointer to the exception record generated
at the point of the exception.
ExceptionFrame - Supplies a pointer to the exception frame generated
at the point of the exception.
TrapFrame - Supplies a pointer to the trap frame generated
at the point of the exception.
Return Value:
TRUE is returned if the machine check has been handled and dismissed -
indicating that execution can continue. FALSE is return otherwise.
--*/
{
CIA_ERR CiaError;
//
// Read the CIA error register to determine the source of the
// error.
//
CiaError.all = READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr );
#if HALDBG
DbgPrint( "Cia Mchk: 0x%x\n", CiaError.all );
#endif //HALDBG
//
// Check that an error is valid. If it is not this is a pretty
// weird fatal condition.
//
if( CiaError.ErrValid == 0 ){
DbgPrint( "Error reported but error valid = 0, CiaErr = 0x%x\n",
CiaError.all );
goto FatalError;
}
//
// Check for any uncorrectable error other than a master abort
// on a PCI transaction. Any of these other errors indicate a
// fatal condition.
//
if( (CiaError.UnCorErr == 1) || // Uncorrectable error
(CiaError.CpuPe == 1) || // Ev5 bus parity error
(CiaError.MemNem == 1) || // Nonexistent memory error
(CiaError.PciSerr == 1) || // PCI bus serr detected
(CiaError.PciPerr == 1) || // PCI bus perr detected
(CiaError.PciAddrPe == 1) || // PCI bus address parity error
(CiaError.RcvdTarAbt == 1) || // Pci Target Abort
(CiaError.PaPteInv == 1) || // Invalid Pte
(CiaError.FromWrtErr == 1) || // Invalid write to flash rom
(CiaError.IoaTimeout == 1) || // Io Timeout occurred
(CiaError.LostUnCorErr == 1) || // Lost uncorrectable error
(CiaError.LostCpuPe == 1) || // Lost Ev5 bus parity error
(CiaError.LostMemNem == 1) || // Lost Nonexistent memory error
(CiaError.LostPciPerr == 1) || // Lost PCI bus perr detected
(CiaError.LostPciAddrPe == 1) || // Lost PCI address parity error
(CiaError.LostRcvdMasAbt == 1) || // Lost Pci Master Abort
(CiaError.LostRcvdTarAbt == 1) || // Lost Pci Target Abort
(CiaError.LostPaPteInv == 1) || // Lost Invalid Pte
(CiaError.LostFromWrtErr == 1) || // Lost Invalid write to flash rom
(CiaError.LostIoaTimeout == 1) // Lost Io Timeout occurred
){
DbgPrint( "Explicit fatal error, CiaErr = 0x%x\n",
CiaError.all );
goto FatalError;
}
//
// Check for a PCI configuration read error. The CIA experiences
// a master abort on a read to a non-existent PCI slot.
//
if( (CiaError.RcvdMasAbt == 1) && (HalpMasterAbortExpected != 0) ){
//
// So far, the error looks like a PCI configuration space read
// that accessed a device that does not exist. In order to fix
// this up we expect that the original faulting instruction must
// be a load with v0 as the destination register. Unfortunately,
// machine checks are not precise exceptions so we may have exectued
// many instructions since the faulting load. For EV5 a pair of
// memory barrier instructions following the load will stall the pipe
// waiting for load completion before the second memory barrier can
// be issued. Therefore, we expect the exception PC to point to either
// the load instruction of one of the two memory barriers. We will
// assume that if the exception pc is not an mb that instead it
// points to the load that machine checked. We must be careful to
// not reexectute the load.
//
ALPHA_INSTRUCTION FaultingInstruction;
BOOLEAN PreviousInstruction = FALSE;
FaultingInstruction.Long = *(PULONG)((ULONG)TrapFrame->Fir);
if( FaultingInstruction.Memory.Opcode != MEMSPC_OP ){
//
// Exception pc does not point to a memory barrier, return
// to the instruction after the exception pc.
//
TrapFrame->Fir += 4;
}
//
// The error has matched all of our conditions. Fix it up by
// writing the value 0xffffffff into the destination of the load.
//
TrapFrame->IntV0 = (ULONGLONG)0xffffffffffffffff;
//
// Clear the error condition in CIA_ERR.
//
CiaError.all = 0;
CiaError.RcvdMasAbt = 1;
CiaError.ErrValid = 1;
WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
CiaError.all );
return TRUE;
} //end if( (CiaError.RcvdMasAbt == 1) && (HalpMasterAbortExpected != 0) )
DbgPrint( "Unexpected master abort\n" );
//
// The system is not well and cannot continue reliable execution.
// Print some useful messages and return FALSE to indicate that the error
// was not handled.
//
FatalError:
DbgPrint( "Handling fatal error\n" );
//
// Clear the error condition in the MCES register.
//
HalpUpdateMces( TRUE, TRUE );
//
// Proceed to display the error.
//
HalAcquireDisplayOwnership(NULL);
//
// Display the dreaded banner.
//
HalDisplayString( "\nFatal system hardware error.\n\n" );
HalpCiaReportFatalError();
return( FALSE );
}
BOOLEAN
HalpTranslateSynToEcc(
PULONG Syndrome
)
/*++
Routine Description:
Translate a syndrome code to ECC error bit code.
Arguments:
Syndrome - pointer to the syndrome.
Return Value:
True if a data bit is in error. False otherwise.
--*/
{
static UCHAR SynToEccTable[0xff] = {0, };
static BOOLEAN SynToEccTableInitialized = FALSE;
ULONG Temp;
//
// Initialize the table.
//
if (!SynToEccTableInitialized) {
SynToEccTableInitialized = TRUE;
//
// Fill in the table.
//
SynToEccTable[0x01] = 0;
SynToEccTable[0x02] = 1;
SynToEccTable[0x04] = 2;
SynToEccTable[0x08] = 3;
SynToEccTable[0x10] = 4;
SynToEccTable[0x20] = 5;
SynToEccTable[0x40] = 6;
SynToEccTable[0x80] = 7;
SynToEccTable[0xce] = 0;
SynToEccTable[0xcb] = 1;
SynToEccTable[0xd3] = 2;
SynToEccTable[0xd5] = 3;
SynToEccTable[0xd6] = 4;
SynToEccTable[0xd9] = 5;
SynToEccTable[0xda] = 6;
SynToEccTable[0xdc] = 7;
SynToEccTable[0x23] = 8;
SynToEccTable[0x25] = 9;
SynToEccTable[0x26] = 10;
SynToEccTable[0x29] = 11;
SynToEccTable[0x2a] = 12;
SynToEccTable[0x2c] = 13;
SynToEccTable[0x31] = 14;
SynToEccTable[0x34] = 15;
SynToEccTable[0x0e] = 16;
SynToEccTable[0x0b] = 17;
SynToEccTable[0x13] = 18;
SynToEccTable[0x15] = 19;
SynToEccTable[0x16] = 20;
SynToEccTable[0x19] = 21;
SynToEccTable[0x1a] = 22;
SynToEccTable[0x1c] = 23;
SynToEccTable[0xe3] = 24;
SynToEccTable[0xe5] = 25;
SynToEccTable[0xe6] = 26;
SynToEccTable[0xe9] = 27;
SynToEccTable[0xea] = 28;
SynToEccTable[0xec] = 29;
SynToEccTable[0xf1] = 30;
SynToEccTable[0xf4] = 31;
SynToEccTable[0x4f] = 32;
SynToEccTable[0x4a] = 33;
SynToEccTable[0x52] = 34;
SynToEccTable[0x54] = 35;
SynToEccTable[0x57] = 36;
SynToEccTable[0x58] = 37;
SynToEccTable[0x5b] = 38;
SynToEccTable[0x5d] = 39;
SynToEccTable[0xa2] = 40;
SynToEccTable[0xa4] = 41;
SynToEccTable[0xa7] = 42;
SynToEccTable[0xa8] = 43;
SynToEccTable[0xab] = 44;
SynToEccTable[0xad] = 45;
SynToEccTable[0xb0] = 46;
SynToEccTable[0xb5] = 47;
SynToEccTable[0x8f] = 48;
SynToEccTable[0x8a] = 49;
SynToEccTable[0x92] = 50;
SynToEccTable[0x94] = 51;
SynToEccTable[0x97] = 52;
SynToEccTable[0x98] = 53;
SynToEccTable[0x9b] = 54;
SynToEccTable[0x9d] = 55;
SynToEccTable[0x62] = 56;
SynToEccTable[0x64] = 57;
SynToEccTable[0x67] = 58;
SynToEccTable[0x68] = 59;
SynToEccTable[0x6b] = 60;
SynToEccTable[0x6d] = 61;
SynToEccTable[0x70] = 62;
SynToEccTable[0x75] = 63;
}
//
// Tranlate the syndrome code.
//
Temp = *Syndrome;
*Syndrome = SynToEccTable[Temp];
//
// Is it a data bit or a check bit in error?
//
if (Temp == 0x01 || Temp == 0x02 || Temp == 0x04 || Temp == 0x08 ||
Temp == 0x10 || Temp == 0x20 || Temp == 0x40 || Temp == 0x80) {
return FALSE;
} else {
return TRUE;
}
}
VOID
HalpCiaErrorInterrupt(
VOID
)
/*++
Routine Description:
Handle a CIA correctable error interrupt.
Arguments:
None.
Return Value:
None.
--*/
{
static ERROR_FRAME Frame;
static CIA_CORRECTABLE_FRAME AlcorFrame;
ERROR_FRAME TempFrame;
PCORRECTABLE_ERROR CorrPtr;
PBOOLEAN ErrorlogBusy;
PULONG DispatchCode;
ULONG Syndrome;
PKINTERRUPT InterruptObject;
PKSPIN_LOCK ErrorlogSpinLock;
CIA_ERR CiaError;
CIA_STAT CiaStat;
CIA_SYN CiaSyn;
CIA_MEM_ERR0 MemErr0;
CIA_MEM_ERR1 MemErr1;
CIA_PCI_ERR0 PciErr0;
CIA_PCI_ERR1 PciErr1;
CIA_PCI_ERR2 PciErr2;
//
// The error is expected to be a corrected ECC error on a DMA or
// Scatter/Gather TLB read/write. Read the error registers relevant
// to this error.
//
CiaError.all = READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr );
//
// Check if an error is latched into the CIA.
//
if( CiaError.ErrValid == 0 ){
#if HALDBG
DbgPrint( "Cia error interrupt without valid CIA error\n" );
#endif //HALDBG
return;
}
//
// Check for the correctable error bit.
//
if( CiaError.CorErr == 0 ){
#if HALDBG
DbgPrint( "Cia error interrupt without correctable error indicated\n" );
#endif //HALDBG
}
//
// Real error, get the interrupt object.
//
DispatchCode = (PULONG)(PCR->InterruptRoutine[CORRECTABLE_VECTOR]);
InterruptObject = CONTAINING_RECORD(DispatchCode,
KINTERRUPT,
DispatchCode);
//
// Set various pointers so we can use them later.
//
CorrPtr = &TempFrame.CorrectableFrame;
ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext +
sizeof(PERROR_FRAME));
ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN));
//
// Clear the data structures that we will use.
//
RtlZeroMemory(&TempFrame, sizeof(ERROR_FRAME));
//
// Increment the number of CIA correctable errors.
//
CiaCorrectedErrors += 1;
CiaStat.all = READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaStat );
CiaSyn.all = READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaSyn );
MemErr0.all = READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr0 );
MemErr1.all = READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr1 );
PciErr0.all = READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr0 );
PciErr1.PciAddress = READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr1 );
PciErr2.PciAddress = READ_CIA_REGISTER(
&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2 );
//
// Print a correctable error message to the debugger.
//
#if HALDBG
DbgPrint( "CIA Correctable Error Number %d, state follows: \n",
CiaCorrectedErrors );
DbgPrint( "\tCIA_ERR : 0x%x\n", CiaError.all );
DbgPrint( "\tCIA_STAT: 0x%x\n", CiaStat.all );
DbgPrint( "\tCIA_SYN : 0x%x\n", CiaSyn.all );
DbgPrint( "\tCIA_MEM0: 0x%x\n", MemErr0.all );
DbgPrint( "\tCIA_MEM1: 0x%x\n", MemErr1.all );
DbgPrint( "\tPCI_ERR0: 0x%x\n", PciErr0.all );
#endif //HALDBG
//
// Fill in the error frame information.
//
TempFrame.Signature = ERROR_FRAME_SIGNATURE;
TempFrame.FrameType = CorrectableFrame;
TempFrame.VersionNumber = ERROR_FRAME_VERSION;
TempFrame.SequenceNumber = CiaCorrectedErrors;
TempFrame.PerformanceCounterValue =
KeQueryPerformanceCounter(NULL).QuadPart;
//
// Check for lost error.
//
if( CiaError.LostCorErr ) {
//
// Since the error registers are locked from a previous error,
// we don't know where the error came from. Mark everything
// as UNIDENTIFIED.
//
CorrPtr->Flags.LostCorrectable = 1;
CorrPtr->Flags.LostAddressSpace = UNIDENTIFIED;
CorrPtr->Flags.LostMemoryErrorSource = UNIDENTIFIED;
}
//
// Set error bit error masks.
//
CorrPtr->Flags.ErrorBitMasksValid = 1;
Syndrome = CiaSyn.all;
if ( HalpTranslateSynToEcc(&Syndrome) )
CorrPtr->DataBitErrorMask = 1 << Syndrome;
else
CorrPtr->CheckBitErrorMask = 1 << Syndrome;
//
// Determine error type.
//
switch (CiaStat.DmSt) {
case CIA_IO_WRITE_ECC:
//
// I/O write ECC error occurred.
//
CorrPtr->Flags.AddressSpace = IO_SPACE;
CorrPtr->Flags.ExtendedErrorValid = 1;
CorrPtr->ErrorInformation.IoError.Interface = PCIBus;
CorrPtr->ErrorInformation.IoError.BusNumber = 0;
CorrPtr->ErrorInformation.IoError.BusAddress.LowPart= PciErr1.PciAddress;
CorrPtr->ErrorInformation.IoError.TransferType = BUS_IO_WRITE;
break;
case CIA_DMA_READ_ECC:
CorrPtr->Flags.AddressSpace = MEMORY_SPACE;
CorrPtr->Flags.ExtendedErrorValid = 1;
//
// Where did the error come from?
//
if ( CiaStat.PaCpuRes == CIA_PROCESSOR_CACHE_ECC ) {
//
// Correctable error comes from processor cache.
//
CorrPtr->Flags.MemoryErrorSource = PROCESSOR_CACHE;
//
// DMA read or TLB miss error occurred.
//
if ( CiaStat.TlbMiss )
CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_READ;
else
CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_READ;
} else if ( CiaStat.PaCpuRes == CIA_SYSTEM_CACHE_ECC ) {
//
// Correctable error comes from system cache.
//
CorrPtr->Flags.MemoryErrorSource = SYSTEM_CACHE;
//
// DMA read or TLB miss error occurred.
//
if ( CiaStat.TlbMiss )
CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_READ;
else
CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_READ;
} else {
//
// Correctable error comes from system memory.
//
CorrPtr->Flags.MemoryErrorSource = SYSTEM_MEMORY;
//
// DMA read or TLB miss error occurred.
//
if ( CiaStat.TlbMiss )
CorrPtr->ErrorInformation.MemoryError.TransferType = TLB_MISS_READ;
else
CorrPtr->ErrorInformation.MemoryError.TransferType = BUS_DMA_READ;
}
break;
case CIA_DMA_WRITE_ECC:
CorrPtr->Flags.AddressSpace = MEMORY_SPACE;
CorrPtr->Flags.ExtendedErrorValid = 1;
//
// Where did the error come from?
//
if ( CiaStat.PaCpuRes == CIA_PROCESSOR_CACHE_ECC ) {
//
// Correctable error comes from processor cache.
//
CorrPtr->Flags.MemoryErrorSource = PROCESSOR_CACHE;
//
// DMA write or TLB miss error occurred.
//
if ( CiaStat.TlbMiss )
CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_WRITE;
else
CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_WRITE;
} else if ( CiaStat.PaCpuRes == CIA_SYSTEM_CACHE_ECC ) {
//
// Correctable error comes from system cache.
//
CorrPtr->Flags.MemoryErrorSource = SYSTEM_CACHE;
//
// DMA write or TLB miss error occurred.
//
if ( CiaStat.TlbMiss )
CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_WRITE;
else
CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_WRITE;
} else {
//
// Correctable error comes from system memory.
//
CorrPtr->Flags.MemoryErrorSource = SYSTEM_MEMORY;
//
// DMA write or TLB miss error occurred.
//
if ( CiaStat.TlbMiss )
CorrPtr->ErrorInformation.MemoryError.TransferType = TLB_MISS_WRITE;
else
CorrPtr->ErrorInformation.MemoryError.TransferType = BUS_DMA_WRITE;
//
//
}
break;
case CIA_IO_READ_ECC:
//
// I/O read ECC error occurred.
//
CorrPtr->Flags.AddressSpace = IO_SPACE;
CorrPtr->Flags.ExtendedErrorValid = 1;
CorrPtr->ErrorInformation.IoError.Interface = PCIBus;
CorrPtr->ErrorInformation.IoError.BusNumber = 0;
CorrPtr->ErrorInformation.IoError.BusAddress.LowPart= PciErr1.PciAddress;
CorrPtr->ErrorInformation.IoError.TransferType = BUS_IO_READ;
break;
default:
//
// Something strange happened. Don't know where the error occurred.
//
CorrPtr->Flags.AddressSpace = UNIDENTIFIED;
break;
}
//
// Get the physical address where the error occurred.
//
CorrPtr->Flags.PhysicalAddressValid = 1;
CorrPtr->PhysicalAddress = (MemErr1.all & 0xff) << 32;
CorrPtr->PhysicalAddress |= MemErr0.all;
//
// Get bits 7:0 of the address from the PCI address.
//
CorrPtr->PhysicalAddress |= PciErr1.PciAddress & 0xff;
//
// Scrub the error if it's any type of memory error.
//
if ( CorrPtr->Flags.AddressSpace == MEMORY_SPACE &&
CorrPtr->Flags.PhysicalAddressValid )
CorrPtr->Flags.ScrubError = 1;
//
// Acquire the spinlock.
//
KiAcquireSpinLock(ErrorlogSpinLock);
//
// Check to see if an errorlog operation is in progress already.
//
if (!*ErrorlogBusy) {
//
// The error is expected to be a corrected ECC error on a DMA or
// Scatter/Gather TLB read/write. Read the error registers relevant
// to this error.
//
AlcorFrame.CiaErr = CiaError.all;
AlcorFrame.CiaStat = CiaStat.all;
AlcorFrame.CiaSyn = CiaSyn.all;
AlcorFrame.MemErr0 = MemErr0.all;
AlcorFrame.MemErr1 = MemErr1.all;
AlcorFrame.PciErr0 = PciErr0.all;
AlcorFrame.PciErr1 = PciErr1.PciAddress;
AlcorFrame.PciErr2 = PciErr2.PciAddress;
//
// Read the CIA configuration registers for logging information.
//
AlcorFrame.Configuration.CiaRev =
READ_CIA_REGISTER( &((PCIA_GENERAL_CSRS)
(CIA_GENERAL_CSRS_QVA))->CiaRevision );
AlcorFrame.Configuration.CiaCtrl =
READ_CIA_REGISTER( &((PCIA_GENERAL_CSRS)
(CIA_GENERAL_CSRS_QVA))->CiaCtrl );
AlcorFrame.Configuration.Mcr =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->Mcr );
AlcorFrame.Configuration.Mba0 =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->Mba0 );
AlcorFrame.Configuration.Mba2 =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->Mba2 );
AlcorFrame.Configuration.Mba4 =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->Mba4 );
AlcorFrame.Configuration.Mba6 =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->Mba6 );
AlcorFrame.Configuration.Mba8 =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->Mba8 );
AlcorFrame.Configuration.MbaA =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->MbaA );
AlcorFrame.Configuration.MbaC =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->MbaC );
AlcorFrame.Configuration.MbaE =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->MbaE );
AlcorFrame.Configuration.Tmg0 =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->Tmg0 );
AlcorFrame.Configuration.Tmg1 =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->Tmg1 );
AlcorFrame.Configuration.Tmg2 =
READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS)
(CIA_MEMORY_CSRS_QVA))->Tmg2 );
AlcorFrame.Configuration.CacheCnfg =
PCR->SecondLevelCacheSize;
//
// Set the raw system information.
//
CorrPtr->RawSystemInformationLength = sizeof(CIA_CORRECTABLE_FRAME);
CorrPtr->RawSystemInformation = &AlcorFrame;
//
// Set the raw processor information. Disregard at the moment.
//
CorrPtr->RawProcessorInformationLength = 0;
//
// Set reporting processor information. Disregard at the moment.
//
CorrPtr->Flags.ProcessorInformationValid = 0;
//
// Set system information. Disregard at the moment.
//
CorrPtr->Flags.SystemInformationValid = 0;
//
// Copy the information that we need to log.
//
RtlCopyMemory(&Frame,
&TempFrame,
sizeof(ERROR_FRAME));
//
// Put frame into ISR service context.
//
*(PERROR_FRAME *)InterruptObject->ServiceContext = &Frame;
} else {
//
// An errorlog operation is in progress already. We will
// set various lost bits and then get out without doing
// an actual errorloging call.
//
Frame.CorrectableFrame.Flags.LostCorrectable = TRUE;
Frame.CorrectableFrame.Flags.LostAddressSpace =
TempFrame.CorrectableFrame.Flags.AddressSpace;
Frame.CorrectableFrame.Flags.LostMemoryErrorSource =
TempFrame.CorrectableFrame.Flags.MemoryErrorSource;
}
//
// Release the spinlock.
//
KiReleaseSpinLock(ErrorlogSpinLock);
//
// Dispatch to the secondary correctable interrupt service routine.
// The assumption here is that if this interrupt ever happens, then
// some driver enabled it, and the driver should have the ISR connected.
//
((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
InterruptObject,
InterruptObject->ServiceContext
);
//
// Clear the corrected error status bit and return to continue
// execution.
//
CiaError.all = 0;
CiaError.CorErr = 1;
WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
CiaError.all );
return;
}