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