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 * Starcat Platform specific functions.
261708Sstevel *
271708Sstevel * called when :
281708Sstevel * machine_type == MTYPE_STARCAT
291708Sstevel */
301708Sstevel
311708Sstevel #pragma ident "%Z%%M% %I% %E% SMI"
321708Sstevel
331708Sstevel #include <stdio.h>
341708Sstevel #include <stdlib.h>
351708Sstevel #include <unistd.h>
361708Sstevel #include <ctype.h>
371708Sstevel #include <string.h>
381708Sstevel #include <kvm.h>
391708Sstevel #include <varargs.h>
401708Sstevel #include <time.h>
411708Sstevel #include <dirent.h>
421708Sstevel #include <fcntl.h>
431708Sstevel #include <assert.h>
441708Sstevel #include <sys/param.h>
451708Sstevel #include <sys/stat.h>
461708Sstevel #include <sys/types.h>
471708Sstevel #include <sys/utsname.h>
481708Sstevel #include <sys/openpromio.h>
491708Sstevel #include <libintl.h>
501708Sstevel #include <syslog.h>
511708Sstevel #include <sys/dkio.h>
521708Sstevel #include <pdevinfo.h>
531708Sstevel #include <display.h>
541708Sstevel #include <pdevinfo_sun4u.h>
551708Sstevel #include <display_sun4u.h>
561708Sstevel #include <libprtdiag.h>
571708Sstevel
581708Sstevel #define HZ_TO_MHZ(x) (((x) + 500000) / 1000000)
591708Sstevel #define PORTID_TO_EXPANDER(p) (((p) >> 5) & 0x1f)
601708Sstevel #define PORTID_TO_SLOT(p) (((p) >> 3) & 0x1)
611708Sstevel #define PORTID_TO_INSTANCE(p) ((p) & 0x3)
621708Sstevel #define SCHIZO_COMPATIBLE "pci108e,8001"
631708Sstevel #define XMITS_COMPATIBLE "pci108e,8002"
641708Sstevel #define SC_BOARD_TYPE(id) (PORTID_TO_SLOT(id) ? "IO" : "SB")
651708Sstevel
661708Sstevel #ifndef TEXT_DOMAIN
671708Sstevel #define TEXT_DOMAIN "SYS_TEST"
681708Sstevel #endif /* TEXT_DOMAIN */
691708Sstevel
701708Sstevel #define DEFAULT_MAX_FREQ 66 /* 66 MHz */
711708Sstevel #define PCIX_MAX_FREQ 90 /* 90 MHz */
721708Sstevel
731708Sstevel /*
741708Sstevel * these functions will overlay the symbol table of libprtdiag
751708Sstevel * at runtime (Starcat systems only)
761708Sstevel */
771708Sstevel
781708Sstevel int do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag);
791708Sstevel void *get_prop_val(Prop *prop);
801708Sstevel Prop *find_prop(Prom_node *pnode, char *name);
811708Sstevel char *get_node_name(Prom_node *pnode);
821708Sstevel char *get_node_type(Prom_node *pnode);
831708Sstevel void add_node(Sys_tree *, Prom_node *);
841708Sstevel void display_pci(Board_node *);
851708Sstevel void display_ffb(Board_node *, int);
861708Sstevel void display_io_cards(struct io_card *list);
871708Sstevel void display_cpu_devices(Sys_tree *tree);
881708Sstevel void display_cpus(Board_node *board);
891708Sstevel void display_memoryconf(Sys_tree *tree, struct grp_info *grps);
901708Sstevel void print_us3_memory_line(int portid, int bank_id, uint64_t bank_size,
911708Sstevel char *bank_status, uint64_t dimm_size, uint32_t intlv, int seg_id);
921708Sstevel void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
931708Sstevel struct system_kstat_data *kstats);
941708Sstevel
951708Sstevel /* Local Functions */
961708Sstevel static void starcat_disp_hw_revisions(Prom_node *root);
971708Sstevel static void display_io_max_bus_speed(struct io_card *p);
981708Sstevel static void display_io_slot_info(struct io_card *p);
991708Sstevel
1001708Sstevel /* The bus max freq is determined based on board level in use */
1011708Sstevel int board_bus_max_freq = DEFAULT_MAX_FREQ; /* 66MHz default */
1021708Sstevel
1031708Sstevel /*
1041708Sstevel * display_pci
1051708Sstevel * Display all the PCI IO cards on this board.
1061708Sstevel */
1071708Sstevel void
display_pci(Board_node * board)1081708Sstevel display_pci(Board_node *board)
1091708Sstevel {
1101708Sstevel struct io_card *card_list = NULL;
1111708Sstevel struct io_card card;
1121708Sstevel void *value;
1131708Sstevel Prom_node *pci;
1141708Sstevel Prom_node *card_node;
1151708Sstevel Prom_node *pci_bridge_node = NULL;
1161708Sstevel char *slot_name_arr[MAX_SLOTS_PER_IO_BD] = {NULL};
1171708Sstevel char *slot_name = NULL;
1181708Sstevel int slot_name_bits;
1191708Sstevel int slot_name_offset = 0;
1201708Sstevel char *child_name;
1211708Sstevel char *name, *type;
1221708Sstevel char buf[MAXSTRLEN];
1231708Sstevel int *int_val;
1241708Sstevel int pci_bus;
1251708Sstevel int pci_bridge = 0;
1261708Sstevel int pci_bridge_dev_no;
1271708Sstevel int child_dev_no;
1281708Sstevel int i;
1291708Sstevel int portid;
1301708Sstevel int version, *pversion;
1311708Sstevel
1321708Sstevel if (board == NULL)
1331708Sstevel return;
1341708Sstevel
1351708Sstevel /* Initialize all the common information */
1361708Sstevel card.display = TRUE;
1371708Sstevel card.board = board->board_num;
1381708Sstevel card.node_id = board->node_id;
1391708Sstevel
1401708Sstevel /*
1411708Sstevel * Search for each schizo, then find/display all nodes under
1421708Sstevel * each schizo node found. Since the model property "SUNW,schizo"
1431708Sstevel * is not supported on Starcat, we must match on the compatible
1441708Sstevel * property "pci108e,8001".
1451708Sstevel */
1461708Sstevel for (pci = dev_find_node_by_compatible(board->nodes, SCHIZO_COMPATIBLE);
1471708Sstevel pci != NULL;
1481708Sstevel pci = dev_next_node_by_compatible(pci, SCHIZO_COMPATIBLE)) {
1491708Sstevel
1501708Sstevel /* set max freq for this board */
1511708Sstevel board_bus_max_freq = DEFAULT_MAX_FREQ;
1521708Sstevel /*
1531708Sstevel * Find out if this is a PCI or cPCI IO Board.
1541708Sstevel * If "enum-impl" property exists in pci node => cPCI.
1551708Sstevel */
1561708Sstevel value = get_prop_val(find_prop(pci, "enum-impl"));
1571708Sstevel if (value == NULL) {
1581708Sstevel (void) sprintf(card.bus_type, "PCI");
1591708Sstevel } else {
1601708Sstevel (void) sprintf(card.bus_type, "cPCI");
1611708Sstevel }
1621708Sstevel
1631708Sstevel if (strstr((char *)get_prop_val(
164*5889Szk194757 find_prop(pci, "compatible")), XMITS_COMPATIBLE)) {
165*5889Szk194757 sprintf(card.notes, "%s", XMITS_COMPATIBLE);
1661708Sstevel /*
1671708Sstevel * With XMITS 3.X and PCI-X mode, the bus speed
1681708Sstevel * can be higher than 66MHZ.
1691708Sstevel */
1701708Sstevel value = (int *)get_prop_val
171*5889Szk194757 (find_prop(pci, "module-revision#"));
1721708Sstevel if (value) {
1731708Sstevel pversion = (int *)value;
1741708Sstevel version = *pversion;
1751708Sstevel if (version >= 4)
1761708Sstevel board_bus_max_freq = PCIX_MAX_FREQ;
1771708Sstevel }
1781708Sstevel } else if (strstr((char *)get_prop_val(
179*5889Szk194757 find_prop(pci, "compatible")), SCHIZO_COMPATIBLE))
1801708Sstevel sprintf(card.notes, "%s", SCHIZO_COMPATIBLE);
1811708Sstevel else
1821708Sstevel sprintf(card.notes, " ");
1831708Sstevel
1841708Sstevel /*
1851708Sstevel * Get slot-names property from parent node and
1861708Sstevel * store the individual slot names in an array.
1871708Sstevel * This is more general than Starcat requires, but
1881708Sstevel * it is correct, according to the slot-names property.
1891708Sstevel */
1901708Sstevel value = (char *)get_prop_val(find_prop(pci, "slot-names"));
1911708Sstevel if (value == NULL) {
1921708Sstevel /*
1931708Sstevel * No slot_names property. This could be an Xmits
1941708Sstevel * card, so check the child node for slot-names property
1951708Sstevel */
1961708Sstevel value = (char *)get_prop_val(
197*5889Szk194757 find_prop(pci->child, "slot-names"));
1981708Sstevel }
1991708Sstevel
2001708Sstevel if (value != NULL) {
2011708Sstevel /* Get the 4 byte bitmask and pointer to first name */
2021708Sstevel slot_name_bits = *(int *)value;
2031708Sstevel if (slot_name_bits > 0)
2041708Sstevel slot_name_offset = slot_name_bits - 1;
2051708Sstevel slot_name = (char *)value + sizeof (int);
2061708Sstevel
2071708Sstevel for (i = 0; i < MAX_SLOTS_PER_IO_BD; i++) {
2081708Sstevel if (! (slot_name_bits & (1 << i))) {
2091708Sstevel slot_name_arr[i] = (char *)NULL;
2101708Sstevel continue;
2111708Sstevel }
2121708Sstevel
2131708Sstevel /*
2141708Sstevel * Save the name pointer into the array
2151708Sstevel * and advance it past the end of this
2161708Sstevel * slot name
2171708Sstevel */
2181708Sstevel slot_name_arr[i] = slot_name;
2191708Sstevel slot_name += strlen(slot_name) + 1;
2201708Sstevel }
2211708Sstevel slot_name = (char *)NULL;
2221708Sstevel }
2231708Sstevel
2241708Sstevel /*
2251708Sstevel * Search for Children of this node ie. Cards.
2261708Sstevel * Note: any of these cards can be a pci-bridge
2271708Sstevel * that itself has children. If we find a
2281708Sstevel * pci-bridge we need to handle it specially.
2291708Sstevel */
2301708Sstevel card_node = pci->child;
2311708Sstevel while (card_node != NULL) {
2321708Sstevel pci_bridge = 0;
2331708Sstevel
2341708Sstevel /* If it doesn't have a name, skip it */
2351708Sstevel name = (char *)get_prop_val(
236*5889Szk194757 find_prop(card_node, "name"));
2371708Sstevel if (name == NULL) {
2381708Sstevel card_node = card_node->sibling;
2391708Sstevel continue;
2401708Sstevel }
2411708Sstevel
2421708Sstevel /*
2431708Sstevel * get dev# and func# for this card from the
2441708Sstevel * 'reg' property.
2451708Sstevel */
2461708Sstevel int_val = (int *)get_prop_val(
247*5889Szk194757 find_prop(card_node, "reg"));
2481708Sstevel if (int_val != NULL) {
2491708Sstevel card.dev_no = (((*int_val) & 0xF800) >> 11);
2501708Sstevel card.func_no = (((*int_val) & 0x700) >> 8);
2511708Sstevel } else {
2521708Sstevel card.dev_no = -1;
2531708Sstevel card.func_no = -1;
2541708Sstevel }
2551708Sstevel
2561708Sstevel /*
2571708Sstevel * If this is a pci-bridge, then store it's dev#
2581708Sstevel * as its children nodes need this to get their slot#.
2591708Sstevel * We set the pci_bridge flag so that we know we are
2601708Sstevel * looking at a pci-bridge node. This flag gets reset
2611708Sstevel * every time we enter this while loop.
2621708Sstevel */
2631708Sstevel
2641708Sstevel /*
2651708Sstevel * Check for a PCI-PCI Bridge for PCI and cPCI
2661708Sstevel * IO Boards using the name and type properties.
2671708Sstevel */
2681708Sstevel type = (char *)get_prop_val(
269*5889Szk194757 find_prop(card_node, "device_type"));
2701708Sstevel if ((type != NULL) &&
271*5889Szk194757 (strncmp(name, "pci", 3) == 0) &&
272*5889Szk194757 (strcmp(type, "pci") == 0)) {
2731708Sstevel pci_bridge_dev_no = card.dev_no;
2741708Sstevel pci_bridge_node = card_node;
2751708Sstevel pci_bridge = TRUE;
2761708Sstevel }
2771708Sstevel
2781708Sstevel /*
2791708Sstevel * Get slot-names property from slot_names_arr.
2801708Sstevel * If we are the child of a pci_bridge we use the
2811708Sstevel * dev# of the pci_bridge as an index to get
2821708Sstevel * the slot number. We know that we are a child of
2831708Sstevel * a pci-bridge if our parent is the same as the last
2841708Sstevel * pci_bridge node found above.
2851708Sstevel */
2861708Sstevel if (card.dev_no != -1) {
2871708Sstevel /*
2881708Sstevel * We compare this card's parent node with the
2891708Sstevel * pci_bridge_node to see if it's a child.
2901708Sstevel */
2911708Sstevel if (card_node->parent == pci_bridge_node) {
2921708Sstevel /* use dev_no of pci_bridge */
2931708Sstevel child_dev_no = pci_bridge_dev_no - 1;
2941708Sstevel } else {
2951708Sstevel /* use card's own dev_no */
2961708Sstevel child_dev_no = card.dev_no - 1;
2971708Sstevel }
2981708Sstevel
2991708Sstevel if (child_dev_no < MAX_SLOTS_PER_IO_BD &&
3001708Sstevel child_dev_no >= 0 &&
3011708Sstevel slot_name_arr
3021708Sstevel [child_dev_no + slot_name_offset] != NULL) {
3031708Sstevel
3041708Sstevel slot_name = slot_name_arr[
3051708Sstevel child_dev_no + slot_name_offset];
3061708Sstevel } else
3071708Sstevel slot_name = (char *)NULL;
3081708Sstevel
3091708Sstevel if (slot_name != NULL && slot_name[0] != '\0') {
3101708Sstevel (void) sprintf(card.slot_str, "%s",
3111708Sstevel slot_name);
3121708Sstevel } else {
3131708Sstevel (void) sprintf(card.slot_str, "-");
3141708Sstevel }
3151708Sstevel } else {
3161708Sstevel (void) sprintf(card.slot_str, "%c", '-');
3171708Sstevel }
3181708Sstevel
3191708Sstevel /*
3201708Sstevel * Get the portid of the schizo that this card
3211708Sstevel * lives under.
3221708Sstevel */
3231708Sstevel portid = -1;
3241708Sstevel value = get_prop_val(find_prop(pci, "portid"));
3251708Sstevel if (value != NULL) {
3261708Sstevel portid = *(int *)value;
3271708Sstevel }
3281708Sstevel card.schizo_portid = portid;
3291708Sstevel
3301708Sstevel #ifdef DEBUG
3311708Sstevel (void) sprintf(card.notes, "%s portid [%d]"
332*5889Szk194757 " dev_no [%d] slot_name[%s] name_bits[%#x]",
333*5889Szk194757 card.notes, portid, card.dev_no,
334*5889Szk194757 ((slot_name != NULL) ? slot_name : "NULL"),
335*5889Szk194757 slot_name_bits);
3361708Sstevel #endif /* DEBUG */
3371708Sstevel
3381708Sstevel /*
3391708Sstevel * Find out whether this is PCI bus A or B
3401708Sstevel * using the 'reg' property.
3411708Sstevel */
3421708Sstevel int_val = (int *)get_prop_val
343*5889Szk194757 (find_prop(pci, "reg"));
3441708Sstevel
3451708Sstevel if (int_val != NULL) {
3461708Sstevel int_val ++; /* skip over first integer */
3471708Sstevel pci_bus = ((*int_val) & 0x7f0000);
3481708Sstevel if (pci_bus == 0x600000)
3491708Sstevel card.pci_bus = 'A';
3501708Sstevel else if (pci_bus == 0x700000)
3511708Sstevel card.pci_bus = 'B';
3521708Sstevel else
3531708Sstevel card.pci_bus = '-';
3541708Sstevel } else {
3551708Sstevel card.pci_bus = '-';
3561708Sstevel }
3571708Sstevel
3581708Sstevel
3591708Sstevel /*
3601708Sstevel * Check for failed status.
3611708Sstevel */
3621708Sstevel if (node_failed(card_node))
3631708Sstevel strcpy(card.status, "fail");
3641708Sstevel else
3651708Sstevel strcpy(card.status, "ok");
3661708Sstevel
3671708Sstevel /* Get the model of this card */
3681708Sstevel value = get_prop_val(find_prop(card_node, "model"));
3691708Sstevel if (value == NULL)
3701708Sstevel card.model[0] = '\0';
3711708Sstevel else {
3721708Sstevel (void) sprintf(card.model, "%s", (char *)value);
3731708Sstevel /*
3741708Sstevel * If we wish to exclude onboard devices
3751708Sstevel * (such as SBBC) then this is the place
3761708Sstevel * and here is how to do it:
3771708Sstevel *
3781708Sstevel * if (strcmp(card.model, "SUNW,sbbc") == 0) {
3791708Sstevel * card_node = card_node->sibling;
3801708Sstevel * continue;
3811708Sstevel * }
3821708Sstevel */
3831708Sstevel }
3841708Sstevel
3851708Sstevel /*
3861708Sstevel * The card may have a "clock-frequency" but we
3871708Sstevel * are not interested in that. Instead we get the
3881708Sstevel * "clock-frequency" of the PCI Bus that the card
3891708Sstevel * resides on. PCI-A can operate at 33Mhz or 66Mhz
3901708Sstevel * depending on what card is plugged into the Bus.
3911708Sstevel * PCI-B always operates at 33Mhz.
3921708Sstevel *
3931708Sstevel */
3941708Sstevel int_val = get_prop_val(find_prop(pci,
395*5889Szk194757 "clock-frequency"));
3961708Sstevel if (int_val != NULL) {
3971708Sstevel card.freq = HZ_TO_MHZ(*int_val);
3981708Sstevel } else {
3991708Sstevel card.freq = -1;
4001708Sstevel }
4011708Sstevel
4021708Sstevel /*
4031708Sstevel * Figure out how we want to display the name
4041708Sstevel */
4051708Sstevel value = get_prop_val(find_prop(card_node,
406*5889Szk194757 "compatible"));
4071708Sstevel if (value != NULL) {
4081708Sstevel /* use 'name'-'compatible' */
4091708Sstevel (void) sprintf(buf, "%s-%s", name,
410*5889Szk194757 (char *)value);
4111708Sstevel } else {
4121708Sstevel /* just use 'name' */
4131708Sstevel (void) sprintf(buf, "%s", name);
4141708Sstevel }
4151708Sstevel name = buf;
4161708Sstevel
4171708Sstevel /*
4181708Sstevel * If this node has children, add the device_type
4191708Sstevel * of the child to the name value of this card.
4201708Sstevel */
4211708Sstevel child_name = (char *)get_node_name(card_node->child);
4221708Sstevel if ((card_node->child != NULL) &&
423*5889Szk194757 (child_name != NULL)) {
4241708Sstevel value = get_prop_val(find_prop(card_node->child,
425*5889Szk194757 "device_type"));
4261708Sstevel if (value != NULL) {
4271708Sstevel /* add device_type of child to name */
4281708Sstevel (void) sprintf(card.name, "%s/%s (%s)",
429*5889Szk194757 name, child_name,
430*5889Szk194757 (char *)value);
4311708Sstevel } else {
4321708Sstevel /* just add child's name */
4331708Sstevel (void) sprintf(card.name, "%s/%s",
434*5889Szk194757 name, child_name);
4351708Sstevel }
4361708Sstevel } else {
4371708Sstevel /* childless, just the card's name */
4381708Sstevel (void) sprintf(card.name, "%s", (char *)name);
4391708Sstevel }
4401708Sstevel
4411708Sstevel /*
4421708Sstevel * If this is a pci-bridge, then add the word
4431708Sstevel * 'pci-bridge' to its model.
4441708Sstevel */
4451708Sstevel if (pci_bridge) {
4461708Sstevel if (card.model[0] == '\0')
4471708Sstevel (void) sprintf(card.model,
448*5889Szk194757 "%s", "pci-bridge");
4491708Sstevel else
4501708Sstevel (void) strcat(card.model,
451*5889Szk194757 "/pci-bridge");
4521708Sstevel }
4531708Sstevel
4541708Sstevel /* insert this card in the list to be displayed later */
4551708Sstevel card_list = insert_io_card(card_list, &card);
4561708Sstevel
4571708Sstevel /*
4581708Sstevel * If we are dealing with a pci-bridge, we need to move
4591708Sstevel * down to the children of this bridge, if there are
4601708Sstevel * any, otherwise its siblings.
4611708Sstevel *
4621708Sstevel * If not a bridge, we are either dealing with a regular
4631708Sstevel * card (in which case we move onto the sibling of this
4641708Sstevel * card) or we are dealing with a child of a pci-bridge
4651708Sstevel * (in which case we move onto the child's siblings or
4661708Sstevel * if there are no more siblings for this child, we
4671708Sstevel * move onto the parent's siblings). I hope you're
4681708Sstevel * getting all this, there will be an exam later.
4691708Sstevel */
4701708Sstevel if (pci_bridge) {
4711708Sstevel if (card_node->child != NULL)
4721708Sstevel card_node = card_node->child;
4731708Sstevel else
4741708Sstevel card_node = card_node->sibling;
4751708Sstevel } else {
4761708Sstevel /*
4771708Sstevel * If our parent is a pci-bridge but there
4781708Sstevel * are no more of its children to process we
4791708Sstevel * move back up to our parent's sibling,
4801708Sstevel * otherwise we move onto our own sibling.
4811708Sstevel */
4821708Sstevel if ((card_node->parent == pci_bridge_node) &&
483*5889Szk194757 (card_node->sibling == NULL))
4841708Sstevel card_node =
4851708Sstevel pci_bridge_node->sibling;
4861708Sstevel else
4871708Sstevel card_node = card_node->sibling;
4881708Sstevel }
4891708Sstevel
4901708Sstevel } /* end while (card_node ...) loop */
4911708Sstevel
4921708Sstevel } /* end for (pci ...) loop */
4931708Sstevel
4941708Sstevel display_io_cards(card_list);
4951708Sstevel free_io_cards(card_list);
4961708Sstevel }
4971708Sstevel
4981708Sstevel /*
4991708Sstevel * display_ffb
5001708Sstevel *
5011708Sstevel * There are no FFB's on a Starcat, however in the generic library,
5021708Sstevel * the display_ffb() function is implemented so we have to define an
5031708Sstevel * empty function here.
5041708Sstevel */
5051708Sstevel /*ARGSUSED0*/
5061708Sstevel void
display_ffb(Board_node * board,int table)5071708Sstevel display_ffb(Board_node *board, int table)
5081708Sstevel {
5091708Sstevel }
5101708Sstevel
5111708Sstevel /*
5121708Sstevel * add_node
5131708Sstevel *
5141708Sstevel * This function adds a board node to the board structure where that
5151708Sstevel * that node's physical component lives.
5161708Sstevel */
5171708Sstevel void
add_node(Sys_tree * root,Prom_node * pnode)5181708Sstevel add_node(Sys_tree *root, Prom_node *pnode)
5191708Sstevel {
5201708Sstevel int portid = -1;
5211708Sstevel int nodeid = -1;
5221708Sstevel void *value;
5231708Sstevel Board_node *bnode;
5241708Sstevel Prom_node *p;
5251708Sstevel char *type;
5261708Sstevel
5271708Sstevel /* Get the board number of this board from the portid prop */
5281708Sstevel if ((value = get_prop_val(find_prop(pnode, "portid"))) == NULL) {
5291708Sstevel if (type = get_node_type(pnode))
5301708Sstevel if (strcmp(type, "cpu") == 0)
5311708Sstevel value = get_prop_val(find_prop(pnode->parent,
5321708Sstevel "portid"));
5331708Sstevel }
5341708Sstevel if (value != NULL) {
5351708Sstevel portid = *(int *)value;
5361708Sstevel nodeid = PORTID_TO_EXPANDER(portid);
5371708Sstevel }
5381708Sstevel
5391708Sstevel /* find the board node with the same board number */
5401708Sstevel if ((bnode = find_board(root, portid)) == NULL) {
5411708Sstevel bnode = insert_board(root, portid);
5421708Sstevel bnode->board_type = UNKNOWN_BOARD;
5431708Sstevel bnode->node_id = nodeid;
5441708Sstevel }
5451708Sstevel
5461708Sstevel /* now attach this prom node to the board list */
5471708Sstevel /* Insert this node at the end of the list */
5481708Sstevel pnode->sibling = NULL;
5491708Sstevel if (bnode->nodes == NULL)
5501708Sstevel bnode->nodes = pnode;
5511708Sstevel else {
5521708Sstevel p = bnode->nodes;
5531708Sstevel while (p->sibling != NULL)
5541708Sstevel p = p->sibling;
5551708Sstevel p->sibling = pnode;
5561708Sstevel }
5571708Sstevel }
5581708Sstevel
5591708Sstevel
5601708Sstevel
5611708Sstevel /*
5621708Sstevel * Print out all the io cards in the list. Also print the column
5631708Sstevel * headers if told to do so.
5641708Sstevel */
5651708Sstevel void
display_io_cards(struct io_card * list)5661708Sstevel display_io_cards(struct io_card *list)
5671708Sstevel {
5681708Sstevel char *hdrfmt = "%-10.10s %-4.4s %-4.4s %-4.4s %-4.4s %-4.4s"
569*5889Szk194757 " %-4.4s %-5.5s %-32.32s %-22.22s"
5701708Sstevel #ifdef DEBUG
571*5889Szk194757 " %-22.22s"
5721708Sstevel #endif /* DEBUG */
573*5889Szk194757 "\n";
5741708Sstevel
5751708Sstevel static int banner = FALSE; /* Have we printed the column headings? */
5761708Sstevel struct io_card *p;
5771708Sstevel
5781708Sstevel if (list == NULL)
5791708Sstevel return;
5801708Sstevel
5811708Sstevel (void) textdomain(TEXT_DOMAIN);
5821708Sstevel
5831708Sstevel if (banner == FALSE) {
5841708Sstevel log_printf(hdrfmt,
5851708Sstevel "", "", "", "",
5861708Sstevel gettext("Bus"),
5871708Sstevel gettext("Max"),
5881708Sstevel "", "", "", "",
5891708Sstevel #ifdef DEBUG
5901708Sstevel "",
5911708Sstevel #endif /* DEBUG */
5921708Sstevel 0);
5931708Sstevel
5941708Sstevel log_printf(hdrfmt,
5951708Sstevel "",
5961708Sstevel gettext("IO"),
5971708Sstevel gettext("Port"),
5981708Sstevel gettext("Bus"),
5991708Sstevel gettext("Freq"),
6001708Sstevel gettext("Bus"),
6011708Sstevel gettext("Dev,"),
6021708Sstevel "", "", "",
6031708Sstevel #ifdef DEBUG
6041708Sstevel "",
6051708Sstevel #endif /* DEBUG */
6061708Sstevel 0);
6071708Sstevel
6081708Sstevel log_printf(hdrfmt,
6091708Sstevel gettext("Slot ID"),
6101708Sstevel gettext("Type"),
6111708Sstevel gettext(" ID"),
6121708Sstevel gettext("Side"),
6131708Sstevel gettext("MHz"),
6141708Sstevel gettext("Freq"),
6151708Sstevel gettext("Func"),
6161708Sstevel gettext("State"),
6171708Sstevel gettext("Name"),
6181708Sstevel gettext("Model"),
6191708Sstevel #ifdef DEBUG
6201708Sstevel gettext("Notes"),
6211708Sstevel #endif /* DEBUG */
6221708Sstevel 0);
6231708Sstevel
6241708Sstevel log_printf(hdrfmt,
6251708Sstevel "----------", "----", "----", "----", "----", "----",
6261708Sstevel "----", "-----", "--------------------------------",
6271708Sstevel "----------------------",
6281708Sstevel #ifdef DEBUG
6291708Sstevel "----------------------",
6301708Sstevel #endif /* DEBUG */
6311708Sstevel 0);
6321708Sstevel
6331708Sstevel banner = TRUE;
6341708Sstevel }
6351708Sstevel
6361708Sstevel for (p = list; p != NULL; p = p -> next) {
6371708Sstevel
6381708Sstevel display_io_slot_info(p);
6391708Sstevel
6401708Sstevel display_io_max_bus_speed(p);
6411708Sstevel
6421708Sstevel log_printf("\n", 0);
6431708Sstevel }
6441708Sstevel }
6451708Sstevel
6461708Sstevel
6471708Sstevel static void
display_io_slot_info(struct io_card * p)6481708Sstevel display_io_slot_info(struct io_card *p)
6491708Sstevel {
6501708Sstevel /*
6511708Sstevel * Onboard devices are distinguished by Slot IDs that
6521708Sstevel * indicate only the I/O board. Plug-in cards indicate
6531708Sstevel * their leaf and Schizo.
6541708Sstevel */
6551708Sstevel
6561708Sstevel if (p->slot_str[0] == '-') {
6571708Sstevel log_printf("/%-2s%02d ",
658*5889Szk194757 SC_BOARD_TYPE(p->board),
659*5889Szk194757 PORTID_TO_EXPANDER(p->board), 0);
6601708Sstevel } else {
6611708Sstevel char c;
6621708Sstevel if (strcmp(p->notes, XMITS_COMPATIBLE) == 0) {
6631708Sstevel log_printf("/%-2s%02d/%s ",
664*5889Szk194757 SC_BOARD_TYPE(p->board),
665*5889Szk194757 PORTID_TO_EXPANDER(p->board),
666*5889Szk194757 p->slot_str, 0);
6671708Sstevel } else {
6681708Sstevel if (p->pci_bus == 'A')
6691708Sstevel c = '3';
6701708Sstevel else if (p->pci_bus == 'B') {
6711708Sstevel c = '5';
6721708Sstevel } else
6731708Sstevel c = '-';
6741708Sstevel log_printf("/%-2s%02d/C%cV%1d ",
675*5889Szk194757 SC_BOARD_TYPE(p->board),
676*5889Szk194757 PORTID_TO_EXPANDER(p->board), c,
677*5889Szk194757 PORTID_TO_INSTANCE(p->schizo_portid),
678*5889Szk194757 0);
6791708Sstevel }
6801708Sstevel }
6811708Sstevel log_printf("%-4.4s ", gettext(p->bus_type), 0);
6821708Sstevel log_printf("%3d ", p->schizo_portid, 0);
6831708Sstevel log_printf(" %c ", p->pci_bus, 0);
6841708Sstevel log_printf(" %3d ", p->freq, 0);
6851708Sstevel }
6861708Sstevel
6871708Sstevel #define BUS_SPEED_PRINT(speed) log_printf(" %d ", speed, 0)
6881708Sstevel
6891708Sstevel static void
display_io_max_bus_speed(struct io_card * p)6901708Sstevel display_io_max_bus_speed(struct io_card *p)
6911708Sstevel {
6921708Sstevel int speed = board_bus_max_freq;
6931708Sstevel
6941708Sstevel switch (p->pci_bus) {
6951708Sstevel case 'A':
6961708Sstevel BUS_SPEED_PRINT(speed);
6971708Sstevel break;
6981708Sstevel case 'B':
6991708Sstevel if (strcmp(p->notes, XMITS_COMPATIBLE) == 0) {
7001708Sstevel if (PORTID_TO_INSTANCE(p->schizo_portid) == 0)
7011708Sstevel BUS_SPEED_PRINT(33);
7021708Sstevel else
7031708Sstevel BUS_SPEED_PRINT(speed);
7041708Sstevel } else
7051708Sstevel BUS_SPEED_PRINT(33);
7061708Sstevel break;
7071708Sstevel default:
7081708Sstevel log_printf(" - ", 0);
7091708Sstevel break;
7101708Sstevel }
7111708Sstevel
7121708Sstevel log_printf("%-1d,%-1d ", p->dev_no, p->func_no, 0);
7131708Sstevel log_printf("%-5.5s ", gettext(p->status), 0);
7141708Sstevel log_printf("%-32.32s%c ", p->name,
715*5889Szk194757 ((strlen(p->name) > 32) ? '+' : ' '), 0);
7161708Sstevel log_printf("%-22.22s%c", p->model,
717*5889Szk194757 ((strlen(p->model) > 22) ? '+' : ' '), 0);
7181708Sstevel #ifdef DEBUG
7191708Sstevel log_printf(" %s", p->notes, 0);
7201708Sstevel #endif /* DEBUG */
7211708Sstevel }
7221708Sstevel
7231708Sstevel void
display_cpu_devices(Sys_tree * tree)7241708Sstevel display_cpu_devices(Sys_tree *tree)
7251708Sstevel {
7261708Sstevel Board_node *bnode;
7271708Sstevel char *hdrfmt = "%-8.8s %-7.7s %-4.4s %-4.4s %-7.7s %-4.4s\n";
7281708Sstevel
7291708Sstevel (void) textdomain(TEXT_DOMAIN);
7301708Sstevel
7311708Sstevel /*
7321708Sstevel * Display the table header for CPUs . Then display the CPU
7331708Sstevel * frequency, cache size, and processor revision of all cpus.
7341708Sstevel */
7351708Sstevel log_printf("\n", 0);
7361708Sstevel log_printf("=========================", 0);
7371708Sstevel log_printf(gettext(" CPUs "), 0);
7381708Sstevel log_printf("=========================", 0);
7391708Sstevel log_printf("\n\n", 0);
7401708Sstevel
7411708Sstevel log_printf(hdrfmt,
7421708Sstevel "",
7431708Sstevel gettext("CPU "),
7441708Sstevel gettext("Run"),
7451708Sstevel gettext(" E$"),
7461708Sstevel gettext(" CPU"),
7471708Sstevel gettext("CPU"), 0);
7481708Sstevel
7491708Sstevel log_printf(hdrfmt,
7501708Sstevel gettext("Slot ID"),
7511708Sstevel gettext("ID "),
7521708Sstevel gettext("MHz"),
7531708Sstevel gettext(" MB"),
7541708Sstevel gettext("Impl."),
7551708Sstevel gettext("Mask"), 0);
7561708Sstevel
7571708Sstevel log_printf(hdrfmt,
7581708Sstevel "--------", "-------", "----", "----", "-------", "----", 0);
7591708Sstevel
7601708Sstevel /* Now display all of the cpus on each board */
7611708Sstevel bnode = tree->bd_list;
7621708Sstevel while (bnode != NULL) {
7631708Sstevel display_cpus(bnode);
7641708Sstevel bnode = bnode->next;
7651708Sstevel }
7661708Sstevel
7671708Sstevel log_printf("\n", 0);
7681708Sstevel }
7691708Sstevel
7701708Sstevel /*
7711708Sstevel * Display the CPUs present on this board.
7721708Sstevel */
7731708Sstevel void
display_cpus(Board_node * board)7741708Sstevel display_cpus(Board_node *board)
7751708Sstevel {
7761708Sstevel Prom_node *cpu;
777*5889Szk194757 uint_t freq; /* CPU clock frequency */
7781708Sstevel int ecache_size; /* External cache size */
7791708Sstevel int *impl;
7801708Sstevel int *mask;
7811708Sstevel int decoded_mask;
7821708Sstevel int *cpuid;
7831708Sstevel int *coreid;
7841708Sstevel int cpuid_prev = -1;
7851708Sstevel int ecache_size_prev = 0;
7861708Sstevel
7871708Sstevel (void) textdomain(TEXT_DOMAIN);
7881708Sstevel /*
7891708Sstevel * display the CPUs' operating frequency, cache size, impl. field
7901708Sstevel * and mask revision.
7911708Sstevel */
7921708Sstevel for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
7931708Sstevel cpu = dev_next_type(cpu, "cpu")) {
7941708Sstevel
7951708Sstevel freq = HZ_TO_MHZ(get_cpu_freq(cpu));
7961708Sstevel ecache_size = get_ecache_size(cpu);
7971708Sstevel impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
7981708Sstevel mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
7991708Sstevel cpuid = (int *)get_prop_val(find_prop(cpu, "cpuid"));
8001708Sstevel if (cpuid == NULL)
8011708Sstevel cpuid = &board->board_num;
8021708Sstevel
8031708Sstevel /* Do not display a failed CPU node */
8041708Sstevel if ((freq == 0) || (impl == 0) || (node_failed(cpu)))
8051708Sstevel continue;
8061708Sstevel
8071708Sstevel if (CPU_IMPL_IS_CMP(*impl)) {
8081708Sstevel coreid = (int *)get_prop_val(find_prop(cpu,
809*5889Szk194757 "reg"));
8101708Sstevel if (coreid == NULL) {
8111708Sstevel continue;
8121708Sstevel }
8131708Sstevel
8141708Sstevel /*
8151708Sstevel * The assumption is made that 2 cores will always be
8161708Sstevel * listed together in the device tree. If either core
8171708Sstevel * is "bad" then the FRU will not be listed.
8181708Sstevel */
8191708Sstevel if (cpuid_prev == -1) {
8201708Sstevel cpuid_prev = *cpuid;
8211708Sstevel ecache_size_prev = ecache_size;
8221708Sstevel continue;
8231708Sstevel } else {
8241708Sstevel /*
8251708Sstevel * Jaguar has a split E$, so the size for both
8261708Sstevel * cores must be added together to get the total
8271708Sstevel * size for the entire chip.
8281708Sstevel *
8291708Sstevel * Panther E$ (L3) is logically shared, so the
8301708Sstevel * total size is equal to the core size.
8311708Sstevel */
8321708Sstevel if (IS_JAGUAR(*impl)) {
8331708Sstevel ecache_size += ecache_size_prev;
8341708Sstevel }
8351708Sstevel
8361708Sstevel ecache_size_prev = 0;
8371708Sstevel }
8381708Sstevel }
8391708Sstevel
8401708Sstevel /*
8411708Sstevel * Print out cpu data.
8421708Sstevel *
8431708Sstevel * Slot ID
8441708Sstevel */
8451708Sstevel log_printf("/%-2s%02d/P%1d ",
8461708Sstevel SC_BOARD_TYPE(*cpuid),
8471708Sstevel PORTID_TO_EXPANDER(*cpuid),
8481708Sstevel PORTID_TO_INSTANCE(*cpuid), 0);
8491708Sstevel
8501708Sstevel /* CPU ID */
8511708Sstevel if (CPU_IMPL_IS_CMP(*impl)) {
8521708Sstevel log_printf("%3d,%3d ", cpuid_prev,
8531708Sstevel *cpuid, 0);
8541708Sstevel cpuid_prev = -1;
8551708Sstevel } else
8561708Sstevel log_printf("%3d ", *cpuid, 0);
8571708Sstevel
8581708Sstevel /* Running frequency */
859*5889Szk194757 log_printf("%4u ", freq, 0);
8601708Sstevel
8611708Sstevel /* Ecache size */
8621708Sstevel if (ecache_size == 0)
8631708Sstevel log_printf("%-4.4s ", gettext("N/A"), 0);
8641708Sstevel else
8651708Sstevel log_printf("%4.1f ",
866*5889Szk194757 (float)ecache_size / (float)(1<<20),
867*5889Szk194757 0);
8681708Sstevel
8691708Sstevel /* Implementation */
8701708Sstevel switch (*impl) {
8711708Sstevel case CHEETAH_IMPL:
8721708Sstevel log_printf("%-7.7s ",
873*5889Szk194757 gettext("US-III"), 0);
8741708Sstevel break;
8751708Sstevel case CHEETAH_PLUS_IMPL:
8761708Sstevel log_printf("%-7.7s ",
877*5889Szk194757 gettext("US-III+"), 0);
8781708Sstevel break;
8791708Sstevel case JAGUAR_IMPL:
8801708Sstevel log_printf("%-7.7s ",
881*5889Szk194757 gettext("US-IV"), 0);
8821708Sstevel break;
8831708Sstevel case PANTHER_IMPL:
8841708Sstevel log_printf("%-7.7s ",
885*5889Szk194757 gettext("US-IV+"), 0);
8861708Sstevel break;
8871708Sstevel default:
8881708Sstevel log_printf("%-7x ", *impl, 0);
8891708Sstevel break;
8901708Sstevel }
8911708Sstevel
8921708Sstevel /* CPU Mask */
8931708Sstevel if (mask == NULL) {
8941708Sstevel log_printf("%-4.4s", gettext("N/A"), 0);
8951708Sstevel } else {
8961708Sstevel if (IS_CHEETAH(*impl))
8971708Sstevel decoded_mask = REMAP_CHEETAH_MASK(*mask);
8981708Sstevel else
8991708Sstevel decoded_mask = *mask;
9001708Sstevel
9011708Sstevel log_printf("%d.%d",
902*5889Szk194757 (decoded_mask >> 4) & 0xf,
903*5889Szk194757 decoded_mask & 0xf, 0);
9041708Sstevel }
9051708Sstevel
9061708Sstevel log_printf("\n", 0);
9071708Sstevel }
9081708Sstevel }
9091708Sstevel
9101708Sstevel
9111708Sstevel /*ARGSUSED1*/
9121708Sstevel void
display_memoryconf(Sys_tree * tree,struct grp_info * grps)9131708Sstevel display_memoryconf(Sys_tree *tree, struct grp_info *grps)
9141708Sstevel {
9151708Sstevel Board_node *bnode = tree->bd_list;
9161708Sstevel char *hdrfmt = "\n%-11.11s %-4.4s %-7.7s %-7.7s %-8.8s %-6.6s"
917*5889Szk194757 " %-10.10s %-10.10s";
9181708Sstevel
9191708Sstevel (void) textdomain(TEXT_DOMAIN);
9201708Sstevel
9211708Sstevel log_printf("=========================", 0);
9221708Sstevel log_printf(gettext(" Memory Configuration "), 0);
9231708Sstevel log_printf("=========================", 0);
9241708Sstevel log_printf("\n", 0);
9251708Sstevel
9261708Sstevel log_printf(hdrfmt,
9271708Sstevel "", "",
9281708Sstevel gettext("Logical"),
9291708Sstevel gettext("Logical"),
9301708Sstevel gettext("Logical"),
9311708Sstevel "", "", "", 0);
9321708Sstevel
9331708Sstevel log_printf(hdrfmt,
9341708Sstevel "",
9351708Sstevel gettext("Port"),
9361708Sstevel gettext("Bank"),
9371708Sstevel gettext("Bank"),
9381708Sstevel gettext("Bank"),
9391708Sstevel gettext(" DIMM"),
9401708Sstevel gettext("Interleave"),
9411708Sstevel gettext("Interleave"), 0);
9421708Sstevel
9431708Sstevel log_printf(hdrfmt,
9441708Sstevel gettext("Slot ID"),
9451708Sstevel gettext(" ID"),
9461708Sstevel gettext("Number"),
9471708Sstevel gettext("Size"),
9481708Sstevel gettext("Status"),
9491708Sstevel gettext(" Size"),
9501708Sstevel gettext("Factor"),
9511708Sstevel gettext("Segment"), 0);
9521708Sstevel
9531708Sstevel log_printf(hdrfmt,
9541708Sstevel "-----------", "----", "-------", "-------", "--------",
9551708Sstevel "------", "----------", "----------", 0);
9561708Sstevel
9571708Sstevel while (bnode != NULL) {
9581708Sstevel if (get_us3_mem_regs(bnode)) {
9591708Sstevel log_printf(
960*5889Szk194757 gettext(
961*5889Szk194757 "\nFailed to get memory information.\n"),
962*5889Szk194757 0);
9631708Sstevel return;
9641708Sstevel }
9651708Sstevel bnode = bnode->next;
9661708Sstevel }
9671708Sstevel
9681708Sstevel /* Display what we have found */
9691708Sstevel display_us3_banks();
9701708Sstevel }
9711708Sstevel
9721708Sstevel
9731708Sstevel /*
9741708Sstevel * This function provides Starcat's formatting of the memory config
9751708Sstevel * information that get_us3_mem_regs() and display_us3_banks() code has
9761708Sstevel * gathered. It overrides the generic print_us3_memory_line() code
9771708Sstevel * which prints an error message.
9781708Sstevel */
9791708Sstevel 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)9801708Sstevel print_us3_memory_line(int portid, int bank_id, uint64_t bank_size,
9811708Sstevel char *bank_status, uint64_t dimm_size, uint32_t intlv, int seg_id)
9821708Sstevel {
9831708Sstevel (void) textdomain(TEXT_DOMAIN);
9841708Sstevel
9851708Sstevel /* Slot ID */
9861708Sstevel log_printf("\n/%-2s%02d/P%1d/B%1d ",
9871708Sstevel SC_BOARD_TYPE(portid), PORTID_TO_EXPANDER(portid),
9881708Sstevel PORTID_TO_INSTANCE(portid), (bank_id & 0x1), 0);
9891708Sstevel
9901708Sstevel /* Port ID */
9911708Sstevel log_printf("%3d ", portid, 0);
9921708Sstevel
9931708Sstevel /* Logical Bank Number */
9941708Sstevel log_printf(" %1d ", (bank_id & 0x3), 0);
9951708Sstevel
9961708Sstevel /* Logical Bank Size */
9971708Sstevel log_printf("%4lldMB ", bank_size, 0);
9981708Sstevel
9991708Sstevel /* Logical Bank Status */
10001708Sstevel log_printf("%-8.8s ", gettext(bank_status), 0);
10011708Sstevel
10021708Sstevel /* DIMM Size */
10031708Sstevel log_printf("%4lldMB ", dimm_size, 0);
10041708Sstevel
10051708Sstevel /* Interleave Factor */
10061708Sstevel log_printf(" %2d-%-3.3s ", intlv, gettext("way"), 0);
10071708Sstevel
10081708Sstevel /* Interleave Segment */
10091708Sstevel log_printf(" %3d", seg_id, 0);
10101708Sstevel }
10111708Sstevel
10121708Sstevel /*ARGSUSED2*/
10131708Sstevel void
display_diaginfo(int flag,Prom_node * root,Sys_tree * tree,struct system_kstat_data * kstats)10141708Sstevel display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
10151708Sstevel struct system_kstat_data *kstats)
10161708Sstevel {
10171708Sstevel if (flag) {
10181708Sstevel /*
10191708Sstevel * display time of latest powerfail. Not all systems
10201708Sstevel * have this capability. For those that do not, this
10211708Sstevel * is just a no-op.
10221708Sstevel */
10231708Sstevel disp_powerfail(root);
10241708Sstevel
10251708Sstevel (void) textdomain(TEXT_DOMAIN);
10261708Sstevel
10271708Sstevel /* Print the header */
10281708Sstevel log_printf("\n", 0);
10291708Sstevel log_printf("=========================", 0);
10301708Sstevel log_printf(gettext(" Diagnostic Information "), 0);
10311708Sstevel log_printf("=========================", 0);
10321708Sstevel log_printf("\n\n", 0);
10331708Sstevel log_printf(gettext("For diagnostic information,"), 0);
10341708Sstevel log_printf("\n", 0);
10351708Sstevel log_printf(gettext(
1036*5889Szk194757 "see /var/opt/SUNWSMS/adm/[A-R]/messages on the SC."),
1037*5889Szk194757 0);
10381708Sstevel log_printf("\n", 0);
10391708Sstevel
10401708Sstevel /* Print the PROM revisions here */
10411708Sstevel starcat_disp_hw_revisions(root);
10421708Sstevel }
10431708Sstevel }
10441708Sstevel
10451708Sstevel /*
10461708Sstevel * local functions - functions that are only needed inside this library
10471708Sstevel */
10481708Sstevel
10491708Sstevel static void
starcat_disp_hw_revisions(Prom_node * root)10501708Sstevel starcat_disp_hw_revisions(Prom_node *root)
10511708Sstevel {
10521708Sstevel Prom_node *pnode;
10531708Sstevel char *version;
10541708Sstevel
10551708Sstevel (void) textdomain(TEXT_DOMAIN);
10561708Sstevel
10571708Sstevel /* Print the header */
10581708Sstevel log_printf("\n", 0);
10591708Sstevel log_printf("=========================", 0);
10601708Sstevel log_printf(gettext(" Hardware Revisions "), 0);
10611708Sstevel log_printf("=========================", 0);
10621708Sstevel log_printf("\n\n", 0);
10631708Sstevel
10641708Sstevel /* Display Prom revision header */
10651708Sstevel log_printf(gettext("OpenBoot firmware revision:"), 0);
10661708Sstevel log_printf("\n---------------------------\n", 0);
10671708Sstevel
10681708Sstevel /*
10691708Sstevel * Display OBP version info
10701708Sstevel */
10711708Sstevel pnode = dev_find_node(root, "openprom");
10721708Sstevel if (pnode != NULL) {
10731708Sstevel version = (char *)get_prop_val(find_prop(pnode, "version"));
10741708Sstevel log_printf("%s\n\n", version, 0);
10751708Sstevel }
10761708Sstevel }
10771708Sstevel
10781708Sstevel /*
10791708Sstevel * We call do_devinfo() in order to use the libdevinfo device tree
10801708Sstevel * instead of OBP's device tree.
10811708Sstevel */
10821708Sstevel int
do_prominfo(int syserrlog,char * pgname,int log_flag,int prt_flag)10831708Sstevel do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag)
10841708Sstevel {
10851708Sstevel
10861708Sstevel return (do_devinfo(syserrlog, pgname, log_flag, prt_flag));
10871708Sstevel
10881708Sstevel }
10891708Sstevel
10901708Sstevel /*
10911708Sstevel * return the property value for the Prop
10921708Sstevel * passed in. (When using libdevinfo)
10931708Sstevel */
10941708Sstevel void *
get_prop_val(Prop * prop)10951708Sstevel get_prop_val(Prop *prop)
10961708Sstevel {
10971708Sstevel if (prop == NULL)
10981708Sstevel return (NULL);
10991708Sstevel
11001708Sstevel return ((void *)(prop->value.val_ptr));
11011708Sstevel }
11021708Sstevel
11031708Sstevel /*
11041708Sstevel * Search a Prom node and retrieve the property with the correct
11051708Sstevel * name. (When using libdevinfo)
11061708Sstevel */
11071708Sstevel Prop *
find_prop(Prom_node * pnode,char * name)11081708Sstevel find_prop(Prom_node *pnode, char *name)
11091708Sstevel {
11101708Sstevel Prop *prop;
11111708Sstevel
11121708Sstevel if (pnode == NULL)
11131708Sstevel return (NULL);
11141708Sstevel
11151708Sstevel for (prop = pnode->props; prop != NULL; prop = prop->next) {
11161708Sstevel if (prop->name.val_ptr != NULL &&
11171708Sstevel strcmp((char *)(prop->name.val_ptr), name) == 0)
11181708Sstevel break;
11191708Sstevel }
11201708Sstevel
11211708Sstevel return (prop);
11221708Sstevel }
11231708Sstevel
11241708Sstevel /*
11251708Sstevel * This function searches through the properties of the node passed in
11261708Sstevel * and returns a pointer to the value of the name property.
11271708Sstevel * (When using libdevinfo)
11281708Sstevel */
11291708Sstevel char *
get_node_name(Prom_node * pnode)11301708Sstevel get_node_name(Prom_node *pnode)
11311708Sstevel {
11321708Sstevel Prop *prop;
11331708Sstevel
11341708Sstevel if (pnode == NULL) {
11351708Sstevel return (NULL);
11361708Sstevel }
11371708Sstevel
11381708Sstevel prop = pnode->props;
11391708Sstevel while (prop != NULL) {
11401708Sstevel if (strcmp("name", (char *)prop->name.val_ptr) == 0)
11411708Sstevel return (prop->value.val_ptr);
11421708Sstevel prop = prop->next;
11431708Sstevel }
11441708Sstevel return (NULL);
11451708Sstevel }
11461708Sstevel
11471708Sstevel /*
11481708Sstevel * This function searches through the properties of the node passed in
11491708Sstevel * and returns a pointer to the value of the device_type property.
11501708Sstevel * (When using libdevinfo)
11511708Sstevel */
11521708Sstevel char *
get_node_type(Prom_node * pnode)11531708Sstevel get_node_type(Prom_node *pnode)
11541708Sstevel {
11551708Sstevel Prop *prop;
11561708Sstevel
11571708Sstevel if (pnode == NULL) {
11581708Sstevel return (NULL);
11591708Sstevel }
11601708Sstevel
11611708Sstevel prop = pnode->props;
11621708Sstevel while (prop != NULL) {
11631708Sstevel if (strcmp("device_type", (char *)prop->name.val_ptr) == 0)
11641708Sstevel return (prop->value.val_ptr);
11651708Sstevel prop = prop->next;
11661708Sstevel }
11671708Sstevel return (NULL);
11681708Sstevel }
1169