11708Sstevel /*
21708Sstevel * CDDL HEADER START
31708Sstevel *
41708Sstevel * The contents of this file are subject to the terms of the
5*5889Szk194757 * Common Development and Distribution License (the "License").
6*5889Szk194757 * You may not use this file except in compliance with the License.
71708Sstevel *
81708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel * or http://www.opensolaris.org/os/licensing.
101708Sstevel * See the License for the specific language governing permissions
111708Sstevel * and limitations under the License.
121708Sstevel *
131708Sstevel * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel *
191708Sstevel * CDDL HEADER END
201708Sstevel */
211708Sstevel /*
22*5889Szk194757 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
231708Sstevel * Use is subject to license terms.
241708Sstevel *
251708Sstevel * Serengeti Platform specific functions.
261708Sstevel *
271708Sstevel */
281708Sstevel
291708Sstevel #pragma ident "%Z%%M% %I% %E% SMI"
301708Sstevel
311708Sstevel #include <stdio.h>
321708Sstevel #include <stdlib.h>
331708Sstevel #include <unistd.h>
341708Sstevel #include <kstat.h>
351708Sstevel #include <string.h>
361708Sstevel #include <assert.h>
371708Sstevel #include <alloca.h>
381708Sstevel #include <libintl.h>
391708Sstevel #include <fcntl.h>
401708Sstevel #include <varargs.h>
411708Sstevel
421708Sstevel #include <sys/openpromio.h>
431708Sstevel #include <sys/sysmacros.h>
441708Sstevel
451708Sstevel #include <sys/serengeti.h>
461708Sstevel #include <sys/sgfrutypes.h>
471708Sstevel
481708Sstevel #include <pdevinfo.h>
491708Sstevel #include <display.h>
501708Sstevel #include <pdevinfo_sun4u.h>
511708Sstevel #include <display_sun4u.h>
521708Sstevel #include <libprtdiag.h>
531708Sstevel
541708Sstevel #include <config_admin.h>
551708Sstevel
561708Sstevel #if !defined(TEXT_DOMAIN)
571708Sstevel #define TEXT_DOMAIN "SYS_TEST"
581708Sstevel #endif
591708Sstevel
601708Sstevel #define SCHIZO_COMPATIBLE "pci108e,8001"
611708Sstevel #define XMITS_COMPATIBLE "pci108e,8002"
621708Sstevel
631708Sstevel #define ACTIVE 0
641708Sstevel #define INACTIVE 1
651708Sstevel #define DISPLAY_INFO 40
661708Sstevel
671708Sstevel #define EVNT2STR(e) ((e) == CFGA_STAT_NONE ? "none" : \
681708Sstevel (e) == CFGA_STAT_EMPTY ? "empty" : \
691708Sstevel (e) == CFGA_STAT_DISCONNECTED ? "disconnected" : \
701708Sstevel (e) == CFGA_STAT_CONNECTED ? "connected" : \
711708Sstevel (e) == CFGA_STAT_UNCONFIGURED ? "unconfigured" : \
721708Sstevel (e) == CFGA_STAT_CONFIGURED ? "configured" : \
731708Sstevel "unknown")
741708Sstevel
751708Sstevel #define COND2STR(c) ((c) == CFGA_COND_UNKNOWN ? "unknown" : \
761708Sstevel (c) == CFGA_COND_OK ? "ok" : \
771708Sstevel (c) == CFGA_COND_FAILING ? "failing" : \
781708Sstevel (c) == CFGA_COND_FAILED ? "failed" : \
791708Sstevel (c) == CFGA_COND_UNUSABLE ? "unusable" : \
801708Sstevel "???")
811708Sstevel
821708Sstevel #define SG_CLK_FREQ_TO_MHZ(x) (((x) + 500000) / 1000000)
831708Sstevel
841708Sstevel #define MAX_STATUS_LEN 8
851708Sstevel #define SG_FAIL "fail"
861708Sstevel #define SG_DISABLED "disabled"
871708Sstevel #define SG_DEGRADED "degraded"
881708Sstevel #define SG_OK "ok"
891708Sstevel
901708Sstevel #define SG_SCHIZO_FAILED 1
911708Sstevel #define SG_SCHIZO_GOOD 0
921708Sstevel
931708Sstevel #define DEFAULT_MAX_FREQ 66 /* 66 MHz */
941708Sstevel #define PCIX_MAX_FREQ 100 /* 100 MHz */
951708Sstevel
961708Sstevel #define CFG_CPU "::cpu"
971708Sstevel
981708Sstevel #define CFG_SET_FRU_NAME_NODE(str, num) \
991708Sstevel { \
1001708Sstevel char tmp_str[MAX_FRU_NAME_LEN]; \
1011708Sstevel sprintf(tmp_str, "/N%d", num); \
1021708Sstevel strncat(str, tmp_str, sizeof (tmp_str)); \
1031708Sstevel }
1041708Sstevel
1051708Sstevel #define CFG_SET_FRU_NAME_CPU_BOARD(str, num) \
1061708Sstevel { \
1071708Sstevel char tmp_str[MAX_FRU_NAME_LEN]; \
1081708Sstevel sprintf(tmp_str, ".%s%d", SG_HPU_TYPE_CPU_BOARD_ID, num); \
1091708Sstevel strncat(str, tmp_str, sizeof (tmp_str)); \
1101708Sstevel }
1111708Sstevel
1121708Sstevel #define CFG_SET_FRU_NAME_MODULE(str, num) \
1131708Sstevel { \
1141708Sstevel char tmp_str[MAX_FRU_NAME_LEN]; \
1151708Sstevel sprintf(tmp_str, "%s%d", CFG_CPU, num); \
1161708Sstevel strncat(str, tmp_str, sizeof (tmp_str)); \
1171708Sstevel }
1181708Sstevel
1191708Sstevel extern int print_flag;
1201708Sstevel
1211708Sstevel /*
1221708Sstevel * these functions will overlay the symbol table of libprtdiag
1231708Sstevel * at runtime (Serengeti systems only)
1241708Sstevel */
1251708Sstevel int do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag);
1261708Sstevel void *get_prop_val(Prop *prop);
1271708Sstevel Prop *find_prop(Prom_node *pnode, char *name);
1281708Sstevel char *get_node_name(Prom_node *pnode);
1291708Sstevel char *get_node_type(Prom_node *pnode);
1301708Sstevel void add_node(Sys_tree *, Prom_node *);
1311708Sstevel void display_pci(Board_node *);
1321708Sstevel void display_ffb(Board_node *, int);
1331708Sstevel void display_io_cards(struct io_card *list);
1341708Sstevel void display_cpu_devices(Sys_tree *tree);
1351708Sstevel void display_cpus(Board_node *board);
1361708Sstevel void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
1371708Sstevel struct system_kstat_data *kstats);
1381708Sstevel void display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats);
1391708Sstevel void get_failed_parts(void);
1401708Sstevel int display_failed_parts(Sys_tree *tree);
1411708Sstevel void display_memoryconf(Sys_tree *tree, struct grp_info *grps);
1421708Sstevel void print_us3_memory_line(int portid, int bank_id, uint64_t bank_size,
1431708Sstevel char *bank_status, uint64_t dimm_size, uint32_t intlv, int seg_id);
1441708Sstevel
1451708Sstevel /* Local Functions */
1461708Sstevel static void serengeti_display_hw_revisions(Prom_node *root,
1471708Sstevel Board_node *bnode);
1481708Sstevel static Board_node *serengeti_find_board(Sys_tree *root, int board, int nodeid);
1491708Sstevel static Board_node *serengeti_insert_board(Sys_tree *root, int board, int nid);
1501708Sstevel static int display_schizo_revisions(Board_node *bdlist, int mode);
1511708Sstevel static void display_sgsbbc_revisions(Board_node *bdlist);
1521708Sstevel static void serengeti_display_board_info(int state);
1531708Sstevel static void serengeti_display_board_info_header(int state);
1541708Sstevel static boolean_t cpu_node_configured(char *const node);
1551708Sstevel static void display_io_max_bus_speed(struct io_card *p);
1561708Sstevel static void display_io_slot_info(struct io_card *p);
1571708Sstevel static void get_slot_name(struct io_card *card, char *slot_name);
1581708Sstevel
1591708Sstevel /* The bus max freq is determined based on board level in use */
1601708Sstevel int board_bus_max_freq = DEFAULT_MAX_FREQ; /* 66MHz default */
1611708Sstevel
1621708Sstevel /*
1631708Sstevel * Serengeti now uses both the devinfo tree and the OBP tree for it's
1641708Sstevel * prtdiag. The devinfo tree is used for getting the HW config of the
1651708Sstevel * system and the OBP device tree is used for listing the failed HW
1661708Sstevel * in the system. This is because devinfo currently does not include
1671708Sstevel * any PROM nodes with a status of 'fail' so we need to go to OBP to
1681708Sstevel * get a list of failed HW. We use the tree flag to allow the same code
1691708Sstevel * to walk both trees.
1701708Sstevel *
1711708Sstevel * We really need to look at having a single tree for all platforms!
1721708Sstevel */
1731708Sstevel #define DEVINFO_TREE 1
1741708Sstevel #define OBP_TREE 2
1751708Sstevel
1761708Sstevel static int tree = DEVINFO_TREE;
1771708Sstevel
1781708Sstevel #ifdef DEBUG
1791708Sstevel #define D_PRINTFINDENT printfindent
1801708Sstevel void
printfindent(int indent,char * fmt,...)1811708Sstevel printfindent(int indent, char *fmt, ...)
1821708Sstevel {
1831708Sstevel va_list ap;
1841708Sstevel int i = 0;
1851708Sstevel for (i = 0; i < indent; i ++)
1861708Sstevel printf("\t");
1871708Sstevel
1881708Sstevel va_start(ap);
1891708Sstevel (void) vprintf(fmt, ap);
1901708Sstevel va_end(ap);
1911708Sstevel }
1921708Sstevel #else
1931708Sstevel #define D_PRINTFINDENT
1941708Sstevel #endif
1951708Sstevel
1961708Sstevel /*
1971708Sstevel * display_pci
1981708Sstevel * Display all the PCI IO cards on this board.
1991708Sstevel */
2001708Sstevel void
display_pci(Board_node * board)2011708Sstevel display_pci(Board_node *board)
2021708Sstevel {
2031708Sstevel struct io_card *card_list = NULL;
2041708Sstevel struct io_card card;
2051708Sstevel void *value;
2061708Sstevel Prom_node *pci;
2071708Sstevel Prom_node *card_node;
2081708Sstevel Prom_node *pci_bridge_node;
2091708Sstevel Prom_node *child_pci_bridge_node;
2101708Sstevel char *slot_name = NULL; /* info in "slot-names" prop */
2111708Sstevel char *child_name;
2121708Sstevel char *name, *type;
2131708Sstevel char *pname, *ptype;
2141708Sstevel char buf[MAXSTRLEN];
2151708Sstevel int *int_val;
2161708Sstevel int pci_bus;
2171708Sstevel int pci_bridge = 0;
2181708Sstevel int pci_bridge_dev_no;
2191708Sstevel char *slot_name_arr[SG_MAX_SLOTS_PER_IO_BD] = {NULL};
2201708Sstevel int i;
2211708Sstevel int portid;
2221708Sstevel int level = 0;
2231708Sstevel int version, *pversion;
2241708Sstevel #ifdef DEBUG
2251708Sstevel int slot_name_bits;
2261708Sstevel #endif
2271708Sstevel
2281708Sstevel if (board == NULL)
2291708Sstevel return;
2301708Sstevel
2311708Sstevel /* Initialize all the common information */
2321708Sstevel card.display = TRUE;
2331708Sstevel card.board = board->board_num;
2341708Sstevel card.node_id = board->node_id;
2351708Sstevel
2361708Sstevel /*
2371708Sstevel * Search for each schizo and xmits, then find/display all nodes under
2381708Sstevel * each schizo and xmits node found.
2391708Sstevel */
2401708Sstevel for (pci = dev_find_node_by_compatible(board->nodes, SCHIZO_COMPATIBLE);
241*5889Szk194757 pci != NULL;
242*5889Szk194757 pci = dev_next_node_by_compatible(pci, SCHIZO_COMPATIBLE)) {
2431708Sstevel
2441708Sstevel /* set max freq for this board */
2451708Sstevel board_bus_max_freq = DEFAULT_MAX_FREQ;
2461708Sstevel /*
2471708Sstevel * Find out if this is a PCI or cPCI IO Board.
2481708Sstevel * If "enum-impl" property exists in pci node => cPCI.
2491708Sstevel */
2501708Sstevel value = get_prop_val(find_prop(pci, "enum-impl"));
2511708Sstevel if (value == NULL) {
2521708Sstevel (void) sprintf(card.bus_type, "PCI");
2531708Sstevel } else {
2541708Sstevel (void) sprintf(card.bus_type, "cPCI");
2551708Sstevel }
2561708Sstevel
2571708Sstevel if (strstr((char *)get_prop_val(
2581708Sstevel find_prop(pci, "compatible")), XMITS_COMPATIBLE)) {
2591708Sstevel sprintf(card.notes, "%s", XMITS_COMPATIBLE);
2601708Sstevel /*
2611708Sstevel * With XMITS 3.X and PCI-X mode, the bus speed
2621708Sstevel * can be higher than 66MHZ.
2631708Sstevel */
2641708Sstevel value = (int *)get_prop_val
265*5889Szk194757 (find_prop(pci, "module-revision#"));
2661708Sstevel if (value) {
2671708Sstevel pversion = (int *)value;
2681708Sstevel version = *pversion;
2691708Sstevel if (version >= 4)
2701708Sstevel board_bus_max_freq = PCIX_MAX_FREQ;
2711708Sstevel }
2721708Sstevel } else if (strstr((char *)get_prop_val(
2731708Sstevel find_prop(pci, "compatible")), SCHIZO_COMPATIBLE))
2741708Sstevel sprintf(card.notes, "%s", SCHIZO_COMPATIBLE);
2751708Sstevel else
2761708Sstevel sprintf(card.notes, " ");
2771708Sstevel
2781708Sstevel /*
2791708Sstevel * Get slot-name properties from parent node and
2801708Sstevel * store them in an array.
2811708Sstevel */
2821708Sstevel value = (char *)get_prop_val(find_prop(pci, "slot-names"));
2831708Sstevel if (value != NULL) {
2841708Sstevel #ifdef DEBUG
2851708Sstevel /* save the 4 byte bitmask */
2861708Sstevel slot_name_bits = *(int *)value;
2871708Sstevel #endif
2881708Sstevel /* array starts after first int */
2891708Sstevel slot_name_arr[0] = (char *)value + sizeof (int);
2901708Sstevel
2911708Sstevel D_PRINTFINDENT(0, "slot_name_arr[0] is [%s]\n",
2921708Sstevel slot_name_arr[0]);
2931708Sstevel
2941708Sstevel for (i = 1; i < SG_MAX_SLOTS_PER_IO_BD; i++) {
2951708Sstevel slot_name_arr[i] = (char *)slot_name_arr[i - 1]
296*5889Szk194757 + strlen(slot_name_arr[i - 1]) +1;
2971708Sstevel
2981708Sstevel D_PRINTFINDENT(0, "slot_name_arr[%d] is [%s]\n", i,
2991708Sstevel slot_name_arr[i]);
3001708Sstevel
3011708Sstevel }
3021708Sstevel }
3031708Sstevel
3041708Sstevel /*
3051708Sstevel * Search for Children of this node ie. Cards.
3061708Sstevel * Note: any of these cards can be a pci-bridge
3071708Sstevel * that itself has children. If we find a
3081708Sstevel * pci-bridge we need to handle it specially.
3091708Sstevel *
3101708Sstevel * There can now be the condition of a pci-bridge
3111708Sstevel * being the child of a pci-bridge which create a
3121708Sstevel * two levels of pci-bridges. This special condition
3131708Sstevel * needs to be handled as well. The variable level
3141708Sstevel * is used to track the depth of the tree. This
3151708Sstevel * variable is then used to find instances of this case.
3161708Sstevel */
3171708Sstevel level = 0;
3181708Sstevel card_node = pci->child;
3191708Sstevel while (card_node != NULL) {
3201708Sstevel pci_bridge = 0;
3211708Sstevel
3221708Sstevel /* If it doesn't have a name, skip it */
3231708Sstevel name = (char *)get_prop_val(
324*5889Szk194757 find_prop(card_node, "name"));
3251708Sstevel if (name == NULL) {
3261708Sstevel card_node = card_node->sibling;
3271708Sstevel continue;
3281708Sstevel }
3291708Sstevel D_PRINTFINDENT(level, "NAME is %s\n", name);
3301708Sstevel
3311708Sstevel type = (char *)get_prop_val(
332*5889Szk194757 find_prop(card_node, "device_type"));
3331708Sstevel
3341708Sstevel /*
3351708Sstevel * get dev# and func# for this card from the
3361708Sstevel * 'reg' property.
3371708Sstevel */
3381708Sstevel int_val = (int *)get_prop_val(
339*5889Szk194757 find_prop(card_node, "reg"));
3401708Sstevel if (int_val != NULL) {
3411708Sstevel card.dev_no = (((*int_val) & 0xF800) >> 11);
3421708Sstevel card.func_no = (((*int_val) & 0x700) >> 8);
3431708Sstevel } else {
3441708Sstevel card.dev_no = -1;
3451708Sstevel card.func_no = -1;
3461708Sstevel }
3471708Sstevel
3481708Sstevel /*
3491708Sstevel * If this is a pci-bridge, then store it's dev#
3501708Sstevel * as it's children nodes need this to get their slot#.
3511708Sstevel * We set the pci_bridge flag so that we know we are
3521708Sstevel * looking at a pci-bridge node. This flag gets reset
3531708Sstevel * every time we enter this while loop.
3541708Sstevel */
3551708Sstevel
3561708Sstevel /*
3571708Sstevel * Check for a PCI-PCI Bridge for PCI and cPCI
3581708Sstevel * IO Boards using the name and type properties.
3591708Sstevel *
3601708Sstevel * If level is greater then 0, then check the parent
3611708Sstevel * node to see if it was also a pci-bridge. We do not
3621708Sstevel * this when level is 0 as this will see the schizo or
3631708Sstevel * xmits device as a pci-bridge node. This will mess
3641708Sstevel * up the slot number of child nodes.
3651708Sstevel */
3661708Sstevel if ((type != NULL) &&
367*5889Szk194757 (strncmp(name, "pci", 3) == 0) &&
368*5889Szk194757 (strcmp(type, "pci") == 0)) {
3691708Sstevel if (level > 0) {
370*5889Szk194757 pname = (char *)get_prop_val(
371*5889Szk194757 find_prop(card_node->parent,
372*5889Szk194757 "name"));
373*5889Szk194757 ptype = (char *)get_prop_val(
374*5889Szk194757 find_prop(card_node->parent,
3751708Sstevel "device_type"));
3761708Sstevel
377*5889Szk194757 if ((ptype != NULL) &&
378*5889Szk194757 (pname != NULL) &&
379*5889Szk194757 (strncmp(pname, "pci", 3) == 0) &&
380*5889Szk194757 (strcmp(ptype, "pci") == 0)) {
381*5889Szk194757 child_pci_bridge_node =
382*5889Szk194757 card_node;
383*5889Szk194757 } else {
384*5889Szk194757 pci_bridge_dev_no = card.dev_no;
385*5889Szk194757 pci_bridge_node = card_node;
386*5889Szk194757 }
3871708Sstevel } else {
3881708Sstevel pci_bridge_dev_no = card.dev_no;
3891708Sstevel pci_bridge_node = card_node;
3901708Sstevel }
3911708Sstevel pci_bridge = TRUE;
3921708Sstevel
3931708Sstevel D_PRINTFINDENT(level,
3941708Sstevel "pci_bridge_dev_no is [%d]\n",
3951708Sstevel pci_bridge_dev_no);
3961708Sstevel }
3971708Sstevel
3981708Sstevel /*
3991708Sstevel * Get slot-names property from slot_names_arr.
4001708Sstevel * If we are the child of a pci_bridge we use the
4011708Sstevel * dev# of the pci_bridge as an index to get
4021708Sstevel * the slot number. We know that we are a child of
4031708Sstevel * a pci-bridge if our parent is the same as the last
4041708Sstevel * pci_bridge node found above.
4051708Sstevel */
4061708Sstevel if (type)
4071708Sstevel D_PRINTFINDENT(level,
4081708Sstevel "*** name is [%s] - type is [%s]\n",
4091708Sstevel name, type);
4101708Sstevel else
4111708Sstevel D_PRINTFINDENT(level,
4121708Sstevel "*** name is [%s]\n", name);
4131708Sstevel
4141708Sstevel if (card.dev_no != -1) {
4151708Sstevel /*
4161708Sstevel * We compare this cards parent node with the
4171708Sstevel * pci_bridge_node to see if it's a child.
4181708Sstevel */
4191708Sstevel if (((level > 0) &&
4201708Sstevel (card_node->parent->parent ==
4211708Sstevel pci_bridge_node)) ||
4221708Sstevel (card_node->parent == pci_bridge_node)) {
4231708Sstevel /* use dev_no of pci_bridge */
4241708Sstevel D_PRINTFINDENT(level,
4251708Sstevel " pci_bridge_dev_no is [%d]\n",
4261708Sstevel pci_bridge_dev_no);
4271708Sstevel
4281708Sstevel slot_name =
4291708Sstevel slot_name_arr[pci_bridge_dev_no -1];
4301708Sstevel } else {
4311708Sstevel /* use cards own dev_no */
4321708Sstevel D_PRINTFINDENT(level,
4331708Sstevel " card.dev_no is [%d]\n",
4341708Sstevel card.dev_no);
4351708Sstevel
4361708Sstevel slot_name =
4371708Sstevel slot_name_arr[card.dev_no - 1];
4381708Sstevel }
4391708Sstevel
4401708Sstevel get_slot_name(&card, slot_name);
4411708Sstevel
4421708Sstevel } else {
4431708Sstevel (void) sprintf(card.slot_str, "%c", '-');
4441708Sstevel }
4451708Sstevel
4461708Sstevel /*
4471708Sstevel * Get the portid of the schizo and xmits that this card
4481708Sstevel * lives under.
4491708Sstevel */
4501708Sstevel portid = -1;
4511708Sstevel value = get_prop_val(find_prop(pci, "portid"));
4521708Sstevel if (value != NULL) {
4531708Sstevel portid = *(int *)value;
4541708Sstevel }
4551708Sstevel card.schizo_portid = portid;
4561708Sstevel
4571708Sstevel #ifdef DEBUG
4581708Sstevel (void) sprintf(card.notes, "%s portid [%d] dev_no[%d]"
459*5889Szk194757 " slot_name[%s] name_bits[%d]",
460*5889Szk194757 card.notes,
461*5889Szk194757 portid,
462*5889Szk194757 card.dev_no, slot_name,
463*5889Szk194757 slot_name_bits);
4641708Sstevel #endif
4651708Sstevel
4661708Sstevel /*
4671708Sstevel * Find out whether this is PCI bus A or B
4681708Sstevel * using the 'reg' property.
4691708Sstevel */
4701708Sstevel int_val = (int *)get_prop_val
471*5889Szk194757 (find_prop(pci, "reg"));
4721708Sstevel
4731708Sstevel if (int_val != NULL) {
4741708Sstevel int_val ++; /* skip over first integer */
4751708Sstevel pci_bus = ((*int_val) & 0x7f0000);
4761708Sstevel if (pci_bus == 0x600000)
4771708Sstevel card.pci_bus = 'A';
4781708Sstevel else if (pci_bus == 0x700000)
4791708Sstevel card.pci_bus = 'B';
4801708Sstevel else
4811708Sstevel card.pci_bus = '-';
4821708Sstevel } else {
4831708Sstevel card.pci_bus = '-';
4841708Sstevel }
4851708Sstevel
4861708Sstevel
4871708Sstevel /*
4881708Sstevel * Check for failed status.
4891708Sstevel */
4901708Sstevel if (node_status(card_node, SG_FAIL))
4911708Sstevel strncpy(card.status, SG_FAIL,
492*5889Szk194757 sizeof (SG_FAIL));
4931708Sstevel else if (node_status(card_node, SG_DISABLED))
4941708Sstevel strncpy(card.status, SG_DISABLED,
495*5889Szk194757 sizeof (SG_DISABLED));
4961708Sstevel else
4971708Sstevel strncpy(card.status, SG_OK,
498*5889Szk194757 sizeof (SG_OK));
4991708Sstevel
5001708Sstevel /* Get the model of this card */
5011708Sstevel value = get_prop_val(find_prop(card_node, "model"));
5021708Sstevel if (value == NULL)
5031708Sstevel card.model[0] = '\0';
5041708Sstevel else {
5051708Sstevel (void) sprintf(card.model, "%s",
506*5889Szk194757 (char *)value);
5071708Sstevel /* Skip sgsbbc nodes, they are not cards */
5081708Sstevel if (strcmp(card.model, "SUNW,sgsbbc") == 0) {
5091708Sstevel card_node = card_node->sibling;
5101708Sstevel continue;
5111708Sstevel }
5121708Sstevel }
5131708Sstevel
5141708Sstevel /*
5151708Sstevel * Check if further processing is necessary to display
5161708Sstevel * this card uniquely.
5171708Sstevel */
5181708Sstevel distinguish_identical_io_cards(name, card_node, &card);
5191708Sstevel
5201708Sstevel /*
5211708Sstevel * The card may have a "clock-frequency" but we
5221708Sstevel * are not interested in that. Instead we get the
5231708Sstevel * "clock-frequency" of the PCI Bus that the card
5241708Sstevel * resides on. PCI-A can operate at 33Mhz or 66Mhz
5251708Sstevel * depending on what card is plugged into the Bus.
5261708Sstevel * PCI-B always operates at 33Mhz.
5271708Sstevel *
5281708Sstevel */
5291708Sstevel int_val = get_prop_val(find_prop(pci,
530*5889Szk194757 "clock-frequency"));
5311708Sstevel if (int_val != NULL) {
5321708Sstevel card.freq = SG_CLK_FREQ_TO_MHZ(*int_val);
5331708Sstevel } else {
5341708Sstevel card.freq = -1;
5351708Sstevel }
5361708Sstevel
5371708Sstevel /*
5381708Sstevel * Figure out how we want to display the name
5391708Sstevel */
5401708Sstevel value = get_prop_val(find_prop(card_node,
541*5889Szk194757 "compatible"));
5421708Sstevel if (value != NULL) {
5431708Sstevel /* use 'name'-'compatible' */
5441708Sstevel (void) sprintf(buf, "%s-%s", name,
545*5889Szk194757 (char *)value);
5461708Sstevel } else {
5471708Sstevel /* just use 'name' */
5481708Sstevel (void) sprintf(buf, "%s", name);
5491708Sstevel }
5501708Sstevel name = buf;
5511708Sstevel
5521708Sstevel /*
5531708Sstevel * If this node has children, add the device_type
5541708Sstevel * of the child to the name value of this card.
5551708Sstevel */
5561708Sstevel child_name = (char *)get_node_name(card_node->child);
5571708Sstevel if ((card_node->child != NULL) &&
558*5889Szk194757 (child_name != NULL)) {
5591708Sstevel value = get_prop_val(find_prop(card_node->child,
560*5889Szk194757 "device_type"));
5611708Sstevel if (value != NULL) {
5621708Sstevel /* add device_type of child to name */
5631708Sstevel (void) sprintf(card.name, "%s/%s (%s)",
564*5889Szk194757 name, child_name,
565*5889Szk194757 (char *)value);
5661708Sstevel } else {
5671708Sstevel /* just add childs name */
5681708Sstevel (void) sprintf(card.name, "%s/%s", name,
569*5889Szk194757 child_name);
5701708Sstevel }
5711708Sstevel } else {
5721708Sstevel (void) sprintf(card.name, "%s", (char *)name);
5731708Sstevel }
5741708Sstevel
5751708Sstevel /*
5761708Sstevel * If this is a pci-bridge, then add the word
5771708Sstevel * 'pci-bridge' to it's model.
5781708Sstevel */
5791708Sstevel if (pci_bridge) {
5801708Sstevel if (strlen(card.model) == 0)
5811708Sstevel (void) sprintf(card.model,
582*5889Szk194757 "%s", "pci-bridge");
5831708Sstevel else
5841708Sstevel (void) sprintf(card.model,
5851708Sstevel "%s/pci-bridge", card.model);
5861708Sstevel }
5871708Sstevel
5881708Sstevel /* insert this card in the list to be displayed later */
5891708Sstevel card_list = insert_io_card(card_list, &card);
5901708Sstevel
5911708Sstevel /*
5921708Sstevel * If we are dealing with a pci-bridge, we need to move
5931708Sstevel * down to the children of this bridge if there are any.
5941708Sstevel *
5951708Sstevel * If we are not, we are either dealing with a regular
5961708Sstevel * card (in which case we move onto the sibling of this
5971708Sstevel * card) or we are dealing with a child of a pci-bridge
5981708Sstevel * (in which case we move onto the child's siblings or
5991708Sstevel * if there are no more siblings for this child, we
6001708Sstevel * move onto the parents siblings).
6011708Sstevel *
6021708Sstevel * Once we reach the last child node of a pci-bridge,
6031708Sstevel * we need to back up the tree to the parents sibling
6041708Sstevel * node. If our parent has no more siblings, we need
6051708Sstevel * to check our grand parent for siblings.
6061708Sstevel *
6071708Sstevel * If we have no more siblings, we simply point to
6081708Sstevel * to the child's sibling which moves us onto the next
6091708Sstevel * bus leaf.
6101708Sstevel *
6111708Sstevel * The variable level gets adjusted on some of the
6121708Sstevel * conditions as this is used to track level within
6131708Sstevel * the tree we have reached.
6141708Sstevel */
6151708Sstevel if (pci_bridge) {
6161708Sstevel if (card_node->child != NULL) {
6171708Sstevel level++;
6181708Sstevel card_node = card_node->child;
6191708Sstevel } else
6201708Sstevel card_node = card_node->sibling;
6211708Sstevel } else {
622*5889Szk194757 if ((card_node->parent == pci_bridge_node) &&
623*5889Szk194757 (card_node->sibling == NULL)) {
624*5889Szk194757 card_node = pci_bridge_node->sibling;
6251708Sstevel if (level > 0)
626*5889Szk194757 level--;
627*5889Szk194757 } else if ((card_node->parent ==
628*5889Szk194757 child_pci_bridge_node) &&
629*5889Szk194757 (card_node->parent->parent ==
630*5889Szk194757 pci_bridge_node)) {
631*5889Szk194757 if ((child_pci_bridge_node->sibling) &&
632*5889Szk194757 (card_node->sibling == NULL)) {
633*5889Szk194757 card_node =
634*5889Szk194757 child_pci_bridge_node-> \
635*5889Szk194757 sibling;
636*5889Szk194757 if (level > 0)
6371708Sstevel level--;
638*5889Szk194757 } else if ((pci_bridge_node->sibling) &&
639*5889Szk194757 (card_node->sibling == NULL)) {
640*5889Szk194757 card_node =
641*5889Szk194757 pci_bridge_node->sibling;
642*5889Szk194757 if (level > 1)
643*5889Szk194757 level = level - 2;
644*5889Szk194757 else if (level > 0)
645*5889Szk194757 level--;
646*5889Szk194757 } else
647*5889Szk194757 card_node = card_node->sibling;
648*5889Szk194757 } else
649*5889Szk194757 card_node = card_node->sibling;
6501708Sstevel }
6511708Sstevel } /* end-while */
6521708Sstevel } /* end-for */
6531708Sstevel
6541708Sstevel display_io_cards(card_list);
6551708Sstevel free_io_cards(card_list);
6561708Sstevel }
6571708Sstevel
6581708Sstevel /*
6591708Sstevel * display_ffb
6601708Sstevel *
6611708Sstevel * There are no FFB's on a Serengeti, however in the generic library,
6621708Sstevel * the display_ffb() function is implemented so we have to define an
6631708Sstevel * empty function here.
6641708Sstevel */
6651708Sstevel /*ARGSUSED0*/
6661708Sstevel void
display_ffb(Board_node * board,int table)6671708Sstevel display_ffb(Board_node *board, int table)
6681708Sstevel {}
6691708Sstevel
6701708Sstevel static void
serengeti_display_board_info_header(int state)6711708Sstevel serengeti_display_board_info_header(int state)
6721708Sstevel {
6731708Sstevel char *fmt = "%-9s %-11s %-12s %-12s %-9s %-40s\n";
6741708Sstevel
6751708Sstevel log_printf("\n", 0);
6761708Sstevel log_printf("=========================", 0);
6771708Sstevel if (state == ACTIVE)
6781708Sstevel log_printf(dgettext(TEXT_DOMAIN,
679*5889Szk194757 " Active Boards for Domain "), 0);
6801708Sstevel else
6811708Sstevel log_printf(dgettext(TEXT_DOMAIN,
682*5889Szk194757 " Available Boards/Slots for Domain "), 0);
6831708Sstevel log_printf("===========================", 0);
6841708Sstevel log_printf("\n", 0);
6851708Sstevel log_printf("\n", 0);
6861708Sstevel
6871708Sstevel log_printf(fmt, "", "Board", "Receptacle", "Occupant", "", "", 0);
6881708Sstevel
6891708Sstevel log_printf(fmt, "FRU Name", "Type", "Status", "Status",
690*5889Szk194757 "Condition", "Info", 0);
6911708Sstevel
6921708Sstevel log_printf(fmt, "---------", "-----------", "-----------",
693*5889Szk194757 "------------", "---------",
694*5889Szk194757 "----------------------------------------", 0);
6951708Sstevel }
6961708Sstevel
6971708Sstevel static void
serengeti_display_board_info(int state)6981708Sstevel serengeti_display_board_info(int state)
6991708Sstevel {
7001708Sstevel int i, z, ret;
7011708Sstevel int nlist = 0;
7021708Sstevel int available_board_count = 0;
7031708Sstevel struct cfga_list_data *board_cfg = NULL;
7041708Sstevel char *err_string = NULL;
7051708Sstevel char tmp_id[CFGA_LOG_EXT_LEN + 1];
7061708Sstevel char tmp_info[DISPLAY_INFO + 1];
7071708Sstevel const char listops[] = "class=sbd";
7081708Sstevel struct cfga_list_data dat;
7091708Sstevel cfga_flags_t flags = NULL;
7101708Sstevel
7111708Sstevel ret = config_list_ext(0, NULL, &board_cfg, &nlist,
712*5889Szk194757 NULL, listops,
713*5889Szk194757 &err_string, flags);
7141708Sstevel
7151708Sstevel if (ret == CFGA_OK) {
7161708Sstevel serengeti_display_board_info_header(state);
7171708Sstevel for (i = 0; i < nlist; i++) {
7181708Sstevel dat = board_cfg[i];
7191708Sstevel
7201708Sstevel if ((state != ACTIVE) &&
7211708Sstevel (dat.ap_o_state == CFGA_STAT_CONFIGURED))
7221708Sstevel continue;
7231708Sstevel else if ((state == ACTIVE) &&
724*5889Szk194757 (dat.ap_o_state != CFGA_STAT_CONFIGURED))
7251708Sstevel continue;
7261708Sstevel if (state == INACTIVE)
7271708Sstevel available_board_count++;
7281708Sstevel
7291708Sstevel memcpy(tmp_id, dat.ap_log_id, CFGA_LOG_EXT_LEN);
7301708Sstevel tmp_id[CFGA_LOG_EXT_LEN] = '\0';
7311708Sstevel for (z = 0; z < strlen(tmp_id); z++) {
7321708Sstevel if (tmp_id[z] == '.')
7331708Sstevel tmp_id[z] = '/';
7341708Sstevel }
7351708Sstevel log_printf("/%-8s ", tmp_id, 0);
7361708Sstevel log_printf("%-11s ", dat.ap_type, 0);
7371708Sstevel
7381708Sstevel log_printf("%-12s ", EVNT2STR(dat.ap_r_state), 0);
7391708Sstevel log_printf("%-12s ", EVNT2STR(dat.ap_o_state), 0);
7401708Sstevel log_printf("%-8s ", COND2STR(dat.ap_cond), 0);
7411708Sstevel
7421708Sstevel memcpy(tmp_info, dat.ap_info, DISPLAY_INFO);
7431708Sstevel tmp_info[DISPLAY_INFO - 1] = '\0';
7441708Sstevel if (strlen(tmp_info) >= (DISPLAY_INFO - 1))
7451708Sstevel tmp_info[DISPLAY_INFO - 2] = '+';
7461708Sstevel log_printf("%-*s\n", (DISPLAY_INFO - 1), tmp_info, 0);
7471708Sstevel }
7481708Sstevel if ((state == INACTIVE) &&
7491708Sstevel (available_board_count == 0)) {
7501708Sstevel log_printf(dgettext(TEXT_DOMAIN,
751*5889Szk194757 "There are currently no "
752*5889Szk194757 "Boards/Slots available "
753*5889Szk194757 "to this Domain\n"), 0);
7541708Sstevel }
7551708Sstevel }
7561708Sstevel if (board_cfg)
7571708Sstevel free(board_cfg);
7581708Sstevel if (err_string)
7591708Sstevel free(err_string);
7601708Sstevel }
7611708Sstevel
7621708Sstevel /*
7631708Sstevel * add_node
7641708Sstevel *
7651708Sstevel * This function adds a board node to the board structure where that
7661708Sstevel * that node's physical component lives.
7671708Sstevel */
7681708Sstevel void
add_node(Sys_tree * root,Prom_node * pnode)7691708Sstevel add_node(Sys_tree *root, Prom_node *pnode)
7701708Sstevel {
7711708Sstevel int board = -1;
7721708Sstevel int portid = -1;
7731708Sstevel int nodeid = -1;
7741708Sstevel
7751708Sstevel void *value = NULL;
7761708Sstevel Board_node *bnode = NULL;
7771708Sstevel Prom_node *p = NULL;
7781708Sstevel char *type;
7791708Sstevel
7801708Sstevel /* Get the board number of this board from the portid prop */
7811708Sstevel if ((value = get_prop_val(find_prop(pnode, "portid"))) == NULL) {
7821708Sstevel if ((type = get_node_type(pnode)) && (strcmp(type, "cpu") == 0))
7831708Sstevel value =
7841708Sstevel get_prop_val(find_prop(pnode->parent, "portid"));
7851708Sstevel }
7861708Sstevel if (value != NULL) {
7871708Sstevel portid = *(int *)value;
7881708Sstevel }
7891708Sstevel
7901708Sstevel nodeid = SG_PORTID_TO_NODEID(portid);
7911708Sstevel board = SG_PORTID_TO_BOARD_NUM(portid);
7921708Sstevel
7931708Sstevel /* find the board node with the same board number */
7941708Sstevel if ((bnode = serengeti_find_board(root, board, nodeid)) == NULL) {
7951708Sstevel bnode = serengeti_insert_board(root, board, nodeid);
7961708Sstevel }
7971708Sstevel
7981708Sstevel /* now attach this prom node to the board list */
7991708Sstevel /* Insert this node at the end of the list */
8001708Sstevel pnode->sibling = NULL;
8011708Sstevel if (bnode->nodes == NULL)
8021708Sstevel bnode->nodes = pnode;
8031708Sstevel else {
8041708Sstevel p = bnode->nodes;
8051708Sstevel while (p->sibling != NULL)
8061708Sstevel p = p->sibling;
8071708Sstevel p->sibling = pnode;
8081708Sstevel }
8091708Sstevel }
8101708Sstevel
8111708Sstevel
8121708Sstevel
8131708Sstevel /*
8141708Sstevel * Print out all the io cards in the list. Also print the column
8151708Sstevel * headers if told to do so.
8161708Sstevel */
8171708Sstevel void
display_io_cards(struct io_card * list)8181708Sstevel display_io_cards(struct io_card *list)
8191708Sstevel {
8201708Sstevel char *fmt = "%-10s %-4s %-4s %-4s %-4s %-4s %-4s %-4s %-4s %-34s";
8211708Sstevel
8221708Sstevel static int banner = FALSE; /* Have we printed the column headings? */
8231708Sstevel struct io_card *p;
8241708Sstevel
8251708Sstevel if (list == NULL)
8261708Sstevel return;
8271708Sstevel
8281708Sstevel if (banner == FALSE) {
8291708Sstevel log_printf(fmt, "", "", "", "", "", "Bus", "Max",
830*5889Szk194757 "", "", "", 0);
8311708Sstevel log_printf("\n", 0);
8321708Sstevel log_printf(fmt, "", "IO", "Port", "Bus", "", "Freq", "Bus",
833*5889Szk194757 "Dev,", "", "", 0);
8341708Sstevel log_printf("\n", 0);
8351708Sstevel log_printf(fmt, "FRU Name", "Type", " ID", "Side", "Slot",
836*5889Szk194757 "MHz", "Freq", "Func", "State", "Name", 0);
8371708Sstevel #ifdef DEBUG
8381708Sstevel log_printf("Model Notes\n", 0);
8391708Sstevel #else
8401708Sstevel log_printf("Model\n", 0);
8411708Sstevel #endif
8421708Sstevel
8431708Sstevel log_printf(fmt, "----------", "----", "----", "----", "----",
844*5889Szk194757 "----", "----", "----", "-----",
845*5889Szk194757 "--------------------------------", 0);
8461708Sstevel #ifdef DEBUG
8471708Sstevel log_printf("---------------------- ", 0);
8481708Sstevel #endif
8491708Sstevel log_printf("----------------------\n", 0);
8501708Sstevel banner = TRUE;
8511708Sstevel }
8521708Sstevel
8531708Sstevel for (p = list; p != NULL; p = p -> next) {
8541708Sstevel
8551708Sstevel display_io_slot_info(p);
8561708Sstevel
8571708Sstevel display_io_max_bus_speed(p);
8581708Sstevel
8591708Sstevel log_printf("\n", 0);
8601708Sstevel }
8611708Sstevel }
8621708Sstevel
8631708Sstevel static void
display_io_slot_info(struct io_card * p)8641708Sstevel display_io_slot_info(struct io_card *p)
8651708Sstevel {
8661708Sstevel char fru_name[MAX_FRU_NAME_LEN] = "";
8671708Sstevel
8681708Sstevel SG_SET_FRU_NAME_NODE(fru_name, p->node_id);
8691708Sstevel SG_SET_FRU_NAME_IO_BOARD(fru_name, p->board);
8701708Sstevel SG_SET_FRU_NAME_MODULE(fru_name, p->schizo_portid % 2);
8711708Sstevel
8721708Sstevel log_printf("%-8s ", fru_name, 0);
8731708Sstevel log_printf("%-4s ", p->bus_type, 0);
8741708Sstevel log_printf("%-3d ", p->schizo_portid, 0);
8751708Sstevel log_printf("%c ", p->pci_bus, 0);
8761708Sstevel log_printf("%-1s ", p->slot_str, 0);
8771708Sstevel log_printf("%-3d ", p->freq, 0);
8781708Sstevel }
8791708Sstevel
8801708Sstevel #define BUS_SPEED_PRINT(speed) log_printf(" %d ", speed, 0)
8811708Sstevel
8821708Sstevel static void
display_io_max_bus_speed(struct io_card * p)8831708Sstevel display_io_max_bus_speed(struct io_card *p)
8841708Sstevel {
8851708Sstevel int speed = board_bus_max_freq;
8861708Sstevel
8871708Sstevel switch (p->pci_bus) {
8881708Sstevel case 'A':
8891708Sstevel BUS_SPEED_PRINT(speed);
8901708Sstevel break;
8911708Sstevel case 'B':
8921708Sstevel if (strcmp(p->notes, XMITS_COMPATIBLE) == 0) {
8931708Sstevel if ((strncmp(p->slot_str, "1", 1) == 0) ||
8941708Sstevel (strncmp(p->slot_str, "0", 1) == 0))
8951708Sstevel BUS_SPEED_PRINT(33);
8961708Sstevel else
8971708Sstevel BUS_SPEED_PRINT(speed);
8981708Sstevel } else
8991708Sstevel BUS_SPEED_PRINT(33);
9001708Sstevel break;
9011708Sstevel default:
9021708Sstevel log_printf(" - ", 0);
9031708Sstevel break;
9041708Sstevel }
9051708Sstevel
9061708Sstevel log_printf("%-1d,%-1d ", p->dev_no, p->func_no, 0);
9071708Sstevel log_printf("%-5s ", p->status, 0);
9081708Sstevel
9091708Sstevel log_printf("%-32.32s%c ", p->name,
910*5889Szk194757 ((strlen(p->name) > 32) ? '+' : ' '), 0);
9111708Sstevel log_printf("%-22.22s%c", p->model,
912*5889Szk194757 ((strlen(p->model) > 22) ? '+' : ' '), 0);
9131708Sstevel #ifdef DEBUG
9141708Sstevel log_printf(" %s", p->notes, 0);
9151708Sstevel #endif /* DEBUG */
9161708Sstevel }
9171708Sstevel
9181708Sstevel void
display_cpu_devices(Sys_tree * tree)9191708Sstevel display_cpu_devices(Sys_tree *tree)
9201708Sstevel {
9211708Sstevel Board_node *bnode;
9221708Sstevel
9231708Sstevel /* printf formats */
9241708Sstevel char *fmt1 = "%-10s %-7s %-4s %-4s %-7s %-4s\n";
9251708Sstevel
9261708Sstevel /*
9271708Sstevel * Display the table header for CPUs . Then display the CPU
9281708Sstevel * frequency, cache size, and processor revision of all cpus.
9291708Sstevel */
9301708Sstevel log_printf("\n", 0);
9311708Sstevel log_printf("=========================", 0);
9321708Sstevel log_printf(" CPUs ", 0);
9331708Sstevel log_printf("=========================", 0);
9341708Sstevel log_printf("======================", 0);
9351708Sstevel log_printf("\n", 0);
9361708Sstevel log_printf("\n", 0);
9371708Sstevel
9381708Sstevel log_printf(fmt1, "", "CPU ", "Run", " E$", "CPU", "CPU", 0);
9391708Sstevel
9401708Sstevel log_printf(fmt1, "FRU Name", "ID ", "MHz", " MB",
941*5889Szk194757 "Impl.", "Mask", 0);
9421708Sstevel
9431708Sstevel log_printf(fmt1, "----------", "-------", "----", "----",
944*5889Szk194757 "-------", "----", 0);
9451708Sstevel
9461708Sstevel /* Now display all of the cpus on each board */
9471708Sstevel bnode = tree->bd_list;
9481708Sstevel while (bnode != NULL) {
9491708Sstevel display_cpus(bnode);
9501708Sstevel bnode = bnode->next;
9511708Sstevel }
9521708Sstevel
9531708Sstevel log_printf("\n", 0);
9541708Sstevel }
9551708Sstevel
9561708Sstevel static boolean_t
cpu_node_configured(char * const node)9571708Sstevel cpu_node_configured(char *const node)
9581708Sstevel {
9591708Sstevel int ret, i;
9601708Sstevel int nlist = 0;
9611708Sstevel boolean_t rv;
9621708Sstevel char *err_string = NULL;
9631708Sstevel char *const *ap_args = NULL;
9641708Sstevel struct cfga_list_data *statlist = NULL;
9651708Sstevel struct cfga_list_data dat;
9661708Sstevel cfga_flags_t flags = CFGA_FLAG_LIST_ALL;
9671708Sstevel
9681708Sstevel if (node == NULL)
9691708Sstevel return (FALSE);
9701708Sstevel
9711708Sstevel ap_args = &node;
9721708Sstevel ret = config_list_ext(1, &node, &statlist, &nlist,
973*5889Szk194757 NULL, NULL, &err_string, flags);
9741708Sstevel
9751708Sstevel if (ret == CFGA_OK) {
9761708Sstevel dat = statlist[0];
9771708Sstevel
9781708Sstevel if (dat.ap_o_state == CFGA_STAT_CONFIGURED)
9791708Sstevel rv = TRUE;
9801708Sstevel else
9811708Sstevel rv = FALSE;
9821708Sstevel } else {
9831708Sstevel rv = FALSE;
9841708Sstevel }
9851708Sstevel if (statlist)
9861708Sstevel free(statlist);
9871708Sstevel if (err_string)
9881708Sstevel free(err_string);
9891708Sstevel return (rv);
9901708Sstevel }
9911708Sstevel
9921708Sstevel /*
9931708Sstevel * Display the CPUs present on this board.
9941708Sstevel */
9951708Sstevel void
display_cpus(Board_node * board)9961708Sstevel display_cpus(Board_node *board)
9971708Sstevel {
9981708Sstevel Prom_node *cpu;
999*5889Szk194757 uint_t freq; /* CPU clock frequency */
10001708Sstevel int ecache_size; /* External cache size */
10011708Sstevel int board_num = board->board_num;
10021708Sstevel int *mid;
10031708Sstevel int *impl;
10041708Sstevel int *mask;
10051708Sstevel int decoded_mask;
10061708Sstevel int *coreid;
10071708Sstevel int mid_prev = -1;
10081708Sstevel int ecache_size_prev = 0;
10091708Sstevel char fru_prev[MAX_FRU_NAME_LEN] = "";
10101708Sstevel
10111708Sstevel /*
10121708Sstevel * display the CPUs' operating frequency, cache size, impl. field
10131708Sstevel * and mask revision.
10141708Sstevel */
10151708Sstevel for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
10161708Sstevel cpu = dev_next_type(cpu, "cpu")) {
10171708Sstevel char fru_name[MAX_FRU_NAME_LEN] = "";
10181708Sstevel char cfg_fru_name[MAX_FRU_NAME_LEN] = "";
10191708Sstevel
10201708Sstevel mid = (int *)get_prop_val(find_prop(cpu, "portid"));
10211708Sstevel if (mid == NULL)
10221708Sstevel mid = (int *)get_prop_val(find_prop(cpu, "cpuid"));
10231708Sstevel freq = SG_CLK_FREQ_TO_MHZ(get_cpu_freq(cpu));
10241708Sstevel ecache_size = get_ecache_size(cpu);
10251708Sstevel impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
10261708Sstevel mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
10271708Sstevel
10281708Sstevel /* Do not display a failed CPU node */
10291708Sstevel if ((impl == NULL) || (freq == 0) || (node_failed(cpu)))
10301708Sstevel continue;
10311708Sstevel
10321708Sstevel /* FRU Name */
10331708Sstevel SG_SET_FRU_NAME_NODE(fru_name, board->node_id);
10341708Sstevel
10351708Sstevel SG_SET_FRU_NAME_CPU_BOARD(fru_name, board_num);
10361708Sstevel SG_SET_FRU_NAME_MODULE(fru_name, *mid % 4);
10371708Sstevel
10381708Sstevel if (CPU_IMPL_IS_CMP(*impl)) {
10391708Sstevel coreid = (int *)get_prop_val(find_prop(cpu,
10401708Sstevel "reg"));
10411708Sstevel if (coreid == NULL) {
10421708Sstevel continue;
10431708Sstevel }
10441708Sstevel
10451708Sstevel /*
10461708Sstevel * The assumption is made that 2 cores will always be
10471708Sstevel * listed together in the device tree. If either core
10481708Sstevel * is "bad" then the FRU will not be listed.
10491708Sstevel *
10501708Sstevel * As display_cpus on Serengeti does actually process
10511708Sstevel * all cpu's per board a copy of the fru_name needs to
10521708Sstevel * be made as the following core may not be its
10531708Sstevel * sibling. If this is the case it is assumed that a
10541708Sstevel * sibling core has failed, so the fru should not be
10551708Sstevel * displayed.
10561708Sstevel *
10571708Sstevel * For the first instance of a core, fru_prev is
10581708Sstevel * expected to be empty. The current values are then
10591708Sstevel * stored and the next board->nodes is processed. If
10601708Sstevel * this is a sibling core, the ecache size it tallied
10611708Sstevel * and the previous value reset and processing
10621708Sstevel * continues.
10631708Sstevel *
10641708Sstevel * If the following core is not a sibling, the new
10651708Sstevel * values are stored and the next board->nodes is
10661708Sstevel * processed.
10671708Sstevel */
10681708Sstevel if (strncmp(fru_prev, "", sizeof (fru_prev)) == 0) {
10691708Sstevel strncpy(fru_prev, fru_name, sizeof (fru_name));
10701708Sstevel mid_prev = *mid;
10711708Sstevel ecache_size_prev = ecache_size;
10721708Sstevel continue;
10731708Sstevel } else {
10741708Sstevel if (strncmp(fru_name, fru_prev,
10751708Sstevel sizeof (fru_prev)) == 0) {
10761708Sstevel /*
10771708Sstevel * Jaguar has a split E$, so the size
10781708Sstevel * for both cores must be added together
10791708Sstevel * to get the total size for the entire
10801708Sstevel * chip.
10811708Sstevel *
10821708Sstevel * Panther E$ (L3) is logically shared,
10831708Sstevel * so the total size is equal to the
10841708Sstevel * core size.
10851708Sstevel */
10861708Sstevel if (IS_JAGUAR(*impl)) {
10871708Sstevel ecache_size += ecache_size_prev;
10881708Sstevel }
10891708Sstevel
10901708Sstevel ecache_size_prev = 0;
10911708Sstevel strncpy(fru_prev, "",
10921708Sstevel sizeof (fru_prev));
10931708Sstevel } else {
10941708Sstevel mid_prev = *mid;
10951708Sstevel ecache_size_prev = ecache_size;
10961708Sstevel strncpy(fru_prev, fru_name,
10971708Sstevel sizeof (fru_name));
10981708Sstevel continue;
10991708Sstevel }
11001708Sstevel }
11011708Sstevel }
11021708Sstevel
11031708Sstevel /*
11041708Sstevel * If cpu is not configured, do not display it
11051708Sstevel */
11061708Sstevel CFG_SET_FRU_NAME_NODE(cfg_fru_name, board->node_id);
11071708Sstevel CFG_SET_FRU_NAME_CPU_BOARD(cfg_fru_name, board_num);
11081708Sstevel CFG_SET_FRU_NAME_MODULE(cfg_fru_name, *mid % 4);
11091708Sstevel
11101708Sstevel if (!(cpu_node_configured(cfg_fru_name))) {
11111708Sstevel continue;
11121708Sstevel }
11131708Sstevel
11141708Sstevel
11151708Sstevel log_printf("%-10s ", fru_name, 0);
11161708Sstevel
11171708Sstevel /* CPU MID */
11181708Sstevel if (CPU_IMPL_IS_CMP(*impl)) {
11191708Sstevel log_printf("%3d,%3d ", mid_prev, *mid, 0);
11201708Sstevel mid_prev = -1;
11211708Sstevel } else
11221708Sstevel log_printf("%3d ", *mid, 0);
11231708Sstevel
11241708Sstevel /* Running frequency */
1125*5889Szk194757 log_printf(" %4u ", freq, 0);
11261708Sstevel
11271708Sstevel /* Ecache size */
11281708Sstevel if (ecache_size == 0)
11291708Sstevel log_printf("%3s ", "N/A", 0);
11301708Sstevel else
11311708Sstevel log_printf("%4.1f ",
1132*5889Szk194757 (float)ecache_size / (float)(1<<20),
1133*5889Szk194757 0);
11341708Sstevel
11351708Sstevel /* Implementation */
11361708Sstevel if (impl == NULL) {
11371708Sstevel log_printf("%6s ", " N/A", 0);
11381708Sstevel } else {
11391708Sstevel switch (*impl) {
11401708Sstevel case CHEETAH_IMPL:
11411708Sstevel log_printf("%-7s ", "US-III", 0);
11421708Sstevel break;
11431708Sstevel case CHEETAH_PLUS_IMPL:
11441708Sstevel log_printf("%-7s ", "US-III+", 0);
11451708Sstevel break;
11461708Sstevel case JAGUAR_IMPL:
11471708Sstevel log_printf("%-7s ", "US-IV", 0);
11481708Sstevel break;
11491708Sstevel case PANTHER_IMPL:
11501708Sstevel log_printf("%-7s ", "US-IV+", 0);
11511708Sstevel break;
11521708Sstevel default:
11531708Sstevel log_printf("%-7x ", *impl, 0);
11541708Sstevel break;
11551708Sstevel }
11561708Sstevel }
11571708Sstevel
11581708Sstevel /* CPU Mask */
11591708Sstevel if (mask == NULL) {
11601708Sstevel log_printf(" %3s ", "N/A", 0);
11611708Sstevel } else {
11621708Sstevel if (IS_CHEETAH(*impl))
11631708Sstevel decoded_mask = REMAP_CHEETAH_MASK(*mask);
11641708Sstevel else
11651708Sstevel decoded_mask = *mask;
11661708Sstevel
11671708Sstevel log_printf(" %d.%d ",
11681708Sstevel (decoded_mask >> 4) & 0xf,
11691708Sstevel decoded_mask & 0xf, 0);
11701708Sstevel }
11711708Sstevel
11721708Sstevel log_printf("\n", 0);
11731708Sstevel }
11741708Sstevel }
11751708Sstevel
11761708Sstevel
11771708Sstevel /*ARGSUSED3*/
11781708Sstevel void
display_diaginfo(int flag,Prom_node * root,Sys_tree * tree,struct system_kstat_data * kstats)11791708Sstevel display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
11801708Sstevel struct system_kstat_data *kstats)
11811708Sstevel {
11821708Sstevel log_printf("\n", 0);
11831708Sstevel log_printf("=========================", 0);
11841708Sstevel log_printf(dgettext(TEXT_DOMAIN, " Hardware Failures "), 0);
11851708Sstevel log_printf("==================================", 0);
11861708Sstevel log_printf("\n", 0);
11871708Sstevel
11881708Sstevel /*
11891708Sstevel * Get a list of failed parts (ie. devices with a status of
11901708Sstevel * 'fail') from the OBP device tree and display them.
11911708Sstevel */
11921708Sstevel get_failed_parts();
11931708Sstevel
11941708Sstevel /* return unless -v option specified */
11951708Sstevel if (!flag) {
11961708Sstevel log_printf("\n", 0);
11971708Sstevel return;
11981708Sstevel }
11991708Sstevel
12001708Sstevel /*
12011708Sstevel * display time of latest powerfail. Not all systems
12021708Sstevel * have this capability. For those that do not, this
12031708Sstevel * is just a no-op.
12041708Sstevel */
12051708Sstevel disp_powerfail(root);
12061708Sstevel
12071708Sstevel /* Print the PROM revisions here */
12081708Sstevel serengeti_display_hw_revisions(root, tree->bd_list);
12091708Sstevel }
12101708Sstevel
12111708Sstevel /*
12121708Sstevel * local functions - functions that are only needed inside this library
12131708Sstevel */
12141708Sstevel
12151708Sstevel static void
serengeti_display_hw_revisions(Prom_node * root,Board_node * bdlist)12161708Sstevel serengeti_display_hw_revisions(Prom_node *root, Board_node *bdlist)
12171708Sstevel {
12181708Sstevel Prom_node *pnode;
12191708Sstevel char *value;
12201708Sstevel
12211708Sstevel /* Print the header */
12221708Sstevel log_printf("\n", 0);
12231708Sstevel log_printf("=========================", 0);
12241708Sstevel log_printf(dgettext(TEXT_DOMAIN, " HW Revisions "), 0);
12251708Sstevel log_printf("=======================================", 0);
12261708Sstevel log_printf("\n", 0);
12271708Sstevel log_printf("\n", 0);
12281708Sstevel
12291708Sstevel /* Display Prom revision header */
12301708Sstevel log_printf("System PROM revisions:\n", 0);
12311708Sstevel log_printf("----------------------\n", 0);
12321708Sstevel
12331708Sstevel /*
12341708Sstevel * Display OBP version info
12351708Sstevel */
12361708Sstevel pnode = dev_find_node(root, "openprom");
12371708Sstevel if (pnode != NULL) {
12381708Sstevel value = (char *)get_prop_val(find_prop(pnode, "version"));
12391708Sstevel log_printf("%s\n\n", value, 0);
12401708Sstevel } else {
12411708Sstevel log_printf("OBP ???\n\n", value, 0);
12421708Sstevel }
12431708Sstevel
12441708Sstevel /*
12451708Sstevel * Display ASIC revisions
12461708Sstevel */
12471708Sstevel log_printf("IO ASIC revisions:\n", 0);
12481708Sstevel log_printf("------------------\n", 0);
12491708Sstevel
12501708Sstevel log_printf(" Port\n", 0);
12511708Sstevel log_printf("FRU Name Model ID Status", 0);
12521708Sstevel #ifdef DEBUG
12531708Sstevel log_printf(" Version Notes\n", 0);
12541708Sstevel #else
12551708Sstevel log_printf(" Version\n", 0);
12561708Sstevel #endif
12571708Sstevel /* ---------FRU Name--Model-----------Port-Status */
12581708Sstevel log_printf("----------- --------------- ---- ---------- "
12591708Sstevel #ifdef DEBUG
1260*5889Szk194757 "------- "
12611708Sstevel #endif
1262*5889Szk194757 "-------\n", 0);
12631708Sstevel /*
12641708Sstevel * Display SCHIZO version info
12651708Sstevel */
12661708Sstevel display_schizo_revisions(bdlist, SG_SCHIZO_GOOD);
12671708Sstevel
12681708Sstevel /*
12691708Sstevel * Display sgsbbc version info
12701708Sstevel */
12711708Sstevel display_sgsbbc_revisions(bdlist);
12721708Sstevel }
12731708Sstevel
12741708Sstevel /*
12751708Sstevel * This function displays Schizo and Xmits revision of boards
12761708Sstevel */
12771708Sstevel static int
display_schizo_revisions(Board_node * bdlist,int mode)12781708Sstevel display_schizo_revisions(Board_node *bdlist, int mode)
12791708Sstevel {
12801708Sstevel Prom_node *pnode;
12811708Sstevel int *int_val;
12821708Sstevel int portid;
12831708Sstevel int prev_portid = -1;
12841708Sstevel char *model;
12851708Sstevel char *status_a, *status_b;
12861708Sstevel char status[MAX_STATUS_LEN];
12871708Sstevel int version;
12881708Sstevel int node_id;
12891708Sstevel #ifdef DEBUG
12901708Sstevel uint32_t a_notes, b_notes;
12911708Sstevel #endif
12921708Sstevel int pci_bus;
12931708Sstevel /*
12941708Sstevel * rv is used when mode is set to SG_SCHIZO_FAILED.
12951708Sstevel * We need to signal if a failure is found so that
12961708Sstevel * the correct headers/footers can be printed.
12971708Sstevel *
12981708Sstevel * rv = 1 implies a failed/disavled schizo device
12991708Sstevel * rv = 0 implies all other cases
13001708Sstevel */
13011708Sstevel int rv = 0;
13021708Sstevel Board_node *bnode;
13031708Sstevel void *value;
13041708Sstevel
13051708Sstevel bnode = bdlist;
13061708Sstevel while (bnode != NULL) {
13071708Sstevel /*
13081708Sstevel * search this board node for all Schizos
13091708Sstevel */
13101708Sstevel for (pnode = dev_find_node_by_compatible(bnode->nodes,
1311*5889Szk194757 SCHIZO_COMPATIBLE); pnode != NULL;
13121708Sstevel pnode = dev_next_node_by_compatible(pnode,
1313*5889Szk194757 SCHIZO_COMPATIBLE)) {
13141708Sstevel
13151708Sstevel char fru_name[MAX_FRU_NAME_LEN] = "";
13161708Sstevel
13171708Sstevel /*
13181708Sstevel * get the reg property to determine
13191708Sstevel * whether we are looking at side A or B
13201708Sstevel */
13211708Sstevel int_val = (int *)get_prop_val
1322*5889Szk194757 (find_prop(pnode, "reg"));
13231708Sstevel if (int_val != NULL) {
13241708Sstevel int_val ++; /* second integer in array */
13251708Sstevel pci_bus = ((*int_val) & 0x7f0000);
13261708Sstevel }
13271708Sstevel
13281708Sstevel /* get portid */
13291708Sstevel int_val = (int *)get_prop_val
1330*5889Szk194757 (find_prop(pnode, "portid"));
13311708Sstevel if (int_val == NULL)
13321708Sstevel continue;
13331708Sstevel
13341708Sstevel portid = *int_val;
13351708Sstevel
13361708Sstevel /*
13371708Sstevel * If this is a new portid and it is PCI bus B,
13381708Sstevel * we skip onto the PCI bus A. (PCI-A and PCI-B share
13391708Sstevel * the same portid)
13401708Sstevel */
13411708Sstevel if ((portid != prev_portid) && (pci_bus == 0x700000)) {
13421708Sstevel prev_portid = portid;
13431708Sstevel /* status */
13441708Sstevel status_b = (char *)get_prop_val
13451708Sstevel (find_prop(pnode, "status"));
13461708Sstevel #ifdef DEBUG
13471708Sstevel b_notes = pci_bus;
13481708Sstevel #endif
13491708Sstevel continue; /* skip to the next schizo */
13501708Sstevel }
13511708Sstevel
13521708Sstevel /*
13531708Sstevel * This must be side A of the same Schizo.
13541708Sstevel * Gather all its props and display them.
13551708Sstevel */
13561708Sstevel #ifdef DEBUG
13571708Sstevel a_notes = pci_bus;
13581708Sstevel #endif
13591708Sstevel
13601708Sstevel prev_portid = portid;
13611708Sstevel
13621708Sstevel /* get the node-id */
13631708Sstevel node_id = SG_PORTID_TO_NODEID(portid);
13641708Sstevel
13651708Sstevel /* model */
13661708Sstevel model = (char *)get_prop_val
1367*5889Szk194757 (find_prop(pnode, "model"));
13681708Sstevel
13691708Sstevel /* version */
13701708Sstevel value = (int *)get_prop_val
1371*5889Szk194757 (find_prop(pnode, "module-revision#"));
13721708Sstevel
13731708Sstevel if (value)
13741708Sstevel int_val = (int *)value;
13751708Sstevel else
13761708Sstevel int_val = (int *)get_prop_val
1377*5889Szk194757 (find_prop(pnode, "version#"));
13781708Sstevel if (int_val != NULL)
13791708Sstevel version = *int_val;
13801708Sstevel else
13811708Sstevel version = -1;
13821708Sstevel
13831708Sstevel /* status */
13841708Sstevel status_a = (char *)get_prop_val(find_prop
1385*5889Szk194757 (pnode, "status"));
13861708Sstevel
13871708Sstevel /*
13881708Sstevel * Display the data
13891708Sstevel */
13901708Sstevel /* FRU Name */
13911708Sstevel SG_SET_FRU_NAME_NODE(fru_name, node_id);
13921708Sstevel SG_SET_FRU_NAME_IO_BOARD(fru_name,
1393*5889Szk194757 SG_IO_BD_PORTID_TO_BD_NUM(portid));
13941708Sstevel SG_SET_FRU_NAME_MODULE(fru_name, portid % 2);
13951708Sstevel
13961708Sstevel if (mode == SG_SCHIZO_FAILED) {
13971708Sstevel if ((status_a != (char *)NULL) &&
13981708Sstevel ((status_b != (char *)NULL))) {
13991708Sstevel if ((strcmp
14001708Sstevel (status_a, SG_DISABLED) == 0) &&
14011708Sstevel (strcmp(status_b,
1402*5889Szk194757 SG_DISABLED) == 0)) {
14031708Sstevel log_printf("\tFRU Type : %s\n ",
1404*5889Szk194757 model, 0);
14051708Sstevel log_printf("\tLocation : %s\n",
1406*5889Szk194757 fru_name, 0);
14071708Sstevel log_printf
14081708Sstevel ("\tPROM status: %s\n\n",
14091708Sstevel SG_DISABLED, 0);
14101708Sstevel rv = 1;
14111708Sstevel }
14121708Sstevel }
14131708Sstevel continue;
14141708Sstevel }
14151708Sstevel /*
14161708Sstevel * This section of code is executed when displaying
14171708Sstevel * non-failed schizo devices. If the mode is set to
14181708Sstevel * SG_SCHIZO_FAILED, then this section of code will
14191708Sstevel * not be executed
14201708Sstevel */
14211708Sstevel if ((status_a == (char *)NULL) &&
14221708Sstevel ((status_b == (char *)NULL)))
14231708Sstevel sprintf(status, " %s ", SG_OK);
14241708Sstevel else if ((status_a == (char *)NULL) &&
1425*5889Szk194757 ((strcmp(status_b, SG_DISABLED) == 0)))
14261708Sstevel sprintf(status, " %s", SG_DEGRADED);
14271708Sstevel else if ((status_b == (char *)NULL) &&
1428*5889Szk194757 ((strcmp(status_a, SG_DISABLED) == 0)))
14291708Sstevel sprintf(status, " %s", SG_DEGRADED);
14301708Sstevel else
14311708Sstevel continue;
14321708Sstevel
14331708Sstevel log_printf("%-12s", fru_name, 0);
14341708Sstevel
14351708Sstevel /* model */
14361708Sstevel
14371708Sstevel if (model != NULL)
14381708Sstevel log_printf("%-15s ", model, 0);
14391708Sstevel else
14401708Sstevel log_printf("%-15s ", "unknown", 0);
14411708Sstevel /* portid */
14421708Sstevel log_printf("%-3d ", portid, 0);
14431708Sstevel
14441708Sstevel /* status */
14451708Sstevel log_printf("%s", status, 0);
14461708Sstevel
14471708Sstevel /* version */
14481708Sstevel log_printf(" %-4d ", version, 0);
14491708Sstevel #ifdef DEBUG
14501708Sstevel log_printf("0x%x 0x%x", a_notes, b_notes, 0);
14511708Sstevel log_printf(" %d", portid, 0);
14521708Sstevel #endif
14531708Sstevel log_printf("\n", 0);
14541708Sstevel }
14551708Sstevel bnode = bnode->next;
14561708Sstevel }
14571708Sstevel return (rv);
14581708Sstevel }
14591708Sstevel
14601708Sstevel static void
display_sgsbbc_revisions(Board_node * bdlist)14611708Sstevel display_sgsbbc_revisions(Board_node *bdlist)
14621708Sstevel {
14631708Sstevel
14641708Sstevel Prom_node *pnode;
14651708Sstevel int *int_val;
14661708Sstevel int portid;
14671708Sstevel char *model;
14681708Sstevel char *status;
14691708Sstevel int revision;
14701708Sstevel int node_id;
14711708Sstevel Board_node *bnode;
14721708Sstevel
14731708Sstevel #ifdef DEBUG
14741708Sstevel char *slot_name;
14751708Sstevel char notes[30];
14761708Sstevel char *value;
14771708Sstevel #endif
14781708Sstevel
14791708Sstevel bnode = bdlist;
14801708Sstevel while (bnode != NULL) {
14811708Sstevel /*
14821708Sstevel * search this board node for all sgsbbc's
14831708Sstevel */
14841708Sstevel for (pnode = dev_find_node_by_type(bnode->nodes, "model",
1485*5889Szk194757 "SUNW,sgsbbc"); pnode != NULL;
1486*5889Szk194757 pnode = dev_next_node_by_type(pnode, "model",
1487*5889Szk194757 "SUNW,sgsbbc")) {
14881708Sstevel
14891708Sstevel char fru_name[MAX_FRU_NAME_LEN] = "";
14901708Sstevel
14911708Sstevel /*
14921708Sstevel * We need to go to this node's parent to
14931708Sstevel * get a portid to tell us what board it is on
14941708Sstevel */
14951708Sstevel int_val = (int *)get_prop_val
1496*5889Szk194757 (find_prop(pnode->parent, "portid"));
14971708Sstevel if (int_val == NULL)
14981708Sstevel continue;
14991708Sstevel
15001708Sstevel portid = *int_val;
15011708Sstevel /* get the node-id */
15021708Sstevel node_id = SG_PORTID_TO_NODEID(portid);
15031708Sstevel
15041708Sstevel /* model */
15051708Sstevel model = (char *)get_prop_val
1506*5889Szk194757 (find_prop(pnode, "model"));
15071708Sstevel
15081708Sstevel /* status */
15091708Sstevel status = (char *)get_prop_val(find_prop
1510*5889Szk194757 (pnode, "status"));
15111708Sstevel
15121708Sstevel /* revision */
15131708Sstevel int_val = (int *)get_prop_val
1514*5889Szk194757 (find_prop(pnode, "revision-id"));
15151708Sstevel if (int_val != NULL)
15161708Sstevel revision = *int_val;
15171708Sstevel else
15181708Sstevel revision = -1;
15191708Sstevel
15201708Sstevel #ifdef DEBUG
15211708Sstevel value = (char *)get_prop_val(
1522*5889Szk194757 find_prop(pnode->parent, "slot-names"));
15231708Sstevel if (value != NULL) {
15241708Sstevel /* Skip the 4 byte bitmask */
15251708Sstevel slot_name = (char *)value + sizeof (int);
15261708Sstevel } else {
15271708Sstevel strcpy(slot_name, "not_found");
15281708Sstevel }
15291708Sstevel (void) sprintf(notes, "[%s] portid [%d]", slot_name,
1530*5889Szk194757 portid);
15311708Sstevel #endif
15321708Sstevel /*
15331708Sstevel * Display the data
15341708Sstevel */
15351708Sstevel /* FRU Name */
15361708Sstevel SG_SET_FRU_NAME_NODE(fru_name, node_id);
15371708Sstevel SG_SET_FRU_NAME_IO_BOARD(fru_name,
1538*5889Szk194757 SG_IO_BD_PORTID_TO_BD_NUM(portid));
15391708Sstevel SG_SET_FRU_NAME_MODULE(fru_name, portid % 2);
15401708Sstevel log_printf("%-12s", fru_name, 0);
15411708Sstevel
15421708Sstevel /* model */
15431708Sstevel if (model != NULL)
15441708Sstevel log_printf("%-15s ", model, 0);
15451708Sstevel else
15461708Sstevel log_printf("%-15s ", "unknown", 0);
15471708Sstevel /* portid */
15481708Sstevel log_printf("%-3d ", portid, 0);
15491708Sstevel /* status */
15501708Sstevel if (status == (char *)NULL)
15511708Sstevel log_printf(" ok ", 0);
15521708Sstevel else
15531708Sstevel log_printf(" fail ", 0);
15541708Sstevel /* revision */
15551708Sstevel log_printf(" %-4d ", revision, 0);
15561708Sstevel #ifdef DEBUG
15571708Sstevel log_printf("%s", notes, 0);
15581708Sstevel #endif
15591708Sstevel log_printf("\n", 0);
15601708Sstevel }
15611708Sstevel bnode = bnode->next;
15621708Sstevel }
15631708Sstevel }
15641708Sstevel
15651708Sstevel /*ARGSUSED0*/
15661708Sstevel void
display_hp_fail_fault(Sys_tree * tree,struct system_kstat_data * kstats)15671708Sstevel display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats)
15681708Sstevel {
15691708Sstevel serengeti_display_board_info(ACTIVE);
15701708Sstevel serengeti_display_board_info(INACTIVE);
15711708Sstevel }
15721708Sstevel
15731708Sstevel /*
15741708Sstevel * display_failed_parts
15751708Sstevel *
15761708Sstevel * Display the failed parts in the system. This function looks for
15771708Sstevel * the status property in all PROM nodes contained in the Sys_tree
15781708Sstevel * passed in.
15791708Sstevel */
15801708Sstevel int
display_failed_parts(Sys_tree * tree)15811708Sstevel display_failed_parts(Sys_tree *tree)
15821708Sstevel {
15831708Sstevel int system_failed = 0;
15841708Sstevel int bank_failed = 0;
15851708Sstevel int schizo_failed = FALSE;
15861708Sstevel int portid, nodeid, board;
15871708Sstevel Board_node *bnode = tree->bd_list;
15881708Sstevel Prom_node *pnode;
15891708Sstevel int *coreid, *impl;
15901708Sstevel print_flag = TRUE;
15911708Sstevel
15921708Sstevel /*
15931708Sstevel * go through all of the OBP nodes looking for
15941708Sstevel * failed units.
15951708Sstevel */
15961708Sstevel while (bnode != NULL) {
15971708Sstevel
15981708Sstevel pnode = find_failed_node(bnode->nodes);
15991708Sstevel if ((pnode != NULL) && !system_failed) {
16001708Sstevel system_failed = TRUE;
16011708Sstevel log_printf("\n", 0);
16021708Sstevel log_printf(dgettext(TEXT_DOMAIN,
1603*5889Szk194757 "Failed Field Replaceable Units (FRU) in "
1604*5889Szk194757 "System:\n"), 0);
16051708Sstevel log_printf("=========================="
1606*5889Szk194757 "====================\n", 0);
16071708Sstevel }
16081708Sstevel
16091708Sstevel while (pnode != NULL) {
16101708Sstevel void *status;
16111708Sstevel char *name, *type, *model;
16121708Sstevel
16131708Sstevel char fru_name[MAX_FRU_NAME_LEN] = "";
16141708Sstevel
16151708Sstevel status = get_prop_val(find_prop(pnode, "status"));
16161708Sstevel name = get_node_name(pnode);
16171708Sstevel
16181708Sstevel /* sanity check of data retreived from PROM */
16191708Sstevel if ((status == NULL) || (name == NULL)) {
16201708Sstevel pnode = next_failed_node(pnode);
16211708Sstevel continue;
16221708Sstevel }
16231708Sstevel
16241708Sstevel type = get_node_type(pnode);
16251708Sstevel portid = get_id(pnode);
16261708Sstevel model = (char *)get_prop_val
16271708Sstevel (find_prop(pnode, "model"));
16281708Sstevel
16291708Sstevel /*
16301708Sstevel * Determine whether FRU is CPU module, Mem Controller,
16311708Sstevel * PCI card, schizo,xmits or sgsbbc.
16321708Sstevel */
16331708Sstevel if ((model != NULL) && strstr(model, "sgsbbc")) {
16341708Sstevel /*
16351708Sstevel * sgsbbc / bootbus-controller
16361708Sstevel */
16371708Sstevel portid = get_id(pnode->parent);
16381708Sstevel nodeid = SG_PORTID_TO_NODEID(portid);
16391708Sstevel board = SG_PORTID_TO_BOARD_NUM(portid);
16401708Sstevel
16411708Sstevel SG_SET_FRU_NAME_NODE(fru_name, nodeid);
16421708Sstevel SG_SET_FRU_NAME_IO_BOARD(fru_name, board);
16431708Sstevel SG_SET_FRU_NAME_MODULE(fru_name, portid % 2);
16441708Sstevel
16451708Sstevel log_printf("\tFailed Device : %s (%s)\n", model,
1646*5889Szk194757 name, 0);
16471708Sstevel log_printf("\tLocation : %s\n", fru_name, 0);
16481708Sstevel
16491708Sstevel } else if (strstr(name, "pci") && (portid == -1)) {
16501708Sstevel /*
16511708Sstevel * PCI Bridge if name = pci and it doesn't
16521708Sstevel * have a portid.
16531708Sstevel */
16541708Sstevel portid = get_id(pnode->parent);
16551708Sstevel nodeid = SG_PORTID_TO_NODEID(portid);
16561708Sstevel board = SG_PORTID_TO_BOARD_NUM(portid);
16571708Sstevel
16581708Sstevel SG_SET_FRU_NAME_NODE(fru_name, nodeid);
16591708Sstevel SG_SET_FRU_NAME_IO_BOARD(fru_name, board);
16601708Sstevel SG_SET_FRU_NAME_MODULE(fru_name, portid % 2);
16611708Sstevel
16621708Sstevel log_printf("\tFRU type : ", 0);
16631708Sstevel log_printf("PCI Bridge Device\n", 0);
16641708Sstevel log_printf("\tLocation : %s\n", fru_name, 0);
16651708Sstevel
16661708Sstevel } else if ((type != NULL) &&
16671708Sstevel (strstr(type, "cpu") ||
16681708Sstevel strstr(type, "memory-controller"))) {
16691708Sstevel /*
16701708Sstevel * CPU or memory controller
16711708Sstevel */
16721708Sstevel portid = get_id(pnode);
16731708Sstevel /*
16741708Sstevel * For cpu nodes that belong to a CMP, the
16751708Sstevel * portid is stored in the parent "cmp" node.
16761708Sstevel */
16771708Sstevel if (portid == -1)
16781708Sstevel portid = get_id(pnode->parent);
16791708Sstevel nodeid = SG_PORTID_TO_NODEID(portid);
16801708Sstevel board = SG_PORTID_TO_BOARD_NUM(portid);
16811708Sstevel
16821708Sstevel SG_SET_FRU_NAME_NODE(fru_name, nodeid);
16831708Sstevel SG_SET_FRU_NAME_CPU_BOARD(fru_name, board);
16841708Sstevel SG_SET_FRU_NAME_MODULE(fru_name, portid % 4);
16851708Sstevel
16861708Sstevel log_printf("\tFRU type : ", 0);
16871708Sstevel
16881708Sstevel if (strstr(type, "memory-controller"))
16891708Sstevel log_printf("Memory Controller on ", 0);
16901708Sstevel
16911708Sstevel log_printf("UltraSPARC module\n", 0);
16921708Sstevel
16931708Sstevel log_printf("\tLocation : %s\n", fru_name, 0);
16941708Sstevel
16951708Sstevel } else {
16961708Sstevel /*
16971708Sstevel * It should only be a PCI card if we get to
16981708Sstevel * here but lets check to be sure.
16991708Sstevel */
17001708Sstevel char *parents_model, *grandparents_model;
17011708Sstevel Prom_node *parent_pnode;
17021708Sstevel int pci_card_found = 0;
17031708Sstevel
17041708Sstevel if (pnode->parent != NULL)
17051708Sstevel parent_pnode = pnode->parent;
17061708Sstevel
17071708Sstevel /*
17081708Sstevel * Is our parent a schizo or xmits
17091708Sstevel */
17101708Sstevel parents_model = (char *)get_prop_val
17111708Sstevel (find_prop(pnode->parent, "model"));
17121708Sstevel if ((parents_model != NULL) &&
17131708Sstevel (strstr(parents_model, "SUNW,schizo") ||
17141708Sstevel strstr(parents_model, "SUNW,xmits"))) {
17151708Sstevel portid = get_id(pnode->parent);
17161708Sstevel pci_card_found = TRUE;
17171708Sstevel }
17181708Sstevel
17191708Sstevel /*
17201708Sstevel * Is our grandparent a schizo xmits
17211708Sstevel */
17221708Sstevel grandparents_model = (char *)get_prop_val
17231708Sstevel (find_prop(parent_pnode->parent, "model"));
17241708Sstevel if ((grandparents_model != NULL) &&
17251708Sstevel (strstr(grandparents_model,
17261708Sstevel "SUNW,schizo") ||
17271708Sstevel strstr(grandparents_model,
17281708Sstevel "SUNW,xmits"))) {
17291708Sstevel portid = get_id(parent_pnode->parent);
17301708Sstevel pci_card_found = TRUE;
17311708Sstevel }
17321708Sstevel
17331708Sstevel if (pci_card_found) {
17341708Sstevel nodeid = SG_PORTID_TO_NODEID(portid);
17351708Sstevel board = SG_PORTID_TO_BOARD_NUM(portid);
17361708Sstevel
17371708Sstevel SG_SET_FRU_NAME_NODE(fru_name, nodeid);
17381708Sstevel SG_SET_FRU_NAME_IO_BOARD(fru_name,
1739*5889Szk194757 board);
17401708Sstevel SG_SET_FRU_NAME_MODULE(fru_name,
1741*5889Szk194757 portid % 2);
17421708Sstevel
17431708Sstevel log_printf("\tFRU type :", 0);
17441708Sstevel log_printf(" PCI Card\n", 0);
17451708Sstevel log_printf("\tLocation : %s\n",
1746*5889Szk194757 fru_name, 0);
17471708Sstevel }
17481708Sstevel }
17491708Sstevel log_printf("\tPROM status: %s\n\n", status, 0);
17501708Sstevel
17511708Sstevel pnode = next_failed_node(pnode);
17521708Sstevel }
17531708Sstevel bnode = bnode->next;
17541708Sstevel
17551708Sstevel }
17561708Sstevel
17571708Sstevel bank_failed = display_us3_failed_banks(system_failed);
17581708Sstevel schizo_failed = display_schizo_revisions(tree->bd_list,
1759*5889Szk194757 SG_SCHIZO_FAILED);
17601708Sstevel if (system_failed || bank_failed || schizo_failed)
17611708Sstevel return (1);
17621708Sstevel else
17631708Sstevel return (0);
17641708Sstevel }
17651708Sstevel
17661708Sstevel
17671708Sstevel /*
17681708Sstevel * This routine displays the memory configuration for all boards in the
17691708Sstevel * system.
17701708Sstevel */
17711708Sstevel /*ARGSUSED0*/
17721708Sstevel void
display_memoryconf(Sys_tree * tree,struct grp_info * grps)17731708Sstevel display_memoryconf(Sys_tree *tree, struct grp_info *grps)
17741708Sstevel {
17751708Sstevel Board_node *bnode = tree->bd_list;
17761708Sstevel
17771708Sstevel log_printf("========================= Memory Configuration"
1778*5889Szk194757 " ===============================\n", 0);
17791708Sstevel log_printf("\n Logical Logical Logical ", 0);
17801708Sstevel log_printf("\n Port Bank Bank Bank "
1781*5889Szk194757 "DIMM Interleave Interleave", 0);
17821708Sstevel log_printf("\nFRU Name ID Num Size Status "
1783*5889Szk194757 "Size Factor Segment", 0);
17841708Sstevel log_printf("\n------------- ---- ---- ------ ----------- "
1785*5889Szk194757 "------ ---------- ----------", 0);
17861708Sstevel
17871708Sstevel while (bnode != NULL) {
17881708Sstevel if (get_us3_mem_regs(bnode)) {
17891708Sstevel log_printf(dgettext(TEXT_DOMAIN,
17901708Sstevel "\nFailed to get memory information.\n"), 0);
17911708Sstevel return;
17921708Sstevel }
17931708Sstevel bnode = bnode->next;
17941708Sstevel }
17951708Sstevel
17961708Sstevel /* Display what we have found */
17971708Sstevel display_us3_banks();
17981708Sstevel }
17991708Sstevel
18001708Sstevel /*
18011708Sstevel * This function provides Serengeti's formatting of the memory config
18021708Sstevel * information that get_us3_mem_regs() and display_us3_banks() code has
18031708Sstevel * gathered. It overrides the generic print_us3_memory_line() code
18041708Sstevel * which prints an error message.
18051708Sstevel */
18061708Sstevel 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)18071708Sstevel print_us3_memory_line(int portid, int bank_id, uint64_t bank_size,
18081708Sstevel char *bank_status, uint64_t dimm_size, uint32_t intlv, int seg_id)
18091708Sstevel {
18101708Sstevel int nodeid, board, mcid;
18111708Sstevel char fru_name[MAX_FRU_NAME_LEN] = "";
18121708Sstevel
18131708Sstevel mcid = SG_PORTID_TO_SAFARI_ID(portid);
18141708Sstevel nodeid = SG_PORTID_TO_NODEID(portid);
18151708Sstevel board = SG_PORTID_TO_BOARD_NUM(portid);
18161708Sstevel
18171708Sstevel SG_SET_FRU_NAME_NODE(fru_name, nodeid);
18181708Sstevel SG_SET_FRU_NAME_CPU_BOARD(fru_name, board);
18191708Sstevel SG_SET_FRU_NAME_MODULE(fru_name, mcid % 4);
18201708Sstevel SG_SET_FRU_NAME_BANK(fru_name, (bank_id % 4) % 2);
18211708Sstevel
18221708Sstevel log_printf("\n%-13s %2d %2d %4lldMB %11-s %4lldMB "
1823*5889Szk194757 " %2d-way %d",
1824*5889Szk194757 fru_name, mcid,
1825*5889Szk194757 (bank_id % 4), bank_size, bank_status, dimm_size,
1826*5889Szk194757 intlv, seg_id, 0);
18271708Sstevel }
18281708Sstevel
18291708Sstevel void
print_us3_failed_memory_line(int portid,int bank_id,char * bank_status)18301708Sstevel print_us3_failed_memory_line(int portid, int bank_id, char *bank_status)
18311708Sstevel {
18321708Sstevel int nodeid, board, mcid;
18331708Sstevel char fru_name[MAX_FRU_NAME_LEN] = "";
18341708Sstevel
18351708Sstevel mcid = SG_PORTID_TO_SAFARI_ID(portid);
18361708Sstevel nodeid = SG_PORTID_TO_NODEID(portid);
18371708Sstevel board = SG_PORTID_TO_BOARD_NUM(portid);
18381708Sstevel
18391708Sstevel SG_SET_FRU_NAME_NODE(fru_name, nodeid);
18401708Sstevel SG_SET_FRU_NAME_CPU_BOARD(fru_name, board);
18411708Sstevel SG_SET_FRU_NAME_MODULE(fru_name, mcid % 4);
18421708Sstevel SG_SET_FRU_NAME_BANK(fru_name, (bank_id % 4) % 2);
18431708Sstevel
18441708Sstevel log_printf("\tFRU type : ", 0);
18451708Sstevel log_printf("Physical Memory Bank\n", 0);
18461708Sstevel log_printf("\tLocation : %s (Logical Bank %2d)\n",
1847*5889Szk194757 fru_name, (bank_id %4), 0);
18481708Sstevel log_printf("\tPROM status: %s\n\n", bank_status, 0);
18491708Sstevel }
18501708Sstevel
18511708Sstevel
18521708Sstevel /*
18531708Sstevel * Find the requested board struct in the system device tree.
18541708Sstevel *
18551708Sstevel * This function overrides the functionality of the generic find_board()
18561708Sstevel * function in libprtdiag, but since we need to pass another parameter,
18571708Sstevel * we cannot simply overlay the symbol table.
18581708Sstevel */
18591708Sstevel static Board_node *
serengeti_find_board(Sys_tree * root,int board,int nodeid)18601708Sstevel serengeti_find_board(Sys_tree *root, int board, int nodeid)
18611708Sstevel {
18621708Sstevel Board_node *bnode = root->bd_list;
18631708Sstevel
18641708Sstevel while ((bnode != NULL) &&
1865*5889Szk194757 ((board != bnode->board_num) || (nodeid != bnode->node_id))) {
18661708Sstevel bnode = bnode->next;
18671708Sstevel }
18681708Sstevel return (bnode);
18691708Sstevel }
18701708Sstevel
18711708Sstevel
18721708Sstevel /*
18731708Sstevel * Add a board to the system list in order (sorted by NodeID then board#).
18741708Sstevel * Initialize all pointer fields to NULL.
18751708Sstevel */
18761708Sstevel static Board_node *
serengeti_insert_board(Sys_tree * root,int board,int nodeid)18771708Sstevel serengeti_insert_board(Sys_tree *root, int board, int nodeid)
18781708Sstevel {
18791708Sstevel Board_node *bnode;
18801708Sstevel Board_node *temp = root->bd_list;
18811708Sstevel
18821708Sstevel if ((bnode = (Board_node *) malloc(sizeof (Board_node))) == NULL) {
18831708Sstevel perror("malloc");
18841708Sstevel exit(1);
18851708Sstevel }
18861708Sstevel
18871708Sstevel bnode->nodes = NULL;
18881708Sstevel bnode->next = NULL;
18891708Sstevel bnode->board_num = board;
18901708Sstevel bnode->node_id = nodeid;
18911708Sstevel bnode->board_type = UNKNOWN_BOARD;
18921708Sstevel
18931708Sstevel if (temp == NULL)
18941708Sstevel root->bd_list = bnode;
18951708Sstevel
18961708Sstevel else if ((temp->board_num > board) && (temp->node_id >= nodeid)) {
18971708Sstevel bnode->next = temp;
18981708Sstevel root->bd_list = bnode;
18991708Sstevel
19001708Sstevel } else {
19011708Sstevel while ((temp->next != NULL) &&
1902*5889Szk194757 ((board > temp->next->board_num) ||
1903*5889Szk194757 (nodeid > temp->node_id)))
19041708Sstevel temp = temp->next;
19051708Sstevel
19061708Sstevel bnode->next = temp->next;
19071708Sstevel temp->next = bnode;
19081708Sstevel }
19091708Sstevel root->board_cnt++;
19101708Sstevel
19111708Sstevel return (bnode);
19121708Sstevel }
19131708Sstevel
19141708Sstevel /*
19151708Sstevel * We call do_devinfo() in order to use the libdevinfo device tree
19161708Sstevel * instead of OBP's device tree.
19171708Sstevel */
19181708Sstevel int
do_prominfo(int syserrlog,char * pgname,int log_flag,int prt_flag)19191708Sstevel do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag)
19201708Sstevel {
19211708Sstevel
19221708Sstevel return (do_devinfo(syserrlog, pgname, log_flag, prt_flag));
19231708Sstevel
19241708Sstevel }
19251708Sstevel
19261708Sstevel /*
19271708Sstevel * return the property value for the Prop passed in depending on
19281708Sstevel * which tree (OBP/DEVINFO) is being used.
19291708Sstevel */
19301708Sstevel void *
get_prop_val(Prop * prop)19311708Sstevel get_prop_val(Prop *prop)
19321708Sstevel {
19331708Sstevel if (prop == NULL)
19341708Sstevel return (NULL);
19351708Sstevel
19361708Sstevel /* Check which tree is being used. */
19371708Sstevel if (tree == DEVINFO_TREE)
19381708Sstevel return ((void *)(prop->value.val_ptr));
19391708Sstevel else {
19401708Sstevel if (prop->value.opp.holds_array)
19411708Sstevel return ((void *)(prop->value.opp.oprom_array));
19421708Sstevel else
19431708Sstevel return ((void *)(&prop->value.opp.oprom_node[0]));
19441708Sstevel }
19451708Sstevel }
19461708Sstevel
19471708Sstevel /*
19481708Sstevel * Search a Prom node and retrieve the property with the correct
19491708Sstevel * name depending on which tree (OBP/DEVINFO) is being used.
19501708Sstevel */
19511708Sstevel Prop *
find_prop(Prom_node * pnode,char * name)19521708Sstevel find_prop(Prom_node *pnode, char *name)
19531708Sstevel {
19541708Sstevel Prop *prop;
19551708Sstevel
19561708Sstevel if (pnode == NULL)
19571708Sstevel return (NULL);
19581708Sstevel
19591708Sstevel if (pnode->props == NULL)
19601708Sstevel return (NULL);
19611708Sstevel
19621708Sstevel prop = pnode->props;
19631708Sstevel
19641708Sstevel /* Check which tree is being used. */
19651708Sstevel if (tree == DEVINFO_TREE) {
19661708Sstevel while ((prop != NULL) &&
19671708Sstevel (strcmp((char *)(prop->name.val_ptr), name)))
19681708Sstevel prop = prop->next;
19691708Sstevel } else {
19701708Sstevel while ((prop != NULL) && (strcmp((char *)
19711708Sstevel (prop->name.opp.oprom_array), name)))
19721708Sstevel prop = prop->next;
19731708Sstevel }
19741708Sstevel return (prop);
19751708Sstevel }
19761708Sstevel
19771708Sstevel /*
19781708Sstevel * This function searches through the properties of the node passed in
19791708Sstevel * and returns a pointer to the value of the name property
19801708Sstevel * depending on which tree (OBP/DEVINFO) is being used.
19811708Sstevel */
19821708Sstevel char *
get_node_name(Prom_node * pnode)19831708Sstevel get_node_name(Prom_node *pnode)
19841708Sstevel {
19851708Sstevel Prop *prop;
19861708Sstevel
19871708Sstevel if (pnode == NULL)
19881708Sstevel return (NULL);
19891708Sstevel
19901708Sstevel prop = pnode->props;
19911708Sstevel while (prop != NULL) {
19921708Sstevel /* Check which tree is being used. */
19931708Sstevel if (tree == DEVINFO_TREE) {
19941708Sstevel if (strcmp("name", (char *)prop->name.val_ptr) == 0)
19951708Sstevel return ((char *)prop->value.val_ptr);
19961708Sstevel } else {
19971708Sstevel if (strcmp("name", prop->name.opp.oprom_array) == 0)
19981708Sstevel return (prop->value.opp.oprom_array);
19991708Sstevel }
20001708Sstevel prop = prop->next;
20011708Sstevel }
20021708Sstevel return (NULL);
20031708Sstevel }
20041708Sstevel
20051708Sstevel /*
20061708Sstevel * This function searches through the properties of the node passed in
20071708Sstevel * and returns a pointer to the value of the device_type property
20081708Sstevel * depending on which tree (OBP/DEVINFO) is being used.
20091708Sstevel */
20101708Sstevel char *
get_node_type(Prom_node * pnode)20111708Sstevel get_node_type(Prom_node *pnode)
20121708Sstevel {
20131708Sstevel Prop *prop;
20141708Sstevel
20151708Sstevel if (pnode == NULL)
20161708Sstevel return (NULL);
20171708Sstevel
20181708Sstevel prop = pnode->props;
20191708Sstevel while (prop != NULL) {
20201708Sstevel /* Check which tree is being used. */
20211708Sstevel if (tree == DEVINFO_TREE) {
20221708Sstevel if (strcmp("device_type", (char *)prop->name.val_ptr)
20231708Sstevel == 0)
20241708Sstevel return ((char *)prop->value.val_ptr);
20251708Sstevel } else {
20261708Sstevel if (strcmp("device_type", prop->name.opp.oprom_array)
20271708Sstevel == 0)
20281708Sstevel return (prop->value.opp.oprom_array);
20291708Sstevel }
20301708Sstevel prop = prop->next;
20311708Sstevel }
20321708Sstevel return (NULL);
20331708Sstevel }
20341708Sstevel
20351708Sstevel /*
20361708Sstevel * Take a snapshot of the OBP device tree and walk this snapshot
20371708Sstevel * to find all failed HW (ie. devices with a status property of
20381708Sstevel * 'fail'). Call display_failed_parts() to display the failed HW.
20391708Sstevel */
20401708Sstevel void
get_failed_parts(void)20411708Sstevel get_failed_parts(void)
20421708Sstevel {
20431708Sstevel int system_failed = 0;
20441708Sstevel Sys_tree obp_sys_tree; /* system information */
20451708Sstevel
20461708Sstevel /* set the the system tree fields */
20471708Sstevel obp_sys_tree.sys_mem = NULL;
20481708Sstevel obp_sys_tree.boards = NULL;
20491708Sstevel obp_sys_tree.bd_list = NULL;
20501708Sstevel obp_sys_tree.board_cnt = 0;
20511708Sstevel
20521708Sstevel if (promopen(O_RDONLY)) {
20531708Sstevel (void) fprintf(stderr, "%s",
2054*5889Szk194757 dgettext(TEXT_DOMAIN, "openprom device "
2055*5889Szk194757 "open failed"));
20561708Sstevel return;
20571708Sstevel }
20581708Sstevel
20591708Sstevel if ((is_openprom() == 0) || (next(0) == 0)) {
20601708Sstevel (void) fprintf(stderr, "%s",
2061*5889Szk194757 dgettext(TEXT_DOMAIN, "openprom device "
2062*5889Szk194757 "error encountered."));
20631708Sstevel return;
20641708Sstevel }
20651708Sstevel
20661708Sstevel tree = OBP_TREE; /* Switch to the OBP tree */
20671708Sstevel
20681708Sstevel (void) walk(&obp_sys_tree, NULL, next(0));
20691708Sstevel
20701708Sstevel system_failed = display_failed_parts(&obp_sys_tree);
20711708Sstevel
20721708Sstevel if (!system_failed) {
20731708Sstevel log_printf(dgettext(TEXT_DOMAIN,
2074*5889Szk194757 "No Hardware failures found in System\n"), 0);
20751708Sstevel }
20761708Sstevel promclose();
20771708Sstevel tree = DEVINFO_TREE; /* Switch back to the DEVINFO tree */
20781708Sstevel }
20791708Sstevel
20801708Sstevel /*
20811708Sstevel * get_slot_name figures out the slot no. for the card. In the case of
20821708Sstevel * XMITS slots 2 & 3 and slots 6 & 7 are reversed in slot_name by OBP
20831708Sstevel * so we need to cater for this to correctly identify the slot no.
20841708Sstevel */
20851708Sstevel static void
get_slot_name(struct io_card * card,char * slot_name)20861708Sstevel get_slot_name(struct io_card *card, char *slot_name)
20871708Sstevel {
20881708Sstevel char tmp_ptr[2];
20891708Sstevel
20901708Sstevel if (strlen(slot_name) != 0) {
20911708Sstevel if (strcmp(card->notes, XMITS_COMPATIBLE) == 0) {
20921708Sstevel (void) sprintf(tmp_ptr, "%c",
2093*5889Szk194757 slot_name[strlen(slot_name) -1]);
20941708Sstevel switch (tmp_ptr[0]) {
20951708Sstevel case '2':
20961708Sstevel (void) sprintf(card->slot_str, "%c", '3');
20971708Sstevel break;
20981708Sstevel case '3':
20991708Sstevel (void) sprintf(card->slot_str, "%c", '2');
21001708Sstevel break;
21011708Sstevel case '6':
21021708Sstevel (void) sprintf(card->slot_str, "%c", '7');
21031708Sstevel break;
21041708Sstevel case '7':
21051708Sstevel (void) sprintf(card->slot_str, "%c", '6');
21061708Sstevel break;
21071708Sstevel default:
21081708Sstevel (void) sprintf(card->slot_str, "%c",
2109*5889Szk194757 slot_name[strlen(slot_name) -1]);
21101708Sstevel }
21111708Sstevel } else
21121708Sstevel (void) sprintf(card->slot_str, "%c",
2113*5889Szk194757 slot_name[strlen(slot_name) -1]);
21141708Sstevel } else
21151708Sstevel (void) sprintf(card->slot_str, "-");
21161708Sstevel }
2117