#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <kstat.h>
#include <string.h>
#include <assert.h>
#include <alloca.h>
#include <libintl.h>
#include <fcntl.h>
#include <varargs.h>
#include <sys/openpromio.h>
#include <sys/sysmacros.h>
#include <sys/serengeti.h>
#include <sys/sgfrutypes.h>
#include <pdevinfo.h>
#include <display.h>
#include <pdevinfo_sun4u.h>
#include <display_sun4u.h>
#include <libprtdiag.h>
#include <config_admin.h>
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
#define SCHIZO_COMPATIBLE "pci108e,8001"
#define XMITS_COMPATIBLE "pci108e,8002"
#define ACTIVE 0
#define INACTIVE 1
#define DISPLAY_INFO 40
#define EVNT2STR(e) ((e) == CFGA_STAT_NONE ? "none" : \
(e) == CFGA_STAT_EMPTY ? "empty" : \
(e) == CFGA_STAT_DISCONNECTED ? "disconnected" : \
(e) == CFGA_STAT_CONNECTED ? "connected" : \
(e) == CFGA_STAT_UNCONFIGURED ? "unconfigured" : \
(e) == CFGA_STAT_CONFIGURED ? "configured" : \
"unknown")
#define COND2STR(c) ((c) == CFGA_COND_UNKNOWN ? "unknown" : \
(c) == CFGA_COND_OK ? "ok" : \
(c) == CFGA_COND_FAILING ? "failing" : \
(c) == CFGA_COND_FAILED ? "failed" : \
(c) == CFGA_COND_UNUSABLE ? "unusable" : \
"???")
#define SG_CLK_FREQ_TO_MHZ(x) (((x) + 500000) / 1000000)
#define MAX_STATUS_LEN 8
#define SG_FAIL "fail"
#define SG_DISABLED "disabled"
#define SG_DEGRADED "degraded"
#define SG_OK "ok"
#define SG_SCHIZO_FAILED 1
#define SG_SCHIZO_GOOD 0
#define DEFAULT_MAX_FREQ 66
#define PCIX_MAX_FREQ 100
#define CFG_CPU "::cpu"
#define CFG_SET_FRU_NAME_NODE(str, num) \
{ \
char tmp_str[MAX_FRU_NAME_LEN]; \
sprintf(tmp_str, "/N%d", num); \
strncat(str, tmp_str, sizeof (tmp_str)); \
}
#define CFG_SET_FRU_NAME_CPU_BOARD(str, num) \
{ \
char tmp_str[MAX_FRU_NAME_LEN]; \
sprintf(tmp_str, ".%s%d", SG_HPU_TYPE_CPU_BOARD_ID, num); \
strncat(str, tmp_str, sizeof (tmp_str)); \
}
#define CFG_SET_FRU_NAME_MODULE(str, num) \
{ \
char tmp_str[MAX_FRU_NAME_LEN]; \
sprintf(tmp_str, "%s%d", CFG_CPU, num); \
strncat(str, tmp_str, sizeof (tmp_str)); \
}
extern int print_flag;
int do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag);
void *get_prop_val(Prop *prop);
Prop *find_prop(Prom_node *pnode, char *name);
char *get_node_name(Prom_node *pnode);
char *get_node_type(Prom_node *pnode);
void add_node(Sys_tree *, Prom_node *);
void display_pci(Board_node *);
void display_ffb(Board_node *, int);
void display_io_cards(struct io_card *list);
void display_cpu_devices(Sys_tree *tree);
void display_cpus(Board_node *board);
void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
struct system_kstat_data *kstats);
void display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats);
void get_failed_parts(void);
int display_failed_parts(Sys_tree *tree);
void display_memoryconf(Sys_tree *tree);
void print_us3_memory_line(int portid, int bank_id, uint64_t bank_size,
char *bank_status, uint64_t dimm_size, uint32_t intlv, int seg_id);
static void serengeti_display_hw_revisions(Prom_node *root,
Board_node *bnode);
static Board_node *serengeti_find_board(Sys_tree *root, int board, int nodeid);
static Board_node *serengeti_insert_board(Sys_tree *root, int board, int nid);
static int display_schizo_revisions(Board_node *bdlist, int mode);
static void display_sgsbbc_revisions(Board_node *bdlist);
static void serengeti_display_board_info(int state);
static void serengeti_display_board_info_header(int state);
static boolean_t cpu_node_configured(char *const node);
static void display_io_max_bus_speed(struct io_card *p);
static void display_io_slot_info(struct io_card *p);
static void get_slot_name(struct io_card *card, char *slot_name);
int board_bus_max_freq = DEFAULT_MAX_FREQ;
#define DEVINFO_TREE 1
#define OBP_TREE 2
static int tree = DEVINFO_TREE;
#ifdef DEBUG
#define D_PRINTFINDENT printfindent
void
printfindent(int indent, char *fmt, ...)
{
va_list ap;
int i = 0;
for (i = 0; i < indent; i ++)
printf("\t");
va_start(ap);
(void) vprintf(fmt, ap);
va_end(ap);
}
#else
#define D_PRINTFINDENT
#endif
void
display_pci(Board_node *board)
{
struct io_card *card_list = NULL;
struct io_card card;
void *value;
Prom_node *pci;
Prom_node *card_node;
Prom_node *pci_bridge_node;
Prom_node *child_pci_bridge_node;
char *slot_name = NULL;
char *child_name;
char *name, *type;
char *pname, *ptype;
char buf[MAXSTRLEN];
int *int_val;
int pci_bus;
int pci_bridge = 0;
int pci_bridge_dev_no;
char *slot_name_arr[SG_MAX_SLOTS_PER_IO_BD] = {NULL};
int i;
int portid;
int level = 0;
int version, *pversion;
#ifdef DEBUG
int slot_name_bits;
#endif
if (board == NULL)
return;
card.display = TRUE;
card.board = board->board_num;
card.node_id = board->node_id;
for (pci = dev_find_node_by_compatible(board->nodes, SCHIZO_COMPATIBLE);
pci != NULL;
pci = dev_next_node_by_compatible(pci, SCHIZO_COMPATIBLE)) {
board_bus_max_freq = DEFAULT_MAX_FREQ;
value = get_prop_val(find_prop(pci, "enum-impl"));
if (value == NULL) {
(void) sprintf(card.bus_type, "PCI");
} else {
(void) sprintf(card.bus_type, "cPCI");
}
if (strstr((char *)get_prop_val(
find_prop(pci, "compatible")), XMITS_COMPATIBLE)) {
sprintf(card.notes, "%s", XMITS_COMPATIBLE);
value = (int *)get_prop_val
(find_prop(pci, "module-revision#"));
if (value) {
pversion = (int *)value;
version = *pversion;
if (version >= 4)
board_bus_max_freq = PCIX_MAX_FREQ;
}
} else if (strstr((char *)get_prop_val(
find_prop(pci, "compatible")), SCHIZO_COMPATIBLE))
sprintf(card.notes, "%s", SCHIZO_COMPATIBLE);
else
sprintf(card.notes, " ");
value = (char *)get_prop_val(find_prop(pci, "slot-names"));
if (value != NULL) {
#ifdef DEBUG
slot_name_bits = *(int *)value;
#endif
slot_name_arr[0] = (char *)value + sizeof (int);
D_PRINTFINDENT(0, "slot_name_arr[0] is [%s]\n",
slot_name_arr[0]);
for (i = 1; i < SG_MAX_SLOTS_PER_IO_BD; i++) {
slot_name_arr[i] = (char *)slot_name_arr[i - 1]
+ strlen(slot_name_arr[i - 1]) +1;
D_PRINTFINDENT(0, "slot_name_arr[%d] is [%s]\n", i,
slot_name_arr[i]);
}
}
level = 0;
card_node = pci->child;
while (card_node != NULL) {
pci_bridge = 0;
name = (char *)get_prop_val(
find_prop(card_node, "name"));
if (name == NULL) {
card_node = card_node->sibling;
continue;
}
D_PRINTFINDENT(level, "NAME is %s\n", name);
type = (char *)get_prop_val(
find_prop(card_node, "device_type"));
int_val = (int *)get_prop_val(
find_prop(card_node, "reg"));
if (int_val != NULL) {
card.dev_no = (((*int_val) & 0xF800) >> 11);
card.func_no = (((*int_val) & 0x700) >> 8);
} else {
card.dev_no = -1;
card.func_no = -1;
}
if ((type != NULL) &&
(strncmp(name, "pci", 3) == 0) &&
(strcmp(type, "pci") == 0)) {
if (level > 0) {
pname = (char *)get_prop_val(
find_prop(card_node->parent,
"name"));
ptype = (char *)get_prop_val(
find_prop(card_node->parent,
"device_type"));
if ((ptype != NULL) &&
(pname != NULL) &&
(strncmp(pname, "pci", 3) == 0) &&
(strcmp(ptype, "pci") == 0)) {
child_pci_bridge_node =
card_node;
} else {
pci_bridge_dev_no = card.dev_no;
pci_bridge_node = card_node;
}
} else {
pci_bridge_dev_no = card.dev_no;
pci_bridge_node = card_node;
}
pci_bridge = TRUE;
D_PRINTFINDENT(level,
"pci_bridge_dev_no is [%d]\n",
pci_bridge_dev_no);
}
if (type)
D_PRINTFINDENT(level,
"*** name is [%s] - type is [%s]\n",
name, type);
else
D_PRINTFINDENT(level,
"*** name is [%s]\n", name);
if (card.dev_no != -1) {
if (((level > 0) &&
(card_node->parent->parent ==
pci_bridge_node)) ||
(card_node->parent == pci_bridge_node)) {
D_PRINTFINDENT(level,
" pci_bridge_dev_no is [%d]\n",
pci_bridge_dev_no);
slot_name =
slot_name_arr[pci_bridge_dev_no -1];
} else {
D_PRINTFINDENT(level,
" card.dev_no is [%d]\n",
card.dev_no);
slot_name =
slot_name_arr[card.dev_no - 1];
}
get_slot_name(&card, slot_name);
} else {
(void) sprintf(card.slot_str, "%c", '-');
}
portid = -1;
value = get_prop_val(find_prop(pci, "portid"));
if (value != NULL) {
portid = *(int *)value;
}
card.schizo_portid = portid;
#ifdef DEBUG
(void) sprintf(card.notes, "%s portid [%d] dev_no[%d]"
" slot_name[%s] name_bits[%d]",
card.notes,
portid,
card.dev_no, slot_name,
slot_name_bits);
#endif
int_val = (int *)get_prop_val
(find_prop(pci, "reg"));
if (int_val != NULL) {
int_val ++;
pci_bus = ((*int_val) & 0x7f0000);
if (pci_bus == 0x600000)
card.pci_bus = 'A';
else if (pci_bus == 0x700000)
card.pci_bus = 'B';
else
card.pci_bus = '-';
} else {
card.pci_bus = '-';
}
if (node_status(card_node, SG_FAIL))
strncpy(card.status, SG_FAIL,
sizeof (SG_FAIL));
else if (node_status(card_node, SG_DISABLED))
strncpy(card.status, SG_DISABLED,
sizeof (SG_DISABLED));
else
strncpy(card.status, SG_OK,
sizeof (SG_OK));
value = get_prop_val(find_prop(card_node, "model"));
if (value == NULL)
card.model[0] = '\0';
else {
(void) sprintf(card.model, "%s",
(char *)value);
if (strcmp(card.model, "SUNW,sgsbbc") == 0) {
card_node = card_node->sibling;
continue;
}
}
distinguish_identical_io_cards(name, card_node, &card);
int_val = get_prop_val(find_prop(pci,
"clock-frequency"));
if (int_val != NULL) {
card.freq = SG_CLK_FREQ_TO_MHZ(*int_val);
} else {
card.freq = -1;
}
value = get_prop_val(find_prop(card_node,
"compatible"));
if (value != NULL) {
(void) sprintf(buf, "%s-%s", name,
(char *)value);
} else {
(void) sprintf(buf, "%s", name);
}
name = buf;
child_name = (char *)get_node_name(card_node->child);
if ((card_node->child != NULL) &&
(child_name != NULL)) {
value = get_prop_val(find_prop(card_node->child,
"device_type"));
if (value != NULL) {
(void) sprintf(card.name, "%s/%s (%s)",
name, child_name,
(char *)value);
} else {
(void) sprintf(card.name, "%s/%s", name,
child_name);
}
} else {
(void) sprintf(card.name, "%s", (char *)name);
}
if (pci_bridge) {
if (strlen(card.model) == 0)
(void) sprintf(card.model,
"%s", "pci-bridge");
else
(void) sprintf(card.model,
"%s/pci-bridge", card.model);
}
card_list = insert_io_card(card_list, &card);
if (pci_bridge) {
if (card_node->child != NULL) {
level++;
card_node = card_node->child;
} else
card_node = card_node->sibling;
} else {
if ((card_node->parent == pci_bridge_node) &&
(card_node->sibling == NULL)) {
card_node = pci_bridge_node->sibling;
if (level > 0)
level--;
} else if ((card_node->parent ==
child_pci_bridge_node) &&
(card_node->parent->parent ==
pci_bridge_node)) {
if ((child_pci_bridge_node->sibling) &&
(card_node->sibling == NULL)) {
card_node =
child_pci_bridge_node-> \
sibling;
if (level > 0)
level--;
} else if ((pci_bridge_node->sibling) &&
(card_node->sibling == NULL)) {
card_node =
pci_bridge_node->sibling;
if (level > 1)
level = level - 2;
else if (level > 0)
level--;
} else
card_node = card_node->sibling;
} else
card_node = card_node->sibling;
}
}
}
display_io_cards(card_list);
free_io_cards(card_list);
}
void
display_ffb(Board_node *board, int table)
{}
static void
serengeti_display_board_info_header(int state)
{
char *fmt = "%-9s %-11s %-12s %-12s %-9s %-40s\n";
log_printf("\n", 0);
log_printf("=========================", 0);
if (state == ACTIVE)
log_printf(dgettext(TEXT_DOMAIN,
" Active Boards for Domain "), 0);
else
log_printf(dgettext(TEXT_DOMAIN,
" Available Boards/Slots for Domain "), 0);
log_printf("===========================", 0);
log_printf("\n", 0);
log_printf("\n", 0);
log_printf(fmt, "", "Board", "Receptacle", "Occupant", "", "", 0);
log_printf(fmt, "FRU Name", "Type", "Status", "Status",
"Condition", "Info", 0);
log_printf(fmt, "---------", "-----------", "-----------",
"------------", "---------",
"----------------------------------------", 0);
}
static void
serengeti_display_board_info(int state)
{
int i, z, ret;
int nlist = 0;
int available_board_count = 0;
struct cfga_list_data *board_cfg = NULL;
char *err_string = NULL;
char tmp_id[CFGA_LOG_EXT_LEN + 1];
char tmp_info[DISPLAY_INFO + 1];
const char listops[] = "class=sbd";
struct cfga_list_data dat;
cfga_flags_t flags = 0;
ret = config_list_ext(0, NULL, &board_cfg, &nlist,
NULL, listops,
&err_string, flags);
if (ret == CFGA_OK) {
serengeti_display_board_info_header(state);
for (i = 0; i < nlist; i++) {
dat = board_cfg[i];
if ((state != ACTIVE) &&
(dat.ap_o_state == CFGA_STAT_CONFIGURED))
continue;
else if ((state == ACTIVE) &&
(dat.ap_o_state != CFGA_STAT_CONFIGURED))
continue;
if (state == INACTIVE)
available_board_count++;
memcpy(tmp_id, dat.ap_log_id, CFGA_LOG_EXT_LEN);
tmp_id[CFGA_LOG_EXT_LEN] = '\0';
for (z = 0; z < strlen(tmp_id); z++) {
if (tmp_id[z] == '.')
tmp_id[z] = '/';
}
log_printf("/%-8s ", tmp_id, 0);
log_printf("%-11s ", dat.ap_type, 0);
log_printf("%-12s ", EVNT2STR(dat.ap_r_state), 0);
log_printf("%-12s ", EVNT2STR(dat.ap_o_state), 0);
log_printf("%-8s ", COND2STR(dat.ap_cond), 0);
memcpy(tmp_info, dat.ap_info, DISPLAY_INFO);
tmp_info[DISPLAY_INFO - 1] = '\0';
if (strlen(tmp_info) >= (DISPLAY_INFO - 1))
tmp_info[DISPLAY_INFO - 2] = '+';
log_printf("%-*s\n", (DISPLAY_INFO - 1), tmp_info, 0);
}
if ((state == INACTIVE) &&
(available_board_count == 0)) {
log_printf(dgettext(TEXT_DOMAIN,
"There are currently no "
"Boards/Slots available "
"to this Domain\n"), 0);
}
}
if (board_cfg)
free(board_cfg);
if (err_string)
free(err_string);
}
void
add_node(Sys_tree *root, Prom_node *pnode)
{
int board = -1;
int portid = -1;
int nodeid = -1;
void *value = NULL;
Board_node *bnode = NULL;
Prom_node *p = NULL;
char *type;
if ((value = get_prop_val(find_prop(pnode, "portid"))) == NULL) {
if ((type = get_node_type(pnode)) && (strcmp(type, "cpu") == 0))
value =
get_prop_val(find_prop(pnode->parent, "portid"));
}
if (value != NULL) {
portid = *(int *)value;
}
nodeid = SG_PORTID_TO_NODEID(portid);
board = SG_PORTID_TO_BOARD_NUM(portid);
if ((bnode = serengeti_find_board(root, board, nodeid)) == NULL) {
bnode = serengeti_insert_board(root, board, nodeid);
}
pnode->sibling = NULL;
if (bnode->nodes == NULL)
bnode->nodes = pnode;
else {
p = bnode->nodes;
while (p->sibling != NULL)
p = p->sibling;
p->sibling = pnode;
}
}
void
display_io_cards(struct io_card *list)
{
char *fmt = "%-10s %-4s %-4s %-4s %-4s %-4s %-4s %-4s %-4s %-34s";
static int banner = FALSE;
struct io_card *p;
if (list == NULL)
return;
if (banner == FALSE) {
log_printf(fmt, "", "", "", "", "", "Bus", "Max",
"", "", "", 0);
log_printf("\n", 0);
log_printf(fmt, "", "IO", "Port", "Bus", "", "Freq", "Bus",
"Dev,", "", "", 0);
log_printf("\n", 0);
log_printf(fmt, "FRU Name", "Type", " ID", "Side", "Slot",
"MHz", "Freq", "Func", "State", "Name", 0);
#ifdef DEBUG
log_printf("Model Notes\n", 0);
#else
log_printf("Model\n", 0);
#endif
log_printf(fmt, "----------", "----", "----", "----", "----",
"----", "----", "----", "-----",
"--------------------------------", 0);
#ifdef DEBUG
log_printf("---------------------- ", 0);
#endif
log_printf("----------------------\n", 0);
banner = TRUE;
}
for (p = list; p != NULL; p = p -> next) {
display_io_slot_info(p);
display_io_max_bus_speed(p);
log_printf("\n", 0);
}
}
static void
display_io_slot_info(struct io_card *p)
{
char fru_name[MAX_FRU_NAME_LEN] = "";
SG_SET_FRU_NAME_NODE(fru_name, p->node_id);
SG_SET_FRU_NAME_IO_BOARD(fru_name, p->board);
SG_SET_FRU_NAME_MODULE(fru_name, p->schizo_portid % 2);
log_printf("%-8s ", fru_name, 0);
log_printf("%-4s ", p->bus_type, 0);
log_printf("%-3d ", p->schizo_portid, 0);
log_printf("%c ", p->pci_bus, 0);
log_printf("%-1s ", p->slot_str, 0);
log_printf("%-3d ", p->freq, 0);
}
#define BUS_SPEED_PRINT(speed) log_printf(" %d ", speed, 0)
static void
display_io_max_bus_speed(struct io_card *p)
{
int speed = board_bus_max_freq;
switch (p->pci_bus) {
case 'A':
BUS_SPEED_PRINT(speed);
break;
case 'B':
if (strcmp(p->notes, XMITS_COMPATIBLE) == 0) {
if ((strncmp(p->slot_str, "1", 1) == 0) ||
(strncmp(p->slot_str, "0", 1) == 0))
BUS_SPEED_PRINT(33);
else
BUS_SPEED_PRINT(speed);
} else
BUS_SPEED_PRINT(33);
break;
default:
log_printf(" - ", 0);
break;
}
log_printf("%-1d,%-1d ", p->dev_no, p->func_no, 0);
log_printf("%-5s ", p->status, 0);
log_printf("%-32.32s%c ", p->name,
((strlen(p->name) > 32) ? '+' : ' '), 0);
log_printf("%-22.22s%c", p->model,
((strlen(p->model) > 22) ? '+' : ' '), 0);
#ifdef DEBUG
log_printf(" %s", p->notes, 0);
#endif
}
void
display_cpu_devices(Sys_tree *tree)
{
Board_node *bnode;
char *fmt1 = "%-10s %-7s %-4s %-4s %-7s %-4s\n";
log_printf("\n", 0);
log_printf("=========================", 0);
log_printf(" CPUs ", 0);
log_printf("=========================", 0);
log_printf("======================", 0);
log_printf("\n", 0);
log_printf("\n", 0);
log_printf(fmt1, "", "CPU ", "Run", " E$", "CPU", "CPU", 0);
log_printf(fmt1, "FRU Name", "ID ", "MHz", " MB",
"Impl.", "Mask", 0);
log_printf(fmt1, "----------", "-------", "----", "----",
"-------", "----", 0);
bnode = tree->bd_list;
while (bnode != NULL) {
display_cpus(bnode);
bnode = bnode->next;
}
log_printf("\n", 0);
}
static boolean_t
cpu_node_configured(char *const node)
{
int ret, i;
int nlist = 0;
boolean_t rv;
char *err_string = NULL;
struct cfga_list_data *statlist = NULL;
struct cfga_list_data dat;
cfga_flags_t flags = CFGA_FLAG_LIST_ALL;
if (node == NULL)
return (FALSE);
ret = config_list_ext(1, &node, &statlist, &nlist,
NULL, NULL, &err_string, flags);
if (ret == CFGA_OK) {
dat = statlist[0];
if (dat.ap_o_state == CFGA_STAT_CONFIGURED)
rv = TRUE;
else
rv = FALSE;
} else {
rv = FALSE;
}
if (statlist)
free(statlist);
if (err_string)
free(err_string);
return (rv);
}
void
display_cpus(Board_node *board)
{
Prom_node *cpu;
uint_t freq;
int ecache_size;
int board_num = board->board_num;
int *mid;
int *impl;
int *mask;
int decoded_mask;
int *coreid;
int mid_prev = -1;
int ecache_size_prev = 0;
char fru_prev[MAX_FRU_NAME_LEN] = "";
for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
cpu = dev_next_type(cpu, "cpu")) {
char fru_name[MAX_FRU_NAME_LEN] = "";
char cfg_fru_name[MAX_FRU_NAME_LEN] = "";
mid = (int *)get_prop_val(find_prop(cpu, "portid"));
if (mid == NULL)
mid = (int *)get_prop_val(find_prop(cpu, "cpuid"));
freq = SG_CLK_FREQ_TO_MHZ(get_cpu_freq(cpu));
ecache_size = get_ecache_size(cpu);
impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
if ((impl == NULL) || (freq == 0) || (node_failed(cpu)))
continue;
SG_SET_FRU_NAME_NODE(fru_name, board->node_id);
SG_SET_FRU_NAME_CPU_BOARD(fru_name, board_num);
SG_SET_FRU_NAME_MODULE(fru_name, *mid % 4);
if (CPU_IMPL_IS_CMP(*impl)) {
coreid = (int *)get_prop_val(find_prop(cpu,
"reg"));
if (coreid == NULL) {
continue;
}
if (strncmp(fru_prev, "", sizeof (fru_prev)) == 0) {
strncpy(fru_prev, fru_name, sizeof (fru_name));
mid_prev = *mid;
ecache_size_prev = ecache_size;
continue;
} else {
if (strncmp(fru_name, fru_prev,
sizeof (fru_prev)) == 0) {
if (IS_JAGUAR(*impl)) {
ecache_size += ecache_size_prev;
}
ecache_size_prev = 0;
strncpy(fru_prev, "",
sizeof (fru_prev));
} else {
mid_prev = *mid;
ecache_size_prev = ecache_size;
strncpy(fru_prev, fru_name,
sizeof (fru_name));
continue;
}
}
}
CFG_SET_FRU_NAME_NODE(cfg_fru_name, board->node_id);
CFG_SET_FRU_NAME_CPU_BOARD(cfg_fru_name, board_num);
CFG_SET_FRU_NAME_MODULE(cfg_fru_name, *mid % 4);
if (!(cpu_node_configured(cfg_fru_name))) {
continue;
}
log_printf("%-10s ", fru_name, 0);
if (CPU_IMPL_IS_CMP(*impl)) {
log_printf("%3d,%3d ", mid_prev, *mid, 0);
mid_prev = -1;
} else
log_printf("%3d ", *mid, 0);
log_printf(" %4u ", freq, 0);
if (ecache_size == 0)
log_printf("%3s ", "N/A", 0);
else
log_printf("%4.1f ",
(float)ecache_size / (float)(1<<20),
0);
if (impl == NULL) {
log_printf("%6s ", " N/A", 0);
} else {
switch (*impl) {
case CHEETAH_IMPL:
log_printf("%-7s ", "US-III", 0);
break;
case CHEETAH_PLUS_IMPL:
log_printf("%-7s ", "US-III+", 0);
break;
case JAGUAR_IMPL:
log_printf("%-7s ", "US-IV", 0);
break;
case PANTHER_IMPL:
log_printf("%-7s ", "US-IV+", 0);
break;
default:
log_printf("%-7x ", *impl, 0);
break;
}
}
if (mask == NULL) {
log_printf(" %3s ", "N/A", 0);
} else {
if (IS_CHEETAH(*impl))
decoded_mask = REMAP_CHEETAH_MASK(*mask);
else
decoded_mask = *mask;
log_printf(" %d.%d ",
(decoded_mask >> 4) & 0xf,
decoded_mask & 0xf, 0);
}
log_printf("\n", 0);
}
}
void
display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
struct system_kstat_data *kstats)
{
log_printf("\n", 0);
log_printf("=========================", 0);
log_printf(dgettext(TEXT_DOMAIN, " Hardware Failures "), 0);
log_printf("==================================", 0);
log_printf("\n", 0);
get_failed_parts();
if (!flag) {
log_printf("\n", 0);
return;
}
disp_powerfail(root);
serengeti_display_hw_revisions(root, tree->bd_list);
}
static void
serengeti_display_hw_revisions(Prom_node *root, Board_node *bdlist)
{
Prom_node *pnode;
char *value;
log_printf("\n", 0);
log_printf("=========================", 0);
log_printf(dgettext(TEXT_DOMAIN, " HW Revisions "), 0);
log_printf("=======================================", 0);
log_printf("\n", 0);
log_printf("\n", 0);
log_printf("System PROM revisions:\n", 0);
log_printf("----------------------\n", 0);
pnode = dev_find_node(root, "openprom");
if (pnode != NULL) {
value = (char *)get_prop_val(find_prop(pnode, "version"));
log_printf("%s\n\n", value, 0);
} else {
log_printf("OBP ???\n\n", value, 0);
}
log_printf("IO ASIC revisions:\n", 0);
log_printf("------------------\n", 0);
log_printf(" Port\n", 0);
log_printf("FRU Name Model ID Status", 0);
#ifdef DEBUG
log_printf(" Version Notes\n", 0);
#else
log_printf(" Version\n", 0);
#endif
log_printf("----------- --------------- ---- ---------- "
#ifdef DEBUG
"------- "
#endif
"-------\n", 0);
display_schizo_revisions(bdlist, SG_SCHIZO_GOOD);
display_sgsbbc_revisions(bdlist);
}
static int
display_schizo_revisions(Board_node *bdlist, int mode)
{
Prom_node *pnode;
int *int_val;
int portid;
int prev_portid = -1;
char *model;
char *status_a, *status_b;
char status[MAX_STATUS_LEN];
int version;
int node_id;
#ifdef DEBUG
uint32_t a_notes, b_notes;
#endif
int pci_bus;
int rv = 0;
Board_node *bnode;
void *value;
bnode = bdlist;
while (bnode != NULL) {
for (pnode = dev_find_node_by_compatible(bnode->nodes,
SCHIZO_COMPATIBLE); pnode != NULL;
pnode = dev_next_node_by_compatible(pnode,
SCHIZO_COMPATIBLE)) {
char fru_name[MAX_FRU_NAME_LEN] = "";
int_val = (int *)get_prop_val
(find_prop(pnode, "reg"));
if (int_val != NULL) {
int_val ++;
pci_bus = ((*int_val) & 0x7f0000);
}
int_val = (int *)get_prop_val
(find_prop(pnode, "portid"));
if (int_val == NULL)
continue;
portid = *int_val;
if ((portid != prev_portid) && (pci_bus == 0x700000)) {
prev_portid = portid;
status_b = (char *)get_prop_val
(find_prop(pnode, "status"));
#ifdef DEBUG
b_notes = pci_bus;
#endif
continue;
}
#ifdef DEBUG
a_notes = pci_bus;
#endif
prev_portid = portid;
node_id = SG_PORTID_TO_NODEID(portid);
model = (char *)get_prop_val
(find_prop(pnode, "model"));
value = (int *)get_prop_val
(find_prop(pnode, "module-revision#"));
if (value)
int_val = (int *)value;
else
int_val = (int *)get_prop_val
(find_prop(pnode, "version#"));
if (int_val != NULL)
version = *int_val;
else
version = -1;
status_a = (char *)get_prop_val(find_prop
(pnode, "status"));
SG_SET_FRU_NAME_NODE(fru_name, node_id);
SG_SET_FRU_NAME_IO_BOARD(fru_name,
SG_IO_BD_PORTID_TO_BD_NUM(portid));
SG_SET_FRU_NAME_MODULE(fru_name, portid % 2);
if (mode == SG_SCHIZO_FAILED) {
if ((status_a != (char *)NULL) &&
((status_b != (char *)NULL))) {
if ((strcmp
(status_a, SG_DISABLED) == 0) &&
(strcmp(status_b,
SG_DISABLED) == 0)) {
log_printf("\tFRU Type : %s\n ",
model, 0);
log_printf("\tLocation : %s\n",
fru_name, 0);
log_printf
("\tPROM status: %s\n\n",
SG_DISABLED, 0);
rv = 1;
}
}
continue;
}
if ((status_a == (char *)NULL) &&
((status_b == (char *)NULL)))
sprintf(status, " %s ", SG_OK);
else if ((status_a == (char *)NULL) &&
((strcmp(status_b, SG_DISABLED) == 0)))
sprintf(status, " %s", SG_DEGRADED);
else if ((status_b == (char *)NULL) &&
((strcmp(status_a, SG_DISABLED) == 0)))
sprintf(status, " %s", SG_DEGRADED);
else
continue;
log_printf("%-12s", fru_name, 0);
if (model != NULL)
log_printf("%-15s ", model, 0);
else
log_printf("%-15s ", "unknown", 0);
log_printf("%-3d ", portid, 0);
log_printf("%s", status, 0);
log_printf(" %-4d ", version, 0);
#ifdef DEBUG
log_printf("0x%x 0x%x", a_notes, b_notes, 0);
log_printf(" %d", portid, 0);
#endif
log_printf("\n", 0);
}
bnode = bnode->next;
}
return (rv);
}
static void
display_sgsbbc_revisions(Board_node *bdlist)
{
Prom_node *pnode;
int *int_val;
int portid;
char *model;
char *status;
int revision;
int node_id;
Board_node *bnode;
#ifdef DEBUG
char *slot_name;
char notes[30];
char *value;
#endif
bnode = bdlist;
while (bnode != NULL) {
for (pnode = dev_find_node_by_type(bnode->nodes, "model",
"SUNW,sgsbbc"); pnode != NULL;
pnode = dev_next_node_by_type(pnode, "model",
"SUNW,sgsbbc")) {
char fru_name[MAX_FRU_NAME_LEN] = "";
int_val = (int *)get_prop_val
(find_prop(pnode->parent, "portid"));
if (int_val == NULL)
continue;
portid = *int_val;
node_id = SG_PORTID_TO_NODEID(portid);
model = (char *)get_prop_val
(find_prop(pnode, "model"));
status = (char *)get_prop_val(find_prop
(pnode, "status"));
int_val = (int *)get_prop_val
(find_prop(pnode, "revision-id"));
if (int_val != NULL)
revision = *int_val;
else
revision = -1;
#ifdef DEBUG
value = (char *)get_prop_val(
find_prop(pnode->parent, "slot-names"));
if (value != NULL) {
slot_name = (char *)value + sizeof (int);
} else {
strcpy(slot_name, "not_found");
}
(void) sprintf(notes, "[%s] portid [%d]", slot_name,
portid);
#endif
SG_SET_FRU_NAME_NODE(fru_name, node_id);
SG_SET_FRU_NAME_IO_BOARD(fru_name,
SG_IO_BD_PORTID_TO_BD_NUM(portid));
SG_SET_FRU_NAME_MODULE(fru_name, portid % 2);
log_printf("%-12s", fru_name, 0);
if (model != NULL)
log_printf("%-15s ", model, 0);
else
log_printf("%-15s ", "unknown", 0);
log_printf("%-3d ", portid, 0);
if (status == (char *)NULL)
log_printf(" ok ", 0);
else
log_printf(" fail ", 0);
log_printf(" %-4d ", revision, 0);
#ifdef DEBUG
log_printf("%s", notes, 0);
#endif
log_printf("\n", 0);
}
bnode = bnode->next;
}
}
void
display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats)
{
serengeti_display_board_info(ACTIVE);
serengeti_display_board_info(INACTIVE);
}
int
display_failed_parts(Sys_tree *tree)
{
int system_failed = 0;
int bank_failed = 0;
int schizo_failed = FALSE;
int portid, nodeid, board;
Board_node *bnode = tree->bd_list;
Prom_node *pnode;
int *coreid, *impl;
print_flag = TRUE;
while (bnode != NULL) {
pnode = find_failed_node(bnode->nodes);
if ((pnode != NULL) && !system_failed) {
system_failed = TRUE;
log_printf("\n", 0);
log_printf(dgettext(TEXT_DOMAIN,
"Failed Field Replaceable Units (FRU) in "
"System:\n"), 0);
log_printf("=========================="
"====================\n", 0);
}
while (pnode != NULL) {
void *status;
char *name, *type, *model;
char fru_name[MAX_FRU_NAME_LEN] = "";
status = get_prop_val(find_prop(pnode, "status"));
name = get_node_name(pnode);
if ((status == NULL) || (name == NULL)) {
pnode = next_failed_node(pnode);
continue;
}
type = get_node_type(pnode);
portid = get_id(pnode);
model = (char *)get_prop_val
(find_prop(pnode, "model"));
if ((model != NULL) && strstr(model, "sgsbbc")) {
portid = get_id(pnode->parent);
nodeid = SG_PORTID_TO_NODEID(portid);
board = SG_PORTID_TO_BOARD_NUM(portid);
SG_SET_FRU_NAME_NODE(fru_name, nodeid);
SG_SET_FRU_NAME_IO_BOARD(fru_name, board);
SG_SET_FRU_NAME_MODULE(fru_name, portid % 2);
log_printf("\tFailed Device : %s (%s)\n", model,
name, 0);
log_printf("\tLocation : %s\n", fru_name, 0);
} else if (strstr(name, "pci") && (portid == -1)) {
portid = get_id(pnode->parent);
nodeid = SG_PORTID_TO_NODEID(portid);
board = SG_PORTID_TO_BOARD_NUM(portid);
SG_SET_FRU_NAME_NODE(fru_name, nodeid);
SG_SET_FRU_NAME_IO_BOARD(fru_name, board);
SG_SET_FRU_NAME_MODULE(fru_name, portid % 2);
log_printf("\tFRU type : ", 0);
log_printf("PCI Bridge Device\n", 0);
log_printf("\tLocation : %s\n", fru_name, 0);
} else if ((type != NULL) &&
(strstr(type, "cpu") ||
strstr(type, "memory-controller"))) {
portid = get_id(pnode);
if (portid == -1)
portid = get_id(pnode->parent);
nodeid = SG_PORTID_TO_NODEID(portid);
board = SG_PORTID_TO_BOARD_NUM(portid);
SG_SET_FRU_NAME_NODE(fru_name, nodeid);
SG_SET_FRU_NAME_CPU_BOARD(fru_name, board);
SG_SET_FRU_NAME_MODULE(fru_name, portid % 4);
log_printf("\tFRU type : ", 0);
if (strstr(type, "memory-controller"))
log_printf("Memory Controller on ", 0);
log_printf("UltraSPARC module\n", 0);
log_printf("\tLocation : %s\n", fru_name, 0);
} else {
char *parents_model, *grandparents_model;
Prom_node *parent_pnode;
int pci_card_found = 0;
if (pnode->parent != NULL)
parent_pnode = pnode->parent;
parents_model = (char *)get_prop_val
(find_prop(pnode->parent, "model"));
if ((parents_model != NULL) &&
(strstr(parents_model, "SUNW,schizo") ||
strstr(parents_model, "SUNW,xmits"))) {
portid = get_id(pnode->parent);
pci_card_found = TRUE;
}
grandparents_model = (char *)get_prop_val
(find_prop(parent_pnode->parent, "model"));
if ((grandparents_model != NULL) &&
(strstr(grandparents_model,
"SUNW,schizo") ||
strstr(grandparents_model,
"SUNW,xmits"))) {
portid = get_id(parent_pnode->parent);
pci_card_found = TRUE;
}
if (pci_card_found) {
nodeid = SG_PORTID_TO_NODEID(portid);
board = SG_PORTID_TO_BOARD_NUM(portid);
SG_SET_FRU_NAME_NODE(fru_name, nodeid);
SG_SET_FRU_NAME_IO_BOARD(fru_name,
board);
SG_SET_FRU_NAME_MODULE(fru_name,
portid % 2);
log_printf("\tFRU type :", 0);
log_printf(" PCI Card\n", 0);
log_printf("\tLocation : %s\n",
fru_name, 0);
}
}
log_printf("\tPROM status: %s\n\n", status, 0);
pnode = next_failed_node(pnode);
}
bnode = bnode->next;
}
bank_failed = display_us3_failed_banks(system_failed);
schizo_failed = display_schizo_revisions(tree->bd_list,
SG_SCHIZO_FAILED);
if (system_failed || bank_failed || schizo_failed)
return (1);
else
return (0);
}
void
display_memoryconf(Sys_tree *tree)
{
Board_node *bnode = tree->bd_list;
log_printf("========================= Memory Configuration"
" ===============================\n", 0);
log_printf("\n Logical Logical Logical ", 0);
log_printf("\n Port Bank Bank Bank "
"DIMM Interleave Interleave", 0);
log_printf("\nFRU Name ID Num Size Status "
"Size Factor Segment", 0);
log_printf("\n------------- ---- ---- ------ ----------- "
"------ ---------- ----------", 0);
while (bnode != NULL) {
if (get_us3_mem_regs(bnode)) {
log_printf(dgettext(TEXT_DOMAIN,
"\nFailed to get memory information.\n"), 0);
return;
}
bnode = bnode->next;
}
display_us3_banks();
}
void
print_us3_memory_line(int portid, int bank_id, uint64_t bank_size,
char *bank_status, uint64_t dimm_size, uint32_t intlv, int seg_id)
{
int nodeid, board, mcid;
char fru_name[MAX_FRU_NAME_LEN] = "";
mcid = SG_PORTID_TO_SAFARI_ID(portid);
nodeid = SG_PORTID_TO_NODEID(portid);
board = SG_PORTID_TO_BOARD_NUM(portid);
SG_SET_FRU_NAME_NODE(fru_name, nodeid);
SG_SET_FRU_NAME_CPU_BOARD(fru_name, board);
SG_SET_FRU_NAME_MODULE(fru_name, mcid % 4);
SG_SET_FRU_NAME_BANK(fru_name, (bank_id % 4) % 2);
log_printf("\n%-13s %2d %2d %4lldMB %11-s %4lldMB "
" %2d-way %d",
fru_name, mcid,
(bank_id % 4), bank_size, bank_status, dimm_size,
intlv, seg_id, 0);
}
void
print_us3_failed_memory_line(int portid, int bank_id, char *bank_status)
{
int nodeid, board, mcid;
char fru_name[MAX_FRU_NAME_LEN] = "";
mcid = SG_PORTID_TO_SAFARI_ID(portid);
nodeid = SG_PORTID_TO_NODEID(portid);
board = SG_PORTID_TO_BOARD_NUM(portid);
SG_SET_FRU_NAME_NODE(fru_name, nodeid);
SG_SET_FRU_NAME_CPU_BOARD(fru_name, board);
SG_SET_FRU_NAME_MODULE(fru_name, mcid % 4);
SG_SET_FRU_NAME_BANK(fru_name, (bank_id % 4) % 2);
log_printf("\tFRU type : ", 0);
log_printf("Physical Memory Bank\n", 0);
log_printf("\tLocation : %s (Logical Bank %2d)\n",
fru_name, (bank_id %4), 0);
log_printf("\tPROM status: %s\n\n", bank_status, 0);
}
static Board_node *
serengeti_find_board(Sys_tree *root, int board, int nodeid)
{
Board_node *bnode = root->bd_list;
while ((bnode != NULL) &&
((board != bnode->board_num) || (nodeid != bnode->node_id))) {
bnode = bnode->next;
}
return (bnode);
}
static Board_node *
serengeti_insert_board(Sys_tree *root, int board, int nodeid)
{
Board_node *bnode;
Board_node *temp = root->bd_list;
if ((bnode = (Board_node *) malloc(sizeof (Board_node))) == NULL) {
perror("malloc");
exit(1);
}
bnode->nodes = NULL;
bnode->next = NULL;
bnode->board_num = board;
bnode->node_id = nodeid;
bnode->board_type = UNKNOWN_BOARD;
if (temp == NULL)
root->bd_list = bnode;
else if ((temp->board_num > board) && (temp->node_id >= nodeid)) {
bnode->next = temp;
root->bd_list = bnode;
} else {
while ((temp->next != NULL) &&
((board > temp->next->board_num) ||
(nodeid > temp->node_id)))
temp = temp->next;
bnode->next = temp->next;
temp->next = bnode;
}
root->board_cnt++;
return (bnode);
}
int
do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag)
{
return (do_devinfo(syserrlog, pgname, log_flag, prt_flag));
}
void *
get_prop_val(Prop *prop)
{
if (prop == NULL)
return (NULL);
if (tree == DEVINFO_TREE)
return ((void *)(prop->value.val_ptr));
else {
if (prop->value.opp.holds_array)
return ((void *)(prop->value.opp.oprom_array));
else
return ((void *)(&prop->value.opp.oprom_node[0]));
}
}
Prop *
find_prop(Prom_node *pnode, char *name)
{
Prop *prop;
if (pnode == NULL)
return (NULL);
if (pnode->props == NULL)
return (NULL);
prop = pnode->props;
if (tree == DEVINFO_TREE) {
while ((prop != NULL) &&
(strcmp((char *)(prop->name.val_ptr), name)))
prop = prop->next;
} else {
while ((prop != NULL) && (strcmp((char *)
(prop->name.opp.oprom_array), name)))
prop = prop->next;
}
return (prop);
}
char *
get_node_name(Prom_node *pnode)
{
Prop *prop;
if (pnode == NULL)
return (NULL);
prop = pnode->props;
while (prop != NULL) {
if (tree == DEVINFO_TREE) {
if (strcmp("name", (char *)prop->name.val_ptr) == 0)
return ((char *)prop->value.val_ptr);
} else {
if (strcmp("name", prop->name.opp.oprom_array) == 0)
return (prop->value.opp.oprom_array);
}
prop = prop->next;
}
return (NULL);
}
char *
get_node_type(Prom_node *pnode)
{
Prop *prop;
if (pnode == NULL)
return (NULL);
prop = pnode->props;
while (prop != NULL) {
if (tree == DEVINFO_TREE) {
if (strcmp("device_type", (char *)prop->name.val_ptr)
== 0)
return ((char *)prop->value.val_ptr);
} else {
if (strcmp("device_type", prop->name.opp.oprom_array)
== 0)
return (prop->value.opp.oprom_array);
}
prop = prop->next;
}
return (NULL);
}
void
get_failed_parts(void)
{
int system_failed = 0;
Sys_tree obp_sys_tree;
obp_sys_tree.sys_mem = NULL;
obp_sys_tree.boards = NULL;
obp_sys_tree.bd_list = NULL;
obp_sys_tree.board_cnt = 0;
if (promopen(O_RDONLY)) {
(void) fprintf(stderr, "%s",
dgettext(TEXT_DOMAIN, "openprom device "
"open failed"));
return;
}
if ((is_openprom() == 0) || (next(0) == 0)) {
(void) fprintf(stderr, "%s",
dgettext(TEXT_DOMAIN, "openprom device "
"error encountered."));
return;
}
tree = OBP_TREE;
(void) walk(&obp_sys_tree, NULL, next(0));
system_failed = display_failed_parts(&obp_sys_tree);
if (!system_failed) {
log_printf(dgettext(TEXT_DOMAIN,
"No Hardware failures found in System\n"), 0);
}
promclose();
tree = DEVINFO_TREE;
}
static void
get_slot_name(struct io_card *card, char *slot_name)
{
char tmp_ptr[2];
if (strlen(slot_name) != 0) {
if (strcmp(card->notes, XMITS_COMPATIBLE) == 0) {
(void) sprintf(tmp_ptr, "%c",
slot_name[strlen(slot_name) -1]);
switch (tmp_ptr[0]) {
case '2':
(void) sprintf(card->slot_str, "%c", '3');
break;
case '3':
(void) sprintf(card->slot_str, "%c", '2');
break;
case '6':
(void) sprintf(card->slot_str, "%c", '7');
break;
case '7':
(void) sprintf(card->slot_str, "%c", '6');
break;
default:
(void) sprintf(card->slot_str, "%c",
slot_name[strlen(slot_name) -1]);
}
} else
(void) sprintf(card->slot_str, "%c",
slot_name[strlen(slot_name) -1]);
} else
(void) sprintf(card->slot_str, "-");
}