xref: /onnv-gate/usr/src/lib/libprtdiag_psr/sparc/desktop/common/picldiag.c (revision 13019:b11dd158cab1)
11708Sstevel /*
21708Sstevel  * CDDL HEADER START
31708Sstevel  *
41708Sstevel  * The contents of this file are subject to the terms of the
51708Sstevel  * Common Development and Distribution License (the "License").
61708Sstevel  * You may not use this file except in compliance with the License.
71708Sstevel  *
81708Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel  * or http://www.opensolaris.org/os/licensing.
101708Sstevel  * See the License for the specific language governing permissions
111708Sstevel  * and limitations under the License.
121708Sstevel  *
131708Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel  * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel  *
191708Sstevel  * CDDL HEADER END
201708Sstevel  */
211708Sstevel 
221708Sstevel /*
23*13019SMichael.Bergknoff@Oracle.COM  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
241708Sstevel  */
251708Sstevel 
261708Sstevel #include <stdio.h>
271708Sstevel #include <stdlib.h>
281708Sstevel #include <string.h>
291708Sstevel #include <alloca.h>
301708Sstevel #include <errno.h>
311708Sstevel #include <libintl.h>
321708Sstevel #include <sys/utsname.h>
331708Sstevel #include <sys/types.h>
341708Sstevel #include <sys/stat.h>
351708Sstevel #include <sys/openpromio.h>
361708Sstevel #include <sys/ddi.h>
371708Sstevel #include <syslog.h>
381708Sstevel #include <fcntl.h>
391708Sstevel #include <dirent.h>
401708Sstevel #include <unistd.h>
411708Sstevel #include <locale.h>
421708Sstevel #include <picl.h>
431708Sstevel #include "pdevinfo.h"
441708Sstevel #include "display.h"
451708Sstevel #include "display_sun4u.h"
461708Sstevel #include "picldefs.h"
471708Sstevel #include "libprtdiag.h"
481708Sstevel 
491708Sstevel #if !defined(TEXT_DOMAIN)
501708Sstevel #define	TEXT_DOMAIN	"SYS_TEST"
511708Sstevel #endif
521708Sstevel 
531708Sstevel #define	EM_INIT_FAIL		dgettext(TEXT_DOMAIN,\
541708Sstevel 	"picl_initialize failed: %s\n")
551708Sstevel #define	EM_GET_ROOT_FAIL	dgettext(TEXT_DOMAIN,\
561708Sstevel 	"Getting root node failed: %s\n")
571708Sstevel #define	EM_PRTDIAG_FAIL		dgettext(TEXT_DOMAIN, "Prtdiag failed!\n")
581708Sstevel 
591708Sstevel #define	SIGN_ON_MSG	dgettext(TEXT_DOMAIN,\
60*13019SMichael.Bergknoff@Oracle.COM 	"System Configuration: Oracle Corporation ")
611708Sstevel #define	SYSCLK_FREQ_MSG	dgettext(TEXT_DOMAIN,\
621708Sstevel 	"System clock frequency: %d MHZ\n")
631708Sstevel #define	SERIAL_NUM_MSG	dgettext(TEXT_DOMAIN,\
641708Sstevel 	"Chassis Serial Number:\n")
651708Sstevel #define	MEM_SIZE_MSG	dgettext(TEXT_DOMAIN, "Memory size: ")
661708Sstevel #define	FFB_DOUBLE_BUF	dgettext(TEXT_DOMAIN, "FFB, Double Buffered")
671708Sstevel #define	FFB_SINGLE_BUF	dgettext(TEXT_DOMAIN, "FFB, Single Buffered")
681708Sstevel 
691708Sstevel #define	DEFAULT_BOARD_NUM	0
701708Sstevel #define	DEFAULT_PORTID		0
711708Sstevel #define	CLK_FREQ_66MHZ		66
721708Sstevel #define	USB			-1
731708Sstevel #define	HUB			-2
741708Sstevel 
751708Sstevel /* bus id */
761708Sstevel #define	SBUS_TYPE		0
771708Sstevel #define	PCI_TYPE		1
781708Sstevel #define	UPA_TYPE		2
791708Sstevel #define	PCIEX_TYPE		3
801708Sstevel 
811708Sstevel #define	UPA_NAME		"upa"
821708Sstevel #define	PCIEX_NAME		"pciex"
831708Sstevel 
841708Sstevel /*
851708Sstevel  * PICL classes
861708Sstevel  */
871708Sstevel #define	PICL_CLASS_OPTIONS		"options"
881708Sstevel 
891708Sstevel /*
901708Sstevel  * Property names
911708Sstevel  */
921708Sstevel 
931708Sstevel #define	OBP_PROP_REG			"reg"
941708Sstevel #define	OBP_PROP_CLOCK_FREQ		"clock-frequency"
951708Sstevel #define	OBP_PROP_BOARD_NUM		"board#"
961708Sstevel #define	OBP_PROP_REVISION_ID		"revision-id"
971708Sstevel #define	OBP_PROP_VERSION_NUM		"version#"
981708Sstevel #define	OBP_PROP_MODREV_NUM		"module-revision#"
992936Svenki #define	OBP_PROP_FIREREV_NUM		"fire-revision#"
1001708Sstevel #define	OBP_PROP_BOARD_TYPE		"board_type"
1011708Sstevel #define	OBP_PROP_ECACHE_SIZE		"ecache-size"
1021708Sstevel #define	OBP_PROP_IMPLEMENTATION		"implementation#"
1031708Sstevel #define	OBP_PROP_MASK			"mask#"
1041708Sstevel #define	OBP_PROP_COMPATIBLE		"compatible"
1051708Sstevel #define	OBP_PROP_BANNER_NAME		"banner-name"
1061708Sstevel #define	OBP_PROP_MODEL			"model"
1071708Sstevel #define	OBP_PROP_66MHZ_CAPABLE		"66mhz-capable"
1081708Sstevel #define	OBP_PROP_FBC_REG_ID		"fbc_reg_id"
1091708Sstevel #define	OBP_PROP_VERSION		"version"
1101708Sstevel 
1111708Sstevel #define	PROP_POWERFAIL_TIME		"powerfail-time"
1121708Sstevel #define	PICL_PROP_LOW_WARNING_THRESHOLD	"LowWarningThreshold"
1131708Sstevel 
1141708Sstevel #define	DEFAULT_LINE_WIDTH		78
1151708Sstevel #define	HEADING_SYMBOL			"="
1161708Sstevel 
1171708Sstevel #define	MAX_IWAYS			32
1181708Sstevel 
1191708Sstevel typedef struct bank_list {
1201708Sstevel 	picl_nodehdl_t		nodeh;
1211708Sstevel 	uint32_t		iway_count;
1221708Sstevel 	uint32_t		iway[MAX_IWAYS];
1231708Sstevel 	struct bank_list	*next;
1241708Sstevel } bank_list_t;
1251708Sstevel 
1261708Sstevel typedef struct {
1271708Sstevel 	uint64_t	base;
1281708Sstevel 	uint64_t	size;
1291708Sstevel 	int		ifactor;
1301708Sstevel 	int		bank_count;
1311708Sstevel } seg_info_t;
1321708Sstevel 
1331708Sstevel static struct io_card	*io_card_list = NULL; /* The head of the IO card list */
1341708Sstevel static bank_list_t	*mem_banks = NULL;
1351708Sstevel static	int		mem_xfersize;
1361708Sstevel static	int		no_xfer_size = 0;
1371708Sstevel 
1381708Sstevel static char *io_device_table[] = {
1391708Sstevel 	"block",
1401708Sstevel 	"disk",
1411708Sstevel 	"cdrom",
1421708Sstevel 	"floppy",
1431708Sstevel 	"tape",
1441708Sstevel 	"network",
1451708Sstevel 	"display",
1461708Sstevel 	"serial",
1471708Sstevel 	"parallel",
1481708Sstevel 	"scsi",
1491708Sstevel 	"scsi-2",
1501708Sstevel 	"scsi-3",
1511708Sstevel 	"ide",
1521708Sstevel 	"fcal",
1531708Sstevel 	"keyboard",
1541708Sstevel 	"mouse",
1551708Sstevel 	"dma"
1561708Sstevel };
1571708Sstevel 
1581708Sstevel #define	NIODEVICE	sizeof (io_device_table) / sizeof (io_device_table[0])
1591708Sstevel 
1601708Sstevel static char *bus_table[] = {
1611708Sstevel 	"ebus",
1621708Sstevel 	"isa",
1631708Sstevel 	"pmu",
1641708Sstevel 	"pci",
1651708Sstevel 	"pciex"
1661708Sstevel };
1671708Sstevel 
1681708Sstevel #define	NBUS	sizeof (bus_table) / sizeof (bus_table[0])
1691708Sstevel 
1701708Sstevel /* prtdiag exit codes */
1711708Sstevel #define	PD_SUCCESS		0
1721708Sstevel #define	PD_SYSTEM_FAILURE	1
1731708Sstevel #define	PD_INTERNAL_FAILURE	2
1741708Sstevel 
1751708Sstevel /*
1761708Sstevel  * Use of global assumes do_prominfo only called from main in prtdiag and
1771708Sstevel  * access does not need to be multi-thread safe.
1781708Sstevel  */
1791708Sstevel static int	exit_code = PD_SUCCESS;
1801708Sstevel 
1811708Sstevel /*
1821708Sstevel  * This function is called from every location where a status value is output.
1831708Sstevel  * It checks the status arg and sets exit_code if an error is detected.
1841708Sstevel  * The status is typically returned from a PICL query. A case-insensitive
1851708Sstevel  * string comparison is done to check for any status that starts with "fail"
1861708Sstevel  * or "fault".
1871708Sstevel  */
1881708Sstevel static void
set_exit_code(char * status)1891708Sstevel set_exit_code(char *status)
1901708Sstevel {
1911708Sstevel 	if (status == NULL)
1921708Sstevel 		return;
1931708Sstevel 
1941708Sstevel 	if (strncasecmp(status, "fail", 4) == 0 ||
1951708Sstevel 	    strncasecmp(status, "fault", 5) == 0)
1961708Sstevel 		exit_code = PD_SYSTEM_FAILURE;
1971708Sstevel }
1981708Sstevel 
1991708Sstevel /*
2001708Sstevel  * check if it is an IO deice
2011708Sstevel  */
2021708Sstevel static int
is_io_device(char * device_class)2031708Sstevel is_io_device(char *device_class)
2041708Sstevel {
2051708Sstevel 	int i;
2061708Sstevel 
2071708Sstevel 	for (i = 0; i < NIODEVICE; i++) {
208*13019SMichael.Bergknoff@Oracle.COM 		if (strcmp(device_class, io_device_table[i]) == 0)
209*13019SMichael.Bergknoff@Oracle.COM 			return (1);
2101708Sstevel 	}
2111708Sstevel 
2121708Sstevel 	return (0);
2131708Sstevel }
2141708Sstevel 
2151708Sstevel /*
2161708Sstevel  * check if it is a bus
2171708Sstevel  */
2181708Sstevel static int
is_bus(char * device_class)2191708Sstevel is_bus(char *device_class)
2201708Sstevel {
2211708Sstevel 	int i;
2221708Sstevel 
2231708Sstevel 	for (i = 0; i < NBUS; i++) {
224*13019SMichael.Bergknoff@Oracle.COM 		if (strcmp(device_class, bus_table[i]) == 0)
225*13019SMichael.Bergknoff@Oracle.COM 			return (1);
2261708Sstevel 	}
2271708Sstevel 
2281708Sstevel 	return (0);
2291708Sstevel }
2301708Sstevel 
2311708Sstevel /*
2321708Sstevel  * search children to get the node by the nodename
2331708Sstevel  */
2341708Sstevel static int
picldiag_get_node_by_name(picl_nodehdl_t rooth,char * name,picl_nodehdl_t * nodeh)2351708Sstevel picldiag_get_node_by_name(picl_nodehdl_t rooth, char *name,
2361708Sstevel     picl_nodehdl_t *nodeh)
2371708Sstevel {
2381708Sstevel 	picl_nodehdl_t	childh;
2391708Sstevel 	int		err;
2401708Sstevel 	char		*nodename;
2411708Sstevel 
2421708Sstevel 	nodename = alloca(strlen(name) + 1);
2431708Sstevel 	if (nodename == NULL)
2441708Sstevel 		return (PICL_FAILURE);
2451708Sstevel 
2461708Sstevel 	err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
2471708Sstevel 	    sizeof (picl_nodehdl_t));
2481708Sstevel 
2491708Sstevel 	while (err == PICL_SUCCESS) {
2501708Sstevel 		err = picl_get_propval_by_name(childh, PICL_PROP_NAME,
2511708Sstevel 		    nodename, (strlen(name) + 1));
2521708Sstevel 		if (err != PICL_SUCCESS) {
2531708Sstevel 			err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
254*13019SMichael.Bergknoff@Oracle.COM 			    &childh, sizeof (picl_nodehdl_t));
2551708Sstevel 			continue;
2561708Sstevel 		}
2571708Sstevel 
2581708Sstevel 		if (strcmp(nodename, name) == 0) {
2591708Sstevel 			*nodeh = childh;
2601708Sstevel 			return (PICL_SUCCESS);
2611708Sstevel 		}
2621708Sstevel 
2631708Sstevel 		err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
2641708Sstevel 		    &childh, sizeof (picl_nodehdl_t));
2651708Sstevel 	}
2661708Sstevel 
2671708Sstevel 	return (err);
2681708Sstevel }
2691708Sstevel 
2701708Sstevel /*
2711708Sstevel  * get the value by the property name of the string prop
2721708Sstevel  * Caller must free the outbuf
2731708Sstevel  */
2741708Sstevel static int
picldiag_get_string_propval(picl_nodehdl_t modh,char * prop_name,char ** outbuf)2751708Sstevel picldiag_get_string_propval(picl_nodehdl_t modh, char *prop_name, char **outbuf)
2761708Sstevel {
2771708Sstevel 	int		err;
2781708Sstevel 	picl_prophdl_t	proph;
2791708Sstevel 	picl_propinfo_t	pinfo;
2801708Sstevel 	char		*prop_value;
2811708Sstevel 
2821708Sstevel 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
2831708Sstevel 	if (err != PICL_SUCCESS)
2841708Sstevel 		return (err);
2851708Sstevel 
2861708Sstevel 	/*
2871708Sstevel 	 * If it is not a string prop, return NULL
2881708Sstevel 	 */
2891708Sstevel 	if (pinfo.type != PICL_PTYPE_CHARSTRING)
290*13019SMichael.Bergknoff@Oracle.COM 		return (PICL_FAILURE);
2911708Sstevel 
2921708Sstevel 	prop_value = malloc(pinfo.size);
2931708Sstevel 	if (prop_value == NULL)
2941708Sstevel 		return (PICL_FAILURE);
2951708Sstevel 
2961708Sstevel 	err = picl_get_propval(proph, prop_value, pinfo.size);
2971708Sstevel 	if (err != PICL_SUCCESS) {
2981708Sstevel 		free(prop_value);
2991708Sstevel 		return (err);
3001708Sstevel 	}
3011708Sstevel 
3021708Sstevel 	*outbuf = prop_value;
3031708Sstevel 	return (PICL_SUCCESS);
3041708Sstevel }
3051708Sstevel 
3061708Sstevel 
3071708Sstevel /*
3081708Sstevel  * return the value as a signed integer
3091708Sstevel  */
3101708Sstevel 
3111708Sstevel static int64_t
picldiag_get_int_propval(picl_nodehdl_t modh,char * prop_name,int * ret)3121708Sstevel picldiag_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
3131708Sstevel {
3141708Sstevel 	int		err;
3151708Sstevel 	picl_prophdl_t	proph;
3161708Sstevel 	picl_propinfo_t	pinfo;
3171708Sstevel 	int8_t		int8v;
3181708Sstevel 	int16_t		int16v;
3191708Sstevel 	int32_t		int32v;
3201708Sstevel 	int64_t		int64v;
3211708Sstevel 
3221708Sstevel 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
3231708Sstevel 	if (err != PICL_SUCCESS) {
3241708Sstevel 		*ret = err;
3251708Sstevel 		return (0);
3261708Sstevel 	}
3271708Sstevel 
3281708Sstevel 	/*
3291708Sstevel 	 * If it is not an int, uint or byte array prop, return failure
3301708Sstevel 	 */
3311708Sstevel 	if ((pinfo.type != PICL_PTYPE_INT) &&
332*13019SMichael.Bergknoff@Oracle.COM 	    (pinfo.type != PICL_PTYPE_UNSIGNED_INT) &&
333*13019SMichael.Bergknoff@Oracle.COM 	    (pinfo.type != PICL_PTYPE_BYTEARRAY)) {
3341708Sstevel 		*ret = PICL_FAILURE;
3351708Sstevel 		return (0);
3361708Sstevel 	}
3371708Sstevel 
3381708Sstevel 	switch (pinfo.size) {
3391708Sstevel 	case sizeof (int8_t):
3401708Sstevel 		err = picl_get_propval(proph, &int8v, sizeof (int8v));
3411708Sstevel 		*ret = err;
3421708Sstevel 		return (int8v);
3431708Sstevel 	case sizeof (int16_t):
3441708Sstevel 		err = picl_get_propval(proph, &int16v, sizeof (int16v));
3451708Sstevel 		*ret = err;
3461708Sstevel 		return (int16v);
3471708Sstevel 	case sizeof (int32_t):
3481708Sstevel 		err = picl_get_propval(proph, &int32v, sizeof (int32v));
3491708Sstevel 		*ret = err;
3501708Sstevel 		return (int32v);
3511708Sstevel 	case sizeof (int64_t):
3521708Sstevel 		err = picl_get_propval(proph, &int64v, sizeof (int64v));
3531708Sstevel 		*ret = err;
3541708Sstevel 		return (int64v);
3551708Sstevel 	default:	/* not supported size */
3561708Sstevel 		*ret = PICL_FAILURE;
3571708Sstevel 		return (0);
3581708Sstevel 	}
3591708Sstevel }
3601708Sstevel 
3611708Sstevel /*
3621708Sstevel  * return the value of the uint prop
3631708Sstevel  */
3641708Sstevel static uint64_t
picldiag_get_uint_propval(picl_nodehdl_t modh,char * prop_name,int * ret)3651708Sstevel picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
3661708Sstevel {
3671708Sstevel 	int		err;
3681708Sstevel 	picl_prophdl_t	proph;
3691708Sstevel 	picl_propinfo_t	pinfo;
3701708Sstevel 	uint8_t		uint8v;
3711708Sstevel 	uint16_t	uint16v;
3721708Sstevel 	uint32_t	uint32v;
3731708Sstevel 	uint64_t	uint64v;
3741708Sstevel 
3751708Sstevel 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
3761708Sstevel 	if (err != PICL_SUCCESS) {
3771708Sstevel 		*ret = err;
3781708Sstevel 		return (0);
3791708Sstevel 	}
3801708Sstevel 
3811708Sstevel 	/*
3821708Sstevel 	 * If it is not an int or uint prop, return failure
3831708Sstevel 	 */
3841708Sstevel 	if ((pinfo.type != PICL_PTYPE_INT) &&
385*13019SMichael.Bergknoff@Oracle.COM 	    (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
3861708Sstevel 		*ret = PICL_FAILURE;
3871708Sstevel 		return (0);
3881708Sstevel 	}
3891708Sstevel 
3901708Sstevel 	/* uint prop */
3911708Sstevel 
3921708Sstevel 	switch (pinfo.size) {
3931708Sstevel 	case sizeof (uint8_t):
3941708Sstevel 		err = picl_get_propval(proph, &uint8v, sizeof (uint8v));
3951708Sstevel 		*ret = err;
3961708Sstevel 		return (uint8v);
3971708Sstevel 	case sizeof (uint16_t):
3981708Sstevel 		err = picl_get_propval(proph, &uint16v, sizeof (uint16v));
3991708Sstevel 		*ret = err;
4001708Sstevel 		return (uint16v);
4011708Sstevel 	case sizeof (uint32_t):
4021708Sstevel 		err = picl_get_propval(proph, &uint32v, sizeof (uint32v));
4031708Sstevel 		*ret = err;
4041708Sstevel 		return (uint32v);
4051708Sstevel 	case sizeof (uint64_t):
4061708Sstevel 		err = picl_get_propval(proph, &uint64v, sizeof (uint64v));
4071708Sstevel 		*ret = err;
4081708Sstevel 		return (uint64v);
4091708Sstevel 	default:	/* not supported size */
4101708Sstevel 		*ret = PICL_FAILURE;
4111708Sstevel 		return (0);
4121708Sstevel 	}
4131708Sstevel }
4141708Sstevel 
4151708Sstevel /*
4161708Sstevel  * return the value of the float prop
4171708Sstevel  */
4181708Sstevel static float
picldiag_get_float_propval(picl_nodehdl_t modh,char * prop_name,int * ret)4191708Sstevel picldiag_get_float_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
4201708Sstevel {
4211708Sstevel 	int		err;
4221708Sstevel 	picl_prophdl_t	proph;
4231708Sstevel 	picl_propinfo_t	pinfo;
4241708Sstevel 	float		floatv;
4251708Sstevel 
4261708Sstevel 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
4271708Sstevel 	if (err != PICL_SUCCESS) {
4281708Sstevel 		*ret = err;
4291708Sstevel 		return ((float)0);
4301708Sstevel 	}
4311708Sstevel 
4321708Sstevel 	/*
4331708Sstevel 	 * If it is not a float prop, return failure
4341708Sstevel 	 */
4351708Sstevel 	if (pinfo.type != PICL_PTYPE_FLOAT) {
4361708Sstevel 		*ret = PICL_FAILURE;
4371708Sstevel 		return ((float)0);
4381708Sstevel 	}
4391708Sstevel 
4401708Sstevel 	*ret = picl_get_propval(proph, &floatv, sizeof (floatv));
4411708Sstevel 	return (floatv);
4421708Sstevel }
4431708Sstevel 
4441708Sstevel /*
4451708Sstevel  * get the clock frequency
4461708Sstevel  */
4471708Sstevel static int
picldiag_get_clock_freq(picl_nodehdl_t modh,uint32_t * freq)4481708Sstevel picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq)
4491708Sstevel {
4501708Sstevel #define	ROUND_TO_MHZ(x)	(((x) + 500000)/ 1000000)
4511708Sstevel 	int		err;
4521708Sstevel 	uint64_t	clk_freq;
4531708Sstevel 
4541708Sstevel 	clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err);
4551708Sstevel 	if (err != PICL_SUCCESS)
4561708Sstevel 		return (err);
4571708Sstevel 
4581708Sstevel 	*freq = ROUND_TO_MHZ(clk_freq);
4591708Sstevel 
4601708Sstevel 	return (PICL_SUCCESS);
4611708Sstevel }
4621708Sstevel 
4631708Sstevel /*
4641708Sstevel  * get the clock frequency from parent
4651708Sstevel  */
4661708Sstevel static int
picldiag_get_clock_from_parent(picl_nodehdl_t nodeh,uint32_t * clk)4671708Sstevel picldiag_get_clock_from_parent(picl_nodehdl_t nodeh, uint32_t *clk)
4681708Sstevel {
4691708Sstevel 	picl_nodehdl_t	parenth;
4701708Sstevel 	int		err;
4711708Sstevel 
4721708Sstevel 
4731708Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
4741708Sstevel 	    &parenth, sizeof (parenth));
4751708Sstevel 
4761708Sstevel 	while (err == PICL_SUCCESS) {
4771708Sstevel 		err = picldiag_get_clock_freq(parenth, clk);
4781708Sstevel 		if (err != PICL_PROPNOTFOUND)
4791708Sstevel 			return (err);
4801708Sstevel 
4811708Sstevel 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
4821708Sstevel 		    &parenth, sizeof (parenth));
4831708Sstevel 	}
4841708Sstevel 
4851708Sstevel 	return (err);
4861708Sstevel }
4871708Sstevel 
4881708Sstevel /*
4891708Sstevel  * get _fru_parent prop
4901708Sstevel  * If not found, then travese superiors (parent nodes) until
4911708Sstevel  * a _fru_parent property is found.
4921708Sstevel  * If not found, no fru parent
4931708Sstevel  */
4941708Sstevel static int
picldiag_get_fru_parent(picl_nodehdl_t nodeh,picl_nodehdl_t * fruparenth)4951708Sstevel picldiag_get_fru_parent(picl_nodehdl_t nodeh, picl_nodehdl_t *fruparenth)
4961708Sstevel {
4971708Sstevel 	picl_nodehdl_t	fruh;
4981708Sstevel 	int		err;
4991708Sstevel 
5001708Sstevel 	/* find fru parent */
5011708Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT,
5021708Sstevel 	    &fruh, sizeof (fruh));
5031708Sstevel 	if (err != PICL_SUCCESS)
5041708Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_REFPROP_LOC_PARENT,
5051708Sstevel 		    &fruh, sizeof (fruh));
5061708Sstevel 
5071708Sstevel 	while (err == PICL_PROPNOTFOUND) {
5081708Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
5091708Sstevel 		    &nodeh, sizeof (nodeh));
5101708Sstevel 		if (err != PICL_SUCCESS)
5111708Sstevel 			return (err);
5121708Sstevel 
5131708Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT,
5141708Sstevel 		    &fruh, sizeof (fruh));
5151708Sstevel 		if (err != PICL_SUCCESS)
5161708Sstevel 			err = picl_get_propval_by_name(nodeh,
5171708Sstevel 			    PICL_REFPROP_LOC_PARENT, &fruh, sizeof (fruh));
5181708Sstevel 	}
5191708Sstevel 
5201708Sstevel 	if (err == PICL_SUCCESS)
5211708Sstevel 		*fruparenth = fruh;
5221708Sstevel 
5231708Sstevel 	return (err);
5241708Sstevel }
5251708Sstevel 
5261708Sstevel /*
5271708Sstevel  * get label
5281708Sstevel  *
5291708Sstevel  * To get the label, use the following algorithm:
5301708Sstevel  * Lookup "Label" property in the fru node itself. If no
5311708Sstevel  * Label found, then traverse superiors (parent nodes) until
5321708Sstevel  * a Label property is found.
5331708Sstevel  * if not found, then no label
5341708Sstevel  */
5351708Sstevel static int
picldiag_get_label(picl_nodehdl_t nodeh,char ** label)5361708Sstevel picldiag_get_label(picl_nodehdl_t nodeh, char **label)
5371708Sstevel {
5381708Sstevel 	int		err;
5391708Sstevel 
5401708Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, label);
5411708Sstevel 
5421708Sstevel 	while (err == PICL_PROPNOTFOUND) {
5431708Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
5441708Sstevel 		    &nodeh, sizeof (nodeh));
5451708Sstevel 		if (err != PICL_SUCCESS)
5461708Sstevel 			return (err);
5471708Sstevel 
5481708Sstevel 		err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL,
5491708Sstevel 		    label);
5501708Sstevel 	}
5511708Sstevel 
5521708Sstevel 	return (err);
5531708Sstevel }
5541708Sstevel 
5551708Sstevel /*
5561708Sstevel  * get combined label
5571708Sstevel  *
5581708Sstevel  * like picldiag_get_label, except concatenates the labels of parent locations
5591708Sstevel  * eg SB0/P3 for processor P3 on system board SB0
5601708Sstevel  *
5611708Sstevel  * if caller specifies non-zero label length, label will be cut to specified
5621708Sstevel  * length.
5631708Sstevel  * negative length is left justified, non-negative length is right justified
5641708Sstevel  */
5651708Sstevel static int
picldiag_get_combined_label(picl_nodehdl_t nodeh,char ** label,int lablen)5661708Sstevel picldiag_get_combined_label(picl_nodehdl_t nodeh, char **label, int lablen)
5671708Sstevel {
5681708Sstevel 	int	err;
5691708Sstevel 	char	*ptr;
5701708Sstevel 	char	*ptr1 = NULL;
5711708Sstevel 	char	*ptr2;
5721708Sstevel 	int	len;
5731708Sstevel 
5741708Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr1);
5751708Sstevel 	if (err != PICL_PROPNOTFOUND && err != PICL_SUCCESS)
5761708Sstevel 		return (err);
5771708Sstevel 
5781708Sstevel 	for (;;) {
5791708Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
5801708Sstevel 		    &nodeh, sizeof (nodeh));
5811708Sstevel 		if (err == PICL_PROPNOTFOUND)
5821708Sstevel 			break;
5831708Sstevel 		if (err != PICL_SUCCESS)
5841708Sstevel 			return (err);
5851708Sstevel 
5861708Sstevel 		err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr);
5871708Sstevel 		if (err == PICL_SUCCESS) {
5881708Sstevel 			if (ptr1 == NULL) {
5891708Sstevel 				ptr1 = ptr;
5901708Sstevel 			} else {
5911708Sstevel 				ptr2 = malloc(strlen(ptr1) + strlen(ptr) + 2);
5921708Sstevel 				if (ptr2 == NULL)
5931708Sstevel 					return (PICL_FAILURE);
5941708Sstevel 				(void) strcpy(ptr2, ptr);
5951708Sstevel 				(void) strcat(ptr2, "/");
5961708Sstevel 				(void) strcat(ptr2, ptr1);
5971708Sstevel 				(void) free(ptr);
5981708Sstevel 				(void) free(ptr1);
5991708Sstevel 				ptr1 = ptr2;
6001708Sstevel 			}
6011708Sstevel 		} else if (err != PICL_PROPNOTFOUND) {
6021708Sstevel 			return (err);
6031708Sstevel 		}
6041708Sstevel 	}
6051708Sstevel 
6061708Sstevel 	if (ptr1 == NULL)
6071708Sstevel 		return (PICL_PROPNOTFOUND);
6081708Sstevel 
6091708Sstevel 	len = strlen(ptr1);
6101708Sstevel 	/* if no string truncation is desired or required */
6111708Sstevel 	if ((lablen == 0) || (len <= abs(lablen))) {
6121708Sstevel 		*label = ptr1;
6131708Sstevel 		return (PICL_SUCCESS);
6141708Sstevel 	}
6151708Sstevel 
6161708Sstevel 	/* string truncation is required; alloc space for (lablen + \0) */
6171708Sstevel 	ptr = malloc(abs(lablen) + 1);
6181708Sstevel 	if (ptr == 0)
6191708Sstevel 		return (PICL_FAILURE);
6201708Sstevel 	if (lablen > 0) {
6211708Sstevel 		/* right justification; label = "+<string>\0" */
6221708Sstevel 		strcpy(ptr, "+");
6231708Sstevel 		strncat(ptr, ptr1 + len - lablen + 1, lablen + 1);
6241708Sstevel 	} else {
6251708Sstevel 		/* left justification; label = "<string>+\0" */
6261708Sstevel 		strncpy(ptr, ptr1, abs(lablen) - 1);
6271708Sstevel 		strcat(ptr, "+");
6281708Sstevel 	}
6291708Sstevel 
6301708Sstevel 	*label = ptr;
6311708Sstevel 	return (PICL_SUCCESS);
6321708Sstevel }
6331708Sstevel 
6341708Sstevel /*
6351708Sstevel  * return the first compatible value
6361708Sstevel  */
6371708Sstevel static int
picldiag_get_first_compatible_value(picl_nodehdl_t nodeh,char ** outbuf)6381708Sstevel picldiag_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
6391708Sstevel {
6401708Sstevel 	int		err;
6411708Sstevel 	picl_prophdl_t	proph;
6421708Sstevel 	picl_propinfo_t	pinfo;
6431708Sstevel 	picl_prophdl_t	tblh;
6441708Sstevel 	picl_prophdl_t	rowproph;
6451708Sstevel 	char		*pval;
6461708Sstevel 
6471708Sstevel 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
6481708Sstevel 	    &pinfo, &proph);
6491708Sstevel 	if (err != PICL_SUCCESS)
650*13019SMichael.Bergknoff@Oracle.COM 		return (err);
6511708Sstevel 
6521708Sstevel 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
6531708Sstevel 		pval = malloc(pinfo.size);
6541708Sstevel 		if (pval == NULL)
6551708Sstevel 			return (PICL_FAILURE);
6561708Sstevel 		err = picl_get_propval(proph, pval, pinfo.size);
6571708Sstevel 		if (err != PICL_SUCCESS) {
6581708Sstevel 			free(pval);
6591708Sstevel 			return (err);
6601708Sstevel 		}
6611708Sstevel 		*outbuf = pval;
6621708Sstevel 		return (PICL_SUCCESS);
6631708Sstevel 	}
6641708Sstevel 
6651708Sstevel 	if (pinfo.type != PICL_PTYPE_TABLE)
6661708Sstevel 		return (PICL_FAILURE);
6671708Sstevel 
6681708Sstevel 	/* get first string from table */
6691708Sstevel 	err = picl_get_propval(proph, &tblh, pinfo.size);
6701708Sstevel 	if (err != PICL_SUCCESS)
6711708Sstevel 		return (err);
6721708Sstevel 
6731708Sstevel 	err = picl_get_next_by_row(tblh, &rowproph);
6741708Sstevel 	if (err != PICL_SUCCESS)
6751708Sstevel 		return (err);
6761708Sstevel 
6771708Sstevel 	err = picl_get_propinfo(rowproph, &pinfo);
6781708Sstevel 	if (err != PICL_SUCCESS)
679*13019SMichael.Bergknoff@Oracle.COM 		return (err);
6801708Sstevel 
6811708Sstevel 	pval = malloc(pinfo.size);
6821708Sstevel 	if (pval == NULL)
6831708Sstevel 		return (PICL_FAILURE);
6841708Sstevel 
6851708Sstevel 	err = picl_get_propval(rowproph, pval, pinfo.size);
6861708Sstevel 	if (err != PICL_SUCCESS) {
6871708Sstevel 		free(pval);
6881708Sstevel 		return (err);
6891708Sstevel 	}
6901708Sstevel 
6911708Sstevel 	*outbuf = pval;
6921708Sstevel 	return (PICL_SUCCESS);
6931708Sstevel }
6941708Sstevel 
6951708Sstevel /*
6961708Sstevel  * print the header in the center
6971708Sstevel  */
6981708Sstevel static void
logprintf_header(char * header,size_t line_width)6991708Sstevel logprintf_header(char *header, size_t line_width)
7001708Sstevel {
7011708Sstevel 	size_t	start_pos;
7021708Sstevel 	size_t	i;
7031708Sstevel 
7041708Sstevel 	log_printf("\n");
7051708Sstevel 	start_pos = (line_width - strlen(header) - 2) / 2;
7061708Sstevel 
7071708Sstevel 	for (i = 0; i < start_pos; i++)
7081708Sstevel 		log_printf("%s", HEADING_SYMBOL);
7091708Sstevel 
7101708Sstevel 	log_printf(" %s ", header);
7111708Sstevel 
7121708Sstevel 	for (i = 0; i < start_pos; i++)
7131708Sstevel 		log_printf("%s", HEADING_SYMBOL);
7141708Sstevel 
7151708Sstevel 	log_printf("\n");
7161708Sstevel }
7171708Sstevel 
7181708Sstevel /*
7191708Sstevel  * print the size
7201708Sstevel  */
7211708Sstevel static void
logprintf_size(uint64_t size)7221708Sstevel logprintf_size(uint64_t size)
7231708Sstevel {
7241708Sstevel #define	SIZE_FIELD	11
7251708Sstevel 
7261708Sstevel 	uint64_t	kbyte = 1024;
7271708Sstevel 	uint64_t	mbyte = 1024 * 1024;
7281708Sstevel 	uint64_t	gbyte = 1024 * 1024 * 1024;
7291708Sstevel 	uint64_t	residue;
7301708Sstevel 	char		buf[SIZE_FIELD];
7311708Sstevel 
7321708Sstevel 	if (size >= gbyte) {
7331708Sstevel 		residue = size % gbyte;
7341708Sstevel 		if (residue == 0)
7351708Sstevel 			snprintf(buf, sizeof (buf), "%dGB",
7361708Sstevel 			    (int)(size / gbyte));
7371708Sstevel 		else
7381708Sstevel 			snprintf(buf, sizeof (buf), "%.2fGB",
7391708Sstevel 			    (float)size / gbyte);
7401708Sstevel 	} else if (size >= mbyte) {
7411708Sstevel 		residue = size % mbyte;
7421708Sstevel 		if (residue == 0)
7431708Sstevel 			snprintf(buf, sizeof (buf), "%dMB",
7441708Sstevel 			    (int)(size / mbyte));
7451708Sstevel 		else
7461708Sstevel 			snprintf(buf, sizeof (buf), "%.2fMB",
7471708Sstevel 			    (float)size / mbyte);
7481708Sstevel 	} else {
7491708Sstevel 		residue = size % kbyte;
7501708Sstevel 		if (residue == 0)
7511708Sstevel 			snprintf(buf, sizeof (buf), "%dKB",
7521708Sstevel 			    (int)(size / kbyte));
7531708Sstevel 		else
7541708Sstevel 			snprintf(buf, sizeof (buf), "%.2fKB",
7551708Sstevel 			    (float)size / kbyte);
7561708Sstevel 	}
7571708Sstevel 
7581708Sstevel 	log_printf("%-10s ", buf);
7591708Sstevel }
7601708Sstevel 
7611708Sstevel /*
7621708Sstevel  * display platform banner
7631708Sstevel  */
7641708Sstevel static int
display_platform_banner(picl_nodehdl_t plafh)7651708Sstevel display_platform_banner(picl_nodehdl_t plafh)
7661708Sstevel {
7671708Sstevel 	char	*platform;
7681708Sstevel 	char	*banner_name;
7691708Sstevel 	int	err;
7701708Sstevel 
7711708Sstevel 	/*
7721708Sstevel 	 * get PICL_PROP_MACHINE and PICL_PROP_BANNER_NAME
7731708Sstevel 	 */
7741708Sstevel 	log_printf(SIGN_ON_MSG);
7751708Sstevel 	err = picldiag_get_string_propval(plafh, PICL_PROP_MACHINE,
7761708Sstevel 	    &platform);
7771708Sstevel 	if (err != PICL_SUCCESS)
7781708Sstevel 		return (err);
7791708Sstevel 	log_printf(" %s", platform);
7801708Sstevel 	free(platform);
7811708Sstevel 
7821708Sstevel 	err = picldiag_get_string_propval(plafh, OBP_PROP_BANNER_NAME,
7831708Sstevel 	    &banner_name);
7841708Sstevel 	if (err != PICL_SUCCESS)
7851708Sstevel 		return (err);
7861708Sstevel 	log_printf(" %s", banner_name);
7871708Sstevel 	free(banner_name);
7881708Sstevel 
7891708Sstevel 	log_printf("\n");
7901708Sstevel 	return (PICL_SUCCESS);
7911708Sstevel }
7921708Sstevel 
7931708Sstevel static int
serialnum_callback(picl_nodehdl_t serialh,void * arg)7941708Sstevel serialnum_callback(picl_nodehdl_t serialh, void *arg)
7951708Sstevel {
7961708Sstevel 	int		*countp = arg;
7971708Sstevel 	int		err;
7981708Sstevel 	picl_nodehdl_t	fruph;
7991708Sstevel 	char		*buf;
8001708Sstevel 
8011708Sstevel 	err = picl_get_propval_by_name(serialh, PICL_REFPROP_FRU_PARENT,
8021708Sstevel 	    &fruph, sizeof (fruph));
8031708Sstevel 	if (err == PICL_PROPNOTFOUND) {
8041708Sstevel 		err = picl_get_propval_by_name(serialh,
8051708Sstevel 		    PICL_REFPROP_LOC_PARENT, &fruph, sizeof (fruph));
8061708Sstevel 	}
8071708Sstevel 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE)
8081708Sstevel 		return (PICL_WALK_CONTINUE);
8091708Sstevel 	if (err != PICL_SUCCESS)
8101708Sstevel 		return (err);
8111708Sstevel 
8121708Sstevel 	err = picldiag_get_string_propval(serialh,
8131708Sstevel 	    PICL_PROP_SERIAL_NUMBER, &buf);
8141708Sstevel 	if (err == PICL_SUCCESS)	{
8151708Sstevel 		log_printf("\n");
8161708Sstevel 		log_printf(SERIAL_NUM_MSG);
8171708Sstevel 		log_printf("----------------------\n");
8181708Sstevel 		log_printf("%s\n", buf);
8191708Sstevel 		free(buf);
8201708Sstevel 		return (PICL_WALK_TERMINATE);
8211708Sstevel 	}
8221708Sstevel 	return (err);
8231708Sstevel }
8241708Sstevel 
8251708Sstevel /*
8261708Sstevel  * display the chassis serial number
8271708Sstevel  */
8281708Sstevel static int
display_serial_number(picl_nodehdl_t plafh)8291708Sstevel display_serial_number(picl_nodehdl_t plafh)
8301708Sstevel {
8311708Sstevel 	int		print_header;
8321708Sstevel 
8331708Sstevel 	picl_walk_tree_by_class(plafh, PICL_CLASS_CHASSIS_SERIAL_NUM,
8341708Sstevel 	    &print_header, serialnum_callback);
8351708Sstevel 	return (PICL_SUCCESS);
8361708Sstevel }
8371708Sstevel 
8381708Sstevel /*
8391708Sstevel  * display the clock frequency
8401708Sstevel  */
8411708Sstevel static int
display_system_clock(picl_nodehdl_t plafh)8421708Sstevel display_system_clock(picl_nodehdl_t plafh)
8431708Sstevel {
8441708Sstevel 	uint32_t	system_clk;
8451708Sstevel 	int		err;
8461708Sstevel 
8471708Sstevel 	err = picldiag_get_clock_freq(plafh, &system_clk);
8481708Sstevel 	if (err != PICL_SUCCESS)
8491708Sstevel 		return (err);
8501708Sstevel 
8511708Sstevel 	log_printf(SYSCLK_FREQ_MSG, system_clk);
8521708Sstevel 
8531708Sstevel 	return (PICL_SUCCESS);
8541708Sstevel }
8551708Sstevel 
8561708Sstevel /*
8571708Sstevel  * callback function to display the memory size
8581708Sstevel  */
8591708Sstevel /*ARGSUSED*/
8601708Sstevel static int
memory_callback(picl_nodehdl_t memh,void * args)8611708Sstevel memory_callback(picl_nodehdl_t memh, void *args)
8621708Sstevel {
8631708Sstevel 	uint64_t	mem_size;
8641708Sstevel 	int		err;
8651708Sstevel 
8661708Sstevel 	log_printf(MEM_SIZE_MSG);
8671708Sstevel 	mem_size = picldiag_get_uint_propval(memh, PICL_PROP_SIZE, &err);
8681708Sstevel 	if (err == PICL_SUCCESS)
8691708Sstevel 		logprintf_size(mem_size);
8701708Sstevel 	log_printf("\n");
8711708Sstevel 	no_xfer_size = 0;
8721708Sstevel 	mem_xfersize = picldiag_get_uint_propval(memh, PICL_PROP_TRANSFER_SIZE,
8731708Sstevel 	    &err);
8741708Sstevel 	if (err == PICL_PROPNOTFOUND)
8751708Sstevel 		no_xfer_size = 1;
8761708Sstevel 	return (PICL_WALK_TERMINATE);
8771708Sstevel }
8781708Sstevel 
8791708Sstevel /*
8801708Sstevel  * callback function to print cpu information
8811708Sstevel  */
8821708Sstevel /*ARGSUSED*/
8831708Sstevel static int
cpu_callback(picl_nodehdl_t nodeh,void * args)8841708Sstevel cpu_callback(picl_nodehdl_t nodeh, void *args)
8851708Sstevel {
8861708Sstevel 	int		err;
8871708Sstevel 	int		id;
8881708Sstevel 	uint64_t 	uintval;
8891708Sstevel 	uint32_t	freq;
8901708Sstevel 	char		*impl_name;
8911708Sstevel 	char		*status;
8921708Sstevel 	picl_prophdl_t	parenth;
8931708Sstevel 	char		*label;
8941708Sstevel 
8951708Sstevel 	/*
8961708Sstevel 	 * If no ID is found, return
8971708Sstevel 	 */
8981708Sstevel 	id = picldiag_get_uint_propval(nodeh, PICL_PROP_ID, &err);
8991708Sstevel 	if (err == PICL_PROPNOTFOUND)
9001708Sstevel 		return (PICL_WALK_CONTINUE);
9011708Sstevel 	else if (err != PICL_SUCCESS)
9021708Sstevel 		return (err);
9031708Sstevel 	log_printf("%-3d  ", id);
9041708Sstevel 
9051708Sstevel 	/*
9061708Sstevel 	 * If no freq is found, return
9071708Sstevel 	 */
9081708Sstevel 	err = picldiag_get_clock_freq(nodeh, &freq);
9091708Sstevel 	if (err == PICL_PROPNOTFOUND)
9101708Sstevel 		return (PICL_WALK_CONTINUE);
9111708Sstevel 	else if (err != PICL_SUCCESS)
9121708Sstevel 		return (err);
9131708Sstevel 	log_printf("%4d MHz  ", freq);
9141708Sstevel 
9151708Sstevel 	/* Ecache size */
9161708Sstevel 	uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_ECACHE_SIZE, &err);
9171708Sstevel 	if (err == PICL_PROPNOTFOUND)
9181708Sstevel 		log_printf(" -          ");
9191708Sstevel 	else if (err == PICL_SUCCESS)
9201708Sstevel 		logprintf_size(uintval);
9211708Sstevel 	else
9221708Sstevel 		return (err);
9231708Sstevel 
9241708Sstevel 	/* Implementation */
9251708Sstevel 	impl_name = NULL;
9261708Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_NAME, &impl_name);
9271708Sstevel 	if (err != PICL_SUCCESS)
9281708Sstevel 		log_printf("  <unknown>           ");
9291708Sstevel 	else
9301708Sstevel 		log_printf(" %-22s ", impl_name);
9311708Sstevel 
9321708Sstevel 	/* CPU Mask */
9331708Sstevel 	uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_MASK, &err);
9341708Sstevel 	if (err == PICL_PROPNOTFOUND)
9351708Sstevel 		log_printf("  -     ");
9361708Sstevel 	else if (err == PICL_SUCCESS)
9371708Sstevel 		log_printf("%2lld.%-2lld   ", (uintval >> 4) & 0xf,
9381708Sstevel 		    uintval & 0xf);
9391708Sstevel 	else
9401708Sstevel 		return (err);
9411708Sstevel 
9421708Sstevel 	/*
9431708Sstevel 	 * Status - if the node has a status property then display that
9441708Sstevel 	 * otherwise display the State property
9451708Sstevel 	 */
9461708Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status);
9471708Sstevel 	if (err == PICL_SUCCESS) {
9481708Sstevel 		log_printf("%-12s", status);
9491708Sstevel 		set_exit_code(status);
9501708Sstevel 		free(status);
9511708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err !=
9521708Sstevel 	    PICL_PROPVALUNAVAILABLE && err != PICL_ENDOFLIST) {
9531708Sstevel 		return (err);
9541708Sstevel 	} else {
9551708Sstevel 		err = picldiag_get_string_propval(nodeh,
9561708Sstevel 		    PICL_PROP_STATE, &status);
9571708Sstevel 		if (err == PICL_SUCCESS) {
9581708Sstevel 			log_printf("%-12s", status);
9591708Sstevel 			set_exit_code(status);
9601708Sstevel 			free(status);
9611708Sstevel 		} else if (err != PICL_PROPNOTFOUND && err !=
9621708Sstevel 		    PICL_PROPVALUNAVAILABLE && err !=
9631708Sstevel 		    PICL_ENDOFLIST) {
9641708Sstevel 			return (err);
9651708Sstevel 		} else {
9661708Sstevel 			log_printf("unknown    ");
9671708Sstevel 		}
9681708Sstevel 	}
9691708Sstevel 
9701708Sstevel 	/*
9711708Sstevel 	 * Location: use label of fru parent
9721708Sstevel 	 */
9731708Sstevel 	err = picldiag_get_fru_parent(nodeh, &parenth);
9741708Sstevel 	if (err == PICL_PROPNOTFOUND) {
9751708Sstevel 		log_printf(" -      ");
9761708Sstevel 	} else if (err == PICL_SUCCESS) {
9771708Sstevel 		err = picldiag_get_combined_label(parenth, &label, 12);
9781708Sstevel 		if (err == PICL_PROPNOTFOUND)
9791708Sstevel 			log_printf(" -      ");
9801708Sstevel 		else if (err == PICL_SUCCESS) {
9811708Sstevel 			log_printf("%s", label);
9821708Sstevel 			free(label);
9831708Sstevel 		} else
9841708Sstevel 			return (err);
9851708Sstevel 	} else
9861708Sstevel 		return (err);
9871708Sstevel 
9881708Sstevel 	log_printf("\n");
9891708Sstevel 	return (PICL_WALK_CONTINUE);
9901708Sstevel }
9911708Sstevel 
9921708Sstevel /*
9931708Sstevel  * display cpu information
9941708Sstevel  */
9951708Sstevel static int
display_cpu_info(picl_nodehdl_t plafh)9961708Sstevel display_cpu_info(picl_nodehdl_t plafh)
9971708Sstevel {
9981708Sstevel 	int	err;
9991708Sstevel 
10001708Sstevel 	/*
10011708Sstevel 	 * Display the table header for CPUs . Then display the CPU
10021708Sstevel 	 * frequency, cache size, and processor revision  on all the boards.
10031708Sstevel 	 */
10041708Sstevel 	logprintf_header(dgettext(TEXT_DOMAIN, "CPUs"), DEFAULT_LINE_WIDTH);
10051708Sstevel 	log_printf("               E$          CPU                    "
1006*13019SMichael.Bergknoff@Oracle.COM 	    "CPU\n");
10071708Sstevel 	log_printf("CPU  Freq      Size        Implementation         "
1008*13019SMichael.Bergknoff@Oracle.COM 	    "Mask    Status      Location\n");
10091708Sstevel 	log_printf("---  --------  ----------  ---------------------  "
1010*13019SMichael.Bergknoff@Oracle.COM 	    "-----   ------      --------\n");
10111708Sstevel 
10121708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU,
10131708Sstevel 	    cpu_callback);
10141708Sstevel 	return (err);
10151708Sstevel }
10161708Sstevel 
10171708Sstevel /*
10181708Sstevel  * Inserts an io_card structure into the list.
10191708Sstevel  */
10201708Sstevel 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)10211708Sstevel add_io_card(uint32_t board, uint32_t bus_id, uint32_t slot, char *label,
10221708Sstevel     uint32_t freq, char *name, char *model, char *status, char *devfs_path)
10231708Sstevel {
10241708Sstevel 	struct io_card card;
10251708Sstevel 
10261708Sstevel 	card.display = 1;
10271708Sstevel 	card.board = board;
10281708Sstevel 	switch (bus_id) {
10291708Sstevel 	case SBUS_TYPE:
10301708Sstevel 		strlcpy(card.bus_type, SBUS_NAME, MAXSTRLEN);
10311708Sstevel 		break;
10321708Sstevel 	case PCI_TYPE:
10331708Sstevel 		strlcpy(card.bus_type, PCI_NAME, MAXSTRLEN);
10341708Sstevel 		break;
10351708Sstevel 	case PCIEX_TYPE:
10361708Sstevel 		strlcpy(card.bus_type, PCIEX_NAME, MAXSTRLEN);
10371708Sstevel 		break;
10381708Sstevel 	case UPA_TYPE:
10391708Sstevel 		strlcpy(card.bus_type, UPA_NAME, MAXSTRLEN);
10401708Sstevel 		break;
10411708Sstevel 	default: /* won't reach here */
10421708Sstevel 		strlcpy(card.bus_type, "", MAXSTRLEN);
10431708Sstevel 		break;
10441708Sstevel 	}
10451708Sstevel 	if (label == NULL)
10461708Sstevel 		card.slot = slot;
10471708Sstevel 	else {
10481708Sstevel 		card.slot = PCI_SLOT_IS_STRING;
10491708Sstevel 		(void) strlcpy(card.slot_str, label, MAXSTRLEN);
10501708Sstevel 	}
10511708Sstevel 	card.freq = freq;
10521708Sstevel 	card.status[0] = '\0';
10531708Sstevel 	card.name[0] = '\0';
10541708Sstevel 	card.model[0] = '\0';
10551708Sstevel 	card.notes[0] = '\0';
10561708Sstevel 	if (status != NULL)
10571708Sstevel 		strlcpy(card.status, status, MAXSTRLEN);
10581708Sstevel 	if (name != NULL)
10591708Sstevel 		strlcpy(card.name, name, MAXSTRLEN);
10601708Sstevel 	if (model != NULL)
10611708Sstevel 		strlcpy(card.model, model, MAXSTRLEN);
10621708Sstevel 	if (status != NULL)
10631708Sstevel 		strlcpy(card.status, status, MAXSTRLEN);
10641708Sstevel 	if (devfs_path != NULL)
10651708Sstevel 		strlcpy(card.notes, devfs_path, MAXSTRLEN);
10661708Sstevel 
10671708Sstevel 	io_card_list = insert_io_card(io_card_list, &card);
10681708Sstevel }
10691708Sstevel 
10701708Sstevel static void
append_to_bank_list(bank_list_t * newptr)10711708Sstevel append_to_bank_list(bank_list_t *newptr)
10721708Sstevel {
10731708Sstevel 	bank_list_t	*ptr;
10741708Sstevel 
10751708Sstevel 	if (mem_banks == NULL) {
10761708Sstevel 		mem_banks = newptr;
10771708Sstevel 		return;
10781708Sstevel 	}
10791708Sstevel 	ptr = mem_banks;
10801708Sstevel 	while (ptr->next != NULL)
10811708Sstevel 		ptr = ptr->next;
10821708Sstevel 
10831708Sstevel 	ptr->next = newptr;
10841708Sstevel }
10851708Sstevel 
10861708Sstevel static void
free_bank_list(void)10871708Sstevel free_bank_list(void)
10881708Sstevel {
10891708Sstevel 	bank_list_t	*ptr;
10901708Sstevel 	bank_list_t	*tmp;
10911708Sstevel 
10921708Sstevel 	for (ptr = mem_banks; ptr != NULL; ptr = tmp) {
10931708Sstevel 		tmp = ptr->next;
10941708Sstevel 		free(ptr);
10951708Sstevel 	}
10961708Sstevel 	mem_banks = NULL;
10971708Sstevel }
10981708Sstevel 
10991708Sstevel 
11001708Sstevel /*
11011708Sstevel  * print label for memory module
11021708Sstevel  */
11031708Sstevel static int
logprintf_memory_module_label(picl_nodehdl_t moduleh)11041708Sstevel logprintf_memory_module_label(picl_nodehdl_t moduleh)
11051708Sstevel {
11061708Sstevel 	picl_nodehdl_t	fruparenth;
11071708Sstevel 	int		err;
11081708Sstevel 	char		*label;
11091708Sstevel 
11101708Sstevel 	err = picldiag_get_fru_parent(moduleh, &fruparenth);
11111708Sstevel 	if (err == PICL_PROPNOTFOUND) {
11121708Sstevel 		log_printf("-");
11131708Sstevel 		return (PICL_SUCCESS);
11141708Sstevel 	} else if (err != PICL_SUCCESS)
11151708Sstevel 		return (err);
11161708Sstevel 
11171708Sstevel 	err = picldiag_get_combined_label(fruparenth, &label, 30);
11181708Sstevel 	if (err == PICL_PROPNOTFOUND)
11191708Sstevel 		log_printf("-");
11201708Sstevel 	else if (err == PICL_SUCCESS) {
11211708Sstevel 		log_printf("%-15s", label);
11221708Sstevel 		free(label);
11231708Sstevel 	} else
11241708Sstevel 		return (err);
11251708Sstevel 
11261708Sstevel 	return (PICL_SUCCESS);
11271708Sstevel }
11281708Sstevel 
11291708Sstevel /*
11301708Sstevel  * print the bank id and add the bank handle in the bank list
11311708Sstevel  * return the head of the bank list
11321708Sstevel  */
11331708Sstevel static int
membank_callback(picl_nodehdl_t bankh,void * args)11341708Sstevel membank_callback(picl_nodehdl_t bankh, void *args)
11351708Sstevel {
11361708Sstevel 	int		err;
11371708Sstevel 	int64_t		id;
11381708Sstevel 	uint64_t	match;
11391708Sstevel 	uint64_t	mask;
11401708Sstevel 	int		i;
11411708Sstevel 	bank_list_t	*newptr;
11421708Sstevel 	seg_info_t	*segp = args;
11431708Sstevel 
11441708Sstevel 	/*
11451708Sstevel 	 * print the bank id in the segment table contains column
11461708Sstevel 	 */
11471708Sstevel 	id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err);
11481708Sstevel 	if (segp->bank_count > 0)
11491708Sstevel 		log_printf(",");
11501708Sstevel 	if (err == PICL_PROPNOTFOUND)
11511708Sstevel 		log_printf("-");
11521708Sstevel 	else if (err == PICL_SUCCESS)
11531708Sstevel 		log_printf("%-lld", id);
11541708Sstevel 	else
11551708Sstevel 		return (err);
11561708Sstevel 	segp->bank_count++;
11571708Sstevel 
11581708Sstevel 	/*
11591708Sstevel 	 * Save the bank information for later (print_bank_table)
11601708Sstevel 	 */
11611708Sstevel 	newptr = malloc(sizeof (*newptr));
11621708Sstevel 	if (newptr == NULL)
11631708Sstevel 		return (PICL_FAILURE);
11641708Sstevel 
11651708Sstevel 	newptr->nodeh = bankh;
11661708Sstevel 	newptr->iway_count = 0;
11671708Sstevel 	newptr->next = NULL;
11681708Sstevel 	append_to_bank_list(newptr);
11691708Sstevel 
11701708Sstevel 	/*
11711708Sstevel 	 * Compute the way numbers for the bank
11721708Sstevel 	 */
11731708Sstevel 	if (no_xfer_size)
11741708Sstevel 		return (PICL_WALK_CONTINUE);
11751708Sstevel 
11761708Sstevel 	match = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMATCH, &err);
11771708Sstevel 	if (err == PICL_PROPNOTFOUND)
11781708Sstevel 		return (PICL_WALK_CONTINUE);
11791708Sstevel 	else if (err != PICL_SUCCESS)
11801708Sstevel 		return (err);
11811708Sstevel 
11821708Sstevel 	mask = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMASK, &err);
11831708Sstevel 	if (err == PICL_PROPNOTFOUND)
11841708Sstevel 		return (PICL_WALK_CONTINUE);
11851708Sstevel 	else if (err != PICL_SUCCESS)
11861708Sstevel 		return (err);
11871708Sstevel 
11881708Sstevel 	i = 0;
11891708Sstevel 	while ((i < segp->ifactor) && (newptr->iway_count < MAX_IWAYS)) {
11901708Sstevel 		if (((segp->base + i * mem_xfersize) & mask) == match)
11911708Sstevel 			newptr->iway[newptr->iway_count++] = i;
11921708Sstevel 		++i;
11931708Sstevel 	}
11941708Sstevel 	return (PICL_WALK_CONTINUE);
11951708Sstevel }
11961708Sstevel 
11971708Sstevel 
11981708Sstevel /*
11991708Sstevel  * find the memory bank and add the bank handle in the bank list
12001708Sstevel  * return the head of the bank list
12011708Sstevel  */
12021708Sstevel static int
logprintf_bankinfo(picl_nodehdl_t segh,seg_info_t * segp)12031708Sstevel logprintf_bankinfo(picl_nodehdl_t segh, seg_info_t *segp)
12041708Sstevel {
12051708Sstevel 	int		err;
12061708Sstevel 
12071708Sstevel 	log_printf("BankIDs ");
12081708Sstevel 	/*
12091708Sstevel 	 * find memory-bank
12101708Sstevel 	 */
12111708Sstevel 	segp->bank_count = 0;
12121708Sstevel 	err = picl_walk_tree_by_class(segh, PICL_CLASS_MEMORY_BANK, segp,
12131708Sstevel 	    membank_callback);
12141708Sstevel 	log_printf("\n");
12151708Sstevel 	return (err);
12161708Sstevel }
12171708Sstevel 
12181708Sstevel /*
12191708Sstevel  * print the label of memory module or the memory module bank ids
12201708Sstevel  */
12211708Sstevel static int
logprintf_seg_contains_col(picl_nodehdl_t nodeh,seg_info_t * segp)12221708Sstevel logprintf_seg_contains_col(picl_nodehdl_t nodeh, seg_info_t *segp)
12231708Sstevel {
12241708Sstevel 	picl_nodehdl_t	moduleh;
12251708Sstevel 	int		err;
12261708Sstevel 
12271708Sstevel 	/*
12281708Sstevel 	 * find memory-module if referenced directly from the memory-segment
12291708Sstevel 	 * (ie no memory banks)
12301708Sstevel 	 */
12311708Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_REFPROP_MEMORY_MODULE,
12321708Sstevel 	    &moduleh, sizeof (moduleh));
12331708Sstevel 	if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND))
12341708Sstevel 		return (err);
12351708Sstevel 	if (err == PICL_SUCCESS) {
12361708Sstevel 		err = logprintf_memory_module_label(moduleh);
12371708Sstevel 		log_printf("\n");
12381708Sstevel 		return (err);
12391708Sstevel 	}
12401708Sstevel 
12411708Sstevel 	/*
12421708Sstevel 	 * memory-module not referenced directly from the memory segment
12431708Sstevel 	 * so list memory banks instead
12441708Sstevel 	 */
12451708Sstevel 	err = logprintf_bankinfo(nodeh, segp);
12461708Sstevel 	return (err);
12471708Sstevel }
12481708Sstevel 
12491708Sstevel /*
12501708Sstevel  * find all memory modules under the given memory module group
12511708Sstevel  * and print its label
12521708Sstevel  */
12531708Sstevel static int
logprintf_memory_module_group_info(picl_nodehdl_t memgrph,uint64_t mcid)12541708Sstevel logprintf_memory_module_group_info(picl_nodehdl_t memgrph, uint64_t mcid)
12551708Sstevel {
12561708Sstevel 	int		err;
12571708Sstevel 	int64_t		id;
12581708Sstevel 	boolean_t	got_status;
12591708Sstevel 	picl_nodehdl_t	moduleh;
12601708Sstevel 	char		piclclass[PICL_CLASSNAMELEN_MAX];
12611708Sstevel 	picl_nodehdl_t	fruparenth;
12621708Sstevel 	char		*status;
12631708Sstevel 
12641708Sstevel 	id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID, &err);
12651708Sstevel 	if (err == PICL_PROPNOTFOUND)
12661708Sstevel 		id = -1;
12671708Sstevel 	else if (err != PICL_SUCCESS)
12681708Sstevel 		return (err);
12691708Sstevel 
12701708Sstevel 	err = picl_get_propval_by_name(memgrph, PICL_PROP_CHILD, &moduleh,
12711708Sstevel 	    sizeof (picl_nodehdl_t));
12721708Sstevel 
12731708Sstevel 	while (err == PICL_SUCCESS) {
12741708Sstevel 		/* controller id */
12751708Sstevel 		log_printf("%-8lld       ", mcid);
12761708Sstevel 
12771708Sstevel 		/* group id */
12781708Sstevel 		if (id == -1) {
12791708Sstevel 			log_printf("-         ");
12801708Sstevel 		} else {
12811708Sstevel 			log_printf("%-8lld ", id);
12821708Sstevel 		}
12831708Sstevel 
12841708Sstevel 		err = picl_get_propval_by_name(moduleh, PICL_PROP_CLASSNAME,
12851708Sstevel 		    piclclass, sizeof (piclclass));
12861708Sstevel 		if (err != PICL_SUCCESS)
12871708Sstevel 			return (err);
12881708Sstevel 
12891708Sstevel 		if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE) == 0) {
12901708Sstevel 			err = logprintf_memory_module_label(moduleh);
12911708Sstevel 			if (err != PICL_SUCCESS)
12921708Sstevel 				return (err);
12931708Sstevel 		}
12941708Sstevel 
12951708Sstevel 		got_status = B_FALSE;
12961708Sstevel 		err = picldiag_get_fru_parent(moduleh, &fruparenth);
12971708Sstevel 		if (err == PICL_SUCCESS) {
12981708Sstevel 			err = picldiag_get_string_propval(fruparenth,
12991708Sstevel 			    PICL_PROP_OPERATIONAL_STATUS, &status);
13001708Sstevel 			if (err == PICL_SUCCESS) {
13011708Sstevel 				got_status = B_TRUE;
13021708Sstevel 			} else if (err != PICL_PROPNOTFOUND)
13031708Sstevel 				return (err);
13041708Sstevel 		} else if (err != PICL_PROPNOTFOUND)
13051708Sstevel 			return (err);
13061708Sstevel 
13071708Sstevel 		if (!got_status) {
13081708Sstevel 			err = picldiag_get_string_propval(moduleh,
13091708Sstevel 			    PICL_PROP_STATUS, &status);
13101708Sstevel 			if (err == PICL_SUCCESS)
13111708Sstevel 				got_status = B_TRUE;
13121708Sstevel 			else if (err != PICL_PROPNOTFOUND)
13131708Sstevel 				return (err);
13141708Sstevel 		}
13151708Sstevel 		if (got_status) {
13161708Sstevel 			log_printf("%s", status);
13171708Sstevel 			set_exit_code(status);
13181708Sstevel 			free(status);
13191708Sstevel 		}
13201708Sstevel 		err = picl_get_propval_by_name(moduleh, PICL_PROP_PEER,
13211708Sstevel 		    &moduleh, sizeof (picl_nodehdl_t));
13221708Sstevel 
13231708Sstevel 		log_printf("\n");
13241708Sstevel 	}
13251708Sstevel 	if (err == PICL_PROPNOTFOUND)
13261708Sstevel 		return (PICL_SUCCESS);
13271708Sstevel 	return (err);
13281708Sstevel }
13291708Sstevel 
13301708Sstevel /*
13311708Sstevel  * search children to find memory module group under memory-controller
13321708Sstevel  */
13331708Sstevel static int
find_memory_module_group(picl_nodehdl_t mch,int * print_header)13341708Sstevel find_memory_module_group(picl_nodehdl_t mch, int *print_header)
13351708Sstevel {
13361708Sstevel 	picl_nodehdl_t	memgrph;
13371708Sstevel 	uint64_t	mcid;
13381708Sstevel 	int		err;
13391708Sstevel 	char		piclclass[PICL_CLASSNAMELEN_MAX];
13401708Sstevel 
13411708Sstevel 	mcid = picldiag_get_uint_propval(mch, OBP_PROP_PORTID, &err);
13421708Sstevel 	if (err == PICL_PROPNOTFOUND)
13431708Sstevel 		mcid = DEFAULT_PORTID;
13441708Sstevel 	else if (err != PICL_SUCCESS)
13451708Sstevel 		return (err);
13461708Sstevel 
13471708Sstevel 	err = picl_get_propval_by_name(mch, PICL_PROP_CHILD,
13481708Sstevel 	    &memgrph, sizeof (picl_nodehdl_t));
13491708Sstevel 	while (err == PICL_SUCCESS) {
13501708Sstevel 		err = picl_get_propval_by_name(memgrph,
13511708Sstevel 		    PICL_PROP_CLASSNAME, piclclass, sizeof (piclclass));
13521708Sstevel 		if (err != PICL_SUCCESS)
13531708Sstevel 			return (err);
13541708Sstevel 
13551708Sstevel 		if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE_GROUP) == 0) {
13561708Sstevel 			if (*print_header == 1) {
13571708Sstevel 				log_printf(
13581708Sstevel 				    dgettext(TEXT_DOMAIN,
1359*13019SMichael.Bergknoff@Oracle.COM 				    "\nMemory Module Groups:\n"));
13601708Sstevel 				log_printf("--------------------------");
13611708Sstevel 				log_printf("------------------------\n");
13621708Sstevel 				log_printf("ControllerID   GroupID  Labels");
13631708Sstevel 				log_printf("         Status\n");
13641708Sstevel 				log_printf("--------------------------");
13651708Sstevel 				log_printf("------------------------\n");
13661708Sstevel 				*print_header = 0;
13671708Sstevel 			}
13681708Sstevel 			err = logprintf_memory_module_group_info(memgrph, mcid);
13691708Sstevel 			if (err != PICL_SUCCESS)
13701708Sstevel 				return (err);
13711708Sstevel 		}
13721708Sstevel 
13731708Sstevel 		err = picl_get_propval_by_name(memgrph, PICL_PROP_PEER,
13741708Sstevel 		    &memgrph, sizeof (picl_nodehdl_t));
13751708Sstevel 	}
13761708Sstevel 	if (err == PICL_PROPNOTFOUND)
13771708Sstevel 		return (PICL_SUCCESS);
13781708Sstevel 	return (err);
13791708Sstevel }
13801708Sstevel 
13811708Sstevel /*
13821708Sstevel  * print memory module group table per memory-controller
13831708Sstevel  */
13841708Sstevel static int
print_memory_module_group_table(picl_nodehdl_t plafh)13851708Sstevel print_memory_module_group_table(picl_nodehdl_t plafh)
13861708Sstevel {
13871708Sstevel 	picl_nodehdl_t	mch;
13881708Sstevel 	int		err;
13891708Sstevel 	char		piclclass[PICL_CLASSNAMELEN_MAX];
13901708Sstevel 	int		print_header;
13911708Sstevel 
13921708Sstevel 	print_header = 1;
13931708Sstevel 
13941708Sstevel 	/*
13951708Sstevel 	 * find memory-controller
13961708Sstevel 	 */
13971708Sstevel 	err = picl_get_propval_by_name(plafh, PICL_PROP_CHILD, &mch,
13981708Sstevel 	    sizeof (picl_nodehdl_t));
13991708Sstevel 	while (err == PICL_SUCCESS) {
14001708Sstevel 		err = picl_get_propval_by_name(mch, PICL_PROP_CLASSNAME,
14011708Sstevel 		    piclclass, sizeof (piclclass));
14021708Sstevel 		if (err != PICL_SUCCESS)
14031708Sstevel 			return (err);
14041708Sstevel 
14051708Sstevel 		if (strcmp(piclclass, PICL_CLASS_MEMORY_CONTROLLER) != 0) {
14061708Sstevel 			err = print_memory_module_group_table(mch);
14071708Sstevel 			if (err != PICL_SUCCESS)
14081708Sstevel 				return (err);
14091708Sstevel 			err = picl_get_propval_by_name(mch, PICL_PROP_PEER,
14101708Sstevel 			    &mch, sizeof (picl_nodehdl_t));
14111708Sstevel 			continue;
14121708Sstevel 		}
14131708Sstevel 
14141708Sstevel 		err = find_memory_module_group(mch, &print_header);
14151708Sstevel 		if (err != PICL_SUCCESS)
14161708Sstevel 			return (err);
14171708Sstevel 
14181708Sstevel 		err = picl_get_propval_by_name(mch, PICL_PROP_PEER,
14191708Sstevel 		    &mch, sizeof (picl_nodehdl_t));
14201708Sstevel 	}
14211708Sstevel 	if (err == PICL_PROPNOTFOUND)
14221708Sstevel 		return (PICL_SUCCESS);
14231708Sstevel 
14241708Sstevel 	return (err);
14251708Sstevel }
14261708Sstevel 
14271708Sstevel /*
14281708Sstevel  * print bank table
14291708Sstevel  */
14301708Sstevel static int
print_bank_table(void)14311708Sstevel print_bank_table(void)
14321708Sstevel {
14331708Sstevel 	bank_list_t	*ptr;
14341708Sstevel 	picl_nodehdl_t	bankh;
14351708Sstevel 	picl_nodehdl_t	memgrph;
14361708Sstevel 	picl_nodehdl_t	mch;
14371708Sstevel 	int		err;
14381708Sstevel 	int32_t		i;
14391708Sstevel 	uint64_t	size;
14401708Sstevel 	int		id;
14411708Sstevel 
14421708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "\nBank Table:\n"));
14431708Sstevel 	log_printf("---------------------------------------");
14441708Sstevel 	log_printf("--------------------\n");
14451708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "           Physical Location\n"));
14461708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "ID       ControllerID  GroupID   "));
14471708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Size       Interleave Way\n"));
14481708Sstevel 	log_printf("---------------------------------------");
14491708Sstevel 	log_printf("--------------------\n");
14501708Sstevel 
14511708Sstevel 	for (ptr = mem_banks; ptr != NULL; ptr = ptr->next) {
14521708Sstevel 		bankh = ptr->nodeh;
14531708Sstevel 		id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err);
14541708Sstevel 		if (err != PICL_SUCCESS)
14551708Sstevel 			log_printf("%-8s ", "-");
14561708Sstevel 		else
14571708Sstevel 			log_printf("%-8d ", id);
14581708Sstevel 
14591708Sstevel 		/* find memory-module-group */
14601708Sstevel 		err = picl_get_propval_by_name(bankh,
14611708Sstevel 		    PICL_REFPROP_MEMORY_MODULE_GROUP, &memgrph,
14621708Sstevel 		    sizeof (memgrph));
14631708Sstevel 		if (err == PICL_PROPNOTFOUND) {
14641708Sstevel 			log_printf("%-8s      ", "-");
14651708Sstevel 			log_printf("%-8s  ", "-");
14661708Sstevel 		} else if (err != PICL_SUCCESS)
14671708Sstevel 			return (err);
14681708Sstevel 		else {
14691708Sstevel 			/*
14701708Sstevel 			 * get controller id
14711708Sstevel 			 */
14721708Sstevel 			err = picl_get_propval_by_name(memgrph,
14731708Sstevel 			    PICL_PROP_PARENT, &mch, sizeof (picl_nodehdl_t));
14741708Sstevel 			if (err != PICL_SUCCESS)
14751708Sstevel 				return (err);
14761708Sstevel 
14771708Sstevel 			id = picldiag_get_uint_propval(mch, OBP_PROP_PORTID,
14781708Sstevel 			    &err);
14791708Sstevel 			if (err == PICL_PROPNOTFOUND)
14801708Sstevel 				id = DEFAULT_PORTID; /* use default */
14811708Sstevel 			else if (err != PICL_SUCCESS)
14821708Sstevel 				return (err);
14831708Sstevel 
14841708Sstevel 			log_printf("%-8d      ", id);
14851708Sstevel 
14861708Sstevel 			/* get group id */
14871708Sstevel 			id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID,
14881708Sstevel 			    &err);
14891708Sstevel 			if (err == PICL_PROPNOTFOUND)
14901708Sstevel 				log_printf("-          ");
14911708Sstevel 			else if (err == PICL_SUCCESS)
14921708Sstevel 				log_printf("%-8d  ", id);
14931708Sstevel 			else
14941708Sstevel 				return (err);
14951708Sstevel 		}
14961708Sstevel 
14971708Sstevel 		size = picldiag_get_uint_propval(bankh, PICL_PROP_SIZE, &err);
14981708Sstevel 		if (err == PICL_PROPNOTFOUND)
14991708Sstevel 			log_printf("-        	 ");
15001708Sstevel 		else if (err == PICL_SUCCESS)
15011708Sstevel 			logprintf_size(size);
15021708Sstevel 		else
15031708Sstevel 			return (err);
15041708Sstevel 
15051708Sstevel 		log_printf("     ");
15061708Sstevel 		for (i = 0; i < ptr->iway_count; i++) {
15071708Sstevel 			if (i != 0)
15081708Sstevel 				log_printf(",");
15091708Sstevel 			log_printf("%d", ptr->iway[i]);
15101708Sstevel 		}
15111708Sstevel 
15121708Sstevel 		log_printf("\n");
15131708Sstevel 	}
15141708Sstevel 	return (PICL_SUCCESS);
15151708Sstevel }
15161708Sstevel 
15171708Sstevel /*
15181708Sstevel  * callback function to print segment, add the bank in the list and
15191708Sstevel  * return the bank list
15201708Sstevel  */
15211708Sstevel /* ARGSUSED */
15221708Sstevel static int
memseg_callback(picl_nodehdl_t segh,void * args)15231708Sstevel memseg_callback(picl_nodehdl_t segh, void *args)
15241708Sstevel {
15251708Sstevel 	seg_info_t	seginfo;
15261708Sstevel 	int		err;
15271708Sstevel 
15281708Sstevel 	/* get base address */
15291708Sstevel 	seginfo.base = picldiag_get_uint_propval(segh, PICL_PROP_BASEADDRESS,
15301708Sstevel 	    &err);
15311708Sstevel 	if (err == PICL_PROPNOTFOUND) {
15321708Sstevel 		log_printf("-\n");
15331708Sstevel 		return (PICL_WALK_CONTINUE);
15341708Sstevel 	} else if (err == PICL_SUCCESS)
15351708Sstevel 		log_printf("0x%-16llx ", seginfo.base);
15361708Sstevel 	else
15371708Sstevel 		return (err);
15381708Sstevel 
15391708Sstevel 	/* get size */
15401708Sstevel 	seginfo.size = picldiag_get_uint_propval(segh, PICL_PROP_SIZE, &err);
15411708Sstevel 	if (err == PICL_PROPNOTFOUND) {
15421708Sstevel 		log_printf("-\n");
15431708Sstevel 		return (PICL_WALK_CONTINUE);
15441708Sstevel 	} else if (err == PICL_SUCCESS)
15451708Sstevel 		logprintf_size(seginfo.size);
15461708Sstevel 	else
15471708Sstevel 		return (err);
15481708Sstevel 
15491708Sstevel 	/* get interleave factor */
15501708Sstevel 	seginfo.ifactor = picldiag_get_uint_propval(segh,
15511708Sstevel 	    PICL_PROP_INTERLEAVE_FACTOR, &err);
15521708Sstevel 
15531708Sstevel 	if (err == PICL_PROPNOTFOUND) {
15541708Sstevel 		log_printf("       -\n");
15551708Sstevel 		return (PICL_WALK_CONTINUE);
15561708Sstevel 	} else if (err == PICL_SUCCESS)
15571708Sstevel 		log_printf("       %-2d          ", seginfo.ifactor);
15581708Sstevel 	else
15591708Sstevel 		return (err);
15601708Sstevel 
15611708Sstevel 	seginfo.bank_count = 0;
15621708Sstevel 	err = logprintf_seg_contains_col(segh, &seginfo);
15631708Sstevel 	if (err != PICL_SUCCESS)
15641708Sstevel 		return (err);
15651708Sstevel 	return (PICL_WALK_CONTINUE);
15661708Sstevel }
15671708Sstevel 
15681708Sstevel /*
15691708Sstevel  * search children to find memory-segment and set up the bank list
15701708Sstevel  */
15711708Sstevel static int
find_segments(picl_nodehdl_t plafh)15721708Sstevel find_segments(picl_nodehdl_t plafh)
15731708Sstevel {
15741708Sstevel 	int		err;
15751708Sstevel 
15761708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Segment Table:\n"));
15771708Sstevel 	log_printf("------------------------------");
15781708Sstevel 	log_printf("-----------------------------------------\n");
15791708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Base Address       Size       "));
15801708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Interleave Factor  Contains\n"));
15811708Sstevel 	log_printf("------------------------------");
15821708Sstevel 	log_printf("-----------------------------------------\n");
15831708Sstevel 
15841708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
15851708Sstevel 	    NULL, memseg_callback);
15861708Sstevel 	return (err);
15871708Sstevel }
15881708Sstevel 
15891708Sstevel /*
15901708Sstevel  * display memory configuration
15911708Sstevel  */
15921708Sstevel static int
display_memory_config(picl_nodehdl_t plafh)15931708Sstevel display_memory_config(picl_nodehdl_t plafh)
15941708Sstevel {
15951708Sstevel 	int		err;
15961708Sstevel 
15971708Sstevel 	logprintf_header(dgettext(TEXT_DOMAIN, "Memory Configuration"),
15981708Sstevel 	    DEFAULT_LINE_WIDTH);
15991708Sstevel 
16001708Sstevel 	mem_banks = NULL;
16011708Sstevel 	err = find_segments(plafh);
16021708Sstevel 
16031708Sstevel 	if ((err == PICL_SUCCESS) && (mem_banks != NULL))
16041708Sstevel 		print_bank_table();
16051708Sstevel 
16061708Sstevel 	free_bank_list();
16071708Sstevel 
16081708Sstevel 	return (print_memory_module_group_table(plafh));
16091708Sstevel }
16101708Sstevel 
16111708Sstevel /*
16121708Sstevel  * print the hub device
16131708Sstevel  */
16141708Sstevel static int
logprintf_hub_devices(picl_nodehdl_t hubh)16151708Sstevel logprintf_hub_devices(picl_nodehdl_t hubh)
16161708Sstevel {
16171708Sstevel 	char		*name;
16181708Sstevel 	int		portnum;
16191708Sstevel 	char		*labelp;
16201708Sstevel 	picl_nodehdl_t	parenth;
16211708Sstevel 	int		err;
16221708Sstevel 
16231708Sstevel 	err = picldiag_get_string_propval(hubh, PICL_PROP_NAME, &name);
16241708Sstevel 	if (err != PICL_SUCCESS)
16251708Sstevel 		return (err);
16261708Sstevel 	log_printf("%-12.12s  ", name);
16271708Sstevel 	free(name);
16281708Sstevel 
16291708Sstevel 	err = picl_get_propval_by_name(hubh, PICL_REFPROP_LOC_PARENT, &parenth,
16301708Sstevel 	    sizeof (picl_nodehdl_t));
16311708Sstevel 
16321708Sstevel 	if (err == PICL_SUCCESS) {
16331708Sstevel 		/* Read the Label */
16341708Sstevel 		err = picldiag_get_label(parenth, &labelp);
16351708Sstevel 		if (err == PICL_SUCCESS) {
16361708Sstevel 			log_printf("%s\n", labelp);
16371708Sstevel 			free(labelp);
16381708Sstevel 			return (PICL_SUCCESS);
16391708Sstevel 		} else if (err != PICL_PROPNOTFOUND) {
16401708Sstevel 			log_printf("\n");
16411708Sstevel 			return (err);
16421708Sstevel 		}
16431708Sstevel 	} else if (err != PICL_PROPNOTFOUND) {
16441708Sstevel 		log_printf("\n");
16451708Sstevel 		return (err);
16461708Sstevel 	}
16471708Sstevel 
16481708Sstevel 	/* No Label, try the reg */
16491708Sstevel 	err = picl_get_propval_by_name(hubh, OBP_PROP_REG, &portnum,
16501708Sstevel 	    sizeof (portnum));
16511708Sstevel 	if (err == PICL_PROPNOTFOUND)
16521708Sstevel 		log_printf("  -\n");
16531708Sstevel 	else if (err != PICL_SUCCESS) {
16541708Sstevel 		log_printf("\n");
16551708Sstevel 		return (err);
16561708Sstevel 	} else
16571708Sstevel 		log_printf("%3d\n", portnum);
16581708Sstevel 
16591708Sstevel 	return (PICL_SUCCESS);
16601708Sstevel }
16611708Sstevel 
16621708Sstevel /*
16631708Sstevel  * callback functions to display hub devices
16641708Sstevel  */
16651708Sstevel /* ARGSUSED */
16661708Sstevel static int
print_usb_devices(picl_nodehdl_t hubh,void * arg)16671708Sstevel print_usb_devices(picl_nodehdl_t hubh, void *arg)
16681708Sstevel {
16691708Sstevel 	picl_nodehdl_t	chdh;
16701708Sstevel 	char		*rootname;
16711708Sstevel 	int		type = *(int *)arg;
16721708Sstevel 	int		hubnum;
16731708Sstevel 	int		err;
16741708Sstevel 
16751708Sstevel 	err = picl_get_propval_by_name(hubh, PICL_PROP_CHILD, &chdh,
16761708Sstevel 	    sizeof (picl_nodehdl_t));
16771708Sstevel 
16781708Sstevel 	/* print header */
16791708Sstevel 	if (err == PICL_SUCCESS) {
16801708Sstevel 		err = picldiag_get_string_propval(hubh, PICL_PROP_NAME,
16811708Sstevel 		    &rootname);
16821708Sstevel 		if (err != PICL_SUCCESS)
16831708Sstevel 			return (err);
16841708Sstevel 
16851708Sstevel 		if (type == USB) {
16861708Sstevel 			log_printf("\n===============================");
16871708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
16881708Sstevel 			    " %s Devices "), rootname);
16891708Sstevel 		} else {
16901708Sstevel 			/* Get its hub number */
16911708Sstevel 			err = picl_get_propval_by_name(hubh,
16921708Sstevel 			    OBP_PROP_REG, &hubnum, sizeof (hubnum));
16931708Sstevel 			if ((err != PICL_SUCCESS) &&
16941708Sstevel 			    (err != PICL_PROPNOTFOUND)) {
16951708Sstevel 				free(rootname);
16961708Sstevel 				return (err);
16971708Sstevel 			}
16981708Sstevel 
16991708Sstevel 			log_printf("\n===============================");
17001708Sstevel 			if (err == PICL_SUCCESS)
17011708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
17021708Sstevel 				    " %s#%d Devices "),
17031708Sstevel 				    rootname, hubnum);
17041708Sstevel 			else
17051708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
17061708Sstevel 				    " %s Devices "), rootname);
17071708Sstevel 		}
17081708Sstevel 
17091708Sstevel 		log_printf("===============================\n\n");
17101708Sstevel 		log_printf("Name          Port#\n");
17111708Sstevel 		log_printf("------------  -----\n");
17121708Sstevel 		free(rootname);
17131708Sstevel 
17141708Sstevel 		do {
17151708Sstevel 			logprintf_hub_devices(chdh);
17161708Sstevel 
17171708Sstevel 			err = picl_get_propval_by_name(chdh, PICL_PROP_PEER,
17181708Sstevel 			    &chdh, sizeof (picl_nodehdl_t));
17191708Sstevel 		} while (err == PICL_SUCCESS);
17201708Sstevel 	}
17211708Sstevel 
17221708Sstevel 
17231708Sstevel 	if (err == PICL_PROPNOTFOUND)
17241708Sstevel 		return (PICL_WALK_CONTINUE);
17251708Sstevel 	return (err);
17261708Sstevel }
17271708Sstevel 
17281708Sstevel /*
17291708Sstevel  * callback functions to display usb devices
17301708Sstevel  */
17311708Sstevel /* ARGSUSED */
17321708Sstevel static int
usb_callback(picl_nodehdl_t usbh,void * args)17331708Sstevel usb_callback(picl_nodehdl_t usbh, void *args)
17341708Sstevel {
17351708Sstevel 	int		err;
17361708Sstevel 	int		type;
17371708Sstevel 
17381708Sstevel 	type = USB;
17391708Sstevel 	err = print_usb_devices(usbh, &type);
17401708Sstevel 	if (err != PICL_WALK_CONTINUE)
17411708Sstevel 		return (err);
17421708Sstevel 	type = HUB;
17431708Sstevel 	err = picl_walk_tree_by_class(usbh, NULL, &type, print_usb_devices);
17441708Sstevel 	if (err == PICL_SUCCESS)
17451708Sstevel 		err = PICL_WALK_CONTINUE;
17461708Sstevel 	return (err);
17471708Sstevel }
17481708Sstevel 
17491708Sstevel 
17501708Sstevel /*
17511708Sstevel  * find usb devices and print its information
17521708Sstevel  */
17531708Sstevel static int
display_usb_devices(picl_nodehdl_t plafh)17541708Sstevel display_usb_devices(picl_nodehdl_t plafh)
17551708Sstevel {
17561708Sstevel 	int err;
17571708Sstevel 
17581708Sstevel 	/*
17591708Sstevel 	 * get the usb node
17601708Sstevel 	 */
17611708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_USB, NULL,
17621708Sstevel 	    usb_callback);
17631708Sstevel 	return (err);
17641708Sstevel }
17651708Sstevel 
17661708Sstevel 
17671708Sstevel 
17681708Sstevel /*
17691708Sstevel  * If nodeh is the io device, add it into the io list and return
17701708Sstevel  * If it is not an io device and it has the subtree, traverse the subtree
17711708Sstevel  * and add all leaf io devices
17721708Sstevel  */
17731708Sstevel 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)17741708Sstevel add_io_leaves(picl_nodehdl_t nodeh, char *parentname, uint32_t board,
17751708Sstevel     uint32_t bus_id, uint64_t slot, uint32_t freq, char *model, char *status)
17761708Sstevel {
17771708Sstevel 	picl_nodehdl_t	childh;
17781708Sstevel 	picl_prophdl_t	proph;
17791708Sstevel 	picl_propinfo_t	pinfo;
17801708Sstevel 	int		err;
17811708Sstevel 	char		*nameval;
17821708Sstevel 	char		piclclass[PICL_CLASSNAMELEN_MAX];
17831708Sstevel 	char		nodename[MAXSTRLEN];
17841708Sstevel 	char		name[MAXSTRLEN];
17851708Sstevel 	char		*devfs_path;
17861708Sstevel 	char		*compatible;
17871708Sstevel 	picl_nodehdl_t	fruparenth;
17881708Sstevel 	char		*label;
17891708Sstevel 	char		binding_name[MAXSTRLEN];
17901708Sstevel 
17911708Sstevel 	err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME, &pinfo,
17921708Sstevel 	    &proph);
17931708Sstevel 	if (err != PICL_SUCCESS)
17941708Sstevel 		return (err);
17951708Sstevel 
17961708Sstevel 	nameval = alloca(pinfo.size);
17971708Sstevel 	if (nameval == NULL)
17981708Sstevel 		return (PICL_FAILURE);
17991708Sstevel 
18001708Sstevel 	err = picl_get_propval(proph, nameval, pinfo.size);
18011708Sstevel 	if (err != PICL_SUCCESS)
18021708Sstevel 		return (err);
18031708Sstevel 
18041708Sstevel 	(void) strlcpy(nodename, nameval, MAXSTRLEN);
18051708Sstevel 
18061708Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
18071708Sstevel 	    piclclass, sizeof (piclclass));
18081708Sstevel 	if (err != PICL_SUCCESS)
18091708Sstevel 		return (err);
18101708Sstevel 
18111708Sstevel 	/* if binding_name is found, name will be <nodename>-<binding_name> */
18121708Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
18131708Sstevel 	    binding_name, sizeof (binding_name));
18141708Sstevel 	if (err == PICL_PROPNOTFOUND) {
18151708Sstevel 		/*
18161708Sstevel 		 * if compatible prop is found, name will be
18171708Sstevel 		 * <nodename>-<compatible>
18181708Sstevel 		 */
18191708Sstevel 		err = picldiag_get_first_compatible_value(nodeh, &compatible);
18201708Sstevel 		if (err == PICL_SUCCESS) {
18211708Sstevel 			strlcat(nodename, "-", MAXSTRLEN);
18221708Sstevel 			strlcat(nodename, compatible, MAXSTRLEN);
18231708Sstevel 			free(compatible);
18241708Sstevel 		} else if (err != PICL_PROPNOTFOUND) {
18251708Sstevel 			return (err);
18261708Sstevel 		}
18271708Sstevel 	} else if (err != PICL_SUCCESS) {
18281708Sstevel 		return (err);
18291708Sstevel 	} else if (strcmp(nodename, binding_name) != 0) {
18301708Sstevel 		if (strcmp(nodename, piclclass) == 0) {
18311708Sstevel 			/*
18321708Sstevel 			 * nodename same as binding name -
18331708Sstevel 			 * no need to display twice
18341708Sstevel 			 */
18351708Sstevel 			strlcpy(nodename, binding_name, MAXSTRLEN);
18361708Sstevel 		} else {
18371708Sstevel 			strlcat(nodename, "-", MAXSTRLEN);
18381708Sstevel 			strlcat(nodename, binding_name, MAXSTRLEN);
18391708Sstevel 		}
18401708Sstevel 	}
18411708Sstevel 
18421708Sstevel 	/*
18431708Sstevel 	 * If it is an immediate child under pci/pciex/sbus/upa and not
18441708Sstevel 	 * a bus node, add it to the io list.
18451708Sstevel 	 * If it is a child under sub-bus and it is in an io
18461708Sstevel 	 * device, add it to the io list.
18471708Sstevel 	 */
18481708Sstevel 	if (((parentname == NULL) && (!is_bus(piclclass))) ||
18491708Sstevel 	    ((parentname != NULL) && (is_io_device(piclclass)))) {
18501708Sstevel 		if (parentname == NULL)
18511708Sstevel 			(void) snprintf(name, MAXSTRLEN, "%s", nodename);
18521708Sstevel 		else
18531708Sstevel 			(void) snprintf(name, MAXSTRLEN, "%s/%s", parentname,
18541708Sstevel 			    nodename);
18551708Sstevel 
18561708Sstevel 		/*
18571708Sstevel 		 * append the class if its class is not a generic
18581708Sstevel 		 * obp-device class
18591708Sstevel 		 */
18601708Sstevel 		if (strcmp(piclclass, PICL_CLASS_OBP_DEVICE))
18611708Sstevel 			(void) snprintf(name, MAXSTRLEN, "%s (%s)", name,
18621708Sstevel 			    piclclass);
18631708Sstevel 
18641708Sstevel 		err = picldiag_get_fru_parent(nodeh, &fruparenth);
18651708Sstevel 		if (err == PICL_PROPNOTFOUND) {
18661708Sstevel 			label = NULL;
18671708Sstevel 		} else if (err != PICL_SUCCESS) {
18681708Sstevel 			return (err);
18691708Sstevel 		} else {
18701708Sstevel 			err = picldiag_get_combined_label(fruparenth, &label,
18711708Sstevel 			    15);
18721708Sstevel 			if (err == PICL_PROPNOTFOUND)
18731708Sstevel 				label = NULL;
18741708Sstevel 			else if (err != PICL_SUCCESS)
18751708Sstevel 				return (err);
18761708Sstevel 		}
18771708Sstevel 		/* devfs-path */
18781708Sstevel 		err =  picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH,
18791708Sstevel 		    &devfs_path);
18801708Sstevel 		if (err == PICL_PROPNOTFOUND)
18811708Sstevel 			devfs_path = NULL;
18821708Sstevel 		else if (err != PICL_SUCCESS)
18831708Sstevel 			return (err);
18841708Sstevel 
18851708Sstevel 		add_io_card(board, bus_id, slot, label, freq, name,
18861708Sstevel 		    model, status, devfs_path);
18871708Sstevel 		if (label != NULL)
18881708Sstevel 			free(label);
18891708Sstevel 		if (devfs_path != NULL)
18901708Sstevel 			free(devfs_path);
18911708Sstevel 		return (PICL_SUCCESS);
18921708Sstevel 	}
18931708Sstevel 
18941708Sstevel 	/*
18951708Sstevel 	 * If there is any child, Go through each child.
18961708Sstevel 	 */
18971708Sstevel 
18981708Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
18991708Sstevel 	    &childh, sizeof (picl_nodehdl_t));
19001708Sstevel 
19011708Sstevel 	/* there is a child */
19021708Sstevel 	while (err == PICL_SUCCESS) {
19031708Sstevel 		if (parentname == NULL)
19041708Sstevel 			(void) strlcpy(name, nodename, MAXSTRLEN);
19051708Sstevel 		else
19061708Sstevel 			(void) snprintf(name, MAXSTRLEN, "%s/%s", parentname,
19071708Sstevel 			    nodename);
19081708Sstevel 
19091708Sstevel 		err = add_io_leaves(childh, name, board, bus_id, slot, freq,
19101708Sstevel 		    model, status);
19111708Sstevel 		if (err != PICL_SUCCESS)
19121708Sstevel 			return (err);
19131708Sstevel 		/*
19141708Sstevel 		 * get next child
19151708Sstevel 		 */
19161708Sstevel 		err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
19171708Sstevel 		    &childh, sizeof (picl_nodehdl_t));
19181708Sstevel 	}
19191708Sstevel 
19201708Sstevel 	if (err == PICL_PROPNOTFOUND)
19211708Sstevel 		return (PICL_SUCCESS);
19221708Sstevel 	return (err);
19231708Sstevel }
19241708Sstevel 
19251708Sstevel /*
19261708Sstevel  * callback function to add all io devices under sbus in io list
19271708Sstevel  */
19281708Sstevel /*ARGSUSED*/
19291708Sstevel static int
sbus_callback(picl_nodehdl_t sbush,void * args)19301708Sstevel sbus_callback(picl_nodehdl_t sbush, void *args)
19311708Sstevel {
19321708Sstevel 	picl_nodehdl_t	nodeh;
19331708Sstevel 	int		err;
19341708Sstevel 	uint32_t	boardnum;
19351708Sstevel 	uint32_t	bus_id;
19361708Sstevel 	uint32_t	slot;
19371708Sstevel 	uint32_t	freq;
19381708Sstevel 	char		*model;
19391708Sstevel 	char		*status;
19401708Sstevel 
19411708Sstevel 	/* Fill in common infomation */
19421708Sstevel 	bus_id = SBUS_TYPE;
19431708Sstevel 
19441708Sstevel 	err = picldiag_get_clock_freq(sbush, &freq);
19451708Sstevel 	if (err == PICL_PROPNOTFOUND)
19461708Sstevel 		return (PICL_WALK_CONTINUE);
19471708Sstevel 	else if (err != PICL_SUCCESS)
19481708Sstevel 		return (err);
19491708Sstevel 	/*
19501708Sstevel 	 * If no board# is found, set boardnum to 0
19511708Sstevel 	 */
19521708Sstevel 	boardnum = picldiag_get_uint_propval(sbush, OBP_PROP_BOARD_NUM, &err);
19531708Sstevel 	if (err == PICL_PROPNOTFOUND)
19541708Sstevel 		boardnum = DEFAULT_BOARD_NUM;
19551708Sstevel 	else if (err != PICL_SUCCESS)
19561708Sstevel 		return (err);
19571708Sstevel 
19581708Sstevel 	err = picl_get_propval_by_name(sbush, PICL_PROP_CHILD, &nodeh,
19591708Sstevel 	    sizeof (picl_nodehdl_t));
19601708Sstevel 
19611708Sstevel 	while (err == PICL_SUCCESS) {
19621708Sstevel 		slot = picldiag_get_uint_propval(nodeh,
19631708Sstevel 		    PICL_PROP_SLOT, &err);
19641708Sstevel 		if (err == PICL_PROPNOTFOUND) {
19651708Sstevel 			err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
19661708Sstevel 			    &nodeh, sizeof (picl_nodehdl_t));
19671708Sstevel 			continue;
19681708Sstevel 		} else if (err != PICL_SUCCESS)
19691708Sstevel 			return (err);
19701708Sstevel 
19711708Sstevel 		err =  picldiag_get_string_propval(nodeh, OBP_PROP_MODEL,
19721708Sstevel 		    &model);
19731708Sstevel 		if (err == PICL_PROPNOTFOUND)
19741708Sstevel 			model = NULL;
19751708Sstevel 		else if (err != PICL_SUCCESS)
19761708Sstevel 			return (err);
19771708Sstevel 
19781708Sstevel 		err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS,
19791708Sstevel 		    &status);
19801708Sstevel 		if (err == PICL_PROPNOTFOUND) {
19811708Sstevel 			status = malloc(5);
19821708Sstevel 			if (status == NULL)
19831708Sstevel 				return (PICL_FAILURE);
19841708Sstevel 			strncpy(status, "okay", 5);
19851708Sstevel 		} else if (err != PICL_SUCCESS)
19861708Sstevel 			return (err);
19871708Sstevel 
19881708Sstevel 		err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot, freq,
19891708Sstevel 		    model, status);
19901708Sstevel 		if (model != NULL)
19911708Sstevel 			free(model);
19921708Sstevel 		if (status != NULL)
19931708Sstevel 			free(status);
19941708Sstevel 		if (err != PICL_SUCCESS)
19951708Sstevel 			return (err);
19961708Sstevel 
19971708Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
19981708Sstevel 		    sizeof (picl_nodehdl_t));
19991708Sstevel 	}
20001708Sstevel 	if (err == PICL_PROPNOTFOUND)
20011708Sstevel 		return (PICL_WALK_CONTINUE);
20021708Sstevel 	return (err);
20031708Sstevel }
20041708Sstevel 
20051708Sstevel /*
20061708Sstevel  * add all io devices under pci/pciex in io list
20071708Sstevel  */
20081708Sstevel /* ARGSUSED */
20091708Sstevel static int
pci_pciex_callback(picl_nodehdl_t pcih,void * args)20101708Sstevel pci_pciex_callback(picl_nodehdl_t pcih, void *args)
20111708Sstevel {
20121708Sstevel 	picl_nodehdl_t	nodeh;
20131708Sstevel 	int		err;
20141708Sstevel 	char		piclclass[PICL_CLASSNAMELEN_MAX];
20151708Sstevel 	uint32_t	boardnum;
20161708Sstevel 	uint32_t	bus_id;
20171708Sstevel 	uint32_t	slot;
20181708Sstevel 	uint32_t	freq;
20191708Sstevel 	char		*model;
20201708Sstevel 	char		*status;
20211708Sstevel 
20221708Sstevel 	if (strcmp(args, PICL_CLASS_PCIEX) == 0)
20231708Sstevel 		bus_id = PCIEX_TYPE;
20241708Sstevel 	else
20251708Sstevel 		bus_id = PCI_TYPE;
20261708Sstevel 
20271708Sstevel 	/*
20281708Sstevel 	 * Check if it has the freq, if not,
20291708Sstevel 	 * If not, use its parent's freq
20301708Sstevel 	 * if its parent's freq is not found, return
20311708Sstevel 	 */
20321708Sstevel 	err = picldiag_get_clock_freq(pcih, &freq);
20331708Sstevel 	if (err == PICL_PROPNOTFOUND) {
20341708Sstevel 		err = picldiag_get_clock_from_parent(pcih, &freq);
20351708Sstevel 		if (err == PICL_PROPNOTFOUND)
20361708Sstevel 			return (PICL_WALK_CONTINUE);
20371708Sstevel 		else if (err != PICL_SUCCESS)
20381708Sstevel 			return (err);
20391708Sstevel 	} else if (err != PICL_SUCCESS)
20401708Sstevel 		return (err);
20411708Sstevel 
20421708Sstevel 	/*
20431708Sstevel 	 * If no board# is found, set boardnum to 0
20441708Sstevel 	 */
20451708Sstevel 	boardnum = picldiag_get_uint_propval(pcih, OBP_PROP_BOARD_NUM, &err);
20461708Sstevel 	if (err == PICL_PROPNOTFOUND)
20471708Sstevel 		boardnum = DEFAULT_BOARD_NUM;
20481708Sstevel 	else if (err != PICL_SUCCESS)
20491708Sstevel 		return (err);
20501708Sstevel 
20511708Sstevel 	/* Walk through the children */
20521708Sstevel 
20531708Sstevel 	err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
20541708Sstevel 	    sizeof (picl_nodehdl_t));
20551708Sstevel 	while (err == PICL_SUCCESS) {
20561708Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
20571708Sstevel 		    piclclass, sizeof (piclclass));
20581708Sstevel 		if (err != PICL_SUCCESS)
20591708Sstevel 			return (err);
20601708Sstevel 
20611708Sstevel 		/*
20621708Sstevel 		 * Skip PCIEX, PCI bridge and USB devices because they will be
20631708Sstevel 		 * processed later
20641708Sstevel 		 */
20651708Sstevel 		if ((strcmp(piclclass, PICL_CLASS_PCI) == 0) ||
20661708Sstevel 		    (strcmp(piclclass, PICL_CLASS_PCIEX) == 0) ||
20671708Sstevel 		    (strcmp(piclclass, PICL_CLASS_USB) == 0)) {
20681708Sstevel 			err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
20691708Sstevel 			    &nodeh, sizeof (picl_nodehdl_t));
20701708Sstevel 			continue;
20711708Sstevel 		}
20721708Sstevel 
20731708Sstevel 		/* Get the device id for pci card */
20741708Sstevel 		slot = picldiag_get_uint_propval(nodeh,
20751708Sstevel 		    PICL_PROP_DEVICE_ID, &err);
20761708Sstevel 		if (err == PICL_PROPNOTFOUND) {
20771708Sstevel 			err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
20781708Sstevel 			    &nodeh, sizeof (picl_nodehdl_t));
20791708Sstevel 			continue;
20801708Sstevel 		} else if (err != PICL_SUCCESS)
20811708Sstevel 			return (err);
20821708Sstevel 
20831708Sstevel 		/* Get the model of this card */
20841708Sstevel 		err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL,
20851708Sstevel 		    &model);
20861708Sstevel 		if (err == PICL_PROPNOTFOUND)
20871708Sstevel 			model = NULL;
20881708Sstevel 		else if (err != PICL_SUCCESS)
20891708Sstevel 			return (err);
20901708Sstevel 
20911708Sstevel 		err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS,
20921708Sstevel 		    &status);
20931708Sstevel 		if (err == PICL_PROPNOTFOUND) {
20941708Sstevel 			status = malloc(5);
20951708Sstevel 			if (status == NULL)
20961708Sstevel 				return (PICL_FAILURE);
20971708Sstevel 			strncpy(status, "okay", 5);
20981708Sstevel 		} else if (err != PICL_SUCCESS)
20991708Sstevel 			return (err);
21001708Sstevel 
21011708Sstevel 		err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot,
21021708Sstevel 		    freq, model, status);
21031708Sstevel 
21041708Sstevel 		if (model != NULL)
21051708Sstevel 			free(model);
21061708Sstevel 
21071708Sstevel 		if (status != NULL)
21081708Sstevel 			free(status);
21091708Sstevel 
21101708Sstevel 		if (err != PICL_SUCCESS)
21111708Sstevel 			return (err);
21121708Sstevel 
21131708Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
21141708Sstevel 		    sizeof (picl_nodehdl_t));
21151708Sstevel 
21161708Sstevel 	}
21171708Sstevel 
21181708Sstevel 	if (err == PICL_PROPNOTFOUND)
21191708Sstevel 		return (PICL_WALK_CONTINUE);
21201708Sstevel 
21211708Sstevel 	return (err);
21221708Sstevel }
21231708Sstevel 
21241708Sstevel /*
21251708Sstevel  * add io devices in io list
21261708Sstevel  * Its slot number is drived from upa-portid
21271708Sstevel  */
21281708Sstevel static int
add_io_devices(picl_nodehdl_t nodeh)21291708Sstevel add_io_devices(picl_nodehdl_t nodeh)
21301708Sstevel {
21311708Sstevel 	int		err;
21321708Sstevel 	uint64_t	board_type;
21331708Sstevel 	char 		piclclass[PICL_CLASSNAMELEN_MAX];
21341708Sstevel 	char 		name[MAXSTRLEN];
21351708Sstevel 	char 		*devfs_path;
21361708Sstevel 	char		*nameval;
21371708Sstevel 	uint32_t	boardnum;
21381708Sstevel 	uint32_t	bus_id;
21391708Sstevel 	uint32_t	slot;
21401708Sstevel 	uint32_t	freq;
21411708Sstevel 	char		*model;
21421708Sstevel 	char		*status;
21431708Sstevel 	picl_prophdl_t  proph;
21441708Sstevel 	picl_propinfo_t	pinfo;
21451708Sstevel 	picl_nodehdl_t	fruparenth;
21461708Sstevel 	char		*label;
21471708Sstevel 
21481708Sstevel 
21491708Sstevel 	bus_id = UPA_TYPE;
21501708Sstevel 
21511708Sstevel 	/*
21521708Sstevel 	 * If clock frequency can't be found from its parent, don't add
21531708Sstevel 	 */
21541708Sstevel 	err = picldiag_get_clock_from_parent(nodeh, &freq);
21551708Sstevel 	if (err == PICL_PROPNOTFOUND)
21561708Sstevel 		return (PICL_SUCCESS);
21571708Sstevel 	else if (err != PICL_SUCCESS)
21581708Sstevel 		return (err);
21591708Sstevel 
21601708Sstevel 	/*
21611708Sstevel 	 * If no board# is found, set boardnum to 0
21621708Sstevel 	 */
21631708Sstevel 	boardnum = picldiag_get_uint_propval(nodeh, OBP_PROP_BOARD_NUM, &err);
21641708Sstevel 	if (err == PICL_PROPNOTFOUND)
21651708Sstevel 		boardnum = DEFAULT_BOARD_NUM;
21661708Sstevel 	else if (err != PICL_SUCCESS)
21671708Sstevel 		return (err);
21681708Sstevel 
21691708Sstevel 	/*
21701708Sstevel 	 * get upa portid as slot number
21711708Sstevel 	 * If upa portid is not found, don't add the card.
21721708Sstevel 	 */
21731708Sstevel 	slot = picldiag_get_uint_propval(nodeh, OBP_PROP_UPA_PORTID,
21741708Sstevel 	    &err);
21751708Sstevel 	if (err == PICL_PROPNOTFOUND)
21761708Sstevel 		return (PICL_SUCCESS);
21771708Sstevel 	else if (err != PICL_SUCCESS)
21781708Sstevel 		return (err);
21791708Sstevel 
21801708Sstevel 	/* Get the model of this card */
21811708Sstevel 	err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL, &model);
21821708Sstevel 	if (err == PICL_PROPNOTFOUND)
21831708Sstevel 		model = NULL;
21841708Sstevel 	else if (err != PICL_SUCCESS)
21851708Sstevel 		return (err);
21861708Sstevel 
21871708Sstevel 	/*
21881708Sstevel 	 * check if it is a ffb device
21891708Sstevel 	 * If it's a ffb device, append its board type to name
21901708Sstevel 	 * otherwise, use its nodename
21911708Sstevel 	 */
21921708Sstevel 	err = picl_get_prop_by_name(nodeh, PICL_PROP_FFB_BOARD_REV, &proph);
21931708Sstevel 	if (err == PICL_PROPNOTFOUND) {
21941708Sstevel 		err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME,
21951708Sstevel 		    &pinfo, &proph);
21961708Sstevel 		if (err != PICL_SUCCESS)
21971708Sstevel 			return (err);
21981708Sstevel 
21991708Sstevel 		nameval = alloca(pinfo.size);
22001708Sstevel 		if (nameval == NULL)
22011708Sstevel 			return (PICL_FAILURE);
22021708Sstevel 
22031708Sstevel 		err = picl_get_propval(proph, nameval, pinfo.size);
22041708Sstevel 		if (err != PICL_SUCCESS)
22051708Sstevel 			return (err);
22061708Sstevel 
22071708Sstevel 		(void) strlcpy(name, nameval, MAXSTRLEN);
22081708Sstevel 	} else if (err == PICL_SUCCESS) {
22091708Sstevel 		/* Find out if it's single or double buffered */
22101708Sstevel 		board_type = picldiag_get_uint_propval(nodeh,
22111708Sstevel 		    OBP_PROP_BOARD_TYPE, &err);
22121708Sstevel 		if (err == PICL_PROPNOTFOUND)
22131708Sstevel 			(void) strlcpy(name, FFB_NAME, sizeof (name));
22141708Sstevel 		if (err == PICL_SUCCESS) {
22151708Sstevel 			if (board_type & FFB_B_BUFF)
22161708Sstevel 				(void) strlcpy(name, FFB_DOUBLE_BUF,
22171708Sstevel 				    sizeof (name));
22181708Sstevel 			else
22191708Sstevel 				(void) strlcpy(name, FFB_SINGLE_BUF,
22201708Sstevel 				    sizeof (name));
22211708Sstevel 		} else
22221708Sstevel 			return (err);
22231708Sstevel 	} else
22241708Sstevel 		return (err);
22251708Sstevel 
22261708Sstevel 	err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
22271708Sstevel 	    piclclass, sizeof (piclclass));
22281708Sstevel 	if (err != PICL_SUCCESS)
22291708Sstevel 		return (err);
22301708Sstevel 
22311708Sstevel 	(void) snprintf(name, sizeof (name), "%s (%s)", name, piclclass);
22321708Sstevel 
22331708Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status);
22341708Sstevel 	if (err == PICL_PROPNOTFOUND) {
22351708Sstevel 		status = malloc(5);
22361708Sstevel 		if (status == NULL)
22371708Sstevel 			return (PICL_FAILURE);
22381708Sstevel 		strncpy(status, "okay", 5);
22391708Sstevel 	} else if (err != PICL_SUCCESS)
22401708Sstevel 		return (err);
22411708Sstevel 
22421708Sstevel 	err = picldiag_get_fru_parent(nodeh, &fruparenth);
22431708Sstevel 	if (err == PICL_PROPNOTFOUND) {
22441708Sstevel 		label = NULL;
22451708Sstevel 	} else if (err != PICL_SUCCESS) {
22461708Sstevel 		return (err);
22471708Sstevel 	} else {
22481708Sstevel 		err = picldiag_get_combined_label(fruparenth, &label, 15);
22491708Sstevel 		if (err == PICL_PROPNOTFOUND)
22501708Sstevel 			label = NULL;
22511708Sstevel 		else if (err != PICL_SUCCESS)
22521708Sstevel 			return (err);
22531708Sstevel 	}
22541708Sstevel 	/* devfs-path */
22551708Sstevel 	err =  picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH,
22561708Sstevel 	    &devfs_path);
22571708Sstevel 	if (err == PICL_PROPNOTFOUND)
22581708Sstevel 		devfs_path = NULL;
22591708Sstevel 	else if (err != PICL_SUCCESS)
22601708Sstevel 		return (err);
22611708Sstevel 
22621708Sstevel 	add_io_card(boardnum, bus_id, slot, label, freq, name, model, status,
22631708Sstevel 	    devfs_path);
22641708Sstevel 	if (label != NULL)
22651708Sstevel 		free(label);
22661708Sstevel 	if (model != NULL)
22671708Sstevel 		free(model);
22681708Sstevel 	if (status != NULL)
22691708Sstevel 		free(status);
22701708Sstevel 	if (devfs_path != NULL)
22711708Sstevel 		free(devfs_path);
22721708Sstevel 
22731708Sstevel 	return (PICL_SUCCESS);
22741708Sstevel }
22751708Sstevel 
22761708Sstevel /*
22771708Sstevel  * loop through all children and add io devices in io list
22781708Sstevel  */
22791708Sstevel static int
process_io_leaves(picl_nodehdl_t rooth)22801708Sstevel process_io_leaves(picl_nodehdl_t rooth)
22811708Sstevel {
22821708Sstevel 	picl_nodehdl_t	nodeh;
22831708Sstevel 	char		classval[PICL_CLASSNAMELEN_MAX];
22841708Sstevel 	int		err;
22851708Sstevel 
22861708Sstevel 	err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh,
22871708Sstevel 	    sizeof (picl_nodehdl_t));
22881708Sstevel 	while (err == PICL_SUCCESS) {
22891708Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
22901708Sstevel 		    classval, sizeof (classval));
22911708Sstevel 		if (err != PICL_SUCCESS)
22921708Sstevel 			return (err);
22931708Sstevel 
22941708Sstevel 		if (is_io_device(classval))
22951708Sstevel 			err = add_io_devices(nodeh);
22961708Sstevel 
22971708Sstevel 		if (err != PICL_SUCCESS)
22981708Sstevel 			return (err);
22991708Sstevel 
23001708Sstevel 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
23011708Sstevel 		    sizeof (picl_nodehdl_t));
23021708Sstevel 	}
23031708Sstevel 
23041708Sstevel 	if (err == PICL_PROPNOTFOUND)
23051708Sstevel 		return (PICL_SUCCESS);
23061708Sstevel 
23071708Sstevel 	return (err);
23081708Sstevel }
23091708Sstevel 
23101708Sstevel /*
23111708Sstevel  * callback function to add all io devices under upa in io list
23121708Sstevel  */
23131708Sstevel /*ARGSUSED*/
23141708Sstevel static int
upa_callback(picl_nodehdl_t upah,void * args)23151708Sstevel upa_callback(picl_nodehdl_t upah, void *args)
23161708Sstevel {
23171708Sstevel 	int		err;
23181708Sstevel 
23191708Sstevel 	err = process_io_leaves(upah);
23201708Sstevel 
23211708Sstevel 	if (err == PICL_SUCCESS)
23221708Sstevel 		return (PICL_WALK_CONTINUE);
23231708Sstevel 	return (err);
23241708Sstevel }
23251708Sstevel 
23261708Sstevel /*
23271708Sstevel  * display ffb hardware configuration
23281708Sstevel  */
23291708Sstevel /* ARGSUSED */
23301708Sstevel static int
ffbconfig_callback(picl_nodehdl_t ffbh,void * arg)23311708Sstevel ffbconfig_callback(picl_nodehdl_t ffbh, void *arg)
23321708Sstevel {
23331708Sstevel 	int		err;
23341708Sstevel 	uint64_t	board_rev;
23351708Sstevel 	uint64_t	fbc_ver;
23361708Sstevel 	char		*dac_ver;
23371708Sstevel 	char		*fbram_ver;
23381708Sstevel 
23391708Sstevel 	/*
23401708Sstevel 	 * If it has PICL_PROP_FFB_BOARD_REV, it is a ffb device
23411708Sstevel 	 * Otherwise, return.
23421708Sstevel 	 */
23431708Sstevel 	board_rev = picldiag_get_uint_propval(ffbh, PICL_PROP_FFB_BOARD_REV,
23441708Sstevel 	    &err);
23451708Sstevel 	if (err == PICL_PROPNOTFOUND)
23461708Sstevel 		return (PICL_WALK_CONTINUE);
23471708Sstevel 	else if (err != PICL_SUCCESS)
23481708Sstevel 		return (err);
23491708Sstevel 
23501708Sstevel 	log_printf("FFB Hardware Configuration:\n");
23511708Sstevel 	log_printf("-----------------------------------\n");
23521708Sstevel 	log_printf("Board rev: %lld\n", board_rev);
23531708Sstevel 
23541708Sstevel 	fbc_ver = picldiag_get_uint_propval(ffbh, OBP_PROP_FBC_REG_ID,
23551708Sstevel 	    &err);
23561708Sstevel 	if (err == PICL_SUCCESS)
23571708Sstevel 		log_printf("FBC version: 0x%llx\n", fbc_ver);
23581708Sstevel 	else if (err != PICL_PROPNOTFOUND)
23591708Sstevel 		return (err);
23601708Sstevel 
23611708Sstevel 	err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_DAC_VER,
23621708Sstevel 	    &dac_ver);
23631708Sstevel 	if (err == PICL_SUCCESS) {
23641708Sstevel 		log_printf("DAC: %s\n", dac_ver);
23651708Sstevel 		free(dac_ver);
23661708Sstevel 	} else if (err != PICL_PROPNOTFOUND)
23671708Sstevel 		return (err);
23681708Sstevel 
23691708Sstevel 	err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_FBRAM_VER,
23701708Sstevel 	    &fbram_ver);
23711708Sstevel 	if (err  == PICL_SUCCESS) {
23721708Sstevel 		log_printf("3DRAM: %s\n", fbram_ver);
23731708Sstevel 		free(fbram_ver);
23741708Sstevel 	} else if (err != PICL_PROPNOTFOUND)
23751708Sstevel 		return (err);
23761708Sstevel 
23771708Sstevel 	log_printf("\n");
23781708Sstevel 	return (PICL_WALK_CONTINUE);
23791708Sstevel }
23801708Sstevel 
23811708Sstevel /*
23821708Sstevel  * find all io devices and add them in the io list
23831708Sstevel  */
23841708Sstevel static int
gather_io_cards(picl_nodehdl_t plafh)23851708Sstevel gather_io_cards(picl_nodehdl_t plafh)
23861708Sstevel {
23871708Sstevel 	int		err;
23881708Sstevel 
23891708Sstevel 	/*
23901708Sstevel 	 * look for io devices under the immediate children of platform
23911708Sstevel 	 */
23921708Sstevel 	err = process_io_leaves(plafh);
23931708Sstevel 	if (err != PICL_SUCCESS)
23941708Sstevel 		return (err);
23951708Sstevel 
23961708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_SBUS,
23971708Sstevel 	    PICL_CLASS_SBUS, sbus_callback);
23981708Sstevel 	if (err != PICL_SUCCESS)
23991708Sstevel 		return (err);
24001708Sstevel 
24011708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
24021708Sstevel 	    PICL_CLASS_PCI, pci_pciex_callback);
24031708Sstevel 	if (err != PICL_SUCCESS)
24041708Sstevel 		return (err);
24051708Sstevel 
24061708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
2407*13019SMichael.Bergknoff@Oracle.COM 	    PICL_CLASS_PCIEX, pci_pciex_callback);
24081708Sstevel 	if (err != PICL_SUCCESS)
24091708Sstevel 		return (err);
24101708Sstevel 
24111708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_UPA,
24121708Sstevel 	    PICL_CLASS_UPA, upa_callback);
24131708Sstevel 
24141708Sstevel 	return (err);
24151708Sstevel }
24161708Sstevel 
24171708Sstevel static void
picldiag_display_io_cards(struct io_card * list)24181708Sstevel picldiag_display_io_cards(struct io_card *list)
24191708Sstevel {
24201708Sstevel 	static int banner = 0; /* Have we printed the column headings? */
24211708Sstevel 	struct io_card *p;
24221708Sstevel 
24231708Sstevel 	if (list == NULL)
24241708Sstevel 		return;
24251708Sstevel 
24261708Sstevel 	if (banner == 0) {
24271708Sstevel 		log_printf("Bus     Freq  Slot +      Name +\n", 0);
24281708Sstevel 		log_printf("Type    MHz   Status      Path"
2429*13019SMichael.Bergknoff@Oracle.COM 		    "                          Model", 0);
24301708Sstevel 		log_printf("\n", 0);
24311708Sstevel 		log_printf("------  ----  ----------  "
2432*13019SMichael.Bergknoff@Oracle.COM 		    "----------------------------  "
2433*13019SMichael.Bergknoff@Oracle.COM 		    "--------------------", 0);
24341708Sstevel 		log_printf("\n", 0);
24351708Sstevel 		banner = 1;
24361708Sstevel 	}
24371708Sstevel 
24381708Sstevel 	for (p = list; p != NULL; p = p -> next) {
24391708Sstevel 		log_printf("%-6s  ", p->bus_type, 0);
24401708Sstevel 		log_printf("%-3d   ", p->freq, 0);
24411708Sstevel 		/*
24421708Sstevel 		 * We check to see if it's an int or
24431708Sstevel 		 * a char string to display for slot.
24441708Sstevel 		 */
24451708Sstevel 		if (p->slot == PCI_SLOT_IS_STRING)
24461708Sstevel 			log_printf("%-10s  ", p->slot_str, 0);
24471708Sstevel 		else
24481708Sstevel 			log_printf("%-10d  ", p->slot, 0);
24491708Sstevel 
24501708Sstevel 		log_printf("%-28.28s", p->name, 0);
24511708Sstevel 		if (strlen(p->name) > 28)
24521708Sstevel 			log_printf("+ ", 0);
24531708Sstevel 		else
24541708Sstevel 			log_printf("  ", 0);
24551708Sstevel 		log_printf("%-19.19s", p->model, 0);
24561708Sstevel 		if (strlen(p->model) > 19)
24571708Sstevel 			log_printf("+", 0);
24581708Sstevel 		log_printf("\n", 0);
24591708Sstevel 		log_printf("              %-10s  ", p->status, 0);
24601708Sstevel 		set_exit_code(p->status);
24611708Sstevel 		if (strlen(p->notes) > 0)
24621708Sstevel 			log_printf("%s", p->notes, 0);
24631708Sstevel 		log_printf("\n\n", 0);
24641708Sstevel 	}
24651708Sstevel }
24661708Sstevel 
24671708Sstevel /*
24681708Sstevel  * display all io devices
24691708Sstevel  */
24701708Sstevel static int
display_io_device_info(picl_nodehdl_t plafh)24711708Sstevel display_io_device_info(picl_nodehdl_t plafh)
24721708Sstevel {
24731708Sstevel 	int	err;
24741708Sstevel 
24751708Sstevel 	err = gather_io_cards(plafh);
24761708Sstevel 	if (err != PICL_SUCCESS)
24771708Sstevel 		return (err);
24781708Sstevel 
24791708Sstevel 	logprintf_header(dgettext(TEXT_DOMAIN, "IO Devices"),
24801708Sstevel 	    DEFAULT_LINE_WIDTH);
24811708Sstevel 
24821708Sstevel 	picldiag_display_io_cards(io_card_list);
24831708Sstevel 
24841708Sstevel 	free_io_cards(io_card_list);
24851708Sstevel 
24861708Sstevel 	return (PICL_SUCCESS);
24871708Sstevel }
24881708Sstevel 
24891708Sstevel /*
24901708Sstevel  * print fan device information
24911708Sstevel  */
24921708Sstevel static int
logprintf_fan_info(picl_nodehdl_t fanh)24931708Sstevel logprintf_fan_info(picl_nodehdl_t fanh)
24941708Sstevel {
24951708Sstevel 	int		err;
24961708Sstevel 	char		*label;
24971708Sstevel 	char		*unit;
24981708Sstevel 	int64_t		speed;
24991708Sstevel 	int64_t		min_speed;
25001708Sstevel 	picl_nodehdl_t	fruph;
25011708Sstevel 
25021708Sstevel 	err = picldiag_get_fru_parent(fanh, &fruph);
25031708Sstevel 	if (err != PICL_SUCCESS)
25041708Sstevel 		return (err);
25051708Sstevel 
25061708Sstevel 	err = picldiag_get_combined_label(fruph, &label, 20);
25071708Sstevel 	if (err != PICL_SUCCESS)
25081708Sstevel 		return (err);
25091708Sstevel 
25101708Sstevel 	log_printf("%-20s ", label);
25111708Sstevel 	free(label);
25121708Sstevel 
25131708Sstevel 	err = picldiag_get_label(fanh, &label);
25141708Sstevel 	if (err == PICL_SUCCESS) {
25151708Sstevel 		log_printf("%-14s  ", label);
25161708Sstevel 		free(label);
25171708Sstevel 	} else if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
25181708Sstevel 		log_printf("  -           ");
25191708Sstevel 	} else
25201708Sstevel 		return (err);
25211708Sstevel 
25221708Sstevel 	speed = picldiag_get_uint_propval(fanh, PICL_PROP_FAN_SPEED, &err);
25231708Sstevel 	if (err == PICL_SUCCESS) {
25241708Sstevel 		min_speed = picldiag_get_uint_propval(fanh,
25251708Sstevel 		    PICL_PROP_LOW_WARNING_THRESHOLD, &err);
25261708Sstevel 		if (err != PICL_SUCCESS)
25271708Sstevel 			min_speed = 0;
25282606Svenki 
25291708Sstevel 		if (speed < min_speed) {
25301708Sstevel 			log_printf("failed (%lld", speed);
25311708Sstevel 			err = picldiag_get_string_propval(fanh,
25321708Sstevel 			    PICL_PROP_FAN_SPEED_UNIT, &unit);
25331708Sstevel 			if (err == PICL_SUCCESS) {
25341708Sstevel 				log_printf("%s", unit);
25351708Sstevel 				free(unit);
25361708Sstevel 			}
25371708Sstevel 			log_printf(")");
25381708Sstevel 			exit_code = PD_SYSTEM_FAILURE;
25391708Sstevel 		} else {
25401708Sstevel 			log_printf("okay");
25411708Sstevel 		}
25421708Sstevel 	} else {
25431708Sstevel 		err = picldiag_get_string_propval(fanh,
25441708Sstevel 		    PICL_PROP_FAN_SPEED_UNIT, &unit);
25451708Sstevel 		if (err == PICL_SUCCESS) {
25461708Sstevel 			log_printf("%-12s ", unit);
25471708Sstevel 			free(unit);
25481708Sstevel 		}
25491708Sstevel 	}
25501708Sstevel 
25511708Sstevel 	log_printf("\n");
25521708Sstevel 	return (PICL_SUCCESS);
25531708Sstevel }
25541708Sstevel 
25551708Sstevel static int
fan_callback(picl_nodehdl_t fanh,void * arg)25561708Sstevel fan_callback(picl_nodehdl_t fanh, void *arg)
25571708Sstevel {
25581708Sstevel 	int	*countp = arg;
25591708Sstevel 
25601708Sstevel 	if (*countp == 0) {
25611708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Fan Status:\n"));
25621708Sstevel 		log_printf("-------------------------------------------\n");
25631708Sstevel 		log_printf("Location             Sensor          Status\n");
25641708Sstevel 		log_printf("-------------------------------------------\n");
25651708Sstevel 	}
25661708Sstevel 	*countp += 1;
25672606Svenki 
25682606Svenki 	(void) logprintf_fan_info(fanh);
25692606Svenki 
25702606Svenki 	return (PICL_WALK_CONTINUE);
25711708Sstevel }
25721708Sstevel 
25731708Sstevel /*
25741708Sstevel  * callback function search children to find fan device and print its speed
25751708Sstevel  */
25761708Sstevel static int
display_fan_speed(picl_nodehdl_t plafh)25771708Sstevel display_fan_speed(picl_nodehdl_t plafh)
25781708Sstevel {
25791708Sstevel 	int		err;
25801708Sstevel 	int		print_header;
25811708Sstevel 
25821708Sstevel 	print_header = 0;
25831708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_FAN,
25841708Sstevel 	    &print_header, fan_callback);
25851708Sstevel 	return (err);
25861708Sstevel }
25871708Sstevel 
25881708Sstevel /*
25891708Sstevel  * print temperature sensor information
25901708Sstevel  */
25911708Sstevel static int
logprintf_temp_info(picl_nodehdl_t temph)25921708Sstevel logprintf_temp_info(picl_nodehdl_t temph)
25931708Sstevel {
25941708Sstevel 	int		err;
25951708Sstevel 	char		*label;
25961708Sstevel 	int64_t		temperature;
25971708Sstevel 	int64_t		threshold;
25981708Sstevel 	picl_nodehdl_t	fruph;
25991708Sstevel 	char		*status = "unknown";
26001708Sstevel 	int		got_temp = 0;
26011708Sstevel 
26021708Sstevel 	err = picldiag_get_fru_parent(temph, &fruph);
26031708Sstevel 	if (err != PICL_SUCCESS)
26041708Sstevel 		return (err);
26051708Sstevel 
26061708Sstevel 	err = picldiag_get_combined_label(fruph, &label, 14);
26071708Sstevel 	if (err != PICL_SUCCESS)
26081708Sstevel 		return (err);
26091708Sstevel 
26101708Sstevel 	log_printf("%-14s ", label);
26111708Sstevel 	free(label);
26121708Sstevel 
26131708Sstevel 	err = picldiag_get_label(temph, &label);
26141708Sstevel 	if (err != PICL_SUCCESS)
26151708Sstevel 		return (err);
26161708Sstevel 	log_printf("%-19s ", label);
26171708Sstevel 	free(label);
26181708Sstevel 
26191708Sstevel 	temperature = picldiag_get_int_propval(temph, PICL_PROP_TEMPERATURE,
26201708Sstevel 	    &err);
26211708Sstevel 	if (err == PICL_SUCCESS) {
26221708Sstevel 		got_temp = 1;
26231708Sstevel 		status = "okay";
26241708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
26251708Sstevel 		return (err);
26261708Sstevel 	}
26271708Sstevel 
26281708Sstevel 	threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_WARNING,
26291708Sstevel 	    &err);
26301708Sstevel 	if (err == PICL_SUCCESS) {
26311708Sstevel 		if (got_temp && temperature < threshold)
26321708Sstevel 			status = "warning";
26331708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
26341708Sstevel 		return (err);
26351708Sstevel 	}
26361708Sstevel 
26371708Sstevel 	threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_SHUTDOWN,
26381708Sstevel 	    &err);
26391708Sstevel 	if (err == PICL_SUCCESS) {
26401708Sstevel 		if (got_temp && temperature < threshold)
26411708Sstevel 			status = "failed";
26421708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
26431708Sstevel 		return (err);
26441708Sstevel 	}
26451708Sstevel 
26461708Sstevel 	threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_WARNING,
26471708Sstevel 	    &err);
26481708Sstevel 	if (err == PICL_SUCCESS) {
26491708Sstevel 		if (got_temp && temperature > threshold)
26501708Sstevel 			status = "warning";
26511708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
26521708Sstevel 		return (err);
26531708Sstevel 	}
26541708Sstevel 
26551708Sstevel 	threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_SHUTDOWN,
26561708Sstevel 	    &err);
26571708Sstevel 	if (err == PICL_SUCCESS) {
26581708Sstevel 		if (got_temp && temperature > threshold)
26591708Sstevel 			status = "failed";
26601708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
26611708Sstevel 		return (err);
26621708Sstevel 	}
26631708Sstevel 
26641708Sstevel 	err = picldiag_get_string_propval(temph, PICL_PROP_CONDITION, &status);
26651708Sstevel 	if (err == PICL_SUCCESS) {
26661708Sstevel 		log_printf("%s", status);
26671708Sstevel 		set_exit_code(status);
26681708Sstevel 		free(status);
26691708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
26701708Sstevel 		return (err);
26711708Sstevel 	} else {
26721708Sstevel 		log_printf("%s ", status);
26731708Sstevel 		set_exit_code(status);
26741708Sstevel 		if (strcmp(status, "failed") == 0 ||
26751708Sstevel 		    strcmp(status, "warning") == 0)
26761708Sstevel 			log_printf("(%.2lldC)", temperature);
26771708Sstevel 	}
26781708Sstevel 
26791708Sstevel 	log_printf("\n");
26801708Sstevel 	return (PICL_SUCCESS);
26811708Sstevel }
26821708Sstevel 
26831708Sstevel static int
temp_callback(picl_nodehdl_t temph,void * arg)26841708Sstevel temp_callback(picl_nodehdl_t temph, void *arg)
26851708Sstevel {
26861708Sstevel 	int		err;
26871708Sstevel 	int	*countp = arg;
26881708Sstevel 
26891708Sstevel 	if (*countp == 0) {
26901708Sstevel 		log_printf("\n");
26911708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Temperature sensors:\n"));
26921708Sstevel 		log_printf("-----------------------------------------\n");
26931708Sstevel 		log_printf("Location       Sensor              Status\n");
26941708Sstevel 		log_printf("-----------------------------------------\n");
26951708Sstevel 	}
26961708Sstevel 	*countp += 1;
26971708Sstevel 	err = logprintf_temp_info(temph);
26981708Sstevel 	if (err == PICL_SUCCESS)
26991708Sstevel 		return (PICL_WALK_CONTINUE);
27001708Sstevel 	return (err);
27011708Sstevel }
27021708Sstevel 
27031708Sstevel /*
27041708Sstevel  * callback function search children to find temp sensors and print the temp
27051708Sstevel  */
27061708Sstevel /* ARGSUSED */
27071708Sstevel static int
display_temp(picl_nodehdl_t plafh)27081708Sstevel display_temp(picl_nodehdl_t plafh)
27091708Sstevel {
27101708Sstevel 	int		err;
27111708Sstevel 	int		print_header;
27121708Sstevel 
27131708Sstevel 	print_header = 0;
27141708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_SENSOR,
27151708Sstevel 	    &print_header, temp_callback);
27161708Sstevel 	if (err != PICL_SUCCESS)
27171708Sstevel 		return (err);
27181708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_INDICATOR,
27191708Sstevel 	    &print_header, temp_callback);
27201708Sstevel 	return (err);
27211708Sstevel }
27221708Sstevel 
27231708Sstevel /*
27241708Sstevel  * print current sensor information
27251708Sstevel  */
27261708Sstevel static int
logprintf_current_info(picl_nodehdl_t currenth)27271708Sstevel logprintf_current_info(picl_nodehdl_t currenth)
27281708Sstevel {
27291708Sstevel 	int		err;
27301708Sstevel 	char		*label;
27311708Sstevel 	float		current;
27321708Sstevel 	float		threshold;
27331708Sstevel 	picl_nodehdl_t	fruph;
27341708Sstevel 	char		*status = "unknown";
27351708Sstevel 	int		got_current = 0;
27361708Sstevel 
27371708Sstevel 	err = picldiag_get_fru_parent(currenth, &fruph);
27381708Sstevel 	if (err != PICL_SUCCESS)
27391708Sstevel 		return (err);
27401708Sstevel 
27411708Sstevel 	err = picldiag_get_combined_label(fruph, &label, 20);
27421708Sstevel 	if (err != PICL_SUCCESS)
27431708Sstevel 		return (err);
27441708Sstevel 
27451708Sstevel 	log_printf("%-20s ", label);
27461708Sstevel 	free(label);
27471708Sstevel 
27481708Sstevel 	err = picldiag_get_label(currenth, &label);
27491708Sstevel 	if (err != PICL_SUCCESS)
27501708Sstevel 		return (err);
27511708Sstevel 	log_printf("%-10s  ", label);
27521708Sstevel 	free(label);
27531708Sstevel 
27541708Sstevel 	current = picldiag_get_float_propval(currenth, PICL_PROP_CURRENT, &err);
27551708Sstevel 	if (err == PICL_SUCCESS) {
27561708Sstevel 		status = "okay";
27571708Sstevel 		got_current = 1;
27581708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
27591708Sstevel 		return (err);
27601708Sstevel 	}
27611708Sstevel 
27621708Sstevel 	threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_WARNING,
27631708Sstevel 	    &err);
27641708Sstevel 	if (err == PICL_SUCCESS) {
27651708Sstevel 		if (got_current && current < threshold)
27661708Sstevel 			status = "warning";
27671708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
27681708Sstevel 		return (err);
27691708Sstevel 	}
27701708Sstevel 
27711708Sstevel 	threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_SHUTDOWN,
27721708Sstevel 	    &err);
27731708Sstevel 	if (err == PICL_SUCCESS) {
27741708Sstevel 		if (got_current && current < threshold)
27751708Sstevel 			status = "failed";
27761708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
27771708Sstevel 		return (err);
27781708Sstevel 	}
27791708Sstevel 
27801708Sstevel 	threshold = picldiag_get_float_propval(currenth, PICL_PROP_HIGH_WARNING,
27811708Sstevel 	    &err);
27821708Sstevel 	if (err == PICL_SUCCESS) {
27831708Sstevel 		if (got_current && current > threshold)
27841708Sstevel 			status = "warning";
27851708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
27861708Sstevel 		return (err);
27871708Sstevel 	}
27881708Sstevel 
27891708Sstevel 	threshold = picldiag_get_float_propval(currenth,
27901708Sstevel 	    PICL_PROP_HIGH_SHUTDOWN, &err);
27911708Sstevel 	if (err == PICL_SUCCESS) {
27921708Sstevel 		if (got_current && current > threshold)
27931708Sstevel 			status = "failed";
27941708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
27951708Sstevel 		return (err);
27961708Sstevel 	}
27971708Sstevel 
27981708Sstevel 	err = picldiag_get_string_propval(currenth,
27991708Sstevel 	    PICL_PROP_CONDITION, &status);
28001708Sstevel 	if (err == PICL_SUCCESS) {
28011708Sstevel 		log_printf(" %s", status);
28021708Sstevel 		set_exit_code(status);
28031708Sstevel 		free(status);
28041708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
28051708Sstevel 		return (err);
28061708Sstevel 	} else {
28071708Sstevel 		log_printf("%s ", status);
28081708Sstevel 		set_exit_code(status);
28091708Sstevel 		if (strcmp(status, "failed") == 0 ||
28101708Sstevel 		    strcmp(status, "warning") == 0)
28111708Sstevel 			log_printf("(%.2fA)", current);
28121708Sstevel 	}
28131708Sstevel 
28141708Sstevel 	log_printf("\n");
28151708Sstevel 	return (PICL_SUCCESS);
28161708Sstevel }
28171708Sstevel 
28181708Sstevel static int
current_callback(picl_nodehdl_t currh,void * arg)28191708Sstevel current_callback(picl_nodehdl_t currh, void *arg)
28201708Sstevel {
28211708Sstevel 	int		err;
28221708Sstevel 	int	*countp = arg;
28231708Sstevel 
28241708Sstevel 	if (*countp == 0) {
28251708Sstevel 		log_printf("------------------------------------\n");
28261708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Current sensors:\n"));
28271708Sstevel 		log_printf("----------------------------------------\n");
28281708Sstevel 		log_printf("Location             Sensor       Status\n");
28291708Sstevel 		log_printf("----------------------------------------\n");
28301708Sstevel 	}
28311708Sstevel 	*countp += 1;
28321708Sstevel 	err = logprintf_current_info(currh);
28331708Sstevel 	if (err == PICL_SUCCESS)
28341708Sstevel 		return (PICL_WALK_CONTINUE);
28351708Sstevel 	return (err);
28361708Sstevel }
28371708Sstevel 
28381708Sstevel /*
28391708Sstevel  * callback function search children to find curr sensors and print the curr
28401708Sstevel  */
28411708Sstevel /* ARGSUSED */
28421708Sstevel static int
display_current(picl_nodehdl_t plafh)28431708Sstevel display_current(picl_nodehdl_t plafh)
28441708Sstevel {
28451708Sstevel 	int		err;
28461708Sstevel 	int		print_header;
28471708Sstevel 
28481708Sstevel 	print_header = 0;
28491708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_SENSOR,
28501708Sstevel 	    &print_header, current_callback);
28511708Sstevel 	if (err != PICL_SUCCESS)
28521708Sstevel 		return (err);
28531708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_INDICATOR,
28541708Sstevel 	    &print_header, current_callback);
28551708Sstevel 	return (err);
28561708Sstevel }
28571708Sstevel 
28581708Sstevel /*
28591708Sstevel  * print voltage sensor information
28601708Sstevel  */
28611708Sstevel static int
logprintf_voltage_info(picl_nodehdl_t voltageh)28621708Sstevel logprintf_voltage_info(picl_nodehdl_t voltageh)
28631708Sstevel {
28641708Sstevel 	int		err;
28651708Sstevel 	char		*label;
28661708Sstevel 	float		voltage;
28671708Sstevel 	float		threshold;
28681708Sstevel 	picl_nodehdl_t	fruph;
28691708Sstevel 	char		*status = "unknown";
28701708Sstevel 	int		got_voltage = 0;
28711708Sstevel 
28721708Sstevel 	err = picldiag_get_fru_parent(voltageh, &fruph);
28731708Sstevel 	if (err != PICL_SUCCESS)
28741708Sstevel 		return (err);
28751708Sstevel 
28761708Sstevel 	err = picldiag_get_combined_label(fruph, &label, 14);
28771708Sstevel 	if (err != PICL_SUCCESS)
28781708Sstevel 		return (err);
28791708Sstevel 
28801708Sstevel 	log_printf("%-14s ", label);
28811708Sstevel 	free(label);
28821708Sstevel 
28831708Sstevel 	err = picldiag_get_label(voltageh, &label);
28841708Sstevel 	if (err != PICL_SUCCESS)
28851708Sstevel 		return (err);
28861708Sstevel 	log_printf("%-12s  ", label);
28871708Sstevel 	free(label);
28881708Sstevel 
28891708Sstevel 	voltage = picldiag_get_float_propval(voltageh, PICL_PROP_VOLTAGE, &err);
28901708Sstevel 	if (err == PICL_SUCCESS) {
28911708Sstevel 		status = "okay";
28921708Sstevel 		got_voltage = 1;
28931708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
28941708Sstevel 		return (err);
28951708Sstevel 	}
28961708Sstevel 
28971708Sstevel 	threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_WARNING,
28981708Sstevel 	    &err);
28991708Sstevel 	if (err == PICL_SUCCESS) {
29001708Sstevel 		if (got_voltage && voltage < threshold)
29011708Sstevel 			status = "warning";
29021708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
29031708Sstevel 		return (err);
29041708Sstevel 	}
29051708Sstevel 
29061708Sstevel 	threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_SHUTDOWN,
29071708Sstevel 	    &err);
29081708Sstevel 	if (err == PICL_SUCCESS) {
29091708Sstevel 		if (got_voltage && voltage < threshold)
29101708Sstevel 			status = "failed";
29111708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
29121708Sstevel 		return (err);
29131708Sstevel 	}
29141708Sstevel 
29151708Sstevel 	threshold = picldiag_get_float_propval(voltageh, PICL_PROP_HIGH_WARNING,
29161708Sstevel 	    &err);
29171708Sstevel 	if (err == PICL_SUCCESS) {
29181708Sstevel 		if (got_voltage && voltage > threshold)
29191708Sstevel 			status = "warning";
29201708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
29211708Sstevel 		return (err);
29221708Sstevel 	}
29231708Sstevel 
29241708Sstevel 	threshold = picldiag_get_float_propval(voltageh,
29251708Sstevel 	    PICL_PROP_HIGH_SHUTDOWN, &err);
29261708Sstevel 	if (err == PICL_SUCCESS) {
29271708Sstevel 		if (got_voltage && voltage > threshold)
29281708Sstevel 			status = "failed";
29291708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
29301708Sstevel 		return (err);
29311708Sstevel 	}
29321708Sstevel 
29331708Sstevel 	err = picldiag_get_string_propval(voltageh,
29341708Sstevel 	    PICL_PROP_CONDITION, &status);
29351708Sstevel 	if (err == PICL_SUCCESS) {
29361708Sstevel 		log_printf("%s", status);
29371708Sstevel 		set_exit_code(status);
29381708Sstevel 		free(status);
29391708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
29401708Sstevel 		return (err);
29411708Sstevel 	} else {
29421708Sstevel 		log_printf("%s ", status);
29431708Sstevel 		set_exit_code(status);
29441708Sstevel 		if (strcmp(status, "warning") == 0 ||
29451708Sstevel 		    strcmp(status, "failed") == 0)
29461708Sstevel 			log_printf("(%.2fV)", voltage);
29471708Sstevel 	}
29481708Sstevel 
29491708Sstevel 	log_printf("\n");
29501708Sstevel 	return (PICL_SUCCESS);
29511708Sstevel }
29521708Sstevel 
29531708Sstevel static int
voltage_callback(picl_nodehdl_t voltageh,void * arg)29541708Sstevel voltage_callback(picl_nodehdl_t voltageh, void *arg)
29551708Sstevel {
29561708Sstevel 	int	*countp = arg;
29571708Sstevel 	int		err;
29581708Sstevel 
29591708Sstevel 	if (*countp == 0) {
29601708Sstevel 		log_printf("------------------------------------\n");
29611708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Voltage sensors:\n"));
29621708Sstevel 		log_printf("-----------------------------------\n");
29631708Sstevel 		log_printf("Location       Sensor        Status\n");
29641708Sstevel 		log_printf("-----------------------------------\n");
29651708Sstevel 	}
29661708Sstevel 	*countp += 1;
29671708Sstevel 	err = logprintf_voltage_info(voltageh);
29681708Sstevel 	if (err == PICL_SUCCESS)
29691708Sstevel 		return (PICL_WALK_CONTINUE);
29701708Sstevel 	return (err);
29711708Sstevel }
29721708Sstevel 
29731708Sstevel /*
29741708Sstevel  * callback function search children to find voltage sensors and print voltage
29751708Sstevel  */
29761708Sstevel /* ARGSUSED */
29771708Sstevel static int
display_voltage(picl_nodehdl_t plafh)29781708Sstevel display_voltage(picl_nodehdl_t plafh)
29791708Sstevel {
29801708Sstevel 	int		err;
29811708Sstevel 	int		print_header;
29821708Sstevel 
29831708Sstevel 	print_header = 0;
29841708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_SENSOR,
29851708Sstevel 	    &print_header, voltage_callback);
29861708Sstevel 	if (err != PICL_SUCCESS)
29871708Sstevel 		return (err);
29881708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_INDICATOR,
29891708Sstevel 	    &print_header, voltage_callback);
29901708Sstevel 	return (err);
29911708Sstevel }
29921708Sstevel 
29931708Sstevel /*
29941708Sstevel  * print led device information
29951708Sstevel  */
29961708Sstevel static int
logprintf_led_info(picl_nodehdl_t ledh)29971708Sstevel logprintf_led_info(picl_nodehdl_t ledh)
29981708Sstevel {
29991708Sstevel 	int		err;
30001708Sstevel 	char		*label;
30011708Sstevel 	char		*state;
30021708Sstevel 	char		*color;
30031708Sstevel 	picl_nodehdl_t  fruph;
30041708Sstevel 
30051708Sstevel 	err = picldiag_get_fru_parent(ledh, &fruph);
30061708Sstevel 	if (err != PICL_SUCCESS)
30071708Sstevel 		return (err);
30081708Sstevel 
30091708Sstevel 	err = picldiag_get_combined_label(fruph, &label, 22);
30101708Sstevel 	if (err != PICL_SUCCESS) {
30111708Sstevel 		log_printf("           -         ", label);
30121708Sstevel 	} else {
30131708Sstevel 		log_printf("%-22s ", label);
30141708Sstevel 		free(label);
30151708Sstevel 	}
30161708Sstevel 
30171708Sstevel 	err = picldiag_get_label(ledh, &label);
30181708Sstevel 	if (err != PICL_SUCCESS)
30191708Sstevel 		return (err);
30201708Sstevel 	log_printf("%-20s  ", label);
30211708Sstevel 	free(label);
30221708Sstevel 
30231708Sstevel 	err = picldiag_get_string_propval(ledh, PICL_PROP_STATE, &state);
30241708Sstevel 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
30251708Sstevel 		log_printf("     -     ");
30261708Sstevel 	} else if (err != PICL_SUCCESS) {
30271708Sstevel 		return (err);
30281708Sstevel 	} else {
30291708Sstevel 		log_printf("%-10s  ", state);
30301708Sstevel 		free(state);
30311708Sstevel 	}
30321708Sstevel 
30331708Sstevel 	err = picldiag_get_string_propval(ledh, PICL_PROP_COLOR, &color);
30341708Sstevel 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
30351708Sstevel 		log_printf("\n");
30361708Sstevel 	} else if (err != PICL_SUCCESS) {
30371708Sstevel 		return (err);
30381708Sstevel 	} else {
30391708Sstevel 		log_printf("%-16s\n", color);
30401708Sstevel 		free(color);
30411708Sstevel 	}
30421708Sstevel 
30431708Sstevel 	return (PICL_SUCCESS);
30441708Sstevel }
30451708Sstevel 
30461708Sstevel static int
led_callback(picl_nodehdl_t ledh,void * arg)30471708Sstevel led_callback(picl_nodehdl_t ledh, void *arg)
30481708Sstevel {
30491708Sstevel 	int		*countp = arg;
30501708Sstevel 	int		err;
30511708Sstevel 
30521708Sstevel 	if (*countp == 0) {
30531708Sstevel 
30541708Sstevel 		log_printf("--------------------------------------"
30551708Sstevel 		    "------------\n");
30561708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Led State:\n"));
30571708Sstevel 		log_printf("----------------------------------------"
30581708Sstevel 		    "----------------------\n");
30591708Sstevel 		log_printf("Location               Led                   State"
30601708Sstevel 		    "       Color\n");
30611708Sstevel 		log_printf("----------------------------------------"
30621708Sstevel 		    "----------------------\n");
30631708Sstevel 	}
30641708Sstevel 	*countp += 1;
30651708Sstevel 	err = logprintf_led_info(ledh);
30661708Sstevel 	if (err == PICL_SUCCESS)
30671708Sstevel 		return (PICL_WALK_CONTINUE);
30681708Sstevel 	return (err);
30691708Sstevel }
30701708Sstevel 
30711708Sstevel /*
30721708Sstevel  * callback function search children to find led devices and print status
30731708Sstevel  */
30741708Sstevel /* ARGSUSED */
30751708Sstevel static int
display_led_status(picl_nodehdl_t plafh)30761708Sstevel display_led_status(picl_nodehdl_t plafh)
30771708Sstevel {
30781708Sstevel 	int		print_header;
30791708Sstevel 
30801708Sstevel 	print_header = 0;
30811708Sstevel 	picl_walk_tree_by_class(plafh, PICL_CLASS_LED,
30821708Sstevel 	    &print_header, led_callback);
30831708Sstevel 	return (PICL_SUCCESS);
30841708Sstevel }
30851708Sstevel 
30861708Sstevel /*
30871708Sstevel  * print keyswitch device information
30881708Sstevel  */
30891708Sstevel static int
logprintf_keyswitch_info(picl_nodehdl_t keyswitchh,picl_nodehdl_t fruph)30901708Sstevel logprintf_keyswitch_info(picl_nodehdl_t keyswitchh, picl_nodehdl_t fruph)
30911708Sstevel {
30921708Sstevel 	int		err;
30931708Sstevel 	char		*label;
30941708Sstevel 	char		*state;
30951708Sstevel 
30961708Sstevel 	err = picldiag_get_combined_label(fruph, &label, 10);
30971708Sstevel 	if (err != PICL_SUCCESS) {
30981708Sstevel 		log_printf("%-14s", "     -");
30991708Sstevel 	} else {
31001708Sstevel 		log_printf("%-14s ", label);
31011708Sstevel 		free(label);
31021708Sstevel 	}
31031708Sstevel 
31041708Sstevel 	err = picldiag_get_label(keyswitchh, &label);
31051708Sstevel 	if (err != PICL_SUCCESS)
31061708Sstevel 		return (err);
31071708Sstevel 	log_printf("%-11s ", label);
31081708Sstevel 	free(label);
31091708Sstevel 
31101708Sstevel 	err = picldiag_get_string_propval(keyswitchh, PICL_PROP_STATE, &state);
31111708Sstevel 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
31121708Sstevel 		log_printf("     -\n");
31131708Sstevel 	} else if (err != PICL_SUCCESS) {
31141708Sstevel 		return (err);
31151708Sstevel 	} else {
31161708Sstevel 		log_printf("%s\n", state);
31171708Sstevel 		free(state);
31181708Sstevel 	}
31191708Sstevel 
31201708Sstevel 	return (PICL_SUCCESS);
31211708Sstevel }
31221708Sstevel 
31231708Sstevel static int
keyswitch_callback(picl_nodehdl_t keyswitchh,void * arg)31241708Sstevel keyswitch_callback(picl_nodehdl_t keyswitchh, void *arg)
31251708Sstevel {
31261708Sstevel 	int		*countp = arg;
31271708Sstevel 	int		err;
31281708Sstevel 	picl_nodehdl_t	fruph;
31291708Sstevel 
31301708Sstevel 	/*
31311708Sstevel 	 * Tamale simulates a key-switch on ENxS. So the presence of a
31321708Sstevel 	 * node of class keyswitch is not sufficient. If it has a fru parent
31331708Sstevel 	 * or location parent, then believe it.
31341708Sstevel 	 */
31351708Sstevel 	err = picl_get_propval_by_name(keyswitchh, PICL_REFPROP_FRU_PARENT,
31361708Sstevel 	    &fruph, sizeof (fruph));
31371708Sstevel 	if (err == PICL_PROPNOTFOUND) {
31381708Sstevel 		err = picl_get_propval_by_name(keyswitchh,
31391708Sstevel 		    PICL_REFPROP_LOC_PARENT, &fruph, sizeof (fruph));
31401708Sstevel 	}
31411708Sstevel 	if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE)
31421708Sstevel 		return (PICL_WALK_CONTINUE);
31431708Sstevel 	if (err != PICL_SUCCESS)
31441708Sstevel 		return (err);
31451708Sstevel 
31461708Sstevel 	if (*countp == 0) {
31471708Sstevel 		log_printf("-----------------------------------------\n");
31481708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "Keyswitch:\n"));
31491708Sstevel 		log_printf("-----------------------------------------\n");
31501708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
31511708Sstevel 		    "Location       Keyswitch   State\n"));
31521708Sstevel 		log_printf("-----------------------------------------\n");
31531708Sstevel 	}
31541708Sstevel 	*countp += 1;
31551708Sstevel 	err = logprintf_keyswitch_info(keyswitchh, fruph);
31561708Sstevel 	if (err == PICL_SUCCESS)
31571708Sstevel 		return (PICL_WALK_CONTINUE);
31581708Sstevel 	return (err);
31591708Sstevel }
31601708Sstevel 
31611708Sstevel /*
31621708Sstevel  * search children to find keyswitch device(s) and print status
31631708Sstevel  */
31641708Sstevel /* ARGSUSED */
31651708Sstevel static int
display_keyswitch(picl_nodehdl_t plafh)31661708Sstevel display_keyswitch(picl_nodehdl_t plafh)
31671708Sstevel {
31681708Sstevel 	int		print_header = 0;
31691708Sstevel 
31701708Sstevel 	picl_walk_tree_by_class(plafh, PICL_CLASS_KEYSWITCH,
31711708Sstevel 	    &print_header, keyswitch_callback);
31721708Sstevel 	return (PICL_SUCCESS);
31731708Sstevel }
31741708Sstevel 
31751708Sstevel /*
31761708Sstevel  * display environment status
31771708Sstevel  */
31781708Sstevel static int
display_envctrl_status(picl_nodehdl_t plafh)31791708Sstevel display_envctrl_status(picl_nodehdl_t plafh)
31801708Sstevel {
31811708Sstevel 	logprintf_header(dgettext(TEXT_DOMAIN, "Environmental Status"),
31821708Sstevel 	    DEFAULT_LINE_WIDTH);
31831708Sstevel 
31841708Sstevel 	display_fan_speed(plafh);
31851708Sstevel 	display_temp(plafh);
31861708Sstevel 	display_current(plafh);
31871708Sstevel 	display_voltage(plafh);
31881708Sstevel 	display_keyswitch(plafh);
31891708Sstevel 	display_led_status(plafh);
31901708Sstevel 
31911708Sstevel 	return (PICL_SUCCESS);
31921708Sstevel }
31931708Sstevel 
31941708Sstevel /*
31951708Sstevel  * print fru operational status
31961708Sstevel  */
31971708Sstevel static int
logprintf_fru_oper_status(picl_nodehdl_t fruh,int * countp)31981708Sstevel logprintf_fru_oper_status(picl_nodehdl_t fruh, int *countp)
31991708Sstevel {
32001708Sstevel 	int		err;
32011708Sstevel 	char		*label;
32021708Sstevel 	char		*status;
32031708Sstevel 
32041708Sstevel 	err = picldiag_get_combined_label(fruh, &label, 23);
32051708Sstevel 	if (err != PICL_SUCCESS)
32061708Sstevel 		return (PICL_WALK_CONTINUE);
32071708Sstevel 
32081708Sstevel 	err = picldiag_get_string_propval(fruh,
32091708Sstevel 	    PICL_PROP_OPERATIONAL_STATUS, &status);
32101708Sstevel 	if (err == PICL_SUCCESS) {
32111708Sstevel 		if (*countp == 0) {
32121708Sstevel 			logprintf_header(dgettext(TEXT_DOMAIN,
32131708Sstevel 			    "FRU Operational Status"),
32141708Sstevel 			    DEFAULT_LINE_WIDTH);
32151708Sstevel 			log_printf("---------------------------------\n");
32161708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
32171708Sstevel 			    "Fru Operational Status:\n"));
32181708Sstevel 			log_printf("---------------------------------\n");
32191708Sstevel 			log_printf("Location                Status\n");
32201708Sstevel 			log_printf("---------------------------------\n");
32211708Sstevel 		}
32221708Sstevel 		*countp += 1;
32231708Sstevel 		log_printf("%-23s ", label);
32241708Sstevel 		free(label);
32251708Sstevel 		log_printf("%s\n", status);
32261708Sstevel 		set_exit_code(status);
32271708Sstevel 		free(status);
32281708Sstevel 	} else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
32291708Sstevel 		free(label);
32301708Sstevel 		return (err);
32311708Sstevel 	} else {
32321708Sstevel 		free(label);
32331708Sstevel 	}
32341708Sstevel 	return (PICL_WALK_CONTINUE);
32351708Sstevel }
32361708Sstevel 
32371708Sstevel static int
fru_oper_status_callback(picl_nodehdl_t fruh,void * arg)32381708Sstevel fru_oper_status_callback(picl_nodehdl_t fruh, void *arg)
32391708Sstevel {
32401708Sstevel 	int err;
32411708Sstevel 
32421708Sstevel 	err = logprintf_fru_oper_status(fruh, (int *)arg);
32431708Sstevel 	return (err);
32441708Sstevel }
32451708Sstevel 
32461708Sstevel /*
32471708Sstevel  * display fru operational status
32481708Sstevel  */
32491708Sstevel static int
display_fru_oper_status(picl_nodehdl_t frutreeh)32501708Sstevel display_fru_oper_status(picl_nodehdl_t frutreeh)
32511708Sstevel {
32521708Sstevel 	int		print_header;
32531708Sstevel 
32541708Sstevel 	print_header = 0;
32551708Sstevel 	picl_walk_tree_by_class(frutreeh, PICL_CLASS_FRU,
32561708Sstevel 	    &print_header, fru_oper_status_callback);
32571708Sstevel 	return (PICL_SUCCESS);
32581708Sstevel }
32591708Sstevel 
32601708Sstevel /*
32611708Sstevel  * check if the node having the version prop
32621708Sstevel  * If yes, print its nodename and version
32631708Sstevel  */
32641708Sstevel /* ARGSUSED */
32651708Sstevel static int
asicrev_callback(picl_nodehdl_t nodeh,void * arg)32661708Sstevel asicrev_callback(picl_nodehdl_t nodeh, void *arg)
32671708Sstevel {
32681708Sstevel 	uint32_t	version;
32691708Sstevel 	char		*name;
32701708Sstevel 	char		*model;
32711708Sstevel 	char		*status;
32721708Sstevel 	int		err;
32731708Sstevel 
32741708Sstevel 	/*
32752936Svenki 	 * Fire based platforms use "fire-revision#" or "module-revision#"
32762936Svenki 	 * (depending on post/pre Fire 2.0) instead of "version#", so we
32772936Svenki 	 * need to check for these if we don't find "version#"
32781708Sstevel 	 */
32791708Sstevel 	version = picldiag_get_uint_propval(nodeh, OBP_PROP_VERSION_NUM, &err);
32801708Sstevel 	if (err == PICL_PROPNOTFOUND) {
32812936Svenki 		version = picldiag_get_uint_propval(nodeh, OBP_PROP_FIREREV_NUM,
32821708Sstevel 		    &err);
32832936Svenki 		if (err == PICL_PROPNOTFOUND) {
32842936Svenki 			version = picldiag_get_uint_propval(nodeh,
32852936Svenki 			    OBP_PROP_MODREV_NUM, &err);
32862936Svenki 			if (err == PICL_PROPNOTFOUND)
32872936Svenki 				return (PICL_WALK_CONTINUE);
32882936Svenki 		}
32891708Sstevel 	}
32901708Sstevel 	if (err != PICL_SUCCESS)
32911708Sstevel 		return (err);
32921708Sstevel 
32931708Sstevel 	/* devfs-path */
32941708Sstevel 	err =  picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, &name);
32951708Sstevel 	if (err == PICL_PROPNOTFOUND)
32961708Sstevel 		name = NULL;
32971708Sstevel 	else if (err != PICL_SUCCESS)
32981708Sstevel 		return (err);
32991708Sstevel 
33001708Sstevel 	/* model */
33011708Sstevel 	err =  picldiag_get_string_propval(nodeh, PICL_PROP_BINDING_NAME,
33021708Sstevel 	    &model);
33031708Sstevel 	if (err == PICL_PROPNOTFOUND)
33041708Sstevel 		model = NULL;
33051708Sstevel 	else if (err != PICL_SUCCESS)
33061708Sstevel 		return (err);
33071708Sstevel 
33081708Sstevel 	/* status */
33091708Sstevel 	err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status);
33101708Sstevel 	if (err == PICL_PROPNOTFOUND)
33111708Sstevel 		status = NULL;
33121708Sstevel 	else if (err != PICL_SUCCESS)
33131708Sstevel 		return (err);
33141708Sstevel 
33151708Sstevel 	/*
33161708Sstevel 	 * Display the data
33171708Sstevel 	 */
33181708Sstevel 
33191708Sstevel 	/* name */
33201708Sstevel 	if (name != NULL) {
33211708Sstevel 		log_printf("%-22s ", name);
33221708Sstevel 		free(name);
33231708Sstevel 	} else
33241708Sstevel 		log_printf("%-22s ", "unknown");
33251708Sstevel 	/* model */
33261708Sstevel 	if (model != NULL) {
33271708Sstevel 		log_printf("%-15s  ", model);
33281708Sstevel 		free(model);
33291708Sstevel 	} else
33301708Sstevel 		log_printf("%-15s  ", "unknown");
33311708Sstevel 	/* status */
33321708Sstevel 	if (status == NULL)
33331708Sstevel 		log_printf("%-15s  ", "okay");
33341708Sstevel 	else {
33351708Sstevel 		log_printf("%-15s  ", status);
33361708Sstevel 		set_exit_code(status);
33371708Sstevel 		free(status);
33381708Sstevel 	}
33391708Sstevel 	/* revision */
33401708Sstevel 	log_printf("  %-4d\n",	version);
33411708Sstevel 
33421708Sstevel 	return (PICL_WALK_CONTINUE);
33431708Sstevel }
33441708Sstevel 
33451708Sstevel /*
33461708Sstevel  * traverse the tree to display asic revision id for ebus
33471708Sstevel  */
33481708Sstevel /* ARGSUSED */
33491708Sstevel static int
ebus_callback(picl_nodehdl_t ebush,void * arg)33501708Sstevel ebus_callback(picl_nodehdl_t ebush, void *arg)
33511708Sstevel {
33521708Sstevel 	uint32_t	id;
33531708Sstevel 	char		*name;
33541708Sstevel 	int		err;
33551708Sstevel 	char		*model;
33561708Sstevel 	char		*status;
33571708Sstevel 
33581708Sstevel 	id = picldiag_get_uint_propval(ebush, OBP_PROP_REVISION_ID, &err);
33591708Sstevel 	if (err == PICL_PROPNOTFOUND)
33601708Sstevel 		return (PICL_WALK_CONTINUE);
33611708Sstevel 	else if (err != PICL_SUCCESS)
33621708Sstevel 		return (err);
33631708Sstevel 
33641708Sstevel 	/* devfs-path */
33651708Sstevel 	err =  picldiag_get_string_propval(ebush, PICL_PROP_DEVFS_PATH, &name);
33661708Sstevel 	if (err == PICL_PROPNOTFOUND)
33671708Sstevel 		name = NULL;
33681708Sstevel 	else if (err != PICL_SUCCESS)
33691708Sstevel 		return (err);
33701708Sstevel 
33711708Sstevel 	/* model */
33721708Sstevel 	err =  picldiag_get_string_propval(ebush, PICL_PROP_BINDING_NAME,
33731708Sstevel 	    &model);
33741708Sstevel 	if (err == PICL_PROPNOTFOUND)
33751708Sstevel 		model = NULL;
33761708Sstevel 	else if (err != PICL_SUCCESS)
33771708Sstevel 		return (err);
33781708Sstevel 
33791708Sstevel 	/* status */
33801708Sstevel 	err = picldiag_get_string_propval(ebush, PICL_PROP_STATUS, &status);
33811708Sstevel 	if (err == PICL_PROPNOTFOUND)
33821708Sstevel 		status = NULL;
33831708Sstevel 	else if (err != PICL_SUCCESS)
33841708Sstevel 		return (err);
33851708Sstevel 
33861708Sstevel 	/*
33871708Sstevel 	 * Display the data
33881708Sstevel 	 */
33891708Sstevel 
33901708Sstevel 	/* name */
33911708Sstevel 	if (name != NULL) {
33921708Sstevel 		log_printf("%-22s ", name);
33931708Sstevel 		free(name);
33941708Sstevel 	} else
33951708Sstevel 		log_printf("%-22s ", "unknown");
33961708Sstevel 	/* model */
33971708Sstevel 	if (model != NULL) {
33981708Sstevel 		log_printf("%-15s  ", model);
33991708Sstevel 		free(model);
34001708Sstevel 	} else
34011708Sstevel 		log_printf("%-15s  ", "unknown");
34021708Sstevel 	/* status */
34031708Sstevel 	if (status == NULL)
34041708Sstevel 		log_printf("%-15s  ", "okay");
34051708Sstevel 	else {
34061708Sstevel 		log_printf("%-15s  ", status);
34071708Sstevel 		set_exit_code(status);
34081708Sstevel 		free(status);
34091708Sstevel 	}
34101708Sstevel 	/* revision */
34111708Sstevel 	log_printf("  %-4d\n",	id);
34121708Sstevel 
34131708Sstevel 	return (PICL_WALK_CONTINUE);
34141708Sstevel }
34151708Sstevel 
34161708Sstevel /*
34171708Sstevel  * display asic revision id
34181708Sstevel  */
34191708Sstevel static int
display_hw_revisions(picl_nodehdl_t plafh)34201708Sstevel display_hw_revisions(picl_nodehdl_t plafh)
34211708Sstevel {
34221708Sstevel 	int	err;
34231708Sstevel 
34241708Sstevel 	/* Print the header */
34251708Sstevel 	logprintf_header(dgettext(TEXT_DOMAIN, "HW Revisions"),
34261708Sstevel 	    DEFAULT_LINE_WIDTH);
34271708Sstevel 
34281708Sstevel 	log_printf("ASIC Revisions:\n");
34291708Sstevel 	log_printf("-----------------------------");
34301708Sstevel 	log_printf("--------------------------------------\n");
34311708Sstevel 	log_printf("Path                   Device");
34321708Sstevel 	log_printf("           Status             Revision\n");
34331708Sstevel 	log_printf("-----------------------------");
34341708Sstevel 	log_printf("--------------------------------------\n");
34351708Sstevel 
34361708Sstevel 	err = picl_walk_tree_by_class(plafh, NULL, NULL, asicrev_callback);
34371708Sstevel 	if (err != PICL_SUCCESS)
34381708Sstevel 		return (err);
34391708Sstevel 
34401708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_EBUS,
34411708Sstevel 	    NULL, ebus_callback);
34421708Sstevel 	if (err != PICL_SUCCESS)
34431708Sstevel 		return (err);
34441708Sstevel 
34451708Sstevel 	log_printf("\n");
34461708Sstevel 
34471708Sstevel 	err = picl_walk_tree_by_class(plafh, PICL_CLASS_DISPLAY,
34481708Sstevel 	    NULL, ffbconfig_callback);
34491708Sstevel 	return (err);
34501708Sstevel }
34511708Sstevel 
34521708Sstevel /*
34531708Sstevel  * find the options node and its powerfail_time prop
34541708Sstevel  * If found, display the list of latest powerfail.
34551708Sstevel  */
34561708Sstevel /* ARGSUSED */
34571708Sstevel static int
options_callback(picl_nodehdl_t nodeh,void * arg)34581708Sstevel options_callback(picl_nodehdl_t nodeh, void *arg)
34591708Sstevel {
34601708Sstevel 	time_t		value;
34611708Sstevel 	char		*failtime;
34621708Sstevel 	int		err;
34631708Sstevel 
34641708Sstevel 	err = picldiag_get_string_propval(nodeh, PROP_POWERFAIL_TIME,
34651708Sstevel 	    &failtime);
34661708Sstevel 	if (err == PICL_PROPNOTFOUND)
34671708Sstevel 		return (PICL_WALK_TERMINATE);
34681708Sstevel 	else if (err != PICL_SUCCESS)
34691708Sstevel 		return (err);
34701708Sstevel 
34711708Sstevel 	value = (time_t)atoi(failtime);
34721708Sstevel 	free(failtime);
34731708Sstevel 	if (value == 0)
34741708Sstevel 		return (PICL_WALK_TERMINATE);
34751708Sstevel 
34761708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "Most recent AC Power Failure:\n"));
34771708Sstevel 	log_printf("=============================\n");
34781708Sstevel 	log_printf("%s", ctime(&value));
34791708Sstevel 	log_printf("\n");
34801708Sstevel 	return (PICL_WALK_TERMINATE);
34811708Sstevel }
34821708Sstevel 
34831708Sstevel /*
34841708Sstevel  * display the OBP and POST prom revisions
34851708Sstevel  */
34861708Sstevel /* ARGSUSED */
34871708Sstevel static int
flashprom_callback(picl_nodehdl_t flashpromh,void * arg)34881708Sstevel flashprom_callback(picl_nodehdl_t flashpromh, void *arg)
34891708Sstevel {
34901708Sstevel 	picl_prophdl_t	proph;
34911708Sstevel 	picl_prophdl_t	tblh;
34921708Sstevel 	picl_prophdl_t	rowproph;
34931708Sstevel 	picl_propinfo_t	pinfo;
34941708Sstevel 	char		*prom_version = NULL;
34951708Sstevel 	char		*obp_version = NULL;
34961708Sstevel 	int		err;
34971708Sstevel 
34981708Sstevel 	err = picl_get_propinfo_by_name(flashpromh, OBP_PROP_VERSION,
34991708Sstevel 	    &pinfo, &proph);
35001708Sstevel 	if (err == PICL_PROPNOTFOUND)
35011708Sstevel 		return (PICL_WALK_TERMINATE);
35021708Sstevel 	else if (err != PICL_SUCCESS)
35031708Sstevel 		return (err);
35041708Sstevel 
35051708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "System PROM revisions:\n"));
35061708Sstevel 	log_printf("----------------------\n");
35071708Sstevel 
35081708Sstevel 	/*
35091708Sstevel 	 * If it's a table prop, the first element is OBP revision
35101708Sstevel 	 * The second one is POST revision.
35111708Sstevel 	 * If it's a charstring prop, the value will be only OBP revision
35121708Sstevel 	 */
35131708Sstevel 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
35141708Sstevel 		prom_version = alloca(pinfo.size);
35151708Sstevel 		if (prom_version == NULL)
35161708Sstevel 			return (PICL_FAILURE);
35171708Sstevel 		err = picl_get_propval(proph, prom_version, pinfo.size);
35181708Sstevel 		if (err != PICL_SUCCESS)
35191708Sstevel 			return (err);
35201708Sstevel 		log_printf("%s\n", prom_version);
35211708Sstevel 	}
35221708Sstevel 
35231708Sstevel 	if (pinfo.type != PICL_PTYPE_TABLE)	/* not supported type */
35241708Sstevel 		return (PICL_WALK_TERMINATE);
35251708Sstevel 
35261708Sstevel 	err = picl_get_propval(proph, &tblh, pinfo.size);
35271708Sstevel 	if (err != PICL_SUCCESS)
35281708Sstevel 		return (err);
35291708Sstevel 
35301708Sstevel 	err = picl_get_next_by_row(tblh, &rowproph);
35311708Sstevel 	if (err == PICL_SUCCESS) {
35321708Sstevel 		/* get first row */
35331708Sstevel 		err = picl_get_propinfo(rowproph, &pinfo);
35341708Sstevel 		if (err != PICL_SUCCESS)
3535*13019SMichael.Bergknoff@Oracle.COM 			return (err);
35361708Sstevel 
35371708Sstevel 		prom_version = alloca(pinfo.size);
35381708Sstevel 		if (prom_version == NULL)
35391708Sstevel 			return (PICL_FAILURE);
35401708Sstevel 
35411708Sstevel 		err = picl_get_propval(rowproph, prom_version, pinfo.size);
35421708Sstevel 		if (err != PICL_SUCCESS)
35431708Sstevel 			return (err);
35441708Sstevel 		log_printf("%s\n", prom_version);
35451708Sstevel 
35461708Sstevel 		/* get second row */
35471708Sstevel 		err = picl_get_next_by_col(rowproph, &rowproph);
35481708Sstevel 		if (err == PICL_SUCCESS) {
35491708Sstevel 			err = picl_get_propinfo(rowproph, &pinfo);
35501708Sstevel 			if (err != PICL_SUCCESS)
35511708Sstevel 				return (err);
35521708Sstevel 
35531708Sstevel 			obp_version = alloca(pinfo.size);
35541708Sstevel 			if (obp_version == NULL)
35551708Sstevel 				return (PICL_FAILURE);
35561708Sstevel 			err = picl_get_propval(rowproph, obp_version,
35571708Sstevel 			    pinfo.size);
35581708Sstevel 			if (err != PICL_SUCCESS)
35591708Sstevel 				return (err);
35601708Sstevel 			log_printf("%s\n", obp_version);
35611708Sstevel 		}
35621708Sstevel 	}
35631708Sstevel 
35641708Sstevel 	return (PICL_WALK_TERMINATE);
35651708Sstevel }
35661708Sstevel 
35671708Sstevel static int
display_system_info(int serrlog,int log_flag,picl_nodehdl_t rooth)35681708Sstevel display_system_info(int serrlog, int log_flag, picl_nodehdl_t rooth)
35691708Sstevel {
35701708Sstevel 	int		err;
35711708Sstevel 	picl_nodehdl_t plafh;
35721708Sstevel 	picl_nodehdl_t frutreeh;
35731708Sstevel 
35741708Sstevel 	err = picldiag_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh);
35751708Sstevel 	if (err != PICL_SUCCESS)
35761708Sstevel 		return (err);
35771708Sstevel 
35781708Sstevel 	if (!log_flag) {
35791708Sstevel 		err = display_platform_banner(plafh);
35801708Sstevel 		if (err != PICL_SUCCESS)
35811708Sstevel 			return (err);
35821708Sstevel 
35831708Sstevel 		err = display_system_clock(plafh);
35841708Sstevel 		if (err != PICL_SUCCESS)
35851708Sstevel 			return (err);
35861708Sstevel 
35871708Sstevel 		err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY,
35881708Sstevel 		    PICL_CLASS_MEMORY, memory_callback);
35891708Sstevel 		if (err != PICL_SUCCESS)
35901708Sstevel 			return (err);
35911708Sstevel 
35921708Sstevel 		err = display_cpu_info(plafh);
35931708Sstevel 		if (err != PICL_SUCCESS)
35941708Sstevel 			return (err);
35951708Sstevel 
35961708Sstevel 		err = display_io_device_info(plafh);
35971708Sstevel 		if (err != PICL_SUCCESS)
35981708Sstevel 			return (err);
35991708Sstevel 
36001708Sstevel 		err = display_memory_config(plafh);
36011708Sstevel 		if (err != PICL_SUCCESS)
36021708Sstevel 			return (err);
36031708Sstevel 
36041708Sstevel 		err = display_usb_devices(plafh);
36051708Sstevel 		if (err != PICL_SUCCESS)
36061708Sstevel 			return (err);
36071708Sstevel 	}
36081708Sstevel 
36091708Sstevel 	if (serrlog) {
36101708Sstevel 		err = picl_walk_tree_by_class(rooth, PICL_CLASS_OPTIONS,
36111708Sstevel 		    NULL, options_callback);
36121708Sstevel 		if (err != PICL_SUCCESS)
36131708Sstevel 			return (err);
36141708Sstevel 
36151708Sstevel 		err = display_envctrl_status(plafh);
36161708Sstevel 		if (err != PICL_SUCCESS)
36171708Sstevel 			return (err);
36181708Sstevel 
36191708Sstevel 		err = picldiag_get_node_by_name(rooth, PICL_NODE_FRUTREE,
36201708Sstevel 		    &frutreeh);
36211708Sstevel 		if (err != PICL_SUCCESS)
36221708Sstevel 			return (err);
36231708Sstevel 
36241708Sstevel 		err = display_fru_oper_status(frutreeh);
36251708Sstevel 		if (err != PICL_SUCCESS)
36261708Sstevel 			return (err);
36271708Sstevel 
36281708Sstevel 		err = display_hw_revisions(plafh);
36291708Sstevel 		if (err != PICL_SUCCESS)
36301708Sstevel 			return (err);
36311708Sstevel 
36321708Sstevel 		err = picl_walk_tree_by_class(plafh, PICL_CLASS_FLASHPROM,
36331708Sstevel 		    NULL, flashprom_callback);
36341708Sstevel 		if (err != PICL_SUCCESS)
36351708Sstevel 			return (err);
36361708Sstevel 
36371708Sstevel 		err = display_serial_number(plafh);
36381708Sstevel 		if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND))
36391708Sstevel 			return (err);
36401708Sstevel 	}
36411708Sstevel 
36421708Sstevel 	return (PICL_SUCCESS);
36431708Sstevel }
36441708Sstevel 
36451708Sstevel /*
36461708Sstevel  * do_prominfo is called from main in prtdiag. It returns PD_SYSTEM_FAILURE if
36471708Sstevel  * any system failure is detected, PD_INTERNAL_FAILURE for internal errors and
36481708Sstevel  * PD_SUCCESS otherwise. main uses the return value as the exit code.
36491708Sstevel  */
36501708Sstevel /* ARGSUSED */
36511708Sstevel int
do_prominfo(int serrlog,char * pgname,int log_flag,int prt_flag)36521708Sstevel do_prominfo(int serrlog, char *pgname, int log_flag, int prt_flag)
36531708Sstevel {
36541708Sstevel 	int		err;
36551708Sstevel 	char		*errstr;
36561708Sstevel 	int		done;
36571708Sstevel 	picl_nodehdl_t	rooth;
36581708Sstevel 
36591708Sstevel 	err = picl_initialize();
36601708Sstevel 	if (err != PICL_SUCCESS) {
36611708Sstevel 		fprintf(stderr, EM_INIT_FAIL, picl_strerror(err));
36621708Sstevel 		return (PD_INTERNAL_FAILURE);
36631708Sstevel 	}
36641708Sstevel 
36651708Sstevel 	do {
36661708Sstevel 		done = 1;
36671708Sstevel 		err = picl_get_root(&rooth);
36681708Sstevel 		if (err != PICL_SUCCESS) {
36691708Sstevel 			fprintf(stderr, EM_GET_ROOT_FAIL, picl_strerror(err));
36701708Sstevel 			return (PD_INTERNAL_FAILURE);
36711708Sstevel 		}
36721708Sstevel 
36731708Sstevel 		err = display_system_info(serrlog, log_flag, rooth);
36741708Sstevel 
36751708Sstevel 		if ((err == PICL_STALEHANDLE) || (err == PICL_INVALIDHANDLE))
36761708Sstevel 			done = 0;
36771708Sstevel 	} while (!done);
36781708Sstevel 
36791708Sstevel 	if (err != PICL_SUCCESS) {
36801708Sstevel 		errstr = picl_strerror(err);
36811708Sstevel 		fprintf(stderr, EM_PRTDIAG_FAIL);
36821708Sstevel 		fprintf(stderr, "%s\n", errstr? errstr : " ");
36831708Sstevel 		exit_code = PD_INTERNAL_FAILURE;
36841708Sstevel 	}
36851708Sstevel 
36861708Sstevel 	(void) picl_shutdown();
36871708Sstevel 
36881708Sstevel 	return (exit_code);
36891708Sstevel }
3690