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