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

409 lines
8.8 KiB
C

/*
* fru_mc3.c-
*
* This file contains the code to analyze an MC3 board, the memory,
* and the ASICs connected to it.
*
*/
#include "evfru.h" /* FRU analyzer definitions */
#include <sys/EVEREST/mc3.h> /* MA chip */
#include "fru_pattern.h"
int addr2sbs(uint bloc, uint offset, uint *slot, uint *bank, uint *simm,
evcfginfo_t *ec);
int extract_bank(evcfginfo_t *ec, unsigned int addrlo, unsigned int addrhi);
void check_mc3(evbrdinfo_t *eb, everror_t *ee, everror_ext_t *eex,
whatswrong_t *ww, evcfginfo_t *ec)
{
int vid;
int leaf;
int e_error, l_error;
fru_element_t src, dest;
#ifdef DEBUG
if (fru_debug)
FRU_PRINTF("Check MC3\n");
#endif
src.unit_type = FRU_MCBOARD;
src.unit_num = NO_UNIT;
vid = eb->eb_mem.eb_mc3num;
#ifdef DEBUG
if (fru_debug)
FRU_PRINTF(" VID %d\n", vid);
#endif
e_error = ee->mc3[vid].ebus_error;
#ifdef DEBUG
if (fru_debug)
FRU_PRINTF("ebus error == 0x%x\n", e_error);
#endif
conditional_update(ww, WITNESS, e_error,
MC3_EBUS_ERROR_ADDR | MC3_EBUS_ERROR_DATA,
&src, NO_ELEM);
conditional_update(ww, PROBABLE, e_error,
MC3_EBUS_ERROR_SENDER_ADDR,
&src, NO_ELEM);
conditional_update(ww, POSSIBLE, e_error,
MC3_EBUS_ERROR_SENDER_DATA,
&src, NO_ELEM);
/*
* If MC3_EBUS_ERROR_DATA is set, we may just be propagating bad
* data.
*/
if ((e_error & (MC3_EBUS_ERROR_DATA | MC3_EBUS_ERROR_SENDER_DATA)) ==
MC3_EBUS_ERROR_SENDER_DATA)
update_confidence(ww, PROBABLE, &src, NO_ELEM);
src.unit_type = FRU_BANK;
for (leaf = 0; leaf < 2; leaf++) {
int bank;
#ifdef DEBUG
if (fru_debug)
FRU_PRINTF(" Leaf %d\n", leaf);
#endif
l_error = ee->mc3[vid].mem_error[leaf];
if (!l_error)
continue;
#ifdef DEBUG
if (fru_debug)
FRU_PRINTF(" error == 0x%x\n", l_error);
#endif
bank = extract_bank(ec, ee->mc3[vid].erraddrlo[leaf],
ee->mc3[vid].erraddrhi[leaf]);
/* If we can't decode the bank, blame the board! */
if (bank == NO_UNIT) {
src.unit_type = FRU_MCBOARD;
} else {
src.unit_num = bank;
}
/*
* Single bit errors don't panic the machine so we'll
* only flag this as POSSIBLE.
*/
conditional_update(ww, POSSIBLE, l_error,
MC3_MEM_ERROR_READ_SBE, &src, NO_ELEM);
if (e_error & MC3_EBUS_ERROR_SENDER_DATA) {
int level;
/*
* If MC3_EBUS_ERROR_DATA is set, we may just be
* propagating * bad data. We can't definitively claim
* to be the source of the error.
*/
if (e_error & MC3_EBUS_ERROR_DATA)
level = POSSIBLE;
else
level = DEFINITE;
conditional_update(ww, level,
l_error, MC3_MEM_ERROR_MULT
| MC3_MEM_ERROR_READ_MBE
| MC3_MEM_ERROR_PWRT_MBE, &src, NO_ELEM);
} else {
/* If _neither_ MC3_EBUS_ERROR_DATA nor MC3_EBUS_ERROR_DATA
* is set, we likely have an MA problem.
*/
dest = src;
src.unit_type = FRU_MCBOARD;
/*
* Since the board doesn't admit to causing the problem,
* flag this as POSSIBLE. For all we know, the
* MC3_EBUS_ERROR_DATA bit should also be set.
*/
conditional_update(ww, PROBABLE,
l_error, MC3_MEM_ERROR_MULT
| MC3_MEM_ERROR_READ_MBE
| MC3_MEM_ERROR_PWRT_MBE, &src, &dest);
}
}
#ifdef DEBUG
if (fru_debug)
display_whatswrong(ww, ec);
#endif
return;
}
int
addr2sbs(uint bloc, uint offset, uint *slot, uint *bank, uint *simm,
evcfginfo_t *ec)
{
int s, l, b;
short enable, simm_type, i_factor, i_position;
uint base_bloc;
evbrdinfo_t *brd;
evbnkcfg_t *bnk;
for (s = 0; s < EV_MAX_SLOTS; s++) {
brd = &(ec->ecfg_board[s]);
if (brd->eb_type == EVTYPE_MC3) {
#ifdef DECODE_DEBUG
FRU_PRINTF("Board %d is memory\n", s);
#endif
/* It's a memory board, do leaf loop */
for (l = 0; l < MC3_NUM_LEAVES; l++) {
#ifdef DECODE_DEBUG
FRU_PRINTF("leaf %d\n", l);
#endif
for (b = 0; b < MC3_BANKS_PER_LEAF; b++) {
bnk = &(brd->eb_banks[l * MC3_BANKS_PER_LEAF + b]);
#ifdef DECODE_DEBUG
FRU_PRINTF("bank %d\n", b);
#endif
/* Nonzero means enabled */
enable = bnk->bnk_enable;
#ifdef DECODE_DEBUG
FRU_PRINTF("Enable = %x\n", enable);
#endif
simm_type = bnk->bnk_size;
#ifdef DECODE_DEBUG
FRU_PRINTF("Type = %x\n", simm_type);
#endif
i_factor = bnk->bnk_if;
i_position = bnk->bnk_ip;
base_bloc = bnk->bnk_bloc;
#ifdef DECODE_DEBUG
FRU_PRINTF("Base bloc = %x\n", base_bloc);
#endif
if (enable && in_bank(bloc, offset, base_bloc, i_factor,
i_position, simm_type)) {
/* We have a winner! */
*slot = s;
/* Banks are in order within the slots */
#ifdef DECODE_DEBUG
FRU_PRINTF("Winner is slot %d, leaf %d, bank %d\n",
s, l, b);
#endif
*bank = b + (l * MC3_BANKS_PER_LEAF);
return 0;
#ifdef DECODE_DEBUG
} else {
FRU_PRINTF("Disabled!\n");
#endif
} /* if enable... */
}
}
} /* If mem_slots... */
} /* for s */
return -1;
}
int extract_bank(evcfginfo_t *ec, unsigned int addrlo, unsigned int addrhi)
{
long long address;
unsigned int bloc_num, slot, bank, simm;
#ifdef DECODE_DEBUG
FRU_PRINTF("addrhi == 0x%x, addrlo == 0x%x\n", addrhi, addrlo);
#endif
address = (long long)addrhi << 32LL;
address |= addrlo;
#ifdef DECODE_DEBUG
FRU_PRINTF("address == 0x%llx\n", address);
#endif
bloc_num = (addrlo >> 8) | ((addrhi & 0xff) << 24);
#ifdef DECODE_DEBUG
FRU_PRINTF("bloc_num = 0x%x\n", bloc_num);
#endif
if (addr2sbs(bloc_num, address & 0xff, &slot, &bank, &simm, ec))
bank = NO_UNIT;
#ifdef DECODE_DEBUG
FRU_PRINTF("Bank == %d\n");
#endif
#ifdef DEBUG
if (fru_debug)
FRU_PRINTF(" address = 0x%llx\n", address);
#endif
return bank;
}
char
bank_letter(uint leaf, uint bank) {
if ((leaf > 1) || (bank > 3))
return '?';
return 'A' + leaf + (bank << 1);
}
#ifdef FRU_PATTERN_MATCHER
int match_mc3leaf(fru_entry_t **token, char vid, everror_t *ee, evcfginfo_t *ec,
whatswrong_t *ww, fru_case_t *case_ptr)
{
fru_entry_t *cur_token;
char fru = 0;
char match = 1;
char leaf;
short bank;
for (leaf = 0; leaf < 2; leaf++) {
cur_token = *token;
fru = 0;
for (cur_token = next_token(cur_token);
!is_control_token(cur_token);
cur_token = next_token(cur_token)) {
if (fru |= is_fru_token(cur_token)) {
#ifdef DEBUG
if (fru_debug)
FRU_PRINTF("FRU would be MC3 leaf\n");
#endif
continue;
}
} /* for !is_control_token() */
if (fru && match) {
/*
* If someone else claimed the error already, we don't know the
* FRU unit.
*/
if (ww->src.unit_type == FRU_BANK) {
bank = NO_UNIT;
} else {
bank = extract_bank(ec, ee->mc3[vid].erraddrlo[leaf],
ee->mc3[vid].erraddrhi[leaf]);
}
update_pattern(ww, case_ptr, FRU_BANK, bank);
}
if (cur_token->entry_type != ENDSUBUNIT)
FRU_PRINTF("Token should have been ENDSUBUNIT!\n");
else
/* Consume ENDSUBUNIT token. */
cur_token = next_token(cur_token);
}
*token = cur_token;
if (match && fru)
return FRU_MATCH_FRU;
else if (match)
return FRU_MATCH_YES;
else
return FRU_MATCH_NO;
}
int match_mc3board(fru_entry_t **token, everror_t *ee, evcfginfo_t *ec,
whatswrong_t *diag, fru_case_t *case_ptr)
{
evbrdinfo_t *eb;
int slot;
int match = 1;
fru_entry_t *cur_token;
char vid;
char fru = 0;
char exists = 0;
whatswrong_t *ww;
for (slot = 1; slot < EV_MAX_SLOTS; slot++) {
eb=&(ec->ecfg_board[slot]);
if (eb->eb_type == EVTYPE_MC3) {
ww = diag + slot;
cur_token = *token;
vid = eb->eb_mem.eb_mc3num;
exists = 1;
for (cur_token = next_token(cur_token);
!is_control_token(cur_token);
cur_token = next_token(cur_token)) {
if (fru |= is_fru_token(cur_token)) {
#ifdef DEBUG
if (fru_debug)
FRU_PRINTF("FRU would be MC3 _BOARD_ (MA?)\n");
#endif
update_pattern(ww, case_ptr, FRU_MCBOARD, NO_UNIT);
continue;
}
if (cur_token->entry_type != MA_EBUSERR) {
FRU_PRINTF("Bad token. Should be MA_EBUSERR, ENDBOARD, or"
"BEGINSUBUNIT\n");
return -1;
}
if ((ee->mc3[vid].ebus_error & cur_token->mask) !=
cur_token->value) {
match = 0;
/* return ? */
}
}
if (cur_token->entry_type == ENDBOARD) {
if (cur_token->value != EVTYPE_MC3) {
FRU_PRINTF("Bad board type on ENDBOARD\n");
return -1;
}
} else if (cur_token->entry_type != BEGINSUBUNIT) {
FRU_PRINTF("Bad control token. Should be ENDBOARD or"
" BEGINSUBUNIT\n");
return -1;
} else { /* IS BEGINSUBUNIT */
if (cur_token->value != SUBUNIT_LEAF) {
FRU_PRINTF("Bad subunit type.\n");
}
if (match_mc3leaf(&cur_token, vid, ee, ec, &diag[slot],
case_ptr)) {
}
}
}
}
*token = find_board_end(cur_token);
if (match && exists)
return 1;
else
return 0;
}
#endif /* FRU_PATTERN_MATCHER */