www.pudn.com > vxworks0108.rar > sysMcp.c
/*---------------------------------------------------------------- +includes+-*/
#include "type.h"
#include "asm.h"
#include "reg.h"
#include "esf.h"
#include "pciConfigLib.h"
#include "config.h"
#include "vg4.h"
#include "mpc107.h"
#include "syslib.h"
#include "string.h"
#include "universe.h"
/*-----------------------------------------------------------------(includes)-*/
/*------------------------------------------------------------------+defines+-*/
#define _PPC_SRR1_MCPIN_U 0x0008 /* set by assertion of MCP */
#define EXC_MCP_LOCK /* lock MCP pin during exception handling */
/*------------------------------------------------------------------(defines)-*/
/*-----------------------------------------------------------------+typedefs+-*/
/*-----------------------------------------------------------------(typedefs)-*/
/*------------------------------------------------------------------+globals+-*/
/* Counter for machine check exceptions caused by assertion of MCP. */
UINT32 mcpExcCnt = 0;
/* ECC single-bit error counter */
UINT32 eccSingleBitErrorCnt = 0;
/* ECC multi-bit error counter */
UINT32 eccMultiBitErrorCnt = 0;
/* User ECC Single-Bit error routines */
LOCAL FUNCPTR eccSingleBitErrorRoutine = NULL;
LOCAL int eccSingleBitArg = 0;
/* User ECC Multi-Bit error routines */
LOCAL FUNCPTR eccMultiBitErrorRoutine = NULL;
LOCAL int eccMultiBitArg = 0;
/*------------------------------------------------------------------(globals)-*/
/*-------------------------------------------------------------+declarations+-*/
IMPORT void printf();
/*-------------------------------------------------------------(declarations)-*/
#if defined (EXC_MCP_LOCK)
/*********************************************************************
*
* mcpLock - Locks out further machine check exceptions from MCP
*
* This routine clears HID0[EMCP]. This masks out further machine check
* exceptions caused by assertion of MCP.
*
* RETURNS: content of HID0 before masking MCP exceptions
*
* ULONG mcpLock
* (
* void
* )
*
*/
LOCAL ULONG mcpLock (void)
{
UINT hid0;
__asm__ volatile ("mfspr %0, 1008
rlwinm 4, %0, 0, 1, 31
mtspr 1008, 4
isync"
: "=r" (hid0) /* output operand, %0 */
: /* no input operand */
: "r4" /* side effects: r4 altered */
);
return (hid0);
}
/*********************************************************************
*
* mcpUnlock - Unlocks machine check exceptions from MCP
*
* This routine sets HID0[EMCP]. This re-enables machine check
* exceptions caused by assertion of MCP.
*
* RETURNS: N/A
*
* ULONG mcpLock
* (
* void
* )
*
*/
LOCAL __inline__ void mcpUnlock
(
ULONG oldHid0 /* value returned by mcpLock() */
)
{
__asm__ volatile ("rlwinm 3, %0, 0, 0, 0
mfspr 4, 1008
or 4, 3, 4
mtspr 1008, 4
isync"
: /* no output operand */
: "r" (oldHid0) /* input operand, %0 = input */
: "r4" /* side effects: r4 altered */
);
return;
}
#endif /* defined (EXC_MCP_LOCK) */
/***************************************************************************
*
* sysMcpExcHandler - machine check exception handler
*
* This function is invoked in response to a PPC Machine Check Exception.
*
* This exception may be due to an ECC error, in which case the user installed
* routine for single-bit or multi-bit errors is called if it has been
* connected. Otherwise the VxWorks generic exception handler is then called.
*
* The machine check exception may also occur due to the VG4 MCP timer.
* The MCP timer can trigger IOCHCK at the ISA bus periodically, if enabled.
* This will trigger the MCP input of the processor via the NMI input of
* the MPC107.
*
* RETURNS: N/A
*
* SEE ALSO: sysMcpInit()
*
*/
LOCAL void sysMcpExcHandler
(
void * pEsf
)
{
#if defined (INCLUDE_ECC) || defined (INCLUDE_MCP_TIMER) || defined (INCLUDE_VME)
#if defined (EXC_MCP_LOCK)
ULONG lockVal;
#endif /* defined (EXC_MCP_LOCK) */
int fatal=0; /* set when error is assumed fatal and
default exception handler shall be called */
volatile ULONG dummy;
#if defined (INCLUDE_ECC)
UINT8 eccRegVal,
eccRegVal2;
#endif /* defined (INCLUDE_ECC) */
#if 0
_PPC_SRR1_MCPIN_U might not been set although, for instance, an VMEbus
error occurred. This happens for example when using the dump command
on the console (e.g. d 0xd0001234).
Better check I/O status bits first.
/*
* Call VxWorks default exception handler, if source for the machine check
* exception is not the MCP.
*/
if ((vxSrr1Get() & (_PPC_SRR1_MCPIN_U << 16)) != (_PPC_SRR1_MCPIN_U << 16))
{
excExcHandle (pEsf);
}
#endif
#if defined (EXC_MCP_LOCK)
/* Disable further machine check exception from the MCP. */
lockVal = mcpLock ();
#endif /* defined (EXC_MCP_LOCK) */
/* Increment counter for number of MCP exceptions. */
mcpExcCnt++;
#if defined (INCLUDE_VME)
{
UINT32 pciCsr;
UINT32 laerr, amerr;
IMPORT UINT32 univBaseAdrs;
/* Get current UNIVERSE status */
sysPciRead32 ((UINT32)(UNIVERSE_PCI_CSR), &pciCsr);
sysPciRead32 ((UINT32)UNIVERSE_V_AMERR, &amerr);
if ((pciCsr & 0xf8000000) || (amerr & V_AMERR_V_STAT)) {
/* VME error occurred */
printf("\nVMEbus ERROR\nUNIVERSE PCI_CSR 0x%x\n", pciCsr, 0, 0, 0, 0);
sysPciWrite32 ((UINT32)(UNIVERSE_PCI_CSR), pciCsr);
sysPciRead32 ((UINT32)UNIVERSE_VAERR, &laerr);
printf("UNIVERSE VAERR 0x%x\n", laerr, 0, 0, 0, 0);
printf("UNIVERSE AMERR 0x%x\n", amerr, 0, 0, 0, 0);
/* Clear any VME address error */
sysPciWrite32 ((UINT32)UNIVERSE_V_AMERR, V_AMERR_V_STAT);
/* Force write due to Write-Posting and get updated status */
sysPciRead32 ((UINT32)(UNIVERSE_PCI_CSR), &pciCsr);
/* Dummy read from 0x0200 to cause the negation of MCP. */
dummy = *((volatile ULONG*)_EXC_OFF_MACH);
fatal = 1;
}
}
#endif /* defined (INCLUDE_VME) */
#if defined (INCLUDE_ECC)
/* Read Error Detection Register 1 and check for ECC trigger exceeded error. */
if (OK == pciConfigInByte (0, 0, 0, MPC107_EDR1, &eccRegVal))
{
if (eccRegVal & MPC107_EDR1_MRPE)
{
/* Increment counter for single-bit errors. */
eccSingleBitErrorCnt++;
/* ECC Single-Bit Error Trigger exceeded */
if ( eccSingleBitErrorRoutine != NULL )
{
(*(FUNCPTR)eccSingleBitErrorRoutine)(eccSingleBitArg);
}
else
{
eccRegVal = 0;
if (OK == pciConfigInByte (0, 0, 0, MPC107_ECCSBETR, &eccRegVal))
{
printf ("ECC Single-Bit Errors occurred (trigger value is %d)!\n",
(UINT)eccRegVal,0,0,0,0);
}
else
{
printf ("ECC Single-Bit Errors occurred!\n",0,0,0,0,0);
}
}
/* reset ECC single-bit error counter */
(void)pciConfigOutByte (0, 0, 0, MPC107_ECCSBEC, 0x00);
/* Clear ECC single-bit error trigger exceeded bit */
(void)pciConfigOutByte (0, 0, 0, MPC107_EDR1, MPC107_EDR1_MRPE);
/* Dummy read from 0x0200 to cause the negation of MCP. */
dummy = *((volatile ULONG*)_EXC_OFF_MACH);
}
}
/* Read Error Detection Register 2 and check for ECC multi-bit error. */
if (OK == pciConfigInByte (0, 0, 0, MPC107_EDR2, &eccRegVal2))
{
if (eccRegVal2 & MPC107_EDR2_EMBE)
{
/* Increment counter for multi-bit errors. */
eccMultiBitErrorCnt++;
/* ECC Multi-Bit Error occurred */
if ( eccMultiBitErrorRoutine != NULL )
{
(*(FUNCPTR)eccMultiBitErrorRoutine)(eccMultiBitArg);
}
else
{
printf ("ECC Multi-Bit Error occurred!\n",0,0,0,0,0);
}
/* Clear ECC multi-bit error bit */
(void)pciConfigOutByte (0, 0, 0, MPC107_EDR2, MPC107_EDR2_EMBE);
/* Dummy read from 0x0200 to cause the negation of MCP. */
dummy = *((volatile ULONG*)_EXC_OFF_MACH);
}
}
#endif /* defined (INCLUDE_ECC) */
/*
* not needed for ECC errors, since they are not reported in the cnf
* status reg, but for VMEbus errors (Target Abort Error).
*/
/* Clear Cnfg Hdr Status Reg of Chaparral (MPC107) */
pciConfigOutWord (0, 0, 0, MPC107_PCI_STAT, MPC107_PCI_STAT_CLR);
#if defined (EXC_MCP_LOCK)
/* Enable machine check exception from the MCP again. */
mcpUnlock (lockVal);
#endif /* defined (EXC_MCP_LOCK) */
if (fatal) {
/* Call VxWorks default exception handler. */
/* excExcHandle (pEsf); */
}
return;
#else
/* Call VxWorks default exception handler. */
/* excExcHandle (pEsf); */
return;
#endif /* defined (INCLUDE_ECC) || defined (INCLUDE_MCP_TIMER) */
}
/***************************************************************************
*
* sysMcpInit - machine check pin initialization
*
* This function is initializes possible MCP sources like memory ECC or
* MCP timer.
*
* First error reporting is disabled for all kind of ECC errors.
* If ECC error handling is included, a machine check exception handler is
* connected, all error counters are reset and error reporting is enabled.
* ECC error reporting for single-bit errors is not enabled by default. It
* must be included in config.h if desired.
*
* PCI Received Target Abort Error is enabled to generate MCP interrupts for
* VMEbus Bus Errors.
* Finally Machine Check Exception are enabled in the MPC107.
*
* RETURNS: N/A
*
* SEE ALSO: sysMcpExcHandler()
*
*/
#if 0
void sysMcpInit (void)
{
#if defined (INCLUDE_ECC)
UINT32 regVal;
#endif /* defined (INCLUDE_ECC) */
int lockVal;
/* Disable single-bit ECC error reporting for SDRAM. */
(void)pciConfigModifyByte (0, 0, 0, MPC107_EER1, MPC107_EER1_MPECCEE, 0);
/* Disable multi-bit ECC error reporting for SDRAM. */
(void)pciConfigModifyByte (0, 0, 0, MPC107_EER2, MPC107_EER2_ECCMEE, 0);
/* Disable PCI Received Target Abort Error in ErrEnR2 - 0xc4 */
(void)pciConfigModifyByte(0, 0, 0, MPC107_EER2, MPC107_EER2_PCIRTAEE, 0);
#if defined (INCLUDE_ECC)
/* Reset error counter. */
eccSingleBitErrorCnt = 0;
eccMultiBitErrorCnt = 0;
mcpExcCnt = 0;
/* Enable ECC error reporting if ECC is enabled. */
if ( OK == pciConfigInLong (0, 0, 0, MPC107_MCCR2, ®Val) )
{
if ( 0 == (regVal & MPC107_MCCR2_INLPARNOTECC) ) /* ECC enabled */
{
/* Clear ECC single-bit error trigger exceeded bit. */
(void)pciConfigOutByte (0, 0, 0, MPC107_EDR1, MPC107_EDR1_MRPE);
/* Clear ECC multi-bit error bit */
(void)pciConfigOutByte (0, 0, 0, MPC107_EDR2, MPC107_EDR2_EMBE);
/* Reset ECC single-bit error counter. */
(void)pciConfigOutByte (0, 0, 0, MPC107_ECCSBEC, 0x00);
/* Set ECC single-bit error trigger to pre-defined value. */
(void)pciConfigOutByte (0, 0, 0, MPC107_ECCSBETR, ECC_SINGLE_BIT_TRIG_VAL);
#if defined (INCLUDE_ECC_SINGLE_BIT)
/* Enable single-bit ECC erorrs for SDRAM */
(void)pciConfigModifyByte (0, 0, 0, MPC107_EER1, MPC107_EER1_MPECCEE, MPC107_EER1_MPECCEE);
#endif /* defined (INCLUDE_ECC_SINGLE_BIT) */
/* Enable multibit ECC erorrs for SDRAM */
(void)pciConfigModifyByte (0, 0, 0, MPC107_EER2, MPC107_EER2_ECCMEE, MPC107_EER2_ECCMEE);
}
}
#endif /* defined (INCLUDE_ECC) */
/* Connect handler for Machine Check exception. */
excConnect ((VOIDFUNCPTR *) _EXC_OFF_MACH, sysMcpExcHandler);
/* Enable Machine Check exception */
lockVal=intLock();
vxMsrSet(vxMsrGet() | _PPC_MSR_ME);
intUnlock(lockVal);
EIEIO_SYNC;
/* Enable Machine Check Pin (EMCP) */
lockVal=intLock();
vxHid0Set(vxHid0Get() | _PPC_HID0_EMCP);
intUnlock(lockVal);
EIEIO_SYNC;
/*
* Enable MCP interrupts in MPC107
* Processor Interface Configuration Register (PRC1/PICR1 - 0xA8)
*/
(void) pciConfigModifyLong(0, 0, 0,
MPC107_PRC1, MPC107_PRC1_MCP_EN, MPC107_PRC1_MCP_EN);
EIEIO_SYNC;
/*
* enable PCI Received Target Abort Error in ErrEnR2 - 0xc4
* this will cause an machine check exception upon VMEbus BERR
* if MCP interrupts are enabled in MPC107 (PICR1 |= MCP_EN)
*/
(void)pciConfigModifyByte(0, 0, 0,
MPC107_EER2, MPC107_EER2_PCIRTAEE, MPC107_EER2_PCIRTAEE);
}
#endif
#if defined (INCLUDE_ECC)
#if defined (INCLUDE_ECC_SINGLE_BIT)
/*****************************************************************************
*
* sysEccSingleBitErrorConnect - connect user routine for ECC single-bit error
*
* This function installs the specified user routine that is to be invoked upon
* an ECC single-bit error. Single-bit errors can be corrected by the ECC
* hardware logic. Therefore single-bit error handling is not included by
* default. To include single-bit error support the following define must be set
* in config.h in addition to INCLUDE_ECC:
* #define INCLUDE_ECC_SINGLE_BIT
*
* The number of single-bit errors at which a mchine check exception is asserted
* may be specified with the following define:
* #define ECC_SINGLE_BIT_TRIG_VAL 0xff (0xff is the default value)
*
* RETURNS: OK, always
*
* SEE ALSO: sysEccMultiBitErrorConnect()
*
*/
STATUS sysEccSingleBitErrorConnect
(
FUNCPTR routine, /* routine called for ECC single-bit error */
int arg /* argument to single-bit error routine */
)
{
eccSingleBitErrorRoutine = routine;
eccSingleBitArg = arg;
return OK;
}
#endif /* defined (INCLUDE_ECC_SINGLE_BIT) */
/*****************************************************************************
*
* sysEccMultiBitErrorConnect - connect user routine for ECC multi-bit error
*
* This function installs the specified user routine that is to be invoked upon
* an ECC multi-bit error. Usually multi-bit errors are not correctable,
* therefore multi-bit ECC error handling is included, if INCLUDE_ECC is defined
* in config.h.
*
* RETURNS: OK, always
*
* SEE ALSO: sysEccSingleBitErrorConnect()
*
*/
STATUS sysEccMultiBitErrorConnect
(
FUNCPTR routine, /* routine called for ECC multi-bit error */
int arg /* argument to multi-bit error routine */
)
{
eccMultiBitErrorRoutine = routine;
eccMultiBitArg = arg;
return OK;
}
#endif /* defined (INCLUDE_ECC) */
#if defined (INCLUDE_SHOW_ROUTINES) && (defined (INCLUDE_ECC) || defined (INCLUDE_MCP_TIMER))
/******************************************************************************
*
* sysMcpExcShow - display MCP debug information
*
* This function displays the number of exceptions handled by the MCP handler
* sysMcpExcHandler(). The number of single-bit and multi-bit ECC errors are
* displayed too.
*
* RETURNS: none
*/
void sysMcpExcShow (void)
{
#if defined (INCLUDE_ECC_SINGLE_BIT)
UINT8 eccRegVal;
#endif /* defined (INCLUDE_ECC_SINGLE_BIT) */
printf ("\nMCP Exception Count Summary:\n");
printf (" # of total MCP exceptions: %8d\n", mcpExcCnt);
#if defined (INCLUDE_ECC_SINGLE_BIT)
printf (" # of single-bit ECC exceptions: %8d\n", eccSingleBitErrorCnt);
if (OK == pciConfigInByte (0, 0, 0, MPC107_ECCSBEC, &eccRegVal))
{
printf (" # of current single-bit ECC errors: %3d\n", eccRegVal);
}
if (OK == pciConfigInByte (0, 0, 0, MPC107_ECCSBETR, &eccRegVal))
{
printf (" single-bit ECC trigger value: %3d\n", eccRegVal);
}
#endif /* defined (INCLUDE_ECC_SINGLE_BIT) */
printf (" # of multi-bit ECC exceptions: %8d\n", eccMultiBitErrorCnt);
}
#endif /* defined (INCLUDE_SHOW_ROUTINES) && (defined (INCLUDE_ECC) || defined (INCLUDE_MCP_TIMER))*/