1
0
Files
irix-657m-src/irix/cmd/icrash_old/lib/libfru/fru_decode.c
2022-09-29 17:59:04 +03:00

257 lines
5.7 KiB
C

/*
* fru_decode.c-
*
* This file decodes the various structures returned by the FRU analysis
* code and prints the results.
*
*/
#include "evfru.h"
/*
*Structure for a FRU entry. FRU is really a misnomer here. What we're
* saying is that these are things that can fail whether field replaceable
* or not.
*/
typedef struct fru_table_entry_s {
short fru_id;
char *fru_name;
} fru_table_entry_t;
/*
* Here's the "FRU" table. Each "FRU" identifier is made up of a class
* (e.g. board, bus ASIC, IO adapter) and an instance. Check out evfru.h
* for more details.
*/
static fru_table_entry_t fru_table[37] = {
{FRU_NONE, "None"},
{FRU_SOFTWARE, "Software"},
{FRU_IPBOARD, "PROCESSOR BOARD"},
{FRU_A, "A CHIP"},
{FRU_D, "D CHIP"},
{FRU_CPU, "CPU"},
{FRU_CACHE, "CACHE"},
{FRU_CC, "CC CHIP"},
{FRU_BBCC, "BBCC CHIP"},
{FRU_TAGRAM, "TAG RAM"},
{FRU_GCACHE, "GCACHE"},
{FRU_DB, "DB CHIP"},
{FRU_BUSTAG, "BUS TAG"},
{FRU_FPU, "FPU"},
{FRU_MCBOARD, "MEMORY BOARD"},
{FRU_MA, "MA CHIP"},
{FRU_MD, "MD CHIP"},
{FRU_BANK, "MEMORY BANK"},
{FRU_MD, "MEMORY SIMM"},
{FRU_IOBOARD, "IO4 BOARD"},
{FRU_IA, "IA CHIP"},
{FRU_ID, "ID CHIP"},
{FRU_MAPRAM, "IO4 MAP RAM"},
{FRU_EPC, "EPC CHIP"},
{FRU_S1, "S1 CHIP"},
{FRU_SCIP, "SCIP CHIP"},
{FRU_F, "F CHIP"},
{FRU_VMECC, "VMECC on VCAM"},
{FRU_FCG, "FCG CHIP"},
{FRU_DANG, "DANG CHIP"},
{FRU_HIPPI, "HIPPI ADAPTER"},
{FRU_ANIOA, "IO ADAPTERS"},
{FRU_VMEDEV, "VME DEVICE or DRIVER SOFTWARE"},
{FRU_SCACHE, "SECONDARY CACHE SIMMS"},
{FRU_PCACHE, "PRIMARY CACHE"},
{FRU_SYSAD, "SysAd Bus or Other CPUs"},
{-1, (char *)0}
};
/*
* These are the confidence levels we use to call out errors.
* The percentages are somewhat arbitrary. We use them only to
* present something field engineers will be familiar with.
*/
char *confidence_strings[NUM_CONFIDENCE_LEVELS] = {
"Not involved",
"10%", /* Witnessed error */
"30%", /* Possible */
"40%", /* Possible */
"70%", /* Probable */
"90%", /* Definite */
"95%" /* Exact pattern match */
};
/* Print out a particular diagnosed element. */
/* ARGSUSED */
static void print_fru(fru_element_t *element, fru_table_entry_t *entry,
evcfginfo_t *ec)
/* ec will be used to determine what's actually a FRU */
{
int class;
class = element->unit_type & FRU_CLASSMASK;
if (element->unit_type & FRUF_SOFTWARE)
if (!fru_ignore_sw)
class = FRUC_SOFTWARE;
else
FRU_PRINTF("Likely SOFTWARE: ");
/* Use class to determine print format. */
switch (class) {
case FRUC_NONE:
FRU_PRINTF("No error found");
break;
case FRUC_SOFTWARE:
FRU_PRINTF("Error caused by SOFTWARE");
break;
case FRUC_BOARD:
FRU_PRINTF("%s", entry->fru_name);
break;
case FRUC_EBUS_ASIC:
FRU_PRINTF("Integral component (%s)",
entry->fru_name);
break;
case FRUC_MEM_BANK:
if (element->unit_num != NO_UNIT) {
int leaf = element->unit_num >> 2;
int bank = element->unit_num & 3;
FRU_PRINTF("%s: leaf %d bank %d (%c)",
entry->fru_name,
leaf, bank,
bank_letter(leaf, bank));
} else {
FRU_PRINTF("%s: Can't identify bank",
entry->fru_name);
}
break;
case FRUC_IOA:
FRU_PRINTF("%s (IO adapter %d)", entry->fru_name,
element->unit_num);
break;
case FRUC_FCIDEV:
FRU_PRINTF("%s attached to F chip IO adapter %d",
entry->fru_name, element->unit_num);
break;
case FRUC_CPUSLICE:
FRU_PRINTF("CPU slice %d (%s)",
element->unit_num, entry->fru_name);
break;
case FRUC_ONEOF:
FRU_PRINTF("ONE OF THE %s", entry->fru_name);
break;
case FRUC_VMEDEV:
FRU_PRINTF("%s, VME bus adapter %d, address 0x%llx",
entry->fru_name, element->unit_num,
element->unit_address);
break;
default:
FRU_PRINTF("Unknown FRU class (0x%x) %s", class,
entry->fru_name);
break;
}
}
/* Decode a FRU identifier and get its hum,an readable name. */
void decode_fru(fru_element_t *element, evcfginfo_t *ec)
{
int i;
for (i = 0; fru_table[i].fru_name; i++) {
if (fru_table[i].fru_id == (FRU_MASK & element->unit_type)) {
print_fru(element, &(fru_table[i]), ec);
return;
}
}
FRU_PRINTF("Can't decode FRU (0x%x)", element->unit_type);
return;
}
/* Convert a board type to a string. */
char *type_to_string(int board)
{
switch(board) {
case EVTYPE_IP19:
return "IP19";
case EVTYPE_IP21:
return "IP21";
case EVTYPE_MC3:
return "MC3";
case EVTYPE_IO4:
return "IO4";
}
return "Unknown";
}
/* Print which board a display applies to. */
/* ARGSUSED */
void decode_board(whatswrong_t *ww, evcfginfo_t *ec)
/* ec will be used to determine what's actually a FRU */
{
/* Don't print the board if we think it's a software error. */
if ((FRU_CLASS(ww->src.unit_type) == FRUC_SOFTWARE) ||
(!fru_ignore_sw && (ww->src.unit_type & FRUF_SOFTWARE))) {
FRU_PRINTF(FRU_INDENT "++ ");
return;
}
if (FRU_CLASS(ww->src.unit_type) == FRUC_BOARD)
FRU_PRINTF(FRU_INDENT "++ ");
else
FRU_PRINTF(FRU_INDENT "++ on the ");
FRU_PRINTF("%s board in slot %d: ",
type_to_string(ww->board_type),
ww->slot_num);
}
/*
* Display the information stored in a whatswrong_t - That is, all information
* about devices connected to a particular Ebus slot.
*/
void display_whatswrong(whatswrong_t *ww, evcfginfo_t *ec)
{
FRU_PRINTF(FRU_INDENT "++ ");
if (ww->src.unit_type && ww->dest.unit_type) {
decode_fru(&(ww->src), ec);
FRU_PRINTF("\n" FRU_INDENT "++ and/or ");
decode_fru(&(ww->dest), ec);
FRU_PRINTF("\n");
} else {
if (ww->src.unit_type)
decode_fru(&(ww->src), ec);
else if (ww->dest.unit_type)
decode_fru(&(ww->dest), ec);
FRU_PRINTF("\n");
}
decode_board(ww, ec);
FRU_PRINTF("%s confidence.\n",
confidence_strings[ww->confidence]);
return;
}