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

981 lines
24 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/sbd.h>
#include <sys/cpu.h>
#include <sys/loaddrs.h>
#include <libsc.h>
#include <libsk.h>
#include <sys/EVEREST/evconfig.h>
#include <sys/EVEREST/evmp.h>
#include <sys/EVEREST/nvram.h>
/*
* Useful macros and definitions.
*/
#define INV_OFFBOARD(_b) \
(NVOFF_INVENTORY + ((_b) * INV_SIZE))
#define INV_OFFUNIT(_b, _u) \
(INV_OFFBOARD(_b) + INV_UNITOFF + ((_u) * INV_UNITSIZE))
#define INV_READ(_b, _f) \
get_nvreg(INV_OFFBOARD(_b) + (_f))
#define INV_READU(_b, _u, _f) \
get_nvreg(INV_OFFUNIT(_b, _u) + (_f))
#define INV_WRITE(_b, _f, _v) \
set_nvreg(INV_OFFBOARD(_b) + (_f), (_v))
#define INV_WRITEU(_b, _u, _f, _v) \
set_nvreg(INV_OFFUNIT(_b, _u) + (_f), (_v))
/*
* External and Forward declarations
*/
char nvchecksum(void);
char *ioa_name(unchar,unchar);
char *board_name(unchar);
char *evdiag_msg(unchar);
void sysctlr_message(char *);
extern void update_checksum(void);
/*
* Forward declarations.
*/
static void check_ip(evbrdinfo_t*, int*, char *, int);
static void check_mc3(evbrdinfo_t*, int*);
static void check_io4(evbrdinfo_t*, int*);
static int parse_args(int, char**, int);
static void switch_ip(int, char*, int, char*, int);
static void switch_mc3(int, char*, int);
static void switch_io4(int, char*, int);
static char* bank_name(unchar);
static char bank_pos(int);
static char *bank_letter = "ACEGBDFH";
/*
* write_inventory()
* Writes the contents of the inventory fields in EVCFGINFO
* into the NVRAM. If the reinitialize parameter is non-zero,
* this routine will actually try to reinitialize the NVRAM
* to rational default values (in particular, we only touch the
* enable fields if reinitialize is set). Otherwise, it will
* just transfer the fields into the NVRAM from the evconfig data
* structure.
*/
int
write_inventory(unsigned reinitialize)
{
uint slot, u;
evbrdinfo_t *brd;
int check;
/* Invalidate the inventory just in case we crash while writing it */
if (set_nvreg(NVOFF_INVENT_VALID, 0) == -1) {
printf("Error in write_inventory: could not invalidate inventory\n");
return -1;
}
for (slot = 0; slot < EV_MAX_SLOTS; slot++) {
brd = &(EVCFGINFO->ecfg_board[slot]);
/* Unify the inventory and type values */
brd->eb_inventory = brd->eb_type;
check = 0;
check += INV_WRITE(slot, INV_TYPE, brd->eb_type);
check += INV_WRITE(slot, INV_REV, brd->eb_rev);
check += INV_WRITE(slot, INV_DIAGVAL, 0);
/* Only touch the ENABLE values if we're reinitializing.
* In all other cases the enable and disable commands will
* take care of it.
*/
if (reinitialize) {
check += INV_WRITE(slot, INV_ENABLE, 1);
}
if (check != 0) {
printf("Error in write_inventory: could not update board %d\n",
slot);
}
/* Now do board-type specific writes */
for (u = 0; u < INV_MAXUNITS; u++) {
unchar type = 0;
switch (brd->eb_type & EVCLASS_MASK) {
case EVCLASS_CPU:
if (u < EV_MAX_CPUS_BOARD) {
evcpucfg_t *cpu = &brd->eb_cpuarr[u];
type = cpu->cpu_inventory = cpu->cpu_diagval;
} else
type = 0;
break;
case EVCLASS_MEM:
type = brd->eb_banks[u].bnk_size;
brd->eb_banks[u].bnk_inventory = brd->eb_banks[u].bnk_size;
break;
case EVCLASS_IO:
type = brd->eb_ioarr[u].ioa_type;
brd->eb_ioarr[u].ioa_inventory = brd->eb_ioarr[u].ioa_type;
break;
}
check = 0;
check += INV_WRITEU(slot, u, INVU_TYPE, type);
check += INV_WRITEU(slot, u, INVU_DIAGVAL, 0);
if (reinitialize)
check += INV_WRITEU(slot, u, INVU_ENABLE, 1);
if (check != 0) {
printf("write_inventory error: update brd %d, unit %d failed\n",
slot, u);
return -1;
}
} /* end for(unit) loop */
} /* end for(slot) loop */
/* Validate the Inventory data */
if (set_nvreg(NVOFF_INVENT_VALID, INVENT_VALID) == -1) {
printf("Error in write_inventory: could not revalidate inventory\n");
return -1;
}
/* Rechecksum the NVRAM */
update_checksum();
return 0;
}
/*
* check_inventory()
* 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()
{
uint slot;
evbrdinfo_t *brd;
int changed = 0;
p_clear();
p_printf("Checking hardware inventory...\n");
sysctlr_message("Checking inventory...");
/* Don't bother running this code if it doesn't look like the
* inventory is valid. Instead, reinitialize the inventory.
*/
if (get_nvreg(NVOFF_INVENT_VALID) != INVENT_VALID) {
printf("WARNING: hardware inventory is invalid. Reinitializing...\n");
write_inventory(1);
}
/* Now iterate through all the slots looking for problems. */
for (slot = 0; slot < EV_MAX_SLOTS; slot++) {
brd = &(EVCFGINFO->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) {
printf("*** slot %d previously contained an %s board\n",
slot, board_name(brd->eb_inventory));
printf(" but now appears to be empty.\n");
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) {
printf("*** slot %d previously contained an %s board\n",
slot, board_name(brd->eb_inventory));
printf(" but now contains an %s board.\n",
board_name(brd->eb_type));
changed = 1;
}
/* Check for problems with diagnostics.
*/
if (brd->eb_diagval != EVDIAG_PASSED) {
printf("*** The %s board in slot %d failed diagnostics.\n",
board_name(brd->eb_type), brd->eb_slot);
printf("*** 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) {
printf("*** The %s board in slot %d is DISABLED\n",
board_name(brd->eb_type), brd->eb_slot);
/*
* changed = 1;
* Donot prompt for <CR> if a board was explicitly disabled
*/
} else {
if (brd->eb_type == brd->eb_inventory) {
switch (brd->eb_type) {
case EVTYPE_IP19:
check_ip(brd, &changed, "IP19", 4);
break;
case EVTYPE_IP21:
check_ip(brd, &changed, "IP21", 2);
break;
case EVTYPE_IP25:
check_ip(brd, &changed, "IP25", 2);
break;
case EVTYPE_MC3:
check_mc3(brd, &changed);
break;
case EVTYPE_IO4:
check_io4(brd, &changed);
break;
default:
break;
}
}
}
} /* end if/else */
} /* end for(slot) loop */
/* Wait for a carriage return */
if (changed) {
char *nonstop = getenv("nonstop");
if (nonstop && *nonstop != '1') {
char buff[128];
p_cursoff();
p_printf("\nPress <Enter> to continue");
gets(buff);
}
}
}
static void
check_ip(evbrdinfo_t *brd, int *changed, char *name, int maxcpus)
{
int unit;
evcpucfg_t *cpu;
for (unit = 0; unit < maxcpus; unit++) {
cpu = &brd->eb_cpuarr[unit];
/* Skip empty slices */
if (cpu->cpu_diagval == EVDIAG_NOTFOUND) {
if (cpu->cpu_inventory != EVDIAG_NOTFOUND) {
printf("***\tSlice %d on the %s in slot %d isn't visible\n",
unit, name, brd->eb_slot);
*changed = 1;
}
continue;
} else if (((EVCFGINFO->ecfg_snum[0] == 'S') &&
(EVCFGINFO->ecfg_snum[1] == '9')) &&
(cpu->cpu_vpid != cpuid())) {
/*
* Do not allow more that 1 CPU on a memphis system.
*/
sysctlr_message("*** Invalid CPU conf\n");
printf("***\t Invalid CPU Configuration\n");
for ( ; ; )
;
}
if (cpu->cpu_diagval != EVDIAG_PASSED) {
printf("***\tSlice %d on the %s in slot %d failed diagnostics\n",
unit, name, brd->eb_slot);
printf("***\t Reason: %s\n", evdiag_msg(cpu->cpu_diagval));
*changed = 1;
}
if (!cpu->cpu_enable)
printf("***\tSlice %d on the %s in slot %d is DISABLED\n",
unit, name, 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) {
printf("***\tBank %c on the MC3 in slot %d has changed.\n",
bank_pos(unit), brd->eb_slot);
printf("***\t 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) {
printf("***\tBank %c on the MC3 in slot %d failed diagnostics.\n",
bank_pos(unit), brd->eb_slot);
printf("***\t Reason: %s\n", evdiag_msg(bnk->bnk_diagval));
*changed = 1;
}
if (!bnk->bnk_enable)
printf("***\tBank %c on the MC3 in slot %d is DISABLED.\n",
bank_pos(unit), brd->eb_slot);
}
}
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->ioa_type != ioa->ioa_inventory) {
printf("***\t IOA %d on the IO4 in slot %d has changed\n",
unit, brd->eb_slot);
printf("***\t 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) {
printf("***\tThe %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);
printf("***\t Reason: %s\n", evdiag_msg(ioa->ioa_diagval));
*changed = 1;
}
if (!ioa->ioa_enable)
printf("***\tThe %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];
}
/*
* enable_cmd()
* Syntax: enable [-R] [-y] [slot] [unit]
* Enables a board or unit in a specified slot. The -R switch
* causes the command to enable recursively; enable -R 1 will
* try to enable all the units of the board in slot 1. The -y
* says to answer all interactive queries with a yes.
*/
#define ENABLE 1
#define DISABLE 0
int
enable_cmd(int argc, char **argv)
{
/* Just return if the command completed successfully */
if (parse_args(argc, argv, 1) == 0) {
update_checksum();
return 0;
}
/* If the command failed, dump out the syntax information */
printf("Enable syntax: enable SLOT [UNIT]\n");
printf(" The enable command allows one to re-enable a slot or unit\n");
printf(" on a slot which has previously been disabled. Re-enabling\n");
printf(" does not take effect immediately; the machine must be\n");
printf(" rebooted.\n");
return 0;
}
/*
* disable_cmd()
* Syntax: disable [-R] [-y] [slot] [unit]
* Disables a board or unit in a specified slot. The -R switch
* causes the command to disable recursively; enable -R 1 will
* try to disable all the units of the board in slot 1. The -y
* says to answer all interactively queries with a yes.
*/
int
disable_cmd(int argc, char **argv)
{
/* Just return if the command completed successfully */
if (parse_args(argc, argv, 0) == 0) {
update_checksum();
return 0;
}
/* If the command failed, dump out the syntax information */
printf("Disable syntax: disable SLOT [UNIT]\n");
printf(" The disable command allows one to disable a board or unit\n");
printf(" on a board. Disabling a board or board unit does not take\n");
printf(" effect until the machine is rebooted.\n");
return 0;
}
static int
parse_args(int argc, char **argv, int swtch)
{
char *slotstr; /* Pointer to slot string */
char *unitstr; /* Pointer to unit string - if exists*/
int slot = -1; /* Actual slot number */
evbrdinfo_t *brd; /* Pointer to board to be disabled */
switch (argc) {
case 1:
printf("Error: A slot number must be given as a parameter.\n");
return -1;
case 2:
slotstr = argv[1];
unitstr = NULL;
break;
case 3:
slotstr = argv[1];
unitstr = argv[2];
break;
default:
printf("Error: Too many arguments.\n");
return -1;
}
/* Scan out slot number */
if (*atob(slotstr, &slot)) {
printf("Error: '%s' is not a valid slot number\n", slotstr);
return -1;
}
if (slot < 0 || slot > EV_MAX_SLOTS) {
printf("Error: slot value must be between 1 and %d\n", slot,
EV_MAX_SLOTS);
return 0;
}
/* Skip empty boards in the system */
brd = BOARD(slot);
if (brd->eb_type == EVTYPE_EMPTY) {
printf("Slot %d is empty. Cannot %s it.\n",
slot, ((swtch == ENABLE) ? "enable" : "disable"));
return 0;
}
switch (brd->eb_type) {
case EVTYPE_IP19:
switch_ip(slot, unitstr, swtch, "IP19", 4);
break;
case EVTYPE_IP21:
switch_ip(slot, unitstr, swtch, "IP21", 2);
break;
case EVTYPE_IP25:
switch_ip(slot, unitstr, swtch, "IP25", 4);
break;
case EVTYPE_MC3:
switch_mc3(slot, unitstr, swtch);
break;
case EVTYPE_IO4:
switch_io4(slot, unitstr, swtch);
break;
default:
printf("WARNING: Unknown board type in slot %d\n", slot);
break;
}
return 0;
}
static void
switch_ip(int slot, char *unitstr, int swtch, char *brdname, int maxcpus)
{
evbrdinfo_t *brd = BOARD(slot);
evcpucfg_t *cpu;
int unit, startunit, endunit;
/* Convert the unit string into a slice number */
if (unitstr != NULL) {
if (*atob(unitstr, &unit)) {
printf("Error: slice should be an integral value, 0<=slice<=%d\n",
maxcpus);
return;
}
} else {
unit = -1;
}
if (unit == -1) {
if (swtch == ENABLE && brd->eb_diagval != EVDIAG_PASSED) {
printf("*** Warning: The %s board in slot %d failed diagnostics\n",
brdname, slot);
printf("*** Reason: %s\n", evdiag_msg(brd->eb_diagval));
}
INV_WRITE(slot, INV_ENABLE, swtch);
brd->eb_enabled = swtch;
startunit = 0;
endunit = maxcpus;
} else if (unit >= maxcpus) {
printf("Error: %s boards have only %d processor slices.\n",
brdname, maxcpus);
return;
} else {
startunit = unit;
endunit = unit+1;
/* If enabling a part of the board, enable the board too */
if ((swtch == ENABLE) && (INV_READ(slot, INV_ENABLE) != ENABLE)){
INV_WRITE(slot, INV_ENABLE, swtch);
brd->eb_enabled = swtch;
}
}
for (unit = startunit; unit < endunit; unit++) {
cpu = &(BOARD(slot)->eb_cpuarr[unit]);
/* Check to see whether the given slice actually exists */
if (cpu->cpu_diagval == EVDIAG_NOTFOUND)
printf("WARNING: Slice %d of the %s in slot %d isn't present\n",
unit, brdname, slot);
if (swtch == DISABLE) {
unsigned spnum =
load_double_lo((long long *)EV_SPNUM) & EV_SPNUM_MASK;
if (spnum != MPCONF[cpu->cpu_vpid].phys_id &&
cpu->cpu_diagval != EVDIAG_NOTFOUND &&
cpu->cpu_enable) {
launch_slave(cpu->cpu_vpid, (void (*)(int))EV_PROM_FLASHLEDS,
0, 0, 0, 0);
}
cpu->cpu_enable = 0;
} else {
if (cpu->cpu_diagval != EVDIAG_NOTFOUND &&
cpu->cpu_diagval != EVDIAG_PASSED) {
printf("Slice %d on %s slot %d failed diagnostics\n",
unit, brdname, slot);
} else {
cpu->cpu_enable = 1;
}
}
INV_WRITEU(slot, unit, INVU_ENABLE, swtch);
printf("%s slice %d on the %s board in slot %d\n",
((swtch == ENABLE) ? "Enabled" : "Disabled"), unit, brdname, slot);
}
printf("Changes will take effect when the machine is power-cycled.\n");
}
static void
switch_mc3(int slot, char *unitstr, int swtch)
{
evbrdinfo_t *brd = BOARD(slot);
evbnkcfg_t *bnk;
int startunit, endunit;
int unit;
/* Convert the bank letter into an actual bank number */
if (unitstr != NULL) {
char uc = *unitstr & 0x5f;
for (unit = 0; unit < 8; unit++)
if (uc == bank_letter[unit])
break;
if (unit >= 8) {
printf("Error: Banks are specified as a letter (A through H)\n");
return;
}
} else unit = -1;
if (unit == -1) {
if (swtch == ENABLE && brd->eb_diagval != EVDIAG_PASSED)
printf("Warning: The MC3 board in slot %d failed diagnostics\n",
slot);
INV_WRITE(slot, INV_ENABLE, swtch);
brd->eb_enabled = swtch;
startunit = 0;
endunit = MC3_NUM_BANKS;
} else if (unit > 7) {
printf("MC3 boards only have 8 banks.\n");
return;
} else {
startunit = unit;
endunit = unit + 1;
/* If enabling a part of the board, enable the board too */
if ((swtch == ENABLE) && (INV_READ(slot, INV_ENABLE) != ENABLE)){
INV_WRITE(slot, INV_ENABLE, swtch);
brd->eb_enabled = swtch;
}
}
for (unit = startunit; unit < endunit; unit++) {
bnk = &(BOARD(slot)->eb_banks[unit]);
if (bnk->bnk_size == MC3_NOBANK)
printf("NOTE: Bank %c on the MC3 board in slot %d is empty.\n",
bank_pos(unit), slot);
if (swtch == DISABLE) {
bnk->bnk_enable = 0;
} else {
if (bnk->bnk_size != MC3_NOBANK &&
bnk->bnk_diagval != EVDIAG_PASSED) {
printf("Bank %c on the MC3 board in slot %d failed diags.\n",
bank_pos(unit), slot);
} else {
bnk->bnk_enable = 1;
}
}
INV_WRITEU(slot, unit, INVU_ENABLE, swtch);
printf("%s bank %c of the MC3 board in slot %d\n",
((swtch == ENABLE) ? "Enabled" : "Disabled"), bank_pos(unit),
slot);
}
printf("Changes will take effect when the machine is reset.\n");
}
static void
switch_io4(int slot, char *unitstr, int swtch)
{
evbrdinfo_t *brd = BOARD(slot);
evioacfg_t *ioa;
int startunit, endunit;
int unit;
/* Convert the unit string into an IOA */
if (unitstr != NULL) {
if (*atob(unitstr, &unit)) {
printf("The IOA must be a number between 1 and 7\n");
return;
}
} else
unit = -1;
if (unit == -1) {
if (swtch == ENABLE && brd->eb_diagval != EVDIAG_PASSED)
printf("Warning: The IO4 board in slot %d failed diagnostics\n",
slot);
INV_WRITE(slot, INV_ENABLE, swtch);
brd->eb_enabled = swtch;
startunit = 1;
endunit = 7;
} else if (unit == 0 || unit > 7) {
printf("Error: Illegal IOA number: %d\n", unit);
return;
} else {
if (brd->eb_ioarr[unit].ioa_type == IO4_ADAP_NULL)
printf("WARNING: IBUS slot %d on the IO4 in slot %d is empty.\n",
unit, slot);
startunit = unit;
endunit = unit + 1;
/* If enabling a part of the board, enable the board too */
if ((swtch == ENABLE) && (INV_READ(slot, INV_ENABLE) != ENABLE)){
INV_WRITE(slot, INV_ENABLE, swtch);
brd->eb_enabled = swtch;
}
}
for (unit = startunit; unit < endunit; unit++) {
ioa = &(BOARD(slot)->eb_ioarr[unit]);
if (swtch == DISABLE) {
ioa->ioa_enable = 0;
} else {
if (ioa->ioa_type != IO4_ADAP_NULL &&
ioa->ioa_diagval != EVDIAG_PASSED) {
printf("The %s in IOA %d on the IO4 in slot %d failed diags.\n",
ioa_name(ioa->ioa_type, ioa->ioa_subtype), unit, slot);
} else {
ioa->ioa_enable = swtch;
}
}
INV_WRITEU(slot, unit, INVU_ENABLE, swtch);
printf("%s IO adapter %d (%s) on the IO4 in slot %d\n",
((swtch == ENABLE) ? "Enabled" : "Disabled"),
unit, ioa_name(ioa->ioa_type, ioa->ioa_subtype), slot);
}
printf("Changes will take effect when the machine is reset.\n");
}
/*
* The update command rewrites the current state of the machine
* into the inventory nvram. It ignores the enable/disable hardware
* state, since in many cases the diagnostics may have only temporarily
* set the disable bits.
*/
/*ARGSUSED*/
int
update_cmd(int argc, char *argv)
{
(void)write_inventory(1);
return 0;
}
/*
* get_cpuinfo()
* Returns a pointer to the cpu cfg structure given
* the physical ID of the cpu.
*/
static evcpucfg_t*
get_cpuinfo(int phys_id)
{
unsigned slot = (phys_id & EV_SLOTNUM_MASK) >> EV_SLOTNUM_SHFT;
unsigned proc = (phys_id & EV_PROCNUM_MASK) >> EV_PROCNUM_SHFT;
evbrdinfo_t *brd;
if (slot >= EV_MAX_SLOTS) {
printf("get_cpuinfo: Bogus slotnum %d\n", slot);
return NULL;
}
if (proc > EV_MAX_CPUS_BOARD) {
printf("get_cpuinfo: Bogus procnum %d\n", proc);
return NULL;
}
brd = &(EVCFGINFO->ecfg_board[slot]);
if (EVCLASS(brd->eb_type) != EVCLASS_CPU) {
printf("get_cpuinfo: slot %d doesn't contain a cpu board\n", slot);
return NULL;
}
return &(brd->eb_cpuarr[proc]);
}
/*
* fix_vpids()
* The kernel assumes (incorrectly) that the processor whose
* vpid is zero is both the master processor and the processor
* which is currently active. This is completely bogus, but
* we deal with it by reordering the array until an active
* processor is in slot zero. Note that this routine _must_
* be called early in the initialization cycle, since lots of
* other data structures (particularly the config tree) are
* built using the information from here.
*/
void
fix_vpids(void)
{
evcpucfg_t *cpu;
int pid;
if ((cpu = get_cpuinfo(MPCONF[0].phys_id)) == NULL)
return;
while (! cpu->cpu_enable) {
mpconf_t temp_mpconf = MPCONF[0];
/* Shift everything down a slot */
pid = 1;
while (MPCONF[pid].mpconf_magic == MPCONF_MAGIC &&
MPCONF[pid].virt_id == pid) {
evcpucfg_t *tmp_cpu = get_cpuinfo(MPCONF[pid].phys_id);
tmp_cpu->cpu_vpid--;
MPCONF[pid].virt_id--;
MPCONF[pid-1] = MPCONF[pid];
pid++;
}
/* Put the disabled processor at the end of the array */
pid--;
MPCONF[pid] = temp_mpconf;
MPCONF[pid].virt_id = pid;
cpu = get_cpuinfo(MPCONF[pid].phys_id);
cpu->cpu_vpid = pid;
/* Now check the new cpu at index 0 to ensure it is enabled */
if ((cpu = get_cpuinfo(MPCONF[0].phys_id)) == NULL)
return;
}
}
void
set_diagval_disable(int vpid, int diagval)
{
int spnum, slot, proc;
spnum = MPCONF[vpid].phys_id;
slot = (spnum & EV_SLOTNUM_MASK) >> EV_SLOTNUM_SHFT;
proc = (spnum & EV_PROCNUM_MASK) >> EV_PROCNUM_SHFT;
EVCFGINFO->ecfg_board[slot].eb_cpuarr[proc].cpu_diagval = diagval;
EVCFGINFO->ecfg_board[slot].eb_cpuarr[proc].cpu_enable = 0;
}
int dump_earoms(void)
{
#if IP19
int i, cpus;
cpus = 0;
i = EV_MAX_CPUS;
while (i && !cpus) {
if (MPCONF[i].phys_id != NULL)
cpus = i;
i--;
}
printf(" EAROM checksums:");
for (i = 0; i <= cpus; i++) {
if (!(i % 16))
printf("\n ");
if (MPCONF[i].phys_id != NULL)
printf("%04x ", MPCONF[i].earom_cksum);
else
printf(" ");
}
printf("\n");
#endif
return 0;
}
void
compare_checksums()
{
#if IP19
int i, cpus;
int dump_checksums = 0;
printf("Comparing EAROM checksums...\n");
cpus = 0;
i = EV_MAX_CPUS;
while (i && !cpus) {
if (MPCONF[i].phys_id != NULL)
cpus = i;
i--;
}
for (i = 0; i <= cpus; i++) {
if (MPCONF[i].virt_id == i) {
if (MPCONF[i].stored_cksum) {
if (MPCONF[i].stored_cksum != MPCONF[i].earom_cksum) {
printf("Disabling CPU %d due to bad EAROM checksum.\n", i);
set_diagval_disable(i, EVDIAG_EAROM_CKSUM);
}
} else {
dump_checksums = 1;
}
}
}
if (dump_checksums)
dump_earoms();
#endif
}