125cf1a30Sjl139090 /*
225cf1a30Sjl139090 * CDDL HEADER START
325cf1a30Sjl139090 *
425cf1a30Sjl139090 * The contents of this file are subject to the terms of the
525cf1a30Sjl139090 * Common Development and Distribution License (the "License").
625cf1a30Sjl139090 * You may not use this file except in compliance with the License.
725cf1a30Sjl139090 *
825cf1a30Sjl139090 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
925cf1a30Sjl139090 * or http://www.opensolaris.org/os/licensing.
1025cf1a30Sjl139090 * See the License for the specific language governing permissions
1125cf1a30Sjl139090 * and limitations under the License.
1225cf1a30Sjl139090 *
1325cf1a30Sjl139090 * When distributing Covered Code, include this CDDL HEADER in each
1425cf1a30Sjl139090 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1525cf1a30Sjl139090 * If applicable, add the following below this CDDL HEADER, with the
1625cf1a30Sjl139090 * fields enclosed by brackets "[]" replaced with your own identifying
1725cf1a30Sjl139090 * information: Portions Copyright [yyyy] [name of copyright owner]
1825cf1a30Sjl139090 *
1925cf1a30Sjl139090 * CDDL HEADER END
2025cf1a30Sjl139090 */
2125cf1a30Sjl139090 /*
225face7b2SJustin Frank * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2325cf1a30Sjl139090 * Use is subject to license terms.
24*2bcbf80cSPeter Tribble * Copyright 2020 Peter Tribble.
2525cf1a30Sjl139090 *
2625cf1a30Sjl139090 * Opl Platform specific functions.
2725cf1a30Sjl139090 *
2825cf1a30Sjl139090 * called when :
2925cf1a30Sjl139090 * machine_type == MTYPE_OPL
3025cf1a30Sjl139090 */
3125cf1a30Sjl139090
3225cf1a30Sjl139090 #include <stdio.h>
3325cf1a30Sjl139090 #include <stdlib.h>
3425cf1a30Sjl139090 #include <unistd.h>
3525cf1a30Sjl139090 #include <ctype.h>
3625cf1a30Sjl139090 #include <string.h>
3725cf1a30Sjl139090 #include <varargs.h>
3825cf1a30Sjl139090 #include <fcntl.h>
3925cf1a30Sjl139090 #include <assert.h>
4025cf1a30Sjl139090 #include <sys/param.h>
4125cf1a30Sjl139090 #include <sys/stat.h>
4225cf1a30Sjl139090 #include <sys/types.h>
4325cf1a30Sjl139090 #include <sys/utsname.h>
4425cf1a30Sjl139090 #include <sys/systeminfo.h>
4525cf1a30Sjl139090 #include <sys/openpromio.h>
4625cf1a30Sjl139090 #include <libintl.h>
4725cf1a30Sjl139090 #include <syslog.h>
4825cf1a30Sjl139090 #include <sys/dkio.h>
4925cf1a30Sjl139090 #include <pdevinfo.h>
5025cf1a30Sjl139090 #include <libprtdiag.h>
5125cf1a30Sjl139090 #include <libdevinfo.h>
5225cf1a30Sjl139090 #include <kstat.h>
5325cf1a30Sjl139090
5425cf1a30Sjl139090 /*
5525cf1a30Sjl139090 * Globals and externs
5625cf1a30Sjl139090 */
5725cf1a30Sjl139090 #define KBYTE 1024
5825cf1a30Sjl139090 #define MBYTE (KBYTE * KBYTE)
5925cf1a30Sjl139090 #define HZ_TO_MHZ(x) ((((uint64_t)(x)) + 500000) / 1000000)
6025cf1a30Sjl139090 #define SCF_SECURE_MODE_KSTAT_NAMED "secure_mode"
6125cf1a30Sjl139090 #define SCF_STAT_MODE_UNLOCK 0
6225cf1a30Sjl139090 #define SCF_STAT_MODE_LOCK 1
6325cf1a30Sjl139090 #define SCF_SYSTEM_KSTAT_NAME "scf"
6425cf1a30Sjl139090 #ifndef TEXT_DOMAIN
6525cf1a30Sjl139090 #define TEXT_DOMAIN "SYS_TEST"
6625cf1a30Sjl139090 #endif /* TEXT_DOMAIN */
6725cf1a30Sjl139090
6825cf1a30Sjl139090 /*
6925cf1a30Sjl139090 * Global functions and variables
7025cf1a30Sjl139090 * these functions will overlay the symbol table of libprtdiag
7125cf1a30Sjl139090 * at runtime (Opl systems only)
7225cf1a30Sjl139090 */
7325cf1a30Sjl139090 struct cs_status {
7425cf1a30Sjl139090 int cs_number;
7525cf1a30Sjl139090 int status;
76e3e793b1Sjimand uint_t avail_hi;
77e3e793b1Sjimand uint_t avail_lo;
78e3e793b1Sjimand uint_t dimm_hi;
79e3e793b1Sjimand uint_t dimm_lo;
8025cf1a30Sjl139090 int dimms;
8125cf1a30Sjl139090 };
8225cf1a30Sjl139090
8325cf1a30Sjl139090 int do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag);
8425cf1a30Sjl139090 void *get_prop_val(Prop *prop);
8525cf1a30Sjl139090 void display_ffb(Board_node *, int);
8625cf1a30Sjl139090 void display_sbus(Board_node *board);
8725cf1a30Sjl139090 void display_cpu_devices(Sys_tree *tree);
8825cf1a30Sjl139090 void display_cpus(Board_node *board);
89*2bcbf80cSPeter Tribble void display_memoryconf(Sys_tree *tree);
9025cf1a30Sjl139090 void display_io_cards(struct io_card *list);
913d808a52Ssubhan void display_io_devices(Sys_tree *tree);
9225cf1a30Sjl139090 void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
9325cf1a30Sjl139090 struct system_kstat_data *kstats);
9425cf1a30Sjl139090 Prop *find_prop(Prom_node *pnode, char *name);
953d808a52Ssubhan int do_piclinfo(int);
961ba18ff1Sjimand int get_proc_mode(void);
9725cf1a30Sjl139090
9825cf1a30Sjl139090 /* Local functions */
9925cf1a30Sjl139090 static void opl_disp_environ(void);
10025cf1a30Sjl139090 static void opl_disp_hw_revisions(Sys_tree *tree, Prom_node *root);
10125cf1a30Sjl139090 static uint64_t print_opl_memory_line(int lsb, struct cs_status *cs_stat,
102d8a0cca9Swh31274 int ngrps, int mirror_mode);
10325cf1a30Sjl139090 static uint64_t get_opl_mem_regs(Board_node *bnode);
10425cf1a30Sjl139090 void add_node(Sys_tree *root, Prom_node *pnode);
10525cf1a30Sjl139090 static int get_prop_size(Prop *prop);
10625cf1a30Sjl139090
1073d808a52Ssubhan static int v_flag = 0;
1083d808a52Ssubhan
1093d808a52Ssubhan /*
11096123858Skd93003 * Linked list of IO card info for display.
11196123858Skd93003 * Using file scope for use in a recursive function.
11296123858Skd93003 */
11396123858Skd93003 static struct io_card *card_list = NULL;
11496123858Skd93003
11596123858Skd93003 /*
11696123858Skd93003 * Check prom node for a class-code. If it exists and it's not a bridge device
11796123858Skd93003 * then add an io_card to card_list. Then recursively call this function for
11896123858Skd93003 * its child and sibling nodes.
11996123858Skd93003 */
12096123858Skd93003 static void
walk_tree_for_pci_devices(Prom_node * node,int board_number)12196123858Skd93003 walk_tree_for_pci_devices(Prom_node *node, int board_number)
12296123858Skd93003 {
12396123858Skd93003 struct io_card card;
12496123858Skd93003 char *str;
12596123858Skd93003 void *val;
12696123858Skd93003 int ccode;
12796123858Skd93003
12896123858Skd93003 if (node == NULL) {
12996123858Skd93003 return;
13096123858Skd93003 }
13196123858Skd93003
13296123858Skd93003 /* Look for a class-code property. Skip, if it's a bridge */
13396123858Skd93003 ccode = -1;
13496123858Skd93003 val = get_prop_val(find_prop(node, "class-code"));
13596123858Skd93003 if (val != NULL) {
13696123858Skd93003 ccode = *(int *)val;
13796123858Skd93003 }
13896123858Skd93003 if ((ccode != -1) && (ccode < 0x60000 || ccode > 0x6ffff)) {
13996123858Skd93003 (void) memset(&card, 0, sizeof (card));
14096123858Skd93003 card.board = board_number;
14196123858Skd93003
14296123858Skd93003 str = (char *)get_prop_val(find_prop(node, "name"));
14396123858Skd93003 (void) strlcpy(card.name, (str == NULL ? "N/A":str),
14496123858Skd93003 sizeof (card.name));
14596123858Skd93003
14696123858Skd93003 str = (char *)get_prop_val(find_prop(node, "model"));
14796123858Skd93003 (void) strlcpy(card.model, (str == NULL ? "N/A":str),
14896123858Skd93003 sizeof (card.model));
14996123858Skd93003
15096123858Skd93003 /* insert card to the list */
15196123858Skd93003 card_list = insert_io_card(card_list, &card);
15296123858Skd93003 }
15396123858Skd93003 /* Call this function for its child/sibling */
15496123858Skd93003 walk_tree_for_pci_devices(node->child, board_number);
15596123858Skd93003 walk_tree_for_pci_devices(node->sibling, board_number);
15696123858Skd93003 }
15796123858Skd93003
15896123858Skd93003 /*
1593d808a52Ssubhan * For display of I/O devices for "prtdiag"
1603d808a52Ssubhan */
1613d808a52Ssubhan void
display_io_devices(Sys_tree * tree)1623d808a52Ssubhan display_io_devices(Sys_tree *tree)
1633d808a52Ssubhan {
1643d808a52Ssubhan Board_node *bnode;
1653d808a52Ssubhan
1663d808a52Ssubhan if (v_flag) {
1673d808a52Ssubhan /*
1683d808a52Ssubhan * OPL's PICL interface for display of PCI I/O devices
1693d808a52Ssubhan * for "prtdiag -v"
1703d808a52Ssubhan */
1713d808a52Ssubhan (void) do_piclinfo(v_flag);
1723d808a52Ssubhan } else {
1733d808a52Ssubhan log_printf("\n", 0);
1743d808a52Ssubhan log_printf("=========================", 0);
1753d808a52Ssubhan log_printf(dgettext(TEXT_DOMAIN, " IO Cards "), 0);
1763d808a52Ssubhan log_printf("=========================", 0);
1773d808a52Ssubhan log_printf("\n", 0);
1783d808a52Ssubhan log_printf("\n", 0);
1793d808a52Ssubhan bnode = tree->bd_list;
1803d808a52Ssubhan while (bnode != NULL) {
18196123858Skd93003 walk_tree_for_pci_devices(bnode->nodes,
18296123858Skd93003 bnode->board_num);
1833d808a52Ssubhan bnode = bnode->next;
1843d808a52Ssubhan }
18525cf1a30Sjl139090 display_io_cards(card_list);
18625cf1a30Sjl139090 free_io_cards(card_list);
18725cf1a30Sjl139090 }
18896123858Skd93003 }
18925cf1a30Sjl139090
19025cf1a30Sjl139090 /*
19125cf1a30Sjl139090 * There are no FFB's on OPL.
19225cf1a30Sjl139090 */
19325cf1a30Sjl139090 /*ARGSUSED*/
19425cf1a30Sjl139090 void
display_ffb(Board_node * board,int table)19525cf1a30Sjl139090 display_ffb(Board_node *board, int table)
19625cf1a30Sjl139090 {
19725cf1a30Sjl139090 }
19825cf1a30Sjl139090
19925cf1a30Sjl139090 /*
20025cf1a30Sjl139090 * There are no Sbus's on OPL.
20125cf1a30Sjl139090 */
20225cf1a30Sjl139090 /*ARGSUSED*/
20325cf1a30Sjl139090 void
display_sbus(Board_node * board)20425cf1a30Sjl139090 display_sbus(Board_node *board)
20525cf1a30Sjl139090 {
20625cf1a30Sjl139090 }
20725cf1a30Sjl139090
20825cf1a30Sjl139090 /*
20925cf1a30Sjl139090 * Details of I/O information. Print out all the io cards.
21025cf1a30Sjl139090 */
21125cf1a30Sjl139090 void
display_io_cards(struct io_card * list)21225cf1a30Sjl139090 display_io_cards(struct io_card *list)
21325cf1a30Sjl139090 {
21425cf1a30Sjl139090 char *hdrfmt = "%-6.6s %-14.14s %-12.12s\n";
21525cf1a30Sjl139090
21625cf1a30Sjl139090 struct io_card *p;
21725cf1a30Sjl139090
21825cf1a30Sjl139090 if (list == NULL)
21925cf1a30Sjl139090 return;
22025cf1a30Sjl139090
22125cf1a30Sjl139090 (void) textdomain(TEXT_DOMAIN);
22225cf1a30Sjl139090
22325cf1a30Sjl139090 log_printf(hdrfmt, gettext("LSB"), gettext("Name"), gettext("Model"),
22425cf1a30Sjl139090 0);
22525cf1a30Sjl139090
22625cf1a30Sjl139090 log_printf(hdrfmt, "---", "-----------------", "------------", 0);
22725cf1a30Sjl139090
22825cf1a30Sjl139090 for (p = list; p != NULL; p = p->next) {
22925cf1a30Sjl139090
23025cf1a30Sjl139090 /* Board number */
23125cf1a30Sjl139090 log_printf(" %02d ", p->board, 0);
23225cf1a30Sjl139090
23325cf1a30Sjl139090 /* Card name */
23425cf1a30Sjl139090 log_printf("%-15.15s", p->name, 0);
23525cf1a30Sjl139090
23625cf1a30Sjl139090 /* Card model */
23725cf1a30Sjl139090 log_printf("%-12.12s", p->model, 0);
23825cf1a30Sjl139090
23925cf1a30Sjl139090 log_printf("\n", 0);
24025cf1a30Sjl139090 }
24125cf1a30Sjl139090 log_printf("\n", 0);
24225cf1a30Sjl139090 }
24325cf1a30Sjl139090
24425cf1a30Sjl139090 /*
24525cf1a30Sjl139090 * Details of CPU information.
24625cf1a30Sjl139090 */
24725cf1a30Sjl139090 void
display_cpu_devices(Sys_tree * tree)24825cf1a30Sjl139090 display_cpu_devices(Sys_tree *tree)
24925cf1a30Sjl139090 {
25025cf1a30Sjl139090 Board_node *bnode;
25125cf1a30Sjl139090 char *hdrfmt =
252e98fafb9Sjl139090 "%-4.4s %-4.4s %-40.40s %-5.5s %-5.5s %-5.5s %-4.4s\n";
25325cf1a30Sjl139090
25425cf1a30Sjl139090 (void) textdomain(TEXT_DOMAIN);
25525cf1a30Sjl139090
25625cf1a30Sjl139090 /*
25725cf1a30Sjl139090 * Display the table header for CPUs . Then display the CPU
25825cf1a30Sjl139090 * frequency, cache size, and processor revision of all cpus.
25925cf1a30Sjl139090 */
26025cf1a30Sjl139090 log_printf("\n", 0);
26125cf1a30Sjl139090 log_printf("====================================", 0);
26225cf1a30Sjl139090 log_printf(gettext(" CPUs "), 0);
26325cf1a30Sjl139090 log_printf("====================================", 0);
26425cf1a30Sjl139090 log_printf("\n\n", 0);
26525cf1a30Sjl139090
26625cf1a30Sjl139090 log_printf(hdrfmt,
26725cf1a30Sjl139090 "",
26825cf1a30Sjl139090 gettext("CPU"),
26925cf1a30Sjl139090 gettext(" CPU "),
27025cf1a30Sjl139090 gettext("Run"),
27125cf1a30Sjl139090 gettext("L2$"),
27225cf1a30Sjl139090 gettext("CPU"),
27325cf1a30Sjl139090 gettext("CPU"), 0);
27425cf1a30Sjl139090
27525cf1a30Sjl139090 log_printf(hdrfmt,
27625cf1a30Sjl139090 gettext("LSB"),
27725cf1a30Sjl139090 gettext("Chip"),
27825cf1a30Sjl139090 gettext(" ID "),
27925cf1a30Sjl139090 gettext("MHz"),
28025cf1a30Sjl139090 gettext(" MB"),
28125cf1a30Sjl139090 gettext("Impl."),
28225cf1a30Sjl139090 gettext("Mask"), 0);
28325cf1a30Sjl139090
28425cf1a30Sjl139090 log_printf(hdrfmt,
285e98fafb9Sjl139090 "---", "----", "----------------------------------------", "----",
28625cf1a30Sjl139090 "---", "-----", "----", 0);
28725cf1a30Sjl139090
28825cf1a30Sjl139090 /* Now display all of the cpus on each board */
28925cf1a30Sjl139090 for (bnode = tree->bd_list; bnode != NULL; bnode = bnode->next) {
29025cf1a30Sjl139090 display_cpus(bnode);
29125cf1a30Sjl139090 }
29225cf1a30Sjl139090
29325cf1a30Sjl139090 log_printf("\n", 0);
29425cf1a30Sjl139090 }
29525cf1a30Sjl139090
29625cf1a30Sjl139090 /*
29725cf1a30Sjl139090 * Display the CPUs present on this board.
29825cf1a30Sjl139090 */
29925cf1a30Sjl139090 void
display_cpus(Board_node * board)30025cf1a30Sjl139090 display_cpus(Board_node *board)
30125cf1a30Sjl139090 {
30225cf1a30Sjl139090 int *impl, *mask, *cpuid, *portid, *l2cache_size;
30325cf1a30Sjl139090 uint_t freq; /* CPU clock frequency */
30425cf1a30Sjl139090 Prom_node *pnode, *cpu;
30525cf1a30Sjl139090 char *name;
30625cf1a30Sjl139090
30725cf1a30Sjl139090 (void) textdomain(TEXT_DOMAIN);
30825cf1a30Sjl139090
30925cf1a30Sjl139090 /*
31025cf1a30Sjl139090 * Get the Cpus' properties for display
31125cf1a30Sjl139090 */
31225cf1a30Sjl139090 for (pnode = board->nodes; pnode != NULL; pnode = pnode->sibling) {
31325cf1a30Sjl139090 char cpu_str[MAXSTRLEN], fcpu_str[MAXSTRLEN] = {0};
31425cf1a30Sjl139090
31525cf1a30Sjl139090 name = get_node_name(pnode);
31625cf1a30Sjl139090 if ((name == NULL) || (strncmp(name, "cmp", 3) != 0)) {
31725cf1a30Sjl139090 continue;
31825cf1a30Sjl139090 }
31925cf1a30Sjl139090
32025cf1a30Sjl139090 portid = (int *)get_prop_val(find_prop(pnode, "portid"));
32125cf1a30Sjl139090 freq = (HZ_TO_MHZ(get_cpu_freq(pnode->child)));
322e98fafb9Sjl139090 l2cache_size = (int *)get_prop_val(find_prop(pnode->child,
323e98fafb9Sjl139090 "l2-cache-size"));
324e98fafb9Sjl139090 impl = (int *)get_prop_val(find_prop(pnode->child,
325e98fafb9Sjl139090 "implementation#"));
32625cf1a30Sjl139090 mask = (int *)get_prop_val(find_prop(pnode->child, "mask#"));
32725cf1a30Sjl139090
32825cf1a30Sjl139090 /* Lsb id */
32925cf1a30Sjl139090 log_printf(" %02d ", board->board_num, 0);
33025cf1a30Sjl139090
33125cf1a30Sjl139090 if (portid != NULL)
33225cf1a30Sjl139090 log_printf("%3d ", (((*portid)>>3)&0x3), 0);
33325cf1a30Sjl139090
33425cf1a30Sjl139090 /*
335e98fafb9Sjl139090 * OPL
33625cf1a30Sjl139090 * Specific parsing of the CMP/CORE/CPU chain.
33725cf1a30Sjl139090 * The internal cpu tree built by walk_di_tree()
33825cf1a30Sjl139090 * in common code can be illustrated by the diagram
33925cf1a30Sjl139090 * below:
34025cf1a30Sjl139090 *
341e98fafb9Sjl139090 * Olympus:
342e98fafb9Sjl139090 *
34325cf1a30Sjl139090 * cmp->cpu->cpu->cpu->cpu->(next board nodes)
34425cf1a30Sjl139090 * / \
34525cf1a30Sjl139090 * core core
346e98fafb9Sjl139090 *
347e98fafb9Sjl139090 * Jupiter:
348e98fafb9Sjl139090 *
349e98fafb9Sjl139090 * cmp->cpu->cpu->cpu->cpu->cpu->cpu->cpu->cpu->(board nodes)
350e98fafb9Sjl139090 * |
351e98fafb9Sjl139090 * _____________
352e98fafb9Sjl139090 * / \ \ \
353e98fafb9Sjl139090 * core core core core
354e98fafb9Sjl139090 *
355e98fafb9Sjl139090 *
35625cf1a30Sjl139090 * where "/" or "\" are children
35725cf1a30Sjl139090 * and "->" are siblings
358e98fafb9Sjl139090 *
35925cf1a30Sjl139090 */
36025cf1a30Sjl139090 for (cpu = pnode->sibling; cpu != NULL; ) {
36125cf1a30Sjl139090 Prom_node *cpu_next = NULL;
36225cf1a30Sjl139090
36325cf1a30Sjl139090 name = get_node_name(cpu);
36425cf1a30Sjl139090 if ((name == NULL) || (strncmp(name, "cpu", 3) != 0)) {
36525cf1a30Sjl139090 break;
36625cf1a30Sjl139090 }
36725cf1a30Sjl139090
36825cf1a30Sjl139090 /* Id assigned to Virtual processor core */
36925cf1a30Sjl139090 cpuid = (int *)get_prop_val(find_prop(cpu, "cpuid"));
37025cf1a30Sjl139090 cpu_next = cpu->sibling;
37125cf1a30Sjl139090
37225cf1a30Sjl139090 if (cpu_next != NULL) {
37325cf1a30Sjl139090 name = get_node_name(cpu_next);
37425cf1a30Sjl139090
37525cf1a30Sjl139090 if ((name == NULL) ||
37625cf1a30Sjl139090 (strncmp(name, "cpu", 3) != 0)) {
37725cf1a30Sjl139090 cpu_next = NULL;
37825cf1a30Sjl139090 }
37925cf1a30Sjl139090 }
38025cf1a30Sjl139090
38125cf1a30Sjl139090 if (cpuid != NULL) {
38225cf1a30Sjl139090 /* Used for printing in comma format */
38325cf1a30Sjl139090 (void) sprintf(cpu_str, "%4d", *cpuid);
38425cf1a30Sjl139090 (void) strlcat(fcpu_str, cpu_str, MAXSTRLEN);
38525cf1a30Sjl139090
386e98fafb9Sjl139090 if (cpu_next != NULL) {
387e98fafb9Sjl139090 (void) strlcat(fcpu_str, ",",
388e98fafb9Sjl139090 MAXSTRLEN);
389e98fafb9Sjl139090 }
39025cf1a30Sjl139090 } else {
39125cf1a30Sjl139090 (void) sprintf(cpu_str, "%4s", "N/A");
39225cf1a30Sjl139090 (void) strlcat(fcpu_str, cpu_str, MAXSTRLEN);
39325cf1a30Sjl139090
394e98fafb9Sjl139090 if (cpu_next != NULL) {
395e98fafb9Sjl139090 (void) strlcat(fcpu_str, ",",
396e98fafb9Sjl139090 MAXSTRLEN);
397e98fafb9Sjl139090 }
39825cf1a30Sjl139090 }
39925cf1a30Sjl139090 cpu = cpu_next;
40025cf1a30Sjl139090 }
40125cf1a30Sjl139090
402e98fafb9Sjl139090 log_printf("%-40.40s", fcpu_str, 0);
40325cf1a30Sjl139090
40425cf1a30Sjl139090 /* Running frequency */
40525cf1a30Sjl139090 if (freq != 0)
40625cf1a30Sjl139090 log_printf(" %4ld ", freq, 0);
40725cf1a30Sjl139090 else
40825cf1a30Sjl139090 log_printf(" %4s ", "N/A", 0);
40925cf1a30Sjl139090
41025cf1a30Sjl139090 /* L2 cache size */
41125cf1a30Sjl139090 if (l2cache_size == NULL)
41225cf1a30Sjl139090 log_printf(" %3s ", "N/A", 0);
41325cf1a30Sjl139090 else {
41425cf1a30Sjl139090 log_printf("%4.1f ",
41525cf1a30Sjl139090 (float)(*l2cache_size) / (float)(1<<20), 0);
41625cf1a30Sjl139090 }
41725cf1a30Sjl139090
41825cf1a30Sjl139090
41925cf1a30Sjl139090 /* Implementation number of processor */
42025cf1a30Sjl139090 if (impl != NULL)
42125cf1a30Sjl139090 log_printf(" %4d ", *impl, 0);
42225cf1a30Sjl139090 else
42325cf1a30Sjl139090 log_printf(" %4s ", "N/A", 0);
42425cf1a30Sjl139090
42525cf1a30Sjl139090 /* Mask Set version */
42625cf1a30Sjl139090 /* Bits 31:24 of VER register is mask. */
42725cf1a30Sjl139090 /* Mask value : Non MTP mode - 00-7f, MTP mode - 80-ff */
42825cf1a30Sjl139090 if (mask == NULL)
429e98fafb9Sjl139090 log_printf("%3s", "N/A", 0);
43025cf1a30Sjl139090 else
431e98fafb9Sjl139090 log_printf("%-3d", (*mask)&0xff, 0);
43225cf1a30Sjl139090
43325cf1a30Sjl139090 log_printf("\n", 0);
43425cf1a30Sjl139090
43525cf1a30Sjl139090 }
43625cf1a30Sjl139090 }
43725cf1a30Sjl139090
43825cf1a30Sjl139090 /*
43925cf1a30Sjl139090 * Gather memory information: Details of memory information.
44025cf1a30Sjl139090 */
44125cf1a30Sjl139090 static uint64_t
get_opl_mem_regs(Board_node * bnode)44225cf1a30Sjl139090 get_opl_mem_regs(Board_node *bnode)
44325cf1a30Sjl139090 {
44425cf1a30Sjl139090 Prom_node *pnode;
44525cf1a30Sjl139090 struct cs_status *cs_stat;
44625cf1a30Sjl139090 uint64_t total_mem = 0;
44725cf1a30Sjl139090 int cs_size, ngrps;
44825cf1a30Sjl139090
44925cf1a30Sjl139090 pnode = dev_find_node(bnode->nodes, "pseudo-mc");
45025cf1a30Sjl139090 while (pnode != NULL) {
45125cf1a30Sjl139090
45225cf1a30Sjl139090 cs_size = get_prop_size(find_prop(pnode, "cs-status"));
45325cf1a30Sjl139090
45425cf1a30Sjl139090 if (cs_size > 0) {
455d8a0cca9Swh31274 int *mirror_mode = NULL;
456d8a0cca9Swh31274 int mode = 0;
45725cf1a30Sjl139090
45825cf1a30Sjl139090 /* OBP returns lists of 7 ints */
45925cf1a30Sjl139090 cs_stat = (struct cs_status *)get_prop_val
46025cf1a30Sjl139090 (find_prop(pnode, "cs-status"));
46125cf1a30Sjl139090
462d8a0cca9Swh31274 mirror_mode = (int *)(get_prop_val
463d8a0cca9Swh31274 (find_prop(pnode, "mirror-mode")));
464d8a0cca9Swh31274
465d8a0cca9Swh31274 if (mirror_mode != NULL)
466d8a0cca9Swh31274 mode = (*mirror_mode);
467d8a0cca9Swh31274
4686b18442eSjimand /*
4696b18442eSjimand * The units of cs_size will be either number of bytes
4706b18442eSjimand * or number of int array elements as this is derived
4716b18442eSjimand * from the libprtdiag Prop node size field which has
4726b18442eSjimand * inconsistent units. Until this is addressed in
4736b18442eSjimand * libprtdiag, we need a heuristic to determine the
4746b18442eSjimand * number of CS groups. Given that the maximum number
4756b18442eSjimand * of CS groups is 2, the maximum number of cs-status
4766b18442eSjimand * array elements will be 2*7=14. Since this is smaller
4776b18442eSjimand * than the byte size of a single struct status, we use
4786b18442eSjimand * this to decide if we are dealing with bytes or array
4796b18442eSjimand * elements in determining the number of CS groups.
4806b18442eSjimand */
4816b18442eSjimand if (cs_size < sizeof (struct cs_status)) {
4826b18442eSjimand /* cs_size is number of total int [] elements */
4836b18442eSjimand ngrps = cs_size / 7;
4846b18442eSjimand } else {
4856b18442eSjimand /* cs_size is total byte count */
48625cf1a30Sjl139090 ngrps = cs_size/sizeof (struct cs_status);
4876b18442eSjimand }
48825cf1a30Sjl139090
48925cf1a30Sjl139090 if (cs_stat != NULL) {
490d8a0cca9Swh31274 total_mem +=
491d8a0cca9Swh31274 print_opl_memory_line(bnode->board_num,
492d8a0cca9Swh31274 cs_stat, ngrps, mode);
49325cf1a30Sjl139090 }
49425cf1a30Sjl139090 }
49525cf1a30Sjl139090
49625cf1a30Sjl139090 pnode = dev_next_node(pnode, "pseudo-mc");
49725cf1a30Sjl139090 }
49825cf1a30Sjl139090 return (total_mem);
49925cf1a30Sjl139090 }
50025cf1a30Sjl139090
50125cf1a30Sjl139090 /*
50225cf1a30Sjl139090 * Display memory information.
50325cf1a30Sjl139090 */
50425cf1a30Sjl139090 void
display_memoryconf(Sys_tree * tree)505*2bcbf80cSPeter Tribble display_memoryconf(Sys_tree *tree)
50625cf1a30Sjl139090 {
50725cf1a30Sjl139090 Board_node *bnode = tree->bd_list;
50825cf1a30Sjl139090 uint64_t total_mem = 0, total_sys_mem = 0;
509d8a0cca9Swh31274 char *hdrfmt = "\n%-5.5s %-6.6s %-18.18s %-10.10s"
510d8a0cca9Swh31274 " %-6.6s %-5.5s %-7.7s %-10.10s";
51125cf1a30Sjl139090
51225cf1a30Sjl139090 (void) textdomain(TEXT_DOMAIN);
51325cf1a30Sjl139090
514d8a0cca9Swh31274 log_printf("============================", 0);
51525cf1a30Sjl139090 log_printf(gettext(" Memory Configuration "), 0);
516d8a0cca9Swh31274 log_printf("============================", 0);
51725cf1a30Sjl139090 log_printf("\n", 0);
51825cf1a30Sjl139090
519d8a0cca9Swh31274 log_printf(hdrfmt,
520d8a0cca9Swh31274 "",
52125cf1a30Sjl139090 gettext("Memory"),
52225cf1a30Sjl139090 gettext("Available"),
52325cf1a30Sjl139090 gettext("Memory"),
52425cf1a30Sjl139090 gettext("DIMM"),
525d8a0cca9Swh31274 gettext("# of"),
526d8a0cca9Swh31274 gettext("Mirror"),
527d8a0cca9Swh31274 gettext("Interleave"),
52825cf1a30Sjl139090 0);
52925cf1a30Sjl139090
53025cf1a30Sjl139090 log_printf(hdrfmt,
53125cf1a30Sjl139090 gettext("LSB"),
53225cf1a30Sjl139090 gettext("Group"),
53325cf1a30Sjl139090 gettext("Size"),
53425cf1a30Sjl139090 gettext("Status"),
53525cf1a30Sjl139090 gettext("Size"),
536d8a0cca9Swh31274 gettext("DIMMs"),
537d8a0cca9Swh31274 gettext("Mode"),
538d8a0cca9Swh31274 gettext("Factor"), 0);
53925cf1a30Sjl139090
54025cf1a30Sjl139090 log_printf(hdrfmt,
541dffe6dfdSjimand "---", "-------", "------------------", "-------", "------",
542d8a0cca9Swh31274 "-----", "-------", "----------", 0);
54325cf1a30Sjl139090
54425cf1a30Sjl139090 log_printf("\n", 0);
54525cf1a30Sjl139090
54625cf1a30Sjl139090 for (bnode = tree->bd_list; bnode != NULL; bnode = bnode->next) {
54725cf1a30Sjl139090 total_mem += get_opl_mem_regs(bnode);
54825cf1a30Sjl139090 }
54925cf1a30Sjl139090
55025cf1a30Sjl139090 /*
55125cf1a30Sjl139090 * Sanity check to ensure that the total amount of system
55225cf1a30Sjl139090 * memory matches the total number of memory that
55325cf1a30Sjl139090 * we find here. Display error message if there is a mis-match.
55425cf1a30Sjl139090 */
55525cf1a30Sjl139090 total_sys_mem = (((uint64_t)sysconf(_SC_PAGESIZE) * (uint64_t)sysconf
55625cf1a30Sjl139090 (_SC_PHYS_PAGES)) / MBYTE);
55725cf1a30Sjl139090
55825cf1a30Sjl139090 if (total_mem != total_sys_mem) {
559e98fafb9Sjl139090 log_printf(dgettext(TEXT_DOMAIN, "\nError:total available "
560e98fafb9Sjl139090 "size [%lldMB] does not match total system memory "
561e98fafb9Sjl139090 "[%lldMB]\n"), total_mem, total_sys_mem, 0);
56225cf1a30Sjl139090 }
56325cf1a30Sjl139090
56425cf1a30Sjl139090 }
56525cf1a30Sjl139090
56625cf1a30Sjl139090 /*
56725cf1a30Sjl139090 * This function provides Opl's formatting of the memory config
56825cf1a30Sjl139090 * information that get_opl_mem_regs() has gathered.
56925cf1a30Sjl139090 */
57025cf1a30Sjl139090 static uint64_t
print_opl_memory_line(int lsb,struct cs_status * cs_stat,int ngrps,int mirror_mode)571d8a0cca9Swh31274 print_opl_memory_line(int lsb, struct cs_status *cs_stat, int ngrps,
572d8a0cca9Swh31274 int mirror_mode)
57325cf1a30Sjl139090 {
57425cf1a30Sjl139090 int i;
57525cf1a30Sjl139090 uint64_t total_board_mem = 0;
576d8a0cca9Swh31274 int i_factor = 2; /* default to non-mirror mode */
577d8a0cca9Swh31274 int interleave;
57825cf1a30Sjl139090
57925cf1a30Sjl139090 (void) textdomain(TEXT_DOMAIN);
58025cf1a30Sjl139090
581d8a0cca9Swh31274 if (mirror_mode)
582d8a0cca9Swh31274 i_factor *= 2;
583d8a0cca9Swh31274
584d8a0cca9Swh31274 /*
585d8a0cca9Swh31274 * Interleave factor calculation:
586d8a0cca9Swh31274 * Obtain "mirror-mode" property from pseudo-mc.
587d8a0cca9Swh31274 * cs_stat[0].dimms/i_factor represents interleave factor per
588d8a0cca9Swh31274 * pseudo-mc node. Must use cs_stat[0].dimms since this will yield
5895face7b2SJustin Frank * interleave factor even if some DIMMs are isolated, except for
5905face7b2SJustin Frank * the case where the entire memory group has been deconfigured (eg. due
5915face7b2SJustin Frank * to DIMM failure); in this case, we use the second memory group
5925face7b2SJustin Frank * (i.e. cs_stat[1]).
593d8a0cca9Swh31274 *
594d8a0cca9Swh31274 * Mirror mode:
595d8a0cca9Swh31274 * interleave factor = (# of DIMMs on cs_stat[0]/4)
596d8a0cca9Swh31274 *
597d8a0cca9Swh31274 * Non-mirror mode:
598d8a0cca9Swh31274 * interleave factor = (# of DIMMs on cs_stat[0]/2)
599d8a0cca9Swh31274 */
600d8a0cca9Swh31274
6015face7b2SJustin Frank if (cs_stat[0].dimms == 0)
6025face7b2SJustin Frank interleave = cs_stat[1].dimms/i_factor;
6035face7b2SJustin Frank else
604d8a0cca9Swh31274 interleave = cs_stat[0].dimms/i_factor;
605d8a0cca9Swh31274
606d8a0cca9Swh31274
60725cf1a30Sjl139090 for (i = 0; i < ngrps; i++) {
608e3e793b1Sjimand uint64_t mem_size;
60925cf1a30Sjl139090
610e3e793b1Sjimand mem_size = ((((uint64_t)cs_stat[i].avail_hi)<<32) +
61125cf1a30Sjl139090 cs_stat[i].avail_lo);
61225cf1a30Sjl139090
613e3e793b1Sjimand if (mem_size == 0)
614e3e793b1Sjimand continue;
61525cf1a30Sjl139090
61625cf1a30Sjl139090 /* Lsb Id */
61725cf1a30Sjl139090 log_printf(" %02d ", lsb, 0);
61825cf1a30Sjl139090
61925cf1a30Sjl139090 /* Memory Group Number */
62025cf1a30Sjl139090 if ((cs_stat[i].cs_number) == 0)
62125cf1a30Sjl139090 log_printf("%-6.6s", "A", 0);
62225cf1a30Sjl139090 else
62325cf1a30Sjl139090 log_printf("%-6.6s", "B", 0);
62425cf1a30Sjl139090
62525cf1a30Sjl139090 /* Memory Group Size */
626dffe6dfdSjimand log_printf("%8lldMB ", mem_size/MBYTE, 0);
62725cf1a30Sjl139090
62825cf1a30Sjl139090 total_board_mem += (mem_size/MBYTE);
62925cf1a30Sjl139090
63025cf1a30Sjl139090 /* Memory Group Status */
63125cf1a30Sjl139090 log_printf("%-11.11s",
63225cf1a30Sjl139090 cs_stat[i].status ? "partial": "okay", 0);
63325cf1a30Sjl139090
63425cf1a30Sjl139090 /* DIMM Size */
63525cf1a30Sjl139090 log_printf("%4lldMB ",
636e3e793b1Sjimand ((((uint64_t)cs_stat[i].dimm_hi)<<32)
63725cf1a30Sjl139090 + cs_stat[i].dimm_lo)/MBYTE, 0);
63825cf1a30Sjl139090
63925cf1a30Sjl139090 /* Number of DIMMs */
640d8a0cca9Swh31274 log_printf(" %2d", cs_stat[i].dimms);
641d8a0cca9Swh31274
642d8a0cca9Swh31274 /* Mirror Mode */
643d8a0cca9Swh31274 if (mirror_mode) {
644d8a0cca9Swh31274 log_printf("%-4.4s", " yes");
645d8a0cca9Swh31274 } else
646d8a0cca9Swh31274 log_printf("%-4.4s", " no ");
647d8a0cca9Swh31274
648d8a0cca9Swh31274 /* Interleave Factor */
649d8a0cca9Swh31274 if (interleave)
650d8a0cca9Swh31274 log_printf(" %d-way\n", interleave);
651d8a0cca9Swh31274 else
652d8a0cca9Swh31274 log_printf(" None\n");
65325cf1a30Sjl139090 }
65425cf1a30Sjl139090 return (total_board_mem);
65525cf1a30Sjl139090 }
65625cf1a30Sjl139090
65725cf1a30Sjl139090 /*
65825cf1a30Sjl139090 * Details of hardware revision and environmental status.
65925cf1a30Sjl139090 */
66025cf1a30Sjl139090 /*ARGSUSED*/
66125cf1a30Sjl139090 void
display_diaginfo(int flag,Prom_node * root,Sys_tree * tree,struct system_kstat_data * kstats)66225cf1a30Sjl139090 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
66325cf1a30Sjl139090 struct system_kstat_data *kstats)
66425cf1a30Sjl139090 {
66525cf1a30Sjl139090 /* Print the PROM revisions */
66625cf1a30Sjl139090 opl_disp_hw_revisions(tree, root);
66725cf1a30Sjl139090 }
66825cf1a30Sjl139090
66925cf1a30Sjl139090 /*
67025cf1a30Sjl139090 * Gather and display hardware revision and environmental status
67125cf1a30Sjl139090 */
67225cf1a30Sjl139090 /*ARGSUSED*/
67325cf1a30Sjl139090 static void
opl_disp_hw_revisions(Sys_tree * tree,Prom_node * root)67425cf1a30Sjl139090 opl_disp_hw_revisions(Sys_tree *tree, Prom_node *root)
67525cf1a30Sjl139090 {
67625cf1a30Sjl139090 char *version;
67725cf1a30Sjl139090 Prom_node *pnode;
6781ba18ff1Sjimand int value;
67925cf1a30Sjl139090
68025cf1a30Sjl139090 (void) textdomain(TEXT_DOMAIN);
68125cf1a30Sjl139090
68225cf1a30Sjl139090 /* Print the header */
68325cf1a30Sjl139090 log_printf("\n", 0);
68425cf1a30Sjl139090 log_printf("====================", 0);
68525cf1a30Sjl139090 log_printf(gettext(" Hardware Revisions "), 0);
68625cf1a30Sjl139090 log_printf("====================", 0);
68725cf1a30Sjl139090 log_printf("\n\n", 0);
68825cf1a30Sjl139090
68925cf1a30Sjl139090 /* Display Prom revision header */
69025cf1a30Sjl139090 log_printf(gettext("System PROM revisions:"), 0);
69125cf1a30Sjl139090 log_printf("\n----------------------\n", 0);
69225cf1a30Sjl139090 log_printf("\n", 0);
69325cf1a30Sjl139090
69425cf1a30Sjl139090 /* Display OBP version info */
69525cf1a30Sjl139090 pnode = dev_find_node(root, "openprom");
69625cf1a30Sjl139090 if (pnode != NULL) {
69725cf1a30Sjl139090 version = (char *)get_prop_val(find_prop(pnode, "version"));
69825cf1a30Sjl139090 if (version != NULL)
69925cf1a30Sjl139090 log_printf("%s\n\n", version, 0);
70025cf1a30Sjl139090 else
70125cf1a30Sjl139090 log_printf("%s\n\n", "N/A", 0);
70225cf1a30Sjl139090 }
70325cf1a30Sjl139090
70425cf1a30Sjl139090 /* Print the header */
70525cf1a30Sjl139090 log_printf("\n", 0);
70625cf1a30Sjl139090 log_printf("===================", 0);
70725cf1a30Sjl139090 log_printf(gettext(" Environmental Status "), 0);
70825cf1a30Sjl139090 log_printf("===================", 0);
70925cf1a30Sjl139090 log_printf("\n\n", 0);
71025cf1a30Sjl139090
71125cf1a30Sjl139090 opl_disp_environ();
7121ba18ff1Sjimand
7131ba18ff1Sjimand /*
7141ba18ff1Sjimand * PICL interface needs to be used for system processor mode display.
7151ba18ff1Sjimand * Check existence of OBP property "SPARC64-VII-mode".
7161ba18ff1Sjimand * No display if property does not exist.
7171ba18ff1Sjimand * If property exists then system is in (Jupiter) SPARC64-VII-mode.
7181ba18ff1Sjimand */
7191ba18ff1Sjimand value = get_proc_mode();
7201ba18ff1Sjimand
7211ba18ff1Sjimand if (value == 0) {
7221ba18ff1Sjimand /* Print the header */
7231ba18ff1Sjimand log_printf("\n", 0);
7241ba18ff1Sjimand log_printf("===================", 0);
7251ba18ff1Sjimand log_printf(gettext(" System Processor Mode "), 0);
7261ba18ff1Sjimand log_printf("===================", 0);
7271ba18ff1Sjimand log_printf("\n\n", 0);
7281ba18ff1Sjimand
7291ba18ff1Sjimand /* Jupiter mode */
7301ba18ff1Sjimand log_printf("%s\n\n", "SPARC64-VII mode");
7311ba18ff1Sjimand }
73225cf1a30Sjl139090 }
73325cf1a30Sjl139090
73425cf1a30Sjl139090 /*
73525cf1a30Sjl139090 * Gather environmental information
73625cf1a30Sjl139090 */
73725cf1a30Sjl139090 static void
opl_disp_environ(void)73825cf1a30Sjl139090 opl_disp_environ(void)
73925cf1a30Sjl139090 {
74025cf1a30Sjl139090 kstat_ctl_t *kc;
74125cf1a30Sjl139090 kstat_t *ksp;
74225cf1a30Sjl139090 kstat_named_t *k;
74325cf1a30Sjl139090
74425cf1a30Sjl139090 if ((kc = kstat_open()) == NULL)
74525cf1a30Sjl139090 return;
74625cf1a30Sjl139090
74725cf1a30Sjl139090 if ((ksp = kstat_lookup
74825cf1a30Sjl139090 (kc, "scfd", 0, SCF_SYSTEM_KSTAT_NAME)) == NULL) {
74925cf1a30Sjl139090 (void) kstat_close(kc);
75025cf1a30Sjl139090 return;
75125cf1a30Sjl139090 }
75225cf1a30Sjl139090
75325cf1a30Sjl139090 if (kstat_read(kc, ksp, NULL) == -1) {
75425cf1a30Sjl139090 (void) kstat_close(kc);
75525cf1a30Sjl139090 return;
75625cf1a30Sjl139090 }
75725cf1a30Sjl139090
75825cf1a30Sjl139090 if ((k = (kstat_named_t *)kstat_data_lookup
75925cf1a30Sjl139090 (ksp, SCF_SECURE_MODE_KSTAT_NAMED)) == NULL) {
76025cf1a30Sjl139090 (void) kstat_close(kc);
76125cf1a30Sjl139090 return;
76225cf1a30Sjl139090 }
76325cf1a30Sjl139090
76425cf1a30Sjl139090 if (k->value.c[0] == SCF_STAT_MODE_LOCK)
76525cf1a30Sjl139090 log_printf("Mode switch is in LOCK mode ", 0);
76625cf1a30Sjl139090 else if (k->value.c[0] == SCF_STAT_MODE_UNLOCK)
76725cf1a30Sjl139090 log_printf("Mode switch is in UNLOCK mode", 0);
76825cf1a30Sjl139090 else
76925cf1a30Sjl139090 log_printf("Mode switch is in UNKNOWN mode", 0);
77025cf1a30Sjl139090
77125cf1a30Sjl139090 log_printf("\n", 0);
77225cf1a30Sjl139090
77325cf1a30Sjl139090 (void) kstat_close(kc);
77425cf1a30Sjl139090 }
77525cf1a30Sjl139090
77625cf1a30Sjl139090
77725cf1a30Sjl139090 /*
77825cf1a30Sjl139090 * Calls do_devinfo() in order to use the libdevinfo device tree
77925cf1a30Sjl139090 * instead of OBP's device tree.
78025cf1a30Sjl139090 */
78125cf1a30Sjl139090 int
do_prominfo(int syserrlog,char * pgname,int log_flag,int prt_flag)78225cf1a30Sjl139090 do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag)
78325cf1a30Sjl139090 {
7843d808a52Ssubhan v_flag = syserrlog;
78525cf1a30Sjl139090 return (do_devinfo(syserrlog, pgname, log_flag, prt_flag));
78625cf1a30Sjl139090 }
78725cf1a30Sjl139090
78825cf1a30Sjl139090 /*
78925cf1a30Sjl139090 * Return the property value for the Prop
79025cf1a30Sjl139090 * passed in. (When using libdevinfo)
79125cf1a30Sjl139090 */
79225cf1a30Sjl139090 void *
get_prop_val(Prop * prop)79325cf1a30Sjl139090 get_prop_val(Prop *prop)
79425cf1a30Sjl139090 {
79525cf1a30Sjl139090 if (prop == NULL)
79625cf1a30Sjl139090 return (NULL);
79725cf1a30Sjl139090
79825cf1a30Sjl139090 return ((void *)(prop->value.val_ptr));
79925cf1a30Sjl139090 }
80025cf1a30Sjl139090
80125cf1a30Sjl139090 /*
80225cf1a30Sjl139090 * Return the property size for the Prop
80325cf1a30Sjl139090 * passed in. (When using libdevinfo)
80425cf1a30Sjl139090 */
80525cf1a30Sjl139090 static int
get_prop_size(Prop * prop)80625cf1a30Sjl139090 get_prop_size(Prop *prop)
80725cf1a30Sjl139090 {
80825cf1a30Sjl139090
80925cf1a30Sjl139090 if ((prop != NULL) && (prop->size > 0))
81025cf1a30Sjl139090 return (prop->size);
81125cf1a30Sjl139090 else
81225cf1a30Sjl139090 return (0);
81325cf1a30Sjl139090 }
81425cf1a30Sjl139090
81525cf1a30Sjl139090
81625cf1a30Sjl139090 /*
81725cf1a30Sjl139090 * Search a Prom node and retrieve the property with the correct
81825cf1a30Sjl139090 * name. (When using libdevinfo)
81925cf1a30Sjl139090 */
82025cf1a30Sjl139090 Prop *
find_prop(Prom_node * pnode,char * name)82125cf1a30Sjl139090 find_prop(Prom_node *pnode, char *name)
82225cf1a30Sjl139090 {
82325cf1a30Sjl139090 Prop *prop;
82425cf1a30Sjl139090
82525cf1a30Sjl139090 if (pnode == NULL)
82625cf1a30Sjl139090 return (NULL);
82725cf1a30Sjl139090
82825cf1a30Sjl139090 for (prop = pnode->props; prop != NULL; prop = prop->next) {
82925cf1a30Sjl139090 if (prop->name.val_ptr != NULL &&
83025cf1a30Sjl139090 strcmp((char *)(prop->name.val_ptr), name) == 0)
83125cf1a30Sjl139090 break;
83225cf1a30Sjl139090 }
83325cf1a30Sjl139090
83425cf1a30Sjl139090 return (prop);
83525cf1a30Sjl139090 }
83625cf1a30Sjl139090
83725cf1a30Sjl139090 /*
83825cf1a30Sjl139090 * This function adds a board node to the board structure where that
83925cf1a30Sjl139090 * that node's physical component lives.
84025cf1a30Sjl139090 */
84125cf1a30Sjl139090 void
add_node(Sys_tree * root,Prom_node * pnode)84225cf1a30Sjl139090 add_node(Sys_tree *root, Prom_node *pnode)
84325cf1a30Sjl139090 {
84425cf1a30Sjl139090 int board;
84525cf1a30Sjl139090 Board_node *bnode;
84625cf1a30Sjl139090 Prom_node *p;
84725cf1a30Sjl139090 char *type;
84825cf1a30Sjl139090
84925cf1a30Sjl139090 if ((board = get_board_num(pnode)) == -1) {
85025cf1a30Sjl139090 type = get_node_type(pnode);
85125cf1a30Sjl139090 if ((type != NULL) && (strcmp(type, "cpu") == 0))
85225cf1a30Sjl139090 board = get_board_num((pnode->parent)->parent);
85325cf1a30Sjl139090 }
85425cf1a30Sjl139090
85525cf1a30Sjl139090 /* find the node with the same board number */
85625cf1a30Sjl139090 if ((bnode = find_board(root, board)) == NULL) {
85725cf1a30Sjl139090 bnode = insert_board(root, board);
85825cf1a30Sjl139090 bnode->board_type = UNKNOWN_BOARD;
85925cf1a30Sjl139090 }
86025cf1a30Sjl139090
86125cf1a30Sjl139090 /* now attach this prom node to the board list */
86225cf1a30Sjl139090 /* Insert this node at the end of the list */
86325cf1a30Sjl139090 pnode->sibling = NULL;
86425cf1a30Sjl139090 if (bnode->nodes == NULL)
86525cf1a30Sjl139090 bnode->nodes = pnode;
86625cf1a30Sjl139090 else {
86725cf1a30Sjl139090 p = bnode->nodes;
86825cf1a30Sjl139090 while (p->sibling != NULL)
86925cf1a30Sjl139090 p = p->sibling;
87025cf1a30Sjl139090 p->sibling = pnode;
87125cf1a30Sjl139090 }
87225cf1a30Sjl139090
87325cf1a30Sjl139090 }
874