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

758 lines
18 KiB
C

#ident "IO6prom/inventory.c : $Revision: 1.42 $"
/***********************************************************************\
* 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 <libsc.h>
#include <libsk.h>
#include <libkl.h>
#include <sn0hinv.h> /* BOARD_NAME macro */
#include <promgraph.h> /* extern module table variables */
#include <sys/SN/slotnum.h>
#include <sys/SN/SN0/ip27config.h> /* Definition of SN00 */
#include <sys/SN/SN0/klhwinit.h> /* IP27_PART_NUM */
#include "io6prom_private.h"
#include "inventory.h"
extern int num_modules ;
extern struct mod_tab module_table[] ;
extern char* find_board_name(lboard_t *l);
/* Factor by which structs on stack need to be allocated.
Due to alignment issues, we need to allocate a larger
buffer for reading in structs from nvram.
*/
#define INVTAB_REV 2
#define STRUCT_PAD 2
void
dump_inv_hdr(invtabhdr_t *ih)
{
printf("inv hdr nic = %x\n", ih->nic) ;
printf("flag type mod slot dv dp ") ;
printf("cmap physid barcode nic offset\n") ;
}
/* print a record for debug purposes */
void
dump_inv_rec(invrec_t *ir, int count)
{
ssize_t offset;
printf("%x %x %d %x %d %d ",
ir->flag,
ir->btype,
ir->modnum,
ir->slotnum,
ir->diagval,
ir->diagparm) ;
printf("%lx %d %s ",
ir->cmap,
ir->physid,
ir->barcode) ;
if (ir->nic+1)
printf("%x\t", ir->nic) ;
else
printf("\t") ;
offset=calc_pnt_nvoff(count);
if (offset < 0) printf("Location invalid: PNT full\n");
else
printf("%x\n", offset) ;
}
void
dump_mod_map(invtabhdr_t *ih)
{
int i = 0 ;
for (i = 1; i <= MAX_MODULES; i++) {
if (ih->modmap & (1 << i))
printf("%d ", i) ;
}
printf("\n") ;
}
void
dump_modnum(void)
{
int i ;
for (i = 1; i <= num_modules; i++) {
printf("%d ", module_table[i].module_id) ;
}
printf("\n") ;
}
/* dump the inventory table from nvram */
void
dump_inventory(void)
{
char buf[STRUCT_PAD*sizeof(invtabhdr_t)] ;
invtabhdr_t *ih = (invtabhdr_t *)buf ;
char buf1[STRUCT_PAD*sizeof(invrec_t)] ;
invrec_t *ir = (invrec_t *)buf1 ;
int i ;
ssize_t offset;
bzero((char *)ih, sizeof(buf)) ;
cpu_get_nvram_buf(NVOFF_INVHDR, sizeof(invtabhdr_t), (char *)ih) ;
printf("Module numbers configured were ...\n") ;
dump_mod_map(ih) ;
dump_inv_hdr(ih) ;
for (i=0; i<ih->cnt; i++) {
offset=calc_pnt_nvoff(i);
if (offset < 0) break;
cpu_get_nvram_buf(offset, sizeof(invrec_t), (char *)ir) ;
dump_inv_rec(ir, i) ;
}
}
/*
* set_compt_flag
*
* construct a bit map of the components found on a brd.
* Each bit represents the presence or absence of a component.
* See inventory.h for the mapping of each bit to a component.
* for eg: bit 0 - CPU A, bit 1 - CPU B and so on ...
* This routine adds a bit for the component represented by k.
*/
void
set_compt_flag(klinfo_t *k, unsigned int *cmap)
{
int i ;
__psunsigned_t map = *cmap ;
switch(k->struct_type) {
case KLSTRUCT_CPU:
map |= (1 << k->physid) ;
break ;
case KLSTRUCT_MEMBNK:
{
klmembnk_t *m ;
m = (klmembnk_t *) k ;
for (i=0;i<MD_MEM_BANKS;i++) {
map |= (m->membnk_bnksz[i] ? (1 << (i+CMAP_MEMBNK_SHIFT)) : 0) ;
}
}
break ;
/* Ignore these components, without them boards do not work */
case KLSTRUCT_HUB:
case KLSTRUCT_XBOW:
case KLSTRUCT_BRI:
case KLSTRUCT_GFX:
case KLSTRUCT_TPU:
case KLSTRUCT_GSN_A:
case KLSTRUCT_GSN_B:
break ;
default: /* All PCI devs */
map |= (1 << (k->physid + CMAP_PCI_SHIFT)) ;
break ;
}
*cmap = map ;
}
/*
* get_nicstr_info
*
* Given the nic string and the type of component, extract
* the laser id and barcode for that board.
*/
void
get_nicstr_info(klinfo_t *k, nic_t *nicp, char *barcode)
{
char *nic_string = 0, *tmp = 0 ;
char laser[32] ;
*laser = 0 ;
/* Get the nicstring ptr based on the type of component.
In certain cases, like the IP27, where there is bound
to be 2 or more nics, choose what looks to be the right string.
*/
switch(k->struct_type) {
case KLSTRUCT_HUB:
nic_string =
(char *)NODE_OFFSET_TO_K1(k->nasid, ((klhub_t *)k)->hub_mfg_nic) ;
/*
Try to find that part which has the IP27 part number.
If not, use the part that begins with NIC:
Normally, there will be a midplane nic and a serial
number nic with the IP27 nic string.
*/
if (tmp = strstr(nic_string, IP27_PART_NUM))
nic_string = tmp ;
else if (tmp = strstr(nic_string, "NIC:"))
nic_string = tmp ;
break ;
case KLSTRUCT_BRI:
/* XXX Bank on the fact that the IO6 NIC appears first
followed by the MIO nic if any.
*/
nic_string =
(char *)NODE_OFFSET_TO_K1(k->nasid, ((klbri_t *)k)->bri_mfg_nic) ;
break ;
case KLSTRUCT_ROU:
nic_string =
(char *)NODE_OFFSET_TO_K1(k->nasid, ((klrou_t *)k)->rou_mfg_nic) ;
break ;
case KLSTRUCT_GFX:
nic_string =
(char *)NODE_OFFSET_TO_K1(k->nasid, ((klgfx_t *)k)->gfx_mfg_nic) ;
break ;
case KLSTRUCT_XBOW:
/* handle midplane nics in HUB case XXX */
break ;
case KLSTRUCT_TPU:
nic_string =
(char *)NODE_OFFSET_TO_K1(k->nasid, ((kltpu_t *)k)->tpu_mfg_nic) ;
break ;
case KLSTRUCT_GSN_A:
case KLSTRUCT_GSN_B:
nic_string =
(char *)NODE_OFFSET_TO_K1(k->nasid, ((klgsn_t *)k)->gsn_mfg_nic) ;
break ;
case KLSTRUCT_XTHD:
nic_string =
(char *)NODE_OFFSET_TO_K1(k->nasid, ((klxthd_t *)k)->xthd_mfg_nic);
break;
}
if (nic_string) {
if (nicp) {
parse_bridge_nic_info(nic_string, "Laser", laser) ;
*nicp = strtoull(laser, 0, 16) ;
}
if (barcode) {
/* Serial will be valid only if the string does not begin with NIC: */
if (strncmp(nic_string, "NIC:", 4))
parse_bridge_nic_info(nic_string, "Serial", barcode) ;
}
}
}
/*
* make_inv_rec
*
* Make a record of the stuff found on a board l.
* This will be written into the nvram.
*/
void
make_inv_rec(lboard_t *l, invrec_t *ir, int count)
{
klinfo_t *k ;
int i ;
bzero((char *)ir, sizeof(invrec_t)) ;
ir->flag |= NVINVREC_VALID ;
ir->btype = l->brd_type ;
ir->modnum = l->brd_module ;
ir->slotnum = l->brd_slot ;
ir->diagval = l->brd_diagval ;
ir->diagparm = l->brd_diagparm ;
for (i=0; i<l->brd_numcompts; i++) {
k = KLCF_COMP(l, i) ;
set_compt_flag(k, &ir->cmap) ;
if (!(ir->nic))
get_nicstr_info(k, &ir->nic, ir->barcode) ;
}
}
/* write a record to nvram */
void
write_inv_rec(invrec_t *ir, int count)
{
ssize_t offset;
offset=calc_pnt_nvoff(count);
if (offset < 0) return;
cpu_set_nvram_offset(offset, sizeof(invrec_t), (char *)ir) ;
}
/* make an inventory record for a board and write it to nvram */
int
write_brdinv(lboard_t *l, void *ap, void *rp)
{
char buf[STRUCT_PAD*sizeof(invrec_t)] ;
invrec_t *ir = (invrec_t *)buf ;
int count = *(int *)ap ;
/*
* XXX Ignore midplanes/XBOWs for now. need to check nic and duplicates.
* Ignore Graphics for now. Need to check component layout on the brd.
* Ignore routers for now. There is a bug in the brd_slot assignment
* in the router code. Ignore TPU boards for now. Ignore GSN boards
* for now.
*/
if ((KLCLASS(l->brd_type) == KLCLASS_ROUTER) ||
(KLCLASS(l->brd_type) == KLCLASS_MIDPLANE) ||
(KLCLASS(l->brd_type) == KLCLASS_GFX) ||
(l->brd_type == KLTYPE_TPU) ||
(l->brd_type == KLTYPE_GSN_A) ||
(l->brd_type == KLTYPE_GSN_B))
return 1 ;
count++ ;
*(int *)ap = count ;
/* If rp != NULL, simply count the number of records. */
if (rp!=NULL) return 1;
make_inv_rec(l, ir, count-1) ;
#ifdef DEBUG
dump_inv_rec(ir, count-1) ;
#endif
write_inv_rec(ir, count-1) ;
printf(".");
return 1 ;
}
void
get_mod_map(invtabhdr_t *ih)
{
int i = 0 ;
unsigned long long m = 0 ;
for (i = 1; i <= num_modules; i++) {
m |= (1 << module_table[i].module_id) ;
}
ih->modmap = m ;
}
void
check_mod_map(invtabhdr_t *ih)
{
int i = 0 ;
unsigned long long m = 0 ;
for (i = 1; i <= num_modules; i++) {
if (!(ih->modmap & (1 << module_table[i].module_id)))
break ;
}
if (i > num_modules)
return ;
printf("***Warning: Module numbers different on re-boot\n") ;
printf("The system previously contained the following module numbers\n") ;
dump_mod_map(ih) ;
printf("It now contains ...\n") ;
dump_modnum() ;
printf("***Warning: Since module numbers have changed you will see\n") ;
printf("a lot of messages about missing and new hardware.\n") ;
}
/* write inventory records for all boards found in the system. */
void
write_inventory(void)
{
char buf[STRUCT_PAD*sizeof(invtabhdr_t)] ;
invtabhdr_t *ih = (invtabhdr_t *)buf ;
int count = 0 ;
if (set_nvreg(NVOFF_INVENT_VALID, 0) == -1) {
printf("Error in write_inventory: could not invalidate inventory\n");
return ;
}
bzero((char *)ih, sizeof(buf)) ;
cpu_get_nvram_buf(NVOFF_INVHDR, sizeof(invtabhdr_t), (char *)ih) ;
/* count the number of boards */
visit_lboard(write_brdinv, (void *)&count, (void *)1L);
printf("Writing %d records", count);
/* write current inventory. */
count=0;
visit_lboard(write_brdinv, (void *)&count, NULL) ;
printf(" DONE\n");
ih->cnt = count ;
ih->tver = INVTAB_REV ;
ih->nic = get_sys_nic() ;
get_mod_map(ih) ;
#ifdef DEBUG
dump_inv_hdr(ih) ;
#endif
cpu_set_nvram_offset(NVOFF_INVHDR, sizeof(invtabhdr_t), (char *)ih) ;
/* Validate the Inventory data */
if (set_nvreg(NVOFF_INVENT_VALID, INVENT_VALID) == -1) {
printf("Error in write_inventory: could not revalidate inventory\n");
return ;
}
update_checksum();
printf("Updated new configuration. Wrote %d records.\n", count) ;
}
/*
Search all records for a match on the module id and slot id.
Return 0 if not found and 1 if found.
Fill ir with the record found.
*/
int
search_nvram_inv(lboard_t *l, invrec_t *ir, int cnt)
{
int i ;
ssize_t offset;
for (i=0; i<cnt; i++) {
offset=calc_pnt_nvoff(i);
if (offset < 0) return(0);
cpu_get_nvram_buf(offset, sizeof(invrec_t), (char *)ir) ;
if ((ir->modnum == l->brd_module) &&
(ir->slotnum == l->brd_slot))
return 1 ;
}
return 0 ;
}
/* From the lboard struct, find the component that will
have a nic string and get the nic and barcode info
from the nic string.
*/
void
get_nicinfo_from_lb(lboard_t *lb, nic_t *nicp, char *barcode)
{
int i ;
klinfo_t *k ;
for (i=0; i<lb->brd_numcompts; i++) {
k = KLCF_COMP(lb, i) ;
get_nicstr_info(k, nicp, barcode) ;
if ((nicp) && (*nicp))
break ;
}
}
/* Check if the given board is present in nvram. This
detects new boards.
*/
int
check_brdinv(lboard_t *l, void *ap, void *rp)
{
int cnt = *(int *)ap ;
invrec_t ir ;
char sname[SLOTNUM_MAXLENGTH] ;
char barcode[MAX_BARCODE] ;
if ((KLCLASS(l->brd_type) == KLCLASS_ROUTER) ||
(KLCLASS(l->brd_type) == KLCLASS_MIDPLANE) ||
(KLCLASS(l->brd_type) == KLCLASS_GFX) ||
(l->brd_type == KLTYPE_TPU) ||
(l->brd_type == KLTYPE_GSN_A) ||
(l->brd_type == KLTYPE_GSN_B))
return 1 ;
bzero((char *)&ir, sizeof(invrec_t)) ;
*barcode = 0 ;
if (!search_nvram_inv(l, &ir, cnt)) {
get_slotname(l->brd_slot, sname) ;
get_nicinfo_from_lb(l, NULL, barcode) ;
printf(
"***Warning: Found a new %s board in module %d, slot %s, serial %s\n",
find_board_name(l), l->brd_module, sname, barcode) ;
printf(
"Please use the \'update\' command from the PROM Monitor "
"to update the inventory\n") ;
}
return 1 ;
}
/*
* Component inventory related routines.
*/
/*
*
*/
void
cmap_to_str(unsigned int cdmap, char *string)
{
char tmp[8];
int i ;
if (cdmap&0x3) {
strcpy(string, "CPU ") ;
if (cdmap&0x1)
strcat(string, "A") ;
if (cdmap&0x2)
strcat(string, "B") ;
}
else if (cdmap&0x3fc) {
strcpy(string, "MEM BANK ") ;
for (i=0;i<MD_MEM_BANKS;i++) {
if ((1<<(i+2)) & cdmap) {
sprintf(tmp, "%d ", i) ;
strcat(string, tmp) ;
}
}
}
else if (cdmap&0x3fc0) {
strcpy(string, "PCI DEV ") ;
for (i=0;i<MAX_PCI_DEVS;i++) {
if ((1<<(i+10)) & cdmap) {
sprintf(tmp, "%d ", i) ;
strcat(string, tmp) ;
}
}
}
}
void
check_compt_map(lboard_t *lb, int index)
{
klinfo_t *k ;
klmembnk_t *m ;
int i;
char sname[SLOTNUM_MAXLENGTH] ;
get_slotname(lb->brd_slot, sname) ;
if (index<2) {
k = NULL ;
while (k = find_component(lb, k, KLSTRUCT_CPU)) {
if (index == k->physid) /* we found our guy */
return ;
}
printf("/hw/module/%d/slot/%s:",
lb->brd_module, sname) ;
if (!k)
printf("CPU %c missing\n", 'A' + index) ;
return ;
}
if ((index >= 2) && (index < 10)) {
k=NULL ;
if (k = find_component(lb, k, KLSTRUCT_MEMBNK)) {
m = (klmembnk_t *)k ;
if (m->membnk_bnksz[index-2])
return ;
else {
printf("/hw/module/%d/slot/%s:",
lb->brd_module, sname) ;
printf("MEM BANK %d missing or disabled\n", index-2) ;
}
}
return ;
}
if ((index >= 10) && (index < 18)) {
for (i=0; i < KLCF_NUM_COMPS(lb); i++) {
k = KLCF_COMP(lb, i) ;
if ((k->struct_type != KLSTRUCT_BRI) && (k->physid == (index-10)))
return ;
}
printf("/hw/module/%d/slot/%s:",
lb->brd_module, sname) ;
printf("PCI DEV %d missing\n", index-10) ;
}
}
/*
* Given a board that was present in the previous boot
* check its components.
*/
void
check_compt_inv(lboard_t *lb, invrec_t *ir)
{
int i ;
klinfo_t *k;
unsigned int cmap = 0, cdmap = 0 ;
char string[32] ;
/* check for missing components */
/* For all the bits set in the nvram cmap
find the corresponding klinfo struct. */
for (i=0; i<32 ; i++) {
if ((1<<i) & ir->cmap)
check_compt_map(lb, i) ;
}
/* check for new components */
*string = 0 ;
for (i = 0; i < KLCF_NUM_COMPS(lb); i++) {
k = KLCF_COMP(lb, i);
set_compt_flag(k, &cmap) ;
if ((ir->cmap & cmap) != cmap) {
cdmap = (~ir->cmap & cmap) ;
cmap_to_str(cdmap, string) ;
printf("\tFound new or re-enabled component %s\n", string) ;
}
}
}
/*
* Check the old inventory records in nvram to the real
* inventory found during this boot. Report any missing
* hardware as well as new hardware.
*/
void
check_inventory()
{
char buf[STRUCT_PAD*sizeof(invtabhdr_t)] ;
invtabhdr_t *ih = (invtabhdr_t *)buf ;
char buf1[STRUCT_PAD*sizeof(invrec_t)] ;
invrec_t *ir = (invrec_t *)buf1 ;
int i ;
lboard_t lb, *rlb = 0 ;
nic_t nic = 0 ;
char barcode[MAX_BARCODE] ;
char sname[SLOTNUM_MAXLENGTH] ;
ssize_t offset;
*barcode = 0 ;
printf("Checking hardware inventory ...............\t\t");
sysctlr_message("Chk Inv");
/* 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("\nWARNING: hardware inventory is invalid. Reinitializing...\n");
write_inventory();
return ;
}
bzero((char *)ih, sizeof(buf)) ;
cpu_get_nvram_buf(NVOFF_INVHDR, sizeof(invtabhdr_t), (char *)ih) ;
if ((!ih->nic) && !(SN00)) {
printf("\nWarning: Inventory table ID value is 0. Check Midplane NIC\n") ;
write_inventory();
return ;
}
if (!check_sys_nic(ih->nic)) {
printf("\nWARNING: This NVRAM did not belong to this system.\
Reinitializing...\n");
write_inventory();
return ;
}
check_mod_map(ih) ;
for (i=0; i<ih->cnt; i++) {
offset=calc_pnt_nvoff(i);
if (offset < 0) continue;
cpu_get_nvram_buf(offset, sizeof(invrec_t), (char *)ir) ;
if (!(ir->flag & NVINVREC_VALID))
continue ;
lb.brd_type = ir->btype ;
lb.brd_module = ir->modnum ;
lb.brd_slot = ir->slotnum ;
get_slotname(ir->slotnum, sname) ;
rlb = get_match_lb(&lb, 0) ;
if ((!rlb) || (!(rlb->brd_flags & ENABLE_BOARD))) {
printf("\n***Warning: Board in module %d, slot %s is missing or disabled\n",
ir->modnum, sname) ;
if( ir->btype == KLTYPE_IP27)
printf("It previously contained a node-board, barcode %s laser %x\n",
ir->barcode, ir->nic) ;
else
printf("It previously contained a %s board, barcode %s laser %x\n",
BOARD_NAME(ir->btype), ir->barcode, ir->nic) ;
} else {
nic = 0 ;
get_nicinfo_from_lb(rlb, &nic, barcode) ;
if (ir->nic != nic) {
printf("\n***Warning: Found a different board in module %d, slot %s,\n",
lb.brd_module, sname) ;
printf("Previous barcode was %s, New barcode is %s\n",
ir->barcode, barcode) ;
}
else /* The board looks good. check its components */
check_compt_inv(rlb, ir) ;
}
}
/* Check for new boards */
visit_lboard(check_brdinv, (void *)&ih->cnt, NULL) ;
printf("DONE\n") ;
}
/*
* The update command rewrites the current state of the machine
* into the inventory nvram.
* update -dump is a debug option to dumpout the inventory table.
*/
/*ARGSUSED*/
int
update_cmd(int argc, char **argv)
{
if (argv[1] && (!strcmp(argv[1], "-dump"))) {
dump_inventory() ;
return 0 ;
}
(void)write_inventory();
return 0;
}
/*
* Print the module numbers of all modules found
* currently.
*/
/*ARGSUSED*/
int
modnum_cmd(int argc, char **argv)
{
dump_modnum() ;
return 0 ;
}