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