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