xref: /onnv-gate/usr/src/lib/libprtdiag/common/display_sun4v.c (revision 4928:7b72c4ee69c0)
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 /*
223941Svenki  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
231708Sstevel  * Use is subject to license terms.
241708Sstevel  */
251708Sstevel 
261708Sstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
271708Sstevel 
281708Sstevel #include <stdio.h>
291708Sstevel #include <stdlib.h>
301708Sstevel #include <unistd.h>
311708Sstevel #include <ctype.h>
321708Sstevel #include <string.h>
331708Sstevel #include <kvm.h>
341708Sstevel #include <varargs.h>
351708Sstevel #include <time.h>
361708Sstevel #include <dirent.h>
371708Sstevel #include <fcntl.h>
381708Sstevel #include <sys/param.h>
391708Sstevel #include <sys/stat.h>
401708Sstevel #include <sys/types.h>
411708Sstevel #include <sys/utsname.h>
421708Sstevel #include <sys/openpromio.h>
431708Sstevel #include <libintl.h>
441708Sstevel #include <syslog.h>
451708Sstevel #include <sys/dkio.h>
463941Svenki #include <sys/systeminfo.h>
473941Svenki #include <picldefs.h>
484802Sfw157321 #include <math.h>
494802Sfw157321 #include <errno.h>
501708Sstevel #include "pdevinfo.h"
511708Sstevel #include "display.h"
521708Sstevel #include "display_sun4v.h"
531708Sstevel #include "libprtdiag.h"
541708Sstevel 
551708Sstevel #if !defined(TEXT_DOMAIN)
561708Sstevel #define	TEXT_DOMAIN	"SYS_TEST"
571708Sstevel #endif
581708Sstevel 
594669Sfw157321 #define	MOTHERBOARD			"MB"
603941Svenki #define	NETWORK				"network"
613941Svenki #define	PCIE_COMPATIBLE_STR		"pciex"
623941Svenki #define	PCIX_COMPATIBLE_STR		"pci"
633941Svenki #define	SUN4V_MACHINE			"sun4v"
643941Svenki #define	PARENT_NAMES			10
653941Svenki 
663941Svenki /*
673941Svenki  * Additional OBP properties
683941Svenki  */
693941Svenki #define	OBP_PROP_COMPATIBLE		"compatible"
703941Svenki #define	OBP_PROP_MODEL			"model"
713941Svenki #define	OBP_PROP_SLOT_NAMES		"slot-names"
723941Svenki 
733941Svenki #define	PICL_NODE_PHYSICAL_PLATFORM	"physical-platform"
743941Svenki #define	PICL_NODE_CHASSIS		"chassis"
753941Svenki #define	MEMORY_SIZE_FIELD		11
763941Svenki #define	INVALID_THRESHOLD		1000000
773941Svenki 
783941Svenki /*
793941Svenki  * Additional picl classes
803941Svenki  */
813941Svenki #ifndef	PICL_CLASS_SUN4V
823941Svenki #define	PICL_CLASS_SUN4V		"sun4v"
833941Svenki #endif
843941Svenki 
853941Svenki #ifndef	PICL_PROP_NAC
863941Svenki #define	PICL_PROP_NAC			"nac"
873941Svenki #endif
883941Svenki 
893941Svenki extern int sys_clk;
903941Svenki extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *,
913941Svenki 	picl_nodehdl_t *);
923941Svenki 
933941Svenki static picl_nodehdl_t rooth = 0, phyplatformh = 0;
943941Svenki static picl_nodehdl_t chassish = 0;
953941Svenki static int class_node_found;
963941Svenki static int syserrlog;
973941Svenki static int all_status_ok;
983941Svenki 
993941Svenki /* local functions */
1003941Svenki static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **);
1013941Svenki static void sun4v_display_memory_conf(picl_nodehdl_t);
1023941Svenki static void sun4v_disp_env_status();
1033941Svenki static void sun4v_env_print_fan_sensors();
1043941Svenki static void sun4v_env_print_fan_indicators();
1053941Svenki static void sun4v_env_print_temp_sensors();
1063941Svenki static void sun4v_env_print_temp_indicators();
1073941Svenki static void sun4v_env_print_current_sensors();
1083941Svenki static void sun4v_env_print_current_indicators();
1093941Svenki static void sun4v_env_print_voltage_sensors();
1103941Svenki static void sun4v_env_print_voltage_indicators();
1113941Svenki static void sun4v_env_print_LEDs();
1123941Svenki static void sun4v_print_fru_status();
1133941Svenki static void sun4v_print_fw_rev();
1143941Svenki static void sun4v_print_chassis_serial_no();
1151708Sstevel 
1161708Sstevel int
1173941Svenki sun4v_display(Sys_tree *tree, Prom_node *root, int log,
1183941Svenki 	picl_nodehdl_t plafh)
1191708Sstevel {
1201708Sstevel 	void *value;		/* used for opaque PROM data */
1211708Sstevel 	struct mem_total memory_total;	/* Total memory in system */
1221708Sstevel 	struct grp_info grps;	/* Info on all groups in system */
1233941Svenki 	char machine[MAXSTRLEN];
1243941Svenki 
1253941Svenki 	if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1)
1263941Svenki 		return (1);
1273941Svenki 	if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0)
1283941Svenki 		return (1);
1291708Sstevel 
1301708Sstevel 	sys_clk = -1;  /* System clock freq. (in MHz) */
1311708Sstevel 
1321708Sstevel 	/*
1331708Sstevel 	 * Now display the machine's configuration. We do this if we
1341708Sstevel 	 * are not logging.
1351708Sstevel 	 */
1361708Sstevel 	if (!logging) {
1371708Sstevel 		struct utsname uts_buf;
1381708Sstevel 
1391708Sstevel 		/*
1401708Sstevel 		 * Display system banner
1411708Sstevel 		 */
1421708Sstevel 		(void) uname(&uts_buf);
1431708Sstevel 
1443941Svenki 		log_printf(dgettext(TEXT_DOMAIN, "System Configuration:  "
1454669Sfw157321 		    "Sun Microsystems  %s %s\n"), uts_buf.machine,
1464669Sfw157321 		    get_prop_val(find_prop(root, "banner-name")), 0);
1471708Sstevel 
1481708Sstevel 		/* display system clock frequency */
1491708Sstevel 		value = get_prop_val(find_prop(root, "clock-frequency"));
1501708Sstevel 		if (value != NULL) {
1511708Sstevel 			sys_clk = ((*((int *)value)) + 500000) / 1000000;
1521708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, "System clock "
1534669Sfw157321 			    "frequency: %d MHz\n"), sys_clk, 0);
1541708Sstevel 		}
1551708Sstevel 
1561708Sstevel 		/* Display the Memory Size */
1571708Sstevel 		display_memorysize(tree, NULL, &grps, &memory_total);
1581708Sstevel 
1591708Sstevel 		/* Display the CPU devices */
1601708Sstevel 		sun4v_display_cpu_devices(plafh);
1611708Sstevel 
1621708Sstevel 		/* Display the Memory configuration */
1633941Svenki 		class_node_found = 0;
1643941Svenki 		sun4v_display_memory_conf(plafh);
1651708Sstevel 
1661708Sstevel 		/* Display all the IO cards. */
1671708Sstevel 		(void) sun4v_display_pci(plafh);
1683941Svenki 		sun4v_display_diaginfo((log || (logging)), root, plafh);
1691708Sstevel 
1703941Svenki 		if (picl_get_root(&rooth) != PICL_SUCCESS)
1713941Svenki 			return (1);
1723941Svenki 		if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM,
1734669Sfw157321 		    &phyplatformh) != PICL_SUCCESS)
1743941Svenki 			return (1);
1753941Svenki 
1763941Svenki 		if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME,
1774669Sfw157321 		    PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
1784669Sfw157321 		    strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS)
1793941Svenki 			return (1);
1803941Svenki 
1813941Svenki 		syserrlog = log;
1823941Svenki 		sun4v_disp_env_status();
1833941Svenki 	}
1843941Svenki 	return (0);
1853941Svenki }
1863941Svenki 
1873941Svenki static void
1883941Svenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card)
1893941Svenki {
1903941Svenki 	char *compatible;
1913941Svenki 
1924003Svivek 	(void) strlcpy(card->bus_type, "PCIX", sizeof (card->bus_type));
1933941Svenki 	if (sun4v_get_first_compatible_value(nodeh, &compatible)
1944669Sfw157321 	    == PICL_SUCCESS) {
1953941Svenki 		if (strncmp(compatible, PCIE_COMPATIBLE_STR,
1964669Sfw157321 		    strlen(PCIE_COMPATIBLE_STR)) == 0)
1974003Svivek 			(void) strlcpy(card->bus_type, "PCIE",
1984669Sfw157321 			    sizeof (card->bus_type));
1993941Svenki 		free(compatible);
2003941Svenki 	}
2013941Svenki }
2023941Svenki 
2033941Svenki static picl_errno_t
2043941Svenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card)
2053941Svenki {
2063941Svenki 	char val[PICL_PROPNAMELEN_MAX];
2073941Svenki 	picl_errno_t err;
2083941Svenki 
2093941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
2104669Sfw157321 	    sizeof (val));
2113941Svenki 	if (err != PICL_SUCCESS)
2123941Svenki 		return (err);
2133941Svenki 
2144003Svivek 	(void) strlcpy(card->slot_str, val, sizeof (card->slot_str));
2153941Svenki 	card->slot = -1;
2163941Svenki 	return (PICL_SUCCESS);
2173941Svenki }
2183941Svenki 
2193941Svenki static void
2203941Svenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card)
2213941Svenki {
2223941Svenki 	picl_errno_t err;
2233941Svenki 	picl_prophdl_t proph;
2243941Svenki 	picl_propinfo_t pinfo;
2253941Svenki 	picl_nodehdl_t pnodeh;
2263941Svenki 	uint8_t *pval;
2273941Svenki 	uint32_t dev_mask;
2283941Svenki 	char uaddr[MAXSTRLEN];
2293941Svenki 	int i;
2303941Svenki 
2313941Svenki 	if (get_slot_label(nodeh, card) == PICL_SUCCESS)
2323941Svenki 		return;
2333941Svenki 	err = PICL_SUCCESS;
2343941Svenki 	while (err == PICL_SUCCESS) {
2353941Svenki 		if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
2364669Sfw157321 		    sizeof (pnodeh)) != PICL_SUCCESS) {
2374669Sfw157321 			(void) strlcpy(card->slot_str, MOTHERBOARD,
2384669Sfw157321 			    sizeof (card->slot_str));
2393941Svenki 			card->slot = -1;
2403941Svenki 			return;
2413941Svenki 		}
2423941Svenki 		if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES,
2434669Sfw157321 		    &pinfo, &proph) == PICL_SUCCESS) {
2443941Svenki 			break;
2453941Svenki 		}
2463941Svenki 		nodeh = pnodeh;
2473941Svenki 	}
2483941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr,
2494669Sfw157321 	    sizeof (uaddr)) != PICL_SUCCESS) {
2504669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
2514669Sfw157321 		    sizeof (card->slot_str));
2523941Svenki 		card->slot = -1;
2533941Svenki 		return;
2543941Svenki 	}
2553941Svenki 	pval = (uint8_t *)malloc(pinfo.size);
2563941Svenki 	if (!pval) {
2574669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
2584669Sfw157321 		    sizeof (card->slot_str));
2593941Svenki 		card->slot = -1;
2603941Svenki 		return;
2613941Svenki 	}
2623941Svenki 	if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) {
2634669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
2644669Sfw157321 		    sizeof (card->slot_str));
2653941Svenki 		card->slot = -1;
2663941Svenki 		free(pval);
2673941Svenki 		return;
2681708Sstevel 	}
2691708Sstevel 
2703941Svenki 	dev_mask = 0;
2713941Svenki 	for (i = 0; i < sizeof (dev_mask); i++)
2723941Svenki 		dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i));
2733941Svenki 	for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) {
2743941Svenki 		if (uaddr[i] == ',') {
2753941Svenki 			uaddr[i] = '\0';
2763941Svenki 			break;
2773941Svenki 		}
2783941Svenki 	}
2793941Svenki 	card->slot = atol(uaddr);
2803941Svenki 	if (((1 << card->slot) & dev_mask) == 0) {
2814669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
2824669Sfw157321 		    sizeof (card->slot_str));
2833941Svenki 		card->slot = -1;
2843941Svenki 	} else {
2853941Svenki 		char *p = (char *)(pval+sizeof (dev_mask));
2863941Svenki 		int shift = sizeof (uint32_t)*8-1-card->slot;
2873941Svenki 		uint32_t x = (dev_mask << shift) >> shift;
2883941Svenki 		int count = 0;	/* count # of 1's in x */
2893941Svenki 		int i = 0;
2903941Svenki 		while (x != 0) {
2913941Svenki 			count++;
2923941Svenki 			x &= x-1;
2933941Svenki 		}
2943941Svenki 		while (count > 1) {
2954669Sfw157321 			while (p[i++] != '\0')
2964669Sfw157321 				;
2973941Svenki 			count--;
2983941Svenki 		}
2994003Svivek 		(void) strlcpy(card->slot_str, (char *)(p+i),
3004669Sfw157321 		    sizeof (card->slot_str));
3013941Svenki 	}
3023941Svenki 	free(pval);
3033941Svenki }
3043941Svenki 
3053941Svenki /*
3063941Svenki  * add all io devices under pci in io list
3073941Svenki  */
3083941Svenki /* ARGSUSED */
3093941Svenki static int
3103941Svenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args)
3113941Svenki {
3123941Svenki 	char path[PICL_PROPNAMELEN_MAX];
3133941Svenki 	char class[PICL_CLASSNAMELEN_MAX];
3143941Svenki 	char name[PICL_PROPNAMELEN_MAX];
3153941Svenki 	char model[PICL_PROPNAMELEN_MAX];
3163941Svenki 	char binding_name[PICL_PROPNAMELEN_MAX];
3173941Svenki 	char val[PICL_PROPNAMELEN_MAX];
3183941Svenki 	char *compatible;
3193941Svenki 	picl_errno_t err;
3203941Svenki 	picl_nodehdl_t nodeh;
3213941Svenki 	struct io_card pci_card;
3223941Svenki 
3233941Svenki 	/* Walk through the children */
3243941Svenki 
3253941Svenki 	err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
3264669Sfw157321 	    sizeof (picl_nodehdl_t));
3273941Svenki 
3283941Svenki 	while (err == PICL_SUCCESS) {
3293941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
3304669Sfw157321 		    class, sizeof (class));
3313941Svenki 		if (err !=  PICL_SUCCESS)
3323941Svenki 			return (err);
3333941Svenki 
3343941Svenki 		if (args) {
3353941Svenki 			char *val = args;
3363941Svenki 			if (strcmp(class, val) == 0) {
3373941Svenki 				err = picl_get_propval_by_name(nodeh,
3384669Sfw157321 				    PICL_PROP_PEER, &nodeh,
3394669Sfw157321 				    sizeof (picl_nodehdl_t));
3403941Svenki 				continue;
3413941Svenki 			} else if (strcmp(val, PICL_CLASS_PCIEX) == 0 &&
3424669Sfw157321 			    strcmp(class, PICL_CLASS_PCI) == 0) {
3433941Svenki 				err = picl_get_propval_by_name(nodeh,
3444669Sfw157321 				    PICL_PROP_PEER, &nodeh,
3454669Sfw157321 				    sizeof (picl_nodehdl_t));
3463941Svenki 				continue;
3473941Svenki 			} else if (strcmp(val, PICL_CLASS_PCI) == 0 &&
3484669Sfw157321 			    strcmp(class, PICL_CLASS_PCIEX) == 0) {
3493941Svenki 				err = picl_get_propval_by_name(nodeh,
3504669Sfw157321 				    PICL_PROP_PEER, &nodeh,
3514669Sfw157321 				    sizeof (picl_nodehdl_t));
3523941Svenki 				continue;
3533941Svenki 			}
3543941Svenki 		}
3553941Svenki 
3563941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
3574669Sfw157321 		    path, sizeof (path));
3583941Svenki 		if (err != PICL_SUCCESS)
3593941Svenki 			return (err);
3603941Svenki 
3613941Svenki 		(void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
3623941Svenki 
3633941Svenki 		get_bus_type(nodeh, &pci_card);
3643941Svenki 		get_slot_number(nodeh, &pci_card);
3653941Svenki 
3663941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name,
3674669Sfw157321 		    sizeof (name));
3683941Svenki 		if (err == PICL_PROPNOTFOUND)
3694003Svivek 			(void) strlcpy(name, "", sizeof (name));
3703941Svenki 		else if (err != PICL_SUCCESS)
3713941Svenki 			return (err);
3723941Svenki 
3733941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val,
3744669Sfw157321 		    sizeof (val));
3753941Svenki 		if (err == PICL_PROPNOTFOUND)
3764003Svivek 			(void) strlcpy(val, "", sizeof (val));
3773941Svenki 		else if (err != PICL_SUCCESS)
3783941Svenki 			return (err);
3793941Svenki 
3803941Svenki 		/* Figure NAC name */
3813941Svenki 		if (pci_card.slot != -1)
3823941Svenki 			(void) snprintf(pci_card.status,
3834669Sfw157321 			    sizeof (pci_card.status),
3844669Sfw157321 			    "%s%d", pci_card.slot_str,
3854669Sfw157321 			    pci_card.slot);
3863941Svenki 		else
3873941Svenki 			(void) snprintf(pci_card.status,
3884669Sfw157321 			    sizeof (pci_card.status),
3894669Sfw157321 			    "%s", pci_card.slot_str);
3903941Svenki 
3913941Svenki 		/*
3923941Svenki 		 * Get the name of this card. If binding_name is found,
3933941Svenki 		 * name will be <nodename>-<binding_name>.
3943941Svenki 		 */
3953941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
3964669Sfw157321 		    binding_name, sizeof (binding_name));
3973941Svenki 		if (err == PICL_SUCCESS) {
3983941Svenki 			if (strcmp(name, binding_name) != 0) {
3993941Svenki 				(void) strlcat(name, "-", sizeof (name));
4003941Svenki 				(void) strlcat(name, binding_name,
4014669Sfw157321 				    sizeof (name));
4023941Svenki 			}
4033941Svenki 		} else if (err == PICL_PROPNOTFOUND) {
4043941Svenki 			/*
4053941Svenki 			 * if compatible prop is not found, name will be
4063941Svenki 			 * <nodename>-<compatible>
4073941Svenki 			 */
4083941Svenki 			err = sun4v_get_first_compatible_value(nodeh,
4094669Sfw157321 			    &compatible);
4103941Svenki 			if (err == PICL_SUCCESS) {
4113941Svenki 				(void) strlcat(name, "-", sizeof (name));
4124003Svivek 				(void) strlcat(name, compatible,
4134669Sfw157321 				    sizeof (name));
4143941Svenki 				free(compatible);
4153941Svenki 			}
4163941Svenki 		} else
4173941Svenki 			return (err);
4183941Svenki 
4193941Svenki 		(void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
4203941Svenki 
4213941Svenki 		/* Get the model of this card */
4223941Svenki 
4233941Svenki 		err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
4244669Sfw157321 		    model, sizeof (model));
4253941Svenki 		if (err == PICL_PROPNOTFOUND)
4264003Svivek 			(void) strlcpy(model, "", sizeof (model));
4273941Svenki 		else if (err != PICL_SUCCESS)
4283941Svenki 			return (err);
4293941Svenki 		(void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
4303941Svenki 
4313941Svenki 		/* Print NAC name */
4324802Sfw157321 		log_printf("%-18s", pci_card.status);
4333941Svenki 		/* Print IO Type */
4343941Svenki 		log_printf("%-6s", pci_card.bus_type);
4353941Svenki 		/* Printf Card Name */
4364802Sfw157321 		log_printf("%-44s", pci_card.name);
4373941Svenki 		/* Print Card Model */
4383941Svenki 		log_printf("%-8s", pci_card.model);
4393941Svenki 		log_printf("\n");
4403941Svenki 		/* Print Status */
4414802Sfw157321 		log_printf("%-18s", val);
4423941Svenki 		/* Print IO Type */
4433941Svenki 		log_printf("%-6s", "");
4443941Svenki 		/* Print Parent Path */
4454802Sfw157321 		log_printf("%-44s", pci_card.notes);
4463941Svenki 		log_printf("\n");
4473941Svenki 
4483941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
4494669Sfw157321 		    sizeof (picl_nodehdl_t));
4503941Svenki 	}
4513941Svenki 	return (PICL_WALK_CONTINUE);
4521708Sstevel }
4531708Sstevel 
4541708Sstevel /*
4551708Sstevel  * display_pci
4561708Sstevel  * Display all the PCI IO cards on this board.
4571708Sstevel  */
4581708Sstevel void
4591708Sstevel sun4v_display_pci(picl_nodehdl_t plafh)
4601708Sstevel {
4614802Sfw157321 	char *fmt = "%-17s %-5s %-44s %-8s";
4623941Svenki 	/* Have we printed the column headings? */
4633941Svenki 	static int banner = FALSE;
4643941Svenki 
4653941Svenki 	if (banner == FALSE) {
4663941Svenki 		log_printf("\n");
4674802Sfw157321 		log_printf("================================");
4683941Svenki 		log_printf(" IO Devices ");
4694802Sfw157321 		log_printf("================================");
4703941Svenki 		log_printf("\n");
4713941Svenki 		log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0);
4723941Svenki 		log_printf("\n");
4733941Svenki 		log_printf(fmt, "Status", "Type", "Path", "", 0);
4743941Svenki 		log_printf("\n");
4753941Svenki 		log_printf("---------------------------------"
4764802Sfw157321 		    "-------------------------------------------\n");
4773941Svenki 		banner = TRUE;
4783941Svenki 	}
4793941Svenki 
4803941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
4814669Sfw157321 	    PICL_CLASS_PCIEX, sun4v_pci_callback);
4823941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
4834669Sfw157321 	    PICL_CLASS_PCI, sun4v_pci_callback);
4843941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V,
4854669Sfw157321 	    PICL_CLASS_SUN4V, sun4v_pci_callback);
4863941Svenki }
4873941Svenki 
4883941Svenki /*
4893941Svenki  * return the first compatible value
4903941Svenki  */
4913941Svenki static int
4923941Svenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
4933941Svenki {
4943941Svenki 	picl_errno_t err;
4953941Svenki 	picl_prophdl_t proph;
4963941Svenki 	picl_propinfo_t pinfo;
4973941Svenki 	picl_prophdl_t tblh;
4983941Svenki 	picl_prophdl_t rowproph;
4993941Svenki 	char *pval;
5003941Svenki 
5013941Svenki 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
5024669Sfw157321 	    &pinfo, &proph);
5033941Svenki 	if (err != PICL_SUCCESS)
5043941Svenki 		return (err);
5053941Svenki 
5063941Svenki 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
5073941Svenki 		pval = malloc(pinfo.size);
5083941Svenki 		if (pval == NULL)
5093941Svenki 			return (PICL_FAILURE);
5103941Svenki 		err = picl_get_propval(proph, pval, pinfo.size);
5113941Svenki 		if (err != PICL_SUCCESS) {
5123941Svenki 			free(pval);
5133941Svenki 			return (err);
5143941Svenki 		}
5153941Svenki 		*outbuf = pval;
5163941Svenki 		return (PICL_SUCCESS);
5173941Svenki 	}
5183941Svenki 
5193941Svenki 	if (pinfo.type != PICL_PTYPE_TABLE)
5203941Svenki 		return (PICL_FAILURE);
5213941Svenki 
5223941Svenki 	/* get first string from table */
5233941Svenki 	err = picl_get_propval(proph, &tblh, pinfo.size);
5243941Svenki 	if (err != PICL_SUCCESS)
5253941Svenki 		return (err);
5263941Svenki 
5273941Svenki 	err = picl_get_next_by_row(tblh, &rowproph);
5283941Svenki 	if (err != PICL_SUCCESS)
5293941Svenki 		return (err);
5303941Svenki 
5313941Svenki 	err = picl_get_propinfo(rowproph, &pinfo);
5323941Svenki 	if (err != PICL_SUCCESS)
5333941Svenki 		return (err);
5343941Svenki 
5353941Svenki 	pval = malloc(pinfo.size);
5363941Svenki 	if (pval == NULL)
5373941Svenki 		return (PICL_FAILURE);
5383941Svenki 
5393941Svenki 	err = picl_get_propval(rowproph, pval, pinfo.size);
5403941Svenki 	if (err != PICL_SUCCESS) {
5413941Svenki 		free(pval);
5423941Svenki 		return (err);
5433941Svenki 	}
5443941Svenki 
5453941Svenki 	*outbuf = pval;
5463941Svenki 	return (PICL_SUCCESS);
5471708Sstevel }
5481708Sstevel 
5493941Svenki /*
5503941Svenki  * print size of a memory segment
5513941Svenki  */
5523941Svenki static void
5533941Svenki print_memory_segment_size(uint64_t size)
5543941Svenki {
5553941Svenki 	uint64_t kbyte = 1024;
5563941Svenki 	uint64_t mbyte = kbyte * kbyte;
5573941Svenki 	uint64_t gbyte = kbyte * mbyte;
5583941Svenki 	char buf[MEMORY_SIZE_FIELD];
5593941Svenki 
5603941Svenki 	if (size >= gbyte) {
5613941Svenki 		if (size % gbyte == 0)
5623941Svenki 			(void) snprintf(buf, sizeof (buf), "%d GB",
5634669Sfw157321 			    (int)(size / gbyte));
5643941Svenki 		else
5653941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f GB",
5664669Sfw157321 			    (float)size / gbyte);
5673941Svenki 	} else if (size >= mbyte) {
5683941Svenki 		if (size % mbyte == 0)
5693941Svenki 			(void) snprintf(buf, sizeof (buf), "%d MB",
5704669Sfw157321 			    (int)(size / mbyte));
5713941Svenki 		else
5723941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f MB",
5734669Sfw157321 			    (float)size / mbyte);
5743941Svenki 	} else {
5753941Svenki 		if (size % kbyte == 0)
5763941Svenki 			(void) snprintf(buf, sizeof (buf), "%d KB",
5774669Sfw157321 			    (int)(size / kbyte));
5783941Svenki 		else
5793941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f KB",
5804669Sfw157321 			    (float)size / kbyte);
5813941Svenki 	}
5823941Svenki 	log_printf("%-7s ", buf);
5833941Svenki }
5843941Svenki 
5853941Svenki /*
5864669Sfw157321  * Enumerate banks and dimms within a memory segment.  We're handed
5874669Sfw157321  * the first bank within the segment - we assume there are dimms
5884669Sfw157321  * (memory-module) nodes underneath.
5893941Svenki  */
5903941Svenki static void
5914669Sfw157321 print_memory_segment_contain(picl_nodehdl_t bank_nodeh)
5921708Sstevel {
5933941Svenki 	char val[PICL_PROPNAMELEN_MAX];
5944669Sfw157321 	picl_nodehdl_t module_nodeh;
5954669Sfw157321 	int flag = 0;
5964669Sfw157321 
5974669Sfw157321 	do {
5984669Sfw157321 		if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD,
5994669Sfw157321 		    &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS)
6004669Sfw157321 			continue;
6014669Sfw157321 		do {
6024669Sfw157321 			if (picl_get_propval_by_name(module_nodeh,
6034669Sfw157321 			    PICL_PROP_NAC, val, sizeof (val)) !=
6044669Sfw157321 			    PICL_SUCCESS)
6054669Sfw157321 				continue;
6064669Sfw157321 			else {
6074669Sfw157321 				if (!flag) {
6084669Sfw157321 					log_printf("%-30s\n", val);
6094669Sfw157321 					flag = 1;
6104669Sfw157321 				} else
6114669Sfw157321 					log_printf("%57s\n", val);
6124669Sfw157321 			}
6134669Sfw157321 		} while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER,
6144669Sfw157321 		    &module_nodeh, sizeof (picl_nodehdl_t)) ==
6154669Sfw157321 		    PICL_SUCCESS);
6164669Sfw157321 	} while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER,
6174669Sfw157321 	    &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS);
6183941Svenki }
6193941Svenki 
6203941Svenki /*
6213941Svenki  * Search node where _class=="memory-segment"
6223941Svenki  * print "Base Address", "Size", etc
6233941Svenki  */
6243941Svenki /*ARGSUSED*/
6253941Svenki static int
6263941Svenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args)
6273941Svenki {
6283941Svenki 	uint64_t base;
6293941Svenki 	uint64_t size;
6303941Svenki 	uint64_t ifactor;
6313941Svenki 	picl_errno_t err = PICL_SUCCESS;
6323941Svenki 
6333941Svenki 	if (class_node_found == 0) {
6343941Svenki 		class_node_found = 1;
6353941Svenki 		return (PICL_WALK_TERMINATE);
6363941Svenki 	}
6373941Svenki 	while (err == PICL_SUCCESS) {
6383941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS,
6394669Sfw157321 		    &base, sizeof (base));
6403941Svenki 		if (err !=  PICL_SUCCESS)
6413941Svenki 			break;
6423941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE,
6434669Sfw157321 		    &size, sizeof (size));
6443941Svenki 		if (err !=  PICL_SUCCESS)
6453941Svenki 			break;
6463941Svenki 		err = picl_get_propval_by_name(nodeh,
6474669Sfw157321 		    PICL_PROP_INTERLEAVE_FACTOR, &ifactor,
6484669Sfw157321 		    sizeof (ifactor));
6493941Svenki 		if (err !=  PICL_SUCCESS)
6503941Svenki 			break;
6513941Svenki 		log_printf("%-13llx", base);
6523941Svenki 		print_memory_segment_size(size);
6534669Sfw157321 		log_printf("%-18lld", ifactor);
6544669Sfw157321 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
6554669Sfw157321 		    &nodeh, sizeof (nodeh));
6564669Sfw157321 		if (err ==  PICL_SUCCESS)
6574669Sfw157321 			print_memory_segment_contain(nodeh);
6583941Svenki 		log_printf("\n");
6593941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
6604669Sfw157321 		    sizeof (picl_nodehdl_t));
6613941Svenki 	}
6623941Svenki 
6633941Svenki 	return (PICL_WALK_CONTINUE);
6643941Svenki }
6653941Svenki 
6663941Svenki /*ARGSUSED*/
6673941Svenki void
6683941Svenki sun4v_display_memory_conf(picl_nodehdl_t plafh)
6693941Svenki {
6703941Svenki 	char *fmt = "%-12s %-7s %-9s %-20s";
6713941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
6724669Sfw157321 	    NULL, sun4v_memory_conf_callback);
6733941Svenki 	if (class_node_found == 0)
6743941Svenki 		return;
6753941Svenki 	log_printf("\n");
6763941Svenki 	log_printf("============================");
6773941Svenki 	log_printf(" Memory Configuration ");
6783941Svenki 	log_printf("============================");
6793941Svenki 	log_printf("\n");
6803941Svenki 	log_printf("Segment Table:\n");
6814669Sfw157321 	log_printf(
6824669Sfw157321 	    "---------------------------------------------------------\n");
6833941Svenki 	log_printf(fmt, "Base Address", "Size", "Interleave Factor",
6844669Sfw157321 	    "Contains", 0);
6853941Svenki 	log_printf("\n");
6864669Sfw157321 	log_printf(
6874669Sfw157321 	    "---------------------------------------------------------\n");
6883941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
6894669Sfw157321 	    NULL, sun4v_memory_conf_callback);
6901708Sstevel }
6911708Sstevel 
6921708Sstevel void
6931708Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh)
6941708Sstevel {
6953941Svenki 	char *fmt = "%-12s %-5s %-8s %-19s %-5s";
6961708Sstevel 
6971708Sstevel 	/*
6981708Sstevel 	 * Display the table header for CPUs . Then display the CPU
6991708Sstevel 	 * frequency, cache size, and processor revision of all cpus.
7001708Sstevel 	 */
7011708Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
7024669Sfw157321 	    "\n"
7034669Sfw157321 	    "========================="
7044669Sfw157321 	    " CPUs "
7054669Sfw157321 	    "==============================================="
7064669Sfw157321 	    "\n"
7074669Sfw157321 	    "\n"));
7081708Sstevel 	log_printf(fmt, "", "", "", "CPU", "CPU", 0);
7091708Sstevel 	log_printf("\n");
7101708Sstevel 	log_printf(fmt, "Location", "CPU", "Freq",
7114669Sfw157321 	    "Implementation", "Mask", 0);
7121708Sstevel 	log_printf("\n");
7131708Sstevel 	log_printf(fmt, "------------", "-----", "--------",
7144669Sfw157321 	    "-------------------", "-----", 0);
7151708Sstevel 	log_printf("\n");
7161708Sstevel 
7171708Sstevel 	(void) picl_walk_tree_by_class(plafh, "cpu", "cpu", sun4v_display_cpus);
7181708Sstevel }
7191708Sstevel 
7201708Sstevel /*
7211708Sstevel  * Display the CPUs present on this board.
7221708Sstevel  */
7231708Sstevel /*ARGSUSED*/
7241708Sstevel int
7251708Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
7261708Sstevel {
7271708Sstevel 	int status;
7283941Svenki 	picl_prophdl_t proph;
7293941Svenki 	picl_prophdl_t tblh;
7303941Svenki 	picl_prophdl_t rowproph;
7311708Sstevel 	picl_propinfo_t propinfo;
7323941Svenki 	int *int_value;
7333941Svenki 	uint64_t cpuid, mask_no;
7343941Svenki 	char *comp_value;
7353941Svenki 	char *no_prop_value = "   ";
7363941Svenki 	char freq_str[MAXSTRLEN];
7373941Svenki 	char fru_name[MAXSTRLEN];
7381708Sstevel 
7391708Sstevel 	/*
7401708Sstevel 	 * Get cpuid property and print it and the NAC name
7411708Sstevel 	 */
7421708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "cpuid", &propinfo, &proph);
7431708Sstevel 	if (status == PICL_SUCCESS) {
7441708Sstevel 		status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
7451708Sstevel 		if (status != PICL_SUCCESS) {
7463941Svenki 			log_printf("%-13s", no_prop_value);
7473941Svenki 			log_printf("%-6s", no_prop_value);
7481708Sstevel 		} else {
7491708Sstevel 			(void) snprintf(fru_name, sizeof (fru_name), "%s%d",
7501708Sstevel 			    CPU_STRAND_NAC, (int)cpuid);
7513941Svenki 			log_printf("%-13s", fru_name);
7523941Svenki 			log_printf("%-6d", (int)cpuid);
7531708Sstevel 		}
7541708Sstevel 	} else {
7553941Svenki 		log_printf("%-13s", no_prop_value);
7563941Svenki 		log_printf("%-6s", no_prop_value);
7571708Sstevel 	}
7581708Sstevel 
7591708Sstevel clock_freq:
7601708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
7614669Sfw157321 	    &proph);
7621708Sstevel 	if (status == PICL_SUCCESS) {
7631708Sstevel 		int_value = malloc(propinfo.size);
7641708Sstevel 		if (int_value == NULL) {
7653941Svenki 			log_printf("%-9s", no_prop_value);
7661708Sstevel 			goto compatible;
7671708Sstevel 		}
7681708Sstevel 		status = picl_get_propval(proph, int_value, propinfo.size);
7691708Sstevel 		if (status != PICL_SUCCESS) {
7703941Svenki 			log_printf("%-9s", no_prop_value);
7711708Sstevel 		} else {
7721708Sstevel 			/* Running frequency */
7731708Sstevel 			(void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
7741708Sstevel 			    CLK_FREQ_TO_MHZ(*int_value));
7753941Svenki 			log_printf("%-9s", freq_str);
7761708Sstevel 		}
7771708Sstevel 		free(int_value);
7781708Sstevel 	} else
7793941Svenki 		log_printf("%-9s", no_prop_value);
7801708Sstevel 
7811708Sstevel compatible:
7821708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
7834669Sfw157321 	    &proph);
7841708Sstevel 	if (status == PICL_SUCCESS) {
7851708Sstevel 		if (propinfo.type == PICL_PTYPE_CHARSTRING) {
7861708Sstevel 			/*
7871708Sstevel 			 * Compatible Property only has 1 value
7881708Sstevel 			 */
7891708Sstevel 			comp_value = malloc(propinfo.size);
7901708Sstevel 			if (comp_value == NULL) {
7913941Svenki 				log_printf("%-20s", no_prop_value, 0);
7921708Sstevel 				goto mask;
7931708Sstevel 			}
7941708Sstevel 			status = picl_get_propval(proph, comp_value,
7954669Sfw157321 			    propinfo.size);
7963941Svenki 			if (status != PICL_SUCCESS)
7973941Svenki 				log_printf("%-20s", no_prop_value, 0);
7983941Svenki 			else
7993941Svenki 				log_printf("%-20s", comp_value, 0);
8003941Svenki 			free(comp_value);
8011708Sstevel 		} else if (propinfo.type == PICL_PTYPE_TABLE) {
8021708Sstevel 			/*
8031708Sstevel 			 * Compatible Property has multiple values
8041708Sstevel 			 */
8051708Sstevel 			status = picl_get_propval(proph, &tblh, propinfo.size);
8061708Sstevel 			if (status != PICL_SUCCESS) {
8073941Svenki 				log_printf("%-20s", no_prop_value, 0);
8081708Sstevel 				goto mask;
8091708Sstevel 			}
8101708Sstevel 			status = picl_get_next_by_row(tblh, &rowproph);
8111708Sstevel 			if (status != PICL_SUCCESS) {
8123941Svenki 				log_printf("%-20s", no_prop_value, 0);
8131708Sstevel 				goto mask;
8141708Sstevel 			}
8151708Sstevel 
8161708Sstevel 			status = picl_get_propinfo(rowproph, &propinfo);
8171708Sstevel 			if (status != PICL_SUCCESS) {
8183941Svenki 				log_printf("%-20s", no_prop_value, 0);
8191708Sstevel 				goto mask;
8201708Sstevel 			}
8211708Sstevel 
8221708Sstevel 			comp_value = malloc(propinfo.size);
8231708Sstevel 			if (comp_value == NULL) {
8243941Svenki 				log_printf("%-20s", no_prop_value, 0);
8251708Sstevel 				goto mask;
8261708Sstevel 			}
8271708Sstevel 			status = picl_get_propval(rowproph, comp_value,
8284669Sfw157321 			    propinfo.size);
8293941Svenki 			if (status != PICL_SUCCESS)
8303941Svenki 				log_printf("%-20s", no_prop_value, 0);
8313941Svenki 			else
8323941Svenki 				log_printf("%-20s", comp_value, 0);
8331708Sstevel 			free(comp_value);
8341708Sstevel 		}
8351708Sstevel 	} else
8363941Svenki 		log_printf("%-20s", no_prop_value, 0);
8371708Sstevel 
8381708Sstevel mask:
8391708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "mask#", &propinfo, &proph);
8401708Sstevel 	if (status == PICL_SUCCESS) {
8411708Sstevel 		status = picl_get_propval(proph, &mask_no, sizeof (mask_no));
8421708Sstevel 		if (status != PICL_SUCCESS) {
8433941Svenki 			log_printf("%-9s", no_prop_value);
8441708Sstevel 		} else {
8451708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, " %2d.%d"),
8464669Sfw157321 			    (mask_no>> 4) & 0xf, mask_no & 0xf);
8471708Sstevel 		}
8481708Sstevel 	} else
8493941Svenki 		log_printf("%-9s", no_prop_value);
8501708Sstevel 
8511708Sstevel done:
8521708Sstevel 	log_printf("\n");
8531708Sstevel 	return (PICL_WALK_CONTINUE);
8541708Sstevel }
8551708Sstevel 
8561708Sstevel void
8571708Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
8581708Sstevel {
8591708Sstevel #ifdef	lint
8601708Sstevel 	flag = flag;
8611708Sstevel 	root = root;
8621708Sstevel 	plafh = plafh;
8631708Sstevel #endif
8641708Sstevel 	/*
8651708Sstevel 	 * This function is intentionally empty
8661708Sstevel 	 */
8671708Sstevel }
8681708Sstevel 
8691708Sstevel void
8701708Sstevel display_boardnum(int num)
8711708Sstevel {
8721708Sstevel 	log_printf("%2d   ", num, 0);
8731708Sstevel }
8743941Svenki 
8753941Svenki static void
8763941Svenki sun4v_disp_env_status()
8773941Svenki {
8783941Svenki 	if (phyplatformh == 0)
8793941Svenki 		return;
8803941Svenki 	log_printf("\n");
8813941Svenki 	log_printf("============================");
8823941Svenki 	log_printf(" Environmental Status ");
8833941Svenki 	log_printf("============================");
8843941Svenki 	log_printf("\n");
8853941Svenki 
8863941Svenki 	class_node_found = 0;
8873941Svenki 	all_status_ok = 1;
8883941Svenki 	sun4v_env_print_fan_sensors();
8893941Svenki 
8903941Svenki 	class_node_found = 0;
8913941Svenki 	all_status_ok = 1;
8923941Svenki 	sun4v_env_print_fan_indicators();
8933941Svenki 
8943941Svenki 	class_node_found = 0;
8953941Svenki 	all_status_ok = 1;
8963941Svenki 	sun4v_env_print_temp_sensors();
8973941Svenki 
8983941Svenki 	class_node_found = 0;
8993941Svenki 	all_status_ok = 1;
9003941Svenki 	sun4v_env_print_temp_indicators();
9013941Svenki 
9023941Svenki 	class_node_found = 0;
9033941Svenki 	all_status_ok = 1;
9043941Svenki 	sun4v_env_print_current_sensors();
9053941Svenki 
9063941Svenki 	class_node_found = 0;
9073941Svenki 	all_status_ok = 1;
9083941Svenki 	sun4v_env_print_current_indicators();
9093941Svenki 
9103941Svenki 	class_node_found = 0;
9113941Svenki 	all_status_ok = 1;
9123941Svenki 	sun4v_env_print_voltage_sensors();
9133941Svenki 
9143941Svenki 	class_node_found = 0;
9153941Svenki 	all_status_ok = 1;
9163941Svenki 	sun4v_env_print_voltage_indicators();
9173941Svenki 
9183941Svenki 	class_node_found = 0;
9193941Svenki 	sun4v_env_print_LEDs();
9203941Svenki 
9213941Svenki 	class_node_found = 0;
9223941Svenki 	all_status_ok = 1;
9233941Svenki 	sun4v_print_fru_status();
9243941Svenki 
9253941Svenki 	class_node_found = 0;
9263941Svenki 	sun4v_print_fw_rev();
9273941Svenki 
9283941Svenki 	sun4v_print_chassis_serial_no();
9293941Svenki }
9303941Svenki 
9313941Svenki /*ARGSUSED*/
9323941Svenki static int
9333941Svenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args)
9343941Svenki {
9353941Svenki 	char val[PICL_PROPNAMELEN_MAX];
9363941Svenki 	picl_nodehdl_t parenth;
9373941Svenki 	char *names[PARENT_NAMES];
9384802Sfw157321 	char *base_units[PICL_PROPNAMELEN_MAX];
9393941Svenki 	char *loc;
9403941Svenki 	int i;
9413941Svenki 	char *prop;
9423941Svenki 	picl_errno_t err;
9433941Svenki 	int32_t lo_warning, lo_shutdown;
9443941Svenki 	int32_t hi_warning, hi_shutdown;
9453941Svenki 	int32_t current_val;
9464802Sfw157321 	int32_t exponent;
9474802Sfw157321 	double display_val;
948*4928Sfw157321 	typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
949*4928Sfw157321 	    SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
950*4928Sfw157321 	sensor_status_t sensor_status = SENSOR_OK;
9513941Svenki 
9523941Svenki 	if (class_node_found == 0) {
9533941Svenki 		class_node_found = 1;
9543941Svenki 		return (PICL_WALK_TERMINATE);
9553941Svenki 	}
9563941Svenki 
957*4928Sfw157321 	prop = (char *)args;
958*4928Sfw157321 	if (!prop) {
959*4928Sfw157321 		sensor_status = SENSOR_UNKNOWN;
960*4928Sfw157321 		all_status_ok = 0;
961*4928Sfw157321 	} else {
9623941Svenki 		err = picl_get_propval_by_name(nodeh,
9634669Sfw157321 		    PICL_PROP_OPERATIONAL_STATUS, val,
9644669Sfw157321 		    sizeof (val));
9653941Svenki 		if (err == PICL_SUCCESS) {
9663941Svenki 			if (strcmp(val, "disabled") == 0) {
967*4928Sfw157321 				sensor_status = SENSOR_DISABLED;
968*4928Sfw157321 			}
969*4928Sfw157321 		}
970*4928Sfw157321 	}
971*4928Sfw157321 
972*4928Sfw157321 	if (sensor_status != SENSOR_DISABLED &&
973*4928Sfw157321 	    sensor_status != SENSOR_UNKNOWN) {
974*4928Sfw157321 		if (picl_get_propval_by_name(nodeh, prop, &current_val,
975*4928Sfw157321 		    sizeof (current_val)) != PICL_SUCCESS) {
976*4928Sfw157321 			sensor_status = SENSOR_UNKNOWN;
977*4928Sfw157321 		}
978*4928Sfw157321 		if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_WARNING,
979*4928Sfw157321 		    &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS)
980*4928Sfw157321 			lo_warning = INVALID_THRESHOLD;
981*4928Sfw157321 		if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_SHUTDOWN,
982*4928Sfw157321 		    &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS)
983*4928Sfw157321 			lo_shutdown = INVALID_THRESHOLD;
984*4928Sfw157321 		if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_WARNING,
985*4928Sfw157321 		    &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS)
986*4928Sfw157321 			hi_warning = INVALID_THRESHOLD;
987*4928Sfw157321 		if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_SHUTDOWN,
988*4928Sfw157321 		    &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS)
989*4928Sfw157321 			hi_shutdown = INVALID_THRESHOLD;
990*4928Sfw157321 
991*4928Sfw157321 		if ((lo_shutdown != INVALID_THRESHOLD &&
992*4928Sfw157321 		    current_val <= lo_shutdown) ||
993*4928Sfw157321 		    (hi_shutdown != INVALID_THRESHOLD &&
994*4928Sfw157321 		    current_val >= hi_shutdown)) {
995*4928Sfw157321 			sensor_status = SENSOR_FAILED;
996*4928Sfw157321 		} else if ((lo_warning != INVALID_THRESHOLD &&
997*4928Sfw157321 		    current_val <= lo_warning) ||
998*4928Sfw157321 		    (hi_warning != INVALID_THRESHOLD &&
999*4928Sfw157321 		    current_val >= hi_warning)) {
1000*4928Sfw157321 			sensor_status = SENSOR_WARN;
10013941Svenki 		} else {
1002*4928Sfw157321 			sensor_status = SENSOR_OK;
1003*4928Sfw157321 		}
1004*4928Sfw157321 	}
1005*4928Sfw157321 
1006*4928Sfw157321 	if (syserrlog == 0) {
1007*4928Sfw157321 		if (sensor_status != SENSOR_OK && all_status_ok == 1) {
10083941Svenki 			all_status_ok = 0;
10093941Svenki 			return (PICL_WALK_TERMINATE);
10103941Svenki 		}
1011*4928Sfw157321 		if (sensor_status == SENSOR_OK) {
1012*4928Sfw157321 			return (PICL_WALK_CONTINUE);
1013*4928Sfw157321 		}
10143941Svenki 	}
1015*4928Sfw157321 
1016*4928Sfw157321 	/*
1017*4928Sfw157321 	 * If we're here then prtdiag was invoked with "-v" or we have
1018*4928Sfw157321 	 * a sensor that is beyond a threshold, so give them a book to
1019*4928Sfw157321 	 * read instead of the Cliff Notes.
1020*4928Sfw157321 	 */
10213941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
10224669Sfw157321 	    sizeof (parenth));
10233941Svenki 	if (err != PICL_SUCCESS) {
10243941Svenki 		log_printf("\n");
10253941Svenki 		return (PICL_WALK_CONTINUE);
10263941Svenki 	}
10274003Svivek 
1028*4928Sfw157321 	/* gather up the path name for the sensor */
1029*4928Sfw157321 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
1030*4928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++) {
1031*4928Sfw157321 			if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
1032*4928Sfw157321 			    NULL) {
1033*4928Sfw157321 				while (--i > -1)
1034*4928Sfw157321 					free(names[i]);
1035*4928Sfw157321 				free(loc);
1036*4928Sfw157321 				loc = NULL;
1037*4928Sfw157321 			}
10383941Svenki 		}
10394003Svivek 	}
1040*4928Sfw157321 	i = 0;
1041*4928Sfw157321 	if (loc != 0) {
1042*4928Sfw157321 		while (err == PICL_SUCCESS) {
1043*4928Sfw157321 			if (parenth == phyplatformh)
1044*4928Sfw157321 				break;
1045*4928Sfw157321 			err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1046*4928Sfw157321 			    names[i++], PICL_PROPNAMELEN_MAX);
1047*4928Sfw157321 			if (err != PICL_SUCCESS) {
1048*4928Sfw157321 				i--;
1049*4928Sfw157321 				break;
1050*4928Sfw157321 			}
1051*4928Sfw157321 			if (i == PARENT_NAMES)
1052*4928Sfw157321 				break;
1053*4928Sfw157321 			err = picl_get_propval_by_name(parenth,
1054*4928Sfw157321 			    PICL_PROP_PARENT, &parenth, sizeof (parenth));
1055*4928Sfw157321 		}
1056*4928Sfw157321 		loc[0] = '\0';
1057*4928Sfw157321 		if (--i > -1) {
1058*4928Sfw157321 			(void) strlcat(loc, names[i],
1059*4928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1060*4928Sfw157321 		}
1061*4928Sfw157321 		while (--i > -1) {
1062*4928Sfw157321 			(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
1063*4928Sfw157321 			    PARENT_NAMES);
1064*4928Sfw157321 			(void) strlcat(loc, names[i],
1065*4928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1066*4928Sfw157321 		}
1067*4928Sfw157321 		log_printf("%-31s", loc);
1068*4928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++)
1069*4928Sfw157321 			free(names[i]);
1070*4928Sfw157321 		free(loc);
1071*4928Sfw157321 	} else {
1072*4928Sfw157321 		log_printf("%-31s", " ");
10733941Svenki 	}
10743941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
10754669Sfw157321 	    sizeof (val));
10763941Svenki 	if (err == PICL_SUCCESS)
10773941Svenki 		log_printf("%-15s", val);
10783941Svenki 
1079*4928Sfw157321 	/*
1080*4928Sfw157321 	 * Get the exponent if present, and do a little math so that
1081*4928Sfw157321 	 * if we need to we can print a normalized value for the
1082*4928Sfw157321 	 * sensor reading.
1083*4928Sfw157321 	 */
10844802Sfw157321 	if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT,
10854802Sfw157321 	    &exponent, sizeof (exponent)) != PICL_SUCCESS)
10864802Sfw157321 		exponent = 0;
10874802Sfw157321 	if (exponent == 0)
10884802Sfw157321 		display_val = (double)current_val;
10894802Sfw157321 	else
10904802Sfw157321 		display_val = (double)current_val *
10914802Sfw157321 		    pow((double)10, (double)exponent);
1092*4928Sfw157321 	err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS,
1093*4928Sfw157321 	    base_units, sizeof (base_units));
10944802Sfw157321 	if (err != PICL_SUCCESS)
10954802Sfw157321 		base_units[0] = '\0';
10963941Svenki 
1097*4928Sfw157321 	switch (sensor_status) {
1098*4928Sfw157321 	case SENSOR_FAILED:
10993941Svenki 		log_printf("%-s", "failed (");
11004802Sfw157321 		log_printf("%-.*f", abs(exponent), display_val);
11014802Sfw157321 		log_printf("%-s %s", base_units, ")");
1102*4928Sfw157321 		break;
1103*4928Sfw157321 	case SENSOR_WARN:
11043941Svenki 		log_printf("%-s", "warning (");
11054802Sfw157321 		log_printf("%-.*f", abs(exponent), display_val);
11064802Sfw157321 		log_printf("%-s %s", base_units, ")");
1107*4928Sfw157321 		break;
1108*4928Sfw157321 	case SENSOR_DISABLED:
1109*4928Sfw157321 		log_printf("%-s", "disabled");
1110*4928Sfw157321 		break;
1111*4928Sfw157321 	case SENSOR_OK:
11123941Svenki 		log_printf("%-s", "ok");
1113*4928Sfw157321 		break;
1114*4928Sfw157321 	default:
1115*4928Sfw157321 		log_printf("%-s", "unknown");
1116*4928Sfw157321 		break;
1117*4928Sfw157321 	}
11183941Svenki 
11193941Svenki 	log_printf("\n");
11203941Svenki 	return (PICL_WALK_CONTINUE);
11213941Svenki }
11223941Svenki 
11233941Svenki /*ARGSUSED*/
11243941Svenki static int
11253941Svenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args)
11263941Svenki {
1127*4928Sfw157321 	char current_val[PICL_PROPNAMELEN_MAX];
1128*4928Sfw157321 	char expected_val[PICL_PROPNAMELEN_MAX];
1129*4928Sfw157321 	char label[PICL_PROPNAMELEN_MAX];
11303941Svenki 	picl_nodehdl_t parenth;
11313941Svenki 	char *names[PARENT_NAMES];
11323941Svenki 	char *loc;
11333941Svenki 	int i = 0;
11343941Svenki 	char *prop = (char *)args;
11353941Svenki 	picl_errno_t err = PICL_SUCCESS;
1136*4928Sfw157321 	typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
1137*4928Sfw157321 	    SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
1138*4928Sfw157321 	sensor_status_t sensor_status = SENSOR_OK;
11393941Svenki 
11403941Svenki 	if (class_node_found == 0) {
11413941Svenki 		class_node_found = 1;
11423941Svenki 		return (PICL_WALK_TERMINATE);
11433941Svenki 	}
1144*4928Sfw157321 
1145*4928Sfw157321 	prop = (char *)args;
1146*4928Sfw157321 	if (!prop) {
1147*4928Sfw157321 		sensor_status = SENSOR_UNKNOWN;
1148*4928Sfw157321 		all_status_ok = 0;
1149*4928Sfw157321 	} else {
11503941Svenki 		err = picl_get_propval_by_name(nodeh,
1151*4928Sfw157321 		    PICL_PROP_OPERATIONAL_STATUS, current_val,
1152*4928Sfw157321 		    sizeof (current_val));
11533941Svenki 		if (err == PICL_SUCCESS) {
1154*4928Sfw157321 			if (strcmp(current_val, "disabled") == 0) {
1155*4928Sfw157321 				sensor_status = SENSOR_DISABLED;
1156*4928Sfw157321 			}
1157*4928Sfw157321 		}
1158*4928Sfw157321 	}
1159*4928Sfw157321 
1160*4928Sfw157321 	if (sensor_status != SENSOR_DISABLED &&
1161*4928Sfw157321 	    sensor_status != SENSOR_UNKNOWN) {
1162*4928Sfw157321 		if (picl_get_propval_by_name(nodeh, prop, &current_val,
1163*4928Sfw157321 		    sizeof (current_val)) != PICL_SUCCESS) {
1164*4928Sfw157321 			(void) strlcpy(current_val, "unknown",
1165*4928Sfw157321 			    sizeof (current_val));
1166*4928Sfw157321 			sensor_status = SENSOR_UNKNOWN;
1167*4928Sfw157321 		} else {
1168*4928Sfw157321 			if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED,
1169*4928Sfw157321 			    &expected_val, sizeof (expected_val)) !=
1170*4928Sfw157321 			    PICL_SUCCESS) {
1171*4928Sfw157321 				sensor_status = SENSOR_UNKNOWN;
1172*4928Sfw157321 			} else {
1173*4928Sfw157321 				if (strncmp(current_val, expected_val,
1174*4928Sfw157321 				    sizeof (current_val)) == 0) {
1175*4928Sfw157321 					sensor_status = SENSOR_OK;
1176*4928Sfw157321 				} else {
1177*4928Sfw157321 					sensor_status = SENSOR_FAILED;
11783941Svenki 				}
1179*4928Sfw157321 			}
1180*4928Sfw157321 		}
1181*4928Sfw157321 	}
1182*4928Sfw157321 
1183*4928Sfw157321 	if (syserrlog == 0) {
1184*4928Sfw157321 		if (sensor_status != SENSOR_OK && all_status_ok == 1) {
11853941Svenki 			all_status_ok = 0;
11863941Svenki 			return (PICL_WALK_TERMINATE);
11873941Svenki 		}
1188*4928Sfw157321 		if (sensor_status == SENSOR_OK) {
1189*4928Sfw157321 			return (PICL_WALK_CONTINUE);
1190*4928Sfw157321 		}
11913941Svenki 	}
1192*4928Sfw157321 
1193*4928Sfw157321 	/*
1194*4928Sfw157321 	 * If we're here then prtdiag was invoked with "-v" or we have
1195*4928Sfw157321 	 * a sensor that is beyond a threshold, so give them a book to
1196*4928Sfw157321 	 * read instead of the Cliff Notes.
1197*4928Sfw157321 	 */
11983941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
11994669Sfw157321 	    sizeof (parenth));
12003941Svenki 	if (err != PICL_SUCCESS) {
12013941Svenki 		log_printf("\n");
12023941Svenki 		return (PICL_WALK_CONTINUE);
12033941Svenki 	}
1204*4928Sfw157321 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
1205*4928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++) {
1206*4928Sfw157321 			if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
1207*4928Sfw157321 			    NULL) {
1208*4928Sfw157321 				while (--i > -1)
1209*4928Sfw157321 					free(names[i]);
1210*4928Sfw157321 				free(loc);
1211*4928Sfw157321 				loc = NULL;
1212*4928Sfw157321 			}
12133941Svenki 		}
12143941Svenki 	}
1215*4928Sfw157321 	i = 0;
1216*4928Sfw157321 	if (loc) {
1217*4928Sfw157321 		while (err == PICL_SUCCESS) {
1218*4928Sfw157321 			if (parenth == phyplatformh)
1219*4928Sfw157321 				break;
1220*4928Sfw157321 			err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1221*4928Sfw157321 			    names[i++], PICL_PROPNAMELEN_MAX);
1222*4928Sfw157321 			if (err != PICL_SUCCESS) {
1223*4928Sfw157321 				i--;
1224*4928Sfw157321 				break;
1225*4928Sfw157321 			}
1226*4928Sfw157321 			if (i == PARENT_NAMES)
1227*4928Sfw157321 				break;
1228*4928Sfw157321 			err = picl_get_propval_by_name(parenth,
1229*4928Sfw157321 			    PICL_PROP_PARENT, &parenth, sizeof (parenth));
1230*4928Sfw157321 		}
1231*4928Sfw157321 		loc[0] = '\0';
1232*4928Sfw157321 		if (--i > -1) {
1233*4928Sfw157321 			(void) strlcat(loc, names[i],
1234*4928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1235*4928Sfw157321 		}
1236*4928Sfw157321 		while (--i > -1) {
1237*4928Sfw157321 			(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
1238*4928Sfw157321 			    PARENT_NAMES);
1239*4928Sfw157321 			(void) strlcat(loc, names[i],
1240*4928Sfw157321 			    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1241*4928Sfw157321 		}
1242*4928Sfw157321 		log_printf("%-31s", loc);
1243*4928Sfw157321 		for (i = 0; i < PARENT_NAMES; i++)
1244*4928Sfw157321 			free(names[i]);
1245*4928Sfw157321 		free(loc);
1246*4928Sfw157321 	} else {
1247*4928Sfw157321 		log_printf("%-31s", "");
12483941Svenki 	}
1249*4928Sfw157321 
1250*4928Sfw157321 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1251*4928Sfw157321 	    sizeof (label));
1252*4928Sfw157321 	if (err != PICL_SUCCESS)
1253*4928Sfw157321 		(void) strlcpy(label, "", sizeof (label));
1254*4928Sfw157321 	log_printf("%-15s", label);
1255*4928Sfw157321 
1256*4928Sfw157321 	log_printf("%-8s", current_val);
1257*4928Sfw157321 
12583941Svenki 	log_printf("\n");
12593941Svenki 	return (PICL_WALK_CONTINUE);
12603941Svenki }
12613941Svenki 
12623941Svenki static void
12633941Svenki sun4v_env_print_fan_sensors()
12643941Svenki {
12654802Sfw157321 	char *fmt = "%-30s %-14s %-10s\n";
12663941Svenki 	/*
12673941Svenki 	 * If there isn't any fan sensor node, return now.
12683941Svenki 	 */
12693941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1270*4928Sfw157321 	    PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED,
12714669Sfw157321 	    sun4v_env_print_sensor_callback);
12723941Svenki 	if (!class_node_found)
12733941Svenki 		return;
12743941Svenki 	log_printf("Fan sensors:\n");
12753941Svenki 	if (syserrlog == 0) {
12763941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
12774669Sfw157321 		    PICL_CLASS_RPM_SENSOR,
1278*4928Sfw157321 		    PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
12793941Svenki 		if (all_status_ok) {
12803941Svenki 			log_printf("All fan sensors are OK.\n");
12813941Svenki 			return;
12823941Svenki 		}
12833941Svenki 	}
12844802Sfw157321 	log_printf("----------------------------------------------------\n");
12853941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
12864802Sfw157321 	log_printf("----------------------------------------------------\n");
12873941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR,
12884669Sfw157321 	    PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
12893941Svenki }
12903941Svenki 
12913941Svenki static void
12923941Svenki sun4v_env_print_fan_indicators()
12933941Svenki {
12944802Sfw157321 	char *fmt = "%-30s %-14s %-10s\n";
12953941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1296*4928Sfw157321 	    PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION,
12974669Sfw157321 	    sun4v_env_print_indicator_callback);
12983941Svenki 	if (!class_node_found)
12993941Svenki 		return;
13003941Svenki 	log_printf("\nFan indicators:\n");
13013941Svenki 	if (syserrlog == 0) {
13023941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
13034669Sfw157321 		    PICL_CLASS_RPM_INDICATOR,
1304*4928Sfw157321 		    (void *)PICL_PROP_CONDITION,
1305*4928Sfw157321 		    sun4v_env_print_indicator_callback);
13063941Svenki 		if (all_status_ok) {
13073941Svenki 			log_printf("All fan indicators are OK.\n");
13083941Svenki 			return;
13093941Svenki 		}
13103941Svenki 	}
13114802Sfw157321 	log_printf("-------------------------------------------------------\n");
13123941Svenki 	log_printf(fmt, "Location", "Sensor", "Condition", 0);
13134802Sfw157321 	log_printf("-------------------------------------------------------\n");
13143941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR,
13154802Sfw157321 	    (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback);
13163941Svenki }
13173941Svenki 
13183941Svenki static void
13193941Svenki sun4v_env_print_temp_sensors()
13203941Svenki {
13214802Sfw157321 	char *fmt = "%-30s %-14s %-10s\n";
13223941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
13234669Sfw157321 	    PICL_CLASS_TEMPERATURE_SENSOR,
13244669Sfw157321 	    (void *)PICL_PROP_TEMPERATURE,
13254669Sfw157321 	    sun4v_env_print_sensor_callback);
13263941Svenki 	if (!class_node_found)
13273941Svenki 		return;
13283941Svenki 
13293941Svenki 	log_printf("\nTemperature sensors:\n");
13303941Svenki 	if (syserrlog == 0) {
13313941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
13324669Sfw157321 		    PICL_CLASS_TEMPERATURE_SENSOR,
1333*4928Sfw157321 		    PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
13343941Svenki 		if (all_status_ok) {
13353941Svenki 			log_printf("All temperature sensors are OK.\n");
13363941Svenki 			return;
13373941Svenki 		}
13383941Svenki 	}
13394802Sfw157321 	log_printf("----------------------------------------------------\n");
13403941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
13414802Sfw157321 	log_printf("----------------------------------------------------\n");
13423941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
13434669Sfw157321 	    PICL_CLASS_TEMPERATURE_SENSOR,
13444669Sfw157321 	    (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
13453941Svenki }
13463941Svenki 
13473941Svenki static void
13483941Svenki sun4v_env_print_temp_indicators()
13493941Svenki {
13504802Sfw157321 	char *fmt = "%-30s %-14s %-8s\n";
13513941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
13524669Sfw157321 	    PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION,
13534669Sfw157321 	    sun4v_env_print_indicator_callback);
13543941Svenki 	if (!class_node_found)
13553941Svenki 		return;
13563941Svenki 	log_printf("\nTemperature indicators:\n");
13573941Svenki 	if (syserrlog == 0) {
13583941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1359*4928Sfw157321 		    PICL_CLASS_TEMPERATURE_INDICATOR,
1360*4928Sfw157321 		    (void *)PICL_PROP_CONDITION,
13614669Sfw157321 		    sun4v_env_print_indicator_callback);
13623941Svenki 		if (all_status_ok) {
13633941Svenki 			log_printf("All temperature indicators are OK.\n");
13643941Svenki 			return;
13653941Svenki 		}
13663941Svenki 	}
13674802Sfw157321 	log_printf("-------------------------------------------------\n");
13683941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
13694802Sfw157321 	log_printf("-------------------------------------------------\n");
13703941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
13714669Sfw157321 	    PICL_CLASS_TEMPERATURE_INDICATOR,
13724669Sfw157321 	    (void *)PICL_PROP_CONDITION,
13734669Sfw157321 	    sun4v_env_print_indicator_callback);
13743941Svenki }
13753941Svenki 
13763941Svenki static void
13773941Svenki sun4v_env_print_current_sensors()
13783941Svenki {
13794802Sfw157321 	char *fmt = "%-30s %-14s %-10s\n";
13803941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR,
13814669Sfw157321 	    (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
13823941Svenki 	if (!class_node_found)
13833941Svenki 		return;
13843941Svenki 	log_printf("\nCurrent sensors:\n");
13853941Svenki 	if (syserrlog == 0) {
13863941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
13874669Sfw157321 		    PICL_CLASS_CURRENT_SENSOR,
1388*4928Sfw157321 		    PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
13893941Svenki 		if (all_status_ok) {
13903941Svenki 			log_printf("All current sensors are OK.\n");
13913941Svenki 			return;
13923941Svenki 		}
13933941Svenki 	}
13944802Sfw157321 	log_printf("----------------------------------------------------\n");
13953941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
13964802Sfw157321 	log_printf("----------------------------------------------------\n");
13973941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
13984669Sfw157321 	    PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
13994669Sfw157321 	    sun4v_env_print_sensor_callback);
14003941Svenki }
14013941Svenki 
14023941Svenki static void
14033941Svenki sun4v_env_print_current_indicators()
14043941Svenki {
14054802Sfw157321 	char *fmt = "%-30s %-14s %-8s\n";
14063941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
14074669Sfw157321 	    PICL_CLASS_CURRENT_INDICATOR,
14084669Sfw157321 	    (void *)PICL_PROP_CONDITION,
14094669Sfw157321 	    sun4v_env_print_indicator_callback);
14103941Svenki 	if (!class_node_found)
14113941Svenki 		return;
14123941Svenki 	log_printf("\nCurrent indicators:\n");
14133941Svenki 	if (syserrlog == 0) {
14143941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1415*4928Sfw157321 		    PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION,
14164669Sfw157321 		    sun4v_env_print_indicator_callback);
14173941Svenki 		if (all_status_ok) {
14183941Svenki 			log_printf("All current indicators are OK.\n");
14193941Svenki 			return;
14203941Svenki 		}
14213941Svenki 	}
14224802Sfw157321 	log_printf("-------------------------------------------------------\n");
14233941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
14244802Sfw157321 	log_printf("-------------------------------------------------------\n");
14253941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
14264669Sfw157321 	    PICL_CLASS_CURRENT_INDICATOR,
14274669Sfw157321 	    (void *)PICL_PROP_CONDITION,
14284669Sfw157321 	    sun4v_env_print_indicator_callback);
14293941Svenki }
14303941Svenki 
14313941Svenki static void
14323941Svenki sun4v_env_print_voltage_sensors()
14333941Svenki {
14344802Sfw157321 	char *fmt = "%-30s %-14s %-10s\n";
14353941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
14364669Sfw157321 	    PICL_CLASS_VOLTAGE_SENSOR,
14374669Sfw157321 	    PICL_PROP_VOLTAGE,
14384669Sfw157321 	    sun4v_env_print_sensor_callback);
14393941Svenki 	if (!class_node_found)
14403941Svenki 		return;
14413941Svenki 	log_printf("\nVoltage sensors:\n");
14423941Svenki 	if (syserrlog == 0) {
14433941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
14444669Sfw157321 		    PICL_CLASS_VOLTAGE_SENSOR,
1445*4928Sfw157321 		    PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback);
14463941Svenki 		if (all_status_ok) {
14473941Svenki 			log_printf("All voltage sensors are OK.\n");
14483941Svenki 			return;
14493941Svenki 		}
14503941Svenki 	}
14514802Sfw157321 	log_printf("----------------------------------------------------\n");
14523941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
14534802Sfw157321 	log_printf("----------------------------------------------------\n");
14543941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
14554669Sfw157321 	    PICL_CLASS_VOLTAGE_SENSOR,
14564669Sfw157321 	    (void *)PICL_PROP_VOLTAGE,
14574669Sfw157321 	    sun4v_env_print_sensor_callback);
14583941Svenki }
14593941Svenki 
14603941Svenki static void
14613941Svenki sun4v_env_print_voltage_indicators()
14623941Svenki {
14634802Sfw157321 	char *fmt = "%-30s %-14s %-8s\n";
14643941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
14654669Sfw157321 	    PICL_CLASS_VOLTAGE_INDICATOR,
14664669Sfw157321 	    (void *)PICL_PROP_CONDITION,
14674669Sfw157321 	    sun4v_env_print_indicator_callback);
14683941Svenki 	if (!class_node_found)
14693941Svenki 		return;
14703941Svenki 	log_printf("\nVoltage indicators:\n");
14713941Svenki 	if (syserrlog == 0) {
14723941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1473*4928Sfw157321 		    PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION,
14744669Sfw157321 		    sun4v_env_print_indicator_callback);
14753941Svenki 		if (all_status_ok) {
14763941Svenki 			log_printf("All voltage indicators are OK.\n");
14773941Svenki 			return;
14783941Svenki 		}
14793941Svenki 	}
14804802Sfw157321 	log_printf("-------------------------------------------------------\n");
14813941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
14824802Sfw157321 	log_printf("-------------------------------------------------------\n");
14833941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
14844669Sfw157321 	    PICL_CLASS_VOLTAGE_INDICATOR,
14854669Sfw157321 	    (void *)PICL_PROP_CONDITION,
14864669Sfw157321 	    sun4v_env_print_indicator_callback);
14873941Svenki }
14883941Svenki 
14893941Svenki static void
14903941Svenki sun4v_env_print_LEDs()
14913941Svenki {
14924802Sfw157321 	char *fmt = "%-30s %-14s %-8s\n";
14933941Svenki 	if (syserrlog == 0)
14943941Svenki 		return;
14953941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
14964669Sfw157321 	    (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
14973941Svenki 	if (!class_node_found)
14983941Svenki 		return;
14993941Svenki 	log_printf("\nLEDs:\n");
15004802Sfw157321 	log_printf("---------------------------------------------------\n");
15013941Svenki 	log_printf(fmt, "Location", "LED", "State", 0);
15024802Sfw157321 	log_printf("---------------------------------------------------\n");
15033941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
15044669Sfw157321 	    (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
15053941Svenki }
15063941Svenki 
15073941Svenki /*ARGSUSED*/
15083941Svenki static int
15093941Svenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args)
15103941Svenki {
15113941Svenki 	char label[PICL_PROPNAMELEN_MAX];
15123941Svenki 	char status[PICL_PROPNAMELEN_MAX];
15133941Svenki 	picl_errno_t err;
15143941Svenki 	picl_prophdl_t proph;
15153941Svenki 	picl_nodehdl_t parenth;
15163941Svenki 	char *names[PARENT_NAMES];
15173941Svenki 	char *loc;
15183941Svenki 	int i;
15193941Svenki 
15203941Svenki 	if (!class_node_found) {
15213941Svenki 		class_node_found = 1;
15223941Svenki 		return (PICL_WALK_TERMINATE);
15233941Svenki 	}
15243941Svenki 	err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph);
15253941Svenki 	if (err != PICL_SUCCESS)
15263941Svenki 		return (PICL_WALK_CONTINUE);
15273941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
15284669Sfw157321 	    sizeof (label));
15293941Svenki 	if (err != PICL_SUCCESS)
15303941Svenki 		return (PICL_WALK_CONTINUE);
15313941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
15324669Sfw157321 	    status, sizeof (status));
15333941Svenki 	if (err != PICL_SUCCESS)
15343941Svenki 		return (PICL_WALK_CONTINUE);
15353941Svenki 	if (syserrlog == 0) {
15363941Svenki 		if (strcmp(status, "disabled") == 0) {
15373941Svenki 			if (all_status_ok) {
15383941Svenki 				all_status_ok = 0;
15393941Svenki 				return (PICL_WALK_TERMINATE);
15403941Svenki 			}
15413941Svenki 		} else
15423941Svenki 			return (PICL_WALK_CONTINUE);
15433941Svenki 	}
15443941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
15454669Sfw157321 	    sizeof (parenth));
15463941Svenki 	if (err != PICL_SUCCESS) {
15473941Svenki 		log_printf("\n");
15483941Svenki 		return (PICL_WALK_CONTINUE);
15493941Svenki 	}
15503941Svenki 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
15513941Svenki 		return (PICL_WALK_TERMINATE);
15523941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
15533941Svenki 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
15543941Svenki 			while (--i > -1)
15553941Svenki 				free(names[i]);
15563941Svenki 			free(loc);
15573941Svenki 			return (PICL_WALK_TERMINATE);
15583941Svenki 		}
15593941Svenki 	i = 0;
15603941Svenki 	while (err == PICL_SUCCESS) {
15614802Sfw157321 		if (parenth == phyplatformh)
15623941Svenki 			break;
15633941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
15644669Sfw157321 		    names[i++], PICL_PROPNAMELEN_MAX);
15653941Svenki 		if (err != PICL_SUCCESS) {
15663941Svenki 			i--;
15673941Svenki 			break;
15683941Svenki 		}
15693941Svenki 		if (i == PARENT_NAMES)
15703941Svenki 			break;
15713941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
15724669Sfw157321 		    &parenth, sizeof (parenth));
15733941Svenki 	}
15743941Svenki 	loc[0] = '\0';
15754003Svivek 	if (--i > -1) {
15764003Svivek 		(void) strlcat(loc, names[i],
15774669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
15784003Svivek 	}
15793941Svenki 	while (--i > -1) {
15804003Svivek 		(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES);
15814003Svivek 		(void) strlcat(loc, names[i],
15824669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
15833941Svenki 	}
15844802Sfw157321 	log_printf("%-31s", loc);
15853941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
15863941Svenki 		free(names[i]);
15873941Svenki 	free(loc);
15883941Svenki 	log_printf("%-10s", label);
15893941Svenki 	log_printf("%-9s", status);
15903941Svenki 	log_printf("\n");
15913941Svenki 	return (PICL_WALK_CONTINUE);
15923941Svenki }
15933941Svenki 
15943941Svenki static void
15953941Svenki sun4v_print_fru_status()
15963941Svenki {
15974802Sfw157321 	char *fmt = "%-30s %-9s %-8s\n";
15983941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
15994669Sfw157321 	    sun4v_print_fru_status_callback);
16003941Svenki 	if (!class_node_found)
16013941Svenki 		return;
16023941Svenki 	log_printf("\n");
16033941Svenki 	log_printf("============================");
16043941Svenki 	log_printf(" FRU Status ");
16053941Svenki 	log_printf("============================");
16063941Svenki 	log_printf("\n");
16073941Svenki 
16083941Svenki 	if (syserrlog == 0) {
16093941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
16104802Sfw157321 		    NULL, NULL,
16114669Sfw157321 		    sun4v_print_fru_status_callback);
16123941Svenki 		if (all_status_ok) {
16133941Svenki 			log_printf("All FRUs are enabled.\n");
16143941Svenki 			return;
16153941Svenki 		}
16163941Svenki 	}
16173941Svenki 	log_printf(fmt, "Location", "Name", "Status", 0);
16184802Sfw157321 	log_printf("--------------------------------------------------\n");
16194802Sfw157321 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
16204669Sfw157321 	    sun4v_print_fru_status_callback);
16213941Svenki }
16223941Svenki 
16233941Svenki /*ARGSUSED*/
16243941Svenki static int
16253941Svenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args)
16263941Svenki {
16273941Svenki 	char label[PICL_PROPNAMELEN_MAX];
16283941Svenki 	char rev[PICL_PROPNAMELEN_MAX];
16293941Svenki 	picl_errno_t err;
16303941Svenki 
16313941Svenki 	if (!class_node_found) {
16323941Svenki 		class_node_found = 1;
16333941Svenki 		return (PICL_WALK_TERMINATE);
16343941Svenki 	}
16353941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
16364669Sfw157321 	    sizeof (label));
16373941Svenki 	if (err != PICL_SUCCESS)
16383941Svenki 		return (PICL_WALK_CONTINUE);
16393941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev,
16404669Sfw157321 	    sizeof (rev));
16413941Svenki 	if (err != PICL_SUCCESS)
16423941Svenki 		return (PICL_WALK_CONTINUE);
16433941Svenki 	if (strlen(rev) == 0)
16443941Svenki 		return (PICL_WALK_CONTINUE);
16453941Svenki 	log_printf("%-21s", label);
16463941Svenki 	log_printf("%-40s", rev);
16473941Svenki 	log_printf("\n");
16483941Svenki 	return (PICL_WALK_CONTINUE);
16493941Svenki }
16503941Svenki 
16513941Svenki static void
16523941Svenki sun4v_print_fw_rev()
16533941Svenki {
16543941Svenki 	char *fmt = "%-20s %-10s\n";
16553941Svenki 	if (syserrlog == 0)
16563941Svenki 		return;
16573941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
16584669Sfw157321 	    sun4v_print_fw_rev_callback);
16593941Svenki 	if (!class_node_found)
16603941Svenki 		return;
16613941Svenki 	log_printf("\n");
16623941Svenki 	log_printf("============================");
16633941Svenki 	log_printf(" FW Version ");
16643941Svenki 	log_printf("============================");
16653941Svenki 	log_printf("\n");
16663941Svenki 	log_printf(fmt, "Name", "Version", 0);
16673941Svenki 	log_printf("----------------------------\n");
16683941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
16694669Sfw157321 	    sun4v_print_fw_rev_callback);
16703941Svenki }
16713941Svenki 
16723941Svenki static void
16733941Svenki sun4v_print_chassis_serial_no()
16743941Svenki {
16753941Svenki 	char val[PICL_PROPNAMELEN_MAX];
16763941Svenki 	picl_errno_t err;
16773941Svenki 	if (syserrlog == 0 || chassish == 0)
16783941Svenki 		return;
16793941Svenki 
16803941Svenki 	log_printf("\n");
16813941Svenki 	log_printf("Chassis Serial Number");
16823941Svenki 	log_printf("\n");
16833941Svenki 	log_printf("---------------------\n");
16843941Svenki 	err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER,
16854669Sfw157321 	    val, sizeof (val));
16863941Svenki 	if (err == PICL_SUCCESS)
16873941Svenki 		log_printf("%s", val);
16883941Svenki 	log_printf("\n");
16893941Svenki }
1690