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