1
0
Files
2022-09-29 17:59:04 +03:00

1628 lines
46 KiB
C

/**************************************************************************
* *
* Copyright (C) 1992-1994, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
/* NOTE: This is a pared down version of kern/ml/EVEREST/everror.c
intended for use only by the FRU analyzer and icrash. */
#ident "$Revision: 1.1 $"
/*
* P L E A S E R E A D
*
* ***** IMPORTANT NOTE *******
*
* READ THIS NOTE BEFORE MAKING ANY CHANGES IN THIS FILE.
*
*
* This file is being shared by IDE diagsnostics code and Kernel. Main
* Reason for this is to use the same code/technique to handle the errors
* both in Kenel and Standalone Mode.
*
* This necessitates certain precaution in adding/removing code from this
* file.
*
* If any code is specific to Kernel, and is not needed in the Standalone
* mode please envelope the code with
* #ifndef _STANDALONE
* #endif
*
* Similarly if some code has to be specific to Standaloce source then use
* #ifdef _STANDALONE
* #endif
*
*
* Just using #ifdef KERNEL would not be sufficient since IDE build does use
* it.
*
*/
#define _KERNEL 1
#include <sys/types.h>
#undef _KERNEL
#include <stdio.h>
#include <sys/sbd.h>
#include <sys/immu.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/EVEREST/everest.h>
#include <sys/EVEREST/evconfig.h>
#include <sys/EVEREST/epc.h>
#include <sys/EVEREST/vmecc.h>
#include <sys/EVEREST/fchip.h>
#include <sys/EVEREST/s1chip.h>
#include <sys/EVEREST/dang.h>
#include "evfru.h"
/* To handle IA Rev-1 bug. Assumes only one IO4 board exists in a system */
static int IA_chiprev=0;
static char IA_bugmsg[]={"( Possible IA Rev1 bug??? )"};
static int ip_slot_print;
char error_dumpbuf[4096];
int error_dumpindx=0;
#ifdef STANDALONE
void adap_error_show (int, int);
void ip19_error_show (int);
void ip21_error_show (int);
void mc3_error_show (int);
#else
static void adap_error_show (int, int);
static void ip19_error_show (int);
static void ip21_error_show (int);
static void mc3_error_show (int);
#endif /* STANDALONE */
static void ip19_cc_error_show (int slot, int pcpuid);
static void ip21_cc_error_show (int slot, int pcpuid);
static void epc_error_show (int, int);
static void dang_error_show (int, int);
static void fcg_error_show (int, int);
static void fchip_error_show (int, int);
static void scsi_error_show (int, int);
void fru_mc3_decode_addr (void (*)(), uint, uint, evcfginfo_t *);
extern int addr2sbs(uint bloc, uint offset, uint *slot, uint *bank,
uint *simm, evcfginfo_t *ec);
#ifndef _STANDALONE
#define MBYTES 1024*1024
int mc3_type_bank_size[] = {16*MBYTES,64*MBYTES,128*MBYTES,256*MBYTES,
256*MBYTES,1024*MBYTES,1024*MBYTES,0};
#define MC3_SBE_MAX_INTR_RATE (HZ) /* min time interval btwn interrupts */
#define MC3_SBE_EXCESSIVE_RATE 3600 /* declare "excessive" if see err */
/* within this many secs of previous */
mc3_array_err_t mc3_errcount[EV_MAX_MC3S];
mc3error_t *last_mc3error; /* for debugging purposes */
#endif /* _STANDALONE */
#ifdef CHIPREV_BUG
#define IAREV1_MSG (((IA_chiprev == 1)) ? IA_bugmsg : "")
#define AREV2_MSG(x) ((x==2) ? "( Possible A Rev2 bug??? )" : "")
#define AREV3_MSG(x) ((x==3) ? "( Possible A Rev3 bug??? )" : "")
#define VMECC_REV1(x) ((!(x >> 8)) ? "( Possible VMECC Rev1 bug??? )" : "")
#endif
#define make_ll(x, y) (evreg_t)((evreg_t)x << 32 | y)
static int everror_udbe; /* set to SPNUM on a user level DBE. Should
* happen only due to bad coding/hardware !!!!
*/
#define IP19_CPUNAME "IP19"
#define IP21_CPUNAME "IP21"
#define MEMNAME "MC3"
#define IONAME "IO4"
/* Undefined prototypes */
extern void qprintf(char *);
extern int vsprintf(char *, const char *, /* va_list */ char *);
extern char bank_letter(uint leaf, uint bank);
void
bad_board_type(int type, int slot)
{
printf("^??? Bad board type %d slot %d\n", type, slot);
}
void
bad_ioa_type(int type, int slot, int padap)
{
printf("^??? Bad ioa type %d slot %d padap %d\n", type, slot, padap);
}
static caddr_t
ioa_name(int type)
{
switch(type){
case IO4_ADAP_EPC : return ("EPC");
case IO4_ADAP_FCHIP: return ("Fchip");
case IO4_ADAP_SCIP : return ("SCIP");
case IO4_ADAP_SCSI : return ("S1");
case IO4_ADAP_VMECC: return ("VMECC");
case IO4_ADAP_HIPPI: return ("HIPPI");
case IO4_ADAP_FCG : return ("FCG");
case IO4_ADAP_DANG : return ("DANG");
default : return ("Unknown");
}
}
#ifdef IDE
#include <ide_msg.h>
#endif
static char everr_msg[256];
#define NEST_DEPTH 2
static char everr_line[256];
#define NONE_LVL 0
#define SLOT_LVL 1
#define ASIC_LVL 2
#define REG_LVL 3
#define BIT_LVL 4
everror_t *errbuf;
evcfginfo_t *ecbuf;
void show_hardware_state(everror_t *pass_errbuf, evcfginfo_t *pass_ecbuf)
{
errbuf = pass_errbuf;
ecbuf = pass_ecbuf;
everest_error_show();
}
void
everest_error_show()
{
int slot;
int id; /* virtual id of the board/adpter */
int padap;
ev_perr(NONE_LVL, "HARDWARE ERROR STATE:\n");
for (slot = 1; slot < EV_MAX_SLOTS; slot++) {
evbrdinfo_t *eb = &(ecbuf->ecfg_board[slot]);
if (eb->eb_enabled == 0)
continue;
switch (eb->eb_type) {
case EVTYPE_IP19:
ip_slot_print=1;
ip19_error_show(slot);
for (id = 0; id < 4; id++)
if (eb->eb_cpuarr[id].cpu_enable)
ip19_cc_error_show(slot, id);
ip_slot_print=0;
break;
case EVTYPE_IP21:
ip_slot_print=1;
ip21_error_show(slot);
for (id = 0; id < 4; id++)
if (eb->eb_cpuarr[id].cpu_enable)
ip21_cc_error_show(slot, id);
ip_slot_print=0;
break;
case EVTYPE_MC3:
mc3_error_show(slot);
break;
case EVTYPE_IO4:
io4_error_show(slot);
for (padap = 1; padap < IO4_MAX_PADAPS; padap++) {
if (eb->eb_ioarr[padap].ioa_enable == 0)
continue;
adap_error_show(slot, padap);
}
break;
default:
break;
}
}
}
/*
* ev_perr : Error printing Routine.
* Format the error based on the level and print it.
*/
void
ev_perr(int level, char *fmt, ...)
{
va_list ap;
unchar *c, *p, val=0;
char *line;
int i;
va_start(ap, fmt);
vsprintf(everr_msg, fmt, ap);
va_end(ap);
for (i = 0; i < level * 2; i++)
putchar(' ');
printf(" %s", everr_msg);
}
#ifndef STANDALONE
static
#endif
void
adap_error_show(int slot, int padap)
{
int type = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_type;
switch (type) {
case IO4_ADAP_FCHIP:
fchip_error_show(slot, padap);
#ifdef _STANDALONE
vmecc_error_show(slot, padap);
#endif
break;
case IO4_ADAP_HIPPI:
fchip_error_show(slot, padap);
io4hip_error_show(slot, padap);
break;
case IO4_ADAP_VMECC:
fchip_error_show(slot, padap);
vmecc_error_show(slot, padap);
break;
case IO4_ADAP_EPC:
epc_error_show(slot, padap);
break;
case IO4_ADAP_FCG:
fchip_error_show(slot, padap);
fcg_error_show(slot, padap);
break;
case IO4_ADAP_DANG:
dang_error_show(slot, padap);
break;
case IO4_ADAP_SCSI:
case IO4_ADAP_SCIP:
scsi_error_show(slot, padap);
break;
case IO4_ADAP_NULL:
break; /* nothing to do*/
default:
bad_ioa_type(type, slot, padap);
}
}
/*
* About these interface functions,
* xxx_error_show - print out the errbuf value onto console.
*/
/*
* Bits 8-11 of the A Chip on IP21 are encoded to identify the
* DB chip and CPU chip having the error.
*/
#define DB0_MIN 10
#define DB0_MAX 11
#define DB1_MIN 8
#define DB1_MAX 9
#define DB_ERRMASK 0x3
#define DB0_ERROR(err) (((err)>>DB0_MIN)&DB_ERRMASK)
#define DB1_ERROR(err) (((err)>>DB1_MIN)&DB_ERRMASK)
char *db0_error[] = {
"", /* no error */
"", /* not valid */
" 11:CPU 0 DB0->D parity error",
"10,11:CPU 1 DB0->D parity error"
};
char *db1_error[] = {
"", /* no error */
"", /* not valid */
" 9:CPU 0 DB1->D parity error",
" 8,9:CPU 1 DB1->D parity error"
};
char *ip21_error[] = {
/************************************ IP21 ***********************************/
" 0:CPU 0 CC->A Channel 0 parity error",
" 1:CPU 0 CC->A Wback Channel parity error",
" 2:CPU 1 CC->A Channel 0 parity error",
" 3:CPU 1 CC->A Wback Channel parity error",
" 4:ADDR_ERROR on EBUS",
" 5:My ADDR_ERROR on EBUS",
"",
"",
" 8:CPU 0 CC->D parity error",
" 9:CPU 0 CC->D parity error",
" 10:CPU 1 CC->D parity error",
" 11:CPU 1 CC->D parity error",
" 12:CPU 0 ADDR_HERE not asserted",
" 13:CPU 0 ADDR_HERE not asserted",
" 14:CPU 1 ADDR_HERE not asserted",
" 15:CPU 1 ADDR_HERE not asserted"
};
#define IP21_ERROR_MAX 16
/************************************ IP19 ***********************************/
char *ip19_error[] = {
" 0:CPU 0 CC->A parity error",
" 1:CPU 1 CC->A parity error",
" 2:CPU 2 CC->A parity error",
" 3:CPU 3 CC->A parity error",
" 4:ADDR_ERROR on EBUS",
" 5:My ADDR_ERROR on EBUS",
"",
"",
" 8:CPU 0 CC->D parity error",
" 9:CPU 1 CC->D parity error",
"10:CPU 2 CC->D parity error",
"11:CPU 3 CC->D parity error",
"12:CPU 0 ADDR_HERE not asserted",
"13:CPU 1 ADDR_HERE not asserted",
"14:CPU 2 ADDR_HERE not asserted",
"15:CPU 3 ADDR_HERE not asserted"
};
#define IP19_ERROR_MAX 16
/* Set to 1 if IP19 slot no is to be printed in cc_error_show */
#ifndef STANDALONE
static
#endif
void
ip19_error_show(int slot)
{
int id = ecbuf->ecfg_board[slot].eb_cpu.eb_cpunum;
int error = errbuf->ip[id].a_error;
int i;
if (error == 0)
return;
ev_perr(SLOT_LVL, "%s in slot %d \n", IP19_CPUNAME, slot);
ip_slot_print = 0;
ev_perr(REG_LVL, "A Chip Error Register: 0x%x\n", error);
for (i = 0; i < IP19_ERROR_MAX; i++) {
if (error & (1L << i))
#ifdef CHIPREV_BUG
if (A_ERROR_ADDR_ERR & (1L << i))
ev_perr(BIT_LVL,"%s %s\n",ip19_error[i],IAREV1_MSG);
else
#endif
ev_perr(BIT_LVL, "%s\n",ip19_error[i]);
}
}
#ifndef STANDALONE
static
#endif
void
ip21_error_show(int slot)
{
int id = ecbuf->ecfg_board[slot].eb_cpu.eb_cpunum;
int error = errbuf->ip[id].a_error;
int i;
if (error == 0)
return;
ev_perr(SLOT_LVL, "%s in slot %d \n", IP21_CPUNAME, slot);
ip_slot_print = 0;
ev_perr(REG_LVL, "A Chip Error Register: 0x%x\n", error);
for (i = 0; i < IP21_ERROR_MAX; i++) {
if (error & (1L << i))
#ifdef CHIPREV_BUG
if (A_ERROR_ADDR_ERR & (1L << i))
ev_perr(BIT_LVL,"%s %s\n",ip21_error[i],IAREV1_MSG);
else
#endif
ev_perr(BIT_LVL, "%s\n",ip21_error[i]);
}
}
/******************************** CC *****************************************/
char *ip19_cc_error[] = {
"0: ECC uncorrectable (multi bit) error in Scache",
"1: ECC correctable (single bit) error in Scache",
"2: Parity Error on TAG RAM Data",
"3: Parity Error on Address from A-chip",
"4: Parity Error on Data from D-chip",
"5: MyRequest TimeOut on EBUS",
"6: MyResponse D-Resource TimeOut in A chip",
"7: MyIntervention Response D-Resource TimeOut in A chip",
"8: Address Error on MyRequest on EBUS",
"9: Data Error on MyData on EBUS",
"10: Internal Bus State is out of sync with A_SYNC"
};
#define IP19_CC_ERROR_MAX 11
char *ip21_cc_error[] = {
" 0:DB chip Parity error DB0", /* 0 */
" 1:DB chip Parity error DB1", /* 1 */
" 2:A Chip Addr Parity", /* 2 */
" 3:Time Out on MyReq on EBus Channel 0", /* 3 */
" 4:Time Out on MyReq on EBus Wback Channel ", /* 4 */
" 5:Addr Error on MyReq on EBus Channel 0", /* 5 */
" 6:Addr Error on MyReq on EBus Wback Channel ", /* 6 */
" 7:Data Sent Error Channel 0", /* 7 */
" 8:Data Sent Error Wback Channel ", /* 8 */
" 9:Data Receive Error", /* 9 */
"10:Intern Bus vs. A_SYNC", /* 10 */
"11:A Chip MyResponse Data Resources Time Out", /* 11 */
"12:A Chip MyIntrvention Data Resources Time Out",/* 12 */
"13:Parity Error on DB - CC shift lines", /* 13 */
};
#define IP21_CC_ERROR_MAX 14
/*
* The size of cache for each R4000 is in mega bytes.
* We will only attempt to dump the cache during bring up stage.
* The space allocated will be returned to the pool
*/
void
dump_local_cache(cachedump_t *cd)
{
if (cd == 0) /* is there space reserved? NO..*/
return;
/* do dump */
}
#ifdef CHIPREV_BUG
#define AREV3_ERRBITS (CC_ERROR_MYRES_TIMEOUT|CC_ERROR_MYINT_TIMEOUT)
#define AREV2_ERRBITS (CC_ERROR_MYREQ_TIMEOUT|AREV3_ERRBITS)
#endif
static void
ip19_cc_error_show(int slot, int pcpuid)
{
int vcpuid = ecbuf->ecfg_board[slot].eb_cpuarr[pcpuid].cpu_vpid;
uint error = errbuf->cpu[vcpuid].cc_ertoip;
int i, alevel;
if (error) {
if (ip_slot_print){
ip_slot_print=0;
ev_perr(SLOT_LVL, "%s in slot %d \n", IP19_CPUNAME, slot);
}
ev_perr(ASIC_LVL,"CC in %s Slot %d, cpu %d\n",
IP19_CPUNAME,slot, pcpuid);
ev_perr(REG_LVL, "CC ERTOIP Register: 0x%x \n", error);
for (i = 0; i < IP19_CC_ERROR_MAX; i++) {
if (error & (1L << i)){
#ifdef CHIPREV_BUG
if ((alevel==2)&&(AREV2_ERRBITS & (1 << i)))
ev_perr(BIT_LVL,"%s %s\n",ip19_cc_error[i],
AREV2_MSG(alevel));
else if((alevel==3)&&(AREV3_ERRBITS & (1<<i)))
ev_perr(BIT_LVL,"%s %s\n",ip19_cc_error[i],
AREV3_MSG(alevel));
else
#endif
ev_perr(BIT_LVL, "%s\n",ip19_cc_error[i]);
}
}
}
}
static void
ip21_cc_error_show(int slot, int pcpuid)
{
int vcpuid = ecbuf->ecfg_board[slot].eb_cpuarr[pcpuid].cpu_vpid;
uint error = errbuf->cpu[vcpuid].cc_ertoip;
int i;
#ifdef CHIPREV_BUG
int alevel;
#endif
if (error) {
if (ip_slot_print){
ip_slot_print=0;
ev_perr(SLOT_LVL, "Cpu Board in slot %d \n", slot);
}
#ifdef CHIPREV_BUG
alevel = EV_GETCONFIG_REG(slot, 0, EV_A_LEVEL);
#endif
#if IP21 && _KERNEL && !_STANDALONE
/*
* Print board rev number if non-zero so we can tell if
* hardware has D-chip error reporting fix.
*/
if (pdaindr[vcpuid].pda->p_dchip_err_hw)
ev_perr(ASIC_LVL,"CC in Cpu Slot %d, cpu %d (rev %d)\n",
slot, pcpuid, pdaindr[vcpuid].pda->p_dchip_err_hw);
else
#endif
ev_perr(ASIC_LVL,"CC in Cpu Slot %d, cpu %d\n",slot,pcpuid);
ev_perr(REG_LVL, "CC ERTOIP Register: 0x%x \n", error);
for (i = 0; i < IP21_CC_ERROR_MAX; i++) {
if (error & (1L << i)){
#ifdef CHIPREV_BUG
if ((alevel==2)&&(AREV2_ERRBITS & (1 << i)))
ev_perr(BIT_LVL,"%s %s\n",ip21_cc_error[i],
AREV2_MSG(alevel));
else if((alevel==3)&&(AREV3_ERRBITS & (1<<i)))
ev_perr(BIT_LVL,"%s %s\n",ip21_cc_error[i],
AREV3_MSG(alevel));
else
#endif
ev_perr(BIT_LVL, "%s\n",ip21_cc_error[i]);
}
}
}
#if _KERNEL && !_STANDALONE
if (pdaindr[vcpuid].pda->p_dchip_err_hw) {
unchar derr;
derr = pdaindr[vcpuid].pda->p_dchip_err_bits;
if (derr) {
ev_perr(REG_LVL, "D Chip Error Register: 0x%x\n", derr);
for (i = 0; i < 4; i++)
if (derr & (1L << i))
ev_perr(BIT_LVL,"%s\n",dchip_error[i]);
}
}
#endif /* _KERNEL */
}
/*
* cpuid gets its value from the PDAPAGE to be setup by the kernel
* In case of standalone, we call the function defined in libsk/ml/EVEREST.c
*/
#ifdef _STANDALONE
#ifdef cpuid
#undef cpuid
extern int cpuid();
#endif
#endif /*_STANDALONE*/
/*********************************** MC3 *************************************/
static void
mc3_sbe_analyze(int slot, int mbid, int *bank_num, int *simm_num)
{
mc3error_t *mc3err = &(errbuf->mc3[mbid]);
evbrdinfo_t *board = &(ecbuf->ecfg_board[slot]);
int bank, bank_base;
uint physaddr;
/* Establish "not found" return values */
*bank_num = MC3_NUM_BANKS;
*simm_num = MC3_SIMMS_PER_BANK;
if (mc3err->mem_error[0]) {
bank_base = 0;
physaddr = ((mc3err->erraddrhi[0] & 0xFF) << 24) |
(mc3err->erraddrlo[0] >> 8);
if (mc3err->syndrome0[0])
*simm_num = 0;
else
if (mc3err->syndrome1[0])
*simm_num = 1;
else
if (mc3err->syndrome2[0])
*simm_num = 2;
else
if (mc3err->syndrome3[0])
*simm_num = 3;
} else
if (mc3err->mem_error[1]) {
bank_base = 4;
physaddr = ((mc3err->erraddrhi[1] & 0xFF) << 24) |
(mc3err->erraddrlo[1] >> 8);
if (mc3err->syndrome0[1])
*simm_num = 0;
else
if (mc3err->syndrome1[1])
*simm_num = 1;
else
if (mc3err->syndrome2[1])
*simm_num = 2;
else
if (mc3err->syndrome3[1])
*simm_num = 3;
} else
return;
for (bank = bank_base + 3; bank >= bank_base; bank--) {
evbnkcfg_t *bnk = &(board->eb_mem.ebun_banks[bank]);
if (bnk->bnk_size == MC3_NOBANK)
continue;
if (physaddr >= bnk->bnk_bloc &&
physaddr < (bnk->bnk_bloc +
((mc3_type_bank_size[bnk->bnk_size]
* bnk->bnk_count) >> 8))) {
*bank_num = bank;
return;
}
}
}
void
mc3_error_show(int slot)
{
int mbid = ecbuf->ecfg_board[slot].eb_mem.eb_mc3num;
mc3error_t *mc3err = &(errbuf->mc3[mbid]);
uint error, i;
int bank_num, simm_num;
caddr_t vaddr;
if ((mc3err->ebus_error == 0) && (mc3err->mem_error[0] == 0) &&
(mc3err->mem_error[1] ==0))
return;
ev_perr(SLOT_LVL, "%s in slot %d \n", MEMNAME, slot);
error = mc3err->ebus_error;
if (error){
ev_perr(REG_LVL, "MA EBus Error register: 0x%x\n", error);
if (error & MC3_EBUS_ERROR_DATA)
ev_perr(BIT_LVL, "0: EBus Data Error\n");
if (error & MC3_EBUS_ERROR_ADDR)
#ifdef CHIPREV_BUG
ev_perr(BIT_LVL, "1: EBus Address Error %s\n", IAREV1_MSG);
#else
ev_perr(BIT_LVL, "1: EBus Address Error\n");
#endif
if (error & MC3_EBUS_ERROR_SENDER_DATA)
ev_perr(BIT_LVL, "2: My EBus Data Error\n");
if (error & MC3_EBUS_ERROR_SENDER_ADDR)
ev_perr(BIT_LVL, "3: My EBus Address Error\n");
}
/* Dump memory leaves information */
for (i=0; i < MC3_NUM_LEAVES; i++){
if ((error = mc3err->mem_error[i]) == 0)
continue;
ev_perr(REG_LVL,"MA Leaf %d Error Status Register: 0x%x\n",i,error);
if (error & MC3_MEM_ERROR_PWRT_MBE) {
mc3_sbe_analyze(slot,mbid,&bank_num,&simm_num);
ev_perr(BIT_LVL,
"0: PartialWrite Uncorrectable (Multiple Bit) Error\n");
}
if (error & MC3_MEM_ERROR_READ_MBE)
ev_perr(BIT_LVL,"1: Read Uncorrectable (Multiple Bit) Error\n");
if (error & MC3_MEM_ERROR_READ_SBE) {
mc3_sbe_analyze(slot,mbid,&bank_num,&simm_num);
ev_perr(BIT_LVL,
"2: Read correctable (SINGLE BIT) Error\n");
}
if (error & MC3_MEM_ERROR_MULT)
ev_perr(BIT_LVL, "3: Multiple occurence of Read correctable (SINGLE BIT) Error\n");
if (error && (mc3err->erraddrhi[i] || mc3err->erraddrlo[i])) {
ev_perr(REG_LVL, "MA Leaf %d Bad Memory Address: 0x%llx\n", i,
make_ll(mc3err->erraddrhi[i], mc3err->erraddrlo[i]));
fru_mc3_decode_addr((void (*)())ev_perr, mc3err->erraddrhi[i],
mc3err->erraddrlo[i], ecbuf);
}
if (mc3err->syndrome0[i])
ev_perr(REG_LVL,
"MA Leaf %d Memory Syndrome Register 0 (SIMM 0): 0x%x\n",
i, mc3err->syndrome0[i]);
if (mc3err->syndrome1[i])
ev_perr(REG_LVL,
"MA Leaf %d Memory Syndrome Register 1 (SIMM 1): 0x%x\n",
i, mc3err->syndrome1[i]);
if (mc3err->syndrome2[i])
ev_perr(REG_LVL,
"MA Leaf %d Memory Syndrome Register 2 (SIMM 2): 0x%x\n",
i, mc3err->syndrome2[i]);
if (mc3err->syndrome3[i])
ev_perr(REG_LVL,
"MA Leaf %d Memory Syndrome Register 3 (SIMM 3): 0x%x\n",
i, mc3err->syndrome3[i]);
}
}
/*
* There is an mc3 bug doing singlebit ECC correction on multiple-bank leaves
* with MA rev0 or rev1: the ECC error might be "scrubbed" by writing back to
* the wrong bank. A board-level workaround is to disable scrubbing and
* reporting of soft errors. If we do see a singlebit error interrupt, and if
* this looks like an old mc3 with multiple banks, then we want to return to
* the interrupt handler, which will summarily panic.
*/
#define MC3_SINGLEBIT_FATAL(_slot) \
mc3_ma_revision(_slot) < 3 && \
( (me->mem_error[0] && !mc3_single_bank_enabled(_slot,0)) \
|| (me->mem_error[1] && !mc3_single_bank_enabled(_slot,1)) )
#if STANDALONE
int ok_to_read_syndrome = 1;
static int panic_on_sbe = 1; /* XXX standalone panics, until MC3 SBE fix */
#else
int ok_to_read_syndrome = 0;
extern int panic_on_sbe;
#endif
/***************************************** IO4 *******************************/
char *io4_ibuserror[] = {
" 0: Sticky Error",
" 1: First Level Map Error for 2-Level Mapping",
" 2: 2-Level Address Map Response Command Error",
" 3: 1-Level Map Data Error",
" 4: 1-Level Address MapResponse Command Error",
" 5: IA Response Data Bad On IBUS",
" 6: DMA Read Response Command Error",
" 7: GFX Write Command Error",
" 8: PIO Read Command Error",
" 9: PIO Write Data Bad",
"10: PIO write Command Error",
"11: PIO ReadResponse Data Error",
"12: DMA Write Data Error (Data From IOA)",
"13: DMA Write Command Error from IOA",
"14: PIO Read Response Command Error from IOA",
"15: Command Error on OP from IOA",
};
#define IO4_IBUSERROR_MAX 16
char *io4_ebuserror[] = {
" 0: Sticky Error",
" 1: My DATA_ERROR Received",
" 2: ADDR_ERROR Detected",
" 3: Non Existent IOA",
" 4: Illegal PIO",
" 5: ADDR_HERE not asserted or My ADDR_ERROR Received",
" 6: EBUS_TIMEOUT Received",
" 7: Invalidate Dirty Exclusive Cache Line",
" 8: Read Resource Time Out",
" 9: DATA_ERROR Received"
};
#define IO4_EBUSERROR_MAX 10
#define IO4_EBUSERR_MASK ((1 << IO4_EBUSERROR_MAX) - 1)
char *io4_ebuserror_op[] = {
"51: Write Back",
"52: DMA Write",
"53: Read Exclusive",
"54: DMA Read",
"55: Address Map Match",
"56: Interrupt from IA"
};
/*
#define IO4_EBUSERROROP_MIN 51
#define IO4_EBUSERROROP_MAX 57
*/
#define IO4_EBUSOUTG_CMD 8
#define IO4_EBUS_CMD_SIZE 8
#define IO4_ORIGINATING_IOA 16
#define IO4_EBUSERROROP_MIN 19
#define IO4_EBUSERROROP_MAX 25
void
io4_error_show(int slot)
{
int window = ecbuf->ecfg_board[slot].eb_io.eb_winnum;
io4error_t *ie = &(errbuf->io4[window]);
int i, error;
if ((ie->ibus_error== 0) && (ie->ebus_error == 0))
return;
ev_perr(SLOT_LVL, "%s board in slot %d \n", IONAME, slot);
if (ie->ibus_error) {
ev_perr(REG_LVL,"IA IBUS Error Register: 0x%x\n", ie->ibus_error);
for (i = 0; i < IO4_IBUSERROR_MAX; i++) {
if (ie->ibus_error & (1L << i))
ev_perr(BIT_LVL, "%s\n",io4_ibuserror[i]);
}
if (i = ((ie->ibus_error >> IO4_IBUSERROR_MAX) & 0x7)){
error = ecbuf->ecfg_board[slot].eb_ioarr[i].ioa_type;
ev_perr(BIT_LVL, "18..16: IOA number of Transaction: %d (%s)\n",
i, ioa_name(error));
}
}
if (ie->ebus_error == 0)
return;
ev_perr(REG_LVL,"IA EBUS Error Register: 0x%x\n", ie->ebus_error);
for (i = 0; i < IO4_EBUSERROR_MAX; i++) {
if (ie->ebus_error & (1L << i))
#ifdef CHIPREV_BUG
if (IO4_EBUSERROR_ADDR_ERR & (1L << i))
ev_perr(BIT_LVL,"%s %s\n", io4_ebuserror[i],IAREV1_MSG);
else
#endif
ev_perr(BIT_LVL,"%s\n", io4_ebuserror[i]);
}
for (i=1, error = (ie->ebus_error >> IO4_EBUSERROR_PIOQFULL_SHIFT);
i < IO4_MAX_PADAPS; i++)
if (error & (1 << i))
ev_perr(BIT_LVL,"%d: PIO Queue full for Adapter %d\n",
(IO4_EBUSERROR_PIOQFULL_SHIFT + i), i);
/* Note: Ebus physical address is in two IO4 IA config registers */
/* Print the Ebus Address register only if proper bits are set in
* Ebus error register !!
*/
if (!(ie->ebus_error & IO4_EBUSERROR_MY_ADDR_ERR))
return;
if(ie->ebus_error2 || ie->ebus_error1)
ev_perr(REG_LVL,"IA Error EBus Address: 0x%llx\n",
make_ll((ie->ebus_error2&0xff), ie->ebus_error1));
if (i = ((ie->ebus_error2 >> IO4_EBUSOUTG_CMD) & 0x7f))
ev_perr(BIT_LVL,"%d..%d: EBus Outgoing Command: 0x%x\n",
(32+IO4_EBUSOUTG_CMD+IO4_EBUS_CMD_SIZE-1),
(32+IO4_EBUSOUTG_CMD), i);
if (i = ((ie->ebus_error2 >> IO4_ORIGINATING_IOA) & 0x7))
ev_perr(BIT_LVL, "%d: Originating IOA number = %d\n",
(32+IO4_ORIGINATING_IOA), i);
for (i = 0; i <= (IO4_EBUSERROROP_MAX-IO4_EBUSERROROP_MIN); i++) {
if (ie->ebus_error2 & (1 << (i + IO4_EBUSERROROP_MIN)))
ev_perr(BIT_LVL,"%s\n",io4_ebuserror_op[i]);
}
}
/**************************************** EPC ********************************/
static char *epc_ierr_ia[] = {
"no error",
"PIO Write Request Data",
"DMA Read Response Data",
"Unexpected DMA Read Response Data or Unexpected IGNT",
"Undetermined Command",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
};
static char *epc_ierr_np[] = {
"no error",
"PIO Write Request Data Error",
"GFX Write Request Data Error",
"DMA Read Response Data Error",
"Address Map Response Data Error",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
};
static char *epc_ierr_epc[] = {
"no error",
"PIO (to EPC) Read Response Command Error",
"PIO (to EPC) Read Response Data Error",
"DMA (Enet) Read Request Command Error",
"DMA (Enet) Write Request Command Error",
"DMA (Enet) Write Request Data Error",
"Interrupt Request Command Error",
"? not used ?",
"? not used ?",
"PIO (thru EPC) Read Response Command Error",
"PIO (thru EPC) Read Response Data Error",
"DMA (PPort) Read Request Command Error",
"DMA (Pport) Write Request Command Error",
"DMA (Pport) Write Request Data Error",
"? not used ?",
"? not used ?",
};
static char *epc_ierr[] = {
"16: Parity Error on IBusAD[15:0]",
"17: Parity Error on IBusAD[31:16]",
"18: Parity Error on IBusAD[47:32]",
"19: Parity Error on IBusAD[63:48]",
"20: Error Overrun",
"21: DMA Read Response 1 msec Timeout Error",
"22: EPC in PIO Drop Mode: Detected a PIO Write Data Error"
};
#define EPC_IERR_MIN 16
#define EPC_IERR_MAX 22
static void
epc_error_show(int slot, int padap)
{
int window = ecbuf->ecfg_board[slot].eb_io.eb_winnum;
ulong swin = SWIN_BASE(window, padap);
int vadap = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_virtid;
int x, i;
epcerror_t *epce = (epcerror_t*)&(errbuf->epc[vadap]);
if ((epce->ibus_error == 0) && (epce->ia_np_error2 == 0))
return;
ev_perr(ASIC_LVL,"EPC in %s slot %d adapter %d\n", IONAME, slot, padap);
if (epce->ibus_error == 0)
goto check_epc_np;
ev_perr(REG_LVL,"Ibus Error Register: 0x%x\n", epce->ibus_error);
x = EPC_IERR_IA(epce->ibus_error);
if (x)
ev_perr(BIT_LVL," 3..0: EPC Detected- %s Error from IA\n",
epc_ierr_ia[x]);
x = EPC_IERR_NP(epce->ibus_error);
i = EPC_IERR_NP_IOA(epce->ibus_error);
if (x)
ev_perr(BIT_LVL," 11..4: EPC Observed- %s from IA to IOA %d\n",
epc_ierr_np[x], i);
#ifdef NOTNEEDED
x = EPC_IERR_NP_IOA(epce->ibus_error);
if (x > 0 && x < 8)
ev_perr(BIT_LVL," 11..8: Bad IOA Destination: %d\n",x);
else if (x == 8)
ev_perr(BIT_LVL," 11..8: Bad IOA unknown due to Command Error\n");
else
ev_perr(BIT_LVL," 11..8: EPC reports Invalid IOA number: %x\n", x);
#endif
x = EPC_IERR_EPC(epce->ibus_error);
if (x) {
ev_perr(BIT_LVL,"15..12: EPC Sent- %s to IA\n",
epc_ierr_epc[x]);
}
for (i = EPC_IERR_MIN; i < EPC_IERR_MAX; i++) {
if (epce->ibus_error & (1L << i))
ev_perr(BIT_LVL,"%s\n", epc_ierr[i - EPC_IERR_MIN]);
}
check_epc_np:
if (epce->ia_np_error2)
ev_perr(REG_LVL,"IBus Opcode+Address: 0x%llx\n",
make_ll(epce->ia_np_error1, epce->ia_np_error2));
}
/************************************ FCHIP **********************************/
char *fchip_error[] = {
" 0: OverWrite",
" 1: Loopback Received",
" 2: Loopback Error",
" 3: F to IBus Command Error - non-interruptable",
" 4: PIO Read Response IBus Data Error - non-interruptable",
" 5: DMA Read Request Timeout Error",
" 6: Unknown IBus Command Error",
" 7: DMA Read Response Ibus Data Error",
" 8: DMA Write Data FCI Error",
" 9: PIO Read Response FCI Data Error",
"10: PIO/GFX Write IBus Data Error",
"11: Load Address Read FCI Error",
"12: DMA Write IBus Command Error",
"13: Address Map Request IBus Command Error",
"14: Interrupt IBus Command Error",
"15: Load Address Write FCI Error",
"16: Unknown FCI Command Error",
"17: Address Map Request Timeout Error",
"18: Address Map Response Data Error",
"19: PIO F Internal Write IBus Data Error",
"20: IBus Surprise",
"21: DMA write IBus data Error",
"22: System FCI Reset",
"23: Software FCI Reset",
"24: Master Reset",
"25: F Error FCI Reset",
"26: F Chip Reset In Progress",
"27: Drop PIO Write Mode",
"28: Drop DMA Write Mode",
"29: Fake DMA Read Mode"
};
#define FCHIP_ERROR_MAX 30
static char *fci_master[]={"VMECC", "FCG", "HIPPI", "NONE" };
#define FCHIP_IBUS_CMD_ERR ((1 << 3)|(1 << 12)|(1 << 13)|(1 << 14))
#define FCHIP_FCI_CMD_ERR (1<<16)
static void
fchip_error_show(int slot, int padap)
{
int window = ecbuf->ecfg_board[slot].eb_io.eb_winnum;
ulong swin = SWIN_BASE(window, padap);
int vadap = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_virtid;
int type = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_type;
fchiperror_t *fe;
int i;
if (type == IO4_ADAP_VMECC) {
fe = &(errbuf->fvmecc[vadap]);
i = 0;
} else if (type == IO4_ADAP_HIPPI) {
fe = &(errbuf->fio4hip[vadap]);
i = 2;
} else if (type == IO4_ADAP_FCG){
fe = &(errbuf->ffcg[vadap]);
i = 1;
}
else i = 3;
if (fe->error == 0)
return;
ev_perr(ASIC_LVL, "Fchip in %s slot %d adapter %d, FCI master: %s\n",
IONAME, slot, padap, fci_master[i]);
ev_perr(REG_LVL, "Error Status Register: 0x%x\n", fe->error);
for (i = 0; i < FCHIP_ERROR_MAX; i++) {
if (fe->error & (1L << i))
ev_perr(BIT_LVL, "%s\n", fchip_error[i]);
}
/* Qualify the Error bits whlie printing addresses */
if (fe->error & FCHIP_IBUS_CMD_ERR)
ev_perr(REG_LVL,"IBus Opcode+Address: 0x%llx\n",fe->ibus_addr);
if (fe->error & FCHIP_FCI_CMD_ERR)
ev_perr(REG_LVL,"FCI Error Command: 0x%x\n", fe->fci);
}
/************************************* FCG ***********************************/
void
fcg_error_show(int slot, int padap)
{
}
/************************************* DANG **********************************/
static char *dang_ierr_p[] = {
"IBus Data Parity Error",
"IBus Command Error",
"IBus Suprise",
"Bus Error for Command or Data",
"Bus Error on Command",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
};
static char *dang_ierr_md[] = {
"DMA Master transaction killed by PIO",
"IBus Read Timeout",
"Incoming IBus Data Parity Error ",
"Incoming GIO Bus Data Parity Error ",
"Incoming Control Block Parity Error ",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
};
static char *dang_ierr_sd[] = {
"Incoming IBus Data Parity Error",
"Incoming GIO Bus Command Parity Error",
"Incoming GIO Bus Byte Count Parity Error",
"Incoming GIO Bus Data Parity Error",
"IBus Read Timeout",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
"? not used ?",
};
/************************************* VMECC *********************************/
static char *vmecc_error[] = {
"0: VME Bus Error on PIO Write (interrupts)",
"1: VME Bus Error on PIO Read (no interrupt), return bad parity data",
"2: VME Slave Got Parity Error (no interrupt)",
"3: VME Acquisition Timeout by PIO Master (interrupt, set dropmode)",
"4: FCIDB Timeout (no interrupt)",
"5: FCI PIO Parity Error (interrupt)",
"6: Overrun among bit 0,1,3,4,5",
"7: in Dropmode"
};
#define VMECC_ERROR_MAX 8
static char *vmecc_errxtra_glvl[] = {
"0: VME backplane levels",
"1: VME backplane levels",
"2: VME backplane levels",
"3: VME backplane levels",
"4: DMA Engine",
"5: PIO Master",
"6: Interrupt Master",
"7: ???"
};
/*
* This table is indexed by a 4-bit integer composed of
* DS1:DS0:A01:~LWORD
* Data here is picked up from the VME specification document.
*/
static char *vme_data_strings[] = { /* ~DS1 ~DS0 A01 ~LWORD */
/* 0 */ "Address Only", /* H H x x */
/* 1 */ "Address Only",
/* 2 */ "Address Only",
/* 3 */ "Address Only",
/* 4 */ "D24: B1-3", /* H L L L */
/* 5 */ "D8: B1", /* H L L H */
/* 6 */ "Illegal",
/* 7 */ "D8: B3", /* H L H H */
/* 8 */ "D24: B0-2", /* L H L L */
/* 9 */ "D8: B0", /* L H L H */
/* a */ "Illegal",
/* b */ "D8: B2", /* L H H H */
/* c */ "Quadword", /* L L L L */
/* d */ "D16: B0-1", /* L L L H */
/* e */ "D16: B1-2", /* L L H L */
/* f */ "D16: B2-3" /* L L H H */
};
void
io4hip_error_show(int slot, int padap)
{
int i;
int window = ecbuf->ecfg_board[slot].eb_io.eb_winnum;
ulong swin = SWIN_BASE(window, padap);
int hadap = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_virtid; io4hiperror_t *he = &(errbuf->io4hip[hadap]);
he->error &= ~VMECC_ERROR_FCIDB_TO; /* Buggy bit in VMEcc */
if (he->error == 0)
return;
ev_perr(ASIC_LVL, "HIPPI in %s slot %d adapter %d \n",
IONAME, slot, padap, swin);
ev_perr(REG_LVL, "Error Cause Register: 0x%x\n", he->error);
for (i = 0; i < VMECC_ERROR_MAX; i++) {
if (he->error & (1L << i))
#ifdef CHIPREV_BUG
if ( VMECC_ERROR_FCIDB_TO & ( 1 << i))
ev_perr(BIT_LVL,"%s %s\n", vmecc_error[i],
VMECC_REV1(he->error));
else
#endif
ev_perr(BIT_LVL, "%s\n", vmecc_error[i]);
}
if (he->xtravme & VMECC_ERRXTRAVME_AVALID)
ev_perr(REG_LVL, "HIPPI-VMECC Address Error Register: 0x%x\n",
he->addrvme);
if (he->xtravme & VMECC_ERRXTRAVME_XVALID) {
ev_perr(REG_LVL,"Extra HIPPI-VMECC Bus signal register: 0x%x\n", he->xtravme);
ev_perr(BIT_LVL, "AM: 0x%x %s %s %s %s %s\n",
he->xtravme & VMECC_ERRXTRAVME_AM,
he->xtravme & VMECC_ERRXTRAVME_IACK ? "IACK" : "",
he->xtravme & VMECC_ERRXTRAVME_WR ? "Write" : "Read", he->xtravme & VMECC_ERRXTRAVME_AS ? "AS" : "",
he->xtravme & VMECC_ERRXTRAVME_DS0 ? "DS0" : "",
he->xtravme & VMECC_ERRXTRAVME_DS1 ? "DS1" : "",
he->xtravme & VMECC_ERRXTRAVME_LWORD ? "LWORD" : " ");
i = VMECC_ERRXTRAVME_GLVL(he->xtravme);
ev_perr(BIT_LVL, "VMECC-Grant-Level: %s\n",
vmecc_errxtra_glvl[i]);
}
}
#define VMECC_ERROR_MAX 8
void
vmecc_error_show(int slot, int padap)
{
int i;
int window = ecbuf->ecfg_board[slot].eb_io.eb_winnum;
ulong swin = SWIN_BASE(window, padap);
int vadap = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_virtid; vmeccerror_t *ve = &(errbuf->vmecc[vadap]);
ulong address_size;
ve->error &= ~VMECC_ERROR_FCIDB_TO; /* Buggy bit in VMEcc */
if (ve->error == 0)
return;
ev_perr(ASIC_LVL, "VMECC in %s slot %d adapter %d \n",
IONAME, slot, padap, swin);
ev_perr(REG_LVL, "Error Cause Register: 0x%x\n", ve->error);
for (i = 0; i < VMECC_ERROR_MAX; i++) {
if (ve->error & (1L << i))
/* VMECC_ERROR_FCIDB_TO gets set due to a bug. */
if (VMECC_ERROR_FCIDB_TO != ( 1 << i))
ev_perr(BIT_LVL, "%s\n", vmecc_error[i]);
}
address_size = ve->xtravme & VMECC_ERRXTRAVME_AM;
if (address_size < 8)
address_size = 64;
else if (address_size < 16)
address_size = 32;
else if ((address_size == 0x29) || (address_size == 0x2d))
address_size = 16;
else if ((address_size >= 0x38) && (address_size <= 0x3f))
address_size = 24;
else
address_size = 0;
if (ve->xtravme & VMECC_ERRXTRAVME_AVALID){
/* LSB is the ~LWORD VME signal.
* Use following table to define LSB of address
*
* ~LWORD ~DS0 ~DS1 LSB
* 0 1 1 0 => 32bit operation
* 1 1 0 0 => 8bit transfer
* 1 0 1 1 => 8bit odd byte transfer
* 1 1 1 0 => 16bit transfer
* So only cases where it needs to be zeroed is when ~DSO=1
*/
if ((ve->addrvme & 1) && /* ~LWORD = 1 */
(ve->xtravme & VMECC_ERRXTRAVME_XVALID) && /* XTRA Valid */
(ve->xtravme & VMECC_ERRXTRAVME_DS0))
ve->addrvme &= ~1; /* Clear LSB */
if (address_size == 16)
ve->addrvme &= 0xffff;
else if (address_size == 24)
ve->addrvme &= 0xffffff;
ev_perr(REG_LVL, "VME Address Error Register: 0x%x\n",
ve->addrvme);
}
if (ve->xtravme & VMECC_ERRXTRAVME_XVALID) {
int data_access =
(ve->xtravme & VMECC_ERRXTRAVME_DATA_MASK)
>> VMECC_ERRXTRAVME_DATA_SHIFT;
#define A01MASK 2
/* data_access is AS:DS1:DS0:LWORD. Strip AS, Move DS1:DS0
* left by one bit, and copy A01 in bit 1, and put ~LWORD in 0.
* This will make data_access as DS1:DS0:A01:~LWORD
*/
data_access = ((data_access & 0x6) << 1) |
(ve->addrvme & A01MASK) | (~data_access & 1);
ev_perr(REG_LVL,"Extra VME Bus signal register: 0x%x\n",
ve->xtravme);
ev_perr(BIT_LVL, "AM: 0x%x %s %s AS:%d DS0:%d DS1:%d LWORD:%d\n",
ve->xtravme & VMECC_ERRXTRAVME_AM,
ve->xtravme & VMECC_ERRXTRAVME_IACK ? "IACK" : "",
ve->xtravme & VMECC_ERRXTRAVME_WR ? "Write" : "Read", ve->xtravme & VMECC_ERRXTRAVME_AS ? 1 : 0,
ve->xtravme & VMECC_ERRXTRAVME_DS0 ? 1 : 0,
ve->xtravme & VMECC_ERRXTRAVME_DS1 ? 1 : 0,
ve->xtravme & VMECC_ERRXTRAVME_LWORD ? 1 : 0);
ev_perr(BIT_LVL, " (A%d%s/%s)\n",
address_size,
ve->xtravme & VMECC_ERRXTRAVME_AMSUPER ? "S" : "NP",
vme_data_strings[data_access]);
i = VMECC_ERRXTRAVME_GLVL(ve->xtravme);
ev_perr(BIT_LVL, "VME-Grant-Level: %s\n",
vmecc_errxtra_glvl[i]);
}
}
/* All three dang error registers are currently 5 bits */
#define DANG_ERRBIT_MIN 0
#define DANG_ERRBIT_MAX 5
void
dang_error_show(int slot, int padap)
{
int window = ecbuf->ecfg_board[slot].eb_io.eb_winnum;
ulong swin = SWIN_BASE(window, padap);
int vadap = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_virtid;
dangerror_t *de = (dangerror_t*)&(errbuf->dang[vadap]);
int inuse = 0;
long long *adptr = (long long *)swin;
int i;
inuse = de->p_error | de->md_error | de->sd_error | de->md_cmplt;
if (inuse)
return;
ev_perr(ASIC_LVL,"DANG in %s slot %d adapter %d\n", IONAME, slot, padap);
if (de->p_error) {
ev_perr(REG_LVL,"PIO Error Register: 0x%x\n", de->p_error);
for (i = DANG_ERRBIT_MIN; i < DANG_ERRBIT_MAX; i++) {
if (de->p_error & (1 << i))
ev_perr(BIT_LVL,"%s\n", dang_ierr_p[i - EPC_IERR_MIN]);
}
}
if (de->md_error) {
ev_perr(REG_LVL,"Master DMA Error Register: 0x%x\n", de->md_error);
for (i = DANG_ERRBIT_MIN; i < DANG_ERRBIT_MAX; i++) {
if (de->md_error & (1 << i))
ev_perr(BIT_LVL,"%s\n", dang_ierr_md[i - EPC_IERR_MIN]);
}
}
if (de->sd_error) {
ev_perr(REG_LVL,"Slave DMA Error Register: 0x%x\n", de->md_error);
for (i = DANG_ERRBIT_MIN; i < DANG_ERRBIT_MAX; i++) {
if (de->sd_error & (1 << i))
ev_perr(BIT_LVL,"%s\n", dang_ierr_md[i - EPC_IERR_MIN]);
}
}
if (de->md_cmplt)
ev_perr(REG_LVL,"Master DMA Complete Register: 0x%x\n",de->md_cmplt);
}
/************************************ SCSI ***********************************/
#define S1_CSR_ERR_MASK (S1_SC_ERR_MASK(0)|S1_SC_ERR_MASK(1)|S1_SC_ERR_MASK(2))
#define S1_IBUSERR_MASK (S1_IERR_ERR_ALL(0) | S1_IERR_ERR_ALL(1) | S1_IERR_ERR_ALL(2))
static char *s1_csr_errors[] = {
/* First 6 bits are command bits */
"6 : Parity Error in SCSI data DMA channel 0",
"7 : Parity Error in SCSI data DMA channel 1",
"8 : Parity Error in SCSI data DMA channel 2",
"9 : PIO Read Error on SCSI Bus 0",
"10: PIO Read Error on SCSI Bus 1",
"11: PIO Read Error on SCSI Bus 2",
"12: PIO Write data Overrun due to PIO FIFO Full",
"13: Missing Write data during PIO write",
"14: PIO with an invalid address",
"15: PIO Drop mode active"
};
static char *s1_ibus_errors[] = {
"",
" 1: Error on Incoming Data to S1",
" 2: Error on Incoming command to S1",
" 3: Error on Outgoing data from S1",
" 4: Error on Outgoing command from S1",
" 5: Error in DMA translation",
" 6: Error in Channel 0",
" 7: Error in Channel 1",
" 8: Error in Channel 2",
" 9: Surprising DMA Read/Ibus Grant",
"10: PIO Read response data Error",
"11: PIO Write request data Error",
"12: DMA Read response data Error",
"13: Interrupt Error"
/* Bits 14-26 indicate overrun of errors for bits 1-13 */
};
void
scsi_error_show(int slot, int padap)
{
int window = ecbuf->ecfg_board[slot].eb_io.eb_winnum;
ulong swin = SWIN_BASE(window, padap);
int vadap = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_virtid;
s1error_t *s1 = (s1error_t*)&(errbuf->s1[vadap]);
int type = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_type;
if ((s1->csr & (S1_CSR_ERR_MASK | S1_SC_IBUS_ERR)) == 0)
return;
ev_perr(ASIC_LVL, "%s in %s slot %d adapter %d\n",
(type == IO4_ADAP_SCIP ? "SCIP": "S1"), IONAME, slot, padap);
if (s1->csr){
ev_perr(REG_LVL, "S1 Command Status Register: 0x%x\n", s1->csr);
for (vadap=6; vadap < 16; vadap++)
if (s1->csr & (1 << vadap))
ev_perr(BIT_LVL, "%s\n",s1_csr_errors[vadap - 6]);
}
if ((s1->csr & S1_SC_IBUS_ERR) && (s1->ibus_error & S1_IBUSERR_MASK)){
ev_perr(REG_LVL, "S1 Ibus error Register: 0x%x\n", s1->ibus_error);
for (vadap=1; vadap < 14; vadap++)
if (s1->ibus_error & (1 << vadap))
ev_perr(BIT_LVL, "%s %s \n", s1_ibus_errors[vadap],
(s1->ibus_error & (1<<(vadap+14)) ? "- multiple occurances" : ""));
ev_perr(REG_LVL, "IBus Opcode+Address: 0x%llx\n",
make_ll(s1->ierr_loghi, s1->ierr_loglo));
}
}
/*****************************************************************************/
/*
int window = ecbuf->ecfg_board[slot].eb_io.eb_winnum;
ulong swin = SWIN_BASE(window, padap);
int vadap = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_virtid;
int type = ecbuf->ecfg_board[slot].eb_ioarr[padap].ioa_type;
*/
/* Array used to find the actual size of a particular
* memory bank. The size is in blocks of 256 bytes, since
* the memory banks base address drops the least significant
* 8 bits to fit the base addr in one word.
*/
unsigned int MemSizes[] = {
0x10000, /* 0 = 16 megs */
0x40000, /* 1 = 64 megs */
0x80000, /* 2 = 128 megs */
0x100000, /* 3 = 256 megs */
0x100000, /* 4 = 256 megs */
0x400000, /* 5 = 1024 megs */
0x400000, /* 6 = 1024 megs */
0x0 /* 7 = no SIMM */
};
/* in_bank returns 1 if the given address is in the same leaf position
* as the bank whose interleave factor and position are provided
* and the address is in the correct range.
*/
int
in_bank(uint bloc, uint offset, uint base_bloc, uint i_factor,
uint i_position, uint simm_type)
{
uint end_bloc;
uint cache_line_num;
end_bloc = base_bloc + MemSizes[simm_type] * MC3_INTERLEAV(i_factor);
#ifdef DECODE_DEBUG
printf("bloc == 0x%x, base = %x, if = %d, ip = %d, type = %d ",
bloc, base_bloc, i_factor, i_position, simm_type);
#endif
/* If it's out of range, return 0 */
if (bloc < base_bloc || bloc >= end_bloc) {
#ifdef DECODE_DEBUG
printf("Not here.\n");
/* Nope. */
#endif
return 0;
}
#ifdef DECODE_DEBUG
printf("End == %x\n", end_bloc);
#endif
/* Is this bank the right position in the "interleave"?
* See if the "block" address falls in _our_ interleave position
*/
cache_line_num = (bloc << 1) + (offset >> 7);
if ((cache_line_num % MC3_INTERLEAV(i_factor)) == i_position) {
#ifdef DECODE_DEBUG
printf("This bank!\n");
#endif
/* We're the one */
return 1;
}
#ifdef DECODE_DEBUG
printf("In range, wrong IP.\n");
#endif
/* Nope. */
return 0;
}
void
fru_mc3_decode_addr(void (*print)(), unsigned int paddrhi, unsigned int paddrlo,
evcfginfo_t *ec)
{
uint slot, leaf, bank, simm;
uint bloc_num;
bloc_num = (paddrlo >> 8) | ((paddrhi & 0xff) << 24);
if (addr2sbs(bloc_num, paddrlo & 0xff, &slot, &bank, &simm, ec)) {
if ((__psint_t)print == (__psint_t)ev_perr)
ev_perr(REG_LVL, " Unable to decode address\n");
else
print(" - Unable to decode address\n");
} else {
leaf = bank >> 2;
bank &= 3;
if ((__psint_t)print == (__psint_t)ev_perr)
ev_perr(REG_LVL, " Slot %d, leaf %d, bank %d (%c)\n",
slot, leaf, bank,
bank_letter(leaf, bank));
else
print("slot %d, leaf %d, bank %d (%c)\n",
slot, leaf, bank,
bank_letter(leaf, bank));
}
}