1
0
Files
irix-657m-src/irix/cmd/sysctlrd/inventory.c
2022-09-29 17:59:04 +03:00

461 lines
12 KiB
C

/***********************************************************************\
* File: inventory.c *
* *
* This file contains the code for manipulating the hardware *
* inventory information. It includes routines which read and *
* write the NVRAM inventory as well as code for checking the *
* validity of the current hardware state. *
* *
\***********************************************************************/
#include <sys/types.h>
#include <sys/cpu.h>
#include <syslog.h>
#include <stdio.h>
#include <sys/EVEREST/evconfig.h>
#include <sys/EVEREST/everest.h>
/*
* Forward declarations.
*/
static void check_ip(evbrdinfo_t*, int*);
static void check_mc3(evbrdinfo_t*, int*);
static void check_io4(evbrdinfo_t*, int*);
static char* bank_name(unchar);
static char bank_pos(int);
char* board_name(unchar);
char* ioa_name(unchar, unchar);
char* evdiag_msg(unchar);
static char *bank_letter = "ACEGBDFH";
/*
* check_inventory(evcfginfo_t *evconfig)
* Looks for eccentricities in the configuration information
* and prints appropriate warnings. It uses the following
* rules:
* 1). If there is a difference between the type and inventory
* fields, a warning is displayed. In particular, if something
* appeared to have disappeared, the system screams.
*
* 2). If the enable field is 0, the types match, and diagval is
* non-zero, the board failed some kind of diagnostic and a
* warning is printed.
*
* 3). If the enable field is zero, the types match, and diagval is
* non-zero, the board was disabled in software for some reason.
*
* 4). If diagval is non-zero, but the enable bit is set, a non-fatal
* problem was detected.
*
*/
void
check_inventory(evcfginfo_t *evconfig)
{
uint slot;
evbrdinfo_t *brd;
int changed = 0;
/* Now iterate through all the slots looking for problems. */
for (slot = 0; slot < EV_MAX_SLOTS; slot++) {
brd = &(evconfig->ecfg_board[slot]);
/* If there is a difference between the type and inventory value,
* do appropriate checking.
*/
if (brd->eb_type == EVTYPE_EMPTY) {
if (brd->eb_inventory != EVTYPE_EMPTY) {
syslog(LOG_NOTICE,
"*** Slot %d previously contained an %s board but is empty",
slot, board_name(brd->eb_inventory));
changed = 1;
}
} else {
/* If a slot isn't empty, we check to see if it contains
* the same board as it used to.
*/
if (brd->eb_type != brd->eb_inventory) {
syslog(LOG_NOTICE,
"*** Slot %d previously contained an %s board but now an %s board.\n",
slot, board_name(brd->eb_inventory),
board_name(brd->eb_type));
changed = 1;
}
/* Check for problems with diagnostics.
*/
if (brd->eb_diagval != EVDIAG_PASSED) {
syslog(LOG_ERR, "*** The %s board in slot %d failed diagnostics.\n",
board_name(brd->eb_type), brd->eb_slot);
syslog(LOG_ERR, "*** Reason: %s\n", evdiag_msg(brd->eb_diagval));
changed = 1;
continue;
}
/* Check to see if the board is still enabled. If it is,
* we also check the units for information.
*/
if (!brd->eb_enabled) {
syslog(LOG_NOTICE, "*** The %s board in slot %d is DISABLED\n",
board_name(brd->eb_type), brd->eb_slot);
changed = 1;
} else {
if (brd->eb_type == brd->eb_inventory) {
switch (EVCLASS(brd->eb_type)) {
case EVCLASS_CPU:
check_ip(brd, &changed);
break;
case EVCLASS_MEM:
check_mc3(brd, &changed);
break;
case EVCLASS_IO:
check_io4(brd, &changed);
break;
default:
break;
}
}
}
} /* end if/else */
} /* end for(slot) loop */
}
static void
check_ip(evbrdinfo_t *brd, int *changed)
{
int unit;
evcpucfg_t *cpu;
for (unit = 0; unit < 4; unit++) {
cpu = &brd->eb_cpuarr[unit];
/* Skip empty slices */
if (cpu->cpu_diagval == EVDIAG_NOTFOUND) {
if (cpu->cpu_inventory != EVDIAG_NOTFOUND) {
syslog(LOG_NOTICE,
"*** Slice %d on the %s in slot %d isn't visible\n",
unit, board_name(brd->eb_type), brd->eb_slot);
*changed = 1;
}
continue;
}
if (cpu->cpu_diagval != EVDIAG_PASSED) {
syslog(LOG_ERR, "*** Slice %d on the %s in slot %d failed diagnostics\n",
unit, board_name(brd->eb_type), brd->eb_slot);
syslog(LOG_ERR, "*** Reason: %s\n", evdiag_msg(cpu->cpu_diagval));
*changed = 1;
}
/*
* The IP21 prom has a bug that causes it to mark the CPU slices that
* don't exit on all IP21 boards (slices 2 & 3) as populated.
* This hack keeps us from printing bogus DISABLED messages.
*/
if ((brd->eb_type == EVTYPE_IP21) && (unit >= 2))
continue;
if (!cpu->cpu_enable)
syslog(LOG_NOTICE, "*** Slice %d on the %s in slot %d is DISABLED\n",
unit, board_name(brd->eb_type), brd->eb_slot);
}
}
static void
check_mc3(evbrdinfo_t *brd, int *changed)
{
int unit;
evbnkcfg_t *bnk;
for (unit = 0; unit < 8; unit++) {
bnk = &brd->eb_banks[unit];
/* Skip empty banks */
if (bnk->bnk_size == MC3_NOBANK && bnk->bnk_inventory == MC3_NOBANK)
continue;
if (bnk->bnk_size != bnk->bnk_inventory) {
syslog(LOG_NOTICE, "*** Bank %c on the MC3 in slot %d has changed.\n",
bank_pos(unit), brd->eb_slot);
syslog(LOG_NOTICE, " Bank used to be %s and now is %s\n",
bank_name(bnk->bnk_inventory), bank_name(bnk->bnk_size));
*changed = 1;
}
if (bnk->bnk_diagval != EVDIAG_PASSED) {
syslog(LOG_ERR, "*** Bank %c on the MC3 in slot %d failed diagnostics.\n",
bank_pos(unit), brd->eb_slot);
syslog(LOG_ERR, "*** Reason: %s\n", evdiag_msg(bnk->bnk_diagval));
*changed = 1;
}
if (!bnk->bnk_enable)
syslog(LOG_ERR, "*** Bank %c on the MC3 in slot %d is DISABLED.\n",
bank_pos(unit), brd->eb_slot);
}
}
static int
ioa_changed(int old_ioa, int new_ioa)
{
if (old_ioa == new_ioa)
return 0;
/* Unix changes the F Chip IOA into the sub ioa. To this code,
* all F chips must be equal.
*/
if ((old_ioa == IO4_ADAP_FCHIP) &&
((new_ioa == IO4_ADAP_FCG) || ((new_ioa == IO4_ADAP_VMECC))))
return 0;
else
return 1;
}
static void
check_io4(evbrdinfo_t *brd, int *changed)
{
int unit;
evioacfg_t *ioa;
for (unit = 1; unit < 8; unit++) {
ioa = &brd->eb_ioarr[unit];
/* Skip empty IOAS */
if (ioa->ioa_type == IO4_ADAP_NULL &&
ioa->ioa_inventory == IO4_ADAP_NULL)
continue;
if (ioa_changed(ioa->ioa_inventory, ioa->ioa_type)) {
syslog(LOG_NOTICE, "*** IOA %d on the IO4 in slot %d has changed\n",
unit, brd->eb_slot);
syslog(LOG_NOTICE, "*** IOA used to be %s and now is %s\n",
ioa_name(ioa->ioa_inventory, 0),
ioa_name(ioa->ioa_type, ioa->ioa_subtype));
*changed = 1;
}
if (ioa->ioa_diagval != EVDIAG_PASSED) {
syslog(LOG_ERR,
"*** The %s at ioa %d on the IO4 in slot %d failed diags.\n",
ioa_name(ioa->ioa_type, ioa->ioa_subtype), unit,
brd->eb_slot);
syslog(LOG_ERR, "*** Reason: %s\n", evdiag_msg(ioa->ioa_diagval));
*changed = 1;
}
/* We can't display messages about disabled F chips. If there's
* nothing connected, Unix disables teh F chip automatically.
* If there's something else connected, the info is accurate.
*/
if (!ioa->ioa_enable && (ioa->ioa_type != IO4_ADAP_FCHIP))
syslog(LOG_NOTICE,
"*** The %s at ioa %d on the IO4 in slot %d is DISABLED\n",
ioa_name(ioa->ioa_type, ioa->ioa_subtype), unit,
brd->eb_slot);
}
}
/*
* bank_name()
* Returns a string corresponding to the bank name.
*/
static char*
bank_name(unchar type)
{
switch(type) {
case 0: return "16 Megabytes";
case 1: return "64 Megabytes";
case 2: return "128 Megabytes";
case 3: return "256 Megabytes";
case 4: return "256 Megabytes";
case 5: return "1 Gigabyte";
case 6: return "1 Gigabyte";
case 7: return "empty";
default: return "Unknown";
}
}
/*
* bank_pos()
* Returns the letter corresponding to a bank's unit number.
*/
char
bank_pos(int unit)
{
if (unit < 0 || unit > 7)
return '?';
else
return bank_letter[unit];
}
/*
* Include the diagnostic value strings.
*/
#include <sys/EVEREST/diagval_strs.i>
/*
* board_name()
* Returns a string pointer to the name of the board whose
* type value was passed.
*/
char*
board_name(unchar type)
{
switch(type) {
case EVTYPE_WEIRDCPU: return "Unknown CPU-type";
case EVTYPE_IP19: return "IP19";
case EVTYPE_IP21: return "IP21";
case EVTYPE_IP25: return "IP25";
case EVTYPE_WEIRDMEM: return "Unknown Memory-type";
case EVTYPE_MC3: return "MC3";
case EVTYPE_WEIRDIO: return "Unknown IO-type";
case EVTYPE_IO4: return "IO4";
case EVTYPE_UNKNOWN: return "Unknown";
case EVTYPE_EMPTY: return "Empty";
default: return "Unrecognized boardtype";
}
}
/*
* ioa_name
* Returns a string pointer to the name of the I/O adapter
* whose type value is passed.
*/
char*
ioa_name(unchar type, unchar subtype)
{
switch (type) {
case IO4_ADAP_SCSI: return "S1 SCSI controller";
case IO4_ADAP_EPC: return "EPC Peripheral controller";
case IO4_ADAP_FCHIP:
switch (subtype) {
case IO4_ADAP_FCG: return "FCI Graphics adapter";
case IO4_ADAP_VMECC: return "VME adapter";
default: return "Flat cable interconnect";
}
case IO4_ADAP_NULL: return "Empty";
default: return "Unknown adapter type";
}
}
/*
* evdiag_msg()
* Returns a pointer to a user-readable diagval message.
*/
char*
evdiag_msg(unchar diagcode)
{
int num_entries;
int i;
num_entries = sizeof(diagval_map) / sizeof(diagval_t);
for (i = 0; i < num_entries; i++) {
if (diagval_map[i].dv_code == diagcode)
return diagval_map[i].dv_msg;
}
return "Unknown diagnostic code";
}
int check_ccrev(evcfginfo_t *evconfig)
{
int slot, slice;
int enabled = -1;
int minccrev = 0xffff;
int maxccrev = 0;
int error = 0;
evbrdinfo_t *brd;
char cpulist[36 * 4];
char one_cpu[5];
for (slot = 0; slot < EV_MAX_SLOTS; slot++) {
/* Look at all enabled CPUs. */
brd = &evconfig->ecfg_board[slot];
if ((brd->eb_type & EVCLASS_MASK) != EVCLASS_CPU)
continue;
/* At this point, we're an enabled CPU */
if (enabled == -1) {
enabled = (brd->eb_cpu.eb_brdflags &
EV_BFLAG_PIGGYBACK);
} else if (enabled != (brd->eb_cpu.eb_brdflags &
EV_BFLAG_PIGGYBACK)) {
error++;
}
if (brd->eb_cpu.eb_ccrev < minccrev)
minccrev = brd->eb_cpu.eb_ccrev;
if (brd->eb_cpu.eb_ccrev > maxccrev)
maxccrev = brd->eb_cpu.eb_ccrev;
}
if (minccrev == 0) {
printf("WARNING: The IO4 Flash PROM on this system is out of date.\n");
return -2;
}
if (enabled == -1) {
printf("ERROR: No CPUs found.\n");
return -1;
}
/* Report status */
if (!error) {
printf("Piggyback reads are currently %s.\n",
enabled ? "enabled" : "disabled");
if (!enabled && (minccrev < 2) && (maxccrev >= 2)) {
printf(" Some processors are capable of piggyback reads but are not enabled");
}
return error;
}
printf("ERROR: Piggyback reads are enabled on some CPUs but not others.\n");
for (enabled = 0; enabled <= 1; enabled++) {
cpulist[0] = '\0';
for (slot = 0; slot < EV_MAX_SLOTS; slot++) {
brd = &evconfig->ecfg_board[slot];
if ((brd->eb_type & EVCLASS_MASK) != EVCLASS_CPU)
continue;
for (slice = 0; slice < EV_MAX_CPUS_BOARD; slice++) {
if (!brd->eb_cpuarr[slice].cpu_enable ||
(brd->eb_cpuarr[slice].cpu_diagval == EVDIAG_NOTFOUND))
continue;
/* At this point, we're an enabled CPU */
if (enabled == (brd->eb_cpu.eb_brdflags &
EV_BFLAG_PIGGYBACK)) {
sprintf(one_cpu, "%d ", brd->eb_cpuarr[slice].cpu_vpid);
strcat(cpulist, one_cpu);
}
}
}
printf(" %s on CPUs %s\n", enabled ? "Disabled" : "Enabled",
cpulist);
}
return error;
}