xref: /onnv-gate/usr/src/lib/libprtdiag/common/display_sun4v.c (revision 8574:34b33d2c8168)
11708Sstevel /*
21708Sstevel  * CDDL HEADER START
31708Sstevel  *
41708Sstevel  * The contents of this file are subject to the terms of the
53941Svenki  * Common Development and Distribution License (the "License").
63941Svenki  * 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 /*
22*8574SJason.Beloro@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
231708Sstevel  * Use is subject to license terms.
241708Sstevel  */
251708Sstevel 
261708Sstevel #include <stdio.h>
271708Sstevel #include <stdlib.h>
285436Sfw157321 #include <alloca.h>
291708Sstevel #include <unistd.h>
301708Sstevel #include <ctype.h>
311708Sstevel #include <string.h>
321708Sstevel #include <kvm.h>
331708Sstevel #include <varargs.h>
341708Sstevel #include <time.h>
351708Sstevel #include <dirent.h>
361708Sstevel #include <fcntl.h>
371708Sstevel #include <sys/param.h>
381708Sstevel #include <sys/stat.h>
391708Sstevel #include <sys/types.h>
401708Sstevel #include <sys/utsname.h>
411708Sstevel #include <sys/openpromio.h>
421708Sstevel #include <libintl.h>
431708Sstevel #include <syslog.h>
441708Sstevel #include <sys/dkio.h>
453941Svenki #include <sys/systeminfo.h>
463941Svenki #include <picldefs.h>
474802Sfw157321 #include <math.h>
484802Sfw157321 #include <errno.h>
491708Sstevel #include "pdevinfo.h"
501708Sstevel #include "display.h"
511708Sstevel #include "display_sun4v.h"
521708Sstevel #include "libprtdiag.h"
531708Sstevel 
541708Sstevel #if !defined(TEXT_DOMAIN)
551708Sstevel #define	TEXT_DOMAIN	"SYS_TEST"
561708Sstevel #endif
571708Sstevel 
584669Sfw157321 #define	MOTHERBOARD			"MB"
593941Svenki #define	NETWORK				"network"
603941Svenki #define	SUN4V_MACHINE			"sun4v"
613941Svenki #define	PARENT_NAMES			10
623941Svenki 
633941Svenki /*
643941Svenki  * Additional OBP properties
653941Svenki  */
663941Svenki #define	OBP_PROP_COMPATIBLE		"compatible"
673941Svenki #define	OBP_PROP_MODEL			"model"
683941Svenki #define	OBP_PROP_SLOT_NAMES		"slot-names"
695436Sfw157321 #define	OBP_PROP_VERSION		"version"
703941Svenki 
713941Svenki #define	PICL_NODE_PHYSICAL_PLATFORM	"physical-platform"
723941Svenki #define	PICL_NODE_CHASSIS		"chassis"
733941Svenki #define	MEMORY_SIZE_FIELD		11
743941Svenki #define	INVALID_THRESHOLD		1000000
753941Svenki 
763941Svenki /*
773941Svenki  * Additional picl classes
783941Svenki  */
793941Svenki #ifndef	PICL_CLASS_SUN4V
803941Svenki #define	PICL_CLASS_SUN4V		"sun4v"
813941Svenki #endif
823941Svenki 
833941Svenki #ifndef	PICL_PROP_NAC
843941Svenki #define	PICL_PROP_NAC			"nac"
853941Svenki #endif
863941Svenki 
873941Svenki extern int sys_clk;
883941Svenki extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *,
893941Svenki 	picl_nodehdl_t *);
903941Svenki 
913941Svenki static picl_nodehdl_t rooth = 0, phyplatformh = 0;
923941Svenki static picl_nodehdl_t chassish = 0;
933941Svenki static int class_node_found;
943941Svenki static int syserrlog;
953941Svenki static int all_status_ok;
963941Svenki 
973941Svenki /* local functions */
983941Svenki static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **);
993941Svenki static void sun4v_display_memory_conf(picl_nodehdl_t);
1005547Smb158278 static int sun4v_disp_env_status();
1013941Svenki static void sun4v_env_print_fan_sensors();
1023941Svenki static void sun4v_env_print_fan_indicators();
1033941Svenki static void sun4v_env_print_temp_sensors();
1043941Svenki static void sun4v_env_print_temp_indicators();
1053941Svenki static void sun4v_env_print_current_sensors();
1063941Svenki static void sun4v_env_print_current_indicators();
1073941Svenki static void sun4v_env_print_voltage_sensors();
1083941Svenki static void sun4v_env_print_voltage_indicators();
109*8574SJason.Beloro@Sun.COM static void sun4v_env_print_humidity_sensors();
110*8574SJason.Beloro@Sun.COM static void sun4v_env_print_humidity_indicators();
1113941Svenki static void sun4v_env_print_LEDs();
1123941Svenki static void sun4v_print_fru_status();
1133941Svenki static void sun4v_print_fw_rev();
1143941Svenki static void sun4v_print_chassis_serial_no();
1155436Sfw157321 static int openprom_callback(picl_nodehdl_t openpromh, void *arg);
1165436Sfw157321 static void sun4v_print_openprom_rev();
1171708Sstevel 
1181708Sstevel int
1193941Svenki sun4v_display(Sys_tree *tree, Prom_node *root, int log,
1203941Svenki 	picl_nodehdl_t plafh)
1211708Sstevel {
1221708Sstevel 	void *value;		/* used for opaque PROM data */
1231708Sstevel 	struct mem_total memory_total;	/* Total memory in system */
1241708Sstevel 	struct grp_info grps;	/* Info on all groups in system */
1253941Svenki 	char machine[MAXSTRLEN];
1265547Smb158278 	int	exit_code = 0;
1273941Svenki 
1283941Svenki 	if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1)
1293941Svenki 		return (1);
1303941Svenki 	if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0)
1313941Svenki 		return (1);
1321708Sstevel 
1331708Sstevel 	sys_clk = -1;  /* System clock freq. (in MHz) */
1341708Sstevel 
1351708Sstevel 	/*
1361708Sstevel 	 * Now display the machine's configuration. We do this if we
1371708Sstevel 	 * are not logging.
1381708Sstevel 	 */
1391708Sstevel 	if (!logging) {
1401708Sstevel 		struct utsname uts_buf;
1411708Sstevel 
1421708Sstevel 		/*
1431708Sstevel 		 * Display system banner
1441708Sstevel 		 */
1451708Sstevel 		(void) uname(&uts_buf);
1461708Sstevel 
1473941Svenki 		log_printf(dgettext(TEXT_DOMAIN, "System Configuration:  "
1484669Sfw157321 		    "Sun Microsystems  %s %s\n"), uts_buf.machine,
1494669Sfw157321 		    get_prop_val(find_prop(root, "banner-name")), 0);
1501708Sstevel 
1511708Sstevel 		/* display system clock frequency */
1521708Sstevel 		value = get_prop_val(find_prop(root, "clock-frequency"));
1531708Sstevel 		if (value != NULL) {
1541708Sstevel 			sys_clk = ((*((int *)value)) + 500000) / 1000000;
1551708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, "System clock "
1564669Sfw157321 			    "frequency: %d MHz\n"), sys_clk, 0);
1571708Sstevel 		}
1581708Sstevel 
1591708Sstevel 		/* Display the Memory Size */
1601708Sstevel 		display_memorysize(tree, NULL, &grps, &memory_total);
1611708Sstevel 
1621708Sstevel 		/* Display the CPU devices */
1631708Sstevel 		sun4v_display_cpu_devices(plafh);
1641708Sstevel 
1651708Sstevel 		/* Display the Memory configuration */
1663941Svenki 		class_node_found = 0;
1673941Svenki 		sun4v_display_memory_conf(plafh);
1681708Sstevel 
1691708Sstevel 		/* Display all the IO cards. */
1701708Sstevel 		(void) sun4v_display_pci(plafh);
1713941Svenki 		sun4v_display_diaginfo((log || (logging)), root, plafh);
1721708Sstevel 
1733941Svenki 		if (picl_get_root(&rooth) != PICL_SUCCESS)
1743941Svenki 			return (1);
1755547Smb158278 
1765547Smb158278 		/*
1775547Smb158278 		 * The physical-platform node may be missing on systems with
1785547Smb158278 		 * older firmware so don't consider that an error.
1795547Smb158278 		 */
1803941Svenki 		if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM,
1814669Sfw157321 		    &phyplatformh) != PICL_SUCCESS)
1825547Smb158278 			return (0);
1833941Svenki 
1843941Svenki 		if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME,
1854669Sfw157321 		    PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
1864669Sfw157321 		    strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS)
1873941Svenki 			return (1);
1883941Svenki 
1893941Svenki 		syserrlog = log;
1905547Smb158278 		exit_code = sun4v_disp_env_status();
1913941Svenki 	}
1925547Smb158278 	return (exit_code);
1933941Svenki }
1943941Svenki 
1955819Sfw157321 /*
1965819Sfw157321  * The binding-name property encodes the bus type.
1975819Sfw157321  */
1983941Svenki static void
1993941Svenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card)
2003941Svenki {
2015819Sfw157321 	char val[PICL_PROPNAMELEN_MAX], *p, *q;
2025819Sfw157321 
2035819Sfw157321 	card->bus_type[0] = '\0';
2043941Svenki 
2055819Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, val,
2065819Sfw157321 	    sizeof (val)) == PICL_SUCCESS) {
2075819Sfw157321 		if (strstr(val, PICL_CLASS_PCIEX))
2084003Svivek 			(void) strlcpy(card->bus_type, "PCIE",
2094669Sfw157321 			    sizeof (card->bus_type));
2105819Sfw157321 		else if (strstr(val, PICL_CLASS_PCI))
2115819Sfw157321 			(void) strlcpy(card->bus_type, "PCIX",
2125819Sfw157321 			    sizeof (card->bus_type));
2135819Sfw157321 		else {
2145819Sfw157321 			/*
2155819Sfw157321 			 * Not perfect: process the binding-name until
2165819Sfw157321 			 * we encounter something that we don't think would
2175819Sfw157321 			 * be part of a bus type.  This may get confused a bit
2185819Sfw157321 			 * if a device or vendor id is encoded right after
2195819Sfw157321 			 * the bus class since there's no delimiter.  If the
2205819Sfw157321 			 * id number begins with a hex digit [abcdef] then
2215819Sfw157321 			 * this will become part of the bus type string
2225819Sfw157321 			 * reported by prtdiag.  This is all an effort to
2235819Sfw157321 			 * print something potentially useful for bus types
2245819Sfw157321 			 * other than PCI/PCIe.
2255819Sfw157321 			 *
2265819Sfw157321 			 * We do this because this code will get called for
2275819Sfw157321 			 * non-PCI class devices like the xaui (class sun4v.)
2285819Sfw157321 			 */
2295819Sfw157321 			if (strstr(val, "SUNW,") != NULL)
2305819Sfw157321 				p = strchr(val, ',') + 1;
2315819Sfw157321 			else
2325819Sfw157321 				p = val;
2335819Sfw157321 			q = p;
2345819Sfw157321 			while (*p != '\0') {
2355819Sfw157321 				if (isdigit((char)*p) || ispunct((char)*p)) {
2365819Sfw157321 					*p = '\0';
2375819Sfw157321 					break;
2385819Sfw157321 				}
2395819Sfw157321 				*p = (char)_toupper((int)*p);
2405819Sfw157321 				++p;
2415819Sfw157321 			}
2425819Sfw157321 			(void) strlcpy(card->bus_type, q,
2435819Sfw157321 			    sizeof (card->bus_type));
2445819Sfw157321 		}
2453941Svenki 	}
2463941Svenki }
2473941Svenki 
2485819Sfw157321 /*
2495819Sfw157321  * Fetch the Label property for this device.  If none is found then
2505819Sfw157321  * search all the siblings with the same device ID for a
2515819Sfw157321  * Label and return that Label.  The plug-in can only match the canonical
2525819Sfw157321  * path from the PRI with a specific devfs path.  So we take care of
2535819Sfw157321  * devices with multiple functions here.  A leaf device downstream of
2545819Sfw157321  * a bridge should fall out of here with PICL_PROPNOTFOUND, and the
2555819Sfw157321  * caller can walk back up the tree in search of the slot's Label.
2565819Sfw157321  */
2573941Svenki static picl_errno_t
2583941Svenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card)
2593941Svenki {
2603941Svenki 	char val[PICL_PROPNAMELEN_MAX];
2613941Svenki 	picl_errno_t err;
2625436Sfw157321 	picl_nodehdl_t pnodeh;
2635819Sfw157321 	uint32_t devid, sib_devid;
2645819Sfw157321 	int32_t instance;
2653941Svenki 
2665436Sfw157321 	/*
2675819Sfw157321 	 * If there's a Label at this node then return it - we're
2685819Sfw157321 	 * done.
2695436Sfw157321 	 */
2703941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
2714669Sfw157321 	    sizeof (val));
2725819Sfw157321 	if (err == PICL_SUCCESS) {
2735819Sfw157321 		(void) strlcpy(card->slot_str, val, sizeof (card->slot_str));
2745819Sfw157321 		return (err);
2755819Sfw157321 	} else if (err != PICL_PROPNOTFOUND)
2765819Sfw157321 		return (err);
2775819Sfw157321 
2785819Sfw157321 	/*
2795819Sfw157321 	 * At this point we're starting to extrapolate what the Label
2805819Sfw157321 	 * should be since there is none at this specific node.
2815819Sfw157321 	 * Note that until the value of "err" is overwritten in the
2825819Sfw157321 	 * loop below, its value should be PICL_PROPNOTFOUND.
2835819Sfw157321 	 */
2845819Sfw157321 
2855819Sfw157321 	/*
2865819Sfw157321 	 * The device must be attached, and we can figure that out if
2875819Sfw157321 	 * the instance number is present and is not equal to -1.
2885819Sfw157321 	 * This will prevent is from returning a Label for a sibling
2895819Sfw157321 	 * node when the node passed in would have a unique Label if the
2905819Sfw157321 	 * device were attached.  But if the device is downstream of a
2915819Sfw157321 	 * node with a Label then pci_callback() will still find that
2925819Sfw157321 	 * and use it.
2935819Sfw157321 	 */
2945819Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_INSTANCE, &instance,
2955819Sfw157321 	    sizeof (instance)) != PICL_SUCCESS)
2965819Sfw157321 		return (err);
2975819Sfw157321 	if (instance == -1)
2985819Sfw157321 		return (err);
2993941Svenki 
3005819Sfw157321 	/*
3015819Sfw157321 	 * Narrow the search to just the one device ID.
3025819Sfw157321 	 */
3035819Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_DEVICE_ID, &devid,
3045819Sfw157321 	    sizeof (devid)) != PICL_SUCCESS)
3055819Sfw157321 		return (err);
3065819Sfw157321 
3075819Sfw157321 	/*
3085819Sfw157321 	 * Go find the first child of the parent so we can search
3095819Sfw157321 	 * all of the siblings.
3105819Sfw157321 	 */
3115819Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
3125819Sfw157321 	    sizeof (pnodeh)) != PICL_SUCCESS)
3135819Sfw157321 		return (err);
3145819Sfw157321 	if (picl_get_propval_by_name(pnodeh, PICL_PROP_CHILD, &pnodeh,
3155819Sfw157321 	    sizeof (pnodeh)) != PICL_SUCCESS)
3165819Sfw157321 		return (err);
3175436Sfw157321 
3185819Sfw157321 	/*
3195819Sfw157321 	 * If the child's device ID matches, then fetch the Label and
3205819Sfw157321 	 * return it.  The first child/device ID should have a Label
3215819Sfw157321 	 * associated with it.
3225819Sfw157321 	 */
3235819Sfw157321 	do {
3245819Sfw157321 		if (picl_get_propval_by_name(pnodeh, PICL_PROP_DEVICE_ID,
3255819Sfw157321 		    &sib_devid, sizeof (sib_devid)) == PICL_SUCCESS) {
3265819Sfw157321 			if (sib_devid == devid) {
3275819Sfw157321 				if ((err = picl_get_propval_by_name(pnodeh,
3285819Sfw157321 				    PICL_PROP_LABEL, val, sizeof (val))) ==
3295819Sfw157321 				    PICL_SUCCESS) {
3305819Sfw157321 					(void) strlcpy(card->slot_str, val,
3315819Sfw157321 					    sizeof (card->slot_str));
3325819Sfw157321 					break;
3335819Sfw157321 				}
3345819Sfw157321 			}
3355819Sfw157321 		}
3365819Sfw157321 	} while (picl_get_propval_by_name(pnodeh, PICL_PROP_PEER, &pnodeh,
3375819Sfw157321 	    sizeof (pnodeh)) == PICL_SUCCESS);
3385819Sfw157321 
3395436Sfw157321 	return (err);
3403941Svenki }
3413941Svenki 
3423941Svenki static void
3433941Svenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card)
3443941Svenki {
3453941Svenki 	picl_errno_t err;
3463941Svenki 	picl_prophdl_t proph;
3473941Svenki 	picl_propinfo_t pinfo;
3483941Svenki 	picl_nodehdl_t pnodeh;
3493941Svenki 	uint8_t *pval;
3503941Svenki 	uint32_t dev_mask;
3513941Svenki 	char uaddr[MAXSTRLEN];
3523941Svenki 	int i;
3533941Svenki 
3543941Svenki 	err = PICL_SUCCESS;
3553941Svenki 	while (err == PICL_SUCCESS) {
3563941Svenki 		if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
3574669Sfw157321 		    sizeof (pnodeh)) != PICL_SUCCESS) {
3584669Sfw157321 			(void) strlcpy(card->slot_str, MOTHERBOARD,
3594669Sfw157321 			    sizeof (card->slot_str));
3603941Svenki 			card->slot = -1;
3613941Svenki 			return;
3623941Svenki 		}
3633941Svenki 		if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES,
3644669Sfw157321 		    &pinfo, &proph) == PICL_SUCCESS) {
3653941Svenki 			break;
3663941Svenki 		}
3673941Svenki 		nodeh = pnodeh;
3683941Svenki 	}
3693941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr,
3704669Sfw157321 	    sizeof (uaddr)) != PICL_SUCCESS) {
3714669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
3724669Sfw157321 		    sizeof (card->slot_str));
3733941Svenki 		card->slot = -1;
3743941Svenki 		return;
3753941Svenki 	}
3763941Svenki 	pval = (uint8_t *)malloc(pinfo.size);
3773941Svenki 	if (!pval) {
3784669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
3794669Sfw157321 		    sizeof (card->slot_str));
3803941Svenki 		card->slot = -1;
3813941Svenki 		return;
3823941Svenki 	}
3833941Svenki 	if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) {
3844669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
3854669Sfw157321 		    sizeof (card->slot_str));
3863941Svenki 		card->slot = -1;
3873941Svenki 		free(pval);
3883941Svenki 		return;
3891708Sstevel 	}
3901708Sstevel 
3913941Svenki 	dev_mask = 0;
3923941Svenki 	for (i = 0; i < sizeof (dev_mask); i++)
3933941Svenki 		dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i));
3943941Svenki 	for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) {
3953941Svenki 		if (uaddr[i] == ',') {
3963941Svenki 			uaddr[i] = '\0';
3973941Svenki 			break;
3983941Svenki 		}
3993941Svenki 	}
4003941Svenki 	card->slot = atol(uaddr);
4013941Svenki 	if (((1 << card->slot) & dev_mask) == 0) {
4024669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
4034669Sfw157321 		    sizeof (card->slot_str));
4043941Svenki 		card->slot = -1;
4053941Svenki 	} else {
4063941Svenki 		char *p = (char *)(pval+sizeof (dev_mask));
4073941Svenki 		int shift = sizeof (uint32_t)*8-1-card->slot;
4083941Svenki 		uint32_t x = (dev_mask << shift) >> shift;
4093941Svenki 		int count = 0;	/* count # of 1's in x */
4103941Svenki 		int i = 0;
4113941Svenki 		while (x != 0) {
4123941Svenki 			count++;
4133941Svenki 			x &= x-1;
4143941Svenki 		}
4153941Svenki 		while (count > 1) {
4164669Sfw157321 			while (p[i++] != '\0')
4174669Sfw157321 				;
4183941Svenki 			count--;
4193941Svenki 		}
4204003Svivek 		(void) strlcpy(card->slot_str, (char *)(p+i),
4214669Sfw157321 		    sizeof (card->slot_str));
4223941Svenki 	}
4233941Svenki 	free(pval);
4243941Svenki }
4253941Svenki 
4263941Svenki /*
4273941Svenki  * add all io devices under pci in io list
4283941Svenki  */
4293941Svenki /* ARGSUSED */
4303941Svenki static int
4313941Svenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args)
4323941Svenki {
4333941Svenki 	char path[PICL_PROPNAMELEN_MAX];
4343941Svenki 	char class[PICL_CLASSNAMELEN_MAX];
4353941Svenki 	char name[PICL_PROPNAMELEN_MAX];
4363941Svenki 	char model[PICL_PROPNAMELEN_MAX];
4373941Svenki 	char binding_name[PICL_PROPNAMELEN_MAX];
4383941Svenki 	char val[PICL_PROPNAMELEN_MAX];
4393941Svenki 	char *compatible;
4403941Svenki 	picl_errno_t err;
4415819Sfw157321 	picl_nodehdl_t nodeh, pnodeh;
4423941Svenki 	struct io_card pci_card;
4433941Svenki 
4443941Svenki 	/* Walk through the children */
4453941Svenki 
4463941Svenki 	err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
4474669Sfw157321 	    sizeof (picl_nodehdl_t));
4483941Svenki 
4493941Svenki 	while (err == PICL_SUCCESS) {
4503941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
4514669Sfw157321 		    class, sizeof (class));
4523941Svenki 		if (err !=  PICL_SUCCESS)
4533941Svenki 			return (err);
4543941Svenki 
4553941Svenki 		if (args) {
4563941Svenki 			char *val = args;
4573941Svenki 			if (strcmp(class, val) == 0) {
4583941Svenki 				err = picl_get_propval_by_name(nodeh,
4594669Sfw157321 				    PICL_PROP_PEER, &nodeh,
4604669Sfw157321 				    sizeof (picl_nodehdl_t));
4613941Svenki 				continue;
4623941Svenki 			} else if (strcmp(val, PICL_CLASS_PCIEX) == 0 &&
4634669Sfw157321 			    strcmp(class, PICL_CLASS_PCI) == 0) {
4643941Svenki 				err = picl_get_propval_by_name(nodeh,
4654669Sfw157321 				    PICL_PROP_PEER, &nodeh,
4664669Sfw157321 				    sizeof (picl_nodehdl_t));
4673941Svenki 				continue;
4683941Svenki 			} else if (strcmp(val, PICL_CLASS_PCI) == 0 &&
4694669Sfw157321 			    strcmp(class, PICL_CLASS_PCIEX) == 0) {
4703941Svenki 				err = picl_get_propval_by_name(nodeh,
4714669Sfw157321 				    PICL_PROP_PEER, &nodeh,
4724669Sfw157321 				    sizeof (picl_nodehdl_t));
4733941Svenki 				continue;
4743941Svenki 			}
4753941Svenki 		}
4763941Svenki 
4773941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
4784669Sfw157321 		    path, sizeof (path));
4793941Svenki 		if (err != PICL_SUCCESS)
4803941Svenki 			return (err);
4813941Svenki 
4823941Svenki 		(void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
4833941Svenki 
4845819Sfw157321 		pnodeh = nodeh;
4855819Sfw157321 		err = get_slot_label(nodeh, &pci_card);
4865819Sfw157321 
4875819Sfw157321 		/*
4885819Sfw157321 		 * No Label at this node, maybe we're looking at a device
4895819Sfw157321 		 * downstream of a bridge.  Walk back up and find a Label and
4905819Sfw157321 		 * record that node in "pnodeh".
4915819Sfw157321 		 */
4925819Sfw157321 		while (err != PICL_SUCCESS) {
4935819Sfw157321 			if (err != PICL_PROPNOTFOUND)
4945819Sfw157321 				break;
4955819Sfw157321 			else if (picl_get_propval_by_name(pnodeh,
4965819Sfw157321 			    PICL_PROP_PARENT, &pnodeh, sizeof (pnodeh)) ==
4975819Sfw157321 			    PICL_SUCCESS)
4985819Sfw157321 				err = get_slot_label(pnodeh, &pci_card);
4995819Sfw157321 			else
5005819Sfw157321 				break;
5015819Sfw157321 		}
5025819Sfw157321 
5035819Sfw157321 		/*
5045819Sfw157321 		 * Can't find a Label for this device in the PCI heirarchy.
5055819Sfw157321 		 * Try to synthesize a slot name from atoms.  This depends
5065819Sfw157321 		 * on the OBP slot_names property being implemented, and this
5075819Sfw157321 		 * so far doesn't seem to be on sun4v.  But just in case that
5085819Sfw157321 		 * is resurrected, the code is here.
5095819Sfw157321 		 */
5105819Sfw157321 		if (err != PICL_SUCCESS) {
5115819Sfw157321 			pnodeh = nodeh;
5125819Sfw157321 			get_slot_number(nodeh, &pci_card);
5135819Sfw157321 		}
5145819Sfw157321 
5155819Sfw157321 		/*
5165819Sfw157321 		 * Passing in pnodeh instead of nodeh will cause prtdiag
5175819Sfw157321 		 * to display the type of IO slot for the leaf node.  For
5185819Sfw157321 		 * built-in devices and a lot of IO cards these will be
5195819Sfw157321 		 * the same thing.  But for IO cards with bridge chips or
5205819Sfw157321 		 * for things like expansion chassis, prtdiag will report
5215819Sfw157321 		 * the bus type of the IO slot and not the leaf, which
5225819Sfw157321 		 * could be different things.
5235819Sfw157321 		 */
5245819Sfw157321 		get_bus_type(pnodeh, &pci_card);
5253941Svenki 
5263941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name,
5274669Sfw157321 		    sizeof (name));
5283941Svenki 		if (err == PICL_PROPNOTFOUND)
5294003Svivek 			(void) strlcpy(name, "", sizeof (name));
5303941Svenki 		else if (err != PICL_SUCCESS)
5313941Svenki 			return (err);
5323941Svenki 
5333941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val,
5344669Sfw157321 		    sizeof (val));
5353941Svenki 		if (err == PICL_PROPNOTFOUND)
5364003Svivek 			(void) strlcpy(val, "", sizeof (val));
5373941Svenki 		else if (err != PICL_SUCCESS)
5383941Svenki 			return (err);
5393941Svenki 
5405436Sfw157321 		(void) snprintf(pci_card.status, sizeof (pci_card.status),
5415436Sfw157321 		    "%s", pci_card.slot_str);
5423941Svenki 
5433941Svenki 		/*
5443941Svenki 		 * Get the name of this card. If binding_name is found,
5453941Svenki 		 * name will be <nodename>-<binding_name>.
5463941Svenki 		 */
5473941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
5484669Sfw157321 		    binding_name, sizeof (binding_name));
5493941Svenki 		if (err == PICL_SUCCESS) {
5503941Svenki 			if (strcmp(name, binding_name) != 0) {
5513941Svenki 				(void) strlcat(name, "-", sizeof (name));
5523941Svenki 				(void) strlcat(name, binding_name,
5534669Sfw157321 				    sizeof (name));
5543941Svenki 			}
5553941Svenki 		} else if (err == PICL_PROPNOTFOUND) {
5563941Svenki 			/*
5573941Svenki 			 * if compatible prop is not found, name will be
5583941Svenki 			 * <nodename>-<compatible>
5593941Svenki 			 */
5603941Svenki 			err = sun4v_get_first_compatible_value(nodeh,
5614669Sfw157321 			    &compatible);
5623941Svenki 			if (err == PICL_SUCCESS) {
5633941Svenki 				(void) strlcat(name, "-", sizeof (name));
5644003Svivek 				(void) strlcat(name, compatible,
5654669Sfw157321 				    sizeof (name));
5663941Svenki 				free(compatible);
5673941Svenki 			}
5683941Svenki 		} else
5693941Svenki 			return (err);
5703941Svenki 
5713941Svenki 		(void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
5723941Svenki 
5733941Svenki 		/* Get the model of this card */
5743941Svenki 
5753941Svenki 		err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
5764669Sfw157321 		    model, sizeof (model));
5773941Svenki 		if (err == PICL_PROPNOTFOUND)
5784003Svivek 			(void) strlcpy(model, "", sizeof (model));
5793941Svenki 		else if (err != PICL_SUCCESS)
5803941Svenki 			return (err);
5813941Svenki 		(void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
5823941Svenki 
5833941Svenki 		/* Print NAC name */
5844802Sfw157321 		log_printf("%-18s", pci_card.status);
5853941Svenki 		/* Print IO Type */
5863941Svenki 		log_printf("%-6s", pci_card.bus_type);
5873941Svenki 		/* Printf Card Name */
5885544Sfw157321 		log_printf("%-34s", pci_card.name);
5893941Svenki 		/* Print Card Model */
5903941Svenki 		log_printf("%-8s", pci_card.model);
5913941Svenki 		log_printf("\n");
5923941Svenki 		/* Print Status */
5934802Sfw157321 		log_printf("%-18s", val);
5943941Svenki 		/* Print IO Type */
5953941Svenki 		log_printf("%-6s", "");
5963941Svenki 		/* Print Parent Path */
5974802Sfw157321 		log_printf("%-44s", pci_card.notes);
5983941Svenki 		log_printf("\n");
5993941Svenki 
6003941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
6014669Sfw157321 		    sizeof (picl_nodehdl_t));
6023941Svenki 	}
6033941Svenki 	return (PICL_WALK_CONTINUE);
6041708Sstevel }
6051708Sstevel 
6061708Sstevel /*
6071708Sstevel  * display_pci
6081708Sstevel  * Display all the PCI IO cards on this board.
6091708Sstevel  */
6101708Sstevel void
6111708Sstevel sun4v_display_pci(picl_nodehdl_t plafh)
6121708Sstevel {
6135544Sfw157321 	char *fmt = "%-17s %-5s %-33s %-8s";
6143941Svenki 	/* Have we printed the column headings? */
6153941Svenki 	static int banner = FALSE;
6163941Svenki 
6173941Svenki 	if (banner == FALSE) {
6183941Svenki 		log_printf("\n");
6194802Sfw157321 		log_printf("================================");
6203941Svenki 		log_printf(" IO Devices ");
6214802Sfw157321 		log_printf("================================");
6223941Svenki 		log_printf("\n");
6233941Svenki 		log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0);
6243941Svenki 		log_printf("\n");
6253941Svenki 		log_printf(fmt, "Status", "Type", "Path", "", 0);
6263941Svenki 		log_printf("\n");
6273941Svenki 		log_printf("---------------------------------"
6284802Sfw157321 		    "-------------------------------------------\n");
6293941Svenki 		banner = TRUE;
6303941Svenki 	}
6313941Svenki 
6323941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
6334669Sfw157321 	    PICL_CLASS_PCIEX, sun4v_pci_callback);
6343941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
6354669Sfw157321 	    PICL_CLASS_PCI, sun4v_pci_callback);
6363941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V,
6374669Sfw157321 	    PICL_CLASS_SUN4V, sun4v_pci_callback);
6383941Svenki }
6393941Svenki 
6403941Svenki /*
6413941Svenki  * return the first compatible value
6423941Svenki  */
6433941Svenki static int
6443941Svenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
6453941Svenki {
6463941Svenki 	picl_errno_t err;
6473941Svenki 	picl_prophdl_t proph;
6483941Svenki 	picl_propinfo_t pinfo;
6493941Svenki 	picl_prophdl_t tblh;
6503941Svenki 	picl_prophdl_t rowproph;
6513941Svenki 	char *pval;
6523941Svenki 
6533941Svenki 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
6544669Sfw157321 	    &pinfo, &proph);
6553941Svenki 	if (err != PICL_SUCCESS)
6563941Svenki 		return (err);
6573941Svenki 
6583941Svenki 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
6593941Svenki 		pval = malloc(pinfo.size);
6603941Svenki 		if (pval == NULL)
6613941Svenki 			return (PICL_FAILURE);
6623941Svenki 		err = picl_get_propval(proph, pval, pinfo.size);
6633941Svenki 		if (err != PICL_SUCCESS) {
6643941Svenki 			free(pval);
6653941Svenki 			return (err);
6663941Svenki 		}
6673941Svenki 		*outbuf = pval;
6683941Svenki 		return (PICL_SUCCESS);
6693941Svenki 	}
6703941Svenki 
6713941Svenki 	if (pinfo.type != PICL_PTYPE_TABLE)
6723941Svenki 		return (PICL_FAILURE);
6733941Svenki 
6743941Svenki 	/* get first string from table */
6753941Svenki 	err = picl_get_propval(proph, &tblh, pinfo.size);
6763941Svenki 	if (err != PICL_SUCCESS)
6773941Svenki 		return (err);
6783941Svenki 
6793941Svenki 	err = picl_get_next_by_row(tblh, &rowproph);
6803941Svenki 	if (err != PICL_SUCCESS)
6813941Svenki 		return (err);
6823941Svenki 
6833941Svenki 	err = picl_get_propinfo(rowproph, &pinfo);
6843941Svenki 	if (err != PICL_SUCCESS)
6853941Svenki 		return (err);
6863941Svenki 
6873941Svenki 	pval = malloc(pinfo.size);
6883941Svenki 	if (pval == NULL)
6893941Svenki 		return (PICL_FAILURE);
6903941Svenki 
6913941Svenki 	err = picl_get_propval(rowproph, pval, pinfo.size);
6923941Svenki 	if (err != PICL_SUCCESS) {
6933941Svenki 		free(pval);
6943941Svenki 		return (err);
6953941Svenki 	}
6963941Svenki 
6973941Svenki 	*outbuf = pval;
6983941Svenki 	return (PICL_SUCCESS);
6991708Sstevel }
7001708Sstevel 
7013941Svenki /*
7023941Svenki  * print size of a memory segment
7033941Svenki  */
7043941Svenki static void
7053941Svenki print_memory_segment_size(uint64_t size)
7063941Svenki {
7073941Svenki 	uint64_t kbyte = 1024;
7083941Svenki 	uint64_t mbyte = kbyte * kbyte;
7093941Svenki 	uint64_t gbyte = kbyte * mbyte;
7105544Sfw157321 	uint64_t tbyte = kbyte * gbyte;
7113941Svenki 	char buf[MEMORY_SIZE_FIELD];
7123941Svenki 
7135544Sfw157321 	if (size >= tbyte) {
7145544Sfw157321 		if (size % tbyte == 0)
7155544Sfw157321 			(void) snprintf(buf, sizeof (buf), "%d TB",
7165544Sfw157321 			    (int)(size / tbyte));
7175544Sfw157321 		else
7185544Sfw157321 			(void) snprintf(buf, sizeof (buf), "%.2f TB",
7195544Sfw157321 			    (float)size / tbyte);
7205544Sfw157321 	} else if (size >= gbyte) {
7213941Svenki 		if (size % gbyte == 0)
7223941Svenki 			(void) snprintf(buf, sizeof (buf), "%d GB",
7234669Sfw157321 			    (int)(size / gbyte));
7243941Svenki 		else
7253941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f GB",
7264669Sfw157321 			    (float)size / gbyte);
7273941Svenki 	} else if (size >= mbyte) {
7283941Svenki 		if (size % mbyte == 0)
7293941Svenki 			(void) snprintf(buf, sizeof (buf), "%d MB",
7304669Sfw157321 			    (int)(size / mbyte));
7313941Svenki 		else
7323941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f MB",
7334669Sfw157321 			    (float)size / mbyte);
7343941Svenki 	} else {
7353941Svenki 		if (size % kbyte == 0)
7363941Svenki 			(void) snprintf(buf, sizeof (buf), "%d KB",
7374669Sfw157321 			    (int)(size / kbyte));
7383941Svenki 		else
7393941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f KB",
7404669Sfw157321 			    (float)size / kbyte);
7413941Svenki 	}
7425544Sfw157321 	log_printf("%-9s", buf);
7433941Svenki }
7443941Svenki 
7453941Svenki /*
7464669Sfw157321  * Enumerate banks and dimms within a memory segment.  We're handed
7474669Sfw157321  * the first bank within the segment - we assume there are dimms
7484669Sfw157321  * (memory-module) nodes underneath.
7493941Svenki  */
7503941Svenki static void
7514669Sfw157321 print_memory_segment_contain(picl_nodehdl_t bank_nodeh)
7521708Sstevel {
7533941Svenki 	char val[PICL_PROPNAMELEN_MAX];
7544669Sfw157321 	picl_nodehdl_t module_nodeh;
7554669Sfw157321 	int flag = 0;
7565544Sfw157321 	uint64_t size;
7574669Sfw157321 
7584669Sfw157321 	do {
7594669Sfw157321 		if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD,
7604669Sfw157321 		    &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS)
7614669Sfw157321 			continue;
7625544Sfw157321 		if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_SIZE,
7635544Sfw157321 		    &size, sizeof (size)) == PICL_SUCCESS) {
7645544Sfw157321 			if (!flag) {
7655544Sfw157321 				print_memory_segment_size(size);
7665544Sfw157321 			} else {
7675544Sfw157321 				log_printf("                "
7685544Sfw157321 				    "                    ");
7695544Sfw157321 				print_memory_segment_size(size);
7705544Sfw157321 				flag = 0;
7715544Sfw157321 			}
7725544Sfw157321 		}
7734669Sfw157321 		do {
7744669Sfw157321 			if (picl_get_propval_by_name(module_nodeh,
7754669Sfw157321 			    PICL_PROP_NAC, val, sizeof (val)) !=
7764669Sfw157321 			    PICL_SUCCESS)
7774669Sfw157321 				continue;
7784669Sfw157321 			else {
7794669Sfw157321 				if (!flag) {
7805544Sfw157321 					log_printf("%s\n", val);
7814669Sfw157321 					flag = 1;
7825544Sfw157321 				} else {
7835544Sfw157321 					log_printf("%s%s\n",
7845544Sfw157321 					    "                       "
7855544Sfw157321 					    "                      ",
7865544Sfw157321 					    val);
7875544Sfw157321 				}
7884669Sfw157321 			}
7894669Sfw157321 		} while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER,
7904669Sfw157321 		    &module_nodeh, sizeof (picl_nodehdl_t)) ==
7914669Sfw157321 		    PICL_SUCCESS);
7924669Sfw157321 	} while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER,
7934669Sfw157321 	    &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS);
7943941Svenki }
7953941Svenki 
7963941Svenki /*
7973941Svenki  * Search node where _class=="memory-segment"
7983941Svenki  * print "Base Address", "Size", etc
7993941Svenki  */
8003941Svenki /*ARGSUSED*/
8013941Svenki static int
8023941Svenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args)
8033941Svenki {
8043941Svenki 	uint64_t base;
8053941Svenki 	uint64_t size;
8063941Svenki 	uint64_t ifactor;
8073941Svenki 	picl_errno_t err = PICL_SUCCESS;
8083941Svenki 
8093941Svenki 	if (class_node_found == 0) {
8103941Svenki 		class_node_found = 1;
8113941Svenki 		return (PICL_WALK_TERMINATE);
8123941Svenki 	}
8133941Svenki 	while (err == PICL_SUCCESS) {
8143941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS,
8154669Sfw157321 		    &base, sizeof (base));
8163941Svenki 		if (err !=  PICL_SUCCESS)
8173941Svenki 			break;
8183941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE,
8194669Sfw157321 		    &size, sizeof (size));
8203941Svenki 		if (err !=  PICL_SUCCESS)
8213941Svenki 			break;
8223941Svenki 		err = picl_get_propval_by_name(nodeh,
8234669Sfw157321 		    PICL_PROP_INTERLEAVE_FACTOR, &ifactor,
8244669Sfw157321 		    sizeof (ifactor));
8253941Svenki 		if (err !=  PICL_SUCCESS)
8263941Svenki 			break;
8275544Sfw157321 		log_printf("0x%-13llx", base);
8283941Svenki 		print_memory_segment_size(size);
8295544Sfw157321 		log_printf("%-12lld", ifactor);
8304669Sfw157321 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
8314669Sfw157321 		    &nodeh, sizeof (nodeh));
8324669Sfw157321 		if (err ==  PICL_SUCCESS)
8334669Sfw157321 			print_memory_segment_contain(nodeh);
8343941Svenki 		log_printf("\n");
8353941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
8364669Sfw157321 		    sizeof (picl_nodehdl_t));
8373941Svenki 	}
8383941Svenki 
8393941Svenki 	return (PICL_WALK_CONTINUE);
8403941Svenki }
8413941Svenki 
8423941Svenki /*ARGSUSED*/
8433941Svenki void
8443941Svenki sun4v_display_memory_conf(picl_nodehdl_t plafh)
8453941Svenki {
8465544Sfw157321 	char *fmt = "%-14s %-8s %-11s %-8s %-s";
8473941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
8484669Sfw157321 	    NULL, sun4v_memory_conf_callback);
8493941Svenki 	if (class_node_found == 0)
8503941Svenki 		return;
8513941Svenki 	log_printf("\n");
8525544Sfw157321 	log_printf("=======================");
8535544Sfw157321 	log_printf(" Physical Memory Configuration ");
8545544Sfw157321 	log_printf("========================");
8553941Svenki 	log_printf("\n");
8563941Svenki 	log_printf("Segment Table:\n");
8574669Sfw157321 	log_printf(
8585544Sfw157321 	    "--------------------------------------------------------------\n");
8595544Sfw157321 	log_printf(fmt, "Base", "Segment", "Interleave", "Bank", "Contains", 0);
8605544Sfw157321 	log_printf("\n");
8615544Sfw157321 	log_printf(fmt, "Address", "Size", "Factor", "Size", "Modules", 0);
8623941Svenki 	log_printf("\n");
8634669Sfw157321 	log_printf(
8645544Sfw157321 	    "--------------------------------------------------------------\n");
8653941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
8664669Sfw157321 	    NULL, sun4v_memory_conf_callback);
8671708Sstevel }
8681708Sstevel 
8691708Sstevel void
8701708Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh)
8711708Sstevel {
8725544Sfw157321 	char *fmt = "%-6s %-9s %-22s %-6s";
8731708Sstevel 
8741708Sstevel 	/*
8751708Sstevel 	 * Display the table header for CPUs . Then display the CPU
8761708Sstevel 	 * frequency, cache size, and processor revision of all cpus.
8771708Sstevel 	 */
8781708Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
8794669Sfw157321 	    "\n"
8805544Sfw157321 	    "================================"
8815544Sfw157321 	    " Virtual CPUs "
8825544Sfw157321 	    "================================"
8834669Sfw157321 	    "\n"
8844669Sfw157321 	    "\n"));
8851708Sstevel 	log_printf("\n");
8865544Sfw157321 	log_printf(fmt, "CPU ID", "Frequency", "Implementation",
8875544Sfw157321 	    "Status", 0);
8881708Sstevel 	log_printf("\n");
8895544Sfw157321 	log_printf(fmt, "------", "---------",
8905544Sfw157321 	    "----------------------", "-------", 0);
8911708Sstevel 	log_printf("\n");
8921708Sstevel 
8935544Sfw157321 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU,
8945544Sfw157321 	    sun4v_display_cpus);
8951708Sstevel }
8961708Sstevel 
8971708Sstevel /*
8981708Sstevel  * Display the CPUs present on this board.
8991708Sstevel  */
9001708Sstevel /*ARGSUSED*/
9011708Sstevel int
9021708Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
9031708Sstevel {
9041708Sstevel 	int status;
9053941Svenki 	picl_prophdl_t proph;
9063941Svenki 	picl_prophdl_t tblh;
9073941Svenki 	picl_prophdl_t rowproph;
9081708Sstevel 	picl_propinfo_t propinfo;
9093941Svenki 	int *int_value;
9105028Sfw157321 	int cpuid;
9113941Svenki 	char *comp_value;
9123941Svenki 	char *no_prop_value = "   ";
9133941Svenki 	char freq_str[MAXSTRLEN];
9145028Sfw157321 	char state[MAXSTRLEN];
9151708Sstevel 
9161708Sstevel 	/*
9171708Sstevel 	 * Get cpuid property and print it and the NAC name
9181708Sstevel 	 */
9195544Sfw157321 	status = picl_get_propinfo_by_name(cpuh, OBP_PROP_CPUID, &propinfo,
9205544Sfw157321 	    &proph);
9211708Sstevel 	if (status == PICL_SUCCESS) {
9221708Sstevel 		status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
9231708Sstevel 		if (status != PICL_SUCCESS) {
9245544Sfw157321 			log_printf("%-7s", no_prop_value);
9251708Sstevel 		} else {
9265544Sfw157321 			log_printf("%-7d", cpuid);
9271708Sstevel 		}
9281708Sstevel 	} else {
9295544Sfw157321 		log_printf("%-7s", no_prop_value);
9301708Sstevel 	}
9311708Sstevel 
9321708Sstevel clock_freq:
9331708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
9344669Sfw157321 	    &proph);
9351708Sstevel 	if (status == PICL_SUCCESS) {
9361708Sstevel 		int_value = malloc(propinfo.size);
9371708Sstevel 		if (int_value == NULL) {
9385544Sfw157321 			log_printf("%-10s", no_prop_value);
9391708Sstevel 			goto compatible;
9401708Sstevel 		}
9411708Sstevel 		status = picl_get_propval(proph, int_value, propinfo.size);
9421708Sstevel 		if (status != PICL_SUCCESS) {
9435544Sfw157321 			log_printf("%-10s", no_prop_value);
9441708Sstevel 		} else {
9451708Sstevel 			/* Running frequency */
9461708Sstevel 			(void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
9471708Sstevel 			    CLK_FREQ_TO_MHZ(*int_value));
9485544Sfw157321 			log_printf("%-10s", freq_str);
9491708Sstevel 		}
9501708Sstevel 		free(int_value);
9511708Sstevel 	} else
9525544Sfw157321 		log_printf("%-10s", no_prop_value);
9531708Sstevel 
9541708Sstevel compatible:
9551708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
9564669Sfw157321 	    &proph);
9571708Sstevel 	if (status == PICL_SUCCESS) {
9581708Sstevel 		if (propinfo.type == PICL_PTYPE_CHARSTRING) {
9591708Sstevel 			/*
9601708Sstevel 			 * Compatible Property only has 1 value
9611708Sstevel 			 */
9621708Sstevel 			comp_value = malloc(propinfo.size);
9631708Sstevel 			if (comp_value == NULL) {
9645544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9655028Sfw157321 				goto state;
9661708Sstevel 			}
9671708Sstevel 			status = picl_get_propval(proph, comp_value,
9684669Sfw157321 			    propinfo.size);
9693941Svenki 			if (status != PICL_SUCCESS)
9705544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9713941Svenki 			else
9725544Sfw157321 				log_printf("%-23s", comp_value, 0);
9733941Svenki 			free(comp_value);
9741708Sstevel 		} else if (propinfo.type == PICL_PTYPE_TABLE) {
9751708Sstevel 			/*
9761708Sstevel 			 * Compatible Property has multiple values
9771708Sstevel 			 */
9781708Sstevel 			status = picl_get_propval(proph, &tblh, propinfo.size);
9791708Sstevel 			if (status != PICL_SUCCESS) {
9805544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9815028Sfw157321 				goto state;
9821708Sstevel 			}
9831708Sstevel 			status = picl_get_next_by_row(tblh, &rowproph);
9841708Sstevel 			if (status != PICL_SUCCESS) {
9855544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9865028Sfw157321 				goto state;
9871708Sstevel 			}
9881708Sstevel 
9891708Sstevel 			status = picl_get_propinfo(rowproph, &propinfo);
9901708Sstevel 			if (status != PICL_SUCCESS) {
9915544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9925028Sfw157321 				goto state;
9931708Sstevel 			}
9941708Sstevel 
9951708Sstevel 			comp_value = malloc(propinfo.size);
9961708Sstevel 			if (comp_value == NULL) {
9975544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9985028Sfw157321 				goto state;
9991708Sstevel 			}
10001708Sstevel 			status = picl_get_propval(rowproph, comp_value,
10014669Sfw157321 			    propinfo.size);
10023941Svenki 			if (status != PICL_SUCCESS)
10035544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
10043941Svenki 			else
10055544Sfw157321 				log_printf("%-23s", comp_value, 0);
10061708Sstevel 			free(comp_value);
10071708Sstevel 		}
10081708Sstevel 	} else
10095544Sfw157321 		log_printf("%-23s", no_prop_value, 0);
10101708Sstevel 
10115028Sfw157321 state:
10125028Sfw157321 	status = picl_get_propinfo_by_name(cpuh, PICL_PROP_STATE,
10135028Sfw157321 	    &propinfo, &proph);
10141708Sstevel 	if (status == PICL_SUCCESS) {
10155028Sfw157321 		status = picl_get_propval(proph, state, sizeof (state));
10161708Sstevel 		if (status != PICL_SUCCESS) {
10173941Svenki 			log_printf("%-9s", no_prop_value);
10181708Sstevel 		} else {
10195028Sfw157321 			log_printf("%-9s", state);
10201708Sstevel 		}
10211708Sstevel 	} else
10223941Svenki 		log_printf("%-9s", no_prop_value);
10231708Sstevel 
10241708Sstevel done:
10251708Sstevel 	log_printf("\n");
10261708Sstevel 	return (PICL_WALK_CONTINUE);
10271708Sstevel }
10281708Sstevel 
10291708Sstevel void
10301708Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
10311708Sstevel {
10321708Sstevel #ifdef	lint
10331708Sstevel 	flag = flag;
10341708Sstevel 	root = root;
10351708Sstevel 	plafh = plafh;
10361708Sstevel #endif
10371708Sstevel 	/*
10381708Sstevel 	 * This function is intentionally empty
10391708Sstevel 	 */
10401708Sstevel }
10411708Sstevel 
10421708Sstevel void
10431708Sstevel display_boardnum(int num)
10441708Sstevel {
10451708Sstevel 	log_printf("%2d   ", num, 0);
10461708Sstevel }
10473941Svenki 
10485547Smb158278 static int
10493941Svenki sun4v_disp_env_status()
10503941Svenki {
10515547Smb158278 	int	exit_code = 0;
10525547Smb158278 
10533941Svenki 	if (phyplatformh == 0)
10545547Smb158278 		return (0);
10553941Svenki 	log_printf("\n");
10563941Svenki 	log_printf("============================");
10573941Svenki 	log_printf(" Environmental Status ");
10583941Svenki 	log_printf("============================");
10593941Svenki 	log_printf("\n");
10603941Svenki 
10613941Svenki 	class_node_found = 0;
10623941Svenki 	all_status_ok = 1;
10633941Svenki 	sun4v_env_print_fan_sensors();
10645547Smb158278 	exit_code |= (!all_status_ok);
10653941Svenki 
10663941Svenki 	class_node_found = 0;
10673941Svenki 	all_status_ok = 1;
10683941Svenki 	sun4v_env_print_fan_indicators();
10695547Smb158278 	exit_code |= (!all_status_ok);
10703941Svenki 
10713941Svenki 	class_node_found = 0;
10723941Svenki 	all_status_ok = 1;
10733941Svenki 	sun4v_env_print_temp_sensors();
10745547Smb158278 	exit_code |= (!all_status_ok);
10753941Svenki 
10763941Svenki 	class_node_found = 0;
10773941Svenki 	all_status_ok = 1;
10783941Svenki 	sun4v_env_print_temp_indicators();
10795547Smb158278 	exit_code |= (!all_status_ok);
10803941Svenki 
10813941Svenki 	class_node_found = 0;
10823941Svenki 	all_status_ok = 1;
10833941Svenki 	sun4v_env_print_current_sensors();
10845547Smb158278 	exit_code |= (!all_status_ok);
10853941Svenki 
10863941Svenki 	class_node_found = 0;
10873941Svenki 	all_status_ok = 1;
10883941Svenki 	sun4v_env_print_current_indicators();
10895547Smb158278 	exit_code |= (!all_status_ok);
10903941Svenki 
10913941Svenki 	class_node_found = 0;
10923941Svenki 	all_status_ok = 1;
10933941Svenki 	sun4v_env_print_voltage_sensors();
10945547Smb158278 	exit_code |= (!all_status_ok);
10953941Svenki 
10963941Svenki 	class_node_found = 0;
10973941Svenki 	all_status_ok = 1;
10983941Svenki 	sun4v_env_print_voltage_indicators();
10995547Smb158278 	exit_code |= (!all_status_ok);
11003941Svenki 
11013941Svenki 	class_node_found = 0;
11025547Smb158278 	all_status_ok = 1;
1103*8574SJason.Beloro@Sun.COM 	sun4v_env_print_humidity_sensors();
1104*8574SJason.Beloro@Sun.COM 	exit_code |= (!all_status_ok);
1105*8574SJason.Beloro@Sun.COM 
1106*8574SJason.Beloro@Sun.COM 	class_node_found = 0;
1107*8574SJason.Beloro@Sun.COM 	all_status_ok = 1;
1108*8574SJason.Beloro@Sun.COM 	sun4v_env_print_humidity_indicators();
1109*8574SJason.Beloro@Sun.COM 	exit_code |= (!all_status_ok);
1110*8574SJason.Beloro@Sun.COM 
1111*8574SJason.Beloro@Sun.COM 	class_node_found = 0;
1112*8574SJason.Beloro@Sun.COM 	all_status_ok = 1;
11133941Svenki 	sun4v_env_print_LEDs();
11145547Smb158278 	exit_code |= (!all_status_ok);
11153941Svenki 
11163941Svenki 	class_node_found = 0;
11173941Svenki 	all_status_ok = 1;
11183941Svenki 	sun4v_print_fru_status();
11195547Smb158278 	exit_code |= (!all_status_ok);
11203941Svenki 
11213941Svenki 	class_node_found = 0;
11223941Svenki 	sun4v_print_fw_rev();
11233941Svenki 
11245436Sfw157321 	class_node_found = 0;
11255436Sfw157321 	sun4v_print_openprom_rev();
11265436Sfw157321 
11273941Svenki 	sun4v_print_chassis_serial_no();
11285547Smb158278 
11295547Smb158278 	return (exit_code);
11303941Svenki }
11313941Svenki 
11323941Svenki /*ARGSUSED*/
11333941Svenki static int
11343941Svenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args)
11353941Svenki {
11363941Svenki 	char val[PICL_PROPNAMELEN_MAX];
11373941Svenki 	picl_nodehdl_t parenth;
11383941Svenki 	char *names[PARENT_NAMES];
11394802Sfw157321 	char *base_units[PICL_PROPNAMELEN_MAX];
11403941Svenki 	char *loc;
11413941Svenki 	int i;
11423941Svenki 	char *prop;
11433941Svenki 	picl_errno_t err;
11445436Sfw157321 	int32_t lo_warning, lo_shutdown, lo_poweroff;
11455436Sfw157321 	int32_t hi_warning, hi_shutdown, hi_poweroff;
11463941Svenki 	int32_t current_val;
11474802Sfw157321 	int32_t exponent;
11484802Sfw157321 	double display_val;
11494928Sfw157321 	typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
11504928Sfw157321 	    SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
11514928Sfw157321 	sensor_status_t sensor_status = SENSOR_OK;
11523941Svenki 
11533941Svenki 	if (class_node_found == 0) {
11543941Svenki 		class_node_found = 1;
11553941Svenki 		return (PICL_WALK_TERMINATE);
11563941Svenki 	}
11573941Svenki 
11584928Sfw157321 	prop = (char *)args;
11594928Sfw157321 	if (!prop) {
11604928Sfw157321 		sensor_status = SENSOR_UNKNOWN;
11614928Sfw157321 		all_status_ok = 0;
11624928Sfw157321 	} else {
11633941Svenki 		err = picl_get_propval_by_name(nodeh,
11644669Sfw157321 		    PICL_PROP_OPERATIONAL_STATUS, val,
11654669Sfw157321 		    sizeof (val));
11663941Svenki 		if (err == PICL_SUCCESS) {
11673941Svenki 			if (strcmp(val, "disabled") == 0) {
11684928Sfw157321 				sensor_status = SENSOR_DISABLED;
11694928Sfw157321 			}
11704928Sfw157321 		}
11714928Sfw157321 	}
11724928Sfw157321 
11734928Sfw157321 	if (sensor_status != SENSOR_DISABLED &&
11744928Sfw157321 	    sensor_status != SENSOR_UNKNOWN) {
11754928Sfw157321 		if (picl_get_propval_by_name(nodeh, prop, &current_val,
11764928Sfw157321 		    sizeof (current_val)) != PICL_SUCCESS) {
11774928Sfw157321 			sensor_status = SENSOR_UNKNOWN;
11785436Sfw157321 		} else {
11795436Sfw157321 			if (picl_get_propval_by_name(nodeh,
11805436Sfw157321 			    PICL_PROP_LOW_WARNING,
11815436Sfw157321 			    &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS)
11825436Sfw157321 				lo_warning = INVALID_THRESHOLD;
11835436Sfw157321 			if (picl_get_propval_by_name(nodeh,
11845436Sfw157321 			    PICL_PROP_LOW_SHUTDOWN,
11855436Sfw157321 			    &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS)
11865436Sfw157321 				lo_shutdown = INVALID_THRESHOLD;
11875436Sfw157321 			if (picl_get_propval_by_name(nodeh,
11885436Sfw157321 			    PICL_PROP_LOW_POWER_OFF,
11895436Sfw157321 			    &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS)
11905436Sfw157321 				lo_poweroff = INVALID_THRESHOLD;
11915436Sfw157321 			if (picl_get_propval_by_name(nodeh,
11925436Sfw157321 			    PICL_PROP_HIGH_WARNING,
11935436Sfw157321 			    &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS)
11945436Sfw157321 				hi_warning = INVALID_THRESHOLD;
11955436Sfw157321 			if (picl_get_propval_by_name(nodeh,
11965436Sfw157321 			    PICL_PROP_HIGH_SHUTDOWN,
11975436Sfw157321 			    &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS)
11985436Sfw157321 				hi_shutdown = INVALID_THRESHOLD;
11995436Sfw157321 			if (picl_get_propval_by_name(nodeh,
12005436Sfw157321 			    PICL_PROP_HIGH_POWER_OFF,
12015436Sfw157321 			    &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS)
12025436Sfw157321 				hi_poweroff = INVALID_THRESHOLD;
12034928Sfw157321 
12045436Sfw157321 			if ((lo_poweroff != INVALID_THRESHOLD &&
12055436Sfw157321 			    current_val <= lo_poweroff) ||
12065436Sfw157321 			    (hi_poweroff != INVALID_THRESHOLD &&
12075436Sfw157321 			    current_val >= hi_poweroff)) {
12085436Sfw157321 				sensor_status = SENSOR_FAILED;
12095436Sfw157321 			} else if ((lo_shutdown != INVALID_THRESHOLD &&
12105436Sfw157321 			    current_val <= lo_shutdown) ||
12115436Sfw157321 			    (hi_shutdown != INVALID_THRESHOLD &&
12125436Sfw157321 			    current_val >= hi_shutdown)) {
12135436Sfw157321 				sensor_status = SENSOR_FAILED;
12145436Sfw157321 			} else if ((lo_warning != INVALID_THRESHOLD &&
12155436Sfw157321 			    current_val <= lo_warning) ||
12165436Sfw157321 			    (hi_warning != INVALID_THRESHOLD &&
12175436Sfw157321 			    current_val >= hi_warning)) {
12185436Sfw157321 				sensor_status = SENSOR_WARN;
12195436Sfw157321 			} else {
12205436Sfw157321 				sensor_status = SENSOR_OK;
12215436Sfw157321 			}
12224928Sfw157321 		}
12234928Sfw157321 	}
12244928Sfw157321 
12254928Sfw157321 	if (syserrlog == 0) {
12264928Sfw157321 		if (sensor_status != SENSOR_OK && all_status_ok == 1) {
12273941Svenki 			all_status_ok = 0;
12283941Svenki 			return (PICL_WALK_TERMINATE);
12293941Svenki 		}
12304928Sfw157321 		if (sensor_status == SENSOR_OK) {
12314928Sfw157321 			return (PICL_WALK_CONTINUE);
12324928Sfw157321 		}
12333941Svenki 	}
12344928Sfw157321 
12354928Sfw157321 	/*
12364928Sfw157321 	 * If we're here then prtdiag was invoked with "-v" or we have
12374928Sfw157321 	 * a sensor that is beyond a threshold, so give them a book to
12384928Sfw157321 	 * read instead of the Cliff Notes.
12394928Sfw157321 	 */
12403941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
12414669Sfw157321 	    sizeof (parenth));
12423941Svenki 	if (err != PICL_SUCCESS) {
12433941Svenki 		log_printf("\n");
12443941Svenki 		return (PICL_WALK_CONTINUE);
12453941Svenki 	}
12464003Svivek 
12474928Sfw157321 	/* gather up the path name for the sensor */
12484928Sfw157321 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
12494928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++) {
12504928Sfw157321 			if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
12514928Sfw157321 			    NULL) {
12524928Sfw157321 				while (--i > -1)
12534928Sfw157321 					free(names[i]);
12544928Sfw157321 				free(loc);
12554928Sfw157321 				loc = NULL;
12564928Sfw157321 			}
12573941Svenki 		}
12584003Svivek 	}
12594928Sfw157321 	i = 0;
12604928Sfw157321 	if (loc != 0) {
12614928Sfw157321 		while (err == PICL_SUCCESS) {
12624928Sfw157321 			if (parenth == phyplatformh)
12634928Sfw157321 				break;
12644928Sfw157321 			err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
12654928Sfw157321 			    names[i++], PICL_PROPNAMELEN_MAX);
12664928Sfw157321 			if (err != PICL_SUCCESS) {
12674928Sfw157321 				i--;
12684928Sfw157321 				break;
12694928Sfw157321 			}
12704928Sfw157321 			if (i == PARENT_NAMES)
12714928Sfw157321 				break;
12724928Sfw157321 			err = picl_get_propval_by_name(parenth,
12734928Sfw157321 			    PICL_PROP_PARENT, &parenth, sizeof (parenth));
12744928Sfw157321 		}
12754928Sfw157321 		loc[0] = '\0';
12764928Sfw157321 		if (--i > -1) {
12774928Sfw157321 			(void) strlcat(loc, names[i],
12784928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
12794928Sfw157321 		}
12804928Sfw157321 		while (--i > -1) {
12814928Sfw157321 			(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
12824928Sfw157321 			    PARENT_NAMES);
12834928Sfw157321 			(void) strlcat(loc, names[i],
12844928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
12854928Sfw157321 		}
12865028Sfw157321 		log_printf("%-35s", loc);
12874928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++)
12884928Sfw157321 			free(names[i]);
12894928Sfw157321 		free(loc);
12904928Sfw157321 	} else {
12915028Sfw157321 		log_printf("%-35s", " ");
12923941Svenki 	}
12933941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
12944669Sfw157321 	    sizeof (val));
12953941Svenki 	if (err == PICL_SUCCESS)
12963941Svenki 		log_printf("%-15s", val);
12973941Svenki 
12984928Sfw157321 	/*
12994928Sfw157321 	 * Get the exponent if present, and do a little math so that
13004928Sfw157321 	 * if we need to we can print a normalized value for the
13014928Sfw157321 	 * sensor reading.
13024928Sfw157321 	 */
13034802Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT,
13044802Sfw157321 	    &exponent, sizeof (exponent)) != PICL_SUCCESS)
13054802Sfw157321 		exponent = 0;
13064802Sfw157321 	if (exponent == 0)
13074802Sfw157321 		display_val = (double)current_val;
13085436Sfw157321 	else {
13094802Sfw157321 		display_val = (double)current_val *
13104802Sfw157321 		    pow((double)10, (double)exponent);
13115436Sfw157321 
13125436Sfw157321 		/*
13135436Sfw157321 		 * Sometimes ILOM will scale a sensor reading but
13145436Sfw157321 		 * there will be nothing to the right of the decimal
13155436Sfw157321 		 * once that value is normalized.  Setting the
13165436Sfw157321 		 * exponent to zero will prevent the printf below
13175436Sfw157321 		 * from printing extraneous zeros.  Otherwise a
13185436Sfw157321 		 * negative exponent is used to set the precision
13195436Sfw157321 		 * for the printf.
13205436Sfw157321 		 */
13215436Sfw157321 		if ((int)display_val == display_val || exponent > 0)
13225436Sfw157321 			exponent = 0;
13235436Sfw157321 	}
13245436Sfw157321 
13254928Sfw157321 	err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS,
13264928Sfw157321 	    base_units, sizeof (base_units));
13274802Sfw157321 	if (err != PICL_SUCCESS)
13284802Sfw157321 		base_units[0] = '\0';
13293941Svenki 
13304928Sfw157321 	switch (sensor_status) {
13314928Sfw157321 	case SENSOR_FAILED:
13323941Svenki 		log_printf("%-s", "failed (");
13334802Sfw157321 		log_printf("%-.*f", abs(exponent), display_val);
13344802Sfw157321 		log_printf("%-s %s", base_units, ")");
13354928Sfw157321 		break;
13364928Sfw157321 	case SENSOR_WARN:
13373941Svenki 		log_printf("%-s", "warning (");
13384802Sfw157321 		log_printf("%-.*f", abs(exponent), display_val);
13394802Sfw157321 		log_printf("%-s %s", base_units, ")");
13404928Sfw157321 		break;
13414928Sfw157321 	case SENSOR_DISABLED:
13424928Sfw157321 		log_printf("%-s", "disabled");
13434928Sfw157321 		break;
13444928Sfw157321 	case SENSOR_OK:
13453941Svenki 		log_printf("%-s", "ok");
13464928Sfw157321 		break;
13474928Sfw157321 	default:
13484928Sfw157321 		log_printf("%-s", "unknown");
13494928Sfw157321 		break;
13504928Sfw157321 	}
13513941Svenki 
13523941Svenki 	log_printf("\n");
13533941Svenki 	return (PICL_WALK_CONTINUE);
13543941Svenki }
13553941Svenki 
13563941Svenki /*ARGSUSED*/
13573941Svenki static int
13583941Svenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args)
13593941Svenki {
13604928Sfw157321 	char current_val[PICL_PROPNAMELEN_MAX];
13614928Sfw157321 	char expected_val[PICL_PROPNAMELEN_MAX];
13624928Sfw157321 	char label[PICL_PROPNAMELEN_MAX];
13633941Svenki 	picl_nodehdl_t parenth;
13643941Svenki 	char *names[PARENT_NAMES];
13653941Svenki 	char *loc;
13663941Svenki 	int i = 0;
13673941Svenki 	char *prop = (char *)args;
13683941Svenki 	picl_errno_t err = PICL_SUCCESS;
13694928Sfw157321 	typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
13704928Sfw157321 	    SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
13714928Sfw157321 	sensor_status_t sensor_status = SENSOR_OK;
13723941Svenki 
13733941Svenki 	if (class_node_found == 0) {
13743941Svenki 		class_node_found = 1;
13753941Svenki 		return (PICL_WALK_TERMINATE);
13763941Svenki 	}
13774928Sfw157321 
13784928Sfw157321 	prop = (char *)args;
13794928Sfw157321 	if (!prop) {
13804928Sfw157321 		sensor_status = SENSOR_UNKNOWN;
13814928Sfw157321 		all_status_ok = 0;
13824928Sfw157321 	} else {
13833941Svenki 		err = picl_get_propval_by_name(nodeh,
13844928Sfw157321 		    PICL_PROP_OPERATIONAL_STATUS, current_val,
13854928Sfw157321 		    sizeof (current_val));
13863941Svenki 		if (err == PICL_SUCCESS) {
13874928Sfw157321 			if (strcmp(current_val, "disabled") == 0) {
13884928Sfw157321 				sensor_status = SENSOR_DISABLED;
13894928Sfw157321 			}
13904928Sfw157321 		}
13914928Sfw157321 	}
13924928Sfw157321 
13934928Sfw157321 	if (sensor_status != SENSOR_DISABLED &&
13944928Sfw157321 	    sensor_status != SENSOR_UNKNOWN) {
13954928Sfw157321 		if (picl_get_propval_by_name(nodeh, prop, &current_val,
13964928Sfw157321 		    sizeof (current_val)) != PICL_SUCCESS) {
13974928Sfw157321 			(void) strlcpy(current_val, "unknown",
13984928Sfw157321 			    sizeof (current_val));
13994928Sfw157321 			sensor_status = SENSOR_UNKNOWN;
14004928Sfw157321 		} else {
14014928Sfw157321 			if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED,
14024928Sfw157321 			    &expected_val, sizeof (expected_val)) !=
14034928Sfw157321 			    PICL_SUCCESS) {
14044928Sfw157321 				sensor_status = SENSOR_UNKNOWN;
14054928Sfw157321 			} else {
14064928Sfw157321 				if (strncmp(current_val, expected_val,
14074928Sfw157321 				    sizeof (current_val)) == 0) {
14084928Sfw157321 					sensor_status = SENSOR_OK;
14094928Sfw157321 				} else {
14104928Sfw157321 					sensor_status = SENSOR_FAILED;
14113941Svenki 				}
14124928Sfw157321 			}
14134928Sfw157321 		}
14144928Sfw157321 	}
14154928Sfw157321 
14164928Sfw157321 	if (syserrlog == 0) {
14174928Sfw157321 		if (sensor_status != SENSOR_OK && all_status_ok == 1) {
14183941Svenki 			all_status_ok = 0;
14193941Svenki 			return (PICL_WALK_TERMINATE);
14203941Svenki 		}
14214928Sfw157321 		if (sensor_status == SENSOR_OK) {
14224928Sfw157321 			return (PICL_WALK_CONTINUE);
14234928Sfw157321 		}
14243941Svenki 	}
14254928Sfw157321 
14264928Sfw157321 	/*
14274928Sfw157321 	 * If we're here then prtdiag was invoked with "-v" or we have
14284928Sfw157321 	 * a sensor that is beyond a threshold, so give them a book to
14294928Sfw157321 	 * read instead of the Cliff Notes.
14304928Sfw157321 	 */
14313941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
14324669Sfw157321 	    sizeof (parenth));
14333941Svenki 	if (err != PICL_SUCCESS) {
14343941Svenki 		log_printf("\n");
14353941Svenki 		return (PICL_WALK_CONTINUE);
14363941Svenki 	}
14374928Sfw157321 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
14384928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++) {
14394928Sfw157321 			if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
14404928Sfw157321 			    NULL) {
14414928Sfw157321 				while (--i > -1)
14424928Sfw157321 					free(names[i]);
14434928Sfw157321 				free(loc);
14444928Sfw157321 				loc = NULL;
14454928Sfw157321 			}
14463941Svenki 		}
14473941Svenki 	}
14484928Sfw157321 	i = 0;
14494928Sfw157321 	if (loc) {
14504928Sfw157321 		while (err == PICL_SUCCESS) {
14514928Sfw157321 			if (parenth == phyplatformh)
14524928Sfw157321 				break;
14534928Sfw157321 			err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
14544928Sfw157321 			    names[i++], PICL_PROPNAMELEN_MAX);
14554928Sfw157321 			if (err != PICL_SUCCESS) {
14564928Sfw157321 				i--;
14574928Sfw157321 				break;
14584928Sfw157321 			}
14594928Sfw157321 			if (i == PARENT_NAMES)
14604928Sfw157321 				break;
14614928Sfw157321 			err = picl_get_propval_by_name(parenth,
14624928Sfw157321 			    PICL_PROP_PARENT, &parenth, sizeof (parenth));
14634928Sfw157321 		}
14644928Sfw157321 		loc[0] = '\0';
14654928Sfw157321 		if (--i > -1) {
14664928Sfw157321 			(void) strlcat(loc, names[i],
14674928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
14684928Sfw157321 		}
14694928Sfw157321 		while (--i > -1) {
14704928Sfw157321 			(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
14714928Sfw157321 			    PARENT_NAMES);
14724928Sfw157321 			(void) strlcat(loc, names[i],
14734928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
14744928Sfw157321 		}
14755028Sfw157321 		log_printf("%-35s", loc);
14764928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++)
14774928Sfw157321 			free(names[i]);
14784928Sfw157321 		free(loc);
14794928Sfw157321 	} else {
14805028Sfw157321 		log_printf("%-35s", "");
14813941Svenki 	}
14824928Sfw157321 
14834928Sfw157321 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
14844928Sfw157321 	    sizeof (label));
14854928Sfw157321 	if (err != PICL_SUCCESS)
14864928Sfw157321 		(void) strlcpy(label, "", sizeof (label));
14874928Sfw157321 	log_printf("%-15s", label);
14884928Sfw157321 
14894928Sfw157321 	log_printf("%-8s", current_val);
14904928Sfw157321 
14913941Svenki 	log_printf("\n");
14923941Svenki 	return (PICL_WALK_CONTINUE);
14933941Svenki }
14943941Svenki 
14953941Svenki static void
14963941Svenki sun4v_env_print_fan_sensors()
14973941Svenki {
14985028Sfw157321 	char *fmt = "%-34s %-14s %-10s\n";
14993941Svenki 	/*
15003941Svenki 	 * If there isn't any fan sensor node, return now.
15013941Svenki 	 */
15023941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
15034928Sfw157321 	    PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED,
15044669Sfw157321 	    sun4v_env_print_sensor_callback);
15053941Svenki 	if (!class_node_found)
15063941Svenki 		return;
15073941Svenki 	log_printf("Fan sensors:\n");
15083941Svenki 	if (syserrlog == 0) {
15093941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
15104669Sfw157321 		    PICL_CLASS_RPM_SENSOR,
15114928Sfw157321 		    PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
15123941Svenki 		if (all_status_ok) {
15133941Svenki 			log_printf("All fan sensors are OK.\n");
15143941Svenki 			return;
15153941Svenki 		}
15163941Svenki 	}
15175028Sfw157321 	log_printf("-------------------------------------------------"
15185028Sfw157321 	    "-----------\n");
15193941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
15205028Sfw157321 	log_printf("-------------------------------------------------"
15215028Sfw157321 	    "-----------\n");
15223941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR,
15234669Sfw157321 	    PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
15243941Svenki }
15253941Svenki 
15263941Svenki static void
15273941Svenki sun4v_env_print_fan_indicators()
15283941Svenki {
15295028Sfw157321 	char *fmt = "%-34s %-14s %-10s\n";
15303941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
15314928Sfw157321 	    PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION,
15324669Sfw157321 	    sun4v_env_print_indicator_callback);
15333941Svenki 	if (!class_node_found)
15343941Svenki 		return;
15353941Svenki 	log_printf("\nFan indicators:\n");
15363941Svenki 	if (syserrlog == 0) {
15373941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
15384669Sfw157321 		    PICL_CLASS_RPM_INDICATOR,
15394928Sfw157321 		    (void *)PICL_PROP_CONDITION,
15404928Sfw157321 		    sun4v_env_print_indicator_callback);
15413941Svenki 		if (all_status_ok) {
15423941Svenki 			log_printf("All fan indicators are OK.\n");
15433941Svenki 			return;
15443941Svenki 		}
15453941Svenki 	}
15465028Sfw157321 	log_printf("-------------------------------------------------"
15475028Sfw157321 	    "-----------\n");
15483941Svenki 	log_printf(fmt, "Location", "Sensor", "Condition", 0);
15495028Sfw157321 	log_printf("-------------------------------------------------"
15505028Sfw157321 	    "-----------\n");
15513941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR,
15524802Sfw157321 	    (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback);
15533941Svenki }
15543941Svenki 
15553941Svenki static void
15563941Svenki sun4v_env_print_temp_sensors()
15573941Svenki {
15585028Sfw157321 	char *fmt = "%-34s %-14s %-10s\n";
15593941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
15604669Sfw157321 	    PICL_CLASS_TEMPERATURE_SENSOR,
15614669Sfw157321 	    (void *)PICL_PROP_TEMPERATURE,
15624669Sfw157321 	    sun4v_env_print_sensor_callback);
15633941Svenki 	if (!class_node_found)
15643941Svenki 		return;
15653941Svenki 
15663941Svenki 	log_printf("\nTemperature sensors:\n");
15673941Svenki 	if (syserrlog == 0) {
15683941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
15694669Sfw157321 		    PICL_CLASS_TEMPERATURE_SENSOR,
15704928Sfw157321 		    PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
15713941Svenki 		if (all_status_ok) {
15723941Svenki 			log_printf("All temperature sensors are OK.\n");
15733941Svenki 			return;
15743941Svenki 		}
15753941Svenki 	}
15765028Sfw157321 	log_printf("-------------------------------------------------"
15775028Sfw157321 	    "-----------\n");
15783941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
15795028Sfw157321 	log_printf("-------------------------------------------------"
15805028Sfw157321 	    "-----------\n");
15813941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
15824669Sfw157321 	    PICL_CLASS_TEMPERATURE_SENSOR,
15834669Sfw157321 	    (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
15843941Svenki }
15853941Svenki 
15863941Svenki static void
15873941Svenki sun4v_env_print_temp_indicators()
15883941Svenki {
15895028Sfw157321 	char *fmt = "%-34s %-14s %-8s\n";
15903941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
15914669Sfw157321 	    PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION,
15924669Sfw157321 	    sun4v_env_print_indicator_callback);
15933941Svenki 	if (!class_node_found)
15943941Svenki 		return;
15953941Svenki 	log_printf("\nTemperature indicators:\n");
15963941Svenki 	if (syserrlog == 0) {
15973941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
15984928Sfw157321 		    PICL_CLASS_TEMPERATURE_INDICATOR,
15994928Sfw157321 		    (void *)PICL_PROP_CONDITION,
16004669Sfw157321 		    sun4v_env_print_indicator_callback);
16013941Svenki 		if (all_status_ok) {
16023941Svenki 			log_printf("All temperature indicators are OK.\n");
16033941Svenki 			return;
16043941Svenki 		}
16053941Svenki 	}
16065028Sfw157321 	log_printf("-------------------------------------------------"
16075028Sfw157321 	    "-----------\n");
16083941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
16095028Sfw157321 	log_printf("-------------------------------------------------"
16105028Sfw157321 	    "-----------\n");
16113941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
16124669Sfw157321 	    PICL_CLASS_TEMPERATURE_INDICATOR,
16134669Sfw157321 	    (void *)PICL_PROP_CONDITION,
16144669Sfw157321 	    sun4v_env_print_indicator_callback);
16153941Svenki }
16163941Svenki 
16173941Svenki static void
16183941Svenki sun4v_env_print_current_sensors()
16193941Svenki {
16205028Sfw157321 	char *fmt = "%-34s %-14s %-10s\n";
16213941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR,
16224669Sfw157321 	    (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
16233941Svenki 	if (!class_node_found)
16243941Svenki 		return;
16253941Svenki 	log_printf("\nCurrent sensors:\n");
16263941Svenki 	if (syserrlog == 0) {
16273941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
16284669Sfw157321 		    PICL_CLASS_CURRENT_SENSOR,
16294928Sfw157321 		    PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
16303941Svenki 		if (all_status_ok) {
16313941Svenki 			log_printf("All current sensors are OK.\n");
16323941Svenki 			return;
16333941Svenki 		}
16343941Svenki 	}
16355028Sfw157321 	log_printf("-------------------------------------------------"
16365028Sfw157321 	    "-----------\n");
16373941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
16385028Sfw157321 	log_printf("-------------------------------------------------"
16395028Sfw157321 	    "-----------\n");
16403941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
16414669Sfw157321 	    PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
16424669Sfw157321 	    sun4v_env_print_sensor_callback);
16433941Svenki }
16443941Svenki 
16453941Svenki static void
16463941Svenki sun4v_env_print_current_indicators()
16473941Svenki {
16485028Sfw157321 	char *fmt = "%-34s %-14s %-8s\n";
16493941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
16504669Sfw157321 	    PICL_CLASS_CURRENT_INDICATOR,
16514669Sfw157321 	    (void *)PICL_PROP_CONDITION,
16524669Sfw157321 	    sun4v_env_print_indicator_callback);
16533941Svenki 	if (!class_node_found)
16543941Svenki 		return;
16553941Svenki 	log_printf("\nCurrent indicators:\n");
16563941Svenki 	if (syserrlog == 0) {
16573941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
16584928Sfw157321 		    PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION,
16594669Sfw157321 		    sun4v_env_print_indicator_callback);
16603941Svenki 		if (all_status_ok) {
16613941Svenki 			log_printf("All current indicators are OK.\n");
16623941Svenki 			return;
16633941Svenki 		}
16643941Svenki 	}
16655028Sfw157321 	log_printf("-------------------------------------------------"
16665028Sfw157321 	    "-----------\n");
16673941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
16685028Sfw157321 	log_printf("-------------------------------------------------"
16695028Sfw157321 	    "-----------\n");
16703941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
16714669Sfw157321 	    PICL_CLASS_CURRENT_INDICATOR,
16724669Sfw157321 	    (void *)PICL_PROP_CONDITION,
16734669Sfw157321 	    sun4v_env_print_indicator_callback);
16743941Svenki }
16753941Svenki 
16763941Svenki static void
16773941Svenki sun4v_env_print_voltage_sensors()
16783941Svenki {
16795028Sfw157321 	char *fmt = "%-34s %-14s %-10s\n";
16803941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
16814669Sfw157321 	    PICL_CLASS_VOLTAGE_SENSOR,
16824669Sfw157321 	    PICL_PROP_VOLTAGE,
16834669Sfw157321 	    sun4v_env_print_sensor_callback);
16843941Svenki 	if (!class_node_found)
16853941Svenki 		return;
16863941Svenki 	log_printf("\nVoltage sensors:\n");
16873941Svenki 	if (syserrlog == 0) {
16883941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
16894669Sfw157321 		    PICL_CLASS_VOLTAGE_SENSOR,
16904928Sfw157321 		    PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback);
16913941Svenki 		if (all_status_ok) {
16923941Svenki 			log_printf("All voltage sensors are OK.\n");
16933941Svenki 			return;
16943941Svenki 		}
16953941Svenki 	}
16965028Sfw157321 	log_printf("-------------------------------------------------"
16975028Sfw157321 	    "-----------\n");
16983941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
16995028Sfw157321 	log_printf("-------------------------------------------------"
17005028Sfw157321 	    "-----------\n");
17013941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
17024669Sfw157321 	    PICL_CLASS_VOLTAGE_SENSOR,
17034669Sfw157321 	    (void *)PICL_PROP_VOLTAGE,
17044669Sfw157321 	    sun4v_env_print_sensor_callback);
17053941Svenki }
17063941Svenki 
17073941Svenki static void
17083941Svenki sun4v_env_print_voltage_indicators()
17093941Svenki {
17105028Sfw157321 	char *fmt = "%-34s %-14s %-8s\n";
17113941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
17124669Sfw157321 	    PICL_CLASS_VOLTAGE_INDICATOR,
17134669Sfw157321 	    (void *)PICL_PROP_CONDITION,
17144669Sfw157321 	    sun4v_env_print_indicator_callback);
17153941Svenki 	if (!class_node_found)
17163941Svenki 		return;
17173941Svenki 	log_printf("\nVoltage indicators:\n");
17183941Svenki 	if (syserrlog == 0) {
17193941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
17204928Sfw157321 		    PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION,
17214669Sfw157321 		    sun4v_env_print_indicator_callback);
17223941Svenki 		if (all_status_ok) {
17233941Svenki 			log_printf("All voltage indicators are OK.\n");
17243941Svenki 			return;
17253941Svenki 		}
17263941Svenki 	}
17275028Sfw157321 	log_printf("-------------------------------------------------"
17285028Sfw157321 	    "-----------\n");
17293941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
17305028Sfw157321 	log_printf("-------------------------------------------------"
17315028Sfw157321 	    "-----------\n");
17323941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
17334669Sfw157321 	    PICL_CLASS_VOLTAGE_INDICATOR,
17344669Sfw157321 	    (void *)PICL_PROP_CONDITION,
17354669Sfw157321 	    sun4v_env_print_indicator_callback);
17363941Svenki }
17373941Svenki 
17383941Svenki static void
1739*8574SJason.Beloro@Sun.COM sun4v_env_print_humidity_sensors()
1740*8574SJason.Beloro@Sun.COM {
1741*8574SJason.Beloro@Sun.COM 	char *fmt = "%-34s %-14s %-10s\n";
1742*8574SJason.Beloro@Sun.COM 	(void) picl_walk_tree_by_class(phyplatformh,
1743*8574SJason.Beloro@Sun.COM 	    PICL_CLASS_HUMIDITY_SENSOR,
1744*8574SJason.Beloro@Sun.COM 	    (void *)PICL_PROP_HUMIDITY,
1745*8574SJason.Beloro@Sun.COM 	    sun4v_env_print_sensor_callback);
1746*8574SJason.Beloro@Sun.COM 	if (!class_node_found)
1747*8574SJason.Beloro@Sun.COM 		return;
1748*8574SJason.Beloro@Sun.COM 	log_printf("\nHumidity sensors:\n");
1749*8574SJason.Beloro@Sun.COM 	if (syserrlog == 0) {
1750*8574SJason.Beloro@Sun.COM 		(void) picl_walk_tree_by_class(phyplatformh,
1751*8574SJason.Beloro@Sun.COM 		    PICL_CLASS_HUMIDITY_SENSOR,
1752*8574SJason.Beloro@Sun.COM 		    PICL_PROP_HUMIDITY, sun4v_env_print_sensor_callback);
1753*8574SJason.Beloro@Sun.COM 		if (all_status_ok) {
1754*8574SJason.Beloro@Sun.COM 			log_printf("All humidity sensors are OK.\n");
1755*8574SJason.Beloro@Sun.COM 			return;
1756*8574SJason.Beloro@Sun.COM 		}
1757*8574SJason.Beloro@Sun.COM 	}
1758*8574SJason.Beloro@Sun.COM 	log_printf("-------------------------------------------------"
1759*8574SJason.Beloro@Sun.COM 	    "-----------\n");
1760*8574SJason.Beloro@Sun.COM 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1761*8574SJason.Beloro@Sun.COM 	log_printf("-------------------------------------------------"
1762*8574SJason.Beloro@Sun.COM 	    "-----------\n");
1763*8574SJason.Beloro@Sun.COM 	(void) picl_walk_tree_by_class(phyplatformh,
1764*8574SJason.Beloro@Sun.COM 	    PICL_CLASS_HUMIDITY_SENSOR,
1765*8574SJason.Beloro@Sun.COM 	    (void *)PICL_PROP_HUMIDITY,
1766*8574SJason.Beloro@Sun.COM 	    sun4v_env_print_sensor_callback);
1767*8574SJason.Beloro@Sun.COM }
1768*8574SJason.Beloro@Sun.COM 
1769*8574SJason.Beloro@Sun.COM static void
1770*8574SJason.Beloro@Sun.COM sun4v_env_print_humidity_indicators()
1771*8574SJason.Beloro@Sun.COM {
1772*8574SJason.Beloro@Sun.COM 	char *fmt = "%-34s %-14s %-8s\n";
1773*8574SJason.Beloro@Sun.COM 	(void) picl_walk_tree_by_class(phyplatformh,
1774*8574SJason.Beloro@Sun.COM 	    PICL_CLASS_HUMIDITY_INDICATOR,
1775*8574SJason.Beloro@Sun.COM 	    (void *)PICL_PROP_CONDITION,
1776*8574SJason.Beloro@Sun.COM 	    sun4v_env_print_indicator_callback);
1777*8574SJason.Beloro@Sun.COM 	if (!class_node_found)
1778*8574SJason.Beloro@Sun.COM 		return;
1779*8574SJason.Beloro@Sun.COM 	log_printf("\nHumidity indicators:\n");
1780*8574SJason.Beloro@Sun.COM 	if (syserrlog == 0) {
1781*8574SJason.Beloro@Sun.COM 		(void) picl_walk_tree_by_class(phyplatformh,
1782*8574SJason.Beloro@Sun.COM 		    PICL_CLASS_HUMIDITY_INDICATOR, (void *)PICL_PROP_CONDITION,
1783*8574SJason.Beloro@Sun.COM 		    sun4v_env_print_indicator_callback);
1784*8574SJason.Beloro@Sun.COM 		if (all_status_ok) {
1785*8574SJason.Beloro@Sun.COM 			log_printf("All humidity indicators are OK.\n");
1786*8574SJason.Beloro@Sun.COM 			return;
1787*8574SJason.Beloro@Sun.COM 		}
1788*8574SJason.Beloro@Sun.COM 	}
1789*8574SJason.Beloro@Sun.COM 	log_printf("-------------------------------------------------"
1790*8574SJason.Beloro@Sun.COM 	    "-----------\n");
1791*8574SJason.Beloro@Sun.COM 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
1792*8574SJason.Beloro@Sun.COM 	log_printf("-------------------------------------------------"
1793*8574SJason.Beloro@Sun.COM 	    "-----------\n");
1794*8574SJason.Beloro@Sun.COM 	(void) picl_walk_tree_by_class(phyplatformh,
1795*8574SJason.Beloro@Sun.COM 	    PICL_CLASS_HUMIDITY_INDICATOR,
1796*8574SJason.Beloro@Sun.COM 	    (void *)PICL_PROP_CONDITION,
1797*8574SJason.Beloro@Sun.COM 	    sun4v_env_print_indicator_callback);
1798*8574SJason.Beloro@Sun.COM }
1799*8574SJason.Beloro@Sun.COM 
1800*8574SJason.Beloro@Sun.COM static void
18013941Svenki sun4v_env_print_LEDs()
18023941Svenki {
18035028Sfw157321 	char *fmt = "%-34s %-14s %-8s\n";
18043941Svenki 	if (syserrlog == 0)
18053941Svenki 		return;
18063941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
18074669Sfw157321 	    (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
18083941Svenki 	if (!class_node_found)
18093941Svenki 		return;
18103941Svenki 	log_printf("\nLEDs:\n");
18115028Sfw157321 	log_printf("-------------------------------------------------"
18125028Sfw157321 	    "-----------\n");
18133941Svenki 	log_printf(fmt, "Location", "LED", "State", 0);
18145028Sfw157321 	log_printf("-------------------------------------------------"
18155028Sfw157321 	    "-----------\n");
18163941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
18174669Sfw157321 	    (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
18183941Svenki }
18193941Svenki 
18203941Svenki /*ARGSUSED*/
18213941Svenki static int
18223941Svenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args)
18233941Svenki {
18243941Svenki 	char label[PICL_PROPNAMELEN_MAX];
18253941Svenki 	char status[PICL_PROPNAMELEN_MAX];
18263941Svenki 	picl_errno_t err;
18273941Svenki 	picl_prophdl_t proph;
18283941Svenki 	picl_nodehdl_t parenth;
18293941Svenki 	char *names[PARENT_NAMES];
18303941Svenki 	char *loc;
18313941Svenki 	int i;
18323941Svenki 
18333941Svenki 	if (!class_node_found) {
18343941Svenki 		class_node_found = 1;
18353941Svenki 		return (PICL_WALK_TERMINATE);
18363941Svenki 	}
18373941Svenki 	err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph);
18383941Svenki 	if (err != PICL_SUCCESS)
18393941Svenki 		return (PICL_WALK_CONTINUE);
18403941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
18414669Sfw157321 	    sizeof (label));
18423941Svenki 	if (err != PICL_SUCCESS)
18433941Svenki 		return (PICL_WALK_CONTINUE);
18443941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
18454669Sfw157321 	    status, sizeof (status));
18463941Svenki 	if (err != PICL_SUCCESS)
18473941Svenki 		return (PICL_WALK_CONTINUE);
18483941Svenki 	if (syserrlog == 0) {
18493941Svenki 		if (strcmp(status, "disabled") == 0) {
18503941Svenki 			if (all_status_ok) {
18513941Svenki 				all_status_ok = 0;
18523941Svenki 				return (PICL_WALK_TERMINATE);
18533941Svenki 			}
18543941Svenki 		} else
18553941Svenki 			return (PICL_WALK_CONTINUE);
18563941Svenki 	}
18573941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
18584669Sfw157321 	    sizeof (parenth));
18593941Svenki 	if (err != PICL_SUCCESS) {
18603941Svenki 		log_printf("\n");
18613941Svenki 		return (PICL_WALK_CONTINUE);
18623941Svenki 	}
18633941Svenki 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
18643941Svenki 		return (PICL_WALK_TERMINATE);
18653941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
18663941Svenki 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
18673941Svenki 			while (--i > -1)
18683941Svenki 				free(names[i]);
18693941Svenki 			free(loc);
18703941Svenki 			return (PICL_WALK_TERMINATE);
18713941Svenki 		}
18723941Svenki 	i = 0;
18733941Svenki 	while (err == PICL_SUCCESS) {
18744802Sfw157321 		if (parenth == phyplatformh)
18753941Svenki 			break;
18763941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
18774669Sfw157321 		    names[i++], PICL_PROPNAMELEN_MAX);
18783941Svenki 		if (err != PICL_SUCCESS) {
18793941Svenki 			i--;
18803941Svenki 			break;
18813941Svenki 		}
18823941Svenki 		if (i == PARENT_NAMES)
18833941Svenki 			break;
18843941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
18854669Sfw157321 		    &parenth, sizeof (parenth));
18863941Svenki 	}
18873941Svenki 	loc[0] = '\0';
18884003Svivek 	if (--i > -1) {
18894003Svivek 		(void) strlcat(loc, names[i],
18904669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18914003Svivek 	}
18923941Svenki 	while (--i > -1) {
18934003Svivek 		(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18944003Svivek 		(void) strlcat(loc, names[i],
18954669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18963941Svenki 	}
18975028Sfw157321 	log_printf("%-35s", loc);
18983941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
18993941Svenki 		free(names[i]);
19003941Svenki 	free(loc);
19013941Svenki 	log_printf("%-10s", label);
19023941Svenki 	log_printf("%-9s", status);
19033941Svenki 	log_printf("\n");
19043941Svenki 	return (PICL_WALK_CONTINUE);
19053941Svenki }
19063941Svenki 
19073941Svenki static void
19083941Svenki sun4v_print_fru_status()
19093941Svenki {
19105028Sfw157321 	char *fmt = "%-34s %-9s %-8s\n";
19115436Sfw157321 
19123941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
19134669Sfw157321 	    sun4v_print_fru_status_callback);
19143941Svenki 	if (!class_node_found)
19153941Svenki 		return;
19165436Sfw157321 
19173941Svenki 	log_printf("\n");
19183941Svenki 	log_printf("============================");
19193941Svenki 	log_printf(" FRU Status ");
19203941Svenki 	log_printf("============================");
19213941Svenki 	log_printf("\n");
19223941Svenki 
19233941Svenki 	if (syserrlog == 0) {
19243941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
19254802Sfw157321 		    NULL, NULL,
19264669Sfw157321 		    sun4v_print_fru_status_callback);
19273941Svenki 		if (all_status_ok) {
19283941Svenki 			log_printf("All FRUs are enabled.\n");
19293941Svenki 			return;
19303941Svenki 		}
19313941Svenki 	}
19323941Svenki 	log_printf(fmt, "Location", "Name", "Status", 0);
19335028Sfw157321 	log_printf("------------------------------------------------------\n");
19344802Sfw157321 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
19354669Sfw157321 	    sun4v_print_fru_status_callback);
19363941Svenki }
19373941Svenki 
19383941Svenki /*ARGSUSED*/
19393941Svenki static int
19403941Svenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args)
19413941Svenki {
19423941Svenki 	char rev[PICL_PROPNAMELEN_MAX];
19433941Svenki 	picl_errno_t err;
19443941Svenki 
19453941Svenki 	if (!class_node_found) {
19463941Svenki 		class_node_found = 1;
19473941Svenki 		return (PICL_WALK_TERMINATE);
19483941Svenki 	}
19495436Sfw157321 
19503941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev,
19514669Sfw157321 	    sizeof (rev));
19523941Svenki 	if (err != PICL_SUCCESS)
19533941Svenki 		return (PICL_WALK_CONTINUE);
19543941Svenki 	if (strlen(rev) == 0)
19553941Svenki 		return (PICL_WALK_CONTINUE);
19565436Sfw157321 	log_printf("%s", rev);
19573941Svenki 	log_printf("\n");
19583941Svenki 	return (PICL_WALK_CONTINUE);
19593941Svenki }
19603941Svenki 
19613941Svenki static void
19623941Svenki sun4v_print_fw_rev()
19633941Svenki {
19643941Svenki 	if (syserrlog == 0)
19653941Svenki 		return;
19665436Sfw157321 
19673941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
19684669Sfw157321 	    sun4v_print_fw_rev_callback);
19693941Svenki 	if (!class_node_found)
19703941Svenki 		return;
19715436Sfw157321 
19723941Svenki 	log_printf("\n");
19733941Svenki 	log_printf("============================");
19743941Svenki 	log_printf(" FW Version ");
19753941Svenki 	log_printf("============================");
19763941Svenki 	log_printf("\n");
19775436Sfw157321 	log_printf("Version\n");
19785028Sfw157321 	log_printf("-------------------------------------------------"
19795028Sfw157321 	    "-----------\n");
19803941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
19814669Sfw157321 	    sun4v_print_fw_rev_callback);
19823941Svenki }
19833941Svenki 
19843941Svenki static void
19855436Sfw157321 sun4v_print_openprom_rev()
19865436Sfw157321 {
19875436Sfw157321 	if (syserrlog == 0)
19885436Sfw157321 		return;
19895436Sfw157321 
19905436Sfw157321 	(void) picl_walk_tree_by_class(rooth, "openprom", NULL,
19915436Sfw157321 	    openprom_callback);
19925436Sfw157321 	if (!class_node_found)
19935436Sfw157321 		return;
19945436Sfw157321 
19955436Sfw157321 	log_printf("\n");
19965436Sfw157321 	log_printf("======================");
19975436Sfw157321 	log_printf(" System PROM revisions ");
19985436Sfw157321 	log_printf("=======================");
19995436Sfw157321 	log_printf("\n");
20005436Sfw157321 	log_printf("Version\n");
20015436Sfw157321 	log_printf("-------------------------------------------------"
20025436Sfw157321 	    "-----------\n");
20035436Sfw157321 	(void) picl_walk_tree_by_class(rooth, "openprom", NULL,
20045436Sfw157321 	    openprom_callback);
20055436Sfw157321 }
20065436Sfw157321 
20075436Sfw157321 /*
20085436Sfw157321  * display the OBP and POST prom revisions (if present)
20095436Sfw157321  */
20105436Sfw157321 /* ARGSUSED */
20115436Sfw157321 static int
20125436Sfw157321 openprom_callback(picl_nodehdl_t openpromh, void *arg)
20135436Sfw157321 {
20145436Sfw157321 	picl_prophdl_t	proph;
20155436Sfw157321 	picl_prophdl_t	tblh;
20165436Sfw157321 	picl_prophdl_t	rowproph;
20175436Sfw157321 	picl_propinfo_t	pinfo;
20185436Sfw157321 	char		*prom_version = NULL;
20195436Sfw157321 	char		*obp_version = NULL;
20205436Sfw157321 	int		err;
20215436Sfw157321 
20225436Sfw157321 	if (!class_node_found) {
20235436Sfw157321 		class_node_found = 1;
20245436Sfw157321 		return (PICL_WALK_TERMINATE);
20255436Sfw157321 	}
20265436Sfw157321 
20275436Sfw157321 	err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION,
20285436Sfw157321 	    &pinfo, &proph);
20295436Sfw157321 	if (err == PICL_PROPNOTFOUND)
20305436Sfw157321 		return (PICL_WALK_TERMINATE);
20315436Sfw157321 	else if (err != PICL_SUCCESS)
20325436Sfw157321 		return (err);
20335436Sfw157321 
20345436Sfw157321 	/*
20355436Sfw157321 	 * If it's a table prop, the first element is OBP revision
20365436Sfw157321 	 * The second one is POST revision.
20375436Sfw157321 	 * If it's a charstring prop, the value will be only OBP revision
20385436Sfw157321 	 */
20395436Sfw157321 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
20405436Sfw157321 		prom_version = (char *)alloca(pinfo.size);
20415436Sfw157321 		if (prom_version == NULL)
20425436Sfw157321 			return (PICL_FAILURE);
20435436Sfw157321 		err = picl_get_propval(proph, prom_version, pinfo.size);
20445436Sfw157321 		if (err != PICL_SUCCESS)
20455436Sfw157321 			return (err);
20465436Sfw157321 		log_printf("%s\n", prom_version);
20475436Sfw157321 	}
20485436Sfw157321 
20495436Sfw157321 	if (pinfo.type != PICL_PTYPE_TABLE)	/* not supported type */
20505436Sfw157321 		return (PICL_WALK_TERMINATE);
20515436Sfw157321 
20525436Sfw157321 	err = picl_get_propval(proph, &tblh, pinfo.size);
20535436Sfw157321 	if (err != PICL_SUCCESS)
20545436Sfw157321 		return (err);
20555436Sfw157321 
20565436Sfw157321 	err = picl_get_next_by_row(tblh, &rowproph);
20575436Sfw157321 	if (err == PICL_SUCCESS) {
20585436Sfw157321 		/* get first row */
20595436Sfw157321 		err = picl_get_propinfo(rowproph, &pinfo);
20605436Sfw157321 		if (err != PICL_SUCCESS)
20615436Sfw157321 			return (err);
20625436Sfw157321 
20635436Sfw157321 		prom_version = (char *)alloca(pinfo.size);
20645436Sfw157321 		if (prom_version == NULL)
20655436Sfw157321 			return (PICL_FAILURE);
20665436Sfw157321 
20675436Sfw157321 		err = picl_get_propval(rowproph, prom_version, pinfo.size);
20685436Sfw157321 		if (err != PICL_SUCCESS)
20695436Sfw157321 			return (err);
20705436Sfw157321 		log_printf("%s\n", prom_version);
20715436Sfw157321 
20725436Sfw157321 		/* get second row */
20735436Sfw157321 		err = picl_get_next_by_col(rowproph, &rowproph);
20745436Sfw157321 		if (err == PICL_SUCCESS) {
20755436Sfw157321 			err = picl_get_propinfo(rowproph, &pinfo);
20765436Sfw157321 			if (err != PICL_SUCCESS)
20775436Sfw157321 				return (err);
20785436Sfw157321 
20795436Sfw157321 			obp_version = (char *)alloca(pinfo.size);
20805436Sfw157321 			if (obp_version == NULL)
20815436Sfw157321 				return (PICL_FAILURE);
20825436Sfw157321 			err = picl_get_propval(rowproph, obp_version,
20835436Sfw157321 			    pinfo.size);
20845436Sfw157321 			if (err != PICL_SUCCESS)
20855436Sfw157321 				return (err);
20865436Sfw157321 			log_printf("%s\n", obp_version);
20875436Sfw157321 		}
20885436Sfw157321 	}
20895436Sfw157321 
20905436Sfw157321 	return (PICL_WALK_TERMINATE);
20915436Sfw157321 }
20925436Sfw157321 
20935436Sfw157321 static void
20943941Svenki sun4v_print_chassis_serial_no()
20953941Svenki {
20963941Svenki 	char val[PICL_PROPNAMELEN_MAX];
20973941Svenki 	picl_errno_t err;
20983941Svenki 	if (syserrlog == 0 || chassish == 0)
20993941Svenki 		return;
21003941Svenki 
21013941Svenki 	log_printf("\n");
21026014Ssuha 	log_printf("Chassis Serial Number");
21033941Svenki 	log_printf("\n");
21043941Svenki 	log_printf("---------------------\n");
21053941Svenki 	err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER,
21064669Sfw157321 	    val, sizeof (val));
21073941Svenki 	if (err == PICL_SUCCESS)
21083941Svenki 		log_printf("%s", val);
21093941Svenki 	log_printf("\n");
21103941Svenki }
2111