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