xref: /onnv-gate/usr/src/lib/libprtdiag/common/display_sun4v.c (revision 4669:2f90c21ad058)
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>
481708Sstevel #include "pdevinfo.h"
491708Sstevel #include "display.h"
501708Sstevel #include "display_sun4v.h"
511708Sstevel #include "libprtdiag.h"
521708Sstevel 
531708Sstevel #if !defined(TEXT_DOMAIN)
541708Sstevel #define	TEXT_DOMAIN	"SYS_TEST"
551708Sstevel #endif
561708Sstevel 
57*4669Sfw157321 #define	MOTHERBOARD			"MB"
583941Svenki #define	NETWORK				"network"
593941Svenki #define	PCIE_COMPATIBLE_STR		"pciex"
603941Svenki #define	PCIX_COMPATIBLE_STR		"pci"
613941Svenki #define	SUN4V_MACHINE			"sun4v"
623941Svenki #define	PARENT_NAMES			10
633941Svenki 
643941Svenki /*
653941Svenki  * Additional OBP properties
663941Svenki  */
673941Svenki #define	OBP_PROP_COMPATIBLE		"compatible"
683941Svenki #define	OBP_PROP_MODEL			"model"
693941Svenki #define	OBP_PROP_SLOT_NAMES		"slot-names"
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);
1003941Svenki static void 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();
1093941Svenki static void sun4v_env_print_LEDs();
1103941Svenki static void sun4v_print_fru_status();
1113941Svenki static void sun4v_print_fw_rev();
1123941Svenki static void sun4v_print_chassis_serial_no();
1131708Sstevel 
1141708Sstevel int
1153941Svenki sun4v_display(Sys_tree *tree, Prom_node *root, int log,
1163941Svenki 	picl_nodehdl_t plafh)
1171708Sstevel {
1181708Sstevel 	void *value;		/* used for opaque PROM data */
1191708Sstevel 	struct mem_total memory_total;	/* Total memory in system */
1201708Sstevel 	struct grp_info grps;	/* Info on all groups in system */
1213941Svenki 	char machine[MAXSTRLEN];
1223941Svenki 
1233941Svenki 	if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1)
1243941Svenki 		return (1);
1253941Svenki 	if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0)
1263941Svenki 		return (1);
1271708Sstevel 
1281708Sstevel 	sys_clk = -1;  /* System clock freq. (in MHz) */
1291708Sstevel 
1301708Sstevel 	/*
1311708Sstevel 	 * Now display the machine's configuration. We do this if we
1321708Sstevel 	 * are not logging.
1331708Sstevel 	 */
1341708Sstevel 	if (!logging) {
1351708Sstevel 		struct utsname uts_buf;
1361708Sstevel 
1371708Sstevel 		/*
1381708Sstevel 		 * Display system banner
1391708Sstevel 		 */
1401708Sstevel 		(void) uname(&uts_buf);
1411708Sstevel 
1423941Svenki 		log_printf(dgettext(TEXT_DOMAIN, "System Configuration:  "
143*4669Sfw157321 		    "Sun Microsystems  %s %s\n"), uts_buf.machine,
144*4669Sfw157321 		    get_prop_val(find_prop(root, "banner-name")), 0);
1451708Sstevel 
1461708Sstevel 		/* display system clock frequency */
1471708Sstevel 		value = get_prop_val(find_prop(root, "clock-frequency"));
1481708Sstevel 		if (value != NULL) {
1491708Sstevel 			sys_clk = ((*((int *)value)) + 500000) / 1000000;
1501708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, "System clock "
151*4669Sfw157321 			    "frequency: %d MHz\n"), sys_clk, 0);
1521708Sstevel 		}
1531708Sstevel 
1541708Sstevel 		/* Display the Memory Size */
1551708Sstevel 		display_memorysize(tree, NULL, &grps, &memory_total);
1561708Sstevel 
1571708Sstevel 		/* Display the CPU devices */
1581708Sstevel 		sun4v_display_cpu_devices(plafh);
1591708Sstevel 
1601708Sstevel 		/* Display the Memory configuration */
1613941Svenki 		class_node_found = 0;
1623941Svenki 		sun4v_display_memory_conf(plafh);
1631708Sstevel 
1641708Sstevel 		/* Display all the IO cards. */
1651708Sstevel 		(void) sun4v_display_pci(plafh);
1663941Svenki 		sun4v_display_diaginfo((log || (logging)), root, plafh);
1671708Sstevel 
1683941Svenki 		if (picl_get_root(&rooth) != PICL_SUCCESS)
1693941Svenki 			return (1);
1703941Svenki 		if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM,
171*4669Sfw157321 		    &phyplatformh) != PICL_SUCCESS)
1723941Svenki 			return (1);
1733941Svenki 
1743941Svenki 		if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME,
175*4669Sfw157321 		    PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
176*4669Sfw157321 		    strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS)
1773941Svenki 			return (1);
1783941Svenki 
1793941Svenki 		syserrlog = log;
1803941Svenki 		sun4v_disp_env_status();
1813941Svenki 	}
1823941Svenki 	return (0);
1833941Svenki }
1843941Svenki 
1853941Svenki static void
1863941Svenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card)
1873941Svenki {
1883941Svenki 	char *compatible;
1893941Svenki 
1904003Svivek 	(void) strlcpy(card->bus_type, "PCIX", sizeof (card->bus_type));
1913941Svenki 	if (sun4v_get_first_compatible_value(nodeh, &compatible)
192*4669Sfw157321 	    == PICL_SUCCESS) {
1933941Svenki 		if (strncmp(compatible, PCIE_COMPATIBLE_STR,
194*4669Sfw157321 		    strlen(PCIE_COMPATIBLE_STR)) == 0)
1954003Svivek 			(void) strlcpy(card->bus_type, "PCIE",
196*4669Sfw157321 			    sizeof (card->bus_type));
1973941Svenki 		free(compatible);
1983941Svenki 	}
1993941Svenki }
2003941Svenki 
2013941Svenki static picl_errno_t
2023941Svenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card)
2033941Svenki {
2043941Svenki 	char val[PICL_PROPNAMELEN_MAX];
2053941Svenki 	picl_errno_t err;
2063941Svenki 
2073941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
208*4669Sfw157321 	    sizeof (val));
2093941Svenki 	if (err != PICL_SUCCESS)
2103941Svenki 		return (err);
2113941Svenki 
2124003Svivek 	(void) strlcpy(card->slot_str, val, sizeof (card->slot_str));
2133941Svenki 	card->slot = -1;
2143941Svenki 	return (PICL_SUCCESS);
2153941Svenki }
2163941Svenki 
2173941Svenki static void
2183941Svenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card)
2193941Svenki {
2203941Svenki 	picl_errno_t err;
2213941Svenki 	picl_prophdl_t proph;
2223941Svenki 	picl_propinfo_t pinfo;
2233941Svenki 	picl_nodehdl_t pnodeh;
2243941Svenki 	uint8_t *pval;
2253941Svenki 	uint32_t dev_mask;
2263941Svenki 	char uaddr[MAXSTRLEN];
2273941Svenki 	int i;
2283941Svenki 
2293941Svenki 	if (get_slot_label(nodeh, card) == PICL_SUCCESS)
2303941Svenki 		return;
2313941Svenki 	err = PICL_SUCCESS;
2323941Svenki 	while (err == PICL_SUCCESS) {
2333941Svenki 		if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
234*4669Sfw157321 		    sizeof (pnodeh)) != PICL_SUCCESS) {
235*4669Sfw157321 			(void) strlcpy(card->slot_str, MOTHERBOARD,
236*4669Sfw157321 			    sizeof (card->slot_str));
2373941Svenki 			card->slot = -1;
2383941Svenki 			return;
2393941Svenki 		}
2403941Svenki 		if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES,
241*4669Sfw157321 		    &pinfo, &proph) == PICL_SUCCESS) {
2423941Svenki 			break;
2433941Svenki 		}
2443941Svenki 		nodeh = pnodeh;
2453941Svenki 	}
2463941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr,
247*4669Sfw157321 	    sizeof (uaddr)) != PICL_SUCCESS) {
248*4669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
249*4669Sfw157321 		    sizeof (card->slot_str));
2503941Svenki 		card->slot = -1;
2513941Svenki 		return;
2523941Svenki 	}
2533941Svenki 	pval = (uint8_t *)malloc(pinfo.size);
2543941Svenki 	if (!pval) {
255*4669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
256*4669Sfw157321 		    sizeof (card->slot_str));
2573941Svenki 		card->slot = -1;
2583941Svenki 		return;
2593941Svenki 	}
2603941Svenki 	if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) {
261*4669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
262*4669Sfw157321 		    sizeof (card->slot_str));
2633941Svenki 		card->slot = -1;
2643941Svenki 		free(pval);
2653941Svenki 		return;
2661708Sstevel 	}
2671708Sstevel 
2683941Svenki 	dev_mask = 0;
2693941Svenki 	for (i = 0; i < sizeof (dev_mask); i++)
2703941Svenki 		dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i));
2713941Svenki 	for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) {
2723941Svenki 		if (uaddr[i] == ',') {
2733941Svenki 			uaddr[i] = '\0';
2743941Svenki 			break;
2753941Svenki 		}
2763941Svenki 	}
2773941Svenki 	card->slot = atol(uaddr);
2783941Svenki 	if (((1 << card->slot) & dev_mask) == 0) {
279*4669Sfw157321 		(void) strlcpy(card->slot_str, MOTHERBOARD,
280*4669Sfw157321 		    sizeof (card->slot_str));
2813941Svenki 		card->slot = -1;
2823941Svenki 	} else {
2833941Svenki 		char *p = (char *)(pval+sizeof (dev_mask));
2843941Svenki 		int shift = sizeof (uint32_t)*8-1-card->slot;
2853941Svenki 		uint32_t x = (dev_mask << shift) >> shift;
2863941Svenki 		int count = 0;	/* count # of 1's in x */
2873941Svenki 		int i = 0;
2883941Svenki 		while (x != 0) {
2893941Svenki 			count++;
2903941Svenki 			x &= x-1;
2913941Svenki 		}
2923941Svenki 		while (count > 1) {
293*4669Sfw157321 			while (p[i++] != '\0')
294*4669Sfw157321 				;
2953941Svenki 			count--;
2963941Svenki 		}
2974003Svivek 		(void) strlcpy(card->slot_str, (char *)(p+i),
298*4669Sfw157321 		    sizeof (card->slot_str));
2993941Svenki 	}
3003941Svenki 	free(pval);
3013941Svenki }
3023941Svenki 
3033941Svenki /*
3043941Svenki  * add all io devices under pci in io list
3053941Svenki  */
3063941Svenki /* ARGSUSED */
3073941Svenki static int
3083941Svenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args)
3093941Svenki {
3103941Svenki 	char path[PICL_PROPNAMELEN_MAX];
3113941Svenki 	char class[PICL_CLASSNAMELEN_MAX];
3123941Svenki 	char name[PICL_PROPNAMELEN_MAX];
3133941Svenki 	char model[PICL_PROPNAMELEN_MAX];
3143941Svenki 	char binding_name[PICL_PROPNAMELEN_MAX];
3153941Svenki 	char val[PICL_PROPNAMELEN_MAX];
3163941Svenki 	char *compatible;
3173941Svenki 	picl_errno_t err;
3183941Svenki 	picl_nodehdl_t nodeh;
3193941Svenki 	struct io_card pci_card;
3203941Svenki 
3213941Svenki 	/* Walk through the children */
3223941Svenki 
3233941Svenki 	err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
324*4669Sfw157321 	    sizeof (picl_nodehdl_t));
3253941Svenki 
3263941Svenki 	while (err == PICL_SUCCESS) {
3273941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
328*4669Sfw157321 		    class, sizeof (class));
3293941Svenki 		if (err !=  PICL_SUCCESS)
3303941Svenki 			return (err);
3313941Svenki 
3323941Svenki 		if (args) {
3333941Svenki 			char *val = args;
3343941Svenki 			if (strcmp(class, val) == 0) {
3353941Svenki 				err = picl_get_propval_by_name(nodeh,
336*4669Sfw157321 				    PICL_PROP_PEER, &nodeh,
337*4669Sfw157321 				    sizeof (picl_nodehdl_t));
3383941Svenki 				continue;
3393941Svenki 			} else if (strcmp(val, PICL_CLASS_PCIEX) == 0 &&
340*4669Sfw157321 			    strcmp(class, PICL_CLASS_PCI) == 0) {
3413941Svenki 				err = picl_get_propval_by_name(nodeh,
342*4669Sfw157321 				    PICL_PROP_PEER, &nodeh,
343*4669Sfw157321 				    sizeof (picl_nodehdl_t));
3443941Svenki 				continue;
3453941Svenki 			} else if (strcmp(val, PICL_CLASS_PCI) == 0 &&
346*4669Sfw157321 			    strcmp(class, PICL_CLASS_PCIEX) == 0) {
3473941Svenki 				err = picl_get_propval_by_name(nodeh,
348*4669Sfw157321 				    PICL_PROP_PEER, &nodeh,
349*4669Sfw157321 				    sizeof (picl_nodehdl_t));
3503941Svenki 				continue;
3513941Svenki 			}
3523941Svenki 		}
3533941Svenki 
3543941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
355*4669Sfw157321 		    path, sizeof (path));
3563941Svenki 		if (err != PICL_SUCCESS)
3573941Svenki 			return (err);
3583941Svenki 
3593941Svenki 		(void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
3603941Svenki 
3613941Svenki 		get_bus_type(nodeh, &pci_card);
3623941Svenki 		get_slot_number(nodeh, &pci_card);
3633941Svenki 
3643941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name,
365*4669Sfw157321 		    sizeof (name));
3663941Svenki 		if (err == PICL_PROPNOTFOUND)
3674003Svivek 			(void) strlcpy(name, "", sizeof (name));
3683941Svenki 		else if (err != PICL_SUCCESS)
3693941Svenki 			return (err);
3703941Svenki 
3713941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val,
372*4669Sfw157321 		    sizeof (val));
3733941Svenki 		if (err == PICL_PROPNOTFOUND)
3744003Svivek 			(void) strlcpy(val, "", sizeof (val));
3753941Svenki 		else if (err != PICL_SUCCESS)
3763941Svenki 			return (err);
3773941Svenki 
3783941Svenki 		/* Figure NAC name */
3793941Svenki 		if (pci_card.slot != -1)
3803941Svenki 			(void) snprintf(pci_card.status,
381*4669Sfw157321 			    sizeof (pci_card.status),
382*4669Sfw157321 			    "%s%d", pci_card.slot_str,
383*4669Sfw157321 			    pci_card.slot);
3843941Svenki 		else
3853941Svenki 			(void) snprintf(pci_card.status,
386*4669Sfw157321 			    sizeof (pci_card.status),
387*4669Sfw157321 			    "%s", pci_card.slot_str);
3883941Svenki 
3893941Svenki 		/*
3903941Svenki 		 * Get the name of this card. If binding_name is found,
3913941Svenki 		 * name will be <nodename>-<binding_name>.
3923941Svenki 		 */
3933941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
394*4669Sfw157321 		    binding_name, sizeof (binding_name));
3953941Svenki 		if (err == PICL_SUCCESS) {
3963941Svenki 			if (strcmp(name, binding_name) != 0) {
3973941Svenki 				(void) strlcat(name, "-", sizeof (name));
3983941Svenki 				(void) strlcat(name, binding_name,
399*4669Sfw157321 				    sizeof (name));
4003941Svenki 			}
4013941Svenki 		} else if (err == PICL_PROPNOTFOUND) {
4023941Svenki 			/*
4033941Svenki 			 * if compatible prop is not found, name will be
4043941Svenki 			 * <nodename>-<compatible>
4053941Svenki 			 */
4063941Svenki 			err = sun4v_get_first_compatible_value(nodeh,
407*4669Sfw157321 			    &compatible);
4083941Svenki 			if (err == PICL_SUCCESS) {
4093941Svenki 				(void) strlcat(name, "-", sizeof (name));
4104003Svivek 				(void) strlcat(name, compatible,
411*4669Sfw157321 				    sizeof (name));
4123941Svenki 				free(compatible);
4133941Svenki 			}
4143941Svenki 		} else
4153941Svenki 			return (err);
4163941Svenki 
4173941Svenki 		(void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
4183941Svenki 
4193941Svenki 		/* Get the model of this card */
4203941Svenki 
4213941Svenki 		err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
422*4669Sfw157321 		    model, sizeof (model));
4233941Svenki 		if (err == PICL_PROPNOTFOUND)
4244003Svivek 			(void) strlcpy(model, "", sizeof (model));
4253941Svenki 		else if (err != PICL_SUCCESS)
4263941Svenki 			return (err);
4273941Svenki 		(void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
4283941Svenki 
4293941Svenki 		/* Print NAC name */
4303941Svenki 		log_printf("%-12s", pci_card.status);
4313941Svenki 		/* Print IO Type */
4323941Svenki 		log_printf("%-6s", pci_card.bus_type);
4333941Svenki 		/* Printf Card Name */
4343941Svenki 		log_printf("%-46s", pci_card.name);
4353941Svenki 		/* Print Card Model */
4363941Svenki 		log_printf("%-8s", pci_card.model);
4373941Svenki 		log_printf("\n");
4383941Svenki 		/* Print Status */
4393941Svenki 		log_printf("%-12s", val);
4403941Svenki 		/* Print IO Type */
4413941Svenki 		log_printf("%-6s", "");
4423941Svenki 		/* Print Parent Path */
4433941Svenki 		log_printf("%-46s", pci_card.notes);
4443941Svenki 		log_printf("\n");
4453941Svenki 
4463941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
447*4669Sfw157321 		    sizeof (picl_nodehdl_t));
4483941Svenki 	}
4493941Svenki 	return (PICL_WALK_CONTINUE);
4501708Sstevel }
4511708Sstevel 
4521708Sstevel /*
4531708Sstevel  * display_pci
4541708Sstevel  * Display all the PCI IO cards on this board.
4551708Sstevel  */
4561708Sstevel void
4571708Sstevel sun4v_display_pci(picl_nodehdl_t plafh)
4581708Sstevel {
4593941Svenki 	char *fmt = "%-11s %-5s %-45s %-8s";
4603941Svenki 	/* Have we printed the column headings? */
4613941Svenki 	static int banner = FALSE;
4623941Svenki 
4633941Svenki 	if (banner == FALSE) {
4643941Svenki 		log_printf("\n");
4653941Svenki 		log_printf("============================");
4663941Svenki 		log_printf(" IO Devices ");
4673941Svenki 		log_printf("============================");
4683941Svenki 		log_printf("\n");
4693941Svenki 		log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0);
4703941Svenki 		log_printf("\n");
4713941Svenki 		log_printf(fmt, "Status", "Type", "Path", "", 0);
4723941Svenki 		log_printf("\n");
4733941Svenki 		log_printf("---------------------------------"
474*4669Sfw157321 		    "------------------------------------\n");
4753941Svenki 		banner = TRUE;
4763941Svenki 	}
4773941Svenki 
4783941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
479*4669Sfw157321 	    PICL_CLASS_PCIEX, sun4v_pci_callback);
4803941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
481*4669Sfw157321 	    PICL_CLASS_PCI, sun4v_pci_callback);
4823941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V,
483*4669Sfw157321 	    PICL_CLASS_SUN4V, sun4v_pci_callback);
4843941Svenki }
4853941Svenki 
4863941Svenki /*
4873941Svenki  * return the first compatible value
4883941Svenki  */
4893941Svenki static int
4903941Svenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
4913941Svenki {
4923941Svenki 	picl_errno_t err;
4933941Svenki 	picl_prophdl_t proph;
4943941Svenki 	picl_propinfo_t pinfo;
4953941Svenki 	picl_prophdl_t tblh;
4963941Svenki 	picl_prophdl_t rowproph;
4973941Svenki 	char *pval;
4983941Svenki 
4993941Svenki 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
500*4669Sfw157321 	    &pinfo, &proph);
5013941Svenki 	if (err != PICL_SUCCESS)
5023941Svenki 		return (err);
5033941Svenki 
5043941Svenki 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
5053941Svenki 		pval = malloc(pinfo.size);
5063941Svenki 		if (pval == NULL)
5073941Svenki 			return (PICL_FAILURE);
5083941Svenki 		err = picl_get_propval(proph, pval, pinfo.size);
5093941Svenki 		if (err != PICL_SUCCESS) {
5103941Svenki 			free(pval);
5113941Svenki 			return (err);
5123941Svenki 		}
5133941Svenki 		*outbuf = pval;
5143941Svenki 		return (PICL_SUCCESS);
5153941Svenki 	}
5163941Svenki 
5173941Svenki 	if (pinfo.type != PICL_PTYPE_TABLE)
5183941Svenki 		return (PICL_FAILURE);
5193941Svenki 
5203941Svenki 	/* get first string from table */
5213941Svenki 	err = picl_get_propval(proph, &tblh, pinfo.size);
5223941Svenki 	if (err != PICL_SUCCESS)
5233941Svenki 		return (err);
5243941Svenki 
5253941Svenki 	err = picl_get_next_by_row(tblh, &rowproph);
5263941Svenki 	if (err != PICL_SUCCESS)
5273941Svenki 		return (err);
5283941Svenki 
5293941Svenki 	err = picl_get_propinfo(rowproph, &pinfo);
5303941Svenki 	if (err != PICL_SUCCESS)
5313941Svenki 		return (err);
5323941Svenki 
5333941Svenki 	pval = malloc(pinfo.size);
5343941Svenki 	if (pval == NULL)
5353941Svenki 		return (PICL_FAILURE);
5363941Svenki 
5373941Svenki 	err = picl_get_propval(rowproph, pval, pinfo.size);
5383941Svenki 	if (err != PICL_SUCCESS) {
5393941Svenki 		free(pval);
5403941Svenki 		return (err);
5413941Svenki 	}
5423941Svenki 
5433941Svenki 	*outbuf = pval;
5443941Svenki 	return (PICL_SUCCESS);
5451708Sstevel }
5461708Sstevel 
5473941Svenki /*
5483941Svenki  * print size of a memory segment
5493941Svenki  */
5503941Svenki static void
5513941Svenki print_memory_segment_size(uint64_t size)
5523941Svenki {
5533941Svenki 	uint64_t kbyte = 1024;
5543941Svenki 	uint64_t mbyte = kbyte * kbyte;
5553941Svenki 	uint64_t gbyte = kbyte * mbyte;
5563941Svenki 	char buf[MEMORY_SIZE_FIELD];
5573941Svenki 
5583941Svenki 	if (size >= gbyte) {
5593941Svenki 		if (size % gbyte == 0)
5603941Svenki 			(void) snprintf(buf, sizeof (buf), "%d GB",
561*4669Sfw157321 			    (int)(size / gbyte));
5623941Svenki 		else
5633941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f GB",
564*4669Sfw157321 			    (float)size / gbyte);
5653941Svenki 	} else if (size >= mbyte) {
5663941Svenki 		if (size % mbyte == 0)
5673941Svenki 			(void) snprintf(buf, sizeof (buf), "%d MB",
568*4669Sfw157321 			    (int)(size / mbyte));
5693941Svenki 		else
5703941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f MB",
571*4669Sfw157321 			    (float)size / mbyte);
5723941Svenki 	} else {
5733941Svenki 		if (size % kbyte == 0)
5743941Svenki 			(void) snprintf(buf, sizeof (buf), "%d KB",
575*4669Sfw157321 			    (int)(size / kbyte));
5763941Svenki 		else
5773941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f KB",
578*4669Sfw157321 			    (float)size / kbyte);
5793941Svenki 	}
5803941Svenki 	log_printf("%-7s ", buf);
5813941Svenki }
5823941Svenki 
5833941Svenki /*
584*4669Sfw157321  * Enumerate banks and dimms within a memory segment.  We're handed
585*4669Sfw157321  * the first bank within the segment - we assume there are dimms
586*4669Sfw157321  * (memory-module) nodes underneath.
5873941Svenki  */
5883941Svenki static void
589*4669Sfw157321 print_memory_segment_contain(picl_nodehdl_t bank_nodeh)
5901708Sstevel {
5913941Svenki 	char val[PICL_PROPNAMELEN_MAX];
592*4669Sfw157321 	picl_nodehdl_t module_nodeh;
593*4669Sfw157321 	int flag = 0;
594*4669Sfw157321 
595*4669Sfw157321 	do {
596*4669Sfw157321 		if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD,
597*4669Sfw157321 		    &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS)
598*4669Sfw157321 			continue;
599*4669Sfw157321 		do {
600*4669Sfw157321 			if (picl_get_propval_by_name(module_nodeh,
601*4669Sfw157321 			    PICL_PROP_NAC, val, sizeof (val)) !=
602*4669Sfw157321 			    PICL_SUCCESS)
603*4669Sfw157321 				continue;
604*4669Sfw157321 			else {
605*4669Sfw157321 				if (!flag) {
606*4669Sfw157321 					log_printf("%-30s\n", val);
607*4669Sfw157321 					flag = 1;
608*4669Sfw157321 				} else
609*4669Sfw157321 					log_printf("%57s\n", val);
610*4669Sfw157321 			}
611*4669Sfw157321 		} while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER,
612*4669Sfw157321 		    &module_nodeh, sizeof (picl_nodehdl_t)) ==
613*4669Sfw157321 		    PICL_SUCCESS);
614*4669Sfw157321 	} while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER,
615*4669Sfw157321 	    &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS);
6163941Svenki }
6173941Svenki 
6183941Svenki /*
6193941Svenki  * Search node where _class=="memory-segment"
6203941Svenki  * print "Base Address", "Size", etc
6213941Svenki  */
6223941Svenki /*ARGSUSED*/
6233941Svenki static int
6243941Svenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args)
6253941Svenki {
6263941Svenki 	uint64_t base;
6273941Svenki 	uint64_t size;
6283941Svenki 	uint64_t ifactor;
6293941Svenki 	picl_errno_t err = PICL_SUCCESS;
6303941Svenki 
6313941Svenki 	if (class_node_found == 0) {
6323941Svenki 		class_node_found = 1;
6333941Svenki 		return (PICL_WALK_TERMINATE);
6343941Svenki 	}
6353941Svenki 	while (err == PICL_SUCCESS) {
6363941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS,
637*4669Sfw157321 		    &base, sizeof (base));
6383941Svenki 		if (err !=  PICL_SUCCESS)
6393941Svenki 			break;
6403941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE,
641*4669Sfw157321 		    &size, sizeof (size));
6423941Svenki 		if (err !=  PICL_SUCCESS)
6433941Svenki 			break;
6443941Svenki 		err = picl_get_propval_by_name(nodeh,
645*4669Sfw157321 		    PICL_PROP_INTERLEAVE_FACTOR, &ifactor,
646*4669Sfw157321 		    sizeof (ifactor));
6473941Svenki 		if (err !=  PICL_SUCCESS)
6483941Svenki 			break;
6493941Svenki 		log_printf("%-13llx", base);
6503941Svenki 		print_memory_segment_size(size);
651*4669Sfw157321 		log_printf("%-18lld", ifactor);
652*4669Sfw157321 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
653*4669Sfw157321 		    &nodeh, sizeof (nodeh));
654*4669Sfw157321 		if (err ==  PICL_SUCCESS)
655*4669Sfw157321 			print_memory_segment_contain(nodeh);
6563941Svenki 		log_printf("\n");
6573941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
658*4669Sfw157321 		    sizeof (picl_nodehdl_t));
6593941Svenki 	}
6603941Svenki 
6613941Svenki 	return (PICL_WALK_CONTINUE);
6623941Svenki }
6633941Svenki 
6643941Svenki /*ARGSUSED*/
6653941Svenki void
6663941Svenki sun4v_display_memory_conf(picl_nodehdl_t plafh)
6673941Svenki {
6683941Svenki 	char *fmt = "%-12s %-7s %-9s %-20s";
6693941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
670*4669Sfw157321 	    NULL, sun4v_memory_conf_callback);
6713941Svenki 	if (class_node_found == 0)
6723941Svenki 		return;
6733941Svenki 	log_printf("\n");
6743941Svenki 	log_printf("============================");
6753941Svenki 	log_printf(" Memory Configuration ");
6763941Svenki 	log_printf("============================");
6773941Svenki 	log_printf("\n");
6783941Svenki 	log_printf("Segment Table:\n");
679*4669Sfw157321 	log_printf(
680*4669Sfw157321 	    "---------------------------------------------------------\n");
6813941Svenki 	log_printf(fmt, "Base Address", "Size", "Interleave Factor",
682*4669Sfw157321 	    "Contains", 0);
6833941Svenki 	log_printf("\n");
684*4669Sfw157321 	log_printf(
685*4669Sfw157321 	    "---------------------------------------------------------\n");
6863941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
687*4669Sfw157321 	    NULL, sun4v_memory_conf_callback);
6881708Sstevel }
6891708Sstevel 
6901708Sstevel void
6911708Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh)
6921708Sstevel {
6933941Svenki 	char *fmt = "%-12s %-5s %-8s %-19s %-5s";
6941708Sstevel 
6951708Sstevel 	/*
6961708Sstevel 	 * Display the table header for CPUs . Then display the CPU
6971708Sstevel 	 * frequency, cache size, and processor revision of all cpus.
6981708Sstevel 	 */
6991708Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
700*4669Sfw157321 	    "\n"
701*4669Sfw157321 	    "========================="
702*4669Sfw157321 	    " CPUs "
703*4669Sfw157321 	    "==============================================="
704*4669Sfw157321 	    "\n"
705*4669Sfw157321 	    "\n"));
7061708Sstevel 	log_printf(fmt, "", "", "", "CPU", "CPU", 0);
7071708Sstevel 	log_printf("\n");
7081708Sstevel 	log_printf(fmt, "Location", "CPU", "Freq",
709*4669Sfw157321 	    "Implementation", "Mask", 0);
7101708Sstevel 	log_printf("\n");
7111708Sstevel 	log_printf(fmt, "------------", "-----", "--------",
712*4669Sfw157321 	    "-------------------", "-----", 0);
7131708Sstevel 	log_printf("\n");
7141708Sstevel 
7151708Sstevel 	(void) picl_walk_tree_by_class(plafh, "cpu", "cpu", sun4v_display_cpus);
7161708Sstevel }
7171708Sstevel 
7181708Sstevel /*
7191708Sstevel  * Display the CPUs present on this board.
7201708Sstevel  */
7211708Sstevel /*ARGSUSED*/
7221708Sstevel int
7231708Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
7241708Sstevel {
7251708Sstevel 	int status;
7263941Svenki 	picl_prophdl_t proph;
7273941Svenki 	picl_prophdl_t tblh;
7283941Svenki 	picl_prophdl_t rowproph;
7291708Sstevel 	picl_propinfo_t propinfo;
7303941Svenki 	int *int_value;
7313941Svenki 	uint64_t cpuid, mask_no;
7323941Svenki 	char *comp_value;
7333941Svenki 	char *no_prop_value = "   ";
7343941Svenki 	char freq_str[MAXSTRLEN];
7353941Svenki 	char fru_name[MAXSTRLEN];
7361708Sstevel 
7371708Sstevel 	/*
7381708Sstevel 	 * Get cpuid property and print it and the NAC name
7391708Sstevel 	 */
7401708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "cpuid", &propinfo, &proph);
7411708Sstevel 	if (status == PICL_SUCCESS) {
7421708Sstevel 		status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
7431708Sstevel 		if (status != PICL_SUCCESS) {
7443941Svenki 			log_printf("%-13s", no_prop_value);
7453941Svenki 			log_printf("%-6s", no_prop_value);
7461708Sstevel 		} else {
7471708Sstevel 			(void) snprintf(fru_name, sizeof (fru_name), "%s%d",
7481708Sstevel 			    CPU_STRAND_NAC, (int)cpuid);
7493941Svenki 			log_printf("%-13s", fru_name);
7503941Svenki 			log_printf("%-6d", (int)cpuid);
7511708Sstevel 		}
7521708Sstevel 	} else {
7533941Svenki 		log_printf("%-13s", no_prop_value);
7543941Svenki 		log_printf("%-6s", no_prop_value);
7551708Sstevel 	}
7561708Sstevel 
7571708Sstevel clock_freq:
7581708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
759*4669Sfw157321 	    &proph);
7601708Sstevel 	if (status == PICL_SUCCESS) {
7611708Sstevel 		int_value = malloc(propinfo.size);
7621708Sstevel 		if (int_value == NULL) {
7633941Svenki 			log_printf("%-9s", no_prop_value);
7641708Sstevel 			goto compatible;
7651708Sstevel 		}
7661708Sstevel 		status = picl_get_propval(proph, int_value, propinfo.size);
7671708Sstevel 		if (status != PICL_SUCCESS) {
7683941Svenki 			log_printf("%-9s", no_prop_value);
7691708Sstevel 		} else {
7701708Sstevel 			/* Running frequency */
7711708Sstevel 			(void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
7721708Sstevel 			    CLK_FREQ_TO_MHZ(*int_value));
7733941Svenki 			log_printf("%-9s", freq_str);
7741708Sstevel 		}
7751708Sstevel 		free(int_value);
7761708Sstevel 	} else
7773941Svenki 		log_printf("%-9s", no_prop_value);
7781708Sstevel 
7791708Sstevel compatible:
7801708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
781*4669Sfw157321 	    &proph);
7821708Sstevel 	if (status == PICL_SUCCESS) {
7831708Sstevel 		if (propinfo.type == PICL_PTYPE_CHARSTRING) {
7841708Sstevel 			/*
7851708Sstevel 			 * Compatible Property only has 1 value
7861708Sstevel 			 */
7871708Sstevel 			comp_value = malloc(propinfo.size);
7881708Sstevel 			if (comp_value == NULL) {
7893941Svenki 				log_printf("%-20s", no_prop_value, 0);
7901708Sstevel 				goto mask;
7911708Sstevel 			}
7921708Sstevel 			status = picl_get_propval(proph, comp_value,
793*4669Sfw157321 			    propinfo.size);
7943941Svenki 			if (status != PICL_SUCCESS)
7953941Svenki 				log_printf("%-20s", no_prop_value, 0);
7963941Svenki 			else
7973941Svenki 				log_printf("%-20s", comp_value, 0);
7983941Svenki 			free(comp_value);
7991708Sstevel 		} else if (propinfo.type == PICL_PTYPE_TABLE) {
8001708Sstevel 			/*
8011708Sstevel 			 * Compatible Property has multiple values
8021708Sstevel 			 */
8031708Sstevel 			status = picl_get_propval(proph, &tblh, propinfo.size);
8041708Sstevel 			if (status != PICL_SUCCESS) {
8053941Svenki 				log_printf("%-20s", no_prop_value, 0);
8061708Sstevel 				goto mask;
8071708Sstevel 			}
8081708Sstevel 			status = picl_get_next_by_row(tblh, &rowproph);
8091708Sstevel 			if (status != PICL_SUCCESS) {
8103941Svenki 				log_printf("%-20s", no_prop_value, 0);
8111708Sstevel 				goto mask;
8121708Sstevel 			}
8131708Sstevel 
8141708Sstevel 			status = picl_get_propinfo(rowproph, &propinfo);
8151708Sstevel 			if (status != PICL_SUCCESS) {
8163941Svenki 				log_printf("%-20s", no_prop_value, 0);
8171708Sstevel 				goto mask;
8181708Sstevel 			}
8191708Sstevel 
8201708Sstevel 			comp_value = malloc(propinfo.size);
8211708Sstevel 			if (comp_value == NULL) {
8223941Svenki 				log_printf("%-20s", no_prop_value, 0);
8231708Sstevel 				goto mask;
8241708Sstevel 			}
8251708Sstevel 			status = picl_get_propval(rowproph, comp_value,
826*4669Sfw157321 			    propinfo.size);
8273941Svenki 			if (status != PICL_SUCCESS)
8283941Svenki 				log_printf("%-20s", no_prop_value, 0);
8293941Svenki 			else
8303941Svenki 				log_printf("%-20s", comp_value, 0);
8311708Sstevel 			free(comp_value);
8321708Sstevel 		}
8331708Sstevel 	} else
8343941Svenki 		log_printf("%-20s", no_prop_value, 0);
8351708Sstevel 
8361708Sstevel mask:
8371708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "mask#", &propinfo, &proph);
8381708Sstevel 	if (status == PICL_SUCCESS) {
8391708Sstevel 		status = picl_get_propval(proph, &mask_no, sizeof (mask_no));
8401708Sstevel 		if (status != PICL_SUCCESS) {
8413941Svenki 			log_printf("%-9s", no_prop_value);
8421708Sstevel 		} else {
8431708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, " %2d.%d"),
844*4669Sfw157321 			    (mask_no>> 4) & 0xf, mask_no & 0xf);
8451708Sstevel 		}
8461708Sstevel 	} else
8473941Svenki 		log_printf("%-9s", no_prop_value);
8481708Sstevel 
8491708Sstevel done:
8501708Sstevel 	log_printf("\n");
8511708Sstevel 	return (PICL_WALK_CONTINUE);
8521708Sstevel }
8531708Sstevel 
8541708Sstevel void
8551708Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
8561708Sstevel {
8571708Sstevel #ifdef	lint
8581708Sstevel 	flag = flag;
8591708Sstevel 	root = root;
8601708Sstevel 	plafh = plafh;
8611708Sstevel #endif
8621708Sstevel 	/*
8631708Sstevel 	 * This function is intentionally empty
8641708Sstevel 	 */
8651708Sstevel }
8661708Sstevel 
8671708Sstevel void
8681708Sstevel display_boardnum(int num)
8691708Sstevel {
8701708Sstevel 	log_printf("%2d   ", num, 0);
8711708Sstevel }
8723941Svenki 
8733941Svenki static void
8743941Svenki sun4v_disp_env_status()
8753941Svenki {
8763941Svenki 	if (phyplatformh == 0)
8773941Svenki 		return;
8783941Svenki 	log_printf("\n");
8793941Svenki 	log_printf("============================");
8803941Svenki 	log_printf(" Environmental Status ");
8813941Svenki 	log_printf("============================");
8823941Svenki 	log_printf("\n");
8833941Svenki 
8843941Svenki 	class_node_found = 0;
8853941Svenki 	all_status_ok = 1;
8863941Svenki 	sun4v_env_print_fan_sensors();
8873941Svenki 
8883941Svenki 	class_node_found = 0;
8893941Svenki 	all_status_ok = 1;
8903941Svenki 	sun4v_env_print_fan_indicators();
8913941Svenki 
8923941Svenki 	class_node_found = 0;
8933941Svenki 	all_status_ok = 1;
8943941Svenki 	sun4v_env_print_temp_sensors();
8953941Svenki 
8963941Svenki 	class_node_found = 0;
8973941Svenki 	all_status_ok = 1;
8983941Svenki 	sun4v_env_print_temp_indicators();
8993941Svenki 
9003941Svenki 	class_node_found = 0;
9013941Svenki 	all_status_ok = 1;
9023941Svenki 	sun4v_env_print_current_sensors();
9033941Svenki 
9043941Svenki 	class_node_found = 0;
9053941Svenki 	all_status_ok = 1;
9063941Svenki 	sun4v_env_print_current_indicators();
9073941Svenki 
9083941Svenki 	class_node_found = 0;
9093941Svenki 	all_status_ok = 1;
9103941Svenki 	sun4v_env_print_voltage_sensors();
9113941Svenki 
9123941Svenki 	class_node_found = 0;
9133941Svenki 	all_status_ok = 1;
9143941Svenki 	sun4v_env_print_voltage_indicators();
9153941Svenki 
9163941Svenki 	class_node_found = 0;
9173941Svenki 	sun4v_env_print_LEDs();
9183941Svenki 
9193941Svenki 	class_node_found = 0;
9203941Svenki 	all_status_ok = 1;
9213941Svenki 	sun4v_print_fru_status();
9223941Svenki 
9233941Svenki 	class_node_found = 0;
9243941Svenki 	sun4v_print_fw_rev();
9253941Svenki 
9263941Svenki 	sun4v_print_chassis_serial_no();
9273941Svenki }
9283941Svenki 
9293941Svenki /*ARGSUSED*/
9303941Svenki static int
9313941Svenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args)
9323941Svenki {
9333941Svenki 	char val[PICL_PROPNAMELEN_MAX];
9343941Svenki 	picl_nodehdl_t parenth;
9353941Svenki 	char *names[PARENT_NAMES];
9363941Svenki 	char *loc;
9373941Svenki 	int i;
9383941Svenki 	char *prop;
9393941Svenki 	picl_errno_t err;
9403941Svenki 	int32_t lo_warning, lo_shutdown;
9413941Svenki 	int32_t hi_warning, hi_shutdown;
9423941Svenki 	int32_t current_val;
9433941Svenki 
9443941Svenki 	if (class_node_found == 0) {
9453941Svenki 		class_node_found = 1;
9463941Svenki 		return (PICL_WALK_TERMINATE);
9473941Svenki 	}
9483941Svenki 
9493941Svenki 	if (syserrlog == 0) {
9503941Svenki 		err = picl_get_propval_by_name(nodeh,
951*4669Sfw157321 		    PICL_PROP_OPERATIONAL_STATUS, val,
952*4669Sfw157321 		    sizeof (val));
9533941Svenki 		if (err == PICL_SUCCESS) {
9543941Svenki 			if (strcmp(val, "disabled") == 0) {
9553941Svenki 				if (all_status_ok) {
9563941Svenki 					all_status_ok = 0;
9573941Svenki 					return (PICL_WALK_TERMINATE);
9583941Svenki 				}
9593941Svenki 			} else
9603941Svenki 				return (PICL_WALK_CONTINUE);
9613941Svenki 		} else {
9623941Svenki 			all_status_ok = 0;
9633941Svenki 			return (PICL_WALK_TERMINATE);
9643941Svenki 		}
9653941Svenki 	}
9663941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
967*4669Sfw157321 	    sizeof (parenth));
9683941Svenki 	if (err != PICL_SUCCESS) {
9693941Svenki 		log_printf("\n");
9703941Svenki 		return (PICL_WALK_CONTINUE);
9713941Svenki 	}
9724003Svivek 
9733941Svenki 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
9743941Svenki 		return (PICL_WALK_TERMINATE);
9753941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
9763941Svenki 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
9773941Svenki 			while (--i > -1)
9783941Svenki 				free(names[i]);
9793941Svenki 			free(loc);
9803941Svenki 			return (PICL_WALK_TERMINATE);
9813941Svenki 		}
9823941Svenki 	i = 0;
9833941Svenki 	while (err == PICL_SUCCESS) {
9843941Svenki 		if (parenth == chassish || parenth == phyplatformh)
9853941Svenki 			break;
9863941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
987*4669Sfw157321 		    names[i++], PICL_PROPNAMELEN_MAX);
9883941Svenki 		if (err != PICL_SUCCESS) {
9893941Svenki 			i--;
9903941Svenki 			break;
9913941Svenki 		}
9923941Svenki 		if (i == PARENT_NAMES)
9933941Svenki 			break;
9943941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
995*4669Sfw157321 		    &parenth, sizeof (parenth));
9963941Svenki 	}
9973941Svenki 	loc[0] = '\0';
9984003Svivek 	if (--i > -1) {
9994003Svivek 		(void) strlcat(loc, names[i],
1000*4669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
10014003Svivek 	}
10023941Svenki 	while (--i > -1) {
10034003Svivek 		(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX*PARENT_NAMES);
10044003Svivek 		(void) strlcat(loc, names[i],
1005*4669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
10063941Svenki 	}
1007*4669Sfw157321 	log_printf("%-21s", loc);
10083941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
10093941Svenki 		free(names[i]);
10103941Svenki 	free(loc);
10113941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
1012*4669Sfw157321 	    sizeof (val));
10133941Svenki 	if (err == PICL_SUCCESS)
10143941Svenki 		log_printf("%-15s", val);
10153941Svenki 
10163941Svenki 	prop = (char *)args;
10173941Svenki 	if (!prop) {
10183941Svenki 		log_printf("\n");
10193941Svenki 		return (PICL_WALK_CONTINUE);
10203941Svenki 	}
10213941Svenki 	if (picl_get_propval_by_name(nodeh, prop, &current_val,
1022*4669Sfw157321 	    sizeof (current_val)) != PICL_SUCCESS) {
10233941Svenki 		log_printf("\n");
10243941Svenki 		return (PICL_WALK_CONTINUE);
10253941Svenki 	}
10263941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_WARNING,
1027*4669Sfw157321 	    &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS)
10283941Svenki 		lo_warning = INVALID_THRESHOLD;
10293941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_SHUTDOWN,
1030*4669Sfw157321 	    &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS)
10313941Svenki 		lo_shutdown = INVALID_THRESHOLD;
10323941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_WARNING,
1033*4669Sfw157321 	    &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS)
10343941Svenki 		hi_warning = INVALID_THRESHOLD;
10353941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_SHUTDOWN,
1036*4669Sfw157321 	    &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS)
10373941Svenki 		hi_shutdown = INVALID_THRESHOLD;
10383941Svenki 
10393941Svenki 	if ((lo_shutdown != INVALID_THRESHOLD &&
1040*4669Sfw157321 	    current_val <= lo_shutdown) ||
1041*4669Sfw157321 	    (hi_shutdown != INVALID_THRESHOLD &&
1042*4669Sfw157321 	    current_val >= hi_shutdown)) {
10433941Svenki 		log_printf("%-s", "failed (");
10443941Svenki 		log_printf("%-d", current_val);
10453941Svenki 		log_printf("%-s", ")");
10463941Svenki 	} else if ((lo_warning != INVALID_THRESHOLD &&
1047*4669Sfw157321 	    current_val <= lo_warning) ||
1048*4669Sfw157321 	    (hi_warning != INVALID_THRESHOLD &&
1049*4669Sfw157321 	    current_val >= hi_warning)) {
10503941Svenki 		log_printf("%-s", "warning (");
10513941Svenki 		log_printf("%-d", current_val);
10523941Svenki 		log_printf("%-s", ")");
10533941Svenki 	} else
10543941Svenki 		log_printf("%-s", "ok");
10553941Svenki 
10563941Svenki 	log_printf("\n");
10573941Svenki 	return (PICL_WALK_CONTINUE);
10583941Svenki }
10593941Svenki 
10603941Svenki /*ARGSUSED*/
10613941Svenki static int
10623941Svenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args)
10633941Svenki {
10643941Svenki 	char val[PICL_PROPNAMELEN_MAX];
10653941Svenki 	char status[PICL_PROPNAMELEN_MAX];
10663941Svenki 	picl_nodehdl_t parenth;
10673941Svenki 	char *names[PARENT_NAMES];
10683941Svenki 	char *loc;
10693941Svenki 	int i = 0;
10703941Svenki 	char *prop = (char *)args;
10713941Svenki 	picl_errno_t err = PICL_SUCCESS;
10723941Svenki 
10733941Svenki 	if (class_node_found == 0) {
10743941Svenki 		class_node_found = 1;
10753941Svenki 		return (PICL_WALK_TERMINATE);
10763941Svenki 	}
10773941Svenki 	if (syserrlog == 0) {
10783941Svenki 		err = picl_get_propval_by_name(nodeh,
1079*4669Sfw157321 		    PICL_PROP_OPERATIONAL_STATUS, status,
1080*4669Sfw157321 		    sizeof (status));
10813941Svenki 		if (err == PICL_SUCCESS) {
10823941Svenki 			if (strcmp(status, "disabled") == 0) {
10833941Svenki 				if (all_status_ok) {
10843941Svenki 					all_status_ok = 0;
10853941Svenki 					return (PICL_WALK_TERMINATE);
10863941Svenki 				}
10873941Svenki 			} else
10883941Svenki 				return (PICL_WALK_CONTINUE);
10893941Svenki 		} else {
10903941Svenki 			all_status_ok = 0;
10913941Svenki 			return (PICL_WALK_TERMINATE);
10923941Svenki 		}
10933941Svenki 	}
10943941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1095*4669Sfw157321 	    sizeof (parenth));
10963941Svenki 	if (err != PICL_SUCCESS) {
10973941Svenki 		log_printf("\n");
10983941Svenki 		return (PICL_WALK_CONTINUE);
10993941Svenki 	}
11003941Svenki 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
11013941Svenki 		return (PICL_WALK_TERMINATE);
11023941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
11033941Svenki 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
11043941Svenki 			while (--i > -1)
11053941Svenki 				free(names[i]);
11063941Svenki 			free(loc);
11073941Svenki 			return (PICL_WALK_TERMINATE);
11083941Svenki 		}
11093941Svenki 	i = 0;
11103941Svenki 	while (err == PICL_SUCCESS) {
11113941Svenki 		if (parenth == chassish || parenth == phyplatformh)
11123941Svenki 			break;
11133941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1114*4669Sfw157321 		    names[i++], PICL_PROPNAMELEN_MAX);
11153941Svenki 		if (err != PICL_SUCCESS) {
11163941Svenki 			i--;
11173941Svenki 			break;
11183941Svenki 		}
11193941Svenki 		if (i == PARENT_NAMES)
11203941Svenki 			break;
11213941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
1122*4669Sfw157321 		    &parenth, sizeof (parenth));
11233941Svenki 	}
11243941Svenki 	loc[0] = '\0';
11254003Svivek 	if (--i > -1) {
11264003Svivek 		(void) strlcat(loc, names[i],
1127*4669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
11284003Svivek 	}
11293941Svenki 	while (--i > -1) {
11304003Svivek 		(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES);
11314003Svivek 		(void) strlcat(loc, names[i],
1132*4669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
11333941Svenki 	}
1134*4669Sfw157321 	log_printf("%-21s", loc);
11353941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
11363941Svenki 		free(names[i]);
11373941Svenki 	free(loc);
11383941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
1139*4669Sfw157321 	    sizeof (val));
11403941Svenki 	if (err == PICL_SUCCESS)
11413941Svenki 		log_printf("%-15s", val);
11423941Svenki 	if (syserrlog == 0) {
11433941Svenki 		log_printf("%-8s", status);
11443941Svenki 		return (PICL_WALK_CONTINUE);
11453941Svenki 	}
1146*4669Sfw157321 	err = picl_get_propval_by_name(nodeh, prop, val, sizeof (val));
11473941Svenki 	if (err == PICL_SUCCESS)
11483941Svenki 		log_printf("%-8s", val);
11493941Svenki 	log_printf("\n");
11503941Svenki 	return (PICL_WALK_CONTINUE);
11513941Svenki }
11523941Svenki 
11533941Svenki static void
11543941Svenki sun4v_env_print_fan_sensors()
11553941Svenki {
1156*4669Sfw157321 	char *fmt = "%-20s %-14s %-10s\n";
11573941Svenki 	/*
11583941Svenki 	 * If there isn't any fan sensor node, return now.
11593941Svenki 	 */
11603941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1161*4669Sfw157321 	    PICL_CLASS_RPM_SENSOR, (void *)PICL_CLASS_RPM_SENSOR,
1162*4669Sfw157321 	    sun4v_env_print_sensor_callback);
11633941Svenki 	if (!class_node_found)
11643941Svenki 		return;
11653941Svenki 	log_printf("Fan sensors:\n");
11663941Svenki 	if (syserrlog == 0) {
11673941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1168*4669Sfw157321 		    PICL_CLASS_RPM_SENSOR,
1169*4669Sfw157321 		    NULL, sun4v_env_print_sensor_callback);
11703941Svenki 		if (all_status_ok) {
11713941Svenki 			log_printf("All fan sensors are OK.\n");
11723941Svenki 			return;
11733941Svenki 		}
11743941Svenki 	}
1175*4669Sfw157321 	log_printf("------------------------------------------\n");
11763941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1177*4669Sfw157321 	log_printf("------------------------------------------\n");
11783941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR,
1179*4669Sfw157321 	    PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
11803941Svenki }
11813941Svenki 
11823941Svenki static void
11833941Svenki sun4v_env_print_fan_indicators()
11843941Svenki {
1185*4669Sfw157321 	char *fmt = "%-20s %-14s %-10s\n";
11863941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1187*4669Sfw157321 	    PICL_CLASS_RPM_INDICATOR, (void *)PICL_CLASS_RPM_INDICATOR,
1188*4669Sfw157321 	    sun4v_env_print_indicator_callback);
11893941Svenki 	if (!class_node_found)
11903941Svenki 		return;
11913941Svenki 	log_printf("\nFan indicators:\n");
11923941Svenki 	if (syserrlog == 0) {
11933941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1194*4669Sfw157321 		    PICL_CLASS_RPM_INDICATOR,
1195*4669Sfw157321 		    NULL, sun4v_env_print_indicator_callback);
11963941Svenki 		if (all_status_ok) {
11973941Svenki 			log_printf("All fan indicators are OK.\n");
11983941Svenki 			return;
11993941Svenki 		}
12003941Svenki 	}
1201*4669Sfw157321 	log_printf("---------------------------------------------\n");
12023941Svenki 	log_printf(fmt, "Location", "Sensor", "Condition", 0);
1203*4669Sfw157321 	log_printf("---------------------------------------------\n");
12043941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR,
1205*4669Sfw157321 	    PICL_CLASS_RPM_INDICATOR, sun4v_env_print_indicator_callback);
12063941Svenki }
12073941Svenki 
12083941Svenki static void
12093941Svenki sun4v_env_print_temp_sensors()
12103941Svenki {
1211*4669Sfw157321 	char *fmt = "%-20s %-14s %-10s\n";
12123941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1213*4669Sfw157321 	    PICL_CLASS_TEMPERATURE_SENSOR,
1214*4669Sfw157321 	    (void *)PICL_PROP_TEMPERATURE,
1215*4669Sfw157321 	    sun4v_env_print_sensor_callback);
12163941Svenki 	if (!class_node_found)
12173941Svenki 		return;
12183941Svenki 
12193941Svenki 	log_printf("\nTemperature sensors:\n");
12203941Svenki 	if (syserrlog == 0) {
12213941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1222*4669Sfw157321 		    PICL_CLASS_TEMPERATURE_SENSOR,
1223*4669Sfw157321 		    NULL, sun4v_env_print_sensor_callback);
12243941Svenki 		if (all_status_ok) {
12253941Svenki 			log_printf("All temperature sensors are OK.\n");
12263941Svenki 			return;
12273941Svenki 		}
12283941Svenki 	}
1229*4669Sfw157321 	log_printf("------------------------------------------\n");
12303941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1231*4669Sfw157321 	log_printf("------------------------------------------\n");
12323941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1233*4669Sfw157321 	    PICL_CLASS_TEMPERATURE_SENSOR,
1234*4669Sfw157321 	    (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
12353941Svenki }
12363941Svenki 
12373941Svenki static void
12383941Svenki sun4v_env_print_temp_indicators()
12393941Svenki {
1240*4669Sfw157321 	char *fmt = "%-20s %-14s %-8s\n";
12413941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1242*4669Sfw157321 	    PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION,
1243*4669Sfw157321 	    sun4v_env_print_indicator_callback);
12443941Svenki 	if (!class_node_found)
12453941Svenki 		return;
12463941Svenki 	log_printf("\nTemperature indicators:\n");
12473941Svenki 	if (syserrlog == 0) {
12483941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1249*4669Sfw157321 		    PICL_CLASS_TEMPERATURE_INDICATOR, NULL,
1250*4669Sfw157321 		    sun4v_env_print_indicator_callback);
12513941Svenki 		if (all_status_ok) {
12523941Svenki 			log_printf("All temperature indicators are OK.\n");
12533941Svenki 			return;
12543941Svenki 		}
12553941Svenki 	}
1256*4669Sfw157321 	log_printf("---------------------------------------\n");
12573941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
1258*4669Sfw157321 	log_printf("---------------------------------------\n");
12593941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1260*4669Sfw157321 	    PICL_CLASS_TEMPERATURE_INDICATOR,
1261*4669Sfw157321 	    (void *)PICL_PROP_CONDITION,
1262*4669Sfw157321 	    sun4v_env_print_indicator_callback);
12633941Svenki }
12643941Svenki 
12653941Svenki static void
12663941Svenki sun4v_env_print_current_sensors()
12673941Svenki {
1268*4669Sfw157321 	char *fmt = "%-20s %-14s %-10s\n";
12693941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR,
1270*4669Sfw157321 	    (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
12713941Svenki 	if (!class_node_found)
12723941Svenki 		return;
12733941Svenki 	log_printf("\nCurrent sensors:\n");
12743941Svenki 	if (syserrlog == 0) {
12753941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1276*4669Sfw157321 		    PICL_CLASS_CURRENT_SENSOR,
1277*4669Sfw157321 		    NULL, sun4v_env_print_sensor_callback);
12783941Svenki 		if (all_status_ok) {
12793941Svenki 			log_printf("All current sensors are OK.\n");
12803941Svenki 			return;
12813941Svenki 		}
12823941Svenki 	}
1283*4669Sfw157321 	log_printf("------------------------------------------\n");
12843941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1285*4669Sfw157321 	log_printf("------------------------------------------\n");
12863941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1287*4669Sfw157321 	    PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
1288*4669Sfw157321 	    sun4v_env_print_sensor_callback);
12893941Svenki }
12903941Svenki 
12913941Svenki static void
12923941Svenki sun4v_env_print_current_indicators()
12933941Svenki {
1294*4669Sfw157321 	char *fmt = "%-20s %-14s %-8s\n";
12953941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1296*4669Sfw157321 	    PICL_CLASS_CURRENT_INDICATOR,
1297*4669Sfw157321 	    (void *)PICL_PROP_CONDITION,
1298*4669Sfw157321 	    sun4v_env_print_indicator_callback);
12993941Svenki 	if (!class_node_found)
13003941Svenki 		return;
13013941Svenki 	log_printf("\nCurrent indicators:\n");
13023941Svenki 	if (syserrlog == 0) {
13033941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1304*4669Sfw157321 		    PICL_CLASS_CURRENT_INDICATOR, NULL,
1305*4669Sfw157321 		    sun4v_env_print_indicator_callback);
13063941Svenki 		if (all_status_ok) {
13073941Svenki 			log_printf("All current indicators are OK.\n");
13083941Svenki 			return;
13093941Svenki 		}
13103941Svenki 	}
1311*4669Sfw157321 	log_printf("---------------------------------------------\n");
13123941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
1313*4669Sfw157321 	log_printf("---------------------------------------------\n");
13143941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1315*4669Sfw157321 	    PICL_CLASS_CURRENT_INDICATOR,
1316*4669Sfw157321 	    (void *)PICL_PROP_CONDITION,
1317*4669Sfw157321 	    sun4v_env_print_indicator_callback);
13183941Svenki }
13193941Svenki 
13203941Svenki static void
13213941Svenki sun4v_env_print_voltage_sensors()
13223941Svenki {
1323*4669Sfw157321 	char *fmt = "%-20s %-14s %-10s\n";
13243941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1325*4669Sfw157321 	    PICL_CLASS_VOLTAGE_SENSOR,
1326*4669Sfw157321 	    PICL_PROP_VOLTAGE,
1327*4669Sfw157321 	    sun4v_env_print_sensor_callback);
13283941Svenki 	if (!class_node_found)
13293941Svenki 		return;
13303941Svenki 	log_printf("\nVoltage sensors:\n");
13313941Svenki 	if (syserrlog == 0) {
13323941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1333*4669Sfw157321 		    PICL_CLASS_VOLTAGE_SENSOR,
1334*4669Sfw157321 		    NULL, sun4v_env_print_sensor_callback);
13353941Svenki 		if (all_status_ok) {
13363941Svenki 			log_printf("All voltage sensors are OK.\n");
13373941Svenki 			return;
13383941Svenki 		}
13393941Svenki 	}
1340*4669Sfw157321 	log_printf("------------------------------------------\n");
13413941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1342*4669Sfw157321 	log_printf("------------------------------------------\n");
13433941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1344*4669Sfw157321 	    PICL_CLASS_VOLTAGE_SENSOR,
1345*4669Sfw157321 	    (void *)PICL_PROP_VOLTAGE,
1346*4669Sfw157321 	    sun4v_env_print_sensor_callback);
13473941Svenki }
13483941Svenki 
13493941Svenki static void
13503941Svenki sun4v_env_print_voltage_indicators()
13513941Svenki {
1352*4669Sfw157321 	char *fmt = "%-20s %-14s %-8s\n";
13533941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1354*4669Sfw157321 	    PICL_CLASS_VOLTAGE_INDICATOR,
1355*4669Sfw157321 	    (void *)PICL_PROP_CONDITION,
1356*4669Sfw157321 	    sun4v_env_print_indicator_callback);
13573941Svenki 	if (!class_node_found)
13583941Svenki 		return;
13593941Svenki 	log_printf("\nVoltage indicators:\n");
13603941Svenki 	if (syserrlog == 0) {
13613941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1362*4669Sfw157321 		    PICL_CLASS_VOLTAGE_INDICATOR, NULL,
1363*4669Sfw157321 		    sun4v_env_print_indicator_callback);
13643941Svenki 		if (all_status_ok) {
13653941Svenki 			log_printf("All voltage indicators are OK.\n");
13663941Svenki 			return;
13673941Svenki 		}
13683941Svenki 	}
1369*4669Sfw157321 	log_printf("---------------------------------------------\n");
13703941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
1371*4669Sfw157321 	log_printf("---------------------------------------------\n");
13723941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1373*4669Sfw157321 	    PICL_CLASS_VOLTAGE_INDICATOR,
1374*4669Sfw157321 	    (void *)PICL_PROP_CONDITION,
1375*4669Sfw157321 	    sun4v_env_print_indicator_callback);
13763941Svenki }
13773941Svenki 
13783941Svenki static void
13793941Svenki sun4v_env_print_LEDs()
13803941Svenki {
1381*4669Sfw157321 	char *fmt = "%-20s %-14s %-8s\n";
13823941Svenki 	if (syserrlog == 0)
13833941Svenki 		return;
13843941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
1385*4669Sfw157321 	    (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
13863941Svenki 	if (!class_node_found)
13873941Svenki 		return;
13883941Svenki 	log_printf("\nLEDs:\n");
1389*4669Sfw157321 	log_printf("-----------------------------------------\n");
13903941Svenki 	log_printf(fmt, "Location", "LED", "State", 0);
1391*4669Sfw157321 	log_printf("-----------------------------------------\n");
13923941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
1393*4669Sfw157321 	    (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
13943941Svenki }
13953941Svenki 
13963941Svenki /*ARGSUSED*/
13973941Svenki static int
13983941Svenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args)
13993941Svenki {
14003941Svenki 	char label[PICL_PROPNAMELEN_MAX];
14013941Svenki 	char status[PICL_PROPNAMELEN_MAX];
14023941Svenki 	picl_errno_t err;
14033941Svenki 	picl_prophdl_t proph;
14043941Svenki 	picl_nodehdl_t parenth;
14053941Svenki 	char *names[PARENT_NAMES];
14063941Svenki 	char *loc;
14073941Svenki 	int i;
14083941Svenki 
14093941Svenki 	if (!class_node_found) {
14103941Svenki 		class_node_found = 1;
14113941Svenki 		return (PICL_WALK_TERMINATE);
14123941Svenki 	}
14133941Svenki 	err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph);
14143941Svenki 	if (err != PICL_SUCCESS)
14153941Svenki 		return (PICL_WALK_CONTINUE);
14163941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1417*4669Sfw157321 	    sizeof (label));
14183941Svenki 	if (err != PICL_SUCCESS)
14193941Svenki 		return (PICL_WALK_CONTINUE);
14203941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
1421*4669Sfw157321 	    status, sizeof (status));
14223941Svenki 	if (err != PICL_SUCCESS)
14233941Svenki 		return (PICL_WALK_CONTINUE);
14243941Svenki 	if (syserrlog == 0) {
14253941Svenki 		if (strcmp(status, "disabled") == 0) {
14263941Svenki 			if (all_status_ok) {
14273941Svenki 				all_status_ok = 0;
14283941Svenki 				return (PICL_WALK_TERMINATE);
14293941Svenki 			}
14303941Svenki 		} else
14313941Svenki 			return (PICL_WALK_CONTINUE);
14323941Svenki 	}
14333941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1434*4669Sfw157321 	    sizeof (parenth));
14353941Svenki 	if (err != PICL_SUCCESS) {
14363941Svenki 		log_printf("\n");
14373941Svenki 		return (PICL_WALK_CONTINUE);
14383941Svenki 	}
14393941Svenki 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
14403941Svenki 		return (PICL_WALK_TERMINATE);
14413941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
14423941Svenki 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
14433941Svenki 			while (--i > -1)
14443941Svenki 				free(names[i]);
14453941Svenki 			free(loc);
14463941Svenki 			return (PICL_WALK_TERMINATE);
14473941Svenki 		}
14483941Svenki 	i = 0;
14493941Svenki 	while (err == PICL_SUCCESS) {
14503941Svenki 		if (parenth == chassish || parenth == phyplatformh)
14513941Svenki 			break;
14523941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1453*4669Sfw157321 		    names[i++], PICL_PROPNAMELEN_MAX);
14543941Svenki 		if (err != PICL_SUCCESS) {
14553941Svenki 			i--;
14563941Svenki 			break;
14573941Svenki 		}
14583941Svenki 		if (i == PARENT_NAMES)
14593941Svenki 			break;
14603941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
1461*4669Sfw157321 		    &parenth, sizeof (parenth));
14623941Svenki 	}
14633941Svenki 	loc[0] = '\0';
14644003Svivek 	if (--i > -1) {
14654003Svivek 		(void) strlcat(loc, names[i],
1466*4669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
14674003Svivek 	}
14683941Svenki 	while (--i > -1) {
14694003Svivek 		(void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES);
14704003Svivek 		(void) strlcat(loc, names[i],
1471*4669Sfw157321 		    PICL_PROPNAMELEN_MAX * PARENT_NAMES);
14723941Svenki 	}
14733941Svenki 	log_printf("%-21s", loc);
14743941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
14753941Svenki 		free(names[i]);
14763941Svenki 	free(loc);
14773941Svenki 	log_printf("%-10s", label);
14783941Svenki 	log_printf("%-9s", status);
14793941Svenki 	log_printf("\n");
14803941Svenki 	return (PICL_WALK_CONTINUE);
14813941Svenki }
14823941Svenki 
14833941Svenki static void
14843941Svenki sun4v_print_fru_status()
14853941Svenki {
14863941Svenki 	char *fmt = "%-20s %-9s %-8s\n";
14873941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1488*4669Sfw157321 	    sun4v_print_fru_status_callback);
14893941Svenki 	if (!class_node_found)
14903941Svenki 		return;
14913941Svenki 	log_printf("\n");
14923941Svenki 	log_printf("============================");
14933941Svenki 	log_printf(" FRU Status ");
14943941Svenki 	log_printf("============================");
14953941Svenki 	log_printf("\n");
14963941Svenki 
14973941Svenki 	if (syserrlog == 0) {
14983941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1499*4669Sfw157321 		    PICL_CLASS_MODULE, NULL,
1500*4669Sfw157321 		    sun4v_print_fru_status_callback);
15013941Svenki 		if (all_status_ok) {
15023941Svenki 			log_printf("All FRUs are enabled.\n");
15033941Svenki 			return;
15043941Svenki 		}
15053941Svenki 	}
15063941Svenki 	log_printf(fmt, "Location", "Name", "Status", 0);
1507*4669Sfw157321 	log_printf("----------------------------------------\n");
15083941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_MODULE, NULL,
1509*4669Sfw157321 	    sun4v_print_fru_status_callback);
15103941Svenki }
15113941Svenki 
15123941Svenki /*ARGSUSED*/
15133941Svenki static int
15143941Svenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args)
15153941Svenki {
15163941Svenki 	char label[PICL_PROPNAMELEN_MAX];
15173941Svenki 	char rev[PICL_PROPNAMELEN_MAX];
15183941Svenki 	picl_errno_t err;
15193941Svenki 
15203941Svenki 	if (!class_node_found) {
15213941Svenki 		class_node_found = 1;
15223941Svenki 		return (PICL_WALK_TERMINATE);
15233941Svenki 	}
15243941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1525*4669Sfw157321 	    sizeof (label));
15263941Svenki 	if (err != PICL_SUCCESS)
15273941Svenki 		return (PICL_WALK_CONTINUE);
15283941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev,
1529*4669Sfw157321 	    sizeof (rev));
15303941Svenki 	if (err != PICL_SUCCESS)
15313941Svenki 		return (PICL_WALK_CONTINUE);
15323941Svenki 	if (strlen(rev) == 0)
15333941Svenki 		return (PICL_WALK_CONTINUE);
15343941Svenki 	log_printf("%-21s", label);
15353941Svenki 	log_printf("%-40s", rev);
15363941Svenki 	log_printf("\n");
15373941Svenki 	return (PICL_WALK_CONTINUE);
15383941Svenki }
15393941Svenki 
15403941Svenki static void
15413941Svenki sun4v_print_fw_rev()
15423941Svenki {
15433941Svenki 	char *fmt = "%-20s %-10s\n";
15443941Svenki 	if (syserrlog == 0)
15453941Svenki 		return;
15463941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1547*4669Sfw157321 	    sun4v_print_fw_rev_callback);
15483941Svenki 	if (!class_node_found)
15493941Svenki 		return;
15503941Svenki 	log_printf("\n");
15513941Svenki 	log_printf("============================");
15523941Svenki 	log_printf(" FW Version ");
15533941Svenki 	log_printf("============================");
15543941Svenki 	log_printf("\n");
15553941Svenki 	log_printf(fmt, "Name", "Version", 0);
15563941Svenki 	log_printf("----------------------------\n");
15573941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1558*4669Sfw157321 	    sun4v_print_fw_rev_callback);
15593941Svenki }
15603941Svenki 
15613941Svenki static void
15623941Svenki sun4v_print_chassis_serial_no()
15633941Svenki {
15643941Svenki 	char val[PICL_PROPNAMELEN_MAX];
15653941Svenki 	picl_errno_t err;
15663941Svenki 	if (syserrlog == 0 || chassish == 0)
15673941Svenki 		return;
15683941Svenki 
15693941Svenki 	log_printf("\n");
15703941Svenki 	log_printf("Chassis Serial Number");
15713941Svenki 	log_printf("\n");
15723941Svenki 	log_printf("---------------------\n");
15733941Svenki 	err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER,
1574*4669Sfw157321 	    val, sizeof (val));
15753941Svenki 	if (err == PICL_SUCCESS)
15763941Svenki 		log_printf("%s", val);
15773941Svenki 	log_printf("\n");
15783941Svenki }
1579