xref: /illumos-gate/usr/src/lib/libprtdiag_psr/sparc/lw8/common/lw8.c (revision 80ab886d233f514d54c2a6bdeb9fdfd951bd6881)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <alloca.h>
33 #include <errno.h>
34 #include <libintl.h>
35 #include <sys/utsname.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/openpromio.h>
39 #include <sys/ddi.h>
40 #include <syslog.h>
41 #include <fcntl.h>
42 #include <dirent.h>
43 #include <unistd.h>
44 #include <locale.h>
45 #include <picl.h>
46 #include "pdevinfo.h"
47 #include "display.h"
48 #include "display_sun4u.h"
49 #include "picldefs.h"
50 #include "libprtdiag.h"
51 
52 #if !defined(TEXT_DOMAIN)
53 #define	TEXT_DOMAIN	"SYS_TEST"
54 #endif
55 
56 #define	EM_INIT_FAIL		dgettext(TEXT_DOMAIN,\
57 	"picl_initialize failed: %s\n")
58 #define	EM_GET_ROOT_FAIL	dgettext(TEXT_DOMAIN,\
59 	"Getting root node failed: %s\n")
60 #define	EM_PRTDIAG_FAIL		dgettext(TEXT_DOMAIN, "Prtdiag failed!\n")
61 
62 #define	SIGN_ON_MSG	dgettext(TEXT_DOMAIN,\
63 	"System Configuration: Sun Microsystems ")
64 #define	SYSCLK_FREQ_MSG	dgettext(TEXT_DOMAIN,\
65 	"System clock frequency: %d MHZ\n")
66 #define	MEM_SIZE_MSG	dgettext(TEXT_DOMAIN, "Memory size: ")
67 #define	FFB_DOUBLE_BUF	dgettext(TEXT_DOMAIN, "FFB, Double Buffered")
68 #define	FFB_SINGLE_BUF	dgettext(TEXT_DOMAIN, "FFB, Single Buffered")
69 
70 #define	DEFAULT_BOARD_NUM	0
71 #define	DEFAULT_PORTID		0
72 #define	CLK_FREQ_66MHZ		66
73 #define	USB			-1
74 #define	HUB			-2
75 
76 /* bus id */
77 #define	SBUS_TYPE		0
78 #define	PCI_TYPE		1
79 #define	UPA_TYPE		2
80 
81 #define	UPA_NAME		"upa"
82 
83 /*
84  * PICL classes
85  */
86 #define	PICL_CLASS_OPTIONS		"options"
87 
88 /*
89  * Property names
90  */
91 
92 #define	OBP_PROP_REG			"reg"
93 #define	OBP_PROP_CLOCK_FREQ		"clock-frequency"
94 #define	OBP_PROP_BOARD_NUM		"board#"
95 #define	OBP_PROP_REVISION_ID		"revision-id"
96 #define	OBP_PROP_VERSION_NUM		"version#"
97 #define	OBP_PROP_BOARD_TYPE		"board_type"
98 #define	OBP_PROP_ECACHE_SIZE		"ecache-size"
99 #define	OBP_PROP_L2_CACHE_SIZE		"l2-cache-size"
100 #define	OBP_PROP_L3_CACHE_SIZE		"l3-cache-size"
101 #define	OBP_PROP_IMPLEMENTATION		"implementation#"
102 #define	OBP_PROP_MASK			"mask#"
103 #define	OBP_PROP_COMPATIBLE		"compatible"
104 #define	OBP_PROP_STATUS			"status"
105 #define	OBP_PROP_BANNER_NAME		"banner-name"
106 #define	OBP_PROP_MODEL			"model"
107 #define	OBP_PROP_66MHZ_CAPABLE		"66mhz-capable"
108 #define	OBP_PROP_FBC_REG_ID		"fbc_reg_id"
109 #define	OBP_PROP_VERSION		"version"
110 
111 #define	PROP_POWERFAIL_TIME		"powerfail-time"
112 #define	PICL_PROP_LOW_WARNING_THRESHOLD	"LowWarningThreshold"
113 
114 #define	DEFAULT_LINE_WIDTH		85
115 #define	HEADING_SYMBOL			"="
116 
117 #define	MAX_IWAYS			32
118 
119 typedef struct bank_list {
120 	picl_nodehdl_t		nodeh;
121 	uint32_t		iway_count;
122 	uint32_t		iway[MAX_IWAYS];
123 	struct bank_list	*next;
124 } bank_list_t;
125 
126 typedef struct {
127 	uint64_t	base;
128 	uint64_t	size;
129 	int		ifactor;
130 	int		bank_count;
131 } seg_info_t;
132 
133 static struct io_card	*io_card_list = NULL; /* The head of the IO card list */
134 static bank_list_t	*mem_banks = NULL;
135 static	int		mem_xfersize;
136 static	int		no_xfer_size = 0;
137 
138 static char *io_device_table[] = {
139 	"block",
140 	"disk",
141 	"cdrom",
142 	"floppy",
143 	"tape",
144 	"network",
145 	"display",
146 	"serial",
147 	"parallel",
148 	"scsi",
149 	"scsi-2",
150 	"scsi-3",
151 	"ide",
152 	"fcal",
153 	"keyboard",
154 	"mouse",
155 	"dma"
156 };
157 
158 #define	NIODEVICE	sizeof (io_device_table) / sizeof (io_device_table[0])
159 
160 static char *bus_table[] = {
161 	"ebus",
162 	"isa",
163 	"pmu"
164 };
165 
166 #define	NBUS	sizeof (bus_table) / sizeof (bus_table[0])
167 
168 /*
169  * check if it is an IO deice
170  */
171 static int
172 is_io_device(char *device_class)
173 {
174 	int i;
175 
176 	for (i = 0; i < NIODEVICE; i++) {
177 	    if (strcmp(device_class, io_device_table[i]) == 0)
178 		return (1);
179 	}
180 
181 	return (0);
182 }
183 
184 /*
185  * check if it is a bus
186  */
187 static int
188 is_bus(char *device_class)
189 {
190 	int i;
191 
192 	for (i = 0; i < NBUS; i++) {
193 	    if (strcmp(device_class, bus_table[i]) == 0)
194 		return (1);
195 	}
196 
197 	return (0);
198 }
199 
200 /*
201  * search children to get the node by the nodename
202  */
203 static int
204 picldiag_get_node_by_name(picl_nodehdl_t rooth, char *name,
205     picl_nodehdl_t *nodeh)
206 {
207 	picl_nodehdl_t	childh;
208 	int		err;
209 	char		*nodename;
210 
211 	nodename = alloca(strlen(name) + 1);
212 	if (nodename == NULL)
213 		return (PICL_FAILURE);
214 
215 	err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
216 	    sizeof (picl_nodehdl_t));
217 
218 	while (err == PICL_SUCCESS) {
219 		err = picl_get_propval_by_name(childh, PICL_PROP_NAME,
220 		    nodename, (strlen(name) + 1));
221 		if (err != PICL_SUCCESS) {
222 			err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
223 				&childh, sizeof (picl_nodehdl_t));
224 			continue;
225 		}
226 
227 		if (strcmp(nodename, name) == 0) {
228 			*nodeh = childh;
229 			return (PICL_SUCCESS);
230 		}
231 
232 		err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
233 		    &childh, sizeof (picl_nodehdl_t));
234 	}
235 
236 	return (err);
237 }
238 
239 /*
240  * get the value by the property name of the string prop
241  * Caller must free the outbuf
242  */
243 static int
244 picldiag_get_string_propval(picl_nodehdl_t modh, char *prop_name, char **outbuf)
245 {
246 	int		err;
247 	picl_prophdl_t	proph;
248 	picl_propinfo_t	pinfo;
249 	char		*prop_value;
250 
251 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
252 	if (err != PICL_SUCCESS)
253 		return (err);
254 
255 	/*
256 	 * If it is not a string prop, return NULL
257 	 */
258 	if (pinfo.type != PICL_PTYPE_CHARSTRING)
259 	    return (PICL_FAILURE);
260 
261 	prop_value = malloc(pinfo.size);
262 	if (prop_value == NULL)
263 		return (PICL_FAILURE);
264 
265 	err = picl_get_propval(proph, prop_value, pinfo.size);
266 	if (err != PICL_SUCCESS) {
267 		free(prop_value);
268 		return (err);
269 	}
270 
271 	*outbuf = prop_value;
272 	return (PICL_SUCCESS);
273 }
274 
275 
276 /*
277  * return the value as a signed integer
278  */
279 
280 static int64_t
281 picldiag_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
282 {
283 	int		err;
284 	picl_prophdl_t	proph;
285 	picl_propinfo_t	pinfo;
286 	int8_t		int8v;
287 	int16_t		int16v;
288 	int32_t		int32v;
289 	int64_t		int64v;
290 
291 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
292 	if (err != PICL_SUCCESS) {
293 		*ret = err;
294 		return (0);
295 	}
296 
297 	/*
298 	 * If it is not an int or uint  prop, return failure
299 	 */
300 	if ((pinfo.type != PICL_PTYPE_INT) &&
301 		(pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
302 		*ret = PICL_FAILURE;
303 		return (0);
304 	}
305 
306 	switch (pinfo.size) {
307 	case sizeof (int8_t):
308 		err = picl_get_propval(proph, &int8v, sizeof (int8v));
309 		*ret = err;
310 		return (int8v);
311 	case sizeof (int16_t):
312 		err = picl_get_propval(proph, &int16v, sizeof (int16v));
313 		*ret = err;
314 		return (int16v);
315 	case sizeof (int32_t):
316 		err = picl_get_propval(proph, &int32v, sizeof (int32v));
317 		*ret = err;
318 		return (int32v);
319 	case sizeof (int64_t):
320 		err = picl_get_propval(proph, &int64v, sizeof (int64v));
321 		*ret = err;
322 		return (int64v);
323 	default:	/* not supported size */
324 		*ret = PICL_FAILURE;
325 		return (0);
326 	}
327 }
328 
329 /*
330  * return the value of the uint prop
331  */
332 static uint64_t
333 picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
334 {
335 	int		err;
336 	picl_prophdl_t	proph;
337 	picl_propinfo_t	pinfo;
338 	uint8_t		uint8v;
339 	uint16_t	uint16v;
340 	uint32_t	uint32v;
341 	uint64_t	uint64v;
342 
343 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
344 	if (err != PICL_SUCCESS) {
345 		*ret = err;
346 		return (0);
347 	}
348 
349 	/*
350 	 * If it is not an int or uint prop, return failure
351 	 */
352 	if ((pinfo.type != PICL_PTYPE_INT) &&
353 		(pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
354 		*ret = PICL_FAILURE;
355 		return (0);
356 	}
357 
358 	/* uint prop */
359 
360 	switch (pinfo.size) {
361 	case sizeof (uint8_t):
362 		err = picl_get_propval(proph, &uint8v, sizeof (uint8v));
363 		*ret = err;
364 		return (uint8v);
365 	case sizeof (uint16_t):
366 		err = picl_get_propval(proph, &uint16v, sizeof (uint16v));
367 		*ret = err;
368 		return (uint16v);
369 	case sizeof (uint32_t):
370 		err = picl_get_propval(proph, &uint32v, sizeof (uint32v));
371 		*ret = err;
372 		return (uint32v);
373 	case sizeof (uint64_t):
374 		err = picl_get_propval(proph, &uint64v, sizeof (uint64v));
375 		*ret = err;
376 		return (uint64v);
377 	default:	/* not supported size */
378 		*ret = PICL_FAILURE;
379 		return (0);
380 	}
381 }
382 
383 /*
384  * return the value of the float prop
385  */
386 static float
387 picldiag_get_float_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
388 {
389 	int		err;
390 	picl_prophdl_t	proph;
391 	picl_propinfo_t	pinfo;
392 	float		floatv;
393 
394 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
395 	if (err != PICL_SUCCESS) {
396 		*ret = err;
397 		return ((float)0);
398 	}
399 
400 	/*
401 	 * If it is not a float prop, return failure
402 	 */
403 	if (pinfo.type != PICL_PTYPE_FLOAT) {
404 		*ret = PICL_FAILURE;
405 		return ((float)0);
406 	}
407 
408 	*ret = picl_get_propval(proph, &floatv, sizeof (floatv));
409 	return (floatv);
410 }
411 
412 /*
413  * get the clock frequency
414  */
415 static int
416 picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq)
417 {
418 #define	ROUND_TO_MHZ(x)	(((x) + 500000)/ 1000000)
419 	int		err;
420 	uint64_t	clk_freq;
421 
422 	clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err);
423 	if (err != PICL_SUCCESS)
424 		return (err);
425 
426 	*freq = ROUND_TO_MHZ(clk_freq);
427 
428 	return (PICL_SUCCESS);
429 }
430 
431 /*
432  * get the clock frequency from parent
433  */
434 static int
435 picldiag_get_clock_from_parent(picl_nodehdl_t nodeh, uint32_t *clk)
436 {
437 	picl_nodehdl_t	parenth;
438 	int		err;
439 
440 
441 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
442 	    &parenth, sizeof (parenth));
443 
444 	while (err == PICL_SUCCESS) {
445 		err = picldiag_get_clock_freq(parenth, clk);
446 		if (err != PICL_PROPNOTFOUND)
447 			return (err);
448 
449 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
450 		    &parenth, sizeof (parenth));
451 	}
452 
453 	return (err);
454 }
455 
456 /*
457  * get _fru_parent prop
458  * If not found, then travese superiors (parent nodes) until
459  * a _fru_parent property is found.
460  * If not found, no fru parent
461  */
462 static int
463 picldiag_get_fru_parent(picl_nodehdl_t nodeh, picl_nodehdl_t *fruparenth)
464 {
465 	picl_nodehdl_t	fruh;
466 	int		err;
467 
468 	/* find fru parent */
469 	err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT,
470 	    &fruh, sizeof (fruh));
471 
472 	if (err != PICL_SUCCESS)
473 		err = picl_get_propval_by_name(nodeh, PICL_REFPROP_LOC_PARENT,
474 		    &fruh, sizeof (fruh));
475 
476 	while (err == PICL_PROPNOTFOUND) {
477 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
478 		    &nodeh, sizeof (nodeh));
479 		if (err != PICL_SUCCESS)
480 			return (err);
481 
482 		err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT,
483 		    &fruh, sizeof (fruh));
484 		if (err != PICL_SUCCESS)
485 			err = picl_get_propval_by_name(nodeh,
486 			    PICL_REFPROP_LOC_PARENT, &fruh, sizeof (fruh));
487 	}
488 
489 	if (err == PICL_SUCCESS)
490 		*fruparenth = fruh;
491 
492 	return (err);
493 }
494 
495 /*
496  * get label
497  *
498  * To get the label, use the following algorithm:
499  * Lookup "Label" property in the fru node itself. If no
500  * Label found, then traverse superiors (parent nodes) until
501  * a Label property is found.
502  * if not found, then no label
503  */
504 static int
505 picldiag_get_label(picl_nodehdl_t nodeh, char **label)
506 {
507 	int		err;
508 
509 	err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, label);
510 
511 	while (err == PICL_PROPNOTFOUND) {
512 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
513 		    &nodeh, sizeof (nodeh));
514 		if (err != PICL_SUCCESS)
515 			return (err);
516 
517 		err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL,
518 		    label);
519 	}
520 
521 	return (err);
522 }
523 
524 /*
525  * get combined label
526  *
527  * like picldiag_get_label, except concatenates the labels of parent locations
528  * eg SB0/P3 for processor P3 on system board SB0
529  *
530  * if caller specifies non-zero label length, label will be cut to specified
531  * length.
532  * negative length is left justified, non-negative length is right justified
533  */
534 static int
535 picldiag_get_combined_label(picl_nodehdl_t nodeh, char **label, int lablen)
536 {
537 	int	err;
538 	char	*ptr;
539 	char	*ptr1 = NULL;
540 	char	*ptr2;
541 	int	len;
542 
543 	err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr1);
544 	if (err != PICL_PROPNOTFOUND && err != PICL_SUCCESS)
545 		return (err);
546 
547 	for (;;) {
548 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
549 		    &nodeh, sizeof (nodeh));
550 		if (err == PICL_PROPNOTFOUND)
551 			break;
552 		if (err != PICL_SUCCESS)
553 			return (err);
554 
555 		err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr);
556 		if (err == PICL_SUCCESS) {
557 			if (ptr1 == NULL) {
558 				ptr1 = ptr;
559 			} else {
560 				ptr2 = malloc(strlen(ptr1) + strlen(ptr) + 2);
561 				if (ptr2 == NULL)
562 					return (PICL_FAILURE);
563 				(void) strcpy(ptr2, ptr);
564 				(void) strcat(ptr2, "/");
565 				(void) strcat(ptr2, ptr1);
566 				(void) free(ptr);
567 				(void) free(ptr1);
568 				ptr1 = ptr2;
569 			}
570 		} else if (err != PICL_PROPNOTFOUND) {
571 			return (err);
572 		}
573 	}
574 
575 	if (ptr1 == NULL)
576 		return (PICL_PROPNOTFOUND);
577 
578 	len = strlen(ptr1);
579 	/* if no string truncation is desired or required */
580 	if ((lablen == 0) || (len <= abs(lablen))) {
581 		*label = ptr1;
582 		return (PICL_SUCCESS);
583 	}
584 
585 	/* string truncation is required; alloc space for (lablen + \0) */
586 	ptr = malloc(abs(lablen) + 1);
587 	if (ptr == 0)
588 		return (PICL_FAILURE);
589 	if (lablen > 0) {
590 		/* right justification; label = "+<string>\0" */
591 		strcpy(ptr, "+");
592 		strncat(ptr, ptr1 + len - lablen + 1, lablen + 1);
593 	} else {
594 		/* left justification; label = "<string>+\0" */
595 		strncpy(ptr, ptr1, abs(lablen) - 1);
596 		strcat(ptr, "+");
597 	}
598 
599 	*label = ptr;
600 	return (PICL_SUCCESS);
601 }
602 
603 /*
604  * return the first compatible value
605  */
606 static int
607 picldiag_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
608 {
609 	int		err;
610 	picl_prophdl_t	proph;
611 	picl_propinfo_t	pinfo;
612 	picl_prophdl_t	tblh;
613 	picl_prophdl_t	rowproph;
614 	char		*pval;
615 
616 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
617 	    &pinfo, &proph);
618 	if (err != PICL_SUCCESS)
619 	    return (err);
620 
621 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
622 		pval = malloc(pinfo.size);
623 		if (pval == NULL)
624 			return (PICL_FAILURE);
625 		err = picl_get_propval(proph, pval, pinfo.size);
626 		if (err != PICL_SUCCESS) {
627 			free(pval);
628 			return (err);
629 		}
630 		*outbuf = pval;
631 		return (PICL_SUCCESS);
632 	}
633 
634 	if (pinfo.type != PICL_PTYPE_TABLE)
635 		return (PICL_FAILURE);
636 
637 	/* get first string from table */
638 	err = picl_get_propval(proph, &tblh, pinfo.size);
639 	if (err != PICL_SUCCESS)
640 		return (err);
641 
642 	err = picl_get_next_by_row(tblh, &rowproph);
643 	if (err != PICL_SUCCESS)
644 		return (err);
645 
646 	err = picl_get_propinfo(rowproph, &pinfo);
647 	if (err != PICL_SUCCESS)
648 	    return (err);
649 
650 	pval = malloc(pinfo.size);
651 	if (pval == NULL)
652 		return (PICL_FAILURE);
653 
654 	err = picl_get_propval(rowproph, pval, pinfo.size);
655 	if (err != PICL_SUCCESS) {
656 		free(pval);
657 		return (err);
658 	}
659 
660 	*outbuf = pval;
661 	return (PICL_SUCCESS);
662 }
663 
664 /*
665  * print the header in the center
666  */
667 static void
668 logprintf_header(char *header, size_t line_width)
669 {
670 	size_t	start_pos;
671 	size_t	i;
672 
673 	log_printf("\n");
674 	start_pos = (line_width - strlen(header) - 2) / 2;
675 
676 	for (i = 0; i < start_pos; i++)
677 		log_printf("%s", HEADING_SYMBOL);
678 
679 	log_printf(" %s ", header);
680 
681 	for (i = 0; i < start_pos; i++)
682 		log_printf("%s", HEADING_SYMBOL);
683 
684 	log_printf("\n");
685 }
686 
687 /*
688  * print the size
689  */
690 static void
691 logprintf_size(uint64_t size)
692 {
693 #define	SIZE_FIELD	11
694 
695 	uint64_t	kbyte = 1024;
696 	uint64_t	mbyte = 1024 * 1024;
697 	uint64_t	gbyte = 1024 * 1024 * 1024;
698 	uint64_t	residue;
699 	char		buf[SIZE_FIELD];
700 
701 	if (size >= gbyte) {
702 		residue = size % gbyte;
703 		if (residue == 0)
704 			snprintf(buf, sizeof (buf), "%dGB",
705 			    (int)(size / gbyte));
706 		else
707 			snprintf(buf, sizeof (buf), "%.2fGB",
708 			    (float)size / gbyte);
709 	} else if (size >= mbyte) {
710 		residue = size % mbyte;
711 		if (residue == 0)
712 			snprintf(buf, sizeof (buf), "%dMB",
713 			    (int)(size / mbyte));
714 		else
715 			snprintf(buf, sizeof (buf), "%.2fMB",
716 			    (float)size / mbyte);
717 	} else {
718 		residue = size % kbyte;
719 		if (residue == 0)
720 			snprintf(buf, sizeof (buf), "%dKB",
721 			    (int)(size / kbyte));
722 		else
723 			snprintf(buf, sizeof (buf), "%.2fKB",
724 			    (float)size / kbyte);
725 	}
726 
727 	log_printf("%-10s ", buf);
728 }
729 
730 /*
731  * display platform banner
732  */
733 static int
734 display_platform_banner(picl_nodehdl_t plafh)
735 {
736 	char	*platform;
737 	char	*banner_name;
738 	int	err;
739 
740 	/*
741 	 * get PICL_PROP_MACHINE and PICL_PROP_BANNER_NAME
742 	 */
743 	log_printf(SIGN_ON_MSG);
744 	err = picldiag_get_string_propval(plafh, PICL_PROP_MACHINE,
745 	    &platform);
746 	if (err != PICL_SUCCESS)
747 		return (err);
748 	log_printf(" %s", platform);
749 	free(platform);
750 
751 	err = picldiag_get_string_propval(plafh, OBP_PROP_BANNER_NAME,
752 	    &banner_name);
753 	if (err != PICL_SUCCESS)
754 		return (err);
755 	log_printf(" %s", banner_name);
756 	free(banner_name);
757 
758 	log_printf("\n");
759 	return (PICL_SUCCESS);
760 }
761 
762 /*
763  * display the clock frequency
764  */
765 static int
766 display_system_clock(picl_nodehdl_t plafh)
767 {
768 	uint32_t	system_clk;
769 	int		err;
770 
771 	err = picldiag_get_clock_freq(plafh, &system_clk);
772 	if (err != PICL_SUCCESS)
773 		return (err);
774 
775 	log_printf(SYSCLK_FREQ_MSG, system_clk);
776 
777 	return (PICL_SUCCESS);
778 }
779 
780 /*
781  * callback function to display the memory size
782  */
783 /*ARGSUSED*/
784 static int
785 memory_callback(picl_nodehdl_t memh, void *args)
786 {
787 	uint64_t	mem_size;
788 	int		err;
789 
790 	log_printf(MEM_SIZE_MSG);
791 	mem_size = picldiag_get_uint_propval(memh, PICL_PROP_SIZE, &err);
792 	if (err == PICL_SUCCESS)
793 		logprintf_size(mem_size);
794 	log_printf("\n");
795 	no_xfer_size = 0;
796 	mem_xfersize = picldiag_get_uint_propval(memh, PICL_PROP_TRANSFER_SIZE,
797 	    &err);
798 	if (err == PICL_PROPNOTFOUND)
799 		no_xfer_size = 1;
800 	return (PICL_WALK_TERMINATE);
801 }
802 
803 /*
804  * callback function to print cpu information
805  */
806 /*ARGSUSED*/
807 static int
808 cpu_callback(picl_nodehdl_t nodeh, void *args)
809 {
810 	int		err;
811 	int		id0, id1;
812 	uint64_t 	uintval;
813 	uint64_t 	decoded_mask;
814 	uint32_t	freq;
815 	char		*impl_name;
816 	char		*status;
817 	picl_prophdl_t	parenth;
818 	picl_prophdl_t	peerh;
819 	char		*label;
820 	int		is_cmp = 0;
821 	int		is_cheetah = 0;
822 
823 	/*
824 	 * first check the implementation. If it's a CMP
825 	 * we need to combine info from both cores.
826 	 */
827 
828 	impl_name = NULL;
829 	uintval = picldiag_get_uint_propval(nodeh,
830 	    OBP_PROP_IMPLEMENTATION, &err);
831 	if (err == PICL_SUCCESS) {
832 		if (CPU_IMPL_IS_CMP(uintval)) {
833 			is_cmp = 1;
834 			err = picldiag_get_first_compatible_value(nodeh,
835 			    &impl_name);
836 			if (err != PICL_SUCCESS)
837 				impl_name = NULL;
838 		} else if (IS_CHEETAH(uintval) || IS_CHEETAH_PLUS(uintval)) {
839 			is_cheetah = 1;
840 			err = picldiag_get_string_propval(nodeh, PICL_PROP_NAME,
841 			    &impl_name);
842 			if (err != PICL_SUCCESS)
843 				impl_name = NULL;
844 		}
845 	} else {
846 		err = picldiag_get_string_propval(nodeh,
847 		    PICL_PROP_NAME, &impl_name);
848 		if (err != PICL_SUCCESS)
849 		impl_name = NULL;
850 	}
851 
852 	/*
853 	 * In the CMP case, combine info from both cores. If we
854 	 * are being called with the first core handle, we display
855 	 * info on the sibling core handle too. If we are being
856 	 * called with the second core hanlde as an argument, simply
857 	 * return.
858 	 */
859 
860 	if (is_cmp) {
861 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
862 		    &peerh, sizeof (picl_nodehdl_t));
863 		if (err != PICL_SUCCESS)
864 			return (PICL_WALK_CONTINUE);
865 		id1 = picldiag_get_uint_propval(peerh, PICL_PROP_ID, &err);
866 		if (err == PICL_PROPNOTFOUND)
867 			return (PICL_WALK_CONTINUE);
868 		else if (err != PICL_SUCCESS)
869 			return (err);
870 	}
871 
872 	/*
873 	 * If no ID is found, return
874 	 */
875 	id0 = picldiag_get_uint_propval(nodeh, PICL_PROP_ID, &err);
876 	if (err == PICL_PROPNOTFOUND)
877 		return (PICL_WALK_CONTINUE);
878 	else if (err != PICL_SUCCESS)
879 		return (err);
880 	if (is_cmp) {
881 		log_printf("%3d,%3d  ", id0, id1);
882 	} else {
883 		log_printf("%7d  ", id0);
884 	}
885 
886 	/*
887 	 * If no freq is found, return
888 	 */
889 	err = picldiag_get_clock_freq(nodeh, &freq);
890 	if (err == PICL_PROPNOTFOUND)
891 		return (PICL_WALK_CONTINUE);
892 	else if (err != PICL_SUCCESS)
893 		return (err);
894 	log_printf("%4d MHz  ", freq);
895 
896 	/* Ecache size */
897 
898 	if (is_cmp) {
899 		uintval = picldiag_get_uint_propval(nodeh,
900 		    OBP_PROP_L3_CACHE_SIZE, &err);
901 		if (err == PICL_SUCCESS) {
902 			/*
903 			 * Panther L3 is logically shared, so the total E$
904 			 * size is equal to the core size.
905 			 */
906 			logprintf_size(uintval);
907 		} else {
908 			uintval = picldiag_get_uint_propval(nodeh,
909 			    OBP_PROP_L2_CACHE_SIZE, &err);
910 			if (err == PICL_SUCCESS) {
911 				/*
912 				 * Jaguar has a split E$, so the total size
913 				 * is the sum of both cores.
914 				 */
915 				logprintf_size(uintval * 2);
916 			} else
917 				log_printf(" -          ");
918 		}
919 	} else {
920 		uintval = picldiag_get_uint_propval(nodeh,
921 			    OBP_PROP_ECACHE_SIZE, &err);
922 		if (err == PICL_SUCCESS)
923 			logprintf_size(uintval);
924 		else
925 			log_printf(" -          ");
926 	}
927 
928 	/* Implementation */
929 	if (impl_name != NULL)
930 		log_printf(" %-20s ", impl_name);
931 	else
932 		log_printf("  <unknown>           ");
933 
934 	/* CPU Mask */
935 	uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_MASK, &err);
936 	if (err == PICL_PROPNOTFOUND)
937 		log_printf("  -     ");
938 	else if (err == PICL_SUCCESS) {
939 		if (is_cheetah) {
940 			decoded_mask = REMAP_CHEETAH_MASK(uintval);
941 		} else {
942 			decoded_mask = uintval;
943 		}
944 		log_printf("%2lld.%-2lld   ", (decoded_mask >> 4) & 0xf,
945 		    decoded_mask & 0xf);
946 	} else
947 		return (err);
948 
949 	/*
950 	 * Status - if the node has a status property then display that
951 	 * otherwise display the State property
952 	 */
953 	err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, &status);
954 	if (err == PICL_SUCCESS) {
955 		log_printf("%-12s", status);
956 		free(status);
957 	} else if (err != PICL_PROPNOTFOUND && err !=
958 	    PICL_PROPVALUNAVAILABLE && err != PICL_ENDOFLIST) {
959 		return (err);
960 	} else {
961 		err = picldiag_get_string_propval(nodeh,
962 		    PICL_PROP_STATE, &status);
963 		if (err == PICL_SUCCESS) {
964 			log_printf("%-12s", status);
965 			free(status);
966 		} else if (err != PICL_PROPNOTFOUND && err !=
967 		    PICL_PROPVALUNAVAILABLE && err !=
968 		    PICL_ENDOFLIST) {
969 			return (err);
970 		} else {
971 			log_printf("unknown    ");
972 		}
973 	}
974 
975 	/*
976 	 * Location: use label of fru parent
977 	 */
978 	err = picldiag_get_fru_parent(nodeh, &parenth);
979 	if (err == PICL_PROPNOTFOUND) {
980 		log_printf(" -      ");
981 	} else if (err == PICL_SUCCESS) {
982 		err = picldiag_get_combined_label(parenth, &label, 12);
983 		if (err == PICL_PROPNOTFOUND)
984 			log_printf(" -      ");
985 		else if (err == PICL_SUCCESS) {
986 			log_printf("%s", label);
987 			free(label);
988 		} else
989 			return (err);
990 	} else
991 		return (err);
992 
993 	log_printf("\n");
994 	return (PICL_WALK_CONTINUE);
995 }
996 
997 /*
998  * display cpu information
999  */
1000 static int
1001 display_cpu_info(picl_nodehdl_t plafh)
1002 {
1003 	int	err;
1004 
1005 	/*
1006 	 * Display the table header for CPUs . Then display the CPU
1007 	 * frequency, cache size, and processor revision  on all the boards.
1008 	 */
1009 	logprintf_header(dgettext(TEXT_DOMAIN, "CPUs"), DEFAULT_LINE_WIDTH);
1010 	log_printf("               E$          CPU                  "
1011 		"CPU\n");
1012 	log_printf("CPU      Freq      Size        Implementation       "
1013 		"Mask    Status      Location\n");
1014 	log_printf("-------  --------  ----------  -------------------  "
1015 		"-----   ------      --------\n");
1016 
1017 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU,
1018 	    cpu_callback);
1019 	return (err);
1020 }
1021 
1022 /*
1023  * Inserts an io_card structure into the list.
1024  */
1025 static void
1026 add_io_card(uint32_t board, uint32_t bus_id, uint32_t slot, char *label,
1027     uint32_t freq, char *name, char *model, char *status, char *devfs_path)
1028 {
1029 	struct io_card card;
1030 
1031 	card.display = 1;
1032 	card.board = board;
1033 	switch (bus_id) {
1034 	case SBUS_TYPE:
1035 		strlcpy(card.bus_type, SBUS_NAME, MAXSTRLEN);
1036 		break;
1037 	case PCI_TYPE:
1038 		strlcpy(card.bus_type, PCI_NAME, MAXSTRLEN);
1039 		break;
1040 	case UPA_TYPE:
1041 		strlcpy(card.bus_type, UPA_NAME, MAXSTRLEN);
1042 		break;
1043 	default: /* won't reach here */
1044 		strlcpy(card.bus_type, "", MAXSTRLEN);
1045 		break;
1046 	}
1047 	if (label == NULL)
1048 		card.slot = slot;
1049 	else {
1050 		card.slot = PCI_SLOT_IS_STRING;
1051 		(void) strlcpy(card.slot_str, label, MAXSTRLEN);
1052 	}
1053 	card.freq = freq;
1054 	card.status[0] = '\0';
1055 	card.name[0] = '\0';
1056 	card.model[0] = '\0';
1057 	card.notes[0] = '\0';
1058 	if (status != NULL)
1059 		strlcpy(card.status, status, MAXSTRLEN);
1060 	if (name != NULL)
1061 		strlcpy(card.name, name, MAXSTRLEN);
1062 	if (model != NULL)
1063 		strlcpy(card.model, model, MAXSTRLEN);
1064 	if (status != NULL)
1065 		strlcpy(card.status, status, MAXSTRLEN);
1066 	if (devfs_path != NULL)
1067 		strlcpy(card.notes, devfs_path, MAXSTRLEN);
1068 
1069 	io_card_list = insert_io_card(io_card_list, &card);
1070 }
1071 
1072 static void
1073 append_to_bank_list(bank_list_t *newptr)
1074 {
1075 	bank_list_t	*ptr;
1076 
1077 	if (mem_banks == NULL) {
1078 		mem_banks = newptr;
1079 		return;
1080 	}
1081 	ptr = mem_banks;
1082 	while (ptr->next != NULL)
1083 		ptr = ptr->next;
1084 
1085 	ptr->next = newptr;
1086 }
1087 
1088 static void
1089 free_bank_list(void)
1090 {
1091 	bank_list_t	*ptr;
1092 	bank_list_t	*tmp;
1093 
1094 	for (ptr = mem_banks; ptr != NULL; ptr = tmp) {
1095 		tmp = ptr->next;
1096 		free(ptr);
1097 	}
1098 	mem_banks = NULL;
1099 }
1100 
1101 
1102 /*
1103  * print label for memory module
1104  */
1105 static int
1106 logprintf_memory_module_label(picl_nodehdl_t moduleh)
1107 {
1108 	picl_nodehdl_t	fruparenth;
1109 	int		err;
1110 	char		*label;
1111 
1112 	err = picldiag_get_fru_parent(moduleh, &fruparenth);
1113 	if (err == PICL_PROPNOTFOUND) {
1114 		log_printf("-");
1115 		return (PICL_SUCCESS);
1116 	} else if (err != PICL_SUCCESS)
1117 		return (err);
1118 
1119 	err = picldiag_get_combined_label(fruparenth, &label, 30);
1120 	if (err == PICL_PROPNOTFOUND)
1121 		log_printf("-");
1122 	else if (err == PICL_SUCCESS) {
1123 		log_printf("%-15s", label);
1124 		free(label);
1125 	} else
1126 		return (err);
1127 
1128 	return (PICL_SUCCESS);
1129 }
1130 
1131 /*
1132  * print the bank id and add the bank handle in the bank list
1133  * return the head of the bank list
1134  */
1135 static int
1136 membank_callback(picl_nodehdl_t bankh, void *args)
1137 {
1138 	int		err;
1139 	int64_t		id;
1140 	uint64_t	match;
1141 	uint64_t	mask;
1142 	int		i;
1143 	bank_list_t	*newptr;
1144 	seg_info_t	*segp = args;
1145 
1146 	/*
1147 	 * print the bank id in the segment table contains column
1148 	 */
1149 	id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err);
1150 	if (segp->bank_count > 0)
1151 		log_printf(",");
1152 	if (err == PICL_PROPNOTFOUND)
1153 		log_printf("-");
1154 	else if (err == PICL_SUCCESS)
1155 		log_printf("%-lld", id);
1156 	else
1157 		return (err);
1158 	segp->bank_count++;
1159 
1160 	/*
1161 	 * Save the bank information for later (print_bank_table)
1162 	 */
1163 	newptr = malloc(sizeof (*newptr));
1164 	if (newptr == NULL)
1165 		return (PICL_FAILURE);
1166 
1167 	newptr->nodeh = bankh;
1168 	newptr->iway_count = 0;
1169 	newptr->next = NULL;
1170 	append_to_bank_list(newptr);
1171 
1172 	/*
1173 	 * Compute the way numbers for the bank
1174 	 */
1175 	if (no_xfer_size)
1176 		return (PICL_WALK_CONTINUE);
1177 
1178 	match = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMATCH, &err);
1179 	if (err == PICL_PROPNOTFOUND)
1180 		return (PICL_WALK_CONTINUE);
1181 	else if (err != PICL_SUCCESS)
1182 		return (err);
1183 
1184 	mask = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMASK, &err);
1185 	if (err == PICL_PROPNOTFOUND)
1186 		return (PICL_WALK_CONTINUE);
1187 	else if (err != PICL_SUCCESS)
1188 		return (err);
1189 
1190 	i = 0;
1191 	while ((i < segp->ifactor) && (newptr->iway_count < MAX_IWAYS)) {
1192 		if (((segp->base + i * mem_xfersize) & mask) == match)
1193 			newptr->iway[newptr->iway_count++] = i;
1194 		++i;
1195 	}
1196 	return (PICL_WALK_CONTINUE);
1197 }
1198 
1199 
1200 /*
1201  * find the memory bank and add the bank handle in the bank list
1202  * return the head of the bank list
1203  */
1204 static int
1205 logprintf_bankinfo(picl_nodehdl_t segh, seg_info_t *segp)
1206 {
1207 	int		err;
1208 
1209 	log_printf("BankIDs ");
1210 	/*
1211 	 * find memory-bank
1212 	 */
1213 	segp->bank_count = 0;
1214 	err = picl_walk_tree_by_class(segh, PICL_CLASS_MEMORY_BANK, segp,
1215 	    membank_callback);
1216 	log_printf("\n");
1217 	return (err);
1218 }
1219 
1220 /*
1221  * print the label of memory module or the memory module bank ids
1222  */
1223 static int
1224 logprintf_seg_contains_col(picl_nodehdl_t nodeh, seg_info_t *segp)
1225 {
1226 	picl_nodehdl_t	moduleh;
1227 	int		err;
1228 
1229 	/*
1230 	 * find memory-module if referenced directly from the memory-segment
1231 	 * (ie no memory banks)
1232 	 */
1233 	err = picl_get_propval_by_name(nodeh, PICL_REFPROP_MEMORY_MODULE,
1234 	    &moduleh, sizeof (moduleh));
1235 	if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND))
1236 		return (err);
1237 	if (err == PICL_SUCCESS) {
1238 		err = logprintf_memory_module_label(moduleh);
1239 		log_printf("\n");
1240 		return (err);
1241 	}
1242 
1243 	/*
1244 	 * memory-module not referenced directly from the memory segment
1245 	 * so list memory banks instead
1246 	 */
1247 	err = logprintf_bankinfo(nodeh, segp);
1248 	return (err);
1249 }
1250 
1251 /*
1252  * find all memory modules under the given memory module group
1253  * and print its label
1254  */
1255 static int
1256 logprintf_memory_module_group_info(picl_nodehdl_t memgrph, uint64_t mcid)
1257 {
1258 	int		err;
1259 	int64_t		id;
1260 	picl_nodehdl_t	moduleh;
1261 	char		piclclass[PICL_CLASSNAMELEN_MAX];
1262 	picl_nodehdl_t	fruparenth;
1263 	char		*status;
1264 
1265 	id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID, &err);
1266 	if (err == PICL_PROPNOTFOUND)
1267 		id = -1;
1268 	else if (err != PICL_SUCCESS)
1269 		return (err);
1270 
1271 	err = picl_get_propval_by_name(memgrph, PICL_PROP_CHILD, &moduleh,
1272 	    sizeof (picl_nodehdl_t));
1273 
1274 	while (err == PICL_SUCCESS) {
1275 		/* controller id */
1276 		log_printf("%-8lld       ", mcid);
1277 
1278 		/* group id */
1279 		if (id == -1) {
1280 			log_printf("-         ");
1281 		} else {
1282 			log_printf("%-8lld ", id);
1283 		}
1284 
1285 		err = picl_get_propval_by_name(moduleh, PICL_PROP_CLASSNAME,
1286 		    piclclass, sizeof (piclclass));
1287 		if (err != PICL_SUCCESS)
1288 			return (err);
1289 
1290 		if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE) == 0) {
1291 			err = logprintf_memory_module_label(moduleh);
1292 			if (err != PICL_SUCCESS)
1293 				return (err);
1294 		}
1295 
1296 		err = picldiag_get_fru_parent(moduleh, &fruparenth);
1297 		if (err == PICL_SUCCESS) {
1298 			err = picldiag_get_string_propval(fruparenth,
1299 			    PICL_PROP_OPERATIONAL_STATUS, &status);
1300 			if (err == PICL_SUCCESS) {
1301 				log_printf("%s", status);
1302 				free(status);
1303 			} else if (err != PICL_PROPNOTFOUND)
1304 				return (err);
1305 		} else if (err != PICL_PROPNOTFOUND)
1306 			return (err);
1307 
1308 		err = picl_get_propval_by_name(moduleh, PICL_PROP_PEER,
1309 		    &moduleh, sizeof (picl_nodehdl_t));
1310 
1311 		log_printf("\n");
1312 	}
1313 	if (err == PICL_PROPNOTFOUND)
1314 		return (PICL_SUCCESS);
1315 	return (err);
1316 }
1317 
1318 /*
1319  * search children to find memory module group under memory-controller
1320  */
1321 static int
1322 find_memory_module_group(picl_nodehdl_t mch, int *print_header)
1323 {
1324 	picl_nodehdl_t	memgrph;
1325 	uint64_t	mcid;
1326 	int		err;
1327 	char		piclclass[PICL_CLASSNAMELEN_MAX];
1328 
1329 	mcid = picldiag_get_uint_propval(mch, OBP_PROP_PORTID, &err);
1330 	if (err == PICL_PROPNOTFOUND)
1331 		mcid = DEFAULT_PORTID;
1332 	else if (err != PICL_SUCCESS)
1333 		return (err);
1334 
1335 	err = picl_get_propval_by_name(mch, PICL_PROP_CHILD,
1336 	    &memgrph, sizeof (picl_nodehdl_t));
1337 	while (err == PICL_SUCCESS) {
1338 		err = picl_get_propval_by_name(memgrph,
1339 		    PICL_PROP_CLASSNAME, piclclass, sizeof (piclclass));
1340 		if (err != PICL_SUCCESS)
1341 			return (err);
1342 
1343 		if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE_GROUP) == 0) {
1344 			if (*print_header == 1) {
1345 				log_printf(
1346 				    dgettext(TEXT_DOMAIN,
1347 					"\nMemory Module Groups:\n"));
1348 				log_printf("--------------------------");
1349 				log_printf("------------------------\n");
1350 				log_printf("ControllerID   GroupID  Labels");
1351 				log_printf("         Status\n");
1352 				log_printf("--------------------------");
1353 				log_printf("------------------------\n");
1354 				*print_header = 0;
1355 			}
1356 			err = logprintf_memory_module_group_info(memgrph, mcid);
1357 			if (err != PICL_SUCCESS)
1358 				return (err);
1359 		}
1360 
1361 		err = picl_get_propval_by_name(memgrph, PICL_PROP_PEER,
1362 		    &memgrph, sizeof (picl_nodehdl_t));
1363 	}
1364 	if (err == PICL_PROPNOTFOUND)
1365 		return (PICL_SUCCESS);
1366 	return (err);
1367 }
1368 
1369 /*
1370  * print memory module group table per memory-controller
1371  */
1372 static int
1373 print_memory_module_group_table(picl_nodehdl_t plafh)
1374 {
1375 	picl_nodehdl_t	mch;
1376 	int		err;
1377 	char		piclclass[PICL_CLASSNAMELEN_MAX];
1378 	int		print_header;
1379 
1380 	print_header = 1;
1381 
1382 	/*
1383 	 * find memory-controller
1384 	 */
1385 	err = picl_get_propval_by_name(plafh, PICL_PROP_CHILD, &mch,
1386 	    sizeof (picl_nodehdl_t));
1387 	while (err == PICL_SUCCESS) {
1388 		err = picl_get_propval_by_name(mch, PICL_PROP_CLASSNAME,
1389 		    piclclass, sizeof (piclclass));
1390 		if (err != PICL_SUCCESS)
1391 			return (err);
1392 
1393 		if (strcmp(piclclass, PICL_CLASS_MEMORY_CONTROLLER) != 0) {
1394 			err = print_memory_module_group_table(mch);
1395 			if (err != PICL_SUCCESS)
1396 				return (err);
1397 			err = picl_get_propval_by_name(mch, PICL_PROP_PEER,
1398 			    &mch, sizeof (picl_nodehdl_t));
1399 			continue;
1400 		}
1401 
1402 		err = find_memory_module_group(mch, &print_header);
1403 		if (err != PICL_SUCCESS)
1404 			return (err);
1405 
1406 		err = picl_get_propval_by_name(mch, PICL_PROP_PEER,
1407 		    &mch, sizeof (picl_nodehdl_t));
1408 	}
1409 	if (err == PICL_PROPNOTFOUND)
1410 		return (PICL_SUCCESS);
1411 
1412 	return (err);
1413 }
1414 
1415 /*
1416  * print bank table
1417  */
1418 static int
1419 print_bank_table(void)
1420 {
1421 	bank_list_t	*ptr;
1422 	picl_nodehdl_t	bankh;
1423 	picl_nodehdl_t	memgrph;
1424 	picl_nodehdl_t	mch;
1425 	int		err;
1426 	int32_t		i;
1427 	uint64_t	size;
1428 	int		id;
1429 
1430 	log_printf(dgettext(TEXT_DOMAIN, "\nBank Table:\n"));
1431 	log_printf("---------------------------------------");
1432 	log_printf("--------------------\n");
1433 	log_printf(dgettext(TEXT_DOMAIN, "           Physical Location\n"));
1434 	log_printf(dgettext(TEXT_DOMAIN, "ID       ControllerID  GroupID   "));
1435 	log_printf(dgettext(TEXT_DOMAIN, "Size       Interleave Way\n"));
1436 	log_printf("---------------------------------------");
1437 	log_printf("--------------------\n");
1438 
1439 	for (ptr = mem_banks; ptr != NULL; ptr = ptr->next) {
1440 		bankh = ptr->nodeh;
1441 		id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err);
1442 		if (err != PICL_SUCCESS)
1443 			log_printf("%-8s ", "-");
1444 		else
1445 			log_printf("%-8d ", id);
1446 
1447 		/* find memory-module-group */
1448 		err = picl_get_propval_by_name(bankh,
1449 		    PICL_REFPROP_MEMORY_MODULE_GROUP, &memgrph,
1450 		    sizeof (memgrph));
1451 		if (err == PICL_PROPNOTFOUND) {
1452 			log_printf("%-8s      ", "-");
1453 			log_printf("%-8s  ", "-");
1454 		} else if (err != PICL_SUCCESS)
1455 			return (err);
1456 		else {
1457 			/*
1458 			 * get controller id
1459 			 */
1460 			err = picl_get_propval_by_name(memgrph,
1461 			    PICL_PROP_PARENT, &mch, sizeof (picl_nodehdl_t));
1462 			if (err != PICL_SUCCESS)
1463 				return (err);
1464 
1465 			id = picldiag_get_uint_propval(mch, OBP_PROP_PORTID,
1466 			    &err);
1467 			if (err == PICL_PROPNOTFOUND)
1468 				id = DEFAULT_PORTID; /* use default */
1469 			else if (err != PICL_SUCCESS)
1470 				return (err);
1471 
1472 			log_printf("%-8d      ", id);
1473 
1474 			/* get group id */
1475 			id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID,
1476 			    &err);
1477 			if (err == PICL_PROPNOTFOUND)
1478 				log_printf("-          ");
1479 			else if (err == PICL_SUCCESS)
1480 				log_printf("%-8d  ", id);
1481 			else
1482 				return (err);
1483 		}
1484 
1485 		size = picldiag_get_uint_propval(bankh, PICL_PROP_SIZE, &err);
1486 		if (err == PICL_PROPNOTFOUND)
1487 			log_printf("-        	 ");
1488 		else if (err == PICL_SUCCESS)
1489 			logprintf_size(size);
1490 		else
1491 			return (err);
1492 
1493 		log_printf("     ");
1494 		for (i = 0; i < ptr->iway_count; i++) {
1495 			if (i != 0)
1496 				log_printf(",");
1497 			log_printf("%d", ptr->iway[i]);
1498 		}
1499 
1500 		log_printf("\n");
1501 	}
1502 	return (PICL_SUCCESS);
1503 }
1504 
1505 /*
1506  * callback function to print segment, add the bank in the list and
1507  * return the bank list
1508  */
1509 /* ARGSUSED */
1510 static int
1511 memseg_callback(picl_nodehdl_t segh, void *args)
1512 {
1513 	seg_info_t	seginfo;
1514 	int		err;
1515 
1516 	/* get base address */
1517 	seginfo.base = picldiag_get_uint_propval(segh, PICL_PROP_BASEADDRESS,
1518 	    &err);
1519 	if (err == PICL_PROPNOTFOUND) {
1520 		log_printf("-\n");
1521 		return (PICL_WALK_CONTINUE);
1522 	} else if (err == PICL_SUCCESS)
1523 		log_printf("0x%-16llx ", seginfo.base);
1524 	else
1525 		return (err);
1526 
1527 	/* get size */
1528 	seginfo.size = picldiag_get_uint_propval(segh, PICL_PROP_SIZE, &err);
1529 	if (err == PICL_PROPNOTFOUND) {
1530 		log_printf("-\n");
1531 		return (PICL_WALK_CONTINUE);
1532 	} else if (err == PICL_SUCCESS)
1533 		logprintf_size(seginfo.size);
1534 	else
1535 		return (err);
1536 
1537 	/* get interleave factor */
1538 	seginfo.ifactor = picldiag_get_uint_propval(segh,
1539 	    PICL_PROP_INTERLEAVE_FACTOR, &err);
1540 
1541 	if (err == PICL_PROPNOTFOUND) {
1542 		log_printf("       -\n");
1543 		return (PICL_WALK_CONTINUE);
1544 	} else if (err == PICL_SUCCESS)
1545 		log_printf("       %-2d          ", seginfo.ifactor);
1546 	else
1547 		return (err);
1548 
1549 	seginfo.bank_count = 0;
1550 	err = logprintf_seg_contains_col(segh, &seginfo);
1551 	if (err != PICL_SUCCESS)
1552 		return (err);
1553 	return (PICL_WALK_CONTINUE);
1554 }
1555 
1556 /*
1557  * search children to find memory-segment and set up the bank list
1558  */
1559 static int
1560 find_segments(picl_nodehdl_t plafh)
1561 {
1562 	int		err;
1563 
1564 	log_printf(dgettext(TEXT_DOMAIN, "Segment Table:\n"));
1565 	log_printf("------------------------------");
1566 	log_printf("-----------------------------------------\n");
1567 	log_printf(dgettext(TEXT_DOMAIN, "Base Address       Size       "));
1568 	log_printf(dgettext(TEXT_DOMAIN, "Interleave Factor  Contains\n"));
1569 	log_printf("------------------------------");
1570 	log_printf("-----------------------------------------\n");
1571 
1572 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
1573 	    NULL, memseg_callback);
1574 	return (err);
1575 }
1576 
1577 /*
1578  * display memory configuration
1579  */
1580 static int
1581 display_memory_config(picl_nodehdl_t plafh)
1582 {
1583 	int		err;
1584 
1585 	logprintf_header(dgettext(TEXT_DOMAIN, "Memory Configuration"),
1586 	    DEFAULT_LINE_WIDTH);
1587 
1588 	mem_banks = NULL;
1589 	err = find_segments(plafh);
1590 
1591 	if ((err == PICL_SUCCESS) && (mem_banks != NULL))
1592 		print_bank_table();
1593 
1594 	free_bank_list();
1595 
1596 	return (print_memory_module_group_table(plafh));
1597 }
1598 
1599 /*
1600  * print the hub device
1601  */
1602 static int
1603 logprintf_hub_devices(picl_nodehdl_t hubh)
1604 {
1605 	char		*name;
1606 	int		portnum;
1607 	int		err;
1608 
1609 	err = picldiag_get_string_propval(hubh, PICL_PROP_NAME, &name);
1610 	if (err != PICL_SUCCESS)
1611 		return (err);
1612 	log_printf("%-12.12s  ", name);
1613 	free(name);
1614 
1615 	err = picl_get_propval_by_name(hubh, OBP_PROP_REG,
1616 	    &portnum, sizeof (portnum));
1617 	if (err == PICL_PROPNOTFOUND)
1618 		log_printf("-\n");
1619 	else if (err == PICL_SUCCESS)
1620 		log_printf("%3d\n", portnum);
1621 	else
1622 		return (err);
1623 
1624 	return (PICL_SUCCESS);
1625 }
1626 
1627 /*
1628  * callback functions to display hub devices
1629  */
1630 /* ARGSUSED */
1631 static int
1632 print_usb_devices(picl_nodehdl_t hubh, void *arg)
1633 {
1634 	picl_nodehdl_t	chdh;
1635 	char		*rootname;
1636 	int		type = *(int *)arg;
1637 	int		hubnum;
1638 	int		err;
1639 
1640 	err = picl_get_propval_by_name(hubh, PICL_PROP_CHILD, &chdh,
1641 	    sizeof (picl_nodehdl_t));
1642 
1643 	/* print header */
1644 	if (err == PICL_SUCCESS) {
1645 		err = picldiag_get_string_propval(hubh, PICL_PROP_NAME,
1646 		    &rootname);
1647 		if (err != PICL_SUCCESS)
1648 			return (err);
1649 
1650 		if (type == USB) {
1651 			log_printf("\n===============================");
1652 			log_printf(dgettext(TEXT_DOMAIN,
1653 			    " %s Devices "), rootname);
1654 		} else {
1655 			/* Get its hub number */
1656 			err = picl_get_propval_by_name(hubh,
1657 			    OBP_PROP_REG, &hubnum, sizeof (hubnum));
1658 			if ((err != PICL_SUCCESS) &&
1659 			    (err != PICL_PROPNOTFOUND)) {
1660 				free(rootname);
1661 				return (err);
1662 			}
1663 
1664 			log_printf("\n===============================");
1665 			if (err == PICL_SUCCESS)
1666 				log_printf(dgettext(TEXT_DOMAIN,
1667 				    " %s#%d Devices "),
1668 				    rootname, hubnum);
1669 			else
1670 				log_printf(dgettext(TEXT_DOMAIN,
1671 				    " %s Devices "), rootname);
1672 		}
1673 
1674 		log_printf("===============================\n\n");
1675 		log_printf("Name          Port#\n");
1676 		log_printf("------------  -----\n");
1677 		free(rootname);
1678 
1679 		do {
1680 			logprintf_hub_devices(chdh);
1681 
1682 			err = picl_get_propval_by_name(chdh, PICL_PROP_PEER,
1683 			    &chdh, sizeof (picl_nodehdl_t));
1684 		} while (err == PICL_SUCCESS);
1685 	}
1686 
1687 
1688 	if (err == PICL_PROPNOTFOUND)
1689 		return (PICL_WALK_CONTINUE);
1690 	return (err);
1691 }
1692 
1693 /*
1694  * callback functions to display usb devices
1695  */
1696 /* ARGSUSED */
1697 static int
1698 usb_callback(picl_nodehdl_t usbh, void *args)
1699 {
1700 	int		err;
1701 	int		type;
1702 
1703 	type = USB;
1704 	err = print_usb_devices(usbh, &type);
1705 	if (err != PICL_WALK_CONTINUE)
1706 		return (err);
1707 	type = HUB;
1708 	err = picl_walk_tree_by_class(usbh, NULL, &type, print_usb_devices);
1709 	if (err == PICL_SUCCESS)
1710 		err = PICL_WALK_CONTINUE;
1711 	return (err);
1712 }
1713 
1714 
1715 /*
1716  * find usb devices and print its information
1717  */
1718 static int
1719 display_usb_devices(picl_nodehdl_t plafh)
1720 {
1721 	int err;
1722 
1723 	/*
1724 	 * get the usb node
1725 	 */
1726 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_USB, NULL,
1727 	    usb_callback);
1728 	return (err);
1729 }
1730 
1731 
1732 
1733 /*
1734  * If nodeh is the io device, add it into the io list and return
1735  * If it is not an io device and it has the subtree, traverse the subtree
1736  * and add all leaf io devices
1737  */
1738 static int
1739 add_io_leaves(picl_nodehdl_t nodeh, char *parentname, uint32_t board,
1740     uint32_t bus_id, uint64_t slot, uint32_t freq, char *model, char *status)
1741 {
1742 	picl_nodehdl_t	childh;
1743 	picl_prophdl_t	proph;
1744 	picl_propinfo_t	pinfo;
1745 	int		err;
1746 	char		*nameval;
1747 	char		piclclass[PICL_CLASSNAMELEN_MAX];
1748 	char		nodename[MAXSTRLEN];
1749 	char		name[MAXSTRLEN];
1750 	char		*devfs_path;
1751 	char		*compatible;
1752 	picl_nodehdl_t	fruparenth;
1753 	char		*label;
1754 	char		binding_name[MAXSTRLEN];
1755 
1756 	err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME, &pinfo,
1757 	    &proph);
1758 	if (err != PICL_SUCCESS)
1759 		return (err);
1760 
1761 	nameval = alloca(pinfo.size);
1762 	if (nameval == NULL)
1763 		return (PICL_FAILURE);
1764 
1765 	err = picl_get_propval(proph, nameval, pinfo.size);
1766 	if (err != PICL_SUCCESS)
1767 		return (err);
1768 
1769 	(void) strlcpy(nodename, nameval, MAXSTRLEN);
1770 
1771 	err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
1772 	    piclclass, sizeof (piclclass));
1773 	if (err != PICL_SUCCESS)
1774 		return (err);
1775 
1776 	/* if binding_name is found, name will be <nodename>-<binding_name> */
1777 	err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
1778 	    binding_name, sizeof (binding_name));
1779 	if (err == PICL_PROPNOTFOUND) {
1780 		/*
1781 		 * if compatible prop is found, name will be
1782 		 * <nodename>-<compatible>
1783 		 */
1784 		err = picldiag_get_first_compatible_value(nodeh, &compatible);
1785 		if (err == PICL_SUCCESS) {
1786 			strlcat(nodename, "-", MAXSTRLEN);
1787 			strlcat(nodename, compatible, MAXSTRLEN);
1788 			free(compatible);
1789 		} else if (err != PICL_PROPNOTFOUND) {
1790 			return (err);
1791 		}
1792 	} else if (err != PICL_SUCCESS) {
1793 		return (err);
1794 	} else if (strcmp(nodename, binding_name) != 0) {
1795 		if (strcmp(nodename, piclclass) == 0) {
1796 			/*
1797 			 * nodename same as binding name -
1798 			 * no need to display twice
1799 			 */
1800 			strlcpy(nodename, binding_name, MAXSTRLEN);
1801 		} else {
1802 			strlcat(nodename, "-", MAXSTRLEN);
1803 			strlcat(nodename, binding_name, MAXSTRLEN);
1804 		}
1805 	}
1806 
1807 	/*
1808 	 * If it is an immediate child under pci/sbus/upa and not
1809 	 * a bus node, add it to the io list.
1810 	 * If it is a child under sub-bus and it is in an io
1811 	 * device, add it to the io list.
1812 	 */
1813 	if (((parentname == NULL) && (!is_bus(piclclass))) ||
1814 	    ((parentname != NULL) && (is_io_device(piclclass)))) {
1815 		if (parentname == NULL)
1816 			(void) snprintf(name, MAXSTRLEN, "%s", nodename);
1817 		else
1818 			(void) snprintf(name, MAXSTRLEN, "%s/%s", parentname,
1819 			    nodename);
1820 
1821 		/*
1822 		 * append the class if its class is not a generic
1823 		 * obp-device class
1824 		 */
1825 		if (strcmp(piclclass, PICL_CLASS_OBP_DEVICE))
1826 			(void) snprintf(name, MAXSTRLEN, "%s (%s)", name,
1827 			    piclclass);
1828 
1829 		err = picldiag_get_fru_parent(nodeh, &fruparenth);
1830 		if (err == PICL_PROPNOTFOUND) {
1831 			label = NULL;
1832 		} else if (err != PICL_SUCCESS) {
1833 			return (err);
1834 		} else {
1835 			err = picldiag_get_combined_label(fruparenth, &label,
1836 			    15);
1837 			if (err == PICL_PROPNOTFOUND)
1838 				label = NULL;
1839 			else if (err != PICL_SUCCESS)
1840 				return (err);
1841 		}
1842 		/* devfs-path */
1843 		err =  picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH,
1844 		    &devfs_path);
1845 		if (err == PICL_PROPNOTFOUND)
1846 			devfs_path = NULL;
1847 		else if (err != PICL_SUCCESS)
1848 			return (err);
1849 
1850 		add_io_card(board, bus_id, slot, label, freq, name,
1851 		    model, status, devfs_path);
1852 		if (label != NULL)
1853 			free(label);
1854 		if (devfs_path != NULL)
1855 			free(devfs_path);
1856 		return (PICL_SUCCESS);
1857 	}
1858 
1859 	/*
1860 	 * If there is any child, Go through each child.
1861 	 */
1862 
1863 	err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
1864 	    &childh, sizeof (picl_nodehdl_t));
1865 
1866 	/* there is a child */
1867 	while (err == PICL_SUCCESS) {
1868 		if (parentname == NULL)
1869 			(void) strlcpy(name, nodename, MAXSTRLEN);
1870 		else
1871 			(void) snprintf(name, MAXSTRLEN, "%s/%s", parentname,
1872 			    nodename);
1873 
1874 		err = add_io_leaves(childh, name, board, bus_id, slot, freq,
1875 		    model, status);
1876 		if (err != PICL_SUCCESS)
1877 			return (err);
1878 		/*
1879 		 * get next child
1880 		 */
1881 		err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
1882 		    &childh, sizeof (picl_nodehdl_t));
1883 	}
1884 
1885 	if (err == PICL_PROPNOTFOUND)
1886 		return (PICL_SUCCESS);
1887 	return (err);
1888 }
1889 
1890 /*
1891  * callback function to add all io devices under sbus in io list
1892  */
1893 /*ARGSUSED*/
1894 static int
1895 sbus_callback(picl_nodehdl_t sbush, void *args)
1896 {
1897 	picl_nodehdl_t	nodeh;
1898 	int		err;
1899 	uint32_t	boardnum;
1900 	uint32_t	bus_id;
1901 	uint32_t	slot;
1902 	uint32_t	freq;
1903 	char		*model;
1904 	char		*status;
1905 
1906 	/* Fill in common infomation */
1907 	bus_id = SBUS_TYPE;
1908 
1909 	err = picldiag_get_clock_freq(sbush, &freq);
1910 	if (err == PICL_PROPNOTFOUND)
1911 		return (PICL_WALK_CONTINUE);
1912 	else if (err != PICL_SUCCESS)
1913 		return (err);
1914 	/*
1915 	 * If no board# is found, set boardnum to 0
1916 	 */
1917 	boardnum = picldiag_get_uint_propval(sbush, OBP_PROP_BOARD_NUM, &err);
1918 	if (err == PICL_PROPNOTFOUND)
1919 		boardnum = DEFAULT_BOARD_NUM;
1920 	else if (err != PICL_SUCCESS)
1921 		return (err);
1922 
1923 	err = picl_get_propval_by_name(sbush, PICL_PROP_CHILD, &nodeh,
1924 	    sizeof (picl_nodehdl_t));
1925 
1926 	while (err == PICL_SUCCESS) {
1927 		slot = picldiag_get_uint_propval(nodeh,
1928 		    PICL_PROP_SLOT, &err);
1929 		if (err == PICL_PROPNOTFOUND) {
1930 			err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
1931 			    &nodeh, sizeof (picl_nodehdl_t));
1932 			continue;
1933 		} else if (err != PICL_SUCCESS)
1934 			return (err);
1935 
1936 		err =  picldiag_get_string_propval(nodeh, OBP_PROP_MODEL,
1937 		    &model);
1938 		if (err == PICL_PROPNOTFOUND)
1939 			model = NULL;
1940 		else if (err != PICL_SUCCESS)
1941 			return (err);
1942 
1943 		err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS,
1944 		    &status);
1945 		if (err == PICL_PROPNOTFOUND) {
1946 			status = malloc(5);
1947 			strncpy(status, "okay", 5);
1948 		} else if (err != PICL_SUCCESS)
1949 			return (err);
1950 
1951 		err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot, freq,
1952 		    model, status);
1953 		if (model != NULL)
1954 			free(model);
1955 		if (status != NULL)
1956 			free(status);
1957 		if (err != PICL_SUCCESS)
1958 			return (err);
1959 
1960 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
1961 		    sizeof (picl_nodehdl_t));
1962 	}
1963 	if (err == PICL_PROPNOTFOUND)
1964 		return (PICL_WALK_CONTINUE);
1965 	return (err);
1966 }
1967 
1968 /*
1969  * add all io devices under pci in io list
1970  */
1971 /* ARGSUSED */
1972 static int
1973 pci_callback(picl_nodehdl_t pcih, void *args)
1974 {
1975 	picl_nodehdl_t	nodeh;
1976 	int		err;
1977 	char		piclclass[PICL_CLASSNAMELEN_MAX];
1978 	uint32_t	boardnum;
1979 	uint32_t	bus_id;
1980 	uint32_t	slot;
1981 	uint32_t	freq;
1982 	char		*model;
1983 	char		*status;
1984 
1985 	/* Fill in common infomation */
1986 	bus_id = PCI_TYPE;
1987 
1988 	/*
1989 	 * Check if it has the freq, if not,
1990 	 * If not, use its parent's freq
1991 	 * if its parent's freq is not found, return
1992 	 */
1993 	err = picldiag_get_clock_freq(pcih, &freq);
1994 	if (err == PICL_PROPNOTFOUND) {
1995 		err = picldiag_get_clock_from_parent(pcih, &freq);
1996 		if (err == PICL_PROPNOTFOUND)
1997 			return (PICL_WALK_CONTINUE);
1998 		else if (err != PICL_SUCCESS)
1999 			return (err);
2000 	} else if (err != PICL_SUCCESS)
2001 		return (err);
2002 
2003 	/*
2004 	 * If no board# is found, set boardnum to 0
2005 	 */
2006 	boardnum = picldiag_get_uint_propval(pcih, OBP_PROP_BOARD_NUM, &err);
2007 	if (err == PICL_PROPNOTFOUND)
2008 		boardnum = DEFAULT_BOARD_NUM;
2009 	else if (err != PICL_SUCCESS)
2010 		return (err);
2011 
2012 	/* Walk through the children */
2013 
2014 	err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
2015 	    sizeof (picl_nodehdl_t));
2016 	while (err == PICL_SUCCESS) {
2017 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
2018 		    piclclass, sizeof (piclclass));
2019 		if (err != PICL_SUCCESS)
2020 			return (err);
2021 
2022 		/*
2023 		 * Skip PCI bridge and USB devices because they will be
2024 		 * processed later
2025 		 */
2026 		if ((strcmp(piclclass, PICL_CLASS_PCI) == 0) ||
2027 		    (strcmp(piclclass, PICL_CLASS_USB) == 0)) {
2028 			err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
2029 			    &nodeh, sizeof (picl_nodehdl_t));
2030 			continue;
2031 		}
2032 
2033 		/* Get the device id for pci card */
2034 		slot = picldiag_get_uint_propval(nodeh,
2035 		    PICL_PROP_DEVICE_ID, &err);
2036 		if (err == PICL_PROPNOTFOUND) {
2037 			err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
2038 			    &nodeh, sizeof (picl_nodehdl_t));
2039 			continue;
2040 		} else if (err != PICL_SUCCESS)
2041 			return (err);
2042 
2043 		/* Get the model of this card */
2044 		err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL,
2045 		    &model);
2046 		if (err == PICL_PROPNOTFOUND)
2047 			model = NULL;
2048 		else if (err != PICL_SUCCESS)
2049 			return (err);
2050 
2051 		err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS,
2052 		    &status);
2053 		if (err == PICL_PROPNOTFOUND) {
2054 			status = malloc(5);
2055 			strncpy(status, "okay", 5);
2056 		} else if (err != PICL_SUCCESS)
2057 			return (err);
2058 
2059 		err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot,
2060 		    freq, model, status);
2061 
2062 		if (model != NULL)
2063 			free(model);
2064 
2065 		if (status != NULL)
2066 			free(status);
2067 
2068 		if (err != PICL_SUCCESS)
2069 			return (err);
2070 
2071 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
2072 		    sizeof (picl_nodehdl_t));
2073 
2074 	}
2075 
2076 	if (err == PICL_PROPNOTFOUND)
2077 		return (PICL_WALK_CONTINUE);
2078 
2079 	return (err);
2080 }
2081 
2082 /*
2083  * add io devices in io list
2084  * Its slot number is drived from upa-portid
2085  */
2086 static int
2087 add_io_devices(picl_nodehdl_t nodeh)
2088 {
2089 	int		err;
2090 	uint64_t	board_type;
2091 	char 		piclclass[PICL_CLASSNAMELEN_MAX];
2092 	char 		name[MAXSTRLEN];
2093 	char 		*devfs_path;
2094 	char		*nameval;
2095 	uint32_t	boardnum;
2096 	uint32_t	bus_id;
2097 	uint32_t	slot;
2098 	uint32_t	freq;
2099 	char		*model;
2100 	char		*status;
2101 	picl_prophdl_t  proph;
2102 	picl_propinfo_t	pinfo;
2103 	picl_nodehdl_t	fruparenth;
2104 	char		*label;
2105 
2106 
2107 	bus_id = UPA_TYPE;
2108 
2109 	/*
2110 	 * If clock frequency can't be found from its parent, don't add
2111 	 */
2112 	err = picldiag_get_clock_from_parent(nodeh, &freq);
2113 	if (err == PICL_PROPNOTFOUND)
2114 		return (PICL_SUCCESS);
2115 	else if (err != PICL_SUCCESS)
2116 		return (err);
2117 
2118 	/*
2119 	 * If no board# is found, set boardnum to 0
2120 	 */
2121 	boardnum = picldiag_get_uint_propval(nodeh, OBP_PROP_BOARD_NUM, &err);
2122 	if (err == PICL_PROPNOTFOUND)
2123 		boardnum = DEFAULT_BOARD_NUM;
2124 	else if (err != PICL_SUCCESS)
2125 		return (err);
2126 
2127 	/*
2128 	 * get upa portid as slot number
2129 	 * If upa portid is not found, don't add the card.
2130 	 */
2131 	slot = picldiag_get_uint_propval(nodeh, OBP_PROP_UPA_PORTID,
2132 	    &err);
2133 	if (err == PICL_PROPNOTFOUND)
2134 		return (PICL_SUCCESS);
2135 	else if (err != PICL_SUCCESS)
2136 		return (err);
2137 
2138 	/* Get the model of this card */
2139 	err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL, &model);
2140 	if (err == PICL_PROPNOTFOUND)
2141 		model = NULL;
2142 	else if (err != PICL_SUCCESS)
2143 		return (err);
2144 
2145 	/*
2146 	 * check if it is a ffb device
2147 	 * If it's a ffb device, append its board type to name
2148 	 * otherwise, use its nodename
2149 	 */
2150 	err = picl_get_prop_by_name(nodeh, PICL_PROP_FFB_BOARD_REV, &proph);
2151 	if (err == PICL_PROPNOTFOUND) {
2152 		err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME,
2153 		    &pinfo, &proph);
2154 		if (err != PICL_SUCCESS)
2155 			return (err);
2156 
2157 		nameval = alloca(pinfo.size);
2158 		if (nameval == NULL)
2159 			return (PICL_FAILURE);
2160 
2161 		err = picl_get_propval(proph, nameval, pinfo.size);
2162 		if (err != PICL_SUCCESS)
2163 			return (err);
2164 
2165 		(void) strlcpy(name, nameval, MAXSTRLEN);
2166 	} else if (err == PICL_SUCCESS) {
2167 		/* Find out if it's single or double buffered */
2168 		board_type = picldiag_get_uint_propval(nodeh,
2169 		    OBP_PROP_BOARD_TYPE, &err);
2170 		if (err == PICL_PROPNOTFOUND)
2171 			(void) strlcpy(name, FFB_NAME, sizeof (name));
2172 		if (err == PICL_SUCCESS) {
2173 			if (board_type & FFB_B_BUFF)
2174 				(void) strlcpy(name, FFB_DOUBLE_BUF,
2175 				    sizeof (name));
2176 			else
2177 				(void) strlcpy(name, FFB_SINGLE_BUF,
2178 				    sizeof (name));
2179 		} else
2180 			return (err);
2181 	} else
2182 		return (err);
2183 
2184 	err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
2185 	    piclclass, sizeof (piclclass));
2186 	if (err != PICL_SUCCESS)
2187 		return (err);
2188 
2189 	(void) snprintf(name, sizeof (name), "%s (%s)", name, piclclass);
2190 
2191 	err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, &status);
2192 	if (err == PICL_PROPNOTFOUND) {
2193 		status = malloc(5);
2194 		strncpy(status, "okay", 5);
2195 	} else if (err != PICL_SUCCESS)
2196 		return (err);
2197 
2198 	err = picldiag_get_fru_parent(nodeh, &fruparenth);
2199 	if (err == PICL_PROPNOTFOUND) {
2200 		label = NULL;
2201 	} else if (err != PICL_SUCCESS) {
2202 		return (err);
2203 	} else {
2204 		err = picldiag_get_combined_label(fruparenth, &label, 15);
2205 		if (err == PICL_PROPNOTFOUND)
2206 			label = NULL;
2207 		else if (err != PICL_SUCCESS)
2208 			return (err);
2209 	}
2210 	/* devfs-path */
2211 	err =  picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH,
2212 	    &devfs_path);
2213 	if (err == PICL_PROPNOTFOUND)
2214 		devfs_path = NULL;
2215 	else if (err != PICL_SUCCESS)
2216 		return (err);
2217 
2218 	add_io_card(boardnum, bus_id, slot, label, freq, name, model, status,
2219 	    devfs_path);
2220 	if (label != NULL)
2221 		free(label);
2222 	if (model != NULL)
2223 		free(model);
2224 	if (status != NULL)
2225 		free(status);
2226 	if (devfs_path != NULL)
2227 		free(devfs_path);
2228 
2229 	return (PICL_SUCCESS);
2230 }
2231 
2232 /*
2233  * loop through all children and add io devices in io list
2234  */
2235 static int
2236 process_io_leaves(picl_nodehdl_t rooth)
2237 {
2238 	picl_nodehdl_t	nodeh;
2239 	char		classval[PICL_CLASSNAMELEN_MAX];
2240 	int		err;
2241 
2242 	err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh,
2243 	    sizeof (picl_nodehdl_t));
2244 	while (err == PICL_SUCCESS) {
2245 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
2246 		    classval, sizeof (classval));
2247 		if (err != PICL_SUCCESS)
2248 			return (err);
2249 
2250 		if (is_io_device(classval))
2251 			err = add_io_devices(nodeh);
2252 
2253 		if (err != PICL_SUCCESS)
2254 			return (err);
2255 
2256 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
2257 		    sizeof (picl_nodehdl_t));
2258 	}
2259 
2260 	if (err == PICL_PROPNOTFOUND)
2261 		return (PICL_SUCCESS);
2262 
2263 	return (err);
2264 }
2265 
2266 /*
2267  * callback function to add all io devices under upa in io list
2268  */
2269 /*ARGSUSED*/
2270 static int
2271 upa_callback(picl_nodehdl_t upah, void *args)
2272 {
2273 	int		err;
2274 
2275 	err = process_io_leaves(upah);
2276 
2277 	if (err == PICL_SUCCESS)
2278 		return (PICL_WALK_CONTINUE);
2279 	return (err);
2280 }
2281 
2282 /*
2283  * display ffb hardware configuration
2284  */
2285 /* ARGSUSED */
2286 static int
2287 ffbconfig_callback(picl_nodehdl_t ffbh, void *arg)
2288 {
2289 	int		err;
2290 	uint64_t	board_rev;
2291 	uint64_t	fbc_ver;
2292 	char		*dac_ver;
2293 	char		*fbram_ver;
2294 
2295 	/*
2296 	 * If it has PICL_PROP_FFB_BOARD_REV, it is a ffb device
2297 	 * Otherwise, return.
2298 	 */
2299 	board_rev = picldiag_get_uint_propval(ffbh, PICL_PROP_FFB_BOARD_REV,
2300 	    &err);
2301 	if (err == PICL_PROPNOTFOUND)
2302 		return (PICL_WALK_CONTINUE);
2303 	else if (err != PICL_SUCCESS)
2304 		return (err);
2305 
2306 	log_printf("FFB Hardware Configuration:\n");
2307 	log_printf("-----------------------------------\n");
2308 	log_printf("Board rev: %lld\n", board_rev);
2309 
2310 	fbc_ver = picldiag_get_uint_propval(ffbh, OBP_PROP_FBC_REG_ID,
2311 	    &err);
2312 	if (err == PICL_SUCCESS)
2313 		log_printf("FBC version: 0x%llx\n", fbc_ver);
2314 	else if (err != PICL_PROPNOTFOUND)
2315 		return (err);
2316 
2317 	err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_DAC_VER,
2318 	    &dac_ver);
2319 	if (err == PICL_SUCCESS) {
2320 		log_printf("DAC: %s\n", dac_ver);
2321 		free(dac_ver);
2322 	} else if (err != PICL_PROPNOTFOUND)
2323 		return (err);
2324 
2325 	err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_FBRAM_VER,
2326 	    &fbram_ver);
2327 	if (err  == PICL_SUCCESS) {
2328 		log_printf("3DRAM: %s\n", fbram_ver);
2329 		free(fbram_ver);
2330 	} else if (err != PICL_PROPNOTFOUND)
2331 		return (err);
2332 
2333 	log_printf("\n");
2334 	return (PICL_WALK_CONTINUE);
2335 }
2336 
2337 /*
2338  * find all io devices and add them in the io list
2339  */
2340 static int
2341 gather_io_cards(picl_nodehdl_t plafh)
2342 {
2343 	int		err;
2344 
2345 	/*
2346 	 * look for io devices under the immediate children of platform
2347 	 */
2348 	err = process_io_leaves(plafh);
2349 
2350 	if (err != PICL_SUCCESS)
2351 		return (err);
2352 
2353 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_SBUS,
2354 	    PICL_CLASS_SBUS, sbus_callback);
2355 	if (err != PICL_SUCCESS)
2356 		return (err);
2357 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
2358 	    PICL_CLASS_PCI, pci_callback);
2359 	if (err != PICL_SUCCESS)
2360 		return (err);
2361 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_UPA,
2362 	    PICL_CLASS_UPA, upa_callback);
2363 	return (err);
2364 }
2365 
2366 static void
2367 picldiag_display_io_cards(struct io_card *list)
2368 {
2369 	static int banner = 0; /* Have we printed the column headings? */
2370 	struct io_card *p;
2371 
2372 	if (list == NULL)
2373 		return;
2374 
2375 	if (banner == 0) {
2376 		log_printf("Bus   Freq      Slot +  Name +\n", 0);
2377 		log_printf("Type  MHz       Status  "
2378 			"Path                          "
2379 			"Model", 0);
2380 		log_printf("\n", 0);
2381 		log_printf("----  ----  ----------  "
2382 			"----------------------------  "
2383 			"--------------------", 0);
2384 		log_printf("\n", 0);
2385 		banner = 1;
2386 	}
2387 
2388 	for (p = list; p != NULL; p = p -> next) {
2389 		log_printf("%-4s  ", p->bus_type, 0);
2390 		log_printf("%3d   ", p->freq, 0);
2391 		/*
2392 		 * We check to see if it's an int or
2393 		 * a char string to display for slot.
2394 		 */
2395 		if (p->slot == PCI_SLOT_IS_STRING)
2396 			log_printf("%10s  ", p->slot_str, 0);
2397 		else
2398 			log_printf("%10d  ", p->slot, 0);
2399 
2400 		log_printf("%-28.28s", p->name, 0);
2401 		if (strlen(p->name) > 28)
2402 			log_printf("+ ", 0);
2403 		else
2404 			log_printf("  ", 0);
2405 		log_printf("%-19.19s", p->model, 0);
2406 		if (strlen(p->model) > 19)
2407 			log_printf("+", 0);
2408 		log_printf("\n", 0);
2409 		log_printf("            %10s  ", p->status, 0);
2410 		if (strlen(p->notes) > 0)
2411 			log_printf("%s", p->notes, 0);
2412 		log_printf("\n\n", 0);
2413 	}
2414 }
2415 
2416 /*
2417  * display all io devices
2418  */
2419 static int
2420 display_io_device_info(picl_nodehdl_t plafh)
2421 {
2422 	int	err;
2423 
2424 	err = gather_io_cards(plafh);
2425 	if (err != PICL_SUCCESS)
2426 		return (err);
2427 
2428 	logprintf_header(dgettext(TEXT_DOMAIN, "IO Devices"),
2429 	    DEFAULT_LINE_WIDTH);
2430 
2431 	picldiag_display_io_cards(io_card_list);
2432 
2433 	free_io_cards(io_card_list);
2434 
2435 	return (PICL_SUCCESS);
2436 }
2437 
2438 /*
2439  * print fan device information
2440  */
2441 static int
2442 logprintf_fan_info(picl_nodehdl_t fanh)
2443 {
2444 	int		err;
2445 	char		*label;
2446 	char		*unit;
2447 	int64_t		speed;
2448 	int64_t		min_speed;
2449 	picl_nodehdl_t	fruph;
2450 
2451 	err = picldiag_get_fru_parent(fanh, &fruph);
2452 	if (err != PICL_SUCCESS)
2453 		return (err);
2454 
2455 	err = picldiag_get_combined_label(fruph, &label, 14);
2456 	if (err != PICL_SUCCESS)
2457 		return (err);
2458 
2459 	log_printf("%-14s ", label);
2460 	free(label);
2461 
2462 	err = picldiag_get_label(fanh, &label);
2463 	if (err == PICL_SUCCESS) {
2464 		log_printf("%-14s  ", label);
2465 		free(label);
2466 	} else if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
2467 		log_printf("  -           ");
2468 	} else
2469 		return (err);
2470 
2471 	speed = picldiag_get_uint_propval(fanh, PICL_PROP_FAN_SPEED, &err);
2472 	if (err == PICL_SUCCESS) {
2473 		min_speed = picldiag_get_uint_propval(fanh,
2474 		    PICL_PROP_LOW_WARNING_THRESHOLD, &err);
2475 		if (err != PICL_SUCCESS)
2476 			min_speed = 1;
2477 		if (speed < min_speed) {
2478 			log_printf("failed (%lld", speed);
2479 			err = picldiag_get_string_propval(fanh,
2480 			    PICL_PROP_FAN_SPEED_UNIT, &unit);
2481 			if (err == PICL_SUCCESS) {
2482 				log_printf("%s", unit);
2483 				free(unit);
2484 			}
2485 			log_printf(")");
2486 		} else {
2487 			log_printf("okay");
2488 		}
2489 	} else {
2490 		err = picldiag_get_string_propval(fanh,
2491 		    PICL_PROP_FAN_SPEED_UNIT, &unit);
2492 		if (err == PICL_SUCCESS) {
2493 			log_printf("%-12s ", unit);
2494 			free(unit);
2495 		}
2496 	}
2497 
2498 	log_printf("\n");
2499 	return (PICL_SUCCESS);
2500 }
2501 
2502 static int
2503 fan_callback(picl_nodehdl_t fanh, void *arg)
2504 {
2505 	int	*countp = arg;
2506 	int		err;
2507 
2508 	if (*countp == 0) {
2509 		log_printf(dgettext(TEXT_DOMAIN, "Fan Status:\n"));
2510 		log_printf("---------------------------------------\n");
2511 		log_printf("Location       Sensor          Status          \n");
2512 		log_printf("---------------------------------------\n");
2513 	}
2514 	*countp += 1;
2515 	err = logprintf_fan_info(fanh);
2516 	if (err == PICL_SUCCESS)
2517 		return (PICL_WALK_CONTINUE);
2518 	return (err);
2519 }
2520 
2521 /*
2522  * callback function search children to find fan device and print its speed
2523  */
2524 static int
2525 display_fan_speed(picl_nodehdl_t plafh)
2526 {
2527 	int		err;
2528 	int		print_header;
2529 
2530 	print_header = 0;
2531 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_FAN,
2532 	    &print_header, fan_callback);
2533 	return (err);
2534 }
2535 
2536 /*
2537  * print temperature sensor information
2538  */
2539 static int
2540 logprintf_temp_info(picl_nodehdl_t temph)
2541 {
2542 	int		err;
2543 	char		*label;
2544 	int64_t		temperature;
2545 	int64_t		threshold;
2546 	picl_nodehdl_t	fruph;
2547 	char		*status = "unknown";
2548 	int		got_temp = 0;
2549 
2550 	err = picldiag_get_fru_parent(temph, &fruph);
2551 	if (err != PICL_SUCCESS)
2552 		return (err);
2553 
2554 	err = picldiag_get_combined_label(fruph, &label, 14);
2555 	if (err != PICL_SUCCESS)
2556 		return (err);
2557 
2558 	log_printf("%-14s ", label);
2559 	free(label);
2560 
2561 	err = picldiag_get_label(temph, &label);
2562 	if (err != PICL_SUCCESS)
2563 		return (err);
2564 	log_printf("%-14s ", label);
2565 	free(label);
2566 
2567 	temperature = picldiag_get_int_propval(temph, PICL_PROP_TEMPERATURE,
2568 	    &err);
2569 	if (err == PICL_SUCCESS) {
2570 		got_temp = 1;
2571 		status = "okay";
2572 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2573 		return (err);
2574 	}
2575 
2576 	threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_WARNING,
2577 	    &err);
2578 	if (err == PICL_SUCCESS) {
2579 		if (got_temp && temperature < threshold)
2580 			status = "warning";
2581 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2582 		return (err);
2583 	}
2584 
2585 	threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_SHUTDOWN,
2586 	    &err);
2587 	if (err == PICL_SUCCESS) {
2588 		if (got_temp && temperature < threshold)
2589 			status = "failed";
2590 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2591 		return (err);
2592 	}
2593 
2594 	threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_WARNING,
2595 	    &err);
2596 	if (err == PICL_SUCCESS) {
2597 		if (got_temp && temperature > threshold)
2598 			status = "warning";
2599 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2600 		return (err);
2601 	}
2602 
2603 	threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_SHUTDOWN,
2604 	    &err);
2605 	if (err == PICL_SUCCESS) {
2606 		if (got_temp && temperature > threshold)
2607 			status = "failed";
2608 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2609 		return (err);
2610 	}
2611 
2612 	err = picldiag_get_string_propval(temph, PICL_PROP_CONDITION, &status);
2613 	if (err == PICL_SUCCESS) {
2614 		log_printf("%s", status);
2615 		free(status);
2616 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2617 		return (err);
2618 	} else {
2619 		log_printf("%s ", status);
2620 		if (strcmp(status, "failed") == 0 ||
2621 		    strcmp(status, "warning") == 0)
2622 			log_printf("(%.2lldC)", temperature);
2623 	}
2624 
2625 	log_printf("\n");
2626 	return (PICL_SUCCESS);
2627 }
2628 
2629 static int
2630 temp_callback(picl_nodehdl_t temph, void *arg)
2631 {
2632 	int		err;
2633 	int	*countp = arg;
2634 
2635 	if (*countp == 0) {
2636 		log_printf("\n");
2637 		log_printf("---------------------------------------\n");
2638 		log_printf(dgettext(TEXT_DOMAIN, "Temperature sensors:\n"));
2639 		log_printf("------------------------------------\n");
2640 		log_printf("Location       Sensor         Status\n");
2641 		log_printf("------------------------------------\n");
2642 	}
2643 	*countp += 1;
2644 	err = logprintf_temp_info(temph);
2645 	if (err == PICL_SUCCESS)
2646 		return (PICL_WALK_CONTINUE);
2647 	return (err);
2648 }
2649 
2650 /*
2651  * callback function search children to find temp sensors and print the temp
2652  */
2653 /* ARGSUSED */
2654 static int
2655 display_temp(picl_nodehdl_t plafh)
2656 {
2657 	int		err;
2658 	int		print_header;
2659 
2660 	print_header = 0;
2661 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_SENSOR,
2662 	    &print_header, temp_callback);
2663 	if (err != PICL_SUCCESS)
2664 		return (err);
2665 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_INDICATOR,
2666 	    &print_header, temp_callback);
2667 	return (err);
2668 }
2669 
2670 /*
2671  * print current sensor information
2672  */
2673 static int
2674 logprintf_current_info(picl_nodehdl_t currenth)
2675 {
2676 	int		err;
2677 	char		*label;
2678 	float		current;
2679 	float		threshold;
2680 	picl_nodehdl_t	fruph;
2681 	char		*status = "unknown";
2682 	int		got_current = 0;
2683 
2684 	err = picldiag_get_fru_parent(currenth, &fruph);
2685 	if (err != PICL_SUCCESS)
2686 		return (err);
2687 
2688 	err = picldiag_get_combined_label(fruph, &label, 10);
2689 	if (err != PICL_SUCCESS)
2690 		return (err);
2691 
2692 	log_printf("%-10s ", label);
2693 	free(label);
2694 
2695 	err = picldiag_get_label(currenth, &label);
2696 	if (err != PICL_SUCCESS)
2697 		return (err);
2698 	log_printf("%-10s  ", label);
2699 	free(label);
2700 
2701 	current = picldiag_get_float_propval(currenth, PICL_PROP_CURRENT, &err);
2702 	if (err == PICL_SUCCESS) {
2703 		status = "okay";
2704 		got_current = 1;
2705 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2706 		return (err);
2707 	}
2708 
2709 	threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_WARNING,
2710 	    &err);
2711 	if (err == PICL_SUCCESS) {
2712 		if (got_current && current < threshold)
2713 			status = "warning";
2714 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2715 		return (err);
2716 	}
2717 
2718 	threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_SHUTDOWN,
2719 	    &err);
2720 	if (err == PICL_SUCCESS) {
2721 		if (got_current && current < threshold)
2722 			status = "failed";
2723 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2724 		return (err);
2725 	}
2726 
2727 	threshold = picldiag_get_float_propval(currenth, PICL_PROP_HIGH_WARNING,
2728 	    &err);
2729 	if (err == PICL_SUCCESS) {
2730 		if (got_current && current > threshold)
2731 			status = "warning";
2732 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2733 		return (err);
2734 	}
2735 
2736 	threshold = picldiag_get_float_propval(currenth,
2737 	    PICL_PROP_HIGH_SHUTDOWN, &err);
2738 	if (err == PICL_SUCCESS) {
2739 		if (got_current && current > threshold)
2740 			status = "failed";
2741 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2742 		return (err);
2743 	}
2744 
2745 	err = picldiag_get_string_propval(currenth,
2746 	    PICL_PROP_CONDITION, &status);
2747 	if (err == PICL_SUCCESS) {
2748 		log_printf(" %s", status);
2749 		free(status);
2750 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2751 		return (err);
2752 	} else {
2753 		log_printf("%s ", status);
2754 		if (strcmp(status, "failed") == 0 ||
2755 		    strcmp(status, "warning") == 0)
2756 			log_printf("(%.2fA)", current);
2757 	}
2758 
2759 	log_printf("\n");
2760 	return (PICL_SUCCESS);
2761 }
2762 
2763 static int
2764 current_callback(picl_nodehdl_t currh, void *arg)
2765 {
2766 	int		err;
2767 	int	*countp = arg;
2768 
2769 	if (*countp == 0) {
2770 		log_printf("------------------------------------\n");
2771 		log_printf(dgettext(TEXT_DOMAIN, "Current sensors:\n"));
2772 		log_printf("------------------------------\n");
2773 		log_printf("Location  Sensor        Status\n");
2774 		log_printf("------------------------------\n");
2775 	}
2776 	*countp += 1;
2777 	err = logprintf_current_info(currh);
2778 	if (err == PICL_SUCCESS)
2779 		return (PICL_WALK_CONTINUE);
2780 	return (err);
2781 }
2782 
2783 /*
2784  * callback function search children to find curr sensors and print the curr
2785  */
2786 /* ARGSUSED */
2787 static int
2788 display_current(picl_nodehdl_t plafh)
2789 {
2790 	int		err;
2791 	int		print_header;
2792 
2793 	print_header = 0;
2794 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_SENSOR,
2795 	    &print_header, current_callback);
2796 	if (err != PICL_SUCCESS)
2797 		return (err);
2798 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_INDICATOR,
2799 	    &print_header, current_callback);
2800 	return (err);
2801 }
2802 
2803 /*
2804  * print voltage sensor information
2805  */
2806 static int
2807 logprintf_voltage_info(picl_nodehdl_t voltageh)
2808 {
2809 	int		err;
2810 	char		*label;
2811 	float		voltage;
2812 	float		threshold;
2813 	picl_nodehdl_t	fruph;
2814 	char		*status = "unknown";
2815 	int		got_voltage = 0;
2816 
2817 	err = picldiag_get_fru_parent(voltageh, &fruph);
2818 	if (err != PICL_SUCCESS)
2819 		return (err);
2820 
2821 	err = picldiag_get_combined_label(fruph, &label, 10);
2822 	if (err != PICL_SUCCESS)
2823 		return (err);
2824 
2825 	log_printf("%-10s ", label);
2826 	free(label);
2827 
2828 	err = picldiag_get_label(voltageh, &label);
2829 	if (err != PICL_SUCCESS)
2830 		return (err);
2831 	log_printf("%-12s  ", label);
2832 	free(label);
2833 
2834 	voltage = picldiag_get_float_propval(voltageh, PICL_PROP_VOLTAGE, &err);
2835 	if (err == PICL_SUCCESS) {
2836 		status = "okay";
2837 		got_voltage = 1;
2838 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2839 		return (err);
2840 	}
2841 
2842 	threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_WARNING,
2843 	    &err);
2844 	if (err == PICL_SUCCESS) {
2845 		if (got_voltage && voltage < threshold)
2846 			status = "warning";
2847 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2848 		return (err);
2849 	}
2850 
2851 	threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_SHUTDOWN,
2852 	    &err);
2853 	if (err == PICL_SUCCESS) {
2854 		if (got_voltage && voltage < threshold)
2855 			status = "failed";
2856 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2857 		return (err);
2858 	}
2859 
2860 	threshold = picldiag_get_float_propval(voltageh, PICL_PROP_HIGH_WARNING,
2861 	    &err);
2862 	if (err == PICL_SUCCESS) {
2863 		if (got_voltage && voltage > threshold)
2864 			status = "warning";
2865 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2866 		return (err);
2867 	}
2868 
2869 	threshold = picldiag_get_float_propval(voltageh,
2870 	    PICL_PROP_HIGH_SHUTDOWN, &err);
2871 	if (err == PICL_SUCCESS) {
2872 		if (got_voltage && voltage > threshold)
2873 			status = "failed";
2874 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2875 		return (err);
2876 	}
2877 
2878 	err = picldiag_get_string_propval(voltageh,
2879 	    PICL_PROP_CONDITION, &status);
2880 	if (err == PICL_SUCCESS) {
2881 		log_printf("%s", status);
2882 		free(status);
2883 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
2884 		return (err);
2885 	} else {
2886 		log_printf("%s ", status);
2887 		if (strcmp(status, "warning") == 0 ||
2888 		    strcmp(status, "failed") == 0)
2889 			log_printf("(%.2fV)", voltage);
2890 	}
2891 
2892 	log_printf("\n");
2893 	return (PICL_SUCCESS);
2894 }
2895 
2896 static int
2897 voltage_callback(picl_nodehdl_t voltageh, void *arg)
2898 {
2899 	int	*countp = arg;
2900 	int		err;
2901 
2902 	if (*countp == 0) {
2903 		log_printf("--------------------------------\n");
2904 		log_printf(dgettext(TEXT_DOMAIN, "Voltage sensors:\n"));
2905 		log_printf("-------------------------------\n");
2906 		log_printf("Location   Sensor        Status\n");
2907 		log_printf("-------------------------------\n");
2908 	}
2909 	*countp += 1;
2910 	err = logprintf_voltage_info(voltageh);
2911 	if (err == PICL_SUCCESS)
2912 		return (PICL_WALK_CONTINUE);
2913 	return (err);
2914 }
2915 
2916 /*
2917  * callback function search children to find voltage sensors and print voltage
2918  */
2919 /* ARGSUSED */
2920 static int
2921 display_voltage(picl_nodehdl_t plafh)
2922 {
2923 	int		err;
2924 	int		print_header;
2925 
2926 	print_header = 0;
2927 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_SENSOR,
2928 	    &print_header, voltage_callback);
2929 	if (err != PICL_SUCCESS)
2930 		return (err);
2931 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_INDICATOR,
2932 	    &print_header, voltage_callback);
2933 	return (err);
2934 }
2935 
2936 /*
2937  * print led device information
2938  */
2939 static int
2940 logprintf_led_info(picl_nodehdl_t ledh)
2941 {
2942 	int		err;
2943 	char		*label;
2944 	char		*state;
2945 	char		*color;
2946 	picl_nodehdl_t  fruph;
2947 
2948 	err = picldiag_get_fru_parent(ledh, &fruph);
2949 	if (err != PICL_SUCCESS)
2950 		return (err);
2951 
2952 	err = picldiag_get_combined_label(fruph, &label, 10);
2953 	if (err != PICL_SUCCESS) {
2954 		log_printf("      -    ", label);
2955 	} else {
2956 		log_printf("%-10s ", label);
2957 		free(label);
2958 	}
2959 
2960 	err = picldiag_get_label(ledh, &label);
2961 	if (err != PICL_SUCCESS)
2962 		return (err);
2963 	log_printf("%-20s  ", label);
2964 	free(label);
2965 
2966 	err = picldiag_get_string_propval(ledh, PICL_PROP_STATE, &state);
2967 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
2968 		log_printf("     -     ");
2969 	} else if (err != PICL_SUCCESS) {
2970 		return (err);
2971 	} else {
2972 		log_printf("%-10s  ", state);
2973 		free(state);
2974 	}
2975 
2976 	err = picldiag_get_string_propval(ledh, PICL_PROP_COLOR, &color);
2977 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
2978 		log_printf("\n");
2979 	} else if (err != PICL_SUCCESS) {
2980 		return (err);
2981 	} else {
2982 		log_printf("%-16s\n", color);
2983 		free(color);
2984 	}
2985 
2986 	return (PICL_SUCCESS);
2987 }
2988 
2989 static int
2990 led_callback(picl_nodehdl_t ledh, void *arg)
2991 {
2992 	int		*countp = arg;
2993 	int		err;
2994 
2995 	if (*countp == 0) {
2996 
2997 		log_printf("--------------------------------------"
2998 		    "------------\n");
2999 		log_printf(dgettext(TEXT_DOMAIN, "Led State:\n"));
3000 		log_printf("--------------------------------------"
3001 		    "------------\n");
3002 		log_printf("Location   Led                   State"
3003 		    "       Color\n");
3004 		log_printf("--------------------------------------"
3005 		    "------------\n");
3006 	}
3007 	*countp += 1;
3008 	err = logprintf_led_info(ledh);
3009 	if (err == PICL_SUCCESS)
3010 		return (PICL_WALK_CONTINUE);
3011 	return (err);
3012 }
3013 
3014 /*
3015  * callback function search children to find led devices and print status
3016  */
3017 /* ARGSUSED */
3018 static int
3019 display_led_status(picl_nodehdl_t plafh)
3020 {
3021 	int		print_header;
3022 
3023 	print_header = 0;
3024 	picl_walk_tree_by_class(plafh, PICL_CLASS_LED,
3025 	    &print_header, led_callback);
3026 	return (PICL_SUCCESS);
3027 }
3028 
3029 /*
3030  * print keyswitch device information
3031  */
3032 static int
3033 logprintf_keyswitch_info(picl_nodehdl_t keyswitchh, picl_nodehdl_t fruph)
3034 {
3035 	int		err;
3036 	char		*label;
3037 	char		*state;
3038 
3039 	err = picldiag_get_combined_label(fruph, &label, 10);
3040 	if (err != PICL_SUCCESS) {
3041 		log_printf("%-14s", "     -");
3042 	} else {
3043 		log_printf("%-14s ", label);
3044 		free(label);
3045 	}
3046 
3047 	err = picldiag_get_label(keyswitchh, &label);
3048 	if (err != PICL_SUCCESS)
3049 		return (err);
3050 	log_printf("%-11s ", label);
3051 	free(label);
3052 
3053 	err = picldiag_get_string_propval(keyswitchh, PICL_PROP_STATE, &state);
3054 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
3055 		log_printf("     -\n");
3056 	} else if (err != PICL_SUCCESS) {
3057 		return (err);
3058 	} else {
3059 		log_printf("%s\n", state);
3060 		free(state);
3061 	}
3062 
3063 	return (PICL_SUCCESS);
3064 }
3065 
3066 static int
3067 keyswitch_callback(picl_nodehdl_t keyswitchh, void *arg)
3068 {
3069 	int		*countp = arg;
3070 	int		err;
3071 	picl_nodehdl_t	fruph;
3072 
3073 	/*
3074 	 * Tamale simulates a key-switch on ENxS. So the presence of a
3075 	 * node of class keyswitch is not sufficient. If it has a fru parent
3076 	 * or location parent, then believe it.
3077 	 */
3078 	err = picl_get_propval_by_name(keyswitchh, PICL_REFPROP_FRU_PARENT,
3079 	    &fruph, sizeof (fruph));
3080 	if (err == PICL_PROPNOTFOUND) {
3081 		err = picl_get_propval_by_name(keyswitchh,
3082 		    PICL_REFPROP_LOC_PARENT, &fruph, sizeof (fruph));
3083 	}
3084 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE)
3085 		return (PICL_WALK_CONTINUE);
3086 	if (err != PICL_SUCCESS)
3087 		return (err);
3088 
3089 	if (*countp == 0) {
3090 		log_printf("-----------------------------------------\n");
3091 		log_printf(dgettext(TEXT_DOMAIN, "Keyswitch:\n"));
3092 		log_printf("-----------------------------------------\n");
3093 		log_printf(dgettext(TEXT_DOMAIN,
3094 		    "Location       Keyswitch   State\n"));
3095 		log_printf("-----------------------------------------\n");
3096 	}
3097 	*countp += 1;
3098 	err = logprintf_keyswitch_info(keyswitchh, fruph);
3099 	if (err == PICL_SUCCESS)
3100 		return (PICL_WALK_CONTINUE);
3101 	return (err);
3102 }
3103 
3104 /*
3105  * search children to find keyswitch device(s) and print status
3106  */
3107 /* ARGSUSED */
3108 static int
3109 display_keyswitch(picl_nodehdl_t plafh)
3110 {
3111 	int		print_header = 0;
3112 
3113 	picl_walk_tree_by_class(plafh, PICL_CLASS_KEYSWITCH,
3114 	    &print_header, keyswitch_callback);
3115 	return (PICL_SUCCESS);
3116 }
3117 
3118 /*
3119  * display environment status
3120  */
3121 static int
3122 display_envctrl_status(picl_nodehdl_t plafh)
3123 {
3124 	logprintf_header(dgettext(TEXT_DOMAIN, "Environmental Status"),
3125 	    DEFAULT_LINE_WIDTH);
3126 
3127 	display_fan_speed(plafh);
3128 	display_temp(plafh);
3129 	display_current(plafh);
3130 	display_voltage(plafh);
3131 	display_keyswitch(plafh);
3132 	display_led_status(plafh);
3133 
3134 	return (PICL_SUCCESS);
3135 }
3136 
3137 /*
3138  * print fru operational status
3139  */
3140 static int
3141 logprintf_fru_oper_status(picl_nodehdl_t fruh, int *countp)
3142 {
3143 	int		err;
3144 	char		*label;
3145 	char		*status;
3146 
3147 	err = picldiag_get_combined_label(fruh, &label, 15);
3148 	if (err != PICL_SUCCESS)
3149 		return (PICL_WALK_CONTINUE);
3150 
3151 	err = picldiag_get_string_propval(fruh,
3152 	    PICL_PROP_OPERATIONAL_STATUS, &status);
3153 	if (err == PICL_SUCCESS) {
3154 		if (*countp == 0) {
3155 			logprintf_header(dgettext(TEXT_DOMAIN,
3156 			    "FRU Operational Status"),
3157 			    DEFAULT_LINE_WIDTH);
3158 			log_printf("-------------------------\n");
3159 			log_printf(dgettext(TEXT_DOMAIN,
3160 			    "Fru Operational Status:\n"));
3161 			log_printf("-------------------------\n");
3162 			log_printf("Location        Status   \n");
3163 			log_printf("-------------------------\n");
3164 		}
3165 		*countp += 1;
3166 		log_printf("%-15s ", label);
3167 		free(label);
3168 		log_printf("%s\n", status);
3169 		free(status);
3170 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
3171 		free(label);
3172 		return (err);
3173 	} else {
3174 		free(label);
3175 	}
3176 	return (PICL_WALK_CONTINUE);
3177 }
3178 
3179 static int
3180 fru_oper_status_callback(picl_nodehdl_t fruh, void *arg)
3181 {
3182 	int err;
3183 
3184 	err = logprintf_fru_oper_status(fruh, (int *)arg);
3185 	return (err);
3186 }
3187 
3188 /*
3189  * display fru operational status
3190  */
3191 static int
3192 display_fru_oper_status(picl_nodehdl_t frutreeh)
3193 {
3194 	int		print_header;
3195 
3196 	print_header = 0;
3197 	picl_walk_tree_by_class(frutreeh, PICL_CLASS_FRU,
3198 	    &print_header, fru_oper_status_callback);
3199 	return (PICL_SUCCESS);
3200 }
3201 
3202 /*
3203  * check if the node having the version prop
3204  * If yes, print its nodename and version
3205  */
3206 /* ARGSUSED */
3207 static int
3208 asicrev_callback(picl_nodehdl_t nodeh, void *arg)
3209 {
3210 	uint32_t	version;
3211 	char		*name;
3212 	char		*model;
3213 	char		*status;
3214 	int		err;
3215 
3216 	version = picldiag_get_uint_propval(nodeh, OBP_PROP_VERSION_NUM,
3217 	    &err);
3218 	if (err == PICL_PROPNOTFOUND)
3219 		return (PICL_WALK_CONTINUE);
3220 	else if (err != PICL_SUCCESS)
3221 		return (err);
3222 
3223 	/* devfs-path */
3224 	err =  picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, &name);
3225 	if (err == PICL_PROPNOTFOUND)
3226 		name = NULL;
3227 	else if (err != PICL_SUCCESS)
3228 		return (err);
3229 
3230 	/* model */
3231 	err =  picldiag_get_string_propval(nodeh, PICL_PROP_BINDING_NAME,
3232 	    &model);
3233 	if (err == PICL_PROPNOTFOUND)
3234 		model = NULL;
3235 	else if (err != PICL_SUCCESS)
3236 		return (err);
3237 
3238 	/* status */
3239 	err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, &status);
3240 	if (err == PICL_PROPNOTFOUND)
3241 		status = NULL;
3242 	else if (err != PICL_SUCCESS)
3243 		return (err);
3244 
3245 	/*
3246 	 * Display the data
3247 	 */
3248 
3249 	/* name */
3250 	if (name != NULL) {
3251 		log_printf("%-22s ", name);
3252 		free(name);
3253 	} else
3254 		log_printf("%-22s ", "unknown");
3255 	/* model */
3256 	if (model != NULL) {
3257 		log_printf("%-15s  ", model);
3258 		free(model);
3259 	} else
3260 		log_printf("%-15s  ", "unknown");
3261 	/* status */
3262 	if (status == NULL)
3263 		log_printf("%-15s  ", "okay");
3264 	else {
3265 		log_printf("%-15s  ", status);
3266 		free(status);
3267 	}
3268 	/* revision */
3269 	log_printf("  %-4d\n",	version);
3270 
3271 	return (PICL_WALK_CONTINUE);
3272 }
3273 
3274 /*
3275  * traverse the tree to display asic revision id for ebus
3276  */
3277 /* ARGSUSED */
3278 static int
3279 ebus_callback(picl_nodehdl_t ebush, void *arg)
3280 {
3281 	uint32_t	id;
3282 	char		*name;
3283 	int		err;
3284 	char		*model;
3285 	char		*status;
3286 
3287 	id = picldiag_get_uint_propval(ebush, OBP_PROP_REVISION_ID, &err);
3288 	if (err == PICL_PROPNOTFOUND)
3289 		return (PICL_WALK_CONTINUE);
3290 	else if (err != PICL_SUCCESS)
3291 		return (err);
3292 
3293 	/* devfs-path */
3294 	err =  picldiag_get_string_propval(ebush, PICL_PROP_DEVFS_PATH, &name);
3295 	if (err == PICL_PROPNOTFOUND)
3296 		name = NULL;
3297 	else if (err != PICL_SUCCESS)
3298 		return (err);
3299 
3300 	/* model */
3301 	err =  picldiag_get_string_propval(ebush, PICL_PROP_BINDING_NAME,
3302 	    &model);
3303 	if (err == PICL_PROPNOTFOUND)
3304 		model = NULL;
3305 	else if (err != PICL_SUCCESS)
3306 		return (err);
3307 
3308 	/* status */
3309 	err = picldiag_get_string_propval(ebush, OBP_PROP_STATUS, &status);
3310 	if (err == PICL_PROPNOTFOUND)
3311 		status = NULL;
3312 	else if (err != PICL_SUCCESS)
3313 		return (err);
3314 
3315 	/*
3316 	 * Display the data
3317 	 */
3318 
3319 	/* name */
3320 	if (name != NULL) {
3321 		log_printf("%-22s ", name);
3322 		free(name);
3323 	} else
3324 		log_printf("%-22s ", "unknown");
3325 	/* model */
3326 	if (model != NULL) {
3327 		log_printf("%-15s  ", model);
3328 		free(model);
3329 	} else
3330 		log_printf("%-15s  ", "unknown");
3331 	/* status */
3332 	if (status == NULL)
3333 		log_printf("%-15s  ", "okay");
3334 	else {
3335 		log_printf("%-15s  ", status);
3336 		free(status);
3337 	}
3338 	/* revision */
3339 	log_printf("  %-4d\n",	id);
3340 
3341 	return (PICL_WALK_CONTINUE);
3342 }
3343 
3344 /*
3345  * display asic revision id
3346  */
3347 static int
3348 display_hw_revisions(picl_nodehdl_t plafh)
3349 {
3350 	int	err;
3351 
3352 	/* Print the header */
3353 	logprintf_header(dgettext(TEXT_DOMAIN, "HW Revisions"),
3354 	    DEFAULT_LINE_WIDTH);
3355 
3356 	log_printf("ASIC Revisions:\n");
3357 	log_printf("-----------------------------");
3358 	log_printf("--------------------------------------\n");
3359 	log_printf("Path                   Device");
3360 	log_printf("           Status             Revision\n");
3361 	log_printf("-----------------------------");
3362 	log_printf("--------------------------------------\n");
3363 
3364 	err = picl_walk_tree_by_class(plafh, NULL, NULL, asicrev_callback);
3365 	if (err != PICL_SUCCESS)
3366 		return (err);
3367 
3368 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_EBUS,
3369 	    NULL, ebus_callback);
3370 	if (err != PICL_SUCCESS)
3371 		return (err);
3372 
3373 	log_printf("\n");
3374 
3375 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_DISPLAY,
3376 	    NULL, ffbconfig_callback);
3377 	return (err);
3378 }
3379 
3380 /*
3381  * find the options node and its powerfail_time prop
3382  * If found, display the list of latest powerfail.
3383  */
3384 /* ARGSUSED */
3385 static int
3386 options_callback(picl_nodehdl_t nodeh, void *arg)
3387 {
3388 	time_t		value;
3389 	char		*failtime;
3390 	int		err;
3391 
3392 	err = picldiag_get_string_propval(nodeh, PROP_POWERFAIL_TIME,
3393 	    &failtime);
3394 	if (err == PICL_PROPNOTFOUND)
3395 		return (PICL_WALK_TERMINATE);
3396 	else if (err != PICL_SUCCESS)
3397 		return (err);
3398 
3399 	value = (time_t)atoi(failtime);
3400 	free(failtime);
3401 	if (value == 0)
3402 		return (PICL_WALK_TERMINATE);
3403 
3404 	log_printf(dgettext(TEXT_DOMAIN, "Most recent AC Power Failure:\n"));
3405 	log_printf("=============================\n");
3406 	log_printf("%s", ctime(&value));
3407 	log_printf("\n");
3408 	return (PICL_WALK_TERMINATE);
3409 }
3410 
3411 /*
3412  * display the OBP and POST prom revisions
3413  */
3414 /* ARGSUSED */
3415 static int
3416 flashprom_callback(picl_nodehdl_t flashpromh, void *arg)
3417 {
3418 	picl_prophdl_t	proph;
3419 	picl_prophdl_t	tblh;
3420 	picl_prophdl_t	rowproph;
3421 	picl_propinfo_t	pinfo;
3422 	char		*prom_version = NULL;
3423 	char		*obp_version = NULL;
3424 	int		err;
3425 
3426 	err = picl_get_propinfo_by_name(flashpromh, OBP_PROP_VERSION,
3427 	    &pinfo, &proph);
3428 	if (err == PICL_PROPNOTFOUND)
3429 		return (PICL_WALK_TERMINATE);
3430 	else if (err != PICL_SUCCESS)
3431 		return (err);
3432 
3433 	log_printf(dgettext(TEXT_DOMAIN, "System PROM revisions:\n"));
3434 	log_printf("----------------------\n");
3435 
3436 	/*
3437 	 * If it's a table prop, the first element is OBP revision
3438 	 * The second one is POST revision.
3439 	 * If it's a charstring prop, the value will be only OBP revision
3440 	 */
3441 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
3442 		prom_version = alloca(pinfo.size);
3443 		if (prom_version == NULL)
3444 			return (PICL_FAILURE);
3445 		err = picl_get_propval(proph, prom_version, pinfo.size);
3446 		if (err != PICL_SUCCESS)
3447 			return (err);
3448 		log_printf("%s\n", prom_version);
3449 	}
3450 
3451 	if (pinfo.type != PICL_PTYPE_TABLE)	/* not supported type */
3452 		return (PICL_WALK_TERMINATE);
3453 
3454 	err = picl_get_propval(proph, &tblh, pinfo.size);
3455 	if (err != PICL_SUCCESS)
3456 		return (err);
3457 
3458 	err = picl_get_next_by_row(tblh, &rowproph);
3459 	if (err == PICL_SUCCESS) {
3460 		/* get first row */
3461 		err = picl_get_propinfo(rowproph, &pinfo);
3462 		if (err != PICL_SUCCESS)
3463 		    return (err);
3464 
3465 		prom_version = alloca(pinfo.size);
3466 		if (prom_version == NULL)
3467 			return (PICL_FAILURE);
3468 
3469 		err = picl_get_propval(rowproph, prom_version, pinfo.size);
3470 		if (err != PICL_SUCCESS)
3471 			return (err);
3472 		log_printf("%s\n", prom_version);
3473 
3474 		/* get second row */
3475 		err = picl_get_next_by_col(rowproph, &rowproph);
3476 		if (err == PICL_SUCCESS) {
3477 			err = picl_get_propinfo(rowproph, &pinfo);
3478 			if (err != PICL_SUCCESS)
3479 				return (err);
3480 
3481 			obp_version = alloca(pinfo.size);
3482 			if (obp_version == NULL)
3483 				return (PICL_FAILURE);
3484 			err = picl_get_propval(rowproph, obp_version,
3485 			    pinfo.size);
3486 			if (err != PICL_SUCCESS)
3487 				return (err);
3488 			log_printf("%s\n", obp_version);
3489 		}
3490 	}
3491 
3492 	return (PICL_WALK_TERMINATE);
3493 }
3494 
3495 static int
3496 display_system_info(int serrlog, int log_flag, picl_nodehdl_t rooth)
3497 {
3498 	int		err;
3499 	picl_nodehdl_t plafh;
3500 	picl_nodehdl_t frutreeh;
3501 
3502 	err = picldiag_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh);
3503 	if (err != PICL_SUCCESS)
3504 		return (err);
3505 
3506 	if (!log_flag) {
3507 		err = display_platform_banner(plafh);
3508 		if (err != PICL_SUCCESS)
3509 			return (err);
3510 
3511 		err = display_system_clock(plafh);
3512 		if (err != PICL_SUCCESS)
3513 			return (err);
3514 
3515 		err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY,
3516 		    PICL_CLASS_MEMORY, memory_callback);
3517 		if (err != PICL_SUCCESS)
3518 			return (err);
3519 
3520 		err = display_cpu_info(plafh);
3521 		if (err != PICL_SUCCESS)
3522 			return (err);
3523 
3524 		err = display_io_device_info(plafh);
3525 		if (err != PICL_SUCCESS)
3526 			return (err);
3527 
3528 		err = display_memory_config(plafh);
3529 		if (err != PICL_SUCCESS)
3530 			return (err);
3531 
3532 		err = display_usb_devices(plafh);
3533 		if (err != PICL_SUCCESS)
3534 			return (err);
3535 	}
3536 
3537 	if (serrlog) {
3538 		err = picl_walk_tree_by_class(rooth, PICL_CLASS_OPTIONS,
3539 		    NULL, options_callback);
3540 		if (err != PICL_SUCCESS)
3541 			return (err);
3542 
3543 		err = display_envctrl_status(plafh);
3544 		if (err != PICL_SUCCESS)
3545 			return (err);
3546 
3547 		err = picldiag_get_node_by_name(rooth, PICL_NODE_FRUTREE,
3548 		    &frutreeh);
3549 		if (err != PICL_SUCCESS)
3550 			return (err);
3551 
3552 		err = display_fru_oper_status(frutreeh);
3553 		if (err != PICL_SUCCESS)
3554 			return (err);
3555 
3556 		err = display_hw_revisions(plafh);
3557 		if (err != PICL_SUCCESS)
3558 			return (err);
3559 
3560 		err = picl_walk_tree_by_class(plafh, PICL_CLASS_FLASHPROM,
3561 		    NULL, flashprom_callback);
3562 		if (err != PICL_SUCCESS)
3563 			return (err);
3564 	}
3565 
3566 	return (PICL_SUCCESS);
3567 }
3568 
3569 /* ARGSUSED */
3570 int
3571 do_prominfo(int serrlog, char *pgname, int log_flag, int prt_flag)
3572 {
3573 	int		err;
3574 	char		*errstr;
3575 	int		done;
3576 	picl_nodehdl_t	rooth;
3577 
3578 	err = picl_initialize();
3579 	if (err != PICL_SUCCESS) {
3580 		fprintf(stderr, EM_INIT_FAIL, picl_strerror(err));
3581 		exit(1);
3582 	}
3583 
3584 	do {
3585 		done = 1;
3586 		err = picl_get_root(&rooth);
3587 		if (err != PICL_SUCCESS) {
3588 			fprintf(stderr, EM_GET_ROOT_FAIL, picl_strerror(err));
3589 			exit(1);
3590 		}
3591 
3592 		err = display_system_info(serrlog, log_flag, rooth);
3593 
3594 		if ((err == PICL_STALEHANDLE) || (err == PICL_INVALIDHANDLE))
3595 			done = 0;
3596 	} while (!done);
3597 
3598 	if (err != PICL_SUCCESS) {
3599 		errstr = picl_strerror(err);
3600 		fprintf(stderr, EM_PRTDIAG_FAIL);
3601 		fprintf(stderr, "%s\n", errstr? errstr : " ");
3602 	}
3603 
3604 	(void) picl_shutdown();
3605 
3606 	return (0);
3607 }
3608