103831d35Sstevel /*
203831d35Sstevel  * CDDL HEADER START
303831d35Sstevel  *
403831d35Sstevel  * The contents of this file are subject to the terms of the
5*2983dda7SMichael Bergknoff  * Common Development and Distribution License (the "License").
6*2983dda7SMichael Bergknoff  * You may not use this file except in compliance with the License.
703831d35Sstevel  *
803831d35Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
903831d35Sstevel  * or http://www.opensolaris.org/os/licensing.
1003831d35Sstevel  * See the License for the specific language governing permissions
1103831d35Sstevel  * and limitations under the License.
1203831d35Sstevel  *
1303831d35Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
1403831d35Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1503831d35Sstevel  * If applicable, add the following below this CDDL HEADER, with the
1603831d35Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
1703831d35Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
1803831d35Sstevel  *
1903831d35Sstevel  * CDDL HEADER END
2003831d35Sstevel  */
2103831d35Sstevel /*
22*2983dda7SMichael Bergknoff  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2303831d35Sstevel  */
2403831d35Sstevel 
2503831d35Sstevel #include <stdio.h>
2603831d35Sstevel #include <stdlib.h>
2703831d35Sstevel #include <string.h>
2803831d35Sstevel #include <alloca.h>
2903831d35Sstevel #include <errno.h>
3003831d35Sstevel #include <libintl.h>
3103831d35Sstevel #include <sys/utsname.h>
3203831d35Sstevel #include <sys/types.h>
3303831d35Sstevel #include <sys/stat.h>
3403831d35Sstevel #include <sys/openpromio.h>
3503831d35Sstevel #include <sys/ddi.h>
3603831d35Sstevel #include <syslog.h>
3703831d35Sstevel #include <fcntl.h>
3803831d35Sstevel #include <dirent.h>
3903831d35Sstevel #include <unistd.h>
4003831d35Sstevel #include <locale.h>
4103831d35Sstevel #include <picl.h>
4203831d35Sstevel #include "pdevinfo.h"
4303831d35Sstevel #include "display.h"
4403831d35Sstevel #include "display_sun4u.h"
4503831d35Sstevel #include "picldefs.h"
4603831d35Sstevel #include "libprtdiag.h"
4703831d35Sstevel 
4803831d35Sstevel #if !defined(TEXT_DOMAIN)
4903831d35Sstevel #define	TEXT_DOMAIN	"SYS_TEST"
5003831d35Sstevel #endif
5103831d35Sstevel 
5203831d35Sstevel #define	EM_INIT_FAIL		dgettext(TEXT_DOMAIN,\
5303831d35Sstevel 	"picl_initialize failed: %s\n")
5403831d35Sstevel #define	EM_GET_ROOT_FAIL	dgettext(TEXT_DOMAIN,\
5503831d35Sstevel 	"Getting root node failed: %s\n")
5603831d35Sstevel #define	EM_PRTDIAG_FAIL		dgettext(TEXT_DOMAIN, "Prtdiag failed!\n")
5703831d35Sstevel 
5803831d35Sstevel #define	SIGN_ON_MSG	dgettext(TEXT_DOMAIN,\
59*2983dda7SMichael Bergknoff 	"System Configuration: Oracle Corporation ")
6003831d35Sstevel #define	SYSCLK_FREQ_MSG	dgettext(TEXT_DOMAIN,\
6103831d35Sstevel 	"System clock frequency: %d MHZ\n")
6203831d35Sstevel #define	MEM_SIZE_MSG	dgettext(TEXT_DOMAIN, "Memory size: ")
6303831d35Sstevel 
6403831d35Sstevel #define	DEFAULT_BOARD_NUM	0
6503831d35Sstevel #define	DEFAULT_PORTID		0
6603831d35Sstevel #define	CLK_FREQ_66MHZ		66
6703831d35Sstevel #define	USB			-1
6803831d35Sstevel #define	HUB			-2
6903831d35Sstevel 
7003831d35Sstevel /* bus id */
7103831d35Sstevel #define	PCI_TYPE		1
7203831d35Sstevel 
7303831d35Sstevel /*
7403831d35Sstevel  * PICL classes
7503831d35Sstevel  */
7603831d35Sstevel #define	PICL_CLASS_OPTIONS		"options"
7703831d35Sstevel 
7803831d35Sstevel /*
7903831d35Sstevel  * Property names
8003831d35Sstevel  */
8103831d35Sstevel 
8203831d35Sstevel #define	OBP_PROP_REG			"reg"
8303831d35Sstevel #define	OBP_PROP_CLOCK_FREQ		"clock-frequency"
8403831d35Sstevel #define	OBP_PROP_BOARD_NUM		"board#"
8503831d35Sstevel #define	OBP_PROP_REVISION_ID		"revision-id"
8603831d35Sstevel #define	OBP_PROP_VERSION_NUM		"version#"
8703831d35Sstevel #define	OBP_PROP_BOARD_TYPE		"board_type"
8803831d35Sstevel #define	OBP_PROP_ECACHE_SIZE		"ecache-size"
8903831d35Sstevel #define	OBP_PROP_IMPLEMENTATION		"implementation#"
9003831d35Sstevel #define	OBP_PROP_MASK			"mask#"
9103831d35Sstevel #define	OBP_PROP_COMPATIBLE		"compatible"
9203831d35Sstevel #define	OBP_PROP_BANNER_NAME		"banner-name"
9303831d35Sstevel #define	OBP_PROP_MODEL			"model"
9403831d35Sstevel #define	OBP_PROP_66MHZ_CAPABLE		"66mhz-capable"
9503831d35Sstevel #define	OBP_PROP_FBC_REG_ID		"fbc_reg_id"
9603831d35Sstevel #define	OBP_PROP_VERSION		"version"
9703831d35Sstevel 
9803831d35Sstevel #define	PROP_POWERFAIL_TIME		"powerfail-time"
9903831d35Sstevel #define	PICL_PROP_LOW_WARNING_THRESHOLD	"LowWarningThreshold"
10003831d35Sstevel 
10103831d35Sstevel #define	DEFAULT_LINE_WIDTH		78
10203831d35Sstevel #define	HEADING_SYMBOL			"="
10303831d35Sstevel 
10403831d35Sstevel #define	SIZE_FIELD	11
10503831d35Sstevel #define	MAX_IWAYS			32
10603831d35Sstevel 
10703831d35Sstevel typedef struct bank_list {
10803831d35Sstevel 	picl_nodehdl_t		nodeh;
10903831d35Sstevel 	uint32_t		iway_count;
11003831d35Sstevel 	uint32_t		iway[MAX_IWAYS];
11103831d35Sstevel 	struct bank_list	*next;
11203831d35Sstevel } bank_list_t;
11303831d35Sstevel 
11403831d35Sstevel typedef struct {
11503831d35Sstevel 	uint64_t	base;
11603831d35Sstevel 	uint64_t	size;
11703831d35Sstevel 	int		ifactor;
11803831d35Sstevel 	int		bank_count;
11903831d35Sstevel } seg_info_t;
12003831d35Sstevel 
12103831d35Sstevel static struct io_card	*io_card_list = NULL; /* The head of the IO card list */
12203831d35Sstevel static bank_list_t	*mem_banks = NULL;
12303831d35Sstevel static	int		mem_xfersize;
12403831d35Sstevel static	int		no_xfer_size = 0;
12503831d35Sstevel 
12603831d35Sstevel static const char *io_device_table[] = {
12703831d35Sstevel 	"block",
12803831d35Sstevel 	"disk",
12903831d35Sstevel 	"cdrom",
13003831d35Sstevel 	"floppy",
13103831d35Sstevel 	"tape",
13203831d35Sstevel 	"network",
13303831d35Sstevel 	"display",
13403831d35Sstevel 	"serial",
13503831d35Sstevel 	"parallel",
13603831d35Sstevel 	"scsi",
13703831d35Sstevel 	"scsi-2",
13803831d35Sstevel 	"scsi-3",
13903831d35Sstevel 	"ide",
14003831d35Sstevel 	"fcal",
14103831d35Sstevel 	"keyboard",
14203831d35Sstevel 	"mouse",
14303831d35Sstevel 	"dma"
14403831d35Sstevel };
14503831d35Sstevel 
14603831d35Sstevel #define	NIODEVICE	(sizeof (io_device_table) / sizeof (io_device_table[0]))
14703831d35Sstevel 
14803831d35Sstevel static const char *bus_table[] = {
14903831d35Sstevel 	"ebus",
15003831d35Sstevel 	"isa",
15103831d35Sstevel 	"pmu"
15203831d35Sstevel };
15303831d35Sstevel 
15403831d35Sstevel #define	NBUS	(sizeof (bus_table) / sizeof (bus_table[0]))
15503831d35Sstevel 
15603831d35Sstevel /*
15703831d35Sstevel  * check if it is an IO deice
15803831d35Sstevel  *	return 1 if this is a io device; return 0 for else.
15903831d35Sstevel  */
16003831d35Sstevel static int
is_io_device(char * device_class)16103831d35Sstevel is_io_device(char *device_class)
16203831d35Sstevel {
16303831d35Sstevel 	int i;
16403831d35Sstevel 
16503831d35Sstevel 	for (i = 0; i < NIODEVICE; i++) {
166*2983dda7SMichael Bergknoff 		if (strcmp(device_class, io_device_table[i]) == 0)
167*2983dda7SMichael Bergknoff 			return (1);
16803831d35Sstevel 	}
16903831d35Sstevel 
17003831d35Sstevel 	return (0);
17103831d35Sstevel }
17203831d35Sstevel 
17303831d35Sstevel /*
17403831d35Sstevel  * check if it is a bus
17503831d35Sstevel  *	return	1 if this is a bus; return 0 for else.
17603831d35Sstevel  */
17703831d35Sstevel static int
is_bus(char * device_class)17803831d35Sstevel is_bus(char *device_class)
17903831d35Sstevel {
18003831d35Sstevel 	int i;
18103831d35Sstevel 
18203831d35Sstevel 	for (i = 0; i < NBUS; i++) {
183*2983dda7SMichael Bergknoff 		if (strcmp(device_class, bus_table[i]) == 0)
184*2983dda7SMichael Bergknoff 			return (1);
18503831d35Sstevel 	}
18603831d35Sstevel 
18703831d35Sstevel 	return (0);
18803831d35Sstevel }
18903831d35Sstevel 
19003831d35Sstevel /*
19103831d35Sstevel  * search children to get the node by the nodename
19203831d35Sstevel  *	return node handler in picl_nodehdl_t *nodeh
19303831d35Sstevel  */
19403831d35Sstevel static int
picldiag_get_node_by_name(picl_nodehdl_t rooth,char * name,picl_nodehdl_t * nodeh)19503831d35Sstevel picldiag_get_node_by_name(picl_nodehdl_t rooth, char *name,
19603831d35Sstevel     picl_nodehdl_t *nodeh)
19703831d35Sstevel {
19803831d35Sstevel 	picl_nodehdl_t	childh;
19903831d35Sstevel 	int		err;
20003831d35Sstevel 	char		*nodename;
20103831d35Sstevel 
20203831d35Sstevel 	nodename = alloca(strlen(name) + 1);
20303831d35Sstevel 	if (nodename == NULL)
20403831d35Sstevel 		return (PICL_FAILURE);
20503831d35Sstevel 
20603831d35Sstevel 	err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
20703831d35Sstevel 	    sizeof (picl_nodehdl_t));
20803831d35Sstevel 
20903831d35Sstevel 	while (err == PICL_SUCCESS) {
21003831d35Sstevel 		err = picl_get_propval_by_name(childh, PICL_PROP_NAME,
21103831d35Sstevel 		    nodename, (strlen(name) + 1));
21203831d35Sstevel 		if (err != PICL_SUCCESS) {
21303831d35Sstevel 			err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
214*2983dda7SMichael Bergknoff 			    &childh, sizeof (picl_nodehdl_t));
21503831d35Sstevel 			continue;
21603831d35Sstevel 		}
21703831d35Sstevel 
21803831d35Sstevel 		if (strcmp(nodename, name) == 0) {
21903831d35Sstevel 			*nodeh = childh;
22003831d35Sstevel 			return (PICL_SUCCESS);
22103831d35Sstevel 		}
22203831d35Sstevel 
22303831d35Sstevel 		err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
22403831d35Sstevel 		    &childh, sizeof (picl_nodehdl_t));
22503831d35Sstevel 	}
22603831d35Sstevel 
22703831d35Sstevel 	return (err);
22803831d35Sstevel }
22903831d35Sstevel 
23003831d35Sstevel /*
23103831d35Sstevel  * get the value by the property name of the string prop
23203831d35Sstevel  *	the value will be in outbuf
23303831d35Sstevel  * Caller must free the outbuf
23403831d35Sstevel  */
23503831d35Sstevel static int
picldiag_get_string_propval(picl_nodehdl_t modh,char * prop_name,char ** outbuf)23603831d35Sstevel picldiag_get_string_propval(picl_nodehdl_t modh, char *prop_name, char **outbuf)
23703831d35Sstevel {
23803831d35Sstevel 	int		err;
23903831d35Sstevel 	picl_prophdl_t	proph;
24003831d35Sstevel 	picl_propinfo_t	pinfo;
24103831d35Sstevel 	char		*prop_value;
24203831d35Sstevel 
24303831d35Sstevel 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
24403831d35Sstevel 	if (err != PICL_SUCCESS)
24503831d35Sstevel 		return (err);
24603831d35Sstevel 
24703831d35Sstevel 	/*
24803831d35Sstevel 	 * If it is not a string prop, return NULL
24903831d35Sstevel 	 */
25003831d35Sstevel 	if (pinfo.type != PICL_PTYPE_CHARSTRING)
251*2983dda7SMichael Bergknoff 		return (PICL_FAILURE);
25203831d35Sstevel 
25303831d35Sstevel 	prop_value = malloc(pinfo.size);
25403831d35Sstevel 	if (prop_value == NULL)
25503831d35Sstevel 		return (PICL_FAILURE);
25603831d35Sstevel 
25703831d35Sstevel 	err = picl_get_propval(proph, prop_value, pinfo.size);
25803831d35Sstevel 	if (err != PICL_SUCCESS) {
25903831d35Sstevel 		free(prop_value);
26003831d35Sstevel 		return (err);
26103831d35Sstevel 	}
26203831d35Sstevel 
26303831d35Sstevel 	*outbuf = prop_value;
26403831d35Sstevel 	return (PICL_SUCCESS);
26503831d35Sstevel }
26603831d35Sstevel 
26703831d35Sstevel 
26803831d35Sstevel /*
26903831d35Sstevel  * return the value as a signed integer
27003831d35Sstevel  */
27103831d35Sstevel 
27203831d35Sstevel static int64_t
picldiag_get_int_propval(picl_nodehdl_t modh,char * prop_name,int * ret)27303831d35Sstevel picldiag_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
27403831d35Sstevel {
27503831d35Sstevel 	int		err;
27603831d35Sstevel 	picl_prophdl_t	proph;
27703831d35Sstevel 	picl_propinfo_t	pinfo;
27803831d35Sstevel 	int8_t		int8v;
27903831d35Sstevel 	int16_t		int16v;
28003831d35Sstevel 	int32_t		int32v;
28103831d35Sstevel 	int64_t		int64v;
28203831d35Sstevel 
28303831d35Sstevel 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
28403831d35Sstevel 	if (err != PICL_SUCCESS) {
28503831d35Sstevel 		*ret = err;
28603831d35Sstevel 		return (0);
28703831d35Sstevel 	}
28803831d35Sstevel 
28903831d35Sstevel 	/*
29003831d35Sstevel 	 * If it is not an int, uint or byte array prop, return failure
29103831d35Sstevel 	 */
29203831d35Sstevel 	if ((pinfo.type != PICL_PTYPE_INT) &&
293*2983dda7SMichael Bergknoff 	    (pinfo.type != PICL_PTYPE_UNSIGNED_INT) &&
294*2983dda7SMichael Bergknoff 	    (pinfo.type != PICL_PTYPE_BYTEARRAY)) {
29503831d35Sstevel 		*ret = PICL_FAILURE;
29603831d35Sstevel 		return (0);
29703831d35Sstevel 	}
29803831d35Sstevel 
29903831d35Sstevel 	switch (pinfo.size) {
30003831d35Sstevel 	case sizeof (int8_t):
30103831d35Sstevel 		err = picl_get_propval(proph, &int8v, sizeof (int8v));
30203831d35Sstevel 		*ret = err;
30303831d35Sstevel 		return (int8v);
30403831d35Sstevel 	case sizeof (int16_t):
30503831d35Sstevel 		err = picl_get_propval(proph, &int16v, sizeof (int16v));
30603831d35Sstevel 		*ret = err;
30703831d35Sstevel 		return (int16v);
30803831d35Sstevel 	case sizeof (int32_t):
30903831d35Sstevel 		err = picl_get_propval(proph, &int32v, sizeof (int32v));
31003831d35Sstevel 		*ret = err;
31103831d35Sstevel 		return (int32v);
31203831d35Sstevel 	case sizeof (int64_t):
31303831d35Sstevel 		err = picl_get_propval(proph, &int64v, sizeof (int64v));
31403831d35Sstevel 		*ret = err;
31503831d35Sstevel 		return (int64v);
31603831d35Sstevel 	default:	/* not supported size */
31703831d35Sstevel 		*ret = PICL_FAILURE;
31803831d35Sstevel 		return (0);
31903831d35Sstevel 	}
32003831d35Sstevel }
32103831d35Sstevel 
32203831d35Sstevel /*
32303831d35Sstevel  * return the value of the uint prop
32403831d35Sstevel  */
32503831d35Sstevel static uint64_t
picldiag_get_uint_propval(picl_nodehdl_t modh,char * prop_name,int * ret)32603831d35Sstevel picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
32703831d35Sstevel {
32803831d35Sstevel 	int		err;
32903831d35Sstevel 	picl_prophdl_t	proph;
33003831d35Sstevel 	picl_propinfo_t	pinfo;
33103831d35Sstevel 	uint8_t		uint8v;
33203831d35Sstevel 	uint16_t	uint16v;
33303831d35Sstevel 	uint32_t	uint32v;
33403831d35Sstevel 	uint64_t	uint64v;
33503831d35Sstevel 
33603831d35Sstevel 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
33703831d35Sstevel 	if (err != PICL_SUCCESS) {
33803831d35Sstevel 		*ret = err;
33903831d35Sstevel 		return (0);
34003831d35Sstevel 	}
34103831d35Sstevel 
34203831d35Sstevel 	/*
34303831d35Sstevel 	 * If it is not an int or uint prop, return failure
34403831d35Sstevel 	 */
34503831d35Sstevel 	if ((pinfo.type != PICL_PTYPE_INT) &&
346*2983dda7SMichael Bergknoff 	    (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
34703831d35Sstevel 		*ret = PICL_FAILURE;
34803831d35Sstevel 		return (0);
34903831d35Sstevel 	}
35003831d35Sstevel 
35103831d35Sstevel 	/* uint prop */
35203831d35Sstevel 
35303831d35Sstevel 	switch (pinfo.size) {
35403831d35Sstevel 	case sizeof (uint8_t):
35503831d35Sstevel 		err = picl_get_propval(proph, &uint8v, sizeof (uint8v));
35603831d35Sstevel 		*ret = err;
35703831d35Sstevel 		return (uint8v);
35803831d35Sstevel 	case sizeof (uint16_t):
35903831d35Sstevel 		err = picl_get_propval(proph, &uint16v, sizeof (uint16v));
36003831d35Sstevel 		*ret = err;
36103831d35Sstevel 		return (uint16v);
36203831d35Sstevel 	case sizeof (uint32_t):
36303831d35Sstevel 		err = picl_get_propval(proph, &uint32v, sizeof (uint32v));
36403831d35Sstevel 		*ret = err;
36503831d35Sstevel 		return (uint32v);
36603831d35Sstevel 	case sizeof (uint64_t):
36703831d35Sstevel 		err = picl_get_propval(proph, &uint64v, sizeof (uint64v));
36803831d35Sstevel 		*ret = err;
36903831d35Sstevel 		return (uint64v);
37003831d35Sstevel 	default:	/* not supported size */
37103831d35Sstevel 		*ret = PICL_FAILURE;
37203831d35Sstevel 		return (0);
37303831d35Sstevel 	}
37403831d35Sstevel }
37503831d35Sstevel 
37603831d35Sstevel /*
37703831d35Sstevel  * return the value of the float prop
37803831d35Sstevel  */
37903831d35Sstevel static float
picldiag_get_float_propval(picl_nodehdl_t modh,char * prop_name,int * ret)38003831d35Sstevel picldiag_get_float_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
38103831d35Sstevel {
38203831d35Sstevel 	int		err;
38303831d35Sstevel 	picl_prophdl_t	proph;
38403831d35Sstevel 	picl_propinfo_t	pinfo;
38503831d35Sstevel 	float		floatv;
38603831d35Sstevel 
38703831d35Sstevel 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
38803831d35Sstevel 	if (err != PICL_SUCCESS) {
38903831d35Sstevel 		*ret = err;
39003831d35Sstevel 		return ((float)0);
39103831d35Sstevel 	}
39203831d35Sstevel 
39303831d35Sstevel 	/*
39403831d35Sstevel 	 * If it is not a float prop, return failure
39503831d35Sstevel 	 */
39603831d35Sstevel 	if (pinfo.type != PICL_PTYPE_FLOAT) {
39703831d35Sstevel 		*ret = PICL_FAILURE;
39803831d35Sstevel 		return ((float)0);
39903831d35Sstevel 	}
40003831d35Sstevel 
40103831d35Sstevel 	*ret = picl_get_propval(proph, &floatv, sizeof (floatv));
40203831d35Sstevel 	return (floatv);
40303831d35Sstevel }
40403831d35Sstevel 
40503831d35Sstevel /*
40603831d35Sstevel  * get the clock frequency
40703831d35Sstevel  */
40803831d35Sstevel static int
picldiag_get_clock_freq(picl_nodehdl_t modh,uint32_t * freq)40903831d35Sstevel picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq)
41003831d35Sstevel {
41103831d35Sstevel #define	ROUND_TO_MHZ(x)	(((x) + 500000)/ 1000000)
41203831d35Sstevel 	int		err;
41303831d35Sstevel 	uint64_t	clk_freq;
41403831d35Sstevel 
41503831d35Sstevel 	clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err);
41603831d35Sstevel 	if (err != PICL_SUCCESS)
41703831d35Sstevel 		return (err);
41803831d35Sstevel 
41903831d35Sstevel 	*freq = ROUND_TO_MHZ(clk_freq);
42003831d35Sstevel 
42103831d35Sstevel 	return (PICL_SUCCESS);
42203831d35Sstevel }
42303831d35Sstevel 
42403831d35Sstevel /*
42503831d35Sstevel  * get the clock frequency from parent
42603831d35Sstevel  */
42703831d35Sstevel static int
picldiag_get_clock_from_parent(picl_nodehdl_t nodeh,uint32_t * clk)42803831d35Sstevel picldiag_get_clock_from_parent(picl_nodehdl_t nodeh, uint32_t *clk)
42903831d35Sstevel {
43003831d35Sstevel 	picl_nodehdl_t	parenth;
43103831d35Sstevel 	int		err;
43203831d35Sstevel 
43303831d35Sstevel 
43403831d35Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
43503831d35Sstevel 	    &parenth, sizeof (parenth));
43603831d35Sstevel 
43703831d35Sstevel 	while (err == PICL_SUCCESS) {
43803831d35Sstevel 		err = picldiag_get_clock_freq(parenth, clk);
43903831d35Sstevel 		if (err != PICL_PROPNOTFOUND)
44003831d35Sstevel 			return (err);
44103831d35Sstevel 
44203831d35Sstevel 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
44303831d35Sstevel 		    &parenth, sizeof (parenth));
44403831d35Sstevel 	}
44503831d35Sstevel 
44603831d35Sstevel 	return (err);
44703831d35Sstevel }
44803831d35Sstevel 
44903831d35Sstevel /*
45003831d35Sstevel  * get _fru_parent prop
45103831d35Sstevel  * If not found, then travese superiors (parent nodes) until
45203831d35Sstevel  * a _fru_parent property is found.
45303831d35Sstevel  * If not found, no fru parent
45403831d35Sstevel  */
45503831d35Sstevel static int
picldiag_get_fru_parent(picl_nodehdl_t nodeh,picl_nodehdl_t * fruparenth)45603831d35Sstevel picldiag_get_fru_parent(picl_nodehdl_t nodeh, picl_nodehdl_t *fruparenth)
45703831d35Sstevel {
45803831d35Sstevel 	picl_nodehdl_t	fruh;
45903831d35Sstevel 	int		err;
46003831d35Sstevel 
46103831d35Sstevel 	/* find fru parent */
46203831d35Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT,
46303831d35Sstevel 	    &fruh, sizeof (fruh));
46403831d35Sstevel 
46503831d35Sstevel 	if (err != PICL_SUCCESS)
46603831d35Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_REFPROP_LOC_PARENT,
46703831d35Sstevel 		    &fruh, sizeof (fruh));
46803831d35Sstevel 
46903831d35Sstevel 	while (err == PICL_PROPNOTFOUND) {
47003831d35Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
47103831d35Sstevel 		    &nodeh, sizeof (nodeh));
47203831d35Sstevel 		if (err != PICL_SUCCESS)
47303831d35Sstevel 			return (err);
47403831d35Sstevel 
47503831d35Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT,
47603831d35Sstevel 		    &fruh, sizeof (fruh));
47703831d35Sstevel 		if (err != PICL_SUCCESS)
47803831d35Sstevel 			err = picl_get_propval_by_name(nodeh,
47903831d35Sstevel 			    PICL_REFPROP_LOC_PARENT, &fruh, sizeof (fruh));
48003831d35Sstevel 	}
48103831d35Sstevel 
48203831d35Sstevel 	if (err == PICL_SUCCESS)
48303831d35Sstevel 		*fruparenth = fruh;
48403831d35Sstevel 
48503831d35Sstevel 	return (err);
48603831d35Sstevel }
48703831d35Sstevel 
48803831d35Sstevel /*
48903831d35Sstevel  * get label
49003831d35Sstevel  *
49103831d35Sstevel  * To get the label, use the following algorithm:
49203831d35Sstevel  * Lookup "Label" property in the fru node itself. If no
49303831d35Sstevel  * Label found, then traverse superiors (parent nodes) until
49403831d35Sstevel  * a Label property is found.
49503831d35Sstevel  * if not found, then no label
49603831d35Sstevel  */
49703831d35Sstevel static int
picldiag_get_label(picl_nodehdl_t nodeh,char ** label)49803831d35Sstevel picldiag_get_label(picl_nodehdl_t nodeh, char **label)
49903831d35Sstevel {
50003831d35Sstevel 	int		err;
50103831d35Sstevel 
50203831d35Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, label);
50303831d35Sstevel 
50403831d35Sstevel 	while (err == PICL_PROPNOTFOUND) {
50503831d35Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
50603831d35Sstevel 		    &nodeh, sizeof (nodeh));
50703831d35Sstevel 		if (err != PICL_SUCCESS)
50803831d35Sstevel 			return (err);
50903831d35Sstevel 
51003831d35Sstevel 		err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL,
51103831d35Sstevel 		    label);
51203831d35Sstevel 	}
51303831d35Sstevel 
51403831d35Sstevel 	return (err);
51503831d35Sstevel }
51603831d35Sstevel 
51703831d35Sstevel /*
51803831d35Sstevel  * get combined label
51903831d35Sstevel  *
52003831d35Sstevel  * like picldiag_get_label, except concatenates the labels of parent locations
52103831d35Sstevel  * eg SB0/P3 for processor P3 on system board SB0
52203831d35Sstevel  *
52303831d35Sstevel  * if caller specifies non-zero label length, label will be cut to specified
52403831d35Sstevel  * length.
52503831d35Sstevel  * negative length is left justified, non-negative length is right justified
52603831d35Sstevel  */
52703831d35Sstevel static int
picldiag_get_combined_label(picl_nodehdl_t nodeh,char ** label,int lablen)52803831d35Sstevel picldiag_get_combined_label(picl_nodehdl_t nodeh, char **label, int lablen)
52903831d35Sstevel {
53003831d35Sstevel 	int	err;
53103831d35Sstevel 	char	*ptr;
53203831d35Sstevel 	char	*ptr1 = NULL;
53303831d35Sstevel 	char	*ptr2;
53403831d35Sstevel 	int	len;
53503831d35Sstevel 
53603831d35Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr1);
53703831d35Sstevel 	if (err != PICL_PROPNOTFOUND && err != PICL_SUCCESS)
53803831d35Sstevel 		return (err);
53903831d35Sstevel 
54003831d35Sstevel 	for (;;) {
54103831d35Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
54203831d35Sstevel 		    &nodeh, sizeof (nodeh));
54303831d35Sstevel 		if (err == PICL_PROPNOTFOUND)
54403831d35Sstevel 			break;
54503831d35Sstevel 		if (err != PICL_SUCCESS)
54603831d35Sstevel 			return (err);
54703831d35Sstevel 
54803831d35Sstevel 		err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr);
54903831d35Sstevel 		if (err == PICL_SUCCESS) {
55003831d35Sstevel 			if (ptr1 == NULL) {
55103831d35Sstevel 				ptr1 = ptr;
55203831d35Sstevel 			} else {
55303831d35Sstevel 				ptr2 = malloc(strlen(ptr1) + strlen(ptr) + 2);
55403831d35Sstevel 				if (ptr2 == NULL)
55503831d35Sstevel 					return (PICL_FAILURE);
55603831d35Sstevel 				(void) strlcpy(ptr2, ptr, strlen(ptr)-1);
55703831d35Sstevel 				(void) strlcat(ptr2, "/", 1);
55803831d35Sstevel 				(void) strlcat(ptr2, ptr1, strlen(ptr1)-1);
55903831d35Sstevel 				(void) strlcat(ptr2, "\0", 1);
56003831d35Sstevel 
56103831d35Sstevel 				(void) free(ptr);
56203831d35Sstevel 				(void) free(ptr1);
56303831d35Sstevel 				ptr1 = ptr2;
56403831d35Sstevel 			}
56503831d35Sstevel 		} else if (err != PICL_PROPNOTFOUND) {
56603831d35Sstevel 			return (err);
56703831d35Sstevel 		}
56803831d35Sstevel 	}
56903831d35Sstevel 
57003831d35Sstevel 	if (ptr1 == NULL)
57103831d35Sstevel 		return (PICL_PROPNOTFOUND);
57203831d35Sstevel 
57303831d35Sstevel 	len = strlen(ptr1);
57403831d35Sstevel 	/* if no string truncation is desired or required */
57503831d35Sstevel 	if ((lablen == 0) || (len <= abs(lablen))) {
57603831d35Sstevel 		*label = ptr1;
57703831d35Sstevel 		return (PICL_SUCCESS);
57803831d35Sstevel 	}
57903831d35Sstevel 
58003831d35Sstevel 	/* string truncation is required; alloc space for (lablen + \0) */
58103831d35Sstevel 	ptr = malloc(abs(lablen) + 1);
58203831d35Sstevel 	if (ptr == 0)
58303831d35Sstevel 		return (PICL_FAILURE);
58403831d35Sstevel 	if (lablen > 0) {
58503831d35Sstevel 		/* right justification; label = "+<string>\0" */
58603831d35Sstevel 		strlcpy(ptr, "+", 1);
58703831d35Sstevel 		strlcat(ptr, ptr1 + len - lablen + 1, lablen + 1);
58803831d35Sstevel 	} else {
58903831d35Sstevel 		/* left justification; label = "<string>+\0" */
59003831d35Sstevel 		strlcpy(ptr, ptr1, abs(lablen) - 1);
59103831d35Sstevel 		strcat(ptr, "+");
59203831d35Sstevel 	}
59303831d35Sstevel 
59403831d35Sstevel 	*label = ptr;
59503831d35Sstevel 	return (PICL_SUCCESS);
59603831d35Sstevel }
59703831d35Sstevel 
59803831d35Sstevel /*
59903831d35Sstevel  * return the first compatible value
60003831d35Sstevel  */
60103831d35Sstevel static int
picldiag_get_first_compatible_value(picl_nodehdl_t nodeh,char ** outbuf)60203831d35Sstevel picldiag_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
60303831d35Sstevel {
60403831d35Sstevel 	int		err;
60503831d35Sstevel 	picl_prophdl_t	proph;
60603831d35Sstevel 	picl_propinfo_t	pinfo;
60703831d35Sstevel 	picl_prophdl_t	tblh;
60803831d35Sstevel 	picl_prophdl_t	rowproph;
60903831d35Sstevel 	char		*pval;
61003831d35Sstevel 
61103831d35Sstevel 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
61203831d35Sstevel 	    &pinfo, &proph);
61303831d35Sstevel 	if (err != PICL_SUCCESS)
614*2983dda7SMichael Bergknoff 		return (err);
61503831d35Sstevel 
61603831d35Sstevel 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
61703831d35Sstevel 		pval = malloc(pinfo.size);
61803831d35Sstevel 		if (pval == NULL)
61903831d35Sstevel 			return (PICL_FAILURE);
62003831d35Sstevel 		err = picl_get_propval(proph, pval, pinfo.size);
62103831d35Sstevel 		if (err != PICL_SUCCESS) {
62203831d35Sstevel 			free(pval);
62303831d35Sstevel 			return (err);
62403831d35Sstevel 		}
62503831d35Sstevel 		*outbuf = pval;
62603831d35Sstevel 		return (PICL_SUCCESS);
62703831d35Sstevel 	}
62803831d35Sstevel 
62903831d35Sstevel 	if (pinfo.type != PICL_PTYPE_TABLE)
63003831d35Sstevel 		return (PICL_FAILURE);
63103831d35Sstevel 
63203831d35Sstevel 	/* get first string from table */
63303831d35Sstevel 	err = picl_get_propval(proph, &tblh, pinfo.size);
63403831d35Sstevel 	if (err != PICL_SUCCESS)
63503831d35Sstevel 		return (err);
63603831d35Sstevel 
63703831d35Sstevel 	err = picl_get_next_by_row(tblh, &rowproph);
63803831d35Sstevel 	if (err != PICL_SUCCESS)
63903831d35Sstevel 		return (err);
64003831d35Sstevel 
64103831d35Sstevel 	err = picl_get_propinfo(rowproph, &pinfo);
64203831d35Sstevel 	if (err != PICL_SUCCESS)
643*2983dda7SMichael Bergknoff 		return (err);
64403831d35Sstevel 
64503831d35Sstevel 	pval = malloc(pinfo.size);
64603831d35Sstevel 	if (pval == NULL)
64703831d35Sstevel 		return (PICL_FAILURE);
64803831d35Sstevel 
64903831d35Sstevel 	err = picl_get_propval(rowproph, pval, pinfo.size);
65003831d35Sstevel 	if (err != PICL_SUCCESS) {
65103831d35Sstevel 		free(pval);
65203831d35Sstevel 		return (err);
65303831d35Sstevel 	}
65403831d35Sstevel 
65503831d35Sstevel 	*outbuf = pval;
65603831d35Sstevel 	return (PICL_SUCCESS);
65703831d35Sstevel }
65803831d35Sstevel 
65903831d35Sstevel /*
66003831d35Sstevel  * print the header in the center
66103831d35Sstevel  */
66203831d35Sstevel static void
logprintf_header(char * header,size_t line_width)66303831d35Sstevel logprintf_header(char *header, size_t line_width)
66403831d35Sstevel {
66503831d35Sstevel 	size_t	start_pos;
66603831d35Sstevel 	size_t	i;
66703831d35Sstevel 
66803831d35Sstevel 	log_printf("\n");
66903831d35Sstevel 	start_pos = (line_width - strlen(header) - 2) / 2;
67003831d35Sstevel 
67103831d35Sstevel 	for (i = 0; i < start_pos; i++)
67203831d35Sstevel 		log_printf("%s", HEADING_SYMBOL);
67303831d35Sstevel 
67403831d35Sstevel 	log_printf(" %s ", header);
67503831d35Sstevel 
67603831d35Sstevel 	for (i = 0; i < start_pos; i++)
67703831d35Sstevel 		log_printf("%s", HEADING_SYMBOL);
67803831d35Sstevel 
67903831d35Sstevel 	log_printf("\n");
68003831d35Sstevel }
68103831d35Sstevel 
68203831d35Sstevel /*
68303831d35Sstevel  * print the size
68403831d35Sstevel  */
68503831d35Sstevel static void
logprintf_size(uint64_t size)68603831d35Sstevel logprintf_size(uint64_t size)
68703831d35Sstevel {
68803831d35Sstevel 
68903831d35Sstevel 	uint64_t	kbyte = 1024;
69003831d35Sstevel 	uint64_t	mbyte = 1024 * 1024;
69103831d35Sstevel 	uint64_t	gbyte = 1024 * 1024 * 1024;
69203831d35Sstevel 	uint64_t	residue;
69303831d35Sstevel 	char		buf[SIZE_FIELD];
69403831d35Sstevel 
69503831d35Sstevel 	if (size >= gbyte) {
69603831d35Sstevel 		residue = size % gbyte;
69703831d35Sstevel 		if (residue == 0)
69803831d35Sstevel 			snprintf(buf, sizeof (buf), "%dGB",
69903831d35Sstevel 			    (int)(size / gbyte));
70003831d35Sstevel 		else
70103831d35Sstevel 			snprintf(buf, sizeof (buf), "%.2fGB",
70203831d35Sstevel 			    (float)size / gbyte);
70303831d35Sstevel 	} else if (size >= mbyte) {
70403831d35Sstevel 		residue = size % mbyte;
70503831d35Sstevel 		if (residue == 0)
70603831d35Sstevel 			snprintf(buf, sizeof (buf), "%dMB",
70703831d35Sstevel 			    (int)(size / mbyte));
70803831d35Sstevel 		else
70903831d35Sstevel 			snprintf(buf, sizeof (buf), "%.2fMB",
71003831d35Sstevel 			    (float)size / mbyte);
71103831d35Sstevel 	} else {
71203831d35Sstevel 		residue = size % kbyte;
71303831d35Sstevel 		if (residue == 0)
71403831d35Sstevel 			snprintf(buf, sizeof (buf), "%dKB",
71503831d35Sstevel 			    (int)(size / kbyte));
71603831d35Sstevel 		else
71703831d35Sstevel 			snprintf(buf, sizeof (buf), "%.2fKB",
71803831d35Sstevel 			    (float)size / kbyte);
71903831d35Sstevel 	}
72003831d35Sstevel 
72103831d35Sstevel 	log_printf("%-10s ", buf);
72203831d35Sstevel }
72303831d35Sstevel 
72403831d35Sstevel /*
72503831d35Sstevel  * display platform banner
72603831d35Sstevel  */
72703831d35Sstevel static int
display_platform_banner(picl_nodehdl_t plafh)72803831d35Sstevel display_platform_banner(picl_nodehdl_t plafh)
72903831d35Sstevel {
73003831d35Sstevel 	char	*platform;
73103831d35Sstevel 	char	*banner_name;
73203831d35Sstevel 	int	err;
73303831d35Sstevel 
73403831d35Sstevel 	/*
73503831d35Sstevel 	 * get PICL_PROP_MACHINE and PICL_PROP_BANNER_NAME
73603831d35Sstevel 	 */
73703831d35Sstevel 	log_printf(SIGN_ON_MSG);
73803831d35Sstevel 	err = picldiag_get_string_propval(plafh, PICL_PROP_MACHINE,
73903831d35Sstevel 	    &platform);
74003831d35Sstevel 	if (err != PICL_SUCCESS)
74103831d35Sstevel 		return (err);
74203831d35Sstevel 	log_printf(" %s", platform);
74303831d35Sstevel 	free(platform);
74403831d35Sstevel 
74503831d35Sstevel 	err = picldiag_get_string_propval(plafh, OBP_PROP_BANNER_NAME,
74603831d35Sstevel 	    &banner_name);
74703831d35Sstevel 	if (err != PICL_SUCCESS)
74803831d35Sstevel 		return (err);
74903831d35Sstevel 	log_printf(" %s", banner_name);
75003831d35Sstevel 	free(banner_name);
75103831d35Sstevel 
75203831d35Sstevel 	log_printf("\n");
75303831d35Sstevel 	return (PICL_SUCCESS);
75403831d35Sstevel }
75503831d35Sstevel 
75603831d35Sstevel /*
75703831d35Sstevel  * display the clock frequency
75803831d35Sstevel  */
75903831d35Sstevel static int
display_system_clock(picl_nodehdl_t plafh)76003831d35Sstevel display_system_clock(picl_nodehdl_t plafh)
76103831d35Sstevel {
76203831d35Sstevel 	uint32_t	system_clk;
76303831d35Sstevel 	int		err;
76403831d35Sstevel 
76503831d35Sstevel 	err = picldiag_get_clock_freq(plafh, &system_clk);
76603831d35Sstevel 	if (err != PICL_SUCCESS)
76703831d35Sstevel 		return (err);
76803831d35Sstevel 
76903831d35Sstevel 	log_printf(SYSCLK_FREQ_MSG, system_clk);
77003831d35Sstevel 
77103831d35Sstevel 	return (PICL_SUCCESS);
77203831d35Sstevel }
77303831d35Sstevel 
77403831d35Sstevel /*
77503831d35Sstevel  * callback function to display the memory size
77603831d35Sstevel  */
77703831d35Sstevel /*ARGSUSED*/
77803831d35Sstevel static int
memory_callback(picl_nodehdl_t memh,void * args)77903831d35Sstevel memory_callback(picl_nodehdl_t memh, void *args)
78003831d35Sstevel {
78103831d35Sstevel 	uint64_t	mem_size;
78203831d35Sstevel 	int		err;
78303831d35Sstevel 
78403831d35Sstevel 	log_printf(MEM_SIZE_MSG);
78503831d35Sstevel 	mem_size = picldiag_get_uint_propval(memh, PICL_PROP_SIZE, &err);
78603831d35Sstevel 	if (err == PICL_SUCCESS)
78703831d35Sstevel 		logprintf_size(mem_size);
78803831d35Sstevel 	log_printf("\n");
78903831d35Sstevel 	no_xfer_size = 0;
79003831d35Sstevel 	mem_xfersize = picldiag_get_uint_propval(memh, PICL_PROP_TRANSFER_SIZE,
79103831d35Sstevel 	    &err);
79203831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
79303831d35Sstevel 		no_xfer_size = 1;
79403831d35Sstevel 	return (PICL_WALK_TERMINATE);
79503831d35Sstevel }
79603831d35Sstevel 
79703831d35Sstevel /*
79803831d35Sstevel  * callback function to print cpu information
79903831d35Sstevel  */
80003831d35Sstevel /*ARGSUSED*/
80103831d35Sstevel static int
cpu_callback(picl_nodehdl_t nodeh,void * args)80203831d35Sstevel cpu_callback(picl_nodehdl_t nodeh, void *args)
80303831d35Sstevel {
80403831d35Sstevel 	int		err;
80503831d35Sstevel 	int		id;
80603831d35Sstevel 	uint64_t 	uintval;
80703831d35Sstevel 	uint32_t	freq;
80803831d35Sstevel 	char		*impl_name;
80903831d35Sstevel 	char		*status;
81003831d35Sstevel 	picl_prophdl_t	parenth;
81103831d35Sstevel 	char		*label;
81203831d35Sstevel 
81303831d35Sstevel 	/*
81403831d35Sstevel 	 * If no ID is found, return
81503831d35Sstevel 	 */
81603831d35Sstevel 	id = picldiag_get_uint_propval(nodeh, PICL_PROP_ID, &err);
81703831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
81803831d35Sstevel 		return (PICL_WALK_CONTINUE);
81903831d35Sstevel 	else if (err != PICL_SUCCESS)
82003831d35Sstevel 		return (err);
82103831d35Sstevel 	log_printf(" %2d  ", id);
82203831d35Sstevel 
82303831d35Sstevel 	/*
82403831d35Sstevel 	 * If no freq is found, return
82503831d35Sstevel 	 */
82603831d35Sstevel 	err = picldiag_get_clock_freq(nodeh, &freq);
82703831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
82803831d35Sstevel 		return (PICL_WALK_CONTINUE);
82903831d35Sstevel 	else if (err != PICL_SUCCESS)
83003831d35Sstevel 		return (err);
83103831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "%4d MHz  "), freq);
83203831d35Sstevel 
83303831d35Sstevel 	/* Ecache size */
83403831d35Sstevel 	uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_ECACHE_SIZE, &err);
83503831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
83603831d35Sstevel 		log_printf(" -          ");
83703831d35Sstevel 	else if (err == PICL_SUCCESS)
83803831d35Sstevel 		logprintf_size(uintval);
83903831d35Sstevel 	else
84003831d35Sstevel 		return (err);
84103831d35Sstevel 
84203831d35Sstevel 	/* Implementation */
84303831d35Sstevel 	impl_name = NULL;
84403831d35Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_NAME, &impl_name);
84503831d35Sstevel 	if (err != PICL_SUCCESS)
84603831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "  <unknown>           "));
84703831d35Sstevel 	else
84803831d35Sstevel 		log_printf(" %-22s ", impl_name);
84903831d35Sstevel 
85003831d35Sstevel 	/* CPU Mask */
85103831d35Sstevel 	uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_MASK, &err);
85203831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
85303831d35Sstevel 		log_printf("  -     ");
85403831d35Sstevel 	else if (err == PICL_SUCCESS)
85503831d35Sstevel 		log_printf("%2lld.%-2lld   ", (uintval >> 4) & 0xf,
85603831d35Sstevel 		    uintval & 0xf);
85703831d35Sstevel 	else
85803831d35Sstevel 		return (err);
85903831d35Sstevel 
86003831d35Sstevel 	/*
86103831d35Sstevel 	 * Status - if the node has a status property then display that
86203831d35Sstevel 	 * otherwise display the State property
86303831d35Sstevel 	 */
86403831d35Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status);
86503831d35Sstevel 	if (err == PICL_SUCCESS) {
86603831d35Sstevel 		log_printf("%-12s", status);
86703831d35Sstevel 		free(status);
86803831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err !=
86903831d35Sstevel 	    PICL_PROPVALUNAVAILABLE && err != PICL_ENDOFLIST) {
87003831d35Sstevel 		return (err);
87103831d35Sstevel 	} else {
87203831d35Sstevel 		err = picldiag_get_string_propval(nodeh,
87303831d35Sstevel 		    PICL_PROP_STATE, &status);
87403831d35Sstevel 		if (err == PICL_SUCCESS) {
87503831d35Sstevel 			log_printf("%-12s", status);
87603831d35Sstevel 			free(status);
87703831d35Sstevel 		} else if (err != PICL_PROPNOTFOUND && err !=
87803831d35Sstevel 		    PICL_PROPVALUNAVAILABLE && err !=
87903831d35Sstevel 		    PICL_ENDOFLIST) {
88003831d35Sstevel 			return (err);
88103831d35Sstevel 		} else {
88203831d35Sstevel 			log_printf(dgettext(TEXT_DOMAIN, "unknown    "));
88303831d35Sstevel 		}
88403831d35Sstevel 	}
88503831d35Sstevel 
88603831d35Sstevel 	/*
88703831d35Sstevel 	 * Location: use label of fru parent
88803831d35Sstevel 	 */
88903831d35Sstevel 	err = picldiag_get_fru_parent(nodeh, &parenth);
89003831d35Sstevel 	if (err == PICL_PROPNOTFOUND) {
89103831d35Sstevel 		log_printf(" -      ");
89203831d35Sstevel 	} else if (err == PICL_SUCCESS) {
89303831d35Sstevel 		err = picldiag_get_combined_label(parenth, &label, 12);
89403831d35Sstevel 		if (err == PICL_PROPNOTFOUND)
89503831d35Sstevel 			log_printf(" -      ");
89603831d35Sstevel 		else if (err == PICL_SUCCESS) {
89703831d35Sstevel 			log_printf("%s", label);
89803831d35Sstevel 			free(label);
89903831d35Sstevel 		} else
90003831d35Sstevel 			return (err);
90103831d35Sstevel 	} else
90203831d35Sstevel 		return (err);
90303831d35Sstevel 
90403831d35Sstevel 	log_printf("\n");
90503831d35Sstevel 	return (PICL_WALK_CONTINUE);
90603831d35Sstevel }
90703831d35Sstevel 
90803831d35Sstevel /*
90903831d35Sstevel  * display cpu information
91003831d35Sstevel  */
91103831d35Sstevel static int
display_cpu_info(picl_nodehdl_t plafh)91203831d35Sstevel display_cpu_info(picl_nodehdl_t plafh)
91303831d35Sstevel {
91403831d35Sstevel 	int	err;
91503831d35Sstevel 
91603831d35Sstevel 	/*
91703831d35Sstevel 	 * Display the table header for CPUs . Then display the CPU
91803831d35Sstevel 	 * frequency, cache size, and processor revision  on all the boards.
91903831d35Sstevel 	 */
92003831d35Sstevel 	logprintf_header(dgettext(TEXT_DOMAIN, "CPUs"), DEFAULT_LINE_WIDTH);
92103831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "               E$          CPU"
922*2983dda7SMichael Bergknoff 	    "                    CPU\n"));
92303831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
92403831d35Sstevel 	    "CPU  Freq      Size        Implementation"
925*2983dda7SMichael Bergknoff 	    "         Mask    Status      Location\n"));
92603831d35Sstevel 	log_printf("---  --------  ----------  ---------------------  "
927*2983dda7SMichael Bergknoff 	    "-----   ------      --------\n");
92803831d35Sstevel 
92903831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU,
93003831d35Sstevel 	    cpu_callback);
93103831d35Sstevel 	return (err);
93203831d35Sstevel }
93303831d35Sstevel 
93403831d35Sstevel /*
93503831d35Sstevel  * Inserts an io_card structure into the list.
93603831d35Sstevel  */
93703831d35Sstevel static void
add_io_card(uint32_t board,uint32_t bus_id,uint32_t slot,char * label,uint32_t freq,char * name,char * model,char * status,char * devfs_path)93803831d35Sstevel add_io_card(uint32_t board, uint32_t bus_id, uint32_t slot, char *label,
93903831d35Sstevel     uint32_t freq, char *name, char *model, char *status, char *devfs_path)
94003831d35Sstevel {
94103831d35Sstevel 	struct io_card card;
94203831d35Sstevel 
94303831d35Sstevel 	card.display = 1;
94403831d35Sstevel 	card.board = board;
94503831d35Sstevel 	switch (bus_id) {
94603831d35Sstevel 	case PCI_TYPE:
94703831d35Sstevel 		strlcpy(card.bus_type, PCI_NAME, MAXSTRLEN);
94803831d35Sstevel 		break;
94903831d35Sstevel 	default: /* won't reach here */
95003831d35Sstevel 		strlcpy(card.bus_type, "", MAXSTRLEN);
95103831d35Sstevel 		break;
95203831d35Sstevel 	}
95303831d35Sstevel 	if (label == NULL)
95403831d35Sstevel 		card.slot = slot;
95503831d35Sstevel 	else {
95603831d35Sstevel 		card.slot = PCI_SLOT_IS_STRING;
95703831d35Sstevel 		(void) strlcpy(card.slot_str, label, MAXSTRLEN);
95803831d35Sstevel 	}
95903831d35Sstevel 	card.freq = freq;
96003831d35Sstevel 	card.status[0] = '\0';
96103831d35Sstevel 	card.name[0] = '\0';
96203831d35Sstevel 	card.model[0] = '\0';
96303831d35Sstevel 	card.notes[0] = '\0';
96403831d35Sstevel 	if (status != NULL)
96503831d35Sstevel 		strlcpy(card.status, status, MAXSTRLEN);
96603831d35Sstevel 	if (name != NULL)
96703831d35Sstevel 		strlcpy(card.name, name, MAXSTRLEN);
96803831d35Sstevel 	if (model != NULL)
96903831d35Sstevel 		strlcpy(card.model, model, MAXSTRLEN);
97003831d35Sstevel 	if (status != NULL)
97103831d35Sstevel 		strlcpy(card.status, status, MAXSTRLEN);
97203831d35Sstevel 	if (devfs_path != NULL)
97303831d35Sstevel 		strlcpy(card.notes, devfs_path, MAXSTRLEN);
97403831d35Sstevel 
97503831d35Sstevel 	io_card_list = insert_io_card(io_card_list, &card);
97603831d35Sstevel }
97703831d35Sstevel 
97803831d35Sstevel static void
append_to_bank_list(bank_list_t * newptr)97903831d35Sstevel append_to_bank_list(bank_list_t *newptr)
98003831d35Sstevel {
98103831d35Sstevel 	bank_list_t	*ptr;
98203831d35Sstevel 
98303831d35Sstevel 	if (mem_banks == NULL) {
98403831d35Sstevel 		mem_banks = newptr;
98503831d35Sstevel 		return;
98603831d35Sstevel 	}
98703831d35Sstevel 	ptr = mem_banks;
98803831d35Sstevel 	while (ptr->next != NULL)
98903831d35Sstevel 		ptr = ptr->next;
99003831d35Sstevel 
99103831d35Sstevel 	ptr->next = newptr;
99203831d35Sstevel }
99303831d35Sstevel 
99403831d35Sstevel static void
free_bank_list(void)99503831d35Sstevel free_bank_list(void)
99603831d35Sstevel {
99703831d35Sstevel 	bank_list_t	*ptr;
99803831d35Sstevel 	bank_list_t	*tmp;
99903831d35Sstevel 
100003831d35Sstevel 	for (ptr = mem_banks; ptr != NULL; ptr = tmp) {
100103831d35Sstevel 		tmp = ptr->next;
100203831d35Sstevel 		free(ptr);
100303831d35Sstevel 	}
100403831d35Sstevel 	mem_banks = NULL;
100503831d35Sstevel }
100603831d35Sstevel 
100703831d35Sstevel 
100803831d35Sstevel /*
100903831d35Sstevel  * print label for memory module
101003831d35Sstevel  */
101103831d35Sstevel static int
logprintf_memory_module_label(picl_nodehdl_t moduleh)101203831d35Sstevel logprintf_memory_module_label(picl_nodehdl_t moduleh)
101303831d35Sstevel {
101403831d35Sstevel 	picl_nodehdl_t	fruparenth;
101503831d35Sstevel 	int		err;
101603831d35Sstevel 	char		*label;
101703831d35Sstevel 
101803831d35Sstevel 	err = picldiag_get_fru_parent(moduleh, &fruparenth);
101903831d35Sstevel 	if (err == PICL_PROPNOTFOUND) {
102003831d35Sstevel 		log_printf("-");
102103831d35Sstevel 		return (PICL_SUCCESS);
102203831d35Sstevel 	} else if (err != PICL_SUCCESS)
102303831d35Sstevel 		return (err);
102403831d35Sstevel 
102503831d35Sstevel 	err = picldiag_get_combined_label(fruparenth, &label, 30);
102603831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
102703831d35Sstevel 		log_printf("-");
102803831d35Sstevel 	else if (err == PICL_SUCCESS) {
102903831d35Sstevel 		log_printf("%-15s", label);
103003831d35Sstevel 		free(label);
103103831d35Sstevel 	} else
103203831d35Sstevel 		return (err);
103303831d35Sstevel 
103403831d35Sstevel 	return (PICL_SUCCESS);
103503831d35Sstevel }
103603831d35Sstevel 
103703831d35Sstevel /*
103803831d35Sstevel  * print the bank id and add the bank handle in the bank list
103903831d35Sstevel  * return the head of the bank list
104003831d35Sstevel  */
104103831d35Sstevel static int
membank_callback(picl_nodehdl_t bankh,void * args)104203831d35Sstevel membank_callback(picl_nodehdl_t bankh, void *args)
104303831d35Sstevel {
104403831d35Sstevel 	int		err;
104503831d35Sstevel 	int64_t		id;
104603831d35Sstevel 	uint64_t	match;
104703831d35Sstevel 	uint64_t	mask;
104803831d35Sstevel 	int		i;
104903831d35Sstevel 	bank_list_t	*newptr;
105003831d35Sstevel 	seg_info_t	*segp = args;
105103831d35Sstevel 
105203831d35Sstevel 	/*
105303831d35Sstevel 	 * print the bank id in the segment table contains column
105403831d35Sstevel 	 */
105503831d35Sstevel 	id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err);
105603831d35Sstevel 	if (segp->bank_count > 0)
105703831d35Sstevel 		log_printf(",");
105803831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
105903831d35Sstevel 		log_printf("-");
106003831d35Sstevel 	else if (err == PICL_SUCCESS)
106103831d35Sstevel 		log_printf("%-lld", id);
106203831d35Sstevel 	else
106303831d35Sstevel 		return (err);
106403831d35Sstevel 	segp->bank_count++;
106503831d35Sstevel 
106603831d35Sstevel 	/*
106703831d35Sstevel 	 * Save the bank information for later (print_bank_table)
106803831d35Sstevel 	 */
106903831d35Sstevel 	newptr = malloc(sizeof (*newptr));
107003831d35Sstevel 	if (newptr == NULL)
107103831d35Sstevel 		return (PICL_FAILURE);
107203831d35Sstevel 
107303831d35Sstevel 	newptr->nodeh = bankh;
107403831d35Sstevel 	newptr->iway_count = 0;
107503831d35Sstevel 	newptr->next = NULL;
107603831d35Sstevel 	append_to_bank_list(newptr);
107703831d35Sstevel 
107803831d35Sstevel 	/*
107903831d35Sstevel 	 * Compute the way numbers for the bank
108003831d35Sstevel 	 */
108103831d35Sstevel 	if (no_xfer_size)
108203831d35Sstevel 		return (PICL_WALK_CONTINUE);
108303831d35Sstevel 
108403831d35Sstevel 	match = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMATCH, &err);
108503831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
108603831d35Sstevel 		return (PICL_WALK_CONTINUE);
108703831d35Sstevel 	else if (err != PICL_SUCCESS)
108803831d35Sstevel 		return (err);
108903831d35Sstevel 
109003831d35Sstevel 	mask = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMASK, &err);
109103831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
109203831d35Sstevel 		return (PICL_WALK_CONTINUE);
109303831d35Sstevel 	else if (err != PICL_SUCCESS)
109403831d35Sstevel 		return (err);
109503831d35Sstevel 
109603831d35Sstevel 	i = 0;
109703831d35Sstevel 	while ((i < segp->ifactor) && (newptr->iway_count < MAX_IWAYS)) {
109803831d35Sstevel 		if (((segp->base + i * mem_xfersize) & mask) == match)
109903831d35Sstevel 			newptr->iway[newptr->iway_count++] = i;
110003831d35Sstevel 		++i;
110103831d35Sstevel 	}
110203831d35Sstevel 	return (PICL_WALK_CONTINUE);
110303831d35Sstevel }
110403831d35Sstevel 
110503831d35Sstevel 
110603831d35Sstevel /*
110703831d35Sstevel  * find the memory bank and add the bank handle in the bank list
110803831d35Sstevel  * return the head of the bank list
110903831d35Sstevel  */
111003831d35Sstevel static int
logprintf_bankinfo(picl_nodehdl_t segh,seg_info_t * segp)111103831d35Sstevel logprintf_bankinfo(picl_nodehdl_t segh, seg_info_t *segp)
111203831d35Sstevel {
111303831d35Sstevel 	int		err;
111403831d35Sstevel 
111503831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "BankIDs "));
111603831d35Sstevel 	/*
111703831d35Sstevel 	 * find memory-bank
111803831d35Sstevel 	 */
111903831d35Sstevel 	segp->bank_count = 0;
112003831d35Sstevel 	err = picl_walk_tree_by_class(segh, PICL_CLASS_MEMORY_BANK, segp,
112103831d35Sstevel 	    membank_callback);
112203831d35Sstevel 	log_printf("\n");
112303831d35Sstevel 	return (err);
112403831d35Sstevel }
112503831d35Sstevel 
112603831d35Sstevel /*
112703831d35Sstevel  * print the label of memory module or the memory module bank ids
112803831d35Sstevel  */
112903831d35Sstevel static int
logprintf_seg_contains_col(picl_nodehdl_t nodeh,seg_info_t * segp)113003831d35Sstevel logprintf_seg_contains_col(picl_nodehdl_t nodeh, seg_info_t *segp)
113103831d35Sstevel {
113203831d35Sstevel 	picl_nodehdl_t	moduleh;
113303831d35Sstevel 	int		err;
113403831d35Sstevel 
113503831d35Sstevel 	/*
113603831d35Sstevel 	 * find memory-module if referenced directly from the memory-segment
113703831d35Sstevel 	 * (ie no memory banks)
113803831d35Sstevel 	 */
113903831d35Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_REFPROP_MEMORY_MODULE,
114003831d35Sstevel 	    &moduleh, sizeof (moduleh));
114103831d35Sstevel 	if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND))
114203831d35Sstevel 		return (err);
114303831d35Sstevel 	if (err == PICL_SUCCESS) {
114403831d35Sstevel 		err = logprintf_memory_module_label(moduleh);
114503831d35Sstevel 		log_printf("\n");
114603831d35Sstevel 		return (err);
114703831d35Sstevel 	}
114803831d35Sstevel 
114903831d35Sstevel 	/*
115003831d35Sstevel 	 * memory-module not referenced directly from the memory segment
115103831d35Sstevel 	 * so list memory banks instead
115203831d35Sstevel 	 */
115303831d35Sstevel 	err = logprintf_bankinfo(nodeh, segp);
115403831d35Sstevel 	return (err);
115503831d35Sstevel }
115603831d35Sstevel 
115703831d35Sstevel /*
115803831d35Sstevel  * find all memory modules under the given memory module group
115903831d35Sstevel  * and print its label
116003831d35Sstevel  */
116103831d35Sstevel static int
logprintf_memory_module_group_info(picl_nodehdl_t memgrph,uint64_t mcid)116203831d35Sstevel logprintf_memory_module_group_info(picl_nodehdl_t memgrph, uint64_t mcid)
116303831d35Sstevel {
116403831d35Sstevel 	int		err;
116503831d35Sstevel 	int64_t		id;
116603831d35Sstevel 	boolean_t	got_status;
116703831d35Sstevel 	picl_nodehdl_t	moduleh;
116803831d35Sstevel 	char		piclclass[PICL_CLASSNAMELEN_MAX];
116903831d35Sstevel 	picl_nodehdl_t	fruparenth;
117003831d35Sstevel 	char		*status;
117103831d35Sstevel 
117203831d35Sstevel 	id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID, &err);
117303831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
117403831d35Sstevel 		id = -1;
117503831d35Sstevel 	else if (err != PICL_SUCCESS)
117603831d35Sstevel 		return (err);
117703831d35Sstevel 
117803831d35Sstevel 	err = picl_get_propval_by_name(memgrph, PICL_PROP_CHILD, &moduleh,
117903831d35Sstevel 	    sizeof (picl_nodehdl_t));
118003831d35Sstevel 
118103831d35Sstevel 	while (err == PICL_SUCCESS) {
118203831d35Sstevel 		/* controller id */
118303831d35Sstevel 		log_printf("%-8lld       ", mcid);
118403831d35Sstevel 
118503831d35Sstevel 		/* group id */
118603831d35Sstevel 		if (id == -1) {
118703831d35Sstevel 			log_printf("-         ");
118803831d35Sstevel 		} else {
118903831d35Sstevel 			log_printf("%-8lld ", id);
119003831d35Sstevel 		}
119103831d35Sstevel 
119203831d35Sstevel 		err = picl_get_propval_by_name(moduleh, PICL_PROP_CLASSNAME,
119303831d35Sstevel 		    piclclass, sizeof (piclclass));
119403831d35Sstevel 		if (err != PICL_SUCCESS)
119503831d35Sstevel 			return (err);
119603831d35Sstevel 
119703831d35Sstevel 		if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE) == 0) {
119803831d35Sstevel 			err = logprintf_memory_module_label(moduleh);
119903831d35Sstevel 			if (err != PICL_SUCCESS)
120003831d35Sstevel 				return (err);
120103831d35Sstevel 		}
120203831d35Sstevel 
120303831d35Sstevel 		got_status = B_FALSE;
120403831d35Sstevel 		err = picldiag_get_fru_parent(moduleh, &fruparenth);
120503831d35Sstevel 		if (err == PICL_SUCCESS) {
120603831d35Sstevel 			err = picldiag_get_string_propval(fruparenth,
120703831d35Sstevel 			    PICL_PROP_OPERATIONAL_STATUS, &status);
120803831d35Sstevel 			if (err == PICL_SUCCESS) {
120903831d35Sstevel 				got_status = B_TRUE;
121003831d35Sstevel 			} else if (err != PICL_PROPNOTFOUND)
121103831d35Sstevel 				return (err);
121203831d35Sstevel 		} else if (err != PICL_PROPNOTFOUND)
121303831d35Sstevel 			return (err);
121403831d35Sstevel 
121503831d35Sstevel 		if (!got_status) {
121603831d35Sstevel 			err = picldiag_get_string_propval(moduleh,
121703831d35Sstevel 			    PICL_PROP_STATUS, &status);
121803831d35Sstevel 			if (err == PICL_SUCCESS)
121903831d35Sstevel 				got_status = B_TRUE;
122003831d35Sstevel 			else if (err != PICL_PROPNOTFOUND)
122103831d35Sstevel 				return (err);
122203831d35Sstevel 		}
122303831d35Sstevel 		if (got_status) {
122403831d35Sstevel 			log_printf("%s", status);
122503831d35Sstevel 			free(status);
122603831d35Sstevel 		}
122703831d35Sstevel 		err = picl_get_propval_by_name(moduleh, PICL_PROP_PEER,
122803831d35Sstevel 		    &moduleh, sizeof (picl_nodehdl_t));
122903831d35Sstevel 
123003831d35Sstevel 		log_printf("\n");
123103831d35Sstevel 	}
123203831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
123303831d35Sstevel 		return (PICL_SUCCESS);
123403831d35Sstevel 	return (err);
123503831d35Sstevel }
123603831d35Sstevel 
123703831d35Sstevel /*
123803831d35Sstevel  * search children to find memory module group under memory-controller
123903831d35Sstevel  */
124003831d35Sstevel static int
find_memory_module_group(picl_nodehdl_t mch,int * print_header)124103831d35Sstevel find_memory_module_group(picl_nodehdl_t mch, int *print_header)
124203831d35Sstevel {
124303831d35Sstevel 	picl_nodehdl_t	memgrph;
124403831d35Sstevel 	uint64_t	mcid;
124503831d35Sstevel 	int		err;
124603831d35Sstevel 	char		piclclass[PICL_CLASSNAMELEN_MAX];
124703831d35Sstevel 
124803831d35Sstevel 	mcid = picldiag_get_uint_propval(mch, OBP_PROP_PORTID, &err);
124903831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
125003831d35Sstevel 		mcid = DEFAULT_PORTID;
125103831d35Sstevel 	else if (err != PICL_SUCCESS)
125203831d35Sstevel 		return (err);
125303831d35Sstevel 
125403831d35Sstevel 	err = picl_get_propval_by_name(mch, PICL_PROP_CHILD,
125503831d35Sstevel 	    &memgrph, sizeof (picl_nodehdl_t));
125603831d35Sstevel 	while (err == PICL_SUCCESS) {
125703831d35Sstevel 		err = picl_get_propval_by_name(memgrph,
125803831d35Sstevel 		    PICL_PROP_CLASSNAME, piclclass, sizeof (piclclass));
125903831d35Sstevel 		if (err != PICL_SUCCESS)
126003831d35Sstevel 			return (err);
126103831d35Sstevel 
126203831d35Sstevel 		if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE_GROUP) == 0) {
126303831d35Sstevel 			if (*print_header == 1) {
126403831d35Sstevel 				log_printf(
126503831d35Sstevel 				    dgettext(TEXT_DOMAIN,
1266*2983dda7SMichael Bergknoff 				    "\nMemory Module Groups:\n"));
126703831d35Sstevel 				log_printf("--------------------------");
126803831d35Sstevel 				log_printf("------\n");
126903831d35Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
127003831d35Sstevel 				    "ControllerID   GroupID  Labels\n"));
127103831d35Sstevel 				log_printf("--------------------------");
127203831d35Sstevel 				log_printf("------\n");
127303831d35Sstevel 				*print_header = 0;
127403831d35Sstevel 			}
127503831d35Sstevel 			err = logprintf_memory_module_group_info(memgrph, mcid);
127603831d35Sstevel 			if (err != PICL_SUCCESS)
127703831d35Sstevel 				return (err);
127803831d35Sstevel 		}
127903831d35Sstevel 
128003831d35Sstevel 		err = picl_get_propval_by_name(memgrph, PICL_PROP_PEER,
128103831d35Sstevel 		    &memgrph, sizeof (picl_nodehdl_t));
128203831d35Sstevel 	}
128303831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
128403831d35Sstevel 		return (PICL_SUCCESS);
128503831d35Sstevel 	return (err);
128603831d35Sstevel }
128703831d35Sstevel 
128803831d35Sstevel /*
128903831d35Sstevel  * print memory module group table per memory-controller
129003831d35Sstevel  */
129103831d35Sstevel static int
print_memory_module_group_table(picl_nodehdl_t plafh)129203831d35Sstevel print_memory_module_group_table(picl_nodehdl_t plafh)
129303831d35Sstevel {
129403831d35Sstevel 	picl_nodehdl_t	mch;
129503831d35Sstevel 	int		err;
129603831d35Sstevel 	char		piclclass[PICL_CLASSNAMELEN_MAX];
129703831d35Sstevel 	int		print_header;
129803831d35Sstevel 
129903831d35Sstevel 	print_header = 1;
130003831d35Sstevel 
130103831d35Sstevel 	/*
130203831d35Sstevel 	 * find memory-controller
130303831d35Sstevel 	 */
130403831d35Sstevel 	err = picl_get_propval_by_name(plafh, PICL_PROP_CHILD, &mch,
130503831d35Sstevel 	    sizeof (picl_nodehdl_t));
130603831d35Sstevel 	while (err == PICL_SUCCESS) {
130703831d35Sstevel 		err = picl_get_propval_by_name(mch, PICL_PROP_CLASSNAME,
130803831d35Sstevel 		    piclclass, sizeof (piclclass));
130903831d35Sstevel 		if (err != PICL_SUCCESS)
131003831d35Sstevel 			return (err);
131103831d35Sstevel 
131203831d35Sstevel 		if (strcmp(piclclass, PICL_CLASS_MEMORY_CONTROLLER) != 0) {
131303831d35Sstevel 			err = print_memory_module_group_table(mch);
131403831d35Sstevel 			if (err != PICL_SUCCESS)
131503831d35Sstevel 				return (err);
131603831d35Sstevel 			err = picl_get_propval_by_name(mch, PICL_PROP_PEER,
131703831d35Sstevel 			    &mch, sizeof (picl_nodehdl_t));
131803831d35Sstevel 			continue;
131903831d35Sstevel 		}
132003831d35Sstevel 
132103831d35Sstevel 		err = find_memory_module_group(mch, &print_header);
132203831d35Sstevel 		if (err != PICL_SUCCESS)
132303831d35Sstevel 			return (err);
132403831d35Sstevel 
132503831d35Sstevel 		err = picl_get_propval_by_name(mch, PICL_PROP_PEER,
132603831d35Sstevel 		    &mch, sizeof (picl_nodehdl_t));
132703831d35Sstevel 	}
132803831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
132903831d35Sstevel 		return (PICL_SUCCESS);
133003831d35Sstevel 
133103831d35Sstevel 	return (err);
133203831d35Sstevel }
133303831d35Sstevel 
133403831d35Sstevel /*
133503831d35Sstevel  * print bank table
133603831d35Sstevel  */
133703831d35Sstevel static int
print_bank_table(void)133803831d35Sstevel print_bank_table(void)
133903831d35Sstevel {
134003831d35Sstevel 	bank_list_t	*ptr;
134103831d35Sstevel 	picl_nodehdl_t	bankh;
134203831d35Sstevel 	picl_nodehdl_t	memgrph;
134303831d35Sstevel 	picl_nodehdl_t	mch;
134403831d35Sstevel 	int		err;
134503831d35Sstevel 	int32_t		i;
134603831d35Sstevel 	uint64_t	size;
134703831d35Sstevel 	int		id;
134803831d35Sstevel 
134903831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "\nBank Table:\n"));
135003831d35Sstevel 	log_printf("---------------------------------------");
135103831d35Sstevel 	log_printf("--------------------\n");
135203831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "           Physical Location\n"));
135303831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "ID       ControllerID  GroupID   "));
135403831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Size       Interleave Way\n"));
135503831d35Sstevel 	log_printf("---------------------------------------");
135603831d35Sstevel 	log_printf("--------------------\n");
135703831d35Sstevel 
135803831d35Sstevel 	for (ptr = mem_banks; ptr != NULL; ptr = ptr->next) {
135903831d35Sstevel 		bankh = ptr->nodeh;
136003831d35Sstevel 		id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err);
136103831d35Sstevel 		if (err != PICL_SUCCESS)
136203831d35Sstevel 			log_printf("%-8s ", "-");
136303831d35Sstevel 		else
136403831d35Sstevel 			log_printf("%-8d ", id);
136503831d35Sstevel 
136603831d35Sstevel 		/* find memory-module-group */
136703831d35Sstevel 		err = picl_get_propval_by_name(bankh,
136803831d35Sstevel 		    PICL_REFPROP_MEMORY_MODULE_GROUP, &memgrph,
136903831d35Sstevel 		    sizeof (memgrph));
137003831d35Sstevel 		if (err == PICL_PROPNOTFOUND) {
137103831d35Sstevel 			log_printf("%-8s      ", "-");
137203831d35Sstevel 			log_printf("%-8s  ", "-");
137303831d35Sstevel 		} else if (err != PICL_SUCCESS)
137403831d35Sstevel 			return (err);
137503831d35Sstevel 		else {
137603831d35Sstevel 			/*
137703831d35Sstevel 			 * get controller id
137803831d35Sstevel 			 */
137903831d35Sstevel 			err = picl_get_propval_by_name(memgrph,
138003831d35Sstevel 			    PICL_PROP_PARENT, &mch, sizeof (picl_nodehdl_t));
138103831d35Sstevel 			if (err != PICL_SUCCESS)
138203831d35Sstevel 				return (err);
138303831d35Sstevel 
138403831d35Sstevel 			id = picldiag_get_uint_propval(mch, OBP_PROP_PORTID,
138503831d35Sstevel 			    &err);
138603831d35Sstevel 			if (err == PICL_PROPNOTFOUND)
138703831d35Sstevel 				id = DEFAULT_PORTID; /* use default */
138803831d35Sstevel 			else if (err != PICL_SUCCESS)
138903831d35Sstevel 				return (err);
139003831d35Sstevel 
139103831d35Sstevel 			log_printf("%-8d      ", id);
139203831d35Sstevel 
139303831d35Sstevel 			/* get group id */
139403831d35Sstevel 			id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID,
139503831d35Sstevel 			    &err);
139603831d35Sstevel 			if (err == PICL_PROPNOTFOUND)
139703831d35Sstevel 				log_printf("-          ");
139803831d35Sstevel 			else if (err == PICL_SUCCESS)
139903831d35Sstevel 				log_printf("%-8d  ", id);
140003831d35Sstevel 			else
140103831d35Sstevel 				return (err);
140203831d35Sstevel 		}
140303831d35Sstevel 
140403831d35Sstevel 		size = picldiag_get_uint_propval(bankh, PICL_PROP_SIZE, &err);
140503831d35Sstevel 		if (err == PICL_PROPNOTFOUND)
140603831d35Sstevel 			log_printf("-        	 ");
140703831d35Sstevel 		else if (err == PICL_SUCCESS)
140803831d35Sstevel 			logprintf_size(size);
140903831d35Sstevel 		else
141003831d35Sstevel 			return (err);
141103831d35Sstevel 
141203831d35Sstevel 		log_printf("     ");
141303831d35Sstevel 		for (i = 0; i < ptr->iway_count; i++) {
141403831d35Sstevel 			if (i != 0)
141503831d35Sstevel 				log_printf(",");
141603831d35Sstevel 			log_printf("%d", ptr->iway[i]);
141703831d35Sstevel 		}
141803831d35Sstevel 
141903831d35Sstevel 		log_printf("\n");
142003831d35Sstevel 	}
142103831d35Sstevel 	return (PICL_SUCCESS);
142203831d35Sstevel }
142303831d35Sstevel 
142403831d35Sstevel /*
142503831d35Sstevel  * callback function to print segment, add the bank in the list and
142603831d35Sstevel  * return the bank list
142703831d35Sstevel  */
142803831d35Sstevel /* ARGSUSED */
142903831d35Sstevel static int
memseg_callback(picl_nodehdl_t segh,void * args)143003831d35Sstevel memseg_callback(picl_nodehdl_t segh, void *args)
143103831d35Sstevel {
143203831d35Sstevel 	seg_info_t	seginfo;
143303831d35Sstevel 	int		err;
143403831d35Sstevel 
143503831d35Sstevel 	/* get base address */
143603831d35Sstevel 	seginfo.base = picldiag_get_uint_propval(segh, PICL_PROP_BASEADDRESS,
143703831d35Sstevel 	    &err);
143803831d35Sstevel 	if (err == PICL_PROPNOTFOUND) {
143903831d35Sstevel 		log_printf("-\n");
144003831d35Sstevel 		return (PICL_WALK_CONTINUE);
144103831d35Sstevel 	} else if (err == PICL_SUCCESS)
144203831d35Sstevel 		log_printf("0x%-16llx ", seginfo.base);
144303831d35Sstevel 	else
144403831d35Sstevel 		return (err);
144503831d35Sstevel 
144603831d35Sstevel 	/* get size */
144703831d35Sstevel 	seginfo.size = picldiag_get_uint_propval(segh, PICL_PROP_SIZE, &err);
144803831d35Sstevel 	if (err == PICL_PROPNOTFOUND) {
144903831d35Sstevel 		log_printf("-\n");
145003831d35Sstevel 		return (PICL_WALK_CONTINUE);
145103831d35Sstevel 	} else if (err == PICL_SUCCESS)
145203831d35Sstevel 		logprintf_size(seginfo.size);
145303831d35Sstevel 	else
145403831d35Sstevel 		return (err);
145503831d35Sstevel 
145603831d35Sstevel 	/* get interleave factor */
145703831d35Sstevel 	seginfo.ifactor = picldiag_get_uint_propval(segh,
145803831d35Sstevel 	    PICL_PROP_INTERLEAVE_FACTOR, &err);
145903831d35Sstevel 
146003831d35Sstevel 	if (err == PICL_PROPNOTFOUND) {
146103831d35Sstevel 		log_printf("       -\n");
146203831d35Sstevel 		return (PICL_WALK_CONTINUE);
146303831d35Sstevel 	} else if (err == PICL_SUCCESS)
146403831d35Sstevel 		log_printf("       %-2d          ", seginfo.ifactor);
146503831d35Sstevel 	else
146603831d35Sstevel 		return (err);
146703831d35Sstevel 
146803831d35Sstevel 	seginfo.bank_count = 0;
146903831d35Sstevel 	err = logprintf_seg_contains_col(segh, &seginfo);
147003831d35Sstevel 	if (err != PICL_SUCCESS)
147103831d35Sstevel 		return (err);
147203831d35Sstevel 	return (PICL_WALK_CONTINUE);
147303831d35Sstevel }
147403831d35Sstevel 
147503831d35Sstevel /*
147603831d35Sstevel  * search children to find memory-segment and set up the bank list
147703831d35Sstevel  */
147803831d35Sstevel static int
find_segments(picl_nodehdl_t plafh)147903831d35Sstevel find_segments(picl_nodehdl_t plafh)
148003831d35Sstevel {
148103831d35Sstevel 	int		err;
148203831d35Sstevel 
148303831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Segment Table:\n"));
148403831d35Sstevel 	log_printf("------------------------------");
148503831d35Sstevel 	log_printf("-----------------------------------------\n");
148603831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Base Address       Size       "));
148703831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Interleave Factor  Contains\n"));
148803831d35Sstevel 	log_printf("------------------------------");
148903831d35Sstevel 	log_printf("-----------------------------------------\n");
149003831d35Sstevel 
149103831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
149203831d35Sstevel 	    NULL, memseg_callback);
149303831d35Sstevel 	return (err);
149403831d35Sstevel }
149503831d35Sstevel 
149603831d35Sstevel /*
149703831d35Sstevel  * display memory configuration
149803831d35Sstevel  */
149903831d35Sstevel static int
display_memory_config(picl_nodehdl_t plafh)150003831d35Sstevel display_memory_config(picl_nodehdl_t plafh)
150103831d35Sstevel {
150203831d35Sstevel 	int		err;
150303831d35Sstevel 
150403831d35Sstevel 	logprintf_header(dgettext(TEXT_DOMAIN, "Memory Configuration"),
150503831d35Sstevel 	    DEFAULT_LINE_WIDTH);
150603831d35Sstevel 
150703831d35Sstevel 	mem_banks = NULL;
150803831d35Sstevel 	err = find_segments(plafh);
150903831d35Sstevel 
151003831d35Sstevel 	if ((err == PICL_SUCCESS) && (mem_banks != NULL))
151103831d35Sstevel 		print_bank_table();
151203831d35Sstevel 
151303831d35Sstevel 	free_bank_list();
151403831d35Sstevel 
151503831d35Sstevel 	return (print_memory_module_group_table(plafh));
151603831d35Sstevel }
151703831d35Sstevel 
151803831d35Sstevel /*
151903831d35Sstevel  * print the hub device
152003831d35Sstevel  */
152103831d35Sstevel static int
logprintf_hub_devices(picl_nodehdl_t hubh)152203831d35Sstevel logprintf_hub_devices(picl_nodehdl_t hubh)
152303831d35Sstevel {
152403831d35Sstevel 	char		*name;
152503831d35Sstevel 	int		portnum;
152603831d35Sstevel 	char		*labelp;
152703831d35Sstevel 	picl_nodehdl_t	parenth;
152803831d35Sstevel 	int		err;
152903831d35Sstevel 
153003831d35Sstevel 	err = picldiag_get_string_propval(hubh, PICL_PROP_NAME, &name);
153103831d35Sstevel 	if (err != PICL_SUCCESS)
153203831d35Sstevel 		return (err);
153303831d35Sstevel 	log_printf("%-12.12s  ", name);
153403831d35Sstevel 	free(name);
153503831d35Sstevel 
153603831d35Sstevel 	err = picl_get_propval_by_name(hubh, PICL_REFPROP_LOC_PARENT, &parenth,
153703831d35Sstevel 	    sizeof (picl_nodehdl_t));
153803831d35Sstevel 
153903831d35Sstevel 	if (err == PICL_SUCCESS) {
154003831d35Sstevel 		/* Read the Label */
154103831d35Sstevel 		err = picldiag_get_label(parenth, &labelp);
154203831d35Sstevel 		if (err == PICL_SUCCESS) {
154303831d35Sstevel 			log_printf("%s\n", labelp);
154403831d35Sstevel 			free(labelp);
154503831d35Sstevel 			return (PICL_SUCCESS);
154603831d35Sstevel 		} else if (err != PICL_PROPNOTFOUND) {
154703831d35Sstevel 			log_printf("\n");
154803831d35Sstevel 			return (err);
154903831d35Sstevel 		}
155003831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND) {
155103831d35Sstevel 		log_printf("\n");
155203831d35Sstevel 		return (err);
155303831d35Sstevel 	}
155403831d35Sstevel 
155503831d35Sstevel 	/* No Label, try the reg */
155603831d35Sstevel 	err = picl_get_propval_by_name(hubh, OBP_PROP_REG, &portnum,
155703831d35Sstevel 	    sizeof (portnum));
155803831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
155903831d35Sstevel 		log_printf("  -\n");
156003831d35Sstevel 	else if (err != PICL_SUCCESS) {
156103831d35Sstevel 		log_printf("\n");
156203831d35Sstevel 		return (err);
156303831d35Sstevel 	} else
156403831d35Sstevel 		log_printf("%3d\n", portnum);
156503831d35Sstevel 
156603831d35Sstevel 	return (PICL_SUCCESS);
156703831d35Sstevel }
156803831d35Sstevel 
156903831d35Sstevel /*
157003831d35Sstevel  * callback functions to display hub devices
157103831d35Sstevel  */
157203831d35Sstevel /* ARGSUSED */
157303831d35Sstevel static int
print_usb_devices(picl_nodehdl_t hubh,void * arg)157403831d35Sstevel print_usb_devices(picl_nodehdl_t hubh, void *arg)
157503831d35Sstevel {
157603831d35Sstevel 	picl_nodehdl_t	chdh;
157703831d35Sstevel 	char		*rootname;
157803831d35Sstevel 	int		type = *(int *)arg;
157903831d35Sstevel 	int		hubnum;
158003831d35Sstevel 	int		err;
158103831d35Sstevel 
158203831d35Sstevel 	err = picl_get_propval_by_name(hubh, PICL_PROP_CHILD, &chdh,
158303831d35Sstevel 	    sizeof (picl_nodehdl_t));
158403831d35Sstevel 
158503831d35Sstevel 	/* print header */
158603831d35Sstevel 	if (err == PICL_SUCCESS) {
158703831d35Sstevel 		err = picldiag_get_string_propval(hubh, PICL_PROP_NAME,
158803831d35Sstevel 		    &rootname);
158903831d35Sstevel 		if (err != PICL_SUCCESS)
159003831d35Sstevel 			return (err);
159103831d35Sstevel 
159203831d35Sstevel 		if (type == USB) {
159303831d35Sstevel 			log_printf("\n===============================");
159403831d35Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
159503831d35Sstevel 			    " %s Devices "), rootname);
159603831d35Sstevel 		} else {
159703831d35Sstevel 			/* Get its hub number */
159803831d35Sstevel 			err = picl_get_propval_by_name(hubh,
159903831d35Sstevel 			    OBP_PROP_REG, &hubnum, sizeof (hubnum));
160003831d35Sstevel 			if ((err != PICL_SUCCESS) &&
160103831d35Sstevel 			    (err != PICL_PROPNOTFOUND)) {
160203831d35Sstevel 				free(rootname);
160303831d35Sstevel 				return (err);
160403831d35Sstevel 			}
160503831d35Sstevel 
160603831d35Sstevel 			log_printf("\n===============================");
160703831d35Sstevel 			if (err == PICL_SUCCESS)
160803831d35Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
160903831d35Sstevel 				    " %s#%d Devices "),
161003831d35Sstevel 				    rootname, hubnum);
161103831d35Sstevel 			else
161203831d35Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
161303831d35Sstevel 				    " %s Devices "), rootname);
161403831d35Sstevel 		}
161503831d35Sstevel 
161603831d35Sstevel 		log_printf("===============================\n\n");
161703831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Name          Port#\n"));
161803831d35Sstevel 		log_printf("------------  -----\n");
161903831d35Sstevel 		free(rootname);
162003831d35Sstevel 
162103831d35Sstevel 		do {
162203831d35Sstevel 			logprintf_hub_devices(chdh);
162303831d35Sstevel 
162403831d35Sstevel 			err = picl_get_propval_by_name(chdh, PICL_PROP_PEER,
162503831d35Sstevel 			    &chdh, sizeof (picl_nodehdl_t));
162603831d35Sstevel 		} while (err == PICL_SUCCESS);
162703831d35Sstevel 	}
162803831d35Sstevel 
162903831d35Sstevel 
163003831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
163103831d35Sstevel 		return (PICL_WALK_CONTINUE);
163203831d35Sstevel 	return (err);
163303831d35Sstevel }
163403831d35Sstevel 
163503831d35Sstevel /*
163603831d35Sstevel  * callback functions to display usb devices
163703831d35Sstevel  */
163803831d35Sstevel /* ARGSUSED */
163903831d35Sstevel static int
usb_callback(picl_nodehdl_t usbh,void * args)164003831d35Sstevel usb_callback(picl_nodehdl_t usbh, void *args)
164103831d35Sstevel {
164203831d35Sstevel 	int		err;
164303831d35Sstevel 	int		type;
164403831d35Sstevel 
164503831d35Sstevel 	type = USB;
164603831d35Sstevel 	err = print_usb_devices(usbh, &type);
164703831d35Sstevel 	if (err != PICL_WALK_CONTINUE)
164803831d35Sstevel 		return (err);
164903831d35Sstevel 	type = HUB;
165003831d35Sstevel 	err = picl_walk_tree_by_class(usbh, NULL, &type, print_usb_devices);
165103831d35Sstevel 	if (err == PICL_SUCCESS)
165203831d35Sstevel 		err = PICL_WALK_CONTINUE;
165303831d35Sstevel 	return (err);
165403831d35Sstevel }
165503831d35Sstevel 
165603831d35Sstevel 
165703831d35Sstevel /*
165803831d35Sstevel  * find usb devices and print its information
165903831d35Sstevel  */
166003831d35Sstevel static int
display_usb_devices(picl_nodehdl_t plafh)166103831d35Sstevel display_usb_devices(picl_nodehdl_t plafh)
166203831d35Sstevel {
166303831d35Sstevel 	int err;
166403831d35Sstevel 
166503831d35Sstevel 	/*
166603831d35Sstevel 	 * get the usb node
166703831d35Sstevel 	 */
166803831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_USB, NULL,
166903831d35Sstevel 	    usb_callback);
167003831d35Sstevel 	return (err);
167103831d35Sstevel }
167203831d35Sstevel 
167303831d35Sstevel 
167403831d35Sstevel 
167503831d35Sstevel /*
167603831d35Sstevel  * If nodeh is the io device, add it into the io list and return
167703831d35Sstevel  * If it is not an io device and it has the subtree, traverse the subtree
167803831d35Sstevel  * and add all leaf io devices
167903831d35Sstevel  */
168003831d35Sstevel static int
add_io_leaves(picl_nodehdl_t nodeh,char * parentname,uint32_t board,uint32_t bus_id,uint64_t slot,uint32_t freq,char * model,char * status)168103831d35Sstevel add_io_leaves(picl_nodehdl_t nodeh, char *parentname, uint32_t board,
168203831d35Sstevel     uint32_t bus_id, uint64_t slot, uint32_t freq, char *model, char *status)
168303831d35Sstevel {
168403831d35Sstevel 	picl_nodehdl_t	childh;
168503831d35Sstevel 	picl_prophdl_t	proph;
168603831d35Sstevel 	picl_propinfo_t	pinfo;
168703831d35Sstevel 	int		err;
168803831d35Sstevel 	char		*nameval;
168903831d35Sstevel 	char		piclclass[PICL_CLASSNAMELEN_MAX];
169003831d35Sstevel 	char		nodename[MAXSTRLEN];
169103831d35Sstevel 	char		name[MAXSTRLEN];
169203831d35Sstevel 	char		*devfs_path;
169303831d35Sstevel 	char		*compatible;
169403831d35Sstevel 	picl_nodehdl_t	fruparenth;
169503831d35Sstevel 	char		*label;
169603831d35Sstevel 	char		binding_name[MAXSTRLEN];
169703831d35Sstevel 
169803831d35Sstevel 	err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME, &pinfo,
169903831d35Sstevel 	    &proph);
170003831d35Sstevel 	if (err != PICL_SUCCESS)
170103831d35Sstevel 		return (err);
170203831d35Sstevel 
170303831d35Sstevel 	nameval = alloca(pinfo.size);
170403831d35Sstevel 	if (nameval == NULL)
170503831d35Sstevel 		return (PICL_FAILURE);
170603831d35Sstevel 
170703831d35Sstevel 	err = picl_get_propval(proph, nameval, pinfo.size);
170803831d35Sstevel 	if (err != PICL_SUCCESS)
170903831d35Sstevel 		return (err);
171003831d35Sstevel 
171103831d35Sstevel 	(void) strlcpy(nodename, nameval, MAXSTRLEN);
171203831d35Sstevel 
171303831d35Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
171403831d35Sstevel 	    piclclass, sizeof (piclclass));
171503831d35Sstevel 	if (err != PICL_SUCCESS)
171603831d35Sstevel 		return (err);
171703831d35Sstevel 
171803831d35Sstevel 	/* if binding_name is found, name will be <nodename>-<binding_name> */
171903831d35Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
172003831d35Sstevel 	    binding_name, sizeof (binding_name));
172103831d35Sstevel 	if (err == PICL_PROPNOTFOUND) {
172203831d35Sstevel 		/*
172303831d35Sstevel 		 * if compatible prop is found, name will be
172403831d35Sstevel 		 * <nodename>-<compatible>
172503831d35Sstevel 		 */
172603831d35Sstevel 		err = picldiag_get_first_compatible_value(nodeh, &compatible);
172703831d35Sstevel 		if (err == PICL_SUCCESS) {
172803831d35Sstevel 			strlcat(nodename, "-", MAXSTRLEN);
172903831d35Sstevel 			strlcat(nodename, compatible, MAXSTRLEN);
173003831d35Sstevel 			free(compatible);
173103831d35Sstevel 		} else if (err != PICL_PROPNOTFOUND) {
173203831d35Sstevel 			return (err);
173303831d35Sstevel 		}
173403831d35Sstevel 	} else if (err != PICL_SUCCESS) {
173503831d35Sstevel 		return (err);
173603831d35Sstevel 	} else if (strcmp(nodename, binding_name) != 0) {
173703831d35Sstevel 		if (strcmp(nodename, piclclass) == 0) {
173803831d35Sstevel 			/*
173903831d35Sstevel 			 * nodename same as binding name -
174003831d35Sstevel 			 * no need to display twice
174103831d35Sstevel 			 */
174203831d35Sstevel 			strlcpy(nodename, binding_name, MAXSTRLEN);
174303831d35Sstevel 		} else {
174403831d35Sstevel 			strlcat(nodename, "-", MAXSTRLEN);
174503831d35Sstevel 			strlcat(nodename, binding_name, MAXSTRLEN);
174603831d35Sstevel 		}
174703831d35Sstevel 	}
174803831d35Sstevel 
174903831d35Sstevel 	/*
175003831d35Sstevel 	 * If it is an immediate child under pci and not
175103831d35Sstevel 	 * a bus node, add it to the io list.
175203831d35Sstevel 	 * If it is a child under sub-bus and it is in an io
175303831d35Sstevel 	 * device, add it to the io list.
175403831d35Sstevel 	 */
175503831d35Sstevel 	if (((parentname == NULL) && (!is_bus(piclclass))) ||
175603831d35Sstevel 	    ((parentname != NULL) && (is_io_device(piclclass)))) {
175703831d35Sstevel 		if (parentname == NULL)
175803831d35Sstevel 			(void) snprintf(name, MAXSTRLEN, "%s", nodename);
175903831d35Sstevel 		else
176003831d35Sstevel 			(void) snprintf(name, MAXSTRLEN, "%s/%s", parentname,
176103831d35Sstevel 			    nodename);
176203831d35Sstevel 
176303831d35Sstevel 		/*
176403831d35Sstevel 		 * append the class if its class is not a generic
176503831d35Sstevel 		 * obp-device class
176603831d35Sstevel 		 */
176703831d35Sstevel 		if (strcmp(piclclass, PICL_CLASS_OBP_DEVICE))
176803831d35Sstevel 			(void) snprintf(name, MAXSTRLEN, "%s (%s)", name,
176903831d35Sstevel 			    piclclass);
177003831d35Sstevel 
177103831d35Sstevel 		err = picldiag_get_fru_parent(nodeh, &fruparenth);
177203831d35Sstevel 		if (err == PICL_PROPNOTFOUND) {
177303831d35Sstevel 			label = NULL;
177403831d35Sstevel 		} else if (err != PICL_SUCCESS) {
177503831d35Sstevel 			return (err);
177603831d35Sstevel 		} else {
177703831d35Sstevel 			err = picldiag_get_combined_label(fruparenth, &label,
177803831d35Sstevel 			    15);
177903831d35Sstevel 			if (err == PICL_PROPNOTFOUND)
178003831d35Sstevel 				label = NULL;
178103831d35Sstevel 			else if (err != PICL_SUCCESS)
178203831d35Sstevel 				return (err);
178303831d35Sstevel 		}
178403831d35Sstevel 		/* devfs-path */
178503831d35Sstevel 		err =  picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH,
178603831d35Sstevel 		    &devfs_path);
178703831d35Sstevel 		if (err == PICL_PROPNOTFOUND)
178803831d35Sstevel 			devfs_path = NULL;
178903831d35Sstevel 		else if (err != PICL_SUCCESS)
179003831d35Sstevel 			return (err);
179103831d35Sstevel 
179203831d35Sstevel 		add_io_card(board, bus_id, slot, label, freq, name,
179303831d35Sstevel 		    model, status, devfs_path);
179403831d35Sstevel 		if (label != NULL)
179503831d35Sstevel 			free(label);
179603831d35Sstevel 		if (devfs_path != NULL)
179703831d35Sstevel 			free(devfs_path);
179803831d35Sstevel 		return (PICL_SUCCESS);
179903831d35Sstevel 	}
180003831d35Sstevel 
180103831d35Sstevel 	/*
180203831d35Sstevel 	 * If there is any child, Go through each child.
180303831d35Sstevel 	 */
180403831d35Sstevel 
180503831d35Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
180603831d35Sstevel 	    &childh, sizeof (picl_nodehdl_t));
180703831d35Sstevel 
180803831d35Sstevel 	/* there is a child */
180903831d35Sstevel 	while (err == PICL_SUCCESS) {
181003831d35Sstevel 		if (parentname == NULL)
181103831d35Sstevel 			(void) strlcpy(name, nodename, MAXSTRLEN);
181203831d35Sstevel 		else
181303831d35Sstevel 			(void) snprintf(name, MAXSTRLEN, "%s/%s", parentname,
181403831d35Sstevel 			    nodename);
181503831d35Sstevel 
181603831d35Sstevel 		err = add_io_leaves(childh, name, board, bus_id, slot, freq,
181703831d35Sstevel 		    model, status);
181803831d35Sstevel 		if (err != PICL_SUCCESS)
181903831d35Sstevel 			return (err);
182003831d35Sstevel 		/*
182103831d35Sstevel 		 * get next child
182203831d35Sstevel 		 */
182303831d35Sstevel 		err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
182403831d35Sstevel 		    &childh, sizeof (picl_nodehdl_t));
182503831d35Sstevel 	}
182603831d35Sstevel 
182703831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
182803831d35Sstevel 		return (PICL_SUCCESS);
182903831d35Sstevel 	return (err);
183003831d35Sstevel }
183103831d35Sstevel 
183203831d35Sstevel 
183303831d35Sstevel /*
183403831d35Sstevel  * add all io devices under pci in io list
183503831d35Sstevel  */
183603831d35Sstevel /* ARGSUSED */
183703831d35Sstevel static int
pci_callback(picl_nodehdl_t pcih,void * args)183803831d35Sstevel pci_callback(picl_nodehdl_t pcih, void *args)
183903831d35Sstevel {
184003831d35Sstevel 	picl_nodehdl_t	nodeh;
184103831d35Sstevel 	int		err;
184203831d35Sstevel 	char		piclclass[PICL_CLASSNAMELEN_MAX];
184303831d35Sstevel 	uint32_t	boardnum;
184403831d35Sstevel 	uint32_t	bus_id;
184503831d35Sstevel 	uint32_t	slot;
184603831d35Sstevel 	uint32_t	freq;
184703831d35Sstevel 	char		*model;
184803831d35Sstevel 	char		*status;
184903831d35Sstevel 
185003831d35Sstevel 	/* Fill in common infomation */
185103831d35Sstevel 	bus_id = PCI_TYPE;
185203831d35Sstevel 
185303831d35Sstevel 	/*
185403831d35Sstevel 	 * Check if it has the freq, if not,
185503831d35Sstevel 	 * If not, use its parent's freq
185603831d35Sstevel 	 * if its parent's freq is not found, return
185703831d35Sstevel 	 */
185803831d35Sstevel 	err = picldiag_get_clock_freq(pcih, &freq);
185903831d35Sstevel 	if (err == PICL_PROPNOTFOUND) {
186003831d35Sstevel 		err = picldiag_get_clock_from_parent(pcih, &freq);
186103831d35Sstevel 		if (err == PICL_PROPNOTFOUND)
186203831d35Sstevel 			return (PICL_WALK_CONTINUE);
186303831d35Sstevel 		else if (err != PICL_SUCCESS)
186403831d35Sstevel 			return (err);
186503831d35Sstevel 	} else if (err != PICL_SUCCESS)
186603831d35Sstevel 		return (err);
186703831d35Sstevel 
186803831d35Sstevel 	/*
186903831d35Sstevel 	 * If no board# is found, set boardnum to 0
187003831d35Sstevel 	 */
187103831d35Sstevel 	boardnum = picldiag_get_uint_propval(pcih, OBP_PROP_BOARD_NUM, &err);
187203831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
187303831d35Sstevel 		boardnum = DEFAULT_BOARD_NUM;
187403831d35Sstevel 	else if (err != PICL_SUCCESS)
187503831d35Sstevel 		return (err);
187603831d35Sstevel 
187703831d35Sstevel 	/* Walk through the children */
187803831d35Sstevel 
187903831d35Sstevel 	err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
188003831d35Sstevel 	    sizeof (picl_nodehdl_t));
188103831d35Sstevel 	while (err == PICL_SUCCESS) {
188203831d35Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
188303831d35Sstevel 		    piclclass, sizeof (piclclass));
188403831d35Sstevel 		if (err != PICL_SUCCESS)
188503831d35Sstevel 			return (err);
188603831d35Sstevel 
188703831d35Sstevel 		/*
188803831d35Sstevel 		 * Skip PCI bridge and USB devices because they will be
188903831d35Sstevel 		 * processed later
189003831d35Sstevel 		 */
189103831d35Sstevel 		if ((strcmp(piclclass, PICL_CLASS_PCI) == 0) ||
189203831d35Sstevel 		    (strcmp(piclclass, PICL_CLASS_USB) == 0)) {
189303831d35Sstevel 			err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
189403831d35Sstevel 			    &nodeh, sizeof (picl_nodehdl_t));
189503831d35Sstevel 			continue;
189603831d35Sstevel 		}
189703831d35Sstevel 
189803831d35Sstevel 		/* Get the device id for pci card */
189903831d35Sstevel 		slot = picldiag_get_uint_propval(nodeh,
190003831d35Sstevel 		    PICL_PROP_DEVICE_ID, &err);
190103831d35Sstevel 		if (err == PICL_PROPNOTFOUND) {
190203831d35Sstevel 			err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
190303831d35Sstevel 			    &nodeh, sizeof (picl_nodehdl_t));
190403831d35Sstevel 			continue;
190503831d35Sstevel 		} else if (err != PICL_SUCCESS)
190603831d35Sstevel 			return (err);
190703831d35Sstevel 
190803831d35Sstevel 		/* Get the model of this card */
190903831d35Sstevel 		err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL,
191003831d35Sstevel 		    &model);
191103831d35Sstevel 		if (err == PICL_PROPNOTFOUND)
191203831d35Sstevel 			model = NULL;
191303831d35Sstevel 		else if (err != PICL_SUCCESS)
191403831d35Sstevel 			return (err);
191503831d35Sstevel 
191603831d35Sstevel 		err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS,
191703831d35Sstevel 		    &status);
191803831d35Sstevel 		if (err == PICL_PROPNOTFOUND) {
191903831d35Sstevel 			status = malloc(5);
192003831d35Sstevel 			if (status == NULL)
192103831d35Sstevel 				return (PICL_FAILURE);
192203831d35Sstevel 			strlcpy(status, "okay", 5);
192303831d35Sstevel 		} else if (err != PICL_SUCCESS)
192403831d35Sstevel 			return (err);
192503831d35Sstevel 
192603831d35Sstevel 		err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot,
192703831d35Sstevel 		    freq, model, status);
192803831d35Sstevel 
192903831d35Sstevel 		if (model != NULL)
193003831d35Sstevel 			free(model);
193103831d35Sstevel 
193203831d35Sstevel 		if (status != NULL)
193303831d35Sstevel 			free(status);
193403831d35Sstevel 
193503831d35Sstevel 		if (err != PICL_SUCCESS)
193603831d35Sstevel 			return (err);
193703831d35Sstevel 
193803831d35Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
193903831d35Sstevel 		    sizeof (picl_nodehdl_t));
194003831d35Sstevel 
194103831d35Sstevel 	}
194203831d35Sstevel 
194303831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
194403831d35Sstevel 		return (PICL_WALK_CONTINUE);
194503831d35Sstevel 
194603831d35Sstevel 	return (err);
194703831d35Sstevel }
194803831d35Sstevel 
194903831d35Sstevel 
195003831d35Sstevel /*
195103831d35Sstevel  * loop through all children and add io devices in io list
195203831d35Sstevel  */
195303831d35Sstevel static int
process_io_leaves(picl_nodehdl_t rooth)195403831d35Sstevel process_io_leaves(picl_nodehdl_t rooth)
195503831d35Sstevel {
195603831d35Sstevel 	picl_nodehdl_t	nodeh;
195703831d35Sstevel 	char		classval[PICL_CLASSNAMELEN_MAX];
195803831d35Sstevel 	int		err;
195903831d35Sstevel 
196003831d35Sstevel 	err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh,
196103831d35Sstevel 	    sizeof (picl_nodehdl_t));
196203831d35Sstevel 	while (err == PICL_SUCCESS) {
196303831d35Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
196403831d35Sstevel 		    classval, sizeof (classval));
196503831d35Sstevel 		if (err != PICL_SUCCESS)
196603831d35Sstevel 			return (err);
196703831d35Sstevel 
196803831d35Sstevel 		if (err != PICL_SUCCESS)
196903831d35Sstevel 			return (err);
197003831d35Sstevel 
197103831d35Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
197203831d35Sstevel 		    sizeof (picl_nodehdl_t));
197303831d35Sstevel 	}
197403831d35Sstevel 
197503831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
197603831d35Sstevel 		return (PICL_SUCCESS);
197703831d35Sstevel 
197803831d35Sstevel 	return (err);
197903831d35Sstevel }
198003831d35Sstevel 
198103831d35Sstevel 
198203831d35Sstevel /*
198303831d35Sstevel  * find all io devices and add them in the io list
198403831d35Sstevel  */
198503831d35Sstevel static int
gather_io_cards(picl_nodehdl_t plafh)198603831d35Sstevel gather_io_cards(picl_nodehdl_t plafh)
198703831d35Sstevel {
198803831d35Sstevel 	int		err;
198903831d35Sstevel 
199003831d35Sstevel 	/*
199103831d35Sstevel 	 * look for io devices under the immediate children of platform
199203831d35Sstevel 	 */
199303831d35Sstevel 	err = process_io_leaves(plafh);
199403831d35Sstevel 
199503831d35Sstevel 	if (err != PICL_SUCCESS)
199603831d35Sstevel 		return (err);
199703831d35Sstevel 
199803831d35Sstevel 	if (err != PICL_SUCCESS)
199903831d35Sstevel 		return (err);
200003831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
200103831d35Sstevel 	    PICL_CLASS_PCI, pci_callback);
200203831d35Sstevel 	if (err != PICL_SUCCESS)
200303831d35Sstevel 		return (err);
200403831d35Sstevel 	return (err);
200503831d35Sstevel }
200603831d35Sstevel 
200703831d35Sstevel static void
picldiag_display_io_cards(struct io_card * list)200803831d35Sstevel picldiag_display_io_cards(struct io_card *list)
200903831d35Sstevel {
201003831d35Sstevel 	static int banner = 0; /* Have we printed the column headings? */
201103831d35Sstevel 	struct io_card *p;
201203831d35Sstevel 
201303831d35Sstevel 	if (list == NULL)
201403831d35Sstevel 		return;
201503831d35Sstevel 
201603831d35Sstevel 	if (banner == 0) {
201703831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
201803831d35Sstevel 		    "Bus   Freq      Slot +  Name +\n"), 0);
201903831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Type  MHz       Status  "
2020*2983dda7SMichael Bergknoff 		    "Path                          "
2021*2983dda7SMichael Bergknoff 		    "Model"), 0);
202203831d35Sstevel 		log_printf("\n", 0);
202303831d35Sstevel 		log_printf("----  ----  ----------  "
2024*2983dda7SMichael Bergknoff 		    "----------------------------  "
2025*2983dda7SMichael Bergknoff 		    "--------------------", 0);
202603831d35Sstevel 		log_printf("\n", 0);
202703831d35Sstevel 		banner = 1;
202803831d35Sstevel 	}
202903831d35Sstevel 
203003831d35Sstevel 	for (p = list; p != NULL; p = p -> next) {
203103831d35Sstevel 		log_printf("%-4s  ", p->bus_type, 0);
203203831d35Sstevel 		log_printf("%3d   ", p->freq, 0);
203303831d35Sstevel 		/*
203403831d35Sstevel 		 * We check to see if it's an int or
203503831d35Sstevel 		 * a char string to display for slot.
203603831d35Sstevel 		 */
203703831d35Sstevel 		if (p->slot == PCI_SLOT_IS_STRING)
203803831d35Sstevel 			log_printf("%10s  ", p->slot_str, 0);
203903831d35Sstevel 		else
204003831d35Sstevel 			log_printf("%10d  ", p->slot, 0);
204103831d35Sstevel 
204203831d35Sstevel 		log_printf("%-28.28s", p->name, 0);
204303831d35Sstevel 		if (strlen(p->name) > 28)
204403831d35Sstevel 			log_printf("+ ", 0);
204503831d35Sstevel 		else
204603831d35Sstevel 			log_printf("  ", 0);
204703831d35Sstevel 		log_printf("%-19.19s", p->model, 0);
204803831d35Sstevel 		if (strlen(p->model) > 19)
204903831d35Sstevel 			log_printf("+", 0);
205003831d35Sstevel 		log_printf("\n", 0);
205103831d35Sstevel 		log_printf("            %10s  ", p->status, 0);
205203831d35Sstevel 		if (strlen(p->notes) > 0)
205303831d35Sstevel 			log_printf("%s", p->notes, 0);
205403831d35Sstevel 		log_printf("\n\n", 0);
205503831d35Sstevel 	}
205603831d35Sstevel }
205703831d35Sstevel 
205803831d35Sstevel /*
205903831d35Sstevel  * display all io devices
206003831d35Sstevel  */
206103831d35Sstevel static int
display_io_device_info(picl_nodehdl_t plafh)206203831d35Sstevel display_io_device_info(picl_nodehdl_t plafh)
206303831d35Sstevel {
206403831d35Sstevel 	int	err;
206503831d35Sstevel 
206603831d35Sstevel 	err = gather_io_cards(plafh);
206703831d35Sstevel 	if (err != PICL_SUCCESS)
206803831d35Sstevel 		return (err);
206903831d35Sstevel 
207003831d35Sstevel 	logprintf_header(dgettext(TEXT_DOMAIN, "IO Devices"),
207103831d35Sstevel 	    DEFAULT_LINE_WIDTH);
207203831d35Sstevel 
207303831d35Sstevel 	picldiag_display_io_cards(io_card_list);
207403831d35Sstevel 
207503831d35Sstevel 	free_io_cards(io_card_list);
207603831d35Sstevel 
207703831d35Sstevel 	return (PICL_SUCCESS);
207803831d35Sstevel }
207903831d35Sstevel 
208003831d35Sstevel /*
208103831d35Sstevel  * print fan device information
208203831d35Sstevel  */
208303831d35Sstevel static int
logprintf_fan_info(picl_nodehdl_t fanh)208403831d35Sstevel logprintf_fan_info(picl_nodehdl_t fanh)
208503831d35Sstevel {
208603831d35Sstevel 	int		err;
208703831d35Sstevel 	char		*label;
208803831d35Sstevel 	char		*unit;
208903831d35Sstevel 	int64_t		speed;
209003831d35Sstevel 	int64_t		min_speed;
209103831d35Sstevel 	picl_nodehdl_t	fruph;
209203831d35Sstevel 
209303831d35Sstevel 	err = picldiag_get_fru_parent(fanh, &fruph);
209403831d35Sstevel 	if (err != PICL_SUCCESS)
209503831d35Sstevel 		return (err);
209603831d35Sstevel 
209703831d35Sstevel 	err = picldiag_get_combined_label(fruph, &label, 14);
209803831d35Sstevel 	if (err != PICL_SUCCESS)
209903831d35Sstevel 		return (err);
210003831d35Sstevel 
210103831d35Sstevel 	log_printf("%-14s ", label);
210203831d35Sstevel 	free(label);
210303831d35Sstevel 
210403831d35Sstevel 	err = picldiag_get_label(fanh, &label);
210503831d35Sstevel 	if (err == PICL_SUCCESS) {
210603831d35Sstevel 		log_printf("%-14s  ", label);
210703831d35Sstevel 		free(label);
210803831d35Sstevel 	} else if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
210903831d35Sstevel 		log_printf("  -           ");
211003831d35Sstevel 	} else
211103831d35Sstevel 		return (err);
211203831d35Sstevel 
211303831d35Sstevel 	speed = picldiag_get_uint_propval(fanh, PICL_PROP_FAN_SPEED, &err);
211403831d35Sstevel 	if (err == PICL_SUCCESS) {
211503831d35Sstevel 		min_speed = picldiag_get_uint_propval(fanh,
211603831d35Sstevel 		    PICL_PROP_LOW_WARNING_THRESHOLD, &err);
211703831d35Sstevel 		if (err != PICL_SUCCESS)
211803831d35Sstevel 			min_speed = 0;
211903831d35Sstevel 		if (speed < min_speed) {
212003831d35Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
212103831d35Sstevel 			    "failed (%lld"), speed);
212203831d35Sstevel 			err = picldiag_get_string_propval(fanh,
212303831d35Sstevel 			    PICL_PROP_FAN_SPEED_UNIT, &unit);
212403831d35Sstevel 			if (err == PICL_SUCCESS) {
212503831d35Sstevel 				log_printf("%s", unit);
212603831d35Sstevel 				free(unit);
212703831d35Sstevel 			}
212803831d35Sstevel 			log_printf(")");
212903831d35Sstevel 		} else {
213003831d35Sstevel 			log_printf(dgettext(TEXT_DOMAIN, "okay"));
213103831d35Sstevel 		}
213203831d35Sstevel 	} else {
213303831d35Sstevel 		err = picldiag_get_string_propval(fanh,
213403831d35Sstevel 		    PICL_PROP_FAN_SPEED_UNIT, &unit);
213503831d35Sstevel 		if (err == PICL_SUCCESS) {
213603831d35Sstevel 			log_printf("%-12s ", unit);
213703831d35Sstevel 			free(unit);
213803831d35Sstevel 		}
213903831d35Sstevel 	}
214003831d35Sstevel 
214103831d35Sstevel 	log_printf("\n");
214203831d35Sstevel 	return (PICL_SUCCESS);
214303831d35Sstevel }
214403831d35Sstevel 
214503831d35Sstevel static int
fan_callback(picl_nodehdl_t fanh,void * arg)214603831d35Sstevel fan_callback(picl_nodehdl_t fanh, void *arg)
214703831d35Sstevel {
214803831d35Sstevel 	int	*countp = arg;
214903831d35Sstevel 	int		err;
215003831d35Sstevel 
215103831d35Sstevel 	if (*countp == 0) {
215203831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Fan Status:\n"));
215303831d35Sstevel 		log_printf("---------------------------------------\n");
215403831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
215503831d35Sstevel 		    "Location       Sensor          Status          \n"));
215603831d35Sstevel 		log_printf("---------------------------------------\n");
215703831d35Sstevel 	}
215803831d35Sstevel 	*countp += 1;
215903831d35Sstevel 	err = logprintf_fan_info(fanh);
216003831d35Sstevel 	if (err == PICL_SUCCESS)
216103831d35Sstevel 		return (PICL_WALK_CONTINUE);
216203831d35Sstevel 	return (err);
216303831d35Sstevel }
216403831d35Sstevel 
216503831d35Sstevel /*
216603831d35Sstevel  * callback function search children to find fan device and print its speed
216703831d35Sstevel  */
216803831d35Sstevel static int
display_fan_speed(picl_nodehdl_t plafh)216903831d35Sstevel display_fan_speed(picl_nodehdl_t plafh)
217003831d35Sstevel {
217103831d35Sstevel 	int		err;
217203831d35Sstevel 	int		print_header;
217303831d35Sstevel 
217403831d35Sstevel 	print_header = 0;
217503831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_FAN,
217603831d35Sstevel 	    &print_header, fan_callback);
217703831d35Sstevel 	return (err);
217803831d35Sstevel }
217903831d35Sstevel 
218003831d35Sstevel /*
218103831d35Sstevel  * print temperature sensor information
218203831d35Sstevel  */
218303831d35Sstevel static int
logprintf_temp_info(picl_nodehdl_t temph)218403831d35Sstevel logprintf_temp_info(picl_nodehdl_t temph)
218503831d35Sstevel {
218603831d35Sstevel 	int		err;
218703831d35Sstevel 	char		*label;
218803831d35Sstevel 	int64_t		temperature;
218903831d35Sstevel 	int64_t		threshold;
219003831d35Sstevel 	picl_nodehdl_t	fruph;
219103831d35Sstevel 	char		*status = "unknown";
219203831d35Sstevel 	int		got_temp = 0;
219303831d35Sstevel 
219403831d35Sstevel 	err = picldiag_get_fru_parent(temph, &fruph);
219503831d35Sstevel 	if (err != PICL_SUCCESS)
219603831d35Sstevel 		return (err);
219703831d35Sstevel 
219803831d35Sstevel 	err = picldiag_get_combined_label(fruph, &label, 14);
219903831d35Sstevel 	if (err != PICL_SUCCESS)
220003831d35Sstevel 		return (err);
220103831d35Sstevel 
220203831d35Sstevel 	log_printf("%-14s ", label);
220303831d35Sstevel 	free(label);
220403831d35Sstevel 
220503831d35Sstevel 	err = picldiag_get_label(temph, &label);
220603831d35Sstevel 	if (err != PICL_SUCCESS)
220703831d35Sstevel 		return (err);
220803831d35Sstevel 	log_printf("%-14s ", label);
220903831d35Sstevel 	free(label);
221003831d35Sstevel 
221103831d35Sstevel 	temperature = picldiag_get_int_propval(temph, PICL_PROP_TEMPERATURE,
221203831d35Sstevel 	    &err);
221303831d35Sstevel 	if (err == PICL_SUCCESS) {
221403831d35Sstevel 		got_temp = 1;
221503831d35Sstevel 		status = "okay";
221603831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
221703831d35Sstevel 		return (err);
221803831d35Sstevel 	}
221903831d35Sstevel 
222003831d35Sstevel 	threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_WARNING,
222103831d35Sstevel 	    &err);
222203831d35Sstevel 	if (err == PICL_SUCCESS) {
222303831d35Sstevel 		if (got_temp && temperature < threshold)
222403831d35Sstevel 			status = "warning";
222503831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
222603831d35Sstevel 		return (err);
222703831d35Sstevel 	}
222803831d35Sstevel 
222903831d35Sstevel 	threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_SHUTDOWN,
223003831d35Sstevel 	    &err);
223103831d35Sstevel 	if (err == PICL_SUCCESS) {
223203831d35Sstevel 		if (got_temp && temperature < threshold)
223303831d35Sstevel 			status = "failed";
223403831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
223503831d35Sstevel 		return (err);
223603831d35Sstevel 	}
223703831d35Sstevel 
223803831d35Sstevel 	threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_WARNING,
223903831d35Sstevel 	    &err);
224003831d35Sstevel 	if (err == PICL_SUCCESS) {
224103831d35Sstevel 		if (got_temp && temperature > threshold)
224203831d35Sstevel 			status = "warning";
224303831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
224403831d35Sstevel 		return (err);
224503831d35Sstevel 	}
224603831d35Sstevel 
224703831d35Sstevel 	threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_SHUTDOWN,
224803831d35Sstevel 	    &err);
224903831d35Sstevel 	if (err == PICL_SUCCESS) {
225003831d35Sstevel 		if (got_temp && temperature > threshold)
225103831d35Sstevel 			status = "failed";
225203831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
225303831d35Sstevel 		return (err);
225403831d35Sstevel 	}
225503831d35Sstevel 
225603831d35Sstevel 	err = picldiag_get_string_propval(temph, PICL_PROP_CONDITION, &status);
225703831d35Sstevel 	if (err == PICL_SUCCESS) {
225803831d35Sstevel 		log_printf("%s", status);
225903831d35Sstevel 		free(status);
226003831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
226103831d35Sstevel 		return (err);
226203831d35Sstevel 	} else {
226303831d35Sstevel 		log_printf("%s ", status);
226403831d35Sstevel 		if (strcmp(status, "failed") == 0 ||
226503831d35Sstevel 		    strcmp(status, "warning") == 0)
226603831d35Sstevel 			log_printf("(%.2lldC)", temperature);
226703831d35Sstevel 	}
226803831d35Sstevel 
226903831d35Sstevel 	log_printf("\n");
227003831d35Sstevel 	return (PICL_SUCCESS);
227103831d35Sstevel }
227203831d35Sstevel 
227303831d35Sstevel static int
temp_callback(picl_nodehdl_t temph,void * arg)227403831d35Sstevel temp_callback(picl_nodehdl_t temph, void *arg)
227503831d35Sstevel {
227603831d35Sstevel 	int		err;
227703831d35Sstevel 	int	*countp = arg;
227803831d35Sstevel 
227903831d35Sstevel 	if (*countp == 0) {
228003831d35Sstevel 		log_printf("\n");
228103831d35Sstevel 		log_printf("---------------------------------------\n");
228203831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Temperature sensors:\n"));
228303831d35Sstevel 		log_printf("------------------------------------\n");
228403831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
228503831d35Sstevel 		    "Location       Sensor         Status\n"));
228603831d35Sstevel 		log_printf("------------------------------------\n");
228703831d35Sstevel 	}
228803831d35Sstevel 	*countp += 1;
228903831d35Sstevel 	err = logprintf_temp_info(temph);
229003831d35Sstevel 	if (err == PICL_SUCCESS)
229103831d35Sstevel 		return (PICL_WALK_CONTINUE);
229203831d35Sstevel 	return (err);
229303831d35Sstevel }
229403831d35Sstevel 
229503831d35Sstevel /*
229603831d35Sstevel  * callback function search children to find temp sensors and print the temp
229703831d35Sstevel  */
229803831d35Sstevel /* ARGSUSED */
229903831d35Sstevel static int
display_temp(picl_nodehdl_t plafh)230003831d35Sstevel display_temp(picl_nodehdl_t plafh)
230103831d35Sstevel {
230203831d35Sstevel 	int		err;
230303831d35Sstevel 	int		print_header;
230403831d35Sstevel 
230503831d35Sstevel 	print_header = 0;
230603831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_SENSOR,
230703831d35Sstevel 	    &print_header, temp_callback);
230803831d35Sstevel 	if (err != PICL_SUCCESS)
230903831d35Sstevel 		return (err);
231003831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_INDICATOR,
231103831d35Sstevel 	    &print_header, temp_callback);
231203831d35Sstevel 	return (err);
231303831d35Sstevel }
231403831d35Sstevel 
231503831d35Sstevel /*
231603831d35Sstevel  * print current sensor information
231703831d35Sstevel  */
231803831d35Sstevel static int
logprintf_current_info(picl_nodehdl_t currenth)231903831d35Sstevel logprintf_current_info(picl_nodehdl_t currenth)
232003831d35Sstevel {
232103831d35Sstevel 	int		err;
232203831d35Sstevel 	char		*label;
232303831d35Sstevel 	float		current;
232403831d35Sstevel 	float		threshold;
232503831d35Sstevel 	picl_nodehdl_t	fruph;
232603831d35Sstevel 	char		*status = "unknown";
232703831d35Sstevel 	int		got_current = 0;
232803831d35Sstevel 
232903831d35Sstevel 	err = picldiag_get_fru_parent(currenth, &fruph);
233003831d35Sstevel 	if (err != PICL_SUCCESS)
233103831d35Sstevel 		return (err);
233203831d35Sstevel 
233303831d35Sstevel 	err = picldiag_get_combined_label(fruph, &label, 10);
233403831d35Sstevel 	if (err != PICL_SUCCESS)
233503831d35Sstevel 		return (err);
233603831d35Sstevel 
233703831d35Sstevel 	log_printf("%-10s ", label);
233803831d35Sstevel 	free(label);
233903831d35Sstevel 
234003831d35Sstevel 	err = picldiag_get_label(currenth, &label);
234103831d35Sstevel 	if (err != PICL_SUCCESS)
234203831d35Sstevel 		return (err);
234303831d35Sstevel 	log_printf("%-10s  ", label);
234403831d35Sstevel 	free(label);
234503831d35Sstevel 
234603831d35Sstevel 	current = picldiag_get_float_propval(currenth, PICL_PROP_CURRENT, &err);
234703831d35Sstevel 	if (err == PICL_SUCCESS) {
234803831d35Sstevel 		status = "okay";
234903831d35Sstevel 		got_current = 1;
235003831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
235103831d35Sstevel 		return (err);
235203831d35Sstevel 	}
235303831d35Sstevel 
235403831d35Sstevel 	threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_WARNING,
235503831d35Sstevel 	    &err);
235603831d35Sstevel 	if (err == PICL_SUCCESS) {
235703831d35Sstevel 		if (got_current && current < threshold)
235803831d35Sstevel 			status = "warning";
235903831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
236003831d35Sstevel 		return (err);
236103831d35Sstevel 	}
236203831d35Sstevel 
236303831d35Sstevel 	threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_SHUTDOWN,
236403831d35Sstevel 	    &err);
236503831d35Sstevel 	if (err == PICL_SUCCESS) {
236603831d35Sstevel 		if (got_current && current < threshold)
236703831d35Sstevel 			status = "failed";
236803831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
236903831d35Sstevel 		return (err);
237003831d35Sstevel 	}
237103831d35Sstevel 
237203831d35Sstevel 	threshold = picldiag_get_float_propval(currenth, PICL_PROP_HIGH_WARNING,
237303831d35Sstevel 	    &err);
237403831d35Sstevel 	if (err == PICL_SUCCESS) {
237503831d35Sstevel 		if (got_current && current > threshold)
237603831d35Sstevel 			status = "warning";
237703831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
237803831d35Sstevel 		return (err);
237903831d35Sstevel 	}
238003831d35Sstevel 
238103831d35Sstevel 	threshold = picldiag_get_float_propval(currenth,
238203831d35Sstevel 	    PICL_PROP_HIGH_SHUTDOWN, &err);
238303831d35Sstevel 	if (err == PICL_SUCCESS) {
238403831d35Sstevel 		if (got_current && current > threshold)
238503831d35Sstevel 			status = "failed";
238603831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
238703831d35Sstevel 		return (err);
238803831d35Sstevel 	}
238903831d35Sstevel 
239003831d35Sstevel 	err = picldiag_get_string_propval(currenth,
239103831d35Sstevel 	    PICL_PROP_CONDITION, &status);
239203831d35Sstevel 	if (err == PICL_SUCCESS) {
239303831d35Sstevel 		log_printf(" %s", status);
239403831d35Sstevel 		free(status);
239503831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
239603831d35Sstevel 		return (err);
239703831d35Sstevel 	} else {
239803831d35Sstevel 		log_printf("%s ", status);
239903831d35Sstevel 		if (strcmp(status, "failed") == 0 ||
240003831d35Sstevel 		    strcmp(status, "warning") == 0)
240103831d35Sstevel 			log_printf("(%.2fA)", current);
240203831d35Sstevel 	}
240303831d35Sstevel 
240403831d35Sstevel 	log_printf("\n");
240503831d35Sstevel 	return (PICL_SUCCESS);
240603831d35Sstevel }
240703831d35Sstevel 
240803831d35Sstevel static int
current_callback(picl_nodehdl_t currh,void * arg)240903831d35Sstevel current_callback(picl_nodehdl_t currh, void *arg)
241003831d35Sstevel {
241103831d35Sstevel 	int		err;
241203831d35Sstevel 	int	*countp = arg;
241303831d35Sstevel 
241403831d35Sstevel 	if (*countp == 0) {
241503831d35Sstevel 		log_printf("------------------------------------\n");
241603831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Current sensors:\n"));
241703831d35Sstevel 		log_printf("------------------------------\n");
241803831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
241903831d35Sstevel 		    "Location  Sensor        Status\n"));
242003831d35Sstevel 		log_printf("------------------------------\n");
242103831d35Sstevel 	}
242203831d35Sstevel 	*countp += 1;
242303831d35Sstevel 	err = logprintf_current_info(currh);
242403831d35Sstevel 	if (err == PICL_SUCCESS)
242503831d35Sstevel 		return (PICL_WALK_CONTINUE);
242603831d35Sstevel 	return (err);
242703831d35Sstevel }
242803831d35Sstevel 
242903831d35Sstevel /*
243003831d35Sstevel  * callback function search children to find curr sensors and print the curr
243103831d35Sstevel  */
243203831d35Sstevel /* ARGSUSED */
243303831d35Sstevel static int
display_current(picl_nodehdl_t plafh)243403831d35Sstevel display_current(picl_nodehdl_t plafh)
243503831d35Sstevel {
243603831d35Sstevel 	int		err;
243703831d35Sstevel 	int		print_header;
243803831d35Sstevel 
243903831d35Sstevel 	print_header = 0;
244003831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_SENSOR,
244103831d35Sstevel 	    &print_header, current_callback);
244203831d35Sstevel 	if (err != PICL_SUCCESS)
244303831d35Sstevel 		return (err);
244403831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_INDICATOR,
244503831d35Sstevel 	    &print_header, current_callback);
244603831d35Sstevel 	return (err);
244703831d35Sstevel }
244803831d35Sstevel 
244903831d35Sstevel /*
245003831d35Sstevel  * print voltage sensor information
245103831d35Sstevel  */
245203831d35Sstevel static int
logprintf_voltage_info(picl_nodehdl_t voltageh)245303831d35Sstevel logprintf_voltage_info(picl_nodehdl_t voltageh)
245403831d35Sstevel {
245503831d35Sstevel 	int		err;
245603831d35Sstevel 	char		*label;
245703831d35Sstevel 	float		voltage;
245803831d35Sstevel 	float		threshold;
245903831d35Sstevel 	picl_nodehdl_t	fruph;
246003831d35Sstevel 	char		*status = "unknown";
246103831d35Sstevel 	int		got_voltage = 0;
246203831d35Sstevel 
246303831d35Sstevel 	err = picldiag_get_fru_parent(voltageh, &fruph);
246403831d35Sstevel 	if (err != PICL_SUCCESS)
246503831d35Sstevel 		return (err);
246603831d35Sstevel 
246703831d35Sstevel 	err = picldiag_get_combined_label(fruph, &label, 10);
246803831d35Sstevel 	if (err != PICL_SUCCESS)
246903831d35Sstevel 		return (err);
247003831d35Sstevel 
247103831d35Sstevel 	log_printf("%-10s ", label);
247203831d35Sstevel 	free(label);
247303831d35Sstevel 
247403831d35Sstevel 	err = picldiag_get_label(voltageh, &label);
247503831d35Sstevel 	if (err != PICL_SUCCESS)
247603831d35Sstevel 		return (err);
247703831d35Sstevel 	log_printf("%-12s  ", label);
247803831d35Sstevel 	free(label);
247903831d35Sstevel 
248003831d35Sstevel 	voltage = picldiag_get_float_propval(voltageh, PICL_PROP_VOLTAGE, &err);
248103831d35Sstevel 	if (err == PICL_SUCCESS) {
248203831d35Sstevel 		status = "okay";
248303831d35Sstevel 		got_voltage = 1;
248403831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
248503831d35Sstevel 		return (err);
248603831d35Sstevel 	}
248703831d35Sstevel 
248803831d35Sstevel 	threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_WARNING,
248903831d35Sstevel 	    &err);
249003831d35Sstevel 	if (err == PICL_SUCCESS) {
249103831d35Sstevel 		if (got_voltage && voltage < threshold)
249203831d35Sstevel 			status = "warning";
249303831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
249403831d35Sstevel 		return (err);
249503831d35Sstevel 	}
249603831d35Sstevel 
249703831d35Sstevel 	threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_SHUTDOWN,
249803831d35Sstevel 	    &err);
249903831d35Sstevel 	if (err == PICL_SUCCESS) {
250003831d35Sstevel 		if (got_voltage && voltage < threshold)
250103831d35Sstevel 			status = "failed";
250203831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
250303831d35Sstevel 		return (err);
250403831d35Sstevel 	}
250503831d35Sstevel 
250603831d35Sstevel 	threshold = picldiag_get_float_propval(voltageh, PICL_PROP_HIGH_WARNING,
250703831d35Sstevel 	    &err);
250803831d35Sstevel 	if (err == PICL_SUCCESS) {
250903831d35Sstevel 		if (got_voltage && voltage > threshold)
251003831d35Sstevel 			status = "warning";
251103831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
251203831d35Sstevel 		return (err);
251303831d35Sstevel 	}
251403831d35Sstevel 
251503831d35Sstevel 	threshold = picldiag_get_float_propval(voltageh,
251603831d35Sstevel 	    PICL_PROP_HIGH_SHUTDOWN, &err);
251703831d35Sstevel 	if (err == PICL_SUCCESS) {
251803831d35Sstevel 		if (got_voltage && voltage > threshold)
251903831d35Sstevel 			status = "failed";
252003831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
252103831d35Sstevel 		return (err);
252203831d35Sstevel 	}
252303831d35Sstevel 
252403831d35Sstevel 	err = picldiag_get_string_propval(voltageh,
252503831d35Sstevel 	    PICL_PROP_CONDITION, &status);
252603831d35Sstevel 	if (err == PICL_SUCCESS) {
252703831d35Sstevel 		log_printf("%s", status);
252803831d35Sstevel 		free(status);
252903831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
253003831d35Sstevel 		return (err);
253103831d35Sstevel 	} else {
253203831d35Sstevel 		log_printf("%s ", status);
253303831d35Sstevel 		if (strcmp(status, "warning") == 0 ||
253403831d35Sstevel 		    strcmp(status, "failed") == 0)
253503831d35Sstevel 			log_printf("(%.2fV)", voltage);
253603831d35Sstevel 	}
253703831d35Sstevel 
253803831d35Sstevel 	log_printf("\n");
253903831d35Sstevel 	return (PICL_SUCCESS);
254003831d35Sstevel }
254103831d35Sstevel 
254203831d35Sstevel static int
voltage_callback(picl_nodehdl_t voltageh,void * arg)254303831d35Sstevel voltage_callback(picl_nodehdl_t voltageh, void *arg)
254403831d35Sstevel {
254503831d35Sstevel 	int	*countp = arg;
254603831d35Sstevel 	int		err;
254703831d35Sstevel 
254803831d35Sstevel 	if (*countp == 0) {
254903831d35Sstevel 		log_printf("--------------------------------\n");
255003831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Voltage sensors:\n"));
255103831d35Sstevel 		log_printf("-------------------------------\n");
255203831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
255303831d35Sstevel 		    "Location   Sensor        Status\n"));
255403831d35Sstevel 		log_printf("-------------------------------\n");
255503831d35Sstevel 	}
255603831d35Sstevel 	*countp += 1;
255703831d35Sstevel 	err = logprintf_voltage_info(voltageh);
255803831d35Sstevel 	if (err == PICL_SUCCESS)
255903831d35Sstevel 		return (PICL_WALK_CONTINUE);
256003831d35Sstevel 	return (err);
256103831d35Sstevel }
256203831d35Sstevel 
256303831d35Sstevel /*
256403831d35Sstevel  * callback function search children to find voltage sensors and print voltage
256503831d35Sstevel  */
256603831d35Sstevel /* ARGSUSED */
256703831d35Sstevel static int
display_voltage(picl_nodehdl_t plafh)256803831d35Sstevel display_voltage(picl_nodehdl_t plafh)
256903831d35Sstevel {
257003831d35Sstevel 	int		err;
257103831d35Sstevel 	int		print_header;
257203831d35Sstevel 
257303831d35Sstevel 	print_header = 0;
257403831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_SENSOR,
257503831d35Sstevel 	    &print_header, voltage_callback);
257603831d35Sstevel 	if (err != PICL_SUCCESS)
257703831d35Sstevel 		return (err);
257803831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_INDICATOR,
257903831d35Sstevel 	    &print_header, voltage_callback);
258003831d35Sstevel 	return (err);
258103831d35Sstevel }
258203831d35Sstevel 
258303831d35Sstevel /*
258403831d35Sstevel  * print led device information
258503831d35Sstevel  */
258603831d35Sstevel static int
logprintf_led_info(picl_nodehdl_t ledh)258703831d35Sstevel logprintf_led_info(picl_nodehdl_t ledh)
258803831d35Sstevel {
258903831d35Sstevel 	int		err;
259003831d35Sstevel 	char		*label;
259103831d35Sstevel 	char		*state;
259203831d35Sstevel 	char		*color;
259303831d35Sstevel 	picl_nodehdl_t  fruph;
259403831d35Sstevel 
259503831d35Sstevel 	err = picldiag_get_fru_parent(ledh, &fruph);
259603831d35Sstevel 	if (err != PICL_SUCCESS)
259703831d35Sstevel 		return (err);
259803831d35Sstevel 
259903831d35Sstevel 	err = picldiag_get_combined_label(fruph, &label, 10);
260003831d35Sstevel 	if (err != PICL_SUCCESS) {
260103831d35Sstevel 		log_printf("      -    ", label);
260203831d35Sstevel 	} else {
260303831d35Sstevel 		log_printf("%-10s ", label);
260403831d35Sstevel 		free(label);
260503831d35Sstevel 	}
260603831d35Sstevel 
260703831d35Sstevel 	err = picldiag_get_label(ledh, &label);
260803831d35Sstevel 	if (err != PICL_SUCCESS)
260903831d35Sstevel 		return (err);
261003831d35Sstevel 	log_printf("%-20s  ", label);
261103831d35Sstevel 	free(label);
261203831d35Sstevel 
261303831d35Sstevel 	err = picldiag_get_string_propval(ledh, PICL_PROP_STATE, &state);
261403831d35Sstevel 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
261503831d35Sstevel 		log_printf("     -     ");
261603831d35Sstevel 	} else if (err != PICL_SUCCESS) {
261703831d35Sstevel 		return (err);
261803831d35Sstevel 	} else {
261903831d35Sstevel 		log_printf("%-10s  ", state);
262003831d35Sstevel 		free(state);
262103831d35Sstevel 	}
262203831d35Sstevel 
262303831d35Sstevel 	err = picldiag_get_string_propval(ledh, PICL_PROP_COLOR, &color);
262403831d35Sstevel 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
262503831d35Sstevel 		log_printf("\n");
262603831d35Sstevel 	} else if (err != PICL_SUCCESS) {
262703831d35Sstevel 		return (err);
262803831d35Sstevel 	} else {
262903831d35Sstevel 		log_printf("%-16s\n", color);
263003831d35Sstevel 		free(color);
263103831d35Sstevel 	}
263203831d35Sstevel 
263303831d35Sstevel 	return (PICL_SUCCESS);
263403831d35Sstevel }
263503831d35Sstevel 
263603831d35Sstevel static int
led_callback(picl_nodehdl_t ledh,void * arg)263703831d35Sstevel led_callback(picl_nodehdl_t ledh, void *arg)
263803831d35Sstevel {
263903831d35Sstevel 	int		*countp = arg;
264003831d35Sstevel 	int		err;
264103831d35Sstevel 
264203831d35Sstevel 	if (*countp == 0) {
264303831d35Sstevel 
264403831d35Sstevel 		log_printf("--------------------------------------"
264503831d35Sstevel 		    "------------\n");
264603831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Led State:\n"));
264703831d35Sstevel 		log_printf("--------------------------------------"
264803831d35Sstevel 		    "------------\n");
264903831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
265003831d35Sstevel 		    "Location   Led                   State"
265103831d35Sstevel 		    "       Color\n"));
265203831d35Sstevel 		log_printf("--------------------------------------"
265303831d35Sstevel 		    "------------\n");
265403831d35Sstevel 	}
265503831d35Sstevel 	*countp += 1;
265603831d35Sstevel 	err = logprintf_led_info(ledh);
265703831d35Sstevel 	if (err == PICL_SUCCESS)
265803831d35Sstevel 		return (PICL_WALK_CONTINUE);
265903831d35Sstevel 	return (err);
266003831d35Sstevel }
266103831d35Sstevel 
266203831d35Sstevel /*
266303831d35Sstevel  * callback function search children to find led devices and print status
266403831d35Sstevel  */
266503831d35Sstevel /* ARGSUSED */
266603831d35Sstevel static int
display_led_status(picl_nodehdl_t plafh)266703831d35Sstevel display_led_status(picl_nodehdl_t plafh)
266803831d35Sstevel {
266903831d35Sstevel 	int		print_header;
267003831d35Sstevel 
267103831d35Sstevel 	print_header = 0;
267203831d35Sstevel 	picl_walk_tree_by_class(plafh, PICL_CLASS_LED,
267303831d35Sstevel 	    &print_header, led_callback);
267403831d35Sstevel 	return (PICL_SUCCESS);
267503831d35Sstevel }
267603831d35Sstevel 
267703831d35Sstevel /*
267803831d35Sstevel  * print keyswitch device information
267903831d35Sstevel  */
268003831d35Sstevel static int
logprintf_keyswitch_info(picl_nodehdl_t keyswitchh,picl_nodehdl_t fruph)268103831d35Sstevel logprintf_keyswitch_info(picl_nodehdl_t keyswitchh, picl_nodehdl_t fruph)
268203831d35Sstevel {
268303831d35Sstevel 	int		err;
268403831d35Sstevel 	char		*label;
268503831d35Sstevel 	char		*state;
268603831d35Sstevel 
268703831d35Sstevel 	err = picldiag_get_combined_label(fruph, &label, 10);
268803831d35Sstevel 	if (err != PICL_SUCCESS) {
268903831d35Sstevel 		log_printf("%-14s", "     -");
269003831d35Sstevel 	} else {
269103831d35Sstevel 		log_printf("%-14s ", label);
269203831d35Sstevel 		free(label);
269303831d35Sstevel 	}
269403831d35Sstevel 
269503831d35Sstevel 	err = picldiag_get_label(keyswitchh, &label);
269603831d35Sstevel 	if (err != PICL_SUCCESS)
269703831d35Sstevel 		return (err);
269803831d35Sstevel 	log_printf("%-11s ", label);
269903831d35Sstevel 	free(label);
270003831d35Sstevel 
270103831d35Sstevel 	err = picldiag_get_string_propval(keyswitchh, PICL_PROP_STATE, &state);
270203831d35Sstevel 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
270303831d35Sstevel 		log_printf("     -\n");
270403831d35Sstevel 	} else if (err != PICL_SUCCESS) {
270503831d35Sstevel 		return (err);
270603831d35Sstevel 	} else {
270703831d35Sstevel 		log_printf("%s\n", state);
270803831d35Sstevel 		free(state);
270903831d35Sstevel 	}
271003831d35Sstevel 
271103831d35Sstevel 	return (PICL_SUCCESS);
271203831d35Sstevel }
271303831d35Sstevel 
271403831d35Sstevel static int
keyswitch_callback(picl_nodehdl_t keyswitchh,void * arg)271503831d35Sstevel keyswitch_callback(picl_nodehdl_t keyswitchh, void *arg)
271603831d35Sstevel {
271703831d35Sstevel 	int		*countp = arg;
271803831d35Sstevel 	int		err;
271903831d35Sstevel 	picl_nodehdl_t	fruph;
272003831d35Sstevel 
272103831d35Sstevel 	/*
272203831d35Sstevel 	 * Tamale simulates a key-switch on ENxS. So the presence of a
272303831d35Sstevel 	 * node of class keyswitch is not sufficient. If it has a fru parent
272403831d35Sstevel 	 * or location parent, then believe it.
272503831d35Sstevel 	 */
272603831d35Sstevel 	err = picl_get_propval_by_name(keyswitchh, PICL_REFPROP_FRU_PARENT,
272703831d35Sstevel 	    &fruph, sizeof (fruph));
272803831d35Sstevel 	if (err == PICL_PROPNOTFOUND) {
272903831d35Sstevel 		err = picl_get_propval_by_name(keyswitchh,
273003831d35Sstevel 		    PICL_REFPROP_LOC_PARENT, &fruph, sizeof (fruph));
273103831d35Sstevel 	}
273203831d35Sstevel 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE)
273303831d35Sstevel 		return (PICL_WALK_CONTINUE);
273403831d35Sstevel 	if (err != PICL_SUCCESS)
273503831d35Sstevel 		return (err);
273603831d35Sstevel 
273703831d35Sstevel 	if (*countp == 0) {
273803831d35Sstevel 		log_printf("-----------------------------------------\n");
273903831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Keyswitch:\n"));
274003831d35Sstevel 		log_printf("-----------------------------------------\n");
274103831d35Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
274203831d35Sstevel 		    "Location       Keyswitch   State\n"));
274303831d35Sstevel 		log_printf("-----------------------------------------\n");
274403831d35Sstevel 	}
274503831d35Sstevel 	*countp += 1;
274603831d35Sstevel 	err = logprintf_keyswitch_info(keyswitchh, fruph);
274703831d35Sstevel 	if (err == PICL_SUCCESS)
274803831d35Sstevel 		return (PICL_WALK_CONTINUE);
274903831d35Sstevel 	return (err);
275003831d35Sstevel }
275103831d35Sstevel 
275203831d35Sstevel /*
275303831d35Sstevel  * search children to find keyswitch device(s) and print status
275403831d35Sstevel  */
275503831d35Sstevel /* ARGSUSED */
275603831d35Sstevel static int
display_keyswitch(picl_nodehdl_t plafh)275703831d35Sstevel display_keyswitch(picl_nodehdl_t plafh)
275803831d35Sstevel {
275903831d35Sstevel 	int		print_header = 0;
276003831d35Sstevel 
276103831d35Sstevel 	picl_walk_tree_by_class(plafh, PICL_CLASS_KEYSWITCH,
276203831d35Sstevel 	    &print_header, keyswitch_callback);
276303831d35Sstevel 	return (PICL_SUCCESS);
276403831d35Sstevel }
276503831d35Sstevel 
276603831d35Sstevel /*
276703831d35Sstevel  * display environment status
276803831d35Sstevel  */
276903831d35Sstevel static int
display_envctrl_status(picl_nodehdl_t plafh)277003831d35Sstevel display_envctrl_status(picl_nodehdl_t plafh)
277103831d35Sstevel {
277203831d35Sstevel 	logprintf_header(dgettext(TEXT_DOMAIN, "Environmental Status"),
277303831d35Sstevel 	    DEFAULT_LINE_WIDTH);
277403831d35Sstevel 
277503831d35Sstevel 	display_fan_speed(plafh);
277603831d35Sstevel 	display_temp(plafh);
277703831d35Sstevel 	display_current(plafh);
277803831d35Sstevel 	display_voltage(plafh);
277903831d35Sstevel 	display_keyswitch(plafh);
278003831d35Sstevel 	display_led_status(plafh);
278103831d35Sstevel 
278203831d35Sstevel 	return (PICL_SUCCESS);
278303831d35Sstevel }
278403831d35Sstevel 
278503831d35Sstevel /*
278603831d35Sstevel  * print fru operational status
278703831d35Sstevel  */
278803831d35Sstevel static int
logprintf_fru_oper_status(picl_nodehdl_t fruh,int * countp)278903831d35Sstevel logprintf_fru_oper_status(picl_nodehdl_t fruh, int *countp)
279003831d35Sstevel {
279103831d35Sstevel 	int		err;
279203831d35Sstevel 	char		*label;
279303831d35Sstevel 	char		*status;
279403831d35Sstevel 
279503831d35Sstevel 	err = picldiag_get_combined_label(fruh, &label, 15);
279603831d35Sstevel 	if (err != PICL_SUCCESS)
279703831d35Sstevel 		return (PICL_WALK_CONTINUE);
279803831d35Sstevel 
279903831d35Sstevel 	err = picldiag_get_string_propval(fruh,
280003831d35Sstevel 	    PICL_PROP_OPERATIONAL_STATUS, &status);
280103831d35Sstevel 	if (err == PICL_SUCCESS) {
280203831d35Sstevel 		if (*countp == 0) {
280303831d35Sstevel 			logprintf_header(dgettext(TEXT_DOMAIN,
280403831d35Sstevel 			    "FRU Operational Status"),
280503831d35Sstevel 			    DEFAULT_LINE_WIDTH);
280603831d35Sstevel 			log_printf("-------------------------\n");
280703831d35Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
280803831d35Sstevel 			    "Fru Operational Status:\n"));
280903831d35Sstevel 			log_printf("-------------------------\n");
281003831d35Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
281103831d35Sstevel 			    "Location        Status   \n"));
281203831d35Sstevel 			log_printf("-------------------------\n");
281303831d35Sstevel 		}
281403831d35Sstevel 		*countp += 1;
281503831d35Sstevel 		log_printf("%-15s ", label);
281603831d35Sstevel 		free(label);
281703831d35Sstevel 		log_printf("%s\n", status);
281803831d35Sstevel 		free(status);
281903831d35Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
282003831d35Sstevel 		free(label);
282103831d35Sstevel 		return (err);
282203831d35Sstevel 	} else {
282303831d35Sstevel 		free(label);
282403831d35Sstevel 	}
282503831d35Sstevel 	return (PICL_WALK_CONTINUE);
282603831d35Sstevel }
282703831d35Sstevel 
282803831d35Sstevel static int
fru_oper_status_callback(picl_nodehdl_t fruh,void * arg)282903831d35Sstevel fru_oper_status_callback(picl_nodehdl_t fruh, void *arg)
283003831d35Sstevel {
283103831d35Sstevel 	int err;
283203831d35Sstevel 
283303831d35Sstevel 	err = logprintf_fru_oper_status(fruh, (int *)arg);
283403831d35Sstevel 	return (err);
283503831d35Sstevel }
283603831d35Sstevel 
283703831d35Sstevel /*
283803831d35Sstevel  * display fru operational status
283903831d35Sstevel  */
284003831d35Sstevel static int
display_fru_oper_status(picl_nodehdl_t frutreeh)284103831d35Sstevel display_fru_oper_status(picl_nodehdl_t frutreeh)
284203831d35Sstevel {
284303831d35Sstevel 	int		print_header;
284403831d35Sstevel 
284503831d35Sstevel 	print_header = 0;
284603831d35Sstevel 	picl_walk_tree_by_class(frutreeh, PICL_CLASS_FRU,
284703831d35Sstevel 	    &print_header, fru_oper_status_callback);
284803831d35Sstevel 	return (PICL_SUCCESS);
284903831d35Sstevel }
285003831d35Sstevel 
285103831d35Sstevel /*
285203831d35Sstevel  * check if the node having the version prop
285303831d35Sstevel  * If yes, print its nodename and version
285403831d35Sstevel  */
285503831d35Sstevel /* ARGSUSED */
285603831d35Sstevel static int
asicrev_callback(picl_nodehdl_t nodeh,void * arg)285703831d35Sstevel asicrev_callback(picl_nodehdl_t nodeh, void *arg)
285803831d35Sstevel {
285903831d35Sstevel 	uint32_t	version;
286003831d35Sstevel 	char		*name;
286103831d35Sstevel 	char		*model;
286203831d35Sstevel 	char		*status;
286303831d35Sstevel 	int		err;
286403831d35Sstevel 
286503831d35Sstevel 	version = picldiag_get_uint_propval(nodeh, OBP_PROP_VERSION_NUM,
286603831d35Sstevel 	    &err);
286703831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
286803831d35Sstevel 		return (PICL_WALK_CONTINUE);
286903831d35Sstevel 	else if (err != PICL_SUCCESS)
287003831d35Sstevel 		return (err);
287103831d35Sstevel 
287203831d35Sstevel 	/* devfs-path */
287303831d35Sstevel 	err =  picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, &name);
287403831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
287503831d35Sstevel 		name = NULL;
287603831d35Sstevel 	else if (err != PICL_SUCCESS)
287703831d35Sstevel 		return (err);
287803831d35Sstevel 
287903831d35Sstevel 	/* model */
288003831d35Sstevel 	err =  picldiag_get_string_propval(nodeh, PICL_PROP_BINDING_NAME,
288103831d35Sstevel 	    &model);
288203831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
288303831d35Sstevel 		model = NULL;
288403831d35Sstevel 	else if (err != PICL_SUCCESS)
288503831d35Sstevel 		return (err);
288603831d35Sstevel 
288703831d35Sstevel 	/* status */
288803831d35Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status);
288903831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
289003831d35Sstevel 		status = NULL;
289103831d35Sstevel 	else if (err != PICL_SUCCESS)
289203831d35Sstevel 		return (err);
289303831d35Sstevel 
289403831d35Sstevel 	/*
289503831d35Sstevel 	 * Display the data
289603831d35Sstevel 	 */
289703831d35Sstevel 
289803831d35Sstevel 	/* name */
289903831d35Sstevel 	if (name != NULL) {
290003831d35Sstevel 		log_printf("%-22s ", name);
290103831d35Sstevel 		free(name);
290203831d35Sstevel 	} else
290303831d35Sstevel 		log_printf("%-22s ", "unknown");
290403831d35Sstevel 	/* model */
290503831d35Sstevel 	if (model != NULL) {
290603831d35Sstevel 		log_printf("%-15s  ", model);
290703831d35Sstevel 		free(model);
290803831d35Sstevel 	} else
290903831d35Sstevel 		log_printf("%-15s  ", "unknown");
291003831d35Sstevel 	/* status */
291103831d35Sstevel 	if (status == NULL)
291203831d35Sstevel 		log_printf("%-15s  ", "okay");
291303831d35Sstevel 	else {
291403831d35Sstevel 		log_printf("%-15s  ", status);
291503831d35Sstevel 		free(status);
291603831d35Sstevel 	}
291703831d35Sstevel 	/* revision */
291803831d35Sstevel 	log_printf("  %-4d\n",	version);
291903831d35Sstevel 
292003831d35Sstevel 	return (PICL_WALK_CONTINUE);
292103831d35Sstevel }
292203831d35Sstevel 
292303831d35Sstevel /*
292403831d35Sstevel  * traverse the tree to display asic revision id for ebus
292503831d35Sstevel  */
292603831d35Sstevel /* ARGSUSED */
292703831d35Sstevel static int
ebus_callback(picl_nodehdl_t ebush,void * arg)292803831d35Sstevel ebus_callback(picl_nodehdl_t ebush, void *arg)
292903831d35Sstevel {
293003831d35Sstevel 	uint32_t	id;
293103831d35Sstevel 	char		*name;
293203831d35Sstevel 	int		err;
293303831d35Sstevel 	char		*model;
293403831d35Sstevel 	char		*status;
293503831d35Sstevel 
293603831d35Sstevel 	id = picldiag_get_uint_propval(ebush, OBP_PROP_REVISION_ID, &err);
293703831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
293803831d35Sstevel 		return (PICL_WALK_CONTINUE);
293903831d35Sstevel 	else if (err != PICL_SUCCESS)
294003831d35Sstevel 		return (err);
294103831d35Sstevel 
294203831d35Sstevel 	/* devfs-path */
294303831d35Sstevel 	err =  picldiag_get_string_propval(ebush, PICL_PROP_DEVFS_PATH, &name);
294403831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
294503831d35Sstevel 		name = NULL;
294603831d35Sstevel 	else if (err != PICL_SUCCESS)
294703831d35Sstevel 		return (err);
294803831d35Sstevel 
294903831d35Sstevel 	/* model */
295003831d35Sstevel 	err =  picldiag_get_string_propval(ebush, PICL_PROP_BINDING_NAME,
295103831d35Sstevel 	    &model);
295203831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
295303831d35Sstevel 		model = NULL;
295403831d35Sstevel 	else if (err != PICL_SUCCESS)
295503831d35Sstevel 		return (err);
295603831d35Sstevel 
295703831d35Sstevel 	/* status */
295803831d35Sstevel 	err = picldiag_get_string_propval(ebush, PICL_PROP_STATUS, &status);
295903831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
296003831d35Sstevel 		status = NULL;
296103831d35Sstevel 	else if (err != PICL_SUCCESS)
296203831d35Sstevel 		return (err);
296303831d35Sstevel 
296403831d35Sstevel 	/*
296503831d35Sstevel 	 * Display the data
296603831d35Sstevel 	 */
296703831d35Sstevel 
296803831d35Sstevel 	/* name */
296903831d35Sstevel 	if (name != NULL) {
297003831d35Sstevel 		log_printf("%-22s ", name);
297103831d35Sstevel 		free(name);
297203831d35Sstevel 	} else
297303831d35Sstevel 		log_printf("%-22s ", "unknown");
297403831d35Sstevel 	/* model */
297503831d35Sstevel 	if (model != NULL) {
297603831d35Sstevel 		log_printf("%-15s  ", model);
297703831d35Sstevel 		free(model);
297803831d35Sstevel 	} else
297903831d35Sstevel 		log_printf("%-15s  ", "unknown");
298003831d35Sstevel 	/* status */
298103831d35Sstevel 	if (status == NULL)
298203831d35Sstevel 		log_printf("%-15s  ", "okay");
298303831d35Sstevel 	else {
298403831d35Sstevel 		log_printf("%-15s  ", status);
298503831d35Sstevel 		free(status);
298603831d35Sstevel 	}
298703831d35Sstevel 	/* revision */
298803831d35Sstevel 	log_printf("  %-4d\n",	id);
298903831d35Sstevel 
299003831d35Sstevel 	return (PICL_WALK_CONTINUE);
299103831d35Sstevel }
299203831d35Sstevel 
299303831d35Sstevel /*
299403831d35Sstevel  * display asic revision id
299503831d35Sstevel  */
299603831d35Sstevel static int
display_hw_revisions(picl_nodehdl_t plafh)299703831d35Sstevel display_hw_revisions(picl_nodehdl_t plafh)
299803831d35Sstevel {
299903831d35Sstevel 	int	err;
300003831d35Sstevel 
300103831d35Sstevel 	/* Print the header */
300203831d35Sstevel 	logprintf_header(dgettext(TEXT_DOMAIN, "HW Revisions"),
300303831d35Sstevel 	    DEFAULT_LINE_WIDTH);
300403831d35Sstevel 
300503831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "ASIC Revisions:\n"));
300603831d35Sstevel 	log_printf("-----------------------------");
300703831d35Sstevel 	log_printf("--------------------------------------\n");
300803831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Path                   Device"));
300903831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
301003831d35Sstevel 	    "           Status             Revision\n"));
301103831d35Sstevel 	log_printf("-----------------------------");
301203831d35Sstevel 	log_printf("--------------------------------------\n");
301303831d35Sstevel 
301403831d35Sstevel 	err = picl_walk_tree_by_class(plafh, NULL, NULL, asicrev_callback);
301503831d35Sstevel 	if (err != PICL_SUCCESS)
301603831d35Sstevel 		return (err);
301703831d35Sstevel 
301803831d35Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_EBUS,
301903831d35Sstevel 	    NULL, ebus_callback);
302003831d35Sstevel 	if (err != PICL_SUCCESS)
302103831d35Sstevel 		return (err);
302203831d35Sstevel 
302303831d35Sstevel 	log_printf("\n");
302403831d35Sstevel 
302503831d35Sstevel 	return (err);
302603831d35Sstevel }
302703831d35Sstevel 
302803831d35Sstevel /*
302903831d35Sstevel  * find the options node and its powerfail_time prop
303003831d35Sstevel  * If found, display the list of latest powerfail.
303103831d35Sstevel  */
303203831d35Sstevel /* ARGSUSED */
303303831d35Sstevel static int
options_callback(picl_nodehdl_t nodeh,void * arg)303403831d35Sstevel options_callback(picl_nodehdl_t nodeh, void *arg)
303503831d35Sstevel {
303603831d35Sstevel 	time_t		value;
303703831d35Sstevel 	char		*failtime;
303803831d35Sstevel 	int		err;
303903831d35Sstevel 
304003831d35Sstevel 	err = picldiag_get_string_propval(nodeh, PROP_POWERFAIL_TIME,
304103831d35Sstevel 	    &failtime);
304203831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
304303831d35Sstevel 		return (PICL_WALK_TERMINATE);
304403831d35Sstevel 	else if (err != PICL_SUCCESS)
304503831d35Sstevel 		return (err);
304603831d35Sstevel 
304703831d35Sstevel 	value = (time_t)atoi(failtime);
304803831d35Sstevel 	free(failtime);
304903831d35Sstevel 	if (value == 0)
305003831d35Sstevel 		return (PICL_WALK_TERMINATE);
305103831d35Sstevel 
305203831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Most recent AC Power Failure:\n"));
305303831d35Sstevel 	log_printf("=============================\n");
305403831d35Sstevel 	log_printf("%s", ctime(&value));
305503831d35Sstevel 	log_printf("\n");
305603831d35Sstevel 	return (PICL_WALK_TERMINATE);
305703831d35Sstevel }
305803831d35Sstevel 
305903831d35Sstevel /*
306003831d35Sstevel  * display the OBP and POST prom revisions
306103831d35Sstevel  */
306203831d35Sstevel /* ARGSUSED */
306303831d35Sstevel static int
flashprom_callback(picl_nodehdl_t flashpromh,void * arg)306403831d35Sstevel flashprom_callback(picl_nodehdl_t flashpromh, void *arg)
306503831d35Sstevel {
306603831d35Sstevel 	picl_prophdl_t	proph;
306703831d35Sstevel 	picl_prophdl_t	tblh;
306803831d35Sstevel 	picl_prophdl_t	rowproph;
306903831d35Sstevel 	picl_propinfo_t	pinfo;
307003831d35Sstevel 	char		*prom_version = NULL;
307103831d35Sstevel 	char		*obp_version = NULL;
307203831d35Sstevel 	int		err;
307303831d35Sstevel 
307403831d35Sstevel 	err = picl_get_propinfo_by_name(flashpromh, OBP_PROP_VERSION,
307503831d35Sstevel 	    &pinfo, &proph);
307603831d35Sstevel 	if (err == PICL_PROPNOTFOUND)
307703831d35Sstevel 		return (PICL_WALK_TERMINATE);
307803831d35Sstevel 	else if (err != PICL_SUCCESS)
307903831d35Sstevel 		return (err);
308003831d35Sstevel 
308103831d35Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "System PROM revisions:\n"));
308203831d35Sstevel 	log_printf("----------------------\n");
308303831d35Sstevel 
308403831d35Sstevel 	/*
308503831d35Sstevel 	 * If it's a table prop, the first element is OBP revision
308603831d35Sstevel 	 * The second one is POST revision.
308703831d35Sstevel 	 * If it's a charstring prop, the value will be only OBP revision
308803831d35Sstevel 	 */
308903831d35Sstevel 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
309003831d35Sstevel 		prom_version = alloca(pinfo.size);
309103831d35Sstevel 		if (prom_version == NULL)
309203831d35Sstevel 			return (PICL_FAILURE);
309303831d35Sstevel 		err = picl_get_propval(proph, prom_version, pinfo.size);
309403831d35Sstevel 		if (err != PICL_SUCCESS)
309503831d35Sstevel 			return (err);
309603831d35Sstevel 		log_printf("%s\n", prom_version);
309703831d35Sstevel 	}
309803831d35Sstevel 
309903831d35Sstevel 	if (pinfo.type != PICL_PTYPE_TABLE)	/* not supported type */
310003831d35Sstevel 		return (PICL_WALK_TERMINATE);
310103831d35Sstevel 
310203831d35Sstevel 	err = picl_get_propval(proph, &tblh, pinfo.size);
310303831d35Sstevel 	if (err != PICL_SUCCESS)
310403831d35Sstevel 		return (err);
310503831d35Sstevel 
310603831d35Sstevel 	err = picl_get_next_by_row(tblh, &rowproph);
310703831d35Sstevel 	if (err == PICL_SUCCESS) {
310803831d35Sstevel 		/* get first row */
310903831d35Sstevel 		err = picl_get_propinfo(rowproph, &pinfo);
311003831d35Sstevel 		if (err != PICL_SUCCESS)
3111*2983dda7SMichael Bergknoff 			return (err);
311203831d35Sstevel 
311303831d35Sstevel 		prom_version = alloca(pinfo.size);
311403831d35Sstevel 		if (prom_version == NULL)
311503831d35Sstevel 			return (PICL_FAILURE);
311603831d35Sstevel 
311703831d35Sstevel 		err = picl_get_propval(rowproph, prom_version, pinfo.size);
311803831d35Sstevel 		if (err != PICL_SUCCESS)
311903831d35Sstevel 			return (err);
312003831d35Sstevel 		log_printf("%s\n", prom_version);
312103831d35Sstevel 
312203831d35Sstevel 		/* get second row */
312303831d35Sstevel 		err = picl_get_next_by_col(rowproph, &rowproph);
312403831d35Sstevel 		if (err == PICL_SUCCESS) {
312503831d35Sstevel 			err = picl_get_propinfo(rowproph, &pinfo);
312603831d35Sstevel 			if (err != PICL_SUCCESS)
312703831d35Sstevel 				return (err);
312803831d35Sstevel 
312903831d35Sstevel 			obp_version = alloca(pinfo.size);
313003831d35Sstevel 			if (obp_version == NULL)
313103831d35Sstevel 				return (PICL_FAILURE);
313203831d35Sstevel 			err = picl_get_propval(rowproph, obp_version,
313303831d35Sstevel 			    pinfo.size);
313403831d35Sstevel 			if (err != PICL_SUCCESS)
313503831d35Sstevel 				return (err);
313603831d35Sstevel 			log_printf("%s\n", obp_version);
313703831d35Sstevel 		}
313803831d35Sstevel 	}
313903831d35Sstevel 
314003831d35Sstevel 	return (PICL_WALK_TERMINATE);
314103831d35Sstevel }
314203831d35Sstevel 
314303831d35Sstevel static int
display_system_info(int serrlog,int log_flag,picl_nodehdl_t rooth)314403831d35Sstevel display_system_info(int serrlog, int log_flag, picl_nodehdl_t rooth)
314503831d35Sstevel {
314603831d35Sstevel 	int		err;
314703831d35Sstevel 	picl_nodehdl_t plafh;
314803831d35Sstevel 	picl_nodehdl_t frutreeh;
314903831d35Sstevel 
315003831d35Sstevel 	err = picldiag_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh);
315103831d35Sstevel 	if (err != PICL_SUCCESS)
315203831d35Sstevel 		return (err);
315303831d35Sstevel 
315403831d35Sstevel 	if (!log_flag) {
315503831d35Sstevel 		err = display_platform_banner(plafh);
315603831d35Sstevel 		if (err != PICL_SUCCESS)
315703831d35Sstevel 			return (err);
315803831d35Sstevel 
315903831d35Sstevel 		err = display_system_clock(plafh);
316003831d35Sstevel 		if (err != PICL_SUCCESS)
316103831d35Sstevel 			return (err);
316203831d35Sstevel 
316303831d35Sstevel 		err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY,
316403831d35Sstevel 		    PICL_CLASS_MEMORY, memory_callback);
316503831d35Sstevel 		if (err != PICL_SUCCESS)
316603831d35Sstevel 			return (err);
316703831d35Sstevel 
316803831d35Sstevel 		err = display_cpu_info(plafh);
316903831d35Sstevel 		if (err != PICL_SUCCESS)
317003831d35Sstevel 			return (err);
317103831d35Sstevel 
317203831d35Sstevel 		err = display_io_device_info(plafh);
317303831d35Sstevel 		if (err != PICL_SUCCESS)
317403831d35Sstevel 			return (err);
317503831d35Sstevel 
317603831d35Sstevel 		err = display_memory_config(plafh);
317703831d35Sstevel 		if (err != PICL_SUCCESS)
317803831d35Sstevel 			return (err);
317903831d35Sstevel 
318003831d35Sstevel 		err = display_usb_devices(plafh);
318103831d35Sstevel 		if (err != PICL_SUCCESS)
318203831d35Sstevel 			return (err);
318303831d35Sstevel 	}
318403831d35Sstevel 
318503831d35Sstevel 	if (serrlog) {
318603831d35Sstevel 		err = picl_walk_tree_by_class(rooth, PICL_CLASS_OPTIONS,
318703831d35Sstevel 		    NULL, options_callback);
318803831d35Sstevel 		if (err != PICL_SUCCESS)
318903831d35Sstevel 			return (err);
319003831d35Sstevel 
319103831d35Sstevel 		err = picldiag_get_node_by_name(rooth, PICL_NODE_FRUTREE,
319203831d35Sstevel 		    &frutreeh);
319303831d35Sstevel 
319403831d35Sstevel 		/* return ok if no frutree in picl on schumacher */
319503831d35Sstevel 		if (err != PICL_SUCCESS)
319603831d35Sstevel 			return	(PICL_SUCCESS);
319703831d35Sstevel 
319803831d35Sstevel 		err = display_fru_oper_status(frutreeh);
319903831d35Sstevel 		if (err != PICL_SUCCESS)
320003831d35Sstevel 			return (err);
320103831d35Sstevel 
320203831d35Sstevel 		err = display_hw_revisions(plafh);
320303831d35Sstevel 		if (err != PICL_SUCCESS)
320403831d35Sstevel 			return (err);
320503831d35Sstevel 
320603831d35Sstevel 		err = picl_walk_tree_by_class(plafh, PICL_CLASS_FLASHPROM,
320703831d35Sstevel 		    NULL, flashprom_callback);
320803831d35Sstevel 		if (err != PICL_SUCCESS)
320903831d35Sstevel 			return (err);
321003831d35Sstevel 	}
321103831d35Sstevel 
321203831d35Sstevel 	return (PICL_SUCCESS);
321303831d35Sstevel }
321403831d35Sstevel 
321503831d35Sstevel /* ARGSUSED */
321603831d35Sstevel int
do_prominfo(int serrlog,char * pgname,int log_flag,int prt_flag)321703831d35Sstevel do_prominfo(int serrlog, char *pgname, int log_flag, int prt_flag)
321803831d35Sstevel {
321903831d35Sstevel 	int		err;
322003831d35Sstevel 	char		*errstr;
322103831d35Sstevel 	int		done;
322203831d35Sstevel 	picl_nodehdl_t	rooth;
322303831d35Sstevel 
322403831d35Sstevel 	err = picl_initialize();
322503831d35Sstevel 	if (err != PICL_SUCCESS) {
322603831d35Sstevel 		fprintf(stderr, EM_INIT_FAIL, picl_strerror(err));
322703831d35Sstevel 		exit(1);
322803831d35Sstevel 	}
322903831d35Sstevel 
323003831d35Sstevel 	do {
323103831d35Sstevel 		done = 1;
323203831d35Sstevel 		err = picl_get_root(&rooth);
323303831d35Sstevel 		if (err != PICL_SUCCESS) {
323403831d35Sstevel 			fprintf(stderr, EM_GET_ROOT_FAIL, picl_strerror(err));
323503831d35Sstevel 			exit(1);
323603831d35Sstevel 		}
323703831d35Sstevel 
323803831d35Sstevel 		err = display_system_info(serrlog, log_flag, rooth);
323903831d35Sstevel 
324003831d35Sstevel 		if ((err == PICL_STALEHANDLE) || (err == PICL_INVALIDHANDLE))
324103831d35Sstevel 			done = 0;
324203831d35Sstevel 	} while (!done);
324303831d35Sstevel 
324403831d35Sstevel 	if (err != PICL_SUCCESS) {
324503831d35Sstevel 		errstr = picl_strerror(err);
324603831d35Sstevel 		fprintf(stderr, EM_PRTDIAG_FAIL);
324703831d35Sstevel 		fprintf(stderr, "%s\n", errstr? errstr : " ");
324803831d35Sstevel 	}
324903831d35Sstevel 
325003831d35Sstevel 	(void) picl_shutdown();
325103831d35Sstevel 
325203831d35Sstevel 	return (0);
325303831d35Sstevel }
3254