xref: /onnv-gate/usr/src/lib/libprtdiag/common/display_sun4v.c (revision 10070:4d7f4e5aa1a4)
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 /*
228574SJason.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();
1098574SJason.Beloro@Sun.COM static void sun4v_env_print_humidity_sensors();
1108574SJason.Beloro@Sun.COM static void sun4v_env_print_humidity_indicators();
1113941Svenki static void sun4v_env_print_LEDs();
1123941Svenki static void sun4v_print_fru_status();
113*10070SBirva.Shah@Sun.COM static int is_fru_absent(picl_nodehdl_t);
1143941Svenki static void sun4v_print_fw_rev();
1153941Svenki static void sun4v_print_chassis_serial_no();
1165436Sfw157321 static int openprom_callback(picl_nodehdl_t openpromh, void *arg);
1175436Sfw157321 static void sun4v_print_openprom_rev();
1181708Sstevel 
1191708Sstevel int
1203941Svenki sun4v_display(Sys_tree *tree, Prom_node *root, int log,
1213941Svenki 	picl_nodehdl_t plafh)
1221708Sstevel {
1231708Sstevel 	void *value;		/* used for opaque PROM data */
1241708Sstevel 	struct mem_total memory_total;	/* Total memory in system */
1251708Sstevel 	struct grp_info grps;	/* Info on all groups in system */
1263941Svenki 	char machine[MAXSTRLEN];
1275547Smb158278 	int	exit_code = 0;
1283941Svenki 
1293941Svenki 	if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1)
1303941Svenki 		return (1);
1313941Svenki 	if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0)
1323941Svenki 		return (1);
1331708Sstevel 
1341708Sstevel 	sys_clk = -1;  /* System clock freq. (in MHz) */
1351708Sstevel 
1361708Sstevel 	/*
1371708Sstevel 	 * Now display the machine's configuration. We do this if we
1381708Sstevel 	 * are not logging.
1391708Sstevel 	 */
1401708Sstevel 	if (!logging) {
1411708Sstevel 		struct utsname uts_buf;
1421708Sstevel 
1431708Sstevel 		/*
1441708Sstevel 		 * Display system banner
1451708Sstevel 		 */
1461708Sstevel 		(void) uname(&uts_buf);
1471708Sstevel 
1483941Svenki 		log_printf(dgettext(TEXT_DOMAIN, "System Configuration:  "
1494669Sfw157321 		    "Sun Microsystems  %s %s\n"), uts_buf.machine,
1504669Sfw157321 		    get_prop_val(find_prop(root, "banner-name")), 0);
1511708Sstevel 
1521708Sstevel 		/* display system clock frequency */
1531708Sstevel 		value = get_prop_val(find_prop(root, "clock-frequency"));
1541708Sstevel 		if (value != NULL) {
1551708Sstevel 			sys_clk = ((*((int *)value)) + 500000) / 1000000;
1561708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, "System clock "
1574669Sfw157321 			    "frequency: %d MHz\n"), sys_clk, 0);
1581708Sstevel 		}
1591708Sstevel 
1601708Sstevel 		/* Display the Memory Size */
1611708Sstevel 		display_memorysize(tree, NULL, &grps, &memory_total);
1621708Sstevel 
1631708Sstevel 		/* Display the CPU devices */
1641708Sstevel 		sun4v_display_cpu_devices(plafh);
1651708Sstevel 
1661708Sstevel 		/* Display the Memory configuration */
1673941Svenki 		class_node_found = 0;
1683941Svenki 		sun4v_display_memory_conf(plafh);
1691708Sstevel 
1701708Sstevel 		/* Display all the IO cards. */
1711708Sstevel 		(void) sun4v_display_pci(plafh);
1723941Svenki 		sun4v_display_diaginfo((log || (logging)), root, plafh);
1731708Sstevel 
1743941Svenki 		if (picl_get_root(&rooth) != PICL_SUCCESS)
1753941Svenki 			return (1);
1765547Smb158278 
1775547Smb158278 		/*
1785547Smb158278 		 * The physical-platform node may be missing on systems with
1795547Smb158278 		 * older firmware so don't consider that an error.
1805547Smb158278 		 */
1813941Svenki 		if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM,
1824669Sfw157321 		    &phyplatformh) != PICL_SUCCESS)
1835547Smb158278 			return (0);
1843941Svenki 
1853941Svenki 		if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME,
1864669Sfw157321 		    PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
1874669Sfw157321 		    strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS)
1883941Svenki 			return (1);
1893941Svenki 
1903941Svenki 		syserrlog = log;
1915547Smb158278 		exit_code = sun4v_disp_env_status();
1923941Svenki 	}
1935547Smb158278 	return (exit_code);
1943941Svenki }
1953941Svenki 
1965819Sfw157321 /*
1975819Sfw157321  * The binding-name property encodes the bus type.
1985819Sfw157321  */
1993941Svenki static void
2003941Svenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card)
2013941Svenki {
2025819Sfw157321 	char val[PICL_PROPNAMELEN_MAX], *p, *q;
2035819Sfw157321 
2045819Sfw157321 	card->bus_type[0] = '\0';
2053941Svenki 
2065819Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, val,
2075819Sfw157321 	    sizeof (val)) == PICL_SUCCESS) {
2085819Sfw157321 		if (strstr(val, PICL_CLASS_PCIEX))
2094003Svivek 			(void) strlcpy(card->bus_type, "PCIE",
2104669Sfw157321 			    sizeof (card->bus_type));
2115819Sfw157321 		else if (strstr(val, PICL_CLASS_PCI))
2125819Sfw157321 			(void) strlcpy(card->bus_type, "PCIX",
2135819Sfw157321 			    sizeof (card->bus_type));
2145819Sfw157321 		else {
2155819Sfw157321 			/*
2165819Sfw157321 			 * Not perfect: process the binding-name until
2175819Sfw157321 			 * we encounter something that we don't think would
2185819Sfw157321 			 * be part of a bus type.  This may get confused a bit
2195819Sfw157321 			 * if a device or vendor id is encoded right after
2205819Sfw157321 			 * the bus class since there's no delimiter.  If the
2215819Sfw157321 			 * id number begins with a hex digit [abcdef] then
2225819Sfw157321 			 * this will become part of the bus type string
2235819Sfw157321 			 * reported by prtdiag.  This is all an effort to
2245819Sfw157321 			 * print something potentially useful for bus types
2255819Sfw157321 			 * other than PCI/PCIe.
2265819Sfw157321 			 *
2275819Sfw157321 			 * We do this because this code will get called for
2285819Sfw157321 			 * non-PCI class devices like the xaui (class sun4v.)
2295819Sfw157321 			 */
2305819Sfw157321 			if (strstr(val, "SUNW,") != NULL)
2315819Sfw157321 				p = strchr(val, ',') + 1;
2325819Sfw157321 			else
2335819Sfw157321 				p = val;
2345819Sfw157321 			q = p;
2355819Sfw157321 			while (*p != '\0') {
2365819Sfw157321 				if (isdigit((char)*p) || ispunct((char)*p)) {
2375819Sfw157321 					*p = '\0';
2385819Sfw157321 					break;
2395819Sfw157321 				}
2405819Sfw157321 				*p = (char)_toupper((int)*p);
2415819Sfw157321 				++p;
2425819Sfw157321 			}
2435819Sfw157321 			(void) strlcpy(card->bus_type, q,
2445819Sfw157321 			    sizeof (card->bus_type));
2455819Sfw157321 		}
2463941Svenki 	}
2473941Svenki }
2483941Svenki 
2495819Sfw157321 /*
2505819Sfw157321  * Fetch the Label property for this device.  If none is found then
2515819Sfw157321  * search all the siblings with the same device ID for a
2525819Sfw157321  * Label and return that Label.  The plug-in can only match the canonical
2535819Sfw157321  * path from the PRI with a specific devfs path.  So we take care of
2545819Sfw157321  * devices with multiple functions here.  A leaf device downstream of
2555819Sfw157321  * a bridge should fall out of here with PICL_PROPNOTFOUND, and the
2565819Sfw157321  * caller can walk back up the tree in search of the slot's Label.
2575819Sfw157321  */
2583941Svenki static picl_errno_t
2593941Svenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card)
2603941Svenki {
2613941Svenki 	char val[PICL_PROPNAMELEN_MAX];
2623941Svenki 	picl_errno_t err;
2635436Sfw157321 	picl_nodehdl_t pnodeh;
2645819Sfw157321 	uint32_t devid, sib_devid;
2655819Sfw157321 	int32_t instance;
2663941Svenki 
2675436Sfw157321 	/*
2685819Sfw157321 	 * If there's a Label at this node then return it - we're
2695819Sfw157321 	 * done.
2705436Sfw157321 	 */
2713941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
2724669Sfw157321 	    sizeof (val));
2735819Sfw157321 	if (err == PICL_SUCCESS) {
2745819Sfw157321 		(void) strlcpy(card->slot_str, val, sizeof (card->slot_str));
2755819Sfw157321 		return (err);
2765819Sfw157321 	} else if (err != PICL_PROPNOTFOUND)
2775819Sfw157321 		return (err);
2785819Sfw157321 
2795819Sfw157321 	/*
2805819Sfw157321 	 * At this point we're starting to extrapolate what the Label
2815819Sfw157321 	 * should be since there is none at this specific node.
2825819Sfw157321 	 * Note that until the value of "err" is overwritten in the
2835819Sfw157321 	 * loop below, its value should be PICL_PROPNOTFOUND.
2845819Sfw157321 	 */
2855819Sfw157321 
2865819Sfw157321 	/*
2875819Sfw157321 	 * The device must be attached, and we can figure that out if
2885819Sfw157321 	 * the instance number is present and is not equal to -1.
2895819Sfw157321 	 * This will prevent is from returning a Label for a sibling
2905819Sfw157321 	 * node when the node passed in would have a unique Label if the
2915819Sfw157321 	 * device were attached.  But if the device is downstream of a
2925819Sfw157321 	 * node with a Label then pci_callback() will still find that
2935819Sfw157321 	 * and use it.
2945819Sfw157321 	 */
2955819Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_INSTANCE, &instance,
2965819Sfw157321 	    sizeof (instance)) != PICL_SUCCESS)
2975819Sfw157321 		return (err);
2985819Sfw157321 	if (instance == -1)
2995819Sfw157321 		return (err);
3003941Svenki 
3015819Sfw157321 	/*
3025819Sfw157321 	 * Narrow the search to just the one device ID.
3035819Sfw157321 	 */
3045819Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_DEVICE_ID, &devid,
3055819Sfw157321 	    sizeof (devid)) != PICL_SUCCESS)
3065819Sfw157321 		return (err);
3075819Sfw157321 
3085819Sfw157321 	/*
3095819Sfw157321 	 * Go find the first child of the parent so we can search
3105819Sfw157321 	 * all of the siblings.
3115819Sfw157321 	 */
3125819Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
3135819Sfw157321 	    sizeof (pnodeh)) != PICL_SUCCESS)
3145819Sfw157321 		return (err);
3155819Sfw157321 	if (picl_get_propval_by_name(pnodeh, PICL_PROP_CHILD, &pnodeh,
3165819Sfw157321 	    sizeof (pnodeh)) != PICL_SUCCESS)
3175819Sfw157321 		return (err);
3185436Sfw157321 
3195819Sfw157321 	/*
3205819Sfw157321 	 * If the child's device ID matches, then fetch the Label and
3215819Sfw157321 	 * return it.  The first child/device ID should have a Label
3225819Sfw157321 	 * associated with it.
3235819Sfw157321 	 */
3245819Sfw157321 	do {
3255819Sfw157321 		if (picl_get_propval_by_name(pnodeh, PICL_PROP_DEVICE_ID,
3265819Sfw157321 		    &sib_devid, sizeof (sib_devid)) == PICL_SUCCESS) {
3275819Sfw157321 			if (sib_devid == devid) {
3285819Sfw157321 				if ((err = picl_get_propval_by_name(pnodeh,
3295819Sfw157321 				    PICL_PROP_LABEL, val, sizeof (val))) ==
3305819Sfw157321 				    PICL_SUCCESS) {
3315819Sfw157321 					(void) strlcpy(card->slot_str, val,
3325819Sfw157321 					    sizeof (card->slot_str));
3335819Sfw157321 					break;
3345819Sfw157321 				}
3355819Sfw157321 			}
3365819Sfw157321 		}
3375819Sfw157321 	} while (picl_get_propval_by_name(pnodeh, PICL_PROP_PEER, &pnodeh,
3385819Sfw157321 	    sizeof (pnodeh)) == PICL_SUCCESS);
3395819Sfw157321 
3405436Sfw157321 	return (err);
3413941Svenki }
3423941Svenki 
3433941Svenki static void
3443941Svenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card)
3453941Svenki {
3463941Svenki 	picl_errno_t err;
3473941Svenki 	picl_prophdl_t proph;
3483941Svenki 	picl_propinfo_t pinfo;
3493941Svenki 	picl_nodehdl_t pnodeh;
3503941Svenki 	uint8_t *pval;
3513941Svenki 	uint32_t dev_mask;
3523941Svenki 	char uaddr[MAXSTRLEN];
3533941Svenki 	int i;
3543941Svenki 
3553941Svenki 	err = PICL_SUCCESS;
3563941Svenki 	while (err == PICL_SUCCESS) {
3573941Svenki 		if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
3584669Sfw157321 		    sizeof (pnodeh)) != PICL_SUCCESS) {
3594669Sfw157321 			(void) strlcpy(card->slot_str, MOTHERBOARD,
3604669Sfw157321 			    sizeof (card->slot_str));
3613941Svenki 			card->slot = -1;
3623941Svenki 			return;
3633941Svenki 		}
3643941Svenki 		if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES,
3654669Sfw157321 		    &pinfo, &proph) == PICL_SUCCESS) {
3663941Svenki 			break;
3673941Svenki 		}
3683941Svenki 		nodeh = pnodeh;
3693941Svenki 	}
3703941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr,
3714669Sfw157321 	    sizeof (uaddr)) != PICL_SUCCESS) {
3724669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
3734669Sfw157321 		    sizeof (card->slot_str));
3743941Svenki 		card->slot = -1;
3753941Svenki 		return;
3763941Svenki 	}
3773941Svenki 	pval = (uint8_t *)malloc(pinfo.size);
3783941Svenki 	if (!pval) {
3794669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
3804669Sfw157321 		    sizeof (card->slot_str));
3813941Svenki 		card->slot = -1;
3823941Svenki 		return;
3833941Svenki 	}
3843941Svenki 	if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) {
3854669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
3864669Sfw157321 		    sizeof (card->slot_str));
3873941Svenki 		card->slot = -1;
3883941Svenki 		free(pval);
3893941Svenki 		return;
3901708Sstevel 	}
3911708Sstevel 
3923941Svenki 	dev_mask = 0;
3933941Svenki 	for (i = 0; i < sizeof (dev_mask); i++)
3943941Svenki 		dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i));
3953941Svenki 	for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) {
3963941Svenki 		if (uaddr[i] == ',') {
3973941Svenki 			uaddr[i] = '\0';
3983941Svenki 			break;
3993941Svenki 		}
4003941Svenki 	}
4013941Svenki 	card->slot = atol(uaddr);
4023941Svenki 	if (((1 << card->slot) & dev_mask) == 0) {
4034669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
4044669Sfw157321 		    sizeof (card->slot_str));
4053941Svenki 		card->slot = -1;
4063941Svenki 	} else {
4073941Svenki 		char *p = (char *)(pval+sizeof (dev_mask));
4083941Svenki 		int shift = sizeof (uint32_t)*8-1-card->slot;
4093941Svenki 		uint32_t x = (dev_mask << shift) >> shift;
4103941Svenki 		int count = 0;	/* count # of 1's in x */
4113941Svenki 		int i = 0;
4123941Svenki 		while (x != 0) {
4133941Svenki 			count++;
4143941Svenki 			x &= x-1;
4153941Svenki 		}
4163941Svenki 		while (count > 1) {
4174669Sfw157321 			while (p[i++] != '\0')
4184669Sfw157321 				;
4193941Svenki 			count--;
4203941Svenki 		}
4214003Svivek 		(void) strlcpy(card->slot_str, (char *)(p+i),
4224669Sfw157321 		    sizeof (card->slot_str));
4233941Svenki 	}
4243941Svenki 	free(pval);
4253941Svenki }
4263941Svenki 
4273941Svenki /*
4283941Svenki  * add all io devices under pci in io list
4293941Svenki  */
4303941Svenki /* ARGSUSED */
4313941Svenki static int
4323941Svenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args)
4333941Svenki {
4343941Svenki 	char path[PICL_PROPNAMELEN_MAX];
4353941Svenki 	char class[PICL_CLASSNAMELEN_MAX];
4363941Svenki 	char name[PICL_PROPNAMELEN_MAX];
4373941Svenki 	char model[PICL_PROPNAMELEN_MAX];
4383941Svenki 	char binding_name[PICL_PROPNAMELEN_MAX];
4393941Svenki 	char val[PICL_PROPNAMELEN_MAX];
4403941Svenki 	char *compatible;
4413941Svenki 	picl_errno_t err;
4425819Sfw157321 	picl_nodehdl_t nodeh, pnodeh;
4433941Svenki 	struct io_card pci_card;
4443941Svenki 
4453941Svenki 	/* Walk through the children */
4463941Svenki 
4473941Svenki 	err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
4484669Sfw157321 	    sizeof (picl_nodehdl_t));
4493941Svenki 
4503941Svenki 	while (err == PICL_SUCCESS) {
4513941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
4524669Sfw157321 		    class, sizeof (class));
4533941Svenki 		if (err !=  PICL_SUCCESS)
4543941Svenki 			return (err);
4553941Svenki 
4563941Svenki 		if (args) {
4573941Svenki 			char *val = args;
4583941Svenki 			if (strcmp(class, val) == 0) {
4593941Svenki 				err = picl_get_propval_by_name(nodeh,
4604669Sfw157321 				    PICL_PROP_PEER, &nodeh,
4614669Sfw157321 				    sizeof (picl_nodehdl_t));
4623941Svenki 				continue;
4633941Svenki 			} else if (strcmp(val, PICL_CLASS_PCIEX) == 0 &&
4644669Sfw157321 			    strcmp(class, PICL_CLASS_PCI) == 0) {
4653941Svenki 				err = picl_get_propval_by_name(nodeh,
4664669Sfw157321 				    PICL_PROP_PEER, &nodeh,
4674669Sfw157321 				    sizeof (picl_nodehdl_t));
4683941Svenki 				continue;
4693941Svenki 			} else if (strcmp(val, PICL_CLASS_PCI) == 0 &&
4704669Sfw157321 			    strcmp(class, PICL_CLASS_PCIEX) == 0) {
4713941Svenki 				err = picl_get_propval_by_name(nodeh,
4724669Sfw157321 				    PICL_PROP_PEER, &nodeh,
4734669Sfw157321 				    sizeof (picl_nodehdl_t));
4743941Svenki 				continue;
4753941Svenki 			}
4763941Svenki 		}
4773941Svenki 
4783941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
4794669Sfw157321 		    path, sizeof (path));
4803941Svenki 		if (err != PICL_SUCCESS)
4813941Svenki 			return (err);
4823941Svenki 
4833941Svenki 		(void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
4843941Svenki 
4855819Sfw157321 		pnodeh = nodeh;
4865819Sfw157321 		err = get_slot_label(nodeh, &pci_card);
4875819Sfw157321 
4885819Sfw157321 		/*
4895819Sfw157321 		 * No Label at this node, maybe we're looking at a device
4905819Sfw157321 		 * downstream of a bridge.  Walk back up and find a Label and
4915819Sfw157321 		 * record that node in "pnodeh".
4925819Sfw157321 		 */
4935819Sfw157321 		while (err != PICL_SUCCESS) {
4945819Sfw157321 			if (err != PICL_PROPNOTFOUND)
4955819Sfw157321 				break;
4965819Sfw157321 			else if (picl_get_propval_by_name(pnodeh,
4975819Sfw157321 			    PICL_PROP_PARENT, &pnodeh, sizeof (pnodeh)) ==
4985819Sfw157321 			    PICL_SUCCESS)
4995819Sfw157321 				err = get_slot_label(pnodeh, &pci_card);
5005819Sfw157321 			else
5015819Sfw157321 				break;
5025819Sfw157321 		}
5035819Sfw157321 
5045819Sfw157321 		/*
5055819Sfw157321 		 * Can't find a Label for this device in the PCI heirarchy.
5065819Sfw157321 		 * Try to synthesize a slot name from atoms.  This depends
5075819Sfw157321 		 * on the OBP slot_names property being implemented, and this
5085819Sfw157321 		 * so far doesn't seem to be on sun4v.  But just in case that
5095819Sfw157321 		 * is resurrected, the code is here.
5105819Sfw157321 		 */
5115819Sfw157321 		if (err != PICL_SUCCESS) {
5125819Sfw157321 			pnodeh = nodeh;
5135819Sfw157321 			get_slot_number(nodeh, &pci_card);
5145819Sfw157321 		}
5155819Sfw157321 
5165819Sfw157321 		/*
5175819Sfw157321 		 * Passing in pnodeh instead of nodeh will cause prtdiag
5185819Sfw157321 		 * to display the type of IO slot for the leaf node.  For
5195819Sfw157321 		 * built-in devices and a lot of IO cards these will be
5205819Sfw157321 		 * the same thing.  But for IO cards with bridge chips or
5215819Sfw157321 		 * for things like expansion chassis, prtdiag will report
5225819Sfw157321 		 * the bus type of the IO slot and not the leaf, which
5235819Sfw157321 		 * could be different things.
5245819Sfw157321 		 */
5255819Sfw157321 		get_bus_type(pnodeh, &pci_card);
5263941Svenki 
5273941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name,
5284669Sfw157321 		    sizeof (name));
5293941Svenki 		if (err == PICL_PROPNOTFOUND)
5304003Svivek 			(void) strlcpy(name, "", sizeof (name));
5313941Svenki 		else if (err != PICL_SUCCESS)
5323941Svenki 			return (err);
5333941Svenki 
5343941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val,
5354669Sfw157321 		    sizeof (val));
5363941Svenki 		if (err == PICL_PROPNOTFOUND)
5374003Svivek 			(void) strlcpy(val, "", sizeof (val));
5383941Svenki 		else if (err != PICL_SUCCESS)
5393941Svenki 			return (err);
5403941Svenki 
5415436Sfw157321 		(void) snprintf(pci_card.status, sizeof (pci_card.status),
5425436Sfw157321 		    "%s", pci_card.slot_str);
5433941Svenki 
5443941Svenki 		/*
5453941Svenki 		 * Get the name of this card. If binding_name is found,
5463941Svenki 		 * name will be <nodename>-<binding_name>.
5473941Svenki 		 */
5483941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
5494669Sfw157321 		    binding_name, sizeof (binding_name));
5503941Svenki 		if (err == PICL_SUCCESS) {
5513941Svenki 			if (strcmp(name, binding_name) != 0) {
5523941Svenki 				(void) strlcat(name, "-", sizeof (name));
5533941Svenki 				(void) strlcat(name, binding_name,
5544669Sfw157321 				    sizeof (name));
5553941Svenki 			}
5563941Svenki 		} else if (err == PICL_PROPNOTFOUND) {
5573941Svenki 			/*
5583941Svenki 			 * if compatible prop is not found, name will be
5593941Svenki 			 * <nodename>-<compatible>
5603941Svenki 			 */
5613941Svenki 			err = sun4v_get_first_compatible_value(nodeh,
5624669Sfw157321 			    &compatible);
5633941Svenki 			if (err == PICL_SUCCESS) {
5643941Svenki 				(void) strlcat(name, "-", sizeof (name));
5654003Svivek 				(void) strlcat(name, compatible,
5664669Sfw157321 				    sizeof (name));
5673941Svenki 				free(compatible);
5683941Svenki 			}
5693941Svenki 		} else
5703941Svenki 			return (err);
5713941Svenki 
5723941Svenki 		(void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
5733941Svenki 
5743941Svenki 		/* Get the model of this card */
5753941Svenki 
5763941Svenki 		err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
5774669Sfw157321 		    model, sizeof (model));
5783941Svenki 		if (err == PICL_PROPNOTFOUND)
5794003Svivek 			(void) strlcpy(model, "", sizeof (model));
5803941Svenki 		else if (err != PICL_SUCCESS)
5813941Svenki 			return (err);
5823941Svenki 		(void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
5833941Svenki 
5843941Svenki 		/* Print NAC name */
5854802Sfw157321 		log_printf("%-18s", pci_card.status);
5863941Svenki 		/* Print IO Type */
5873941Svenki 		log_printf("%-6s", pci_card.bus_type);
5883941Svenki 		/* Printf Card Name */
5895544Sfw157321 		log_printf("%-34s", pci_card.name);
5903941Svenki 		/* Print Card Model */
5913941Svenki 		log_printf("%-8s", pci_card.model);
5923941Svenki 		log_printf("\n");
5933941Svenki 		/* Print Status */
5944802Sfw157321 		log_printf("%-18s", val);
5953941Svenki 		/* Print IO Type */
5963941Svenki 		log_printf("%-6s", "");
5973941Svenki 		/* Print Parent Path */
5984802Sfw157321 		log_printf("%-44s", pci_card.notes);
5993941Svenki 		log_printf("\n");
6003941Svenki 
6013941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
6024669Sfw157321 		    sizeof (picl_nodehdl_t));
6033941Svenki 	}
6043941Svenki 	return (PICL_WALK_CONTINUE);
6051708Sstevel }
6061708Sstevel 
6071708Sstevel /*
6081708Sstevel  * display_pci
6091708Sstevel  * Display all the PCI IO cards on this board.
6101708Sstevel  */
6111708Sstevel void
6121708Sstevel sun4v_display_pci(picl_nodehdl_t plafh)
6131708Sstevel {
6145544Sfw157321 	char *fmt = "%-17s %-5s %-33s %-8s";
6153941Svenki 	/* Have we printed the column headings? */
6163941Svenki 	static int banner = FALSE;
6173941Svenki 
6183941Svenki 	if (banner == FALSE) {
6193941Svenki 		log_printf("\n");
6204802Sfw157321 		log_printf("================================");
6213941Svenki 		log_printf(" IO Devices ");
6224802Sfw157321 		log_printf("================================");
6233941Svenki 		log_printf("\n");
6243941Svenki 		log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0);
6253941Svenki 		log_printf("\n");
6263941Svenki 		log_printf(fmt, "Status", "Type", "Path", "", 0);
6273941Svenki 		log_printf("\n");
6283941Svenki 		log_printf("---------------------------------"
6294802Sfw157321 		    "-------------------------------------------\n");
6303941Svenki 		banner = TRUE;
6313941Svenki 	}
6323941Svenki 
6333941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
6344669Sfw157321 	    PICL_CLASS_PCIEX, sun4v_pci_callback);
6353941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
6364669Sfw157321 	    PICL_CLASS_PCI, sun4v_pci_callback);
6373941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V,
6384669Sfw157321 	    PICL_CLASS_SUN4V, sun4v_pci_callback);
6393941Svenki }
6403941Svenki 
6413941Svenki /*
6423941Svenki  * return the first compatible value
6433941Svenki  */
6443941Svenki static int
6453941Svenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
6463941Svenki {
6473941Svenki 	picl_errno_t err;
6483941Svenki 	picl_prophdl_t proph;
6493941Svenki 	picl_propinfo_t pinfo;
6503941Svenki 	picl_prophdl_t tblh;
6513941Svenki 	picl_prophdl_t rowproph;
6523941Svenki 	char *pval;
6533941Svenki 
6543941Svenki 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
6554669Sfw157321 	    &pinfo, &proph);
6563941Svenki 	if (err != PICL_SUCCESS)
6573941Svenki 		return (err);
6583941Svenki 
6593941Svenki 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
6603941Svenki 		pval = malloc(pinfo.size);
6613941Svenki 		if (pval == NULL)
6623941Svenki 			return (PICL_FAILURE);
6633941Svenki 		err = picl_get_propval(proph, pval, pinfo.size);
6643941Svenki 		if (err != PICL_SUCCESS) {
6653941Svenki 			free(pval);
6663941Svenki 			return (err);
6673941Svenki 		}
6683941Svenki 		*outbuf = pval;
6693941Svenki 		return (PICL_SUCCESS);
6703941Svenki 	}
6713941Svenki 
6723941Svenki 	if (pinfo.type != PICL_PTYPE_TABLE)
6733941Svenki 		return (PICL_FAILURE);
6743941Svenki 
6753941Svenki 	/* get first string from table */
6763941Svenki 	err = picl_get_propval(proph, &tblh, pinfo.size);
6773941Svenki 	if (err != PICL_SUCCESS)
6783941Svenki 		return (err);
6793941Svenki 
6803941Svenki 	err = picl_get_next_by_row(tblh, &rowproph);
6813941Svenki 	if (err != PICL_SUCCESS)
6823941Svenki 		return (err);
6833941Svenki 
6843941Svenki 	err = picl_get_propinfo(rowproph, &pinfo);
6853941Svenki 	if (err != PICL_SUCCESS)
6863941Svenki 		return (err);
6873941Svenki 
6883941Svenki 	pval = malloc(pinfo.size);
6893941Svenki 	if (pval == NULL)
6903941Svenki 		return (PICL_FAILURE);
6913941Svenki 
6923941Svenki 	err = picl_get_propval(rowproph, pval, pinfo.size);
6933941Svenki 	if (err != PICL_SUCCESS) {
6943941Svenki 		free(pval);
6953941Svenki 		return (err);
6963941Svenki 	}
6973941Svenki 
6983941Svenki 	*outbuf = pval;
6993941Svenki 	return (PICL_SUCCESS);
7001708Sstevel }
7011708Sstevel 
7023941Svenki /*
7033941Svenki  * print size of a memory segment
7043941Svenki  */
7053941Svenki static void
7063941Svenki print_memory_segment_size(uint64_t size)
7073941Svenki {
7083941Svenki 	uint64_t kbyte = 1024;
7093941Svenki 	uint64_t mbyte = kbyte * kbyte;
7103941Svenki 	uint64_t gbyte = kbyte * mbyte;
7115544Sfw157321 	uint64_t tbyte = kbyte * gbyte;
7123941Svenki 	char buf[MEMORY_SIZE_FIELD];
7133941Svenki 
7145544Sfw157321 	if (size >= tbyte) {
7155544Sfw157321 		if (size % tbyte == 0)
7165544Sfw157321 			(void) snprintf(buf, sizeof (buf), "%d TB",
7175544Sfw157321 			    (int)(size / tbyte));
7185544Sfw157321 		else
7195544Sfw157321 			(void) snprintf(buf, sizeof (buf), "%.2f TB",
7205544Sfw157321 			    (float)size / tbyte);
7215544Sfw157321 	} else if (size >= gbyte) {
7223941Svenki 		if (size % gbyte == 0)
7233941Svenki 			(void) snprintf(buf, sizeof (buf), "%d GB",
7244669Sfw157321 			    (int)(size / gbyte));
7253941Svenki 		else
7263941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f GB",
7274669Sfw157321 			    (float)size / gbyte);
7283941Svenki 	} else if (size >= mbyte) {
7293941Svenki 		if (size % mbyte == 0)
7303941Svenki 			(void) snprintf(buf, sizeof (buf), "%d MB",
7314669Sfw157321 			    (int)(size / mbyte));
7323941Svenki 		else
7333941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f MB",
7344669Sfw157321 			    (float)size / mbyte);
7353941Svenki 	} else {
7363941Svenki 		if (size % kbyte == 0)
7373941Svenki 			(void) snprintf(buf, sizeof (buf), "%d KB",
7384669Sfw157321 			    (int)(size / kbyte));
7393941Svenki 		else
7403941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f KB",
7414669Sfw157321 			    (float)size / kbyte);
7423941Svenki 	}
7435544Sfw157321 	log_printf("%-9s", buf);
7443941Svenki }
7453941Svenki 
7463941Svenki /*
7474669Sfw157321  * Enumerate banks and dimms within a memory segment.  We're handed
7484669Sfw157321  * the first bank within the segment - we assume there are dimms
7494669Sfw157321  * (memory-module) nodes underneath.
7503941Svenki  */
7513941Svenki static void
7524669Sfw157321 print_memory_segment_contain(picl_nodehdl_t bank_nodeh)
7531708Sstevel {
7543941Svenki 	char val[PICL_PROPNAMELEN_MAX];
7554669Sfw157321 	picl_nodehdl_t module_nodeh;
7564669Sfw157321 	int flag = 0;
7575544Sfw157321 	uint64_t size;
7584669Sfw157321 
7594669Sfw157321 	do {
7604669Sfw157321 		if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD,
7614669Sfw157321 		    &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS)
7624669Sfw157321 			continue;
7635544Sfw157321 		if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_SIZE,
7645544Sfw157321 		    &size, sizeof (size)) == PICL_SUCCESS) {
7655544Sfw157321 			if (!flag) {
7665544Sfw157321 				print_memory_segment_size(size);
7675544Sfw157321 			} else {
7685544Sfw157321 				log_printf("                "
7695544Sfw157321 				    "                    ");
7705544Sfw157321 				print_memory_segment_size(size);
7715544Sfw157321 				flag = 0;
7725544Sfw157321 			}
7735544Sfw157321 		}
7744669Sfw157321 		do {
7754669Sfw157321 			if (picl_get_propval_by_name(module_nodeh,
7764669Sfw157321 			    PICL_PROP_NAC, val, sizeof (val)) !=
7774669Sfw157321 			    PICL_SUCCESS)
7784669Sfw157321 				continue;
7794669Sfw157321 			else {
7804669Sfw157321 				if (!flag) {
7815544Sfw157321 					log_printf("%s\n", val);
7824669Sfw157321 					flag = 1;
7835544Sfw157321 				} else {
7845544Sfw157321 					log_printf("%s%s\n",
7855544Sfw157321 					    "                       "
7865544Sfw157321 					    "                      ",
7875544Sfw157321 					    val);
7885544Sfw157321 				}
7894669Sfw157321 			}
7904669Sfw157321 		} while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER,
7914669Sfw157321 		    &module_nodeh, sizeof (picl_nodehdl_t)) ==
7924669Sfw157321 		    PICL_SUCCESS);
7934669Sfw157321 	} while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER,
7944669Sfw157321 	    &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS);
7953941Svenki }
7963941Svenki 
7973941Svenki /*
7983941Svenki  * Search node where _class=="memory-segment"
7993941Svenki  * print "Base Address", "Size", etc
8003941Svenki  */
8013941Svenki /*ARGSUSED*/
8023941Svenki static int
8033941Svenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args)
8043941Svenki {
8053941Svenki 	uint64_t base;
8063941Svenki 	uint64_t size;
8073941Svenki 	uint64_t ifactor;
8083941Svenki 	picl_errno_t err = PICL_SUCCESS;
8093941Svenki 
8103941Svenki 	if (class_node_found == 0) {
8113941Svenki 		class_node_found = 1;
8123941Svenki 		return (PICL_WALK_TERMINATE);
8133941Svenki 	}
8143941Svenki 	while (err == PICL_SUCCESS) {
8153941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS,
8164669Sfw157321 		    &base, sizeof (base));
8173941Svenki 		if (err !=  PICL_SUCCESS)
8183941Svenki 			break;
8193941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE,
8204669Sfw157321 		    &size, sizeof (size));
8213941Svenki 		if (err !=  PICL_SUCCESS)
8223941Svenki 			break;
8233941Svenki 		err = picl_get_propval_by_name(nodeh,
8244669Sfw157321 		    PICL_PROP_INTERLEAVE_FACTOR, &ifactor,
8254669Sfw157321 		    sizeof (ifactor));
8263941Svenki 		if (err !=  PICL_SUCCESS)
8273941Svenki 			break;
8285544Sfw157321 		log_printf("0x%-13llx", base);
8293941Svenki 		print_memory_segment_size(size);
8305544Sfw157321 		log_printf("%-12lld", ifactor);
8314669Sfw157321 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
8324669Sfw157321 		    &nodeh, sizeof (nodeh));
8334669Sfw157321 		if (err ==  PICL_SUCCESS)
8344669Sfw157321 			print_memory_segment_contain(nodeh);
8353941Svenki 		log_printf("\n");
8363941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
8374669Sfw157321 		    sizeof (picl_nodehdl_t));
8383941Svenki 	}
8393941Svenki 
8403941Svenki 	return (PICL_WALK_CONTINUE);
8413941Svenki }
8423941Svenki 
8433941Svenki /*ARGSUSED*/
8443941Svenki void
8453941Svenki sun4v_display_memory_conf(picl_nodehdl_t plafh)
8463941Svenki {
8475544Sfw157321 	char *fmt = "%-14s %-8s %-11s %-8s %-s";
8483941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
8494669Sfw157321 	    NULL, sun4v_memory_conf_callback);
8503941Svenki 	if (class_node_found == 0)
8513941Svenki 		return;
8523941Svenki 	log_printf("\n");
8535544Sfw157321 	log_printf("=======================");
8545544Sfw157321 	log_printf(" Physical Memory Configuration ");
8555544Sfw157321 	log_printf("========================");
8563941Svenki 	log_printf("\n");
8573941Svenki 	log_printf("Segment Table:\n");
8584669Sfw157321 	log_printf(
8595544Sfw157321 	    "--------------------------------------------------------------\n");
8605544Sfw157321 	log_printf(fmt, "Base", "Segment", "Interleave", "Bank", "Contains", 0);
8615544Sfw157321 	log_printf("\n");
8625544Sfw157321 	log_printf(fmt, "Address", "Size", "Factor", "Size", "Modules", 0);
8633941Svenki 	log_printf("\n");
8644669Sfw157321 	log_printf(
8655544Sfw157321 	    "--------------------------------------------------------------\n");
8663941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
8674669Sfw157321 	    NULL, sun4v_memory_conf_callback);
8681708Sstevel }
8691708Sstevel 
8701708Sstevel void
8711708Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh)
8721708Sstevel {
8735544Sfw157321 	char *fmt = "%-6s %-9s %-22s %-6s";
8741708Sstevel 
8751708Sstevel 	/*
8761708Sstevel 	 * Display the table header for CPUs . Then display the CPU
8771708Sstevel 	 * frequency, cache size, and processor revision of all cpus.
8781708Sstevel 	 */
8791708Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
8804669Sfw157321 	    "\n"
8815544Sfw157321 	    "================================"
8825544Sfw157321 	    " Virtual CPUs "
8835544Sfw157321 	    "================================"
8844669Sfw157321 	    "\n"
8854669Sfw157321 	    "\n"));
8861708Sstevel 	log_printf("\n");
8875544Sfw157321 	log_printf(fmt, "CPU ID", "Frequency", "Implementation",
8885544Sfw157321 	    "Status", 0);
8891708Sstevel 	log_printf("\n");
8905544Sfw157321 	log_printf(fmt, "------", "---------",
8915544Sfw157321 	    "----------------------", "-------", 0);
8921708Sstevel 	log_printf("\n");
8931708Sstevel 
8945544Sfw157321 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU,
8955544Sfw157321 	    sun4v_display_cpus);
8961708Sstevel }
8971708Sstevel 
8981708Sstevel /*
8991708Sstevel  * Display the CPUs present on this board.
9001708Sstevel  */
9011708Sstevel /*ARGSUSED*/
9021708Sstevel int
9031708Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
9041708Sstevel {
9051708Sstevel 	int status;
9063941Svenki 	picl_prophdl_t proph;
9073941Svenki 	picl_prophdl_t tblh;
9083941Svenki 	picl_prophdl_t rowproph;
9091708Sstevel 	picl_propinfo_t propinfo;
9103941Svenki 	int *int_value;
9115028Sfw157321 	int cpuid;
9123941Svenki 	char *comp_value;
9133941Svenki 	char *no_prop_value = "   ";
9143941Svenki 	char freq_str[MAXSTRLEN];
9155028Sfw157321 	char state[MAXSTRLEN];
9161708Sstevel 
9171708Sstevel 	/*
9181708Sstevel 	 * Get cpuid property and print it and the NAC name
9191708Sstevel 	 */
9205544Sfw157321 	status = picl_get_propinfo_by_name(cpuh, OBP_PROP_CPUID, &propinfo,
9215544Sfw157321 	    &proph);
9221708Sstevel 	if (status == PICL_SUCCESS) {
9231708Sstevel 		status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
9241708Sstevel 		if (status != PICL_SUCCESS) {
9255544Sfw157321 			log_printf("%-7s", no_prop_value);
9261708Sstevel 		} else {
9275544Sfw157321 			log_printf("%-7d", cpuid);
9281708Sstevel 		}
9291708Sstevel 	} else {
9305544Sfw157321 		log_printf("%-7s", no_prop_value);
9311708Sstevel 	}
9321708Sstevel 
9331708Sstevel clock_freq:
9341708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
9354669Sfw157321 	    &proph);
9361708Sstevel 	if (status == PICL_SUCCESS) {
9371708Sstevel 		int_value = malloc(propinfo.size);
9381708Sstevel 		if (int_value == NULL) {
9395544Sfw157321 			log_printf("%-10s", no_prop_value);
9401708Sstevel 			goto compatible;
9411708Sstevel 		}
9421708Sstevel 		status = picl_get_propval(proph, int_value, propinfo.size);
9431708Sstevel 		if (status != PICL_SUCCESS) {
9445544Sfw157321 			log_printf("%-10s", no_prop_value);
9451708Sstevel 		} else {
9461708Sstevel 			/* Running frequency */
9471708Sstevel 			(void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
9481708Sstevel 			    CLK_FREQ_TO_MHZ(*int_value));
9495544Sfw157321 			log_printf("%-10s", freq_str);
9501708Sstevel 		}
9511708Sstevel 		free(int_value);
9521708Sstevel 	} else
9535544Sfw157321 		log_printf("%-10s", no_prop_value);
9541708Sstevel 
9551708Sstevel compatible:
9561708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
9574669Sfw157321 	    &proph);
9581708Sstevel 	if (status == PICL_SUCCESS) {
9591708Sstevel 		if (propinfo.type == PICL_PTYPE_CHARSTRING) {
9601708Sstevel 			/*
9611708Sstevel 			 * Compatible Property only has 1 value
9621708Sstevel 			 */
9631708Sstevel 			comp_value = malloc(propinfo.size);
9641708Sstevel 			if (comp_value == NULL) {
9655544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9665028Sfw157321 				goto state;
9671708Sstevel 			}
9681708Sstevel 			status = picl_get_propval(proph, comp_value,
9694669Sfw157321 			    propinfo.size);
9703941Svenki 			if (status != PICL_SUCCESS)
9715544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9723941Svenki 			else
9735544Sfw157321 				log_printf("%-23s", comp_value, 0);
9743941Svenki 			free(comp_value);
9751708Sstevel 		} else if (propinfo.type == PICL_PTYPE_TABLE) {
9761708Sstevel 			/*
9771708Sstevel 			 * Compatible Property has multiple values
9781708Sstevel 			 */
9791708Sstevel 			status = picl_get_propval(proph, &tblh, propinfo.size);
9801708Sstevel 			if (status != PICL_SUCCESS) {
9815544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9825028Sfw157321 				goto state;
9831708Sstevel 			}
9841708Sstevel 			status = picl_get_next_by_row(tblh, &rowproph);
9851708Sstevel 			if (status != PICL_SUCCESS) {
9865544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9875028Sfw157321 				goto state;
9881708Sstevel 			}
9891708Sstevel 
9901708Sstevel 			status = picl_get_propinfo(rowproph, &propinfo);
9911708Sstevel 			if (status != PICL_SUCCESS) {
9925544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9935028Sfw157321 				goto state;
9941708Sstevel 			}
9951708Sstevel 
9961708Sstevel 			comp_value = malloc(propinfo.size);
9971708Sstevel 			if (comp_value == NULL) {
9985544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
9995028Sfw157321 				goto state;
10001708Sstevel 			}
10011708Sstevel 			status = picl_get_propval(rowproph, comp_value,
10024669Sfw157321 			    propinfo.size);
10033941Svenki 			if (status != PICL_SUCCESS)
10045544Sfw157321 				log_printf("%-23s", no_prop_value, 0);
10053941Svenki 			else
10065544Sfw157321 				log_printf("%-23s", comp_value, 0);
10071708Sstevel 			free(comp_value);
10081708Sstevel 		}
10091708Sstevel 	} else
10105544Sfw157321 		log_printf("%-23s", no_prop_value, 0);
10111708Sstevel 
10125028Sfw157321 state:
10135028Sfw157321 	status = picl_get_propinfo_by_name(cpuh, PICL_PROP_STATE,
10145028Sfw157321 	    &propinfo, &proph);
10151708Sstevel 	if (status == PICL_SUCCESS) {
10165028Sfw157321 		status = picl_get_propval(proph, state, sizeof (state));
10171708Sstevel 		if (status != PICL_SUCCESS) {
10183941Svenki 			log_printf("%-9s", no_prop_value);
10191708Sstevel 		} else {
10205028Sfw157321 			log_printf("%-9s", state);
10211708Sstevel 		}
10221708Sstevel 	} else
10233941Svenki 		log_printf("%-9s", no_prop_value);
10241708Sstevel 
10251708Sstevel done:
10261708Sstevel 	log_printf("\n");
10271708Sstevel 	return (PICL_WALK_CONTINUE);
10281708Sstevel }
10291708Sstevel 
10301708Sstevel void
10311708Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
10321708Sstevel {
10331708Sstevel #ifdef	lint
10341708Sstevel 	flag = flag;
10351708Sstevel 	root = root;
10361708Sstevel 	plafh = plafh;
10371708Sstevel #endif
10381708Sstevel 	/*
10391708Sstevel 	 * This function is intentionally empty
10401708Sstevel 	 */
10411708Sstevel }
10421708Sstevel 
10431708Sstevel void
10441708Sstevel display_boardnum(int num)
10451708Sstevel {
10461708Sstevel 	log_printf("%2d   ", num, 0);
10471708Sstevel }
10483941Svenki 
10495547Smb158278 static int
10503941Svenki sun4v_disp_env_status()
10513941Svenki {
10525547Smb158278 	int	exit_code = 0;
10535547Smb158278 
10543941Svenki 	if (phyplatformh == 0)
10555547Smb158278 		return (0);
10563941Svenki 	log_printf("\n");
10573941Svenki 	log_printf("============================");
10583941Svenki 	log_printf(" Environmental Status ");
10593941Svenki 	log_printf("============================");
10603941Svenki 	log_printf("\n");
10613941Svenki 
10623941Svenki 	class_node_found = 0;
10633941Svenki 	all_status_ok = 1;
10643941Svenki 	sun4v_env_print_fan_sensors();
10655547Smb158278 	exit_code |= (!all_status_ok);
10663941Svenki 
10673941Svenki 	class_node_found = 0;
10683941Svenki 	all_status_ok = 1;
10693941Svenki 	sun4v_env_print_fan_indicators();
10705547Smb158278 	exit_code |= (!all_status_ok);
10713941Svenki 
10723941Svenki 	class_node_found = 0;
10733941Svenki 	all_status_ok = 1;
10743941Svenki 	sun4v_env_print_temp_sensors();
10755547Smb158278 	exit_code |= (!all_status_ok);
10763941Svenki 
10773941Svenki 	class_node_found = 0;
10783941Svenki 	all_status_ok = 1;
10793941Svenki 	sun4v_env_print_temp_indicators();
10805547Smb158278 	exit_code |= (!all_status_ok);
10813941Svenki 
10823941Svenki 	class_node_found = 0;
10833941Svenki 	all_status_ok = 1;
10843941Svenki 	sun4v_env_print_current_sensors();
10855547Smb158278 	exit_code |= (!all_status_ok);
10863941Svenki 
10873941Svenki 	class_node_found = 0;
10883941Svenki 	all_status_ok = 1;
10893941Svenki 	sun4v_env_print_current_indicators();
10905547Smb158278 	exit_code |= (!all_status_ok);
10913941Svenki 
10923941Svenki 	class_node_found = 0;
10933941Svenki 	all_status_ok = 1;
10943941Svenki 	sun4v_env_print_voltage_sensors();
10955547Smb158278 	exit_code |= (!all_status_ok);
10963941Svenki 
10973941Svenki 	class_node_found = 0;
10983941Svenki 	all_status_ok = 1;
10993941Svenki 	sun4v_env_print_voltage_indicators();
11005547Smb158278 	exit_code |= (!all_status_ok);
11013941Svenki 
11023941Svenki 	class_node_found = 0;
11035547Smb158278 	all_status_ok = 1;
11048574SJason.Beloro@Sun.COM 	sun4v_env_print_humidity_sensors();
11058574SJason.Beloro@Sun.COM 	exit_code |= (!all_status_ok);
11068574SJason.Beloro@Sun.COM 
11078574SJason.Beloro@Sun.COM 	class_node_found = 0;
11088574SJason.Beloro@Sun.COM 	all_status_ok = 1;
11098574SJason.Beloro@Sun.COM 	sun4v_env_print_humidity_indicators();
11108574SJason.Beloro@Sun.COM 	exit_code |= (!all_status_ok);
11118574SJason.Beloro@Sun.COM 
11128574SJason.Beloro@Sun.COM 	class_node_found = 0;
11138574SJason.Beloro@Sun.COM 	all_status_ok = 1;
11143941Svenki 	sun4v_env_print_LEDs();
11155547Smb158278 	exit_code |= (!all_status_ok);
11163941Svenki 
11173941Svenki 	class_node_found = 0;
11183941Svenki 	all_status_ok = 1;
11193941Svenki 	sun4v_print_fru_status();
11205547Smb158278 	exit_code |= (!all_status_ok);
11213941Svenki 
11223941Svenki 	class_node_found = 0;
11233941Svenki 	sun4v_print_fw_rev();
11243941Svenki 
11255436Sfw157321 	class_node_found = 0;
11265436Sfw157321 	sun4v_print_openprom_rev();
11275436Sfw157321 
11283941Svenki 	sun4v_print_chassis_serial_no();
11295547Smb158278 
11305547Smb158278 	return (exit_code);
11313941Svenki }
11323941Svenki 
11333941Svenki /*ARGSUSED*/
11343941Svenki static int
11353941Svenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args)
11363941Svenki {
11373941Svenki 	char val[PICL_PROPNAMELEN_MAX];
11383941Svenki 	picl_nodehdl_t parenth;
11393941Svenki 	char *names[PARENT_NAMES];
11404802Sfw157321 	char *base_units[PICL_PROPNAMELEN_MAX];
11413941Svenki 	char *loc;
11423941Svenki 	int i;
11433941Svenki 	char *prop;
11443941Svenki 	picl_errno_t err;
11455436Sfw157321 	int32_t lo_warning, lo_shutdown, lo_poweroff;
11465436Sfw157321 	int32_t hi_warning, hi_shutdown, hi_poweroff;
11473941Svenki 	int32_t current_val;
11484802Sfw157321 	int32_t exponent;
11494802Sfw157321 	double display_val;
11504928Sfw157321 	typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
11514928Sfw157321 	    SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
11524928Sfw157321 	sensor_status_t sensor_status = SENSOR_OK;
11533941Svenki 
11543941Svenki 	if (class_node_found == 0) {
11553941Svenki 		class_node_found = 1;
11563941Svenki 		return (PICL_WALK_TERMINATE);
11573941Svenki 	}
11583941Svenki 
11594928Sfw157321 	prop = (char *)args;
11604928Sfw157321 	if (!prop) {
11614928Sfw157321 		sensor_status = SENSOR_UNKNOWN;
11624928Sfw157321 		all_status_ok = 0;
11634928Sfw157321 	} else {
11643941Svenki 		err = picl_get_propval_by_name(nodeh,
11654669Sfw157321 		    PICL_PROP_OPERATIONAL_STATUS, val,
11664669Sfw157321 		    sizeof (val));
11673941Svenki 		if (err == PICL_SUCCESS) {
11683941Svenki 			if (strcmp(val, "disabled") == 0) {
11694928Sfw157321 				sensor_status = SENSOR_DISABLED;
11704928Sfw157321 			}
11714928Sfw157321 		}
11724928Sfw157321 	}
11734928Sfw157321 
11744928Sfw157321 	if (sensor_status != SENSOR_DISABLED &&
11754928Sfw157321 	    sensor_status != SENSOR_UNKNOWN) {
11764928Sfw157321 		if (picl_get_propval_by_name(nodeh, prop, &current_val,
11774928Sfw157321 		    sizeof (current_val)) != PICL_SUCCESS) {
11784928Sfw157321 			sensor_status = SENSOR_UNKNOWN;
11795436Sfw157321 		} else {
11805436Sfw157321 			if (picl_get_propval_by_name(nodeh,
11815436Sfw157321 			    PICL_PROP_LOW_WARNING,
11825436Sfw157321 			    &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS)
11835436Sfw157321 				lo_warning = INVALID_THRESHOLD;
11845436Sfw157321 			if (picl_get_propval_by_name(nodeh,
11855436Sfw157321 			    PICL_PROP_LOW_SHUTDOWN,
11865436Sfw157321 			    &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS)
11875436Sfw157321 				lo_shutdown = INVALID_THRESHOLD;
11885436Sfw157321 			if (picl_get_propval_by_name(nodeh,
11895436Sfw157321 			    PICL_PROP_LOW_POWER_OFF,
11905436Sfw157321 			    &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS)
11915436Sfw157321 				lo_poweroff = INVALID_THRESHOLD;
11925436Sfw157321 			if (picl_get_propval_by_name(nodeh,
11935436Sfw157321 			    PICL_PROP_HIGH_WARNING,
11945436Sfw157321 			    &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS)
11955436Sfw157321 				hi_warning = INVALID_THRESHOLD;
11965436Sfw157321 			if (picl_get_propval_by_name(nodeh,
11975436Sfw157321 			    PICL_PROP_HIGH_SHUTDOWN,
11985436Sfw157321 			    &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS)
11995436Sfw157321 				hi_shutdown = INVALID_THRESHOLD;
12005436Sfw157321 			if (picl_get_propval_by_name(nodeh,
12015436Sfw157321 			    PICL_PROP_HIGH_POWER_OFF,
12025436Sfw157321 			    &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS)
12035436Sfw157321 				hi_poweroff = INVALID_THRESHOLD;
12044928Sfw157321 
12055436Sfw157321 			if ((lo_poweroff != INVALID_THRESHOLD &&
12065436Sfw157321 			    current_val <= lo_poweroff) ||
12075436Sfw157321 			    (hi_poweroff != INVALID_THRESHOLD &&
12085436Sfw157321 			    current_val >= hi_poweroff)) {
12095436Sfw157321 				sensor_status = SENSOR_FAILED;
12105436Sfw157321 			} else if ((lo_shutdown != INVALID_THRESHOLD &&
12115436Sfw157321 			    current_val <= lo_shutdown) ||
12125436Sfw157321 			    (hi_shutdown != INVALID_THRESHOLD &&
12135436Sfw157321 			    current_val >= hi_shutdown)) {
12145436Sfw157321 				sensor_status = SENSOR_FAILED;
12155436Sfw157321 			} else if ((lo_warning != INVALID_THRESHOLD &&
12165436Sfw157321 			    current_val <= lo_warning) ||
12175436Sfw157321 			    (hi_warning != INVALID_THRESHOLD &&
12185436Sfw157321 			    current_val >= hi_warning)) {
12195436Sfw157321 				sensor_status = SENSOR_WARN;
12205436Sfw157321 			} else {
12215436Sfw157321 				sensor_status = SENSOR_OK;
12225436Sfw157321 			}
12234928Sfw157321 		}
12244928Sfw157321 	}
12254928Sfw157321 
12264928Sfw157321 	if (syserrlog == 0) {
12274928Sfw157321 		if (sensor_status != SENSOR_OK && all_status_ok == 1) {
12283941Svenki 			all_status_ok = 0;
12293941Svenki 			return (PICL_WALK_TERMINATE);
12303941Svenki 		}
12314928Sfw157321 		if (sensor_status == SENSOR_OK) {
12324928Sfw157321 			return (PICL_WALK_CONTINUE);
12334928Sfw157321 		}
12343941Svenki 	}
12354928Sfw157321 
12364928Sfw157321 	/*
12374928Sfw157321 	 * If we're here then prtdiag was invoked with "-v" or we have
12384928Sfw157321 	 * a sensor that is beyond a threshold, so give them a book to
12394928Sfw157321 	 * read instead of the Cliff Notes.
12404928Sfw157321 	 */
12413941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
12424669Sfw157321 	    sizeof (parenth));
12433941Svenki 	if (err != PICL_SUCCESS) {
12443941Svenki 		log_printf("\n");
12453941Svenki 		return (PICL_WALK_CONTINUE);
12463941Svenki 	}
12474003Svivek 
12484928Sfw157321 	/* gather up the path name for the sensor */
12494928Sfw157321 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
12504928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++) {
12514928Sfw157321 			if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
12524928Sfw157321 			    NULL) {
12534928Sfw157321 				while (--i > -1)
12544928Sfw157321 					free(names[i]);
12554928Sfw157321 				free(loc);
12564928Sfw157321 				loc = NULL;
12574928Sfw157321 			}
12583941Svenki 		}
12594003Svivek 	}
12604928Sfw157321 	i = 0;
12614928Sfw157321 	if (loc != 0) {
12624928Sfw157321 		while (err == PICL_SUCCESS) {
12634928Sfw157321 			if (parenth == phyplatformh)
12644928Sfw157321 				break;
12654928Sfw157321 			err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
12664928Sfw157321 			    names[i++], PICL_PROPNAMELEN_MAX);
12674928Sfw157321 			if (err != PICL_SUCCESS) {
12684928Sfw157321 				i--;
12694928Sfw157321 				break;
12704928Sfw157321 			}
12714928Sfw157321 			if (i == PARENT_NAMES)
12724928Sfw157321 				break;
12734928Sfw157321 			err = picl_get_propval_by_name(parenth,
12744928Sfw157321 			    PICL_PROP_PARENT, &parenth, sizeof (parenth));
12754928Sfw157321 		}
12764928Sfw157321 		loc[0] = '\0';
12774928Sfw157321 		if (--i > -1) {
12784928Sfw157321 			(void) strlcat(loc, names[i],
12794928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
12804928Sfw157321 		}
12814928Sfw157321 		while (--i > -1) {
12824928Sfw157321 			(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
12834928Sfw157321 			    PARENT_NAMES);
12844928Sfw157321 			(void) strlcat(loc, names[i],
12854928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
12864928Sfw157321 		}
12875028Sfw157321 		log_printf("%-35s", loc);
12884928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++)
12894928Sfw157321 			free(names[i]);
12904928Sfw157321 		free(loc);
12914928Sfw157321 	} else {
12925028Sfw157321 		log_printf("%-35s", " ");
12933941Svenki 	}
12943941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
12954669Sfw157321 	    sizeof (val));
12963941Svenki 	if (err == PICL_SUCCESS)
12973941Svenki 		log_printf("%-15s", val);
12983941Svenki 
12994928Sfw157321 	/*
13004928Sfw157321 	 * Get the exponent if present, and do a little math so that
13014928Sfw157321 	 * if we need to we can print a normalized value for the
13024928Sfw157321 	 * sensor reading.
13034928Sfw157321 	 */
13044802Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT,
13054802Sfw157321 	    &exponent, sizeof (exponent)) != PICL_SUCCESS)
13064802Sfw157321 		exponent = 0;
13074802Sfw157321 	if (exponent == 0)
13084802Sfw157321 		display_val = (double)current_val;
13095436Sfw157321 	else {
13104802Sfw157321 		display_val = (double)current_val *
13114802Sfw157321 		    pow((double)10, (double)exponent);
13125436Sfw157321 
13135436Sfw157321 		/*
13145436Sfw157321 		 * Sometimes ILOM will scale a sensor reading but
13155436Sfw157321 		 * there will be nothing to the right of the decimal
13165436Sfw157321 		 * once that value is normalized.  Setting the
13175436Sfw157321 		 * exponent to zero will prevent the printf below
13185436Sfw157321 		 * from printing extraneous zeros.  Otherwise a
13195436Sfw157321 		 * negative exponent is used to set the precision
13205436Sfw157321 		 * for the printf.
13215436Sfw157321 		 */
13225436Sfw157321 		if ((int)display_val == display_val || exponent > 0)
13235436Sfw157321 			exponent = 0;
13245436Sfw157321 	}
13255436Sfw157321 
13264928Sfw157321 	err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS,
13274928Sfw157321 	    base_units, sizeof (base_units));
13284802Sfw157321 	if (err != PICL_SUCCESS)
13294802Sfw157321 		base_units[0] = '\0';
13303941Svenki 
13314928Sfw157321 	switch (sensor_status) {
13324928Sfw157321 	case SENSOR_FAILED:
13333941Svenki 		log_printf("%-s", "failed (");
13344802Sfw157321 		log_printf("%-.*f", abs(exponent), display_val);
13354802Sfw157321 		log_printf("%-s %s", base_units, ")");
13364928Sfw157321 		break;
13374928Sfw157321 	case SENSOR_WARN:
13383941Svenki 		log_printf("%-s", "warning (");
13394802Sfw157321 		log_printf("%-.*f", abs(exponent), display_val);
13404802Sfw157321 		log_printf("%-s %s", base_units, ")");
13414928Sfw157321 		break;
13424928Sfw157321 	case SENSOR_DISABLED:
13434928Sfw157321 		log_printf("%-s", "disabled");
13444928Sfw157321 		break;
13454928Sfw157321 	case SENSOR_OK:
13463941Svenki 		log_printf("%-s", "ok");
13474928Sfw157321 		break;
13484928Sfw157321 	default:
13494928Sfw157321 		log_printf("%-s", "unknown");
13504928Sfw157321 		break;
13514928Sfw157321 	}
13523941Svenki 
13533941Svenki 	log_printf("\n");
13543941Svenki 	return (PICL_WALK_CONTINUE);
13553941Svenki }
13563941Svenki 
13573941Svenki /*ARGSUSED*/
13583941Svenki static int
13593941Svenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args)
13603941Svenki {
13614928Sfw157321 	char current_val[PICL_PROPNAMELEN_MAX];
13624928Sfw157321 	char expected_val[PICL_PROPNAMELEN_MAX];
13634928Sfw157321 	char label[PICL_PROPNAMELEN_MAX];
13643941Svenki 	picl_nodehdl_t parenth;
13653941Svenki 	char *names[PARENT_NAMES];
13663941Svenki 	char *loc;
13673941Svenki 	int i = 0;
13683941Svenki 	char *prop = (char *)args;
13693941Svenki 	picl_errno_t err = PICL_SUCCESS;
13704928Sfw157321 	typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
13714928Sfw157321 	    SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
13724928Sfw157321 	sensor_status_t sensor_status = SENSOR_OK;
13733941Svenki 
13743941Svenki 	if (class_node_found == 0) {
13753941Svenki 		class_node_found = 1;
13763941Svenki 		return (PICL_WALK_TERMINATE);
13773941Svenki 	}
13784928Sfw157321 
13794928Sfw157321 	prop = (char *)args;
13804928Sfw157321 	if (!prop) {
13814928Sfw157321 		sensor_status = SENSOR_UNKNOWN;
13824928Sfw157321 		all_status_ok = 0;
13834928Sfw157321 	} else {
13843941Svenki 		err = picl_get_propval_by_name(nodeh,
13854928Sfw157321 		    PICL_PROP_OPERATIONAL_STATUS, current_val,
13864928Sfw157321 		    sizeof (current_val));
13873941Svenki 		if (err == PICL_SUCCESS) {
13884928Sfw157321 			if (strcmp(current_val, "disabled") == 0) {
13894928Sfw157321 				sensor_status = SENSOR_DISABLED;
13904928Sfw157321 			}
13914928Sfw157321 		}
13924928Sfw157321 	}
13934928Sfw157321 
13944928Sfw157321 	if (sensor_status != SENSOR_DISABLED &&
13954928Sfw157321 	    sensor_status != SENSOR_UNKNOWN) {
13964928Sfw157321 		if (picl_get_propval_by_name(nodeh, prop, &current_val,
13974928Sfw157321 		    sizeof (current_val)) != PICL_SUCCESS) {
13984928Sfw157321 			(void) strlcpy(current_val, "unknown",
13994928Sfw157321 			    sizeof (current_val));
14004928Sfw157321 			sensor_status = SENSOR_UNKNOWN;
14014928Sfw157321 		} else {
14024928Sfw157321 			if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED,
14034928Sfw157321 			    &expected_val, sizeof (expected_val)) !=
14044928Sfw157321 			    PICL_SUCCESS) {
14054928Sfw157321 				sensor_status = SENSOR_UNKNOWN;
14064928Sfw157321 			} else {
14074928Sfw157321 				if (strncmp(current_val, expected_val,
14084928Sfw157321 				    sizeof (current_val)) == 0) {
14094928Sfw157321 					sensor_status = SENSOR_OK;
14104928Sfw157321 				} else {
14114928Sfw157321 					sensor_status = SENSOR_FAILED;
14123941Svenki 				}
14134928Sfw157321 			}
14144928Sfw157321 		}
14154928Sfw157321 	}
14164928Sfw157321 
14174928Sfw157321 	if (syserrlog == 0) {
14184928Sfw157321 		if (sensor_status != SENSOR_OK && all_status_ok == 1) {
14193941Svenki 			all_status_ok = 0;
14203941Svenki 			return (PICL_WALK_TERMINATE);
14213941Svenki 		}
14224928Sfw157321 		if (sensor_status == SENSOR_OK) {
14234928Sfw157321 			return (PICL_WALK_CONTINUE);
14244928Sfw157321 		}
14253941Svenki 	}
14264928Sfw157321 
14274928Sfw157321 	/*
14284928Sfw157321 	 * If we're here then prtdiag was invoked with "-v" or we have
14294928Sfw157321 	 * a sensor that is beyond a threshold, so give them a book to
14304928Sfw157321 	 * read instead of the Cliff Notes.
14314928Sfw157321 	 */
14323941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
14334669Sfw157321 	    sizeof (parenth));
14343941Svenki 	if (err != PICL_SUCCESS) {
14353941Svenki 		log_printf("\n");
14363941Svenki 		return (PICL_WALK_CONTINUE);
14373941Svenki 	}
14384928Sfw157321 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
14394928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++) {
14404928Sfw157321 			if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
14414928Sfw157321 			    NULL) {
14424928Sfw157321 				while (--i > -1)
14434928Sfw157321 					free(names[i]);
14444928Sfw157321 				free(loc);
14454928Sfw157321 				loc = NULL;
14464928Sfw157321 			}
14473941Svenki 		}
14483941Svenki 	}
14494928Sfw157321 	i = 0;
14504928Sfw157321 	if (loc) {
14514928Sfw157321 		while (err == PICL_SUCCESS) {
14524928Sfw157321 			if (parenth == phyplatformh)
14534928Sfw157321 				break;
14544928Sfw157321 			err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
14554928Sfw157321 			    names[i++], PICL_PROPNAMELEN_MAX);
14564928Sfw157321 			if (err != PICL_SUCCESS) {
14574928Sfw157321 				i--;
14584928Sfw157321 				break;
14594928Sfw157321 			}
14604928Sfw157321 			if (i == PARENT_NAMES)
14614928Sfw157321 				break;
14624928Sfw157321 			err = picl_get_propval_by_name(parenth,
14634928Sfw157321 			    PICL_PROP_PARENT, &parenth, sizeof (parenth));
14644928Sfw157321 		}
14654928Sfw157321 		loc[0] = '\0';
14664928Sfw157321 		if (--i > -1) {
14674928Sfw157321 			(void) strlcat(loc, names[i],
14684928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
14694928Sfw157321 		}
14704928Sfw157321 		while (--i > -1) {
14714928Sfw157321 			(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
14724928Sfw157321 			    PARENT_NAMES);
14734928Sfw157321 			(void) strlcat(loc, names[i],
14744928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
14754928Sfw157321 		}
14765028Sfw157321 		log_printf("%-35s", loc);
14774928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++)
14784928Sfw157321 			free(names[i]);
14794928Sfw157321 		free(loc);
14804928Sfw157321 	} else {
14815028Sfw157321 		log_printf("%-35s", "");
14823941Svenki 	}
14834928Sfw157321 
14844928Sfw157321 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
14854928Sfw157321 	    sizeof (label));
14864928Sfw157321 	if (err != PICL_SUCCESS)
14874928Sfw157321 		(void) strlcpy(label, "", sizeof (label));
14884928Sfw157321 	log_printf("%-15s", label);
14894928Sfw157321 
14904928Sfw157321 	log_printf("%-8s", current_val);
14914928Sfw157321 
14923941Svenki 	log_printf("\n");
14933941Svenki 	return (PICL_WALK_CONTINUE);
14943941Svenki }
14953941Svenki 
14963941Svenki static void
14973941Svenki sun4v_env_print_fan_sensors()
14983941Svenki {
14995028Sfw157321 	char *fmt = "%-34s %-14s %-10s\n";
15003941Svenki 	/*
15013941Svenki 	 * If there isn't any fan sensor node, return now.
15023941Svenki 	 */
15033941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
15044928Sfw157321 	    PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED,
15054669Sfw157321 	    sun4v_env_print_sensor_callback);
15063941Svenki 	if (!class_node_found)
15073941Svenki 		return;
15083941Svenki 	log_printf("Fan sensors:\n");
15093941Svenki 	if (syserrlog == 0) {
15103941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
15114669Sfw157321 		    PICL_CLASS_RPM_SENSOR,
15124928Sfw157321 		    PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
15133941Svenki 		if (all_status_ok) {
15143941Svenki 			log_printf("All fan sensors are OK.\n");
15153941Svenki 			return;
15163941Svenki 		}
15173941Svenki 	}
15185028Sfw157321 	log_printf("-------------------------------------------------"
15195028Sfw157321 	    "-----------\n");
15203941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
15215028Sfw157321 	log_printf("-------------------------------------------------"
15225028Sfw157321 	    "-----------\n");
15233941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR,
15244669Sfw157321 	    PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
15253941Svenki }
15263941Svenki 
15273941Svenki static void
15283941Svenki sun4v_env_print_fan_indicators()
15293941Svenki {
15305028Sfw157321 	char *fmt = "%-34s %-14s %-10s\n";
15313941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
15324928Sfw157321 	    PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION,
15334669Sfw157321 	    sun4v_env_print_indicator_callback);
15343941Svenki 	if (!class_node_found)
15353941Svenki 		return;
15363941Svenki 	log_printf("\nFan indicators:\n");
15373941Svenki 	if (syserrlog == 0) {
15383941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
15394669Sfw157321 		    PICL_CLASS_RPM_INDICATOR,
15404928Sfw157321 		    (void *)PICL_PROP_CONDITION,
15414928Sfw157321 		    sun4v_env_print_indicator_callback);
15423941Svenki 		if (all_status_ok) {
15433941Svenki 			log_printf("All fan indicators are OK.\n");
15443941Svenki 			return;
15453941Svenki 		}
15463941Svenki 	}
15475028Sfw157321 	log_printf("-------------------------------------------------"
15485028Sfw157321 	    "-----------\n");
15493941Svenki 	log_printf(fmt, "Location", "Sensor", "Condition", 0);
15505028Sfw157321 	log_printf("-------------------------------------------------"
15515028Sfw157321 	    "-----------\n");
15523941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR,
15534802Sfw157321 	    (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback);
15543941Svenki }
15553941Svenki 
15563941Svenki static void
15573941Svenki sun4v_env_print_temp_sensors()
15583941Svenki {
15595028Sfw157321 	char *fmt = "%-34s %-14s %-10s\n";
15603941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
15614669Sfw157321 	    PICL_CLASS_TEMPERATURE_SENSOR,
15624669Sfw157321 	    (void *)PICL_PROP_TEMPERATURE,
15634669Sfw157321 	    sun4v_env_print_sensor_callback);
15643941Svenki 	if (!class_node_found)
15653941Svenki 		return;
15663941Svenki 
15673941Svenki 	log_printf("\nTemperature sensors:\n");
15683941Svenki 	if (syserrlog == 0) {
15693941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
15704669Sfw157321 		    PICL_CLASS_TEMPERATURE_SENSOR,
15714928Sfw157321 		    PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
15723941Svenki 		if (all_status_ok) {
15733941Svenki 			log_printf("All temperature sensors are OK.\n");
15743941Svenki 			return;
15753941Svenki 		}
15763941Svenki 	}
15775028Sfw157321 	log_printf("-------------------------------------------------"
15785028Sfw157321 	    "-----------\n");
15793941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
15805028Sfw157321 	log_printf("-------------------------------------------------"
15815028Sfw157321 	    "-----------\n");
15823941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
15834669Sfw157321 	    PICL_CLASS_TEMPERATURE_SENSOR,
15844669Sfw157321 	    (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
15853941Svenki }
15863941Svenki 
15873941Svenki static void
15883941Svenki sun4v_env_print_temp_indicators()
15893941Svenki {
15905028Sfw157321 	char *fmt = "%-34s %-14s %-8s\n";
15913941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
15924669Sfw157321 	    PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION,
15934669Sfw157321 	    sun4v_env_print_indicator_callback);
15943941Svenki 	if (!class_node_found)
15953941Svenki 		return;
15963941Svenki 	log_printf("\nTemperature indicators:\n");
15973941Svenki 	if (syserrlog == 0) {
15983941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
15994928Sfw157321 		    PICL_CLASS_TEMPERATURE_INDICATOR,
16004928Sfw157321 		    (void *)PICL_PROP_CONDITION,
16014669Sfw157321 		    sun4v_env_print_indicator_callback);
16023941Svenki 		if (all_status_ok) {
16033941Svenki 			log_printf("All temperature indicators are OK.\n");
16043941Svenki 			return;
16053941Svenki 		}
16063941Svenki 	}
16075028Sfw157321 	log_printf("-------------------------------------------------"
16085028Sfw157321 	    "-----------\n");
16093941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
16105028Sfw157321 	log_printf("-------------------------------------------------"
16115028Sfw157321 	    "-----------\n");
16123941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
16134669Sfw157321 	    PICL_CLASS_TEMPERATURE_INDICATOR,
16144669Sfw157321 	    (void *)PICL_PROP_CONDITION,
16154669Sfw157321 	    sun4v_env_print_indicator_callback);
16163941Svenki }
16173941Svenki 
16183941Svenki static void
16193941Svenki sun4v_env_print_current_sensors()
16203941Svenki {
16215028Sfw157321 	char *fmt = "%-34s %-14s %-10s\n";
16223941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR,
16234669Sfw157321 	    (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
16243941Svenki 	if (!class_node_found)
16253941Svenki 		return;
16263941Svenki 	log_printf("\nCurrent sensors:\n");
16273941Svenki 	if (syserrlog == 0) {
16283941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
16294669Sfw157321 		    PICL_CLASS_CURRENT_SENSOR,
16304928Sfw157321 		    PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
16313941Svenki 		if (all_status_ok) {
16323941Svenki 			log_printf("All current sensors are OK.\n");
16333941Svenki 			return;
16343941Svenki 		}
16353941Svenki 	}
16365028Sfw157321 	log_printf("-------------------------------------------------"
16375028Sfw157321 	    "-----------\n");
16383941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
16395028Sfw157321 	log_printf("-------------------------------------------------"
16405028Sfw157321 	    "-----------\n");
16413941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
16424669Sfw157321 	    PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
16434669Sfw157321 	    sun4v_env_print_sensor_callback);
16443941Svenki }
16453941Svenki 
16463941Svenki static void
16473941Svenki sun4v_env_print_current_indicators()
16483941Svenki {
16495028Sfw157321 	char *fmt = "%-34s %-14s %-8s\n";
16503941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
16514669Sfw157321 	    PICL_CLASS_CURRENT_INDICATOR,
16524669Sfw157321 	    (void *)PICL_PROP_CONDITION,
16534669Sfw157321 	    sun4v_env_print_indicator_callback);
16543941Svenki 	if (!class_node_found)
16553941Svenki 		return;
16563941Svenki 	log_printf("\nCurrent indicators:\n");
16573941Svenki 	if (syserrlog == 0) {
16583941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
16594928Sfw157321 		    PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION,
16604669Sfw157321 		    sun4v_env_print_indicator_callback);
16613941Svenki 		if (all_status_ok) {
16623941Svenki 			log_printf("All current indicators are OK.\n");
16633941Svenki 			return;
16643941Svenki 		}
16653941Svenki 	}
16665028Sfw157321 	log_printf("-------------------------------------------------"
16675028Sfw157321 	    "-----------\n");
16683941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
16695028Sfw157321 	log_printf("-------------------------------------------------"
16705028Sfw157321 	    "-----------\n");
16713941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
16724669Sfw157321 	    PICL_CLASS_CURRENT_INDICATOR,
16734669Sfw157321 	    (void *)PICL_PROP_CONDITION,
16744669Sfw157321 	    sun4v_env_print_indicator_callback);
16753941Svenki }
16763941Svenki 
16773941Svenki static void
16783941Svenki sun4v_env_print_voltage_sensors()
16793941Svenki {
16805028Sfw157321 	char *fmt = "%-34s %-14s %-10s\n";
16813941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
16824669Sfw157321 	    PICL_CLASS_VOLTAGE_SENSOR,
16834669Sfw157321 	    PICL_PROP_VOLTAGE,
16844669Sfw157321 	    sun4v_env_print_sensor_callback);
16853941Svenki 	if (!class_node_found)
16863941Svenki 		return;
16873941Svenki 	log_printf("\nVoltage sensors:\n");
16883941Svenki 	if (syserrlog == 0) {
16893941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
16904669Sfw157321 		    PICL_CLASS_VOLTAGE_SENSOR,
16914928Sfw157321 		    PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback);
16923941Svenki 		if (all_status_ok) {
16933941Svenki 			log_printf("All voltage sensors are OK.\n");
16943941Svenki 			return;
16953941Svenki 		}
16963941Svenki 	}
16975028Sfw157321 	log_printf("-------------------------------------------------"
16985028Sfw157321 	    "-----------\n");
16993941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
17005028Sfw157321 	log_printf("-------------------------------------------------"
17015028Sfw157321 	    "-----------\n");
17023941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
17034669Sfw157321 	    PICL_CLASS_VOLTAGE_SENSOR,
17044669Sfw157321 	    (void *)PICL_PROP_VOLTAGE,
17054669Sfw157321 	    sun4v_env_print_sensor_callback);
17063941Svenki }
17073941Svenki 
17083941Svenki static void
17093941Svenki sun4v_env_print_voltage_indicators()
17103941Svenki {
17115028Sfw157321 	char *fmt = "%-34s %-14s %-8s\n";
17123941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
17134669Sfw157321 	    PICL_CLASS_VOLTAGE_INDICATOR,
17144669Sfw157321 	    (void *)PICL_PROP_CONDITION,
17154669Sfw157321 	    sun4v_env_print_indicator_callback);
17163941Svenki 	if (!class_node_found)
17173941Svenki 		return;
17183941Svenki 	log_printf("\nVoltage indicators:\n");
17193941Svenki 	if (syserrlog == 0) {
17203941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
17214928Sfw157321 		    PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION,
17224669Sfw157321 		    sun4v_env_print_indicator_callback);
17233941Svenki 		if (all_status_ok) {
17243941Svenki 			log_printf("All voltage indicators are OK.\n");
17253941Svenki 			return;
17263941Svenki 		}
17273941Svenki 	}
17285028Sfw157321 	log_printf("-------------------------------------------------"
17295028Sfw157321 	    "-----------\n");
17303941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
17315028Sfw157321 	log_printf("-------------------------------------------------"
17325028Sfw157321 	    "-----------\n");
17333941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
17344669Sfw157321 	    PICL_CLASS_VOLTAGE_INDICATOR,
17354669Sfw157321 	    (void *)PICL_PROP_CONDITION,
17364669Sfw157321 	    sun4v_env_print_indicator_callback);
17373941Svenki }
17383941Svenki 
17393941Svenki static void
17408574SJason.Beloro@Sun.COM sun4v_env_print_humidity_sensors()
17418574SJason.Beloro@Sun.COM {
17428574SJason.Beloro@Sun.COM 	char *fmt = "%-34s %-14s %-10s\n";
17438574SJason.Beloro@Sun.COM 	(void) picl_walk_tree_by_class(phyplatformh,
17448574SJason.Beloro@Sun.COM 	    PICL_CLASS_HUMIDITY_SENSOR,
17458574SJason.Beloro@Sun.COM 	    (void *)PICL_PROP_HUMIDITY,
17468574SJason.Beloro@Sun.COM 	    sun4v_env_print_sensor_callback);
17478574SJason.Beloro@Sun.COM 	if (!class_node_found)
17488574SJason.Beloro@Sun.COM 		return;
17498574SJason.Beloro@Sun.COM 	log_printf("\nHumidity sensors:\n");
17508574SJason.Beloro@Sun.COM 	if (syserrlog == 0) {
17518574SJason.Beloro@Sun.COM 		(void) picl_walk_tree_by_class(phyplatformh,
17528574SJason.Beloro@Sun.COM 		    PICL_CLASS_HUMIDITY_SENSOR,
17538574SJason.Beloro@Sun.COM 		    PICL_PROP_HUMIDITY, sun4v_env_print_sensor_callback);
17548574SJason.Beloro@Sun.COM 		if (all_status_ok) {
17558574SJason.Beloro@Sun.COM 			log_printf("All humidity sensors are OK.\n");
17568574SJason.Beloro@Sun.COM 			return;
17578574SJason.Beloro@Sun.COM 		}
17588574SJason.Beloro@Sun.COM 	}
17598574SJason.Beloro@Sun.COM 	log_printf("-------------------------------------------------"
17608574SJason.Beloro@Sun.COM 	    "-----------\n");
17618574SJason.Beloro@Sun.COM 	log_printf(fmt, "Location", "Sensor", "Status", 0);
17628574SJason.Beloro@Sun.COM 	log_printf("-------------------------------------------------"
17638574SJason.Beloro@Sun.COM 	    "-----------\n");
17648574SJason.Beloro@Sun.COM 	(void) picl_walk_tree_by_class(phyplatformh,
17658574SJason.Beloro@Sun.COM 	    PICL_CLASS_HUMIDITY_SENSOR,
17668574SJason.Beloro@Sun.COM 	    (void *)PICL_PROP_HUMIDITY,
17678574SJason.Beloro@Sun.COM 	    sun4v_env_print_sensor_callback);
17688574SJason.Beloro@Sun.COM }
17698574SJason.Beloro@Sun.COM 
17708574SJason.Beloro@Sun.COM static void
17718574SJason.Beloro@Sun.COM sun4v_env_print_humidity_indicators()
17728574SJason.Beloro@Sun.COM {
17738574SJason.Beloro@Sun.COM 	char *fmt = "%-34s %-14s %-8s\n";
17748574SJason.Beloro@Sun.COM 	(void) picl_walk_tree_by_class(phyplatformh,
17758574SJason.Beloro@Sun.COM 	    PICL_CLASS_HUMIDITY_INDICATOR,
17768574SJason.Beloro@Sun.COM 	    (void *)PICL_PROP_CONDITION,
17778574SJason.Beloro@Sun.COM 	    sun4v_env_print_indicator_callback);
17788574SJason.Beloro@Sun.COM 	if (!class_node_found)
17798574SJason.Beloro@Sun.COM 		return;
17808574SJason.Beloro@Sun.COM 	log_printf("\nHumidity indicators:\n");
17818574SJason.Beloro@Sun.COM 	if (syserrlog == 0) {
17828574SJason.Beloro@Sun.COM 		(void) picl_walk_tree_by_class(phyplatformh,
17838574SJason.Beloro@Sun.COM 		    PICL_CLASS_HUMIDITY_INDICATOR, (void *)PICL_PROP_CONDITION,
17848574SJason.Beloro@Sun.COM 		    sun4v_env_print_indicator_callback);
17858574SJason.Beloro@Sun.COM 		if (all_status_ok) {
17868574SJason.Beloro@Sun.COM 			log_printf("All humidity indicators are OK.\n");
17878574SJason.Beloro@Sun.COM 			return;
17888574SJason.Beloro@Sun.COM 		}
17898574SJason.Beloro@Sun.COM 	}
17908574SJason.Beloro@Sun.COM 	log_printf("-------------------------------------------------"
17918574SJason.Beloro@Sun.COM 	    "-----------\n");
17928574SJason.Beloro@Sun.COM 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
17938574SJason.Beloro@Sun.COM 	log_printf("-------------------------------------------------"
17948574SJason.Beloro@Sun.COM 	    "-----------\n");
17958574SJason.Beloro@Sun.COM 	(void) picl_walk_tree_by_class(phyplatformh,
17968574SJason.Beloro@Sun.COM 	    PICL_CLASS_HUMIDITY_INDICATOR,
17978574SJason.Beloro@Sun.COM 	    (void *)PICL_PROP_CONDITION,
17988574SJason.Beloro@Sun.COM 	    sun4v_env_print_indicator_callback);
17998574SJason.Beloro@Sun.COM }
18008574SJason.Beloro@Sun.COM 
18018574SJason.Beloro@Sun.COM static void
18023941Svenki sun4v_env_print_LEDs()
18033941Svenki {
18045028Sfw157321 	char *fmt = "%-34s %-14s %-8s\n";
18053941Svenki 	if (syserrlog == 0)
18063941Svenki 		return;
18073941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
18084669Sfw157321 	    (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
18093941Svenki 	if (!class_node_found)
18103941Svenki 		return;
18113941Svenki 	log_printf("\nLEDs:\n");
18125028Sfw157321 	log_printf("-------------------------------------------------"
18135028Sfw157321 	    "-----------\n");
18143941Svenki 	log_printf(fmt, "Location", "LED", "State", 0);
18155028Sfw157321 	log_printf("-------------------------------------------------"
18165028Sfw157321 	    "-----------\n");
18173941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
18184669Sfw157321 	    (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
18193941Svenki }
18203941Svenki 
18213941Svenki /*ARGSUSED*/
18223941Svenki static int
18233941Svenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args)
18243941Svenki {
18253941Svenki 	char label[PICL_PROPNAMELEN_MAX];
18263941Svenki 	char status[PICL_PROPNAMELEN_MAX];
18273941Svenki 	picl_errno_t err;
18283941Svenki 	picl_prophdl_t proph;
18293941Svenki 	picl_nodehdl_t parenth;
18303941Svenki 	char *names[PARENT_NAMES];
18313941Svenki 	char *loc;
18323941Svenki 	int i;
18333941Svenki 
18343941Svenki 	if (!class_node_found) {
18353941Svenki 		class_node_found = 1;
18363941Svenki 		return (PICL_WALK_TERMINATE);
18373941Svenki 	}
18383941Svenki 	err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph);
18393941Svenki 	if (err != PICL_SUCCESS)
18403941Svenki 		return (PICL_WALK_CONTINUE);
18413941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
18424669Sfw157321 	    sizeof (label));
18433941Svenki 	if (err != PICL_SUCCESS)
18443941Svenki 		return (PICL_WALK_CONTINUE);
18453941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
18464669Sfw157321 	    status, sizeof (status));
18473941Svenki 	if (err != PICL_SUCCESS)
18483941Svenki 		return (PICL_WALK_CONTINUE);
18493941Svenki 	if (syserrlog == 0) {
18503941Svenki 		if (strcmp(status, "disabled") == 0) {
18513941Svenki 			if (all_status_ok) {
18523941Svenki 				all_status_ok = 0;
18533941Svenki 				return (PICL_WALK_TERMINATE);
18543941Svenki 			}
18553941Svenki 		} else
18563941Svenki 			return (PICL_WALK_CONTINUE);
18573941Svenki 	}
1858*10070SBirva.Shah@Sun.COM 
1859*10070SBirva.Shah@Sun.COM 	if (is_fru_absent(nodeh))
1860*10070SBirva.Shah@Sun.COM 		strcpy(status, "Not present");
1861*10070SBirva.Shah@Sun.COM 
18623941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
18634669Sfw157321 	    sizeof (parenth));
18643941Svenki 	if (err != PICL_SUCCESS) {
18653941Svenki 		log_printf("\n");
18663941Svenki 		return (PICL_WALK_CONTINUE);
18673941Svenki 	}
18683941Svenki 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
18693941Svenki 		return (PICL_WALK_TERMINATE);
18703941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
18713941Svenki 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
18723941Svenki 			while (--i > -1)
18733941Svenki 				free(names[i]);
18743941Svenki 			free(loc);
18753941Svenki 			return (PICL_WALK_TERMINATE);
18763941Svenki 		}
18773941Svenki 	i = 0;
18783941Svenki 	while (err == PICL_SUCCESS) {
18794802Sfw157321 		if (parenth == phyplatformh)
18803941Svenki 			break;
18813941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
18824669Sfw157321 		    names[i++], PICL_PROPNAMELEN_MAX);
18833941Svenki 		if (err != PICL_SUCCESS) {
18843941Svenki 			i--;
18853941Svenki 			break;
18863941Svenki 		}
18873941Svenki 		if (i == PARENT_NAMES)
18883941Svenki 			break;
18893941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
18904669Sfw157321 		    &parenth, sizeof (parenth));
18913941Svenki 	}
18923941Svenki 	loc[0] = '\0';
18934003Svivek 	if (--i > -1) {
18944003Svivek 		(void) strlcat(loc, names[i],
18954669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18964003Svivek 	}
18973941Svenki 	while (--i > -1) {
18984003Svivek 		(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18994003Svivek 		(void) strlcat(loc, names[i],
19004669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
19013941Svenki 	}
19025028Sfw157321 	log_printf("%-35s", loc);
19033941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
19043941Svenki 		free(names[i]);
19053941Svenki 	free(loc);
19063941Svenki 	log_printf("%-10s", label);
19073941Svenki 	log_printf("%-9s", status);
19083941Svenki 	log_printf("\n");
19093941Svenki 	return (PICL_WALK_CONTINUE);
19103941Svenki }
19113941Svenki 
19123941Svenki static void
19133941Svenki sun4v_print_fru_status()
19143941Svenki {
19155028Sfw157321 	char *fmt = "%-34s %-9s %-8s\n";
19165436Sfw157321 
19173941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
19184669Sfw157321 	    sun4v_print_fru_status_callback);
19193941Svenki 	if (!class_node_found)
19203941Svenki 		return;
19215436Sfw157321 
19223941Svenki 	log_printf("\n");
19233941Svenki 	log_printf("============================");
19243941Svenki 	log_printf(" FRU Status ");
19253941Svenki 	log_printf("============================");
19263941Svenki 	log_printf("\n");
19273941Svenki 
19283941Svenki 	if (syserrlog == 0) {
19293941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
19304802Sfw157321 		    NULL, NULL,
19314669Sfw157321 		    sun4v_print_fru_status_callback);
19323941Svenki 		if (all_status_ok) {
19333941Svenki 			log_printf("All FRUs are enabled.\n");
19343941Svenki 			return;
19353941Svenki 		}
19363941Svenki 	}
19373941Svenki 	log_printf(fmt, "Location", "Name", "Status", 0);
19385028Sfw157321 	log_printf("------------------------------------------------------\n");
19394802Sfw157321 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
19404669Sfw157321 	    sun4v_print_fru_status_callback);
19413941Svenki }
19423941Svenki 
1943*10070SBirva.Shah@Sun.COM /*  Check the children of the FRU node for a presence indicator */
1944*10070SBirva.Shah@Sun.COM static int
1945*10070SBirva.Shah@Sun.COM is_fru_absent(picl_nodehdl_t fruh)
1946*10070SBirva.Shah@Sun.COM {
1947*10070SBirva.Shah@Sun.COM 	char class [PICL_CLASSNAMELEN_MAX];
1948*10070SBirva.Shah@Sun.COM 	char condition [PICL_PROPNAMELEN_MAX];
1949*10070SBirva.Shah@Sun.COM 	picl_errno_t err;
1950*10070SBirva.Shah@Sun.COM 	picl_nodehdl_t nodeh;
1951*10070SBirva.Shah@Sun.COM 
1952*10070SBirva.Shah@Sun.COM 	err = picl_get_propval_by_name(fruh, PICL_PROP_CHILD, &nodeh,
1953*10070SBirva.Shah@Sun.COM 	    sizeof (picl_nodehdl_t));
1954*10070SBirva.Shah@Sun.COM 	while (err == PICL_SUCCESS) {
1955*10070SBirva.Shah@Sun.COM 		err = picl_get_propval_by_name(nodeh,
1956*10070SBirva.Shah@Sun.COM 		    PICL_PROP_CLASSNAME, class, sizeof (class));
1957*10070SBirva.Shah@Sun.COM 		if (err == PICL_SUCCESS &&
1958*10070SBirva.Shah@Sun.COM 		    strcmp(class, "presence-indicator") == 0) {
1959*10070SBirva.Shah@Sun.COM 			err = picl_get_propval_by_name(nodeh,
1960*10070SBirva.Shah@Sun.COM 			    PICL_PROP_CONDITION, condition,
1961*10070SBirva.Shah@Sun.COM 			    sizeof (condition));
1962*10070SBirva.Shah@Sun.COM 			if (err == PICL_SUCCESS) {
1963*10070SBirva.Shah@Sun.COM 				if (strcmp(condition, "Absent") == 0) {
1964*10070SBirva.Shah@Sun.COM 					return (1);
1965*10070SBirva.Shah@Sun.COM 				} else	{
1966*10070SBirva.Shah@Sun.COM 					return (0);
1967*10070SBirva.Shah@Sun.COM 				}
1968*10070SBirva.Shah@Sun.COM 			}
1969*10070SBirva.Shah@Sun.COM 		}
1970*10070SBirva.Shah@Sun.COM 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
1971*10070SBirva.Shah@Sun.COM 		    &nodeh, sizeof (picl_nodehdl_t));
1972*10070SBirva.Shah@Sun.COM 	}
1973*10070SBirva.Shah@Sun.COM 	return (0);
1974*10070SBirva.Shah@Sun.COM }
1975*10070SBirva.Shah@Sun.COM 
19763941Svenki /*ARGSUSED*/
19773941Svenki static int
19783941Svenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args)
19793941Svenki {
19803941Svenki 	char rev[PICL_PROPNAMELEN_MAX];
19813941Svenki 	picl_errno_t err;
19823941Svenki 
19833941Svenki 	if (!class_node_found) {
19843941Svenki 		class_node_found = 1;
19853941Svenki 		return (PICL_WALK_TERMINATE);
19863941Svenki 	}
19875436Sfw157321 
19883941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev,
19894669Sfw157321 	    sizeof (rev));
19903941Svenki 	if (err != PICL_SUCCESS)
19913941Svenki 		return (PICL_WALK_CONTINUE);
19923941Svenki 	if (strlen(rev) == 0)
19933941Svenki 		return (PICL_WALK_CONTINUE);
19945436Sfw157321 	log_printf("%s", rev);
19953941Svenki 	log_printf("\n");
19963941Svenki 	return (PICL_WALK_CONTINUE);
19973941Svenki }
19983941Svenki 
19993941Svenki static void
20003941Svenki sun4v_print_fw_rev()
20013941Svenki {
20023941Svenki 	if (syserrlog == 0)
20033941Svenki 		return;
20045436Sfw157321 
20053941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
20064669Sfw157321 	    sun4v_print_fw_rev_callback);
20073941Svenki 	if (!class_node_found)
20083941Svenki 		return;
20095436Sfw157321 
20103941Svenki 	log_printf("\n");
20113941Svenki 	log_printf("============================");
20123941Svenki 	log_printf(" FW Version ");
20133941Svenki 	log_printf("============================");
20143941Svenki 	log_printf("\n");
20155436Sfw157321 	log_printf("Version\n");
20165028Sfw157321 	log_printf("-------------------------------------------------"
20175028Sfw157321 	    "-----------\n");
20183941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
20194669Sfw157321 	    sun4v_print_fw_rev_callback);
20203941Svenki }
20213941Svenki 
20223941Svenki static void
20235436Sfw157321 sun4v_print_openprom_rev()
20245436Sfw157321 {
20255436Sfw157321 	if (syserrlog == 0)
20265436Sfw157321 		return;
20275436Sfw157321 
20285436Sfw157321 	(void) picl_walk_tree_by_class(rooth, "openprom", NULL,
20295436Sfw157321 	    openprom_callback);
20305436Sfw157321 	if (!class_node_found)
20315436Sfw157321 		return;
20325436Sfw157321 
20335436Sfw157321 	log_printf("\n");
20345436Sfw157321 	log_printf("======================");
20355436Sfw157321 	log_printf(" System PROM revisions ");
20365436Sfw157321 	log_printf("=======================");
20375436Sfw157321 	log_printf("\n");
20385436Sfw157321 	log_printf("Version\n");
20395436Sfw157321 	log_printf("-------------------------------------------------"
20405436Sfw157321 	    "-----------\n");
20415436Sfw157321 	(void) picl_walk_tree_by_class(rooth, "openprom", NULL,
20425436Sfw157321 	    openprom_callback);
20435436Sfw157321 }
20445436Sfw157321 
20455436Sfw157321 /*
20465436Sfw157321  * display the OBP and POST prom revisions (if present)
20475436Sfw157321  */
20485436Sfw157321 /* ARGSUSED */
20495436Sfw157321 static int
20505436Sfw157321 openprom_callback(picl_nodehdl_t openpromh, void *arg)
20515436Sfw157321 {
20525436Sfw157321 	picl_prophdl_t	proph;
20535436Sfw157321 	picl_prophdl_t	tblh;
20545436Sfw157321 	picl_prophdl_t	rowproph;
20555436Sfw157321 	picl_propinfo_t	pinfo;
20565436Sfw157321 	char		*prom_version = NULL;
20575436Sfw157321 	char		*obp_version = NULL;
20585436Sfw157321 	int		err;
20595436Sfw157321 
20605436Sfw157321 	if (!class_node_found) {
20615436Sfw157321 		class_node_found = 1;
20625436Sfw157321 		return (PICL_WALK_TERMINATE);
20635436Sfw157321 	}
20645436Sfw157321 
20655436Sfw157321 	err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION,
20665436Sfw157321 	    &pinfo, &proph);
20675436Sfw157321 	if (err == PICL_PROPNOTFOUND)
20685436Sfw157321 		return (PICL_WALK_TERMINATE);
20695436Sfw157321 	else if (err != PICL_SUCCESS)
20705436Sfw157321 		return (err);
20715436Sfw157321 
20725436Sfw157321 	/*
20735436Sfw157321 	 * If it's a table prop, the first element is OBP revision
20745436Sfw157321 	 * The second one is POST revision.
20755436Sfw157321 	 * If it's a charstring prop, the value will be only OBP revision
20765436Sfw157321 	 */
20775436Sfw157321 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
20785436Sfw157321 		prom_version = (char *)alloca(pinfo.size);
20795436Sfw157321 		if (prom_version == NULL)
20805436Sfw157321 			return (PICL_FAILURE);
20815436Sfw157321 		err = picl_get_propval(proph, prom_version, pinfo.size);
20825436Sfw157321 		if (err != PICL_SUCCESS)
20835436Sfw157321 			return (err);
20845436Sfw157321 		log_printf("%s\n", prom_version);
20855436Sfw157321 	}
20865436Sfw157321 
20875436Sfw157321 	if (pinfo.type != PICL_PTYPE_TABLE)	/* not supported type */
20885436Sfw157321 		return (PICL_WALK_TERMINATE);
20895436Sfw157321 
20905436Sfw157321 	err = picl_get_propval(proph, &tblh, pinfo.size);
20915436Sfw157321 	if (err != PICL_SUCCESS)
20925436Sfw157321 		return (err);
20935436Sfw157321 
20945436Sfw157321 	err = picl_get_next_by_row(tblh, &rowproph);
20955436Sfw157321 	if (err == PICL_SUCCESS) {
20965436Sfw157321 		/* get first row */
20975436Sfw157321 		err = picl_get_propinfo(rowproph, &pinfo);
20985436Sfw157321 		if (err != PICL_SUCCESS)
20995436Sfw157321 			return (err);
21005436Sfw157321 
21015436Sfw157321 		prom_version = (char *)alloca(pinfo.size);
21025436Sfw157321 		if (prom_version == NULL)
21035436Sfw157321 			return (PICL_FAILURE);
21045436Sfw157321 
21055436Sfw157321 		err = picl_get_propval(rowproph, prom_version, pinfo.size);
21065436Sfw157321 		if (err != PICL_SUCCESS)
21075436Sfw157321 			return (err);
21085436Sfw157321 		log_printf("%s\n", prom_version);
21095436Sfw157321 
21105436Sfw157321 		/* get second row */
21115436Sfw157321 		err = picl_get_next_by_col(rowproph, &rowproph);
21125436Sfw157321 		if (err == PICL_SUCCESS) {
21135436Sfw157321 			err = picl_get_propinfo(rowproph, &pinfo);
21145436Sfw157321 			if (err != PICL_SUCCESS)
21155436Sfw157321 				return (err);
21165436Sfw157321 
21175436Sfw157321 			obp_version = (char *)alloca(pinfo.size);
21185436Sfw157321 			if (obp_version == NULL)
21195436Sfw157321 				return (PICL_FAILURE);
21205436Sfw157321 			err = picl_get_propval(rowproph, obp_version,
21215436Sfw157321 			    pinfo.size);
21225436Sfw157321 			if (err != PICL_SUCCESS)
21235436Sfw157321 				return (err);
21245436Sfw157321 			log_printf("%s\n", obp_version);
21255436Sfw157321 		}
21265436Sfw157321 	}
21275436Sfw157321 
21285436Sfw157321 	return (PICL_WALK_TERMINATE);
21295436Sfw157321 }
21305436Sfw157321 
21315436Sfw157321 static void
21323941Svenki sun4v_print_chassis_serial_no()
21333941Svenki {
21343941Svenki 	char val[PICL_PROPNAMELEN_MAX];
21353941Svenki 	picl_errno_t err;
21363941Svenki 	if (syserrlog == 0 || chassish == 0)
21373941Svenki 		return;
21383941Svenki 
21393941Svenki 	log_printf("\n");
21406014Ssuha 	log_printf("Chassis Serial Number");
21413941Svenki 	log_printf("\n");
21423941Svenki 	log_printf("---------------------\n");
21433941Svenki 	err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER,
21444669Sfw157321 	    val, sizeof (val));
21453941Svenki 	if (err == PICL_SUCCESS)
21463941Svenki 		log_printf("%s", val);
21473941Svenki 	log_printf("\n");
21483941Svenki }
2149