xref: /onnv-gate/usr/src/lib/libprtdiag/common/display_sun4v.c (revision 3941:328be6a20f20)
11708Sstevel /*
21708Sstevel  * CDDL HEADER START
31708Sstevel  *
41708Sstevel  * The contents of this file are subject to the terms of the
5*3941Svenki  * Common Development and Distribution License (the "License").
6*3941Svenki  * You may not use this file except in compliance with the License.
71708Sstevel  *
81708Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel  * or http://www.opensolaris.org/os/licensing.
101708Sstevel  * See the License for the specific language governing permissions
111708Sstevel  * and limitations under the License.
121708Sstevel  *
131708Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel  * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel  *
191708Sstevel  * CDDL HEADER END
201708Sstevel  */
211708Sstevel /*
22*3941Svenki  * 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>
46*3941Svenki #include <sys/systeminfo.h>
47*3941Svenki #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*3941Svenki #define	IOBOARD				"IOBD"
58*3941Svenki #define	NETWORK				"network"
59*3941Svenki #define	PCIE_COMPATIBLE_STR		"pciex"
60*3941Svenki #define	PCIX_COMPATIBLE_STR		"pci"
61*3941Svenki #define	SUN4V_MACHINE			"sun4v"
62*3941Svenki #define	PARENT_NAMES			10
63*3941Svenki 
64*3941Svenki /*
65*3941Svenki  * Additional OBP properties
66*3941Svenki  */
67*3941Svenki #define	OBP_PROP_COMPATIBLE		"compatible"
68*3941Svenki #define	OBP_PROP_MODEL			"model"
69*3941Svenki #define	OBP_PROP_SLOT_NAMES		"slot-names"
70*3941Svenki 
71*3941Svenki #define	PICL_NODE_PHYSICAL_PLATFORM	"physical-platform"
72*3941Svenki #define	PICL_NODE_CHASSIS		"chassis"
73*3941Svenki #define	MEMORY_SIZE_FIELD		11
74*3941Svenki #define	INVALID_THRESHOLD		1000000
75*3941Svenki 
76*3941Svenki /*
77*3941Svenki  * Additional picl classes
78*3941Svenki  */
79*3941Svenki #ifndef	PICL_CLASS_SUN4V
80*3941Svenki #define	PICL_CLASS_SUN4V		"sun4v"
81*3941Svenki #endif
82*3941Svenki 
83*3941Svenki #ifndef	PICL_PROP_NAC
84*3941Svenki #define	PICL_PROP_NAC			"nac"
85*3941Svenki #endif
86*3941Svenki 
87*3941Svenki extern int sys_clk;
88*3941Svenki extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *,
89*3941Svenki 	picl_nodehdl_t *);
90*3941Svenki 
91*3941Svenki static picl_nodehdl_t rooth = 0, phyplatformh = 0;
92*3941Svenki static picl_nodehdl_t chassish = 0;
93*3941Svenki static int class_node_found;
94*3941Svenki static int syserrlog;
95*3941Svenki static int all_status_ok;
96*3941Svenki 
97*3941Svenki /* local functions */
98*3941Svenki static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **);
99*3941Svenki static void sun4v_display_memory_conf(picl_nodehdl_t);
100*3941Svenki static void sun4v_disp_env_status();
101*3941Svenki static void sun4v_env_print_fan_sensors();
102*3941Svenki static void sun4v_env_print_fan_indicators();
103*3941Svenki static void sun4v_env_print_temp_sensors();
104*3941Svenki static void sun4v_env_print_temp_indicators();
105*3941Svenki static void sun4v_env_print_current_sensors();
106*3941Svenki static void sun4v_env_print_current_indicators();
107*3941Svenki static void sun4v_env_print_voltage_sensors();
108*3941Svenki static void sun4v_env_print_voltage_indicators();
109*3941Svenki static void sun4v_env_print_LEDs();
110*3941Svenki static void sun4v_print_fru_status();
111*3941Svenki static void sun4v_print_fw_rev();
112*3941Svenki static void sun4v_print_chassis_serial_no();
1131708Sstevel 
1141708Sstevel int
115*3941Svenki sun4v_display(Sys_tree *tree, Prom_node *root, int log,
116*3941Svenki 	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 */
121*3941Svenki 	char machine[MAXSTRLEN];
122*3941Svenki 
123*3941Svenki 	if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1)
124*3941Svenki 		return (1);
125*3941Svenki 	if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0)
126*3941Svenki 		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 
142*3941Svenki 		log_printf(dgettext(TEXT_DOMAIN, "System Configuration:  "
143*3941Svenki 			"Sun Microsystems  %s %s\n"), uts_buf.machine,
144*3941Svenki 			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 "
1511708Sstevel 				"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 */
161*3941Svenki 		class_node_found = 0;
162*3941Svenki 		sun4v_display_memory_conf(plafh);
1631708Sstevel 
1641708Sstevel 		/* Display all the IO cards. */
1651708Sstevel 		(void) sun4v_display_pci(plafh);
166*3941Svenki 		sun4v_display_diaginfo((log || (logging)), root, plafh);
1671708Sstevel 
168*3941Svenki 		if (picl_get_root(&rooth) != PICL_SUCCESS)
169*3941Svenki 			return (1);
170*3941Svenki 		if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM,
171*3941Svenki 			&phyplatformh) != PICL_SUCCESS)
172*3941Svenki 			return (1);
173*3941Svenki 
174*3941Svenki 		if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME,
175*3941Svenki 			PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
176*3941Svenki 			strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS)
177*3941Svenki 			return (1);
178*3941Svenki 
179*3941Svenki 		syserrlog = log;
180*3941Svenki 		sun4v_disp_env_status();
181*3941Svenki 	}
182*3941Svenki 	return (0);
183*3941Svenki }
184*3941Svenki 
185*3941Svenki static void
186*3941Svenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card)
187*3941Svenki {
188*3941Svenki 	char *compatible;
189*3941Svenki 
190*3941Svenki 	(void) strcpy(card->bus_type, "PCIX");
191*3941Svenki 	if (sun4v_get_first_compatible_value(nodeh, &compatible)
192*3941Svenki 		== PICL_SUCCESS) {
193*3941Svenki 		if (strncmp(compatible, PCIE_COMPATIBLE_STR,
194*3941Svenki 			strlen(PCIE_COMPATIBLE_STR)) == 0)
195*3941Svenki 			(void) strcpy(card->bus_type, "PCIE");
196*3941Svenki 		free(compatible);
197*3941Svenki 	}
198*3941Svenki }
199*3941Svenki 
200*3941Svenki static picl_errno_t
201*3941Svenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card)
202*3941Svenki {
203*3941Svenki 	char val[PICL_PROPNAMELEN_MAX];
204*3941Svenki 	picl_errno_t err;
205*3941Svenki 
206*3941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
207*3941Svenki 		sizeof (val));
208*3941Svenki 	if (err != PICL_SUCCESS)
209*3941Svenki 		return (err);
210*3941Svenki 
211*3941Svenki 	(void) strcpy(card->slot_str, val);
212*3941Svenki 	card->slot = -1;
213*3941Svenki 	return (PICL_SUCCESS);
214*3941Svenki }
215*3941Svenki 
216*3941Svenki static void
217*3941Svenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card)
218*3941Svenki {
219*3941Svenki 	picl_errno_t err;
220*3941Svenki 	picl_prophdl_t proph;
221*3941Svenki 	picl_propinfo_t pinfo;
222*3941Svenki 	picl_nodehdl_t pnodeh;
223*3941Svenki 	uint8_t *pval;
224*3941Svenki 	uint32_t dev_mask;
225*3941Svenki 	char uaddr[MAXSTRLEN];
226*3941Svenki 	int i;
227*3941Svenki 
228*3941Svenki 	if (get_slot_label(nodeh, card) == PICL_SUCCESS)
229*3941Svenki 		return;
230*3941Svenki 	err = PICL_SUCCESS;
231*3941Svenki 	while (err == PICL_SUCCESS) {
232*3941Svenki 		if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
233*3941Svenki 			sizeof (pnodeh)) != PICL_SUCCESS) {
234*3941Svenki 			(void) strcpy(card->slot_str, IOBOARD);
235*3941Svenki 			card->slot = -1;
236*3941Svenki 			return;
237*3941Svenki 		}
238*3941Svenki 		if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES,
239*3941Svenki 			&pinfo, &proph) == PICL_SUCCESS) {
240*3941Svenki 			break;
241*3941Svenki 		}
242*3941Svenki 		nodeh = pnodeh;
243*3941Svenki 	}
244*3941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr,
245*3941Svenki 		sizeof (uaddr)) != PICL_SUCCESS) {
246*3941Svenki 		(void) strcpy(card->slot_str, IOBOARD);
247*3941Svenki 		card->slot = -1;
248*3941Svenki 		return;
249*3941Svenki 	}
250*3941Svenki 	pval = (uint8_t *)malloc(pinfo.size);
251*3941Svenki 	if (!pval) {
252*3941Svenki 		(void) strcpy(card->slot_str, IOBOARD);
253*3941Svenki 		card->slot = -1;
254*3941Svenki 		return;
255*3941Svenki 	}
256*3941Svenki 	if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) {
257*3941Svenki 		(void) strcpy(card->slot_str, IOBOARD);
258*3941Svenki 		card->slot = -1;
259*3941Svenki 		free(pval);
260*3941Svenki 		return;
2611708Sstevel 	}
2621708Sstevel 
263*3941Svenki 	dev_mask = 0;
264*3941Svenki 	for (i = 0; i < sizeof (dev_mask); i++)
265*3941Svenki 		dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i));
266*3941Svenki 	for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) {
267*3941Svenki 		if (uaddr[i] == ',') {
268*3941Svenki 			uaddr[i] = '\0';
269*3941Svenki 			break;
270*3941Svenki 		}
271*3941Svenki 	}
272*3941Svenki 	card->slot = atol(uaddr);
273*3941Svenki 	if (((1 << card->slot) & dev_mask) == 0) {
274*3941Svenki 		(void) strcpy(card->slot_str, IOBOARD);
275*3941Svenki 		card->slot = -1;
276*3941Svenki 	} else {
277*3941Svenki 		char *p = (char *)(pval+sizeof (dev_mask));
278*3941Svenki 		int shift = sizeof (uint32_t)*8-1-card->slot;
279*3941Svenki 		uint32_t x = (dev_mask << shift) >> shift;
280*3941Svenki 		int count = 0;	/* count # of 1's in x */
281*3941Svenki 		int i = 0;
282*3941Svenki 		while (x != 0) {
283*3941Svenki 			count++;
284*3941Svenki 			x &= x-1;
285*3941Svenki 		}
286*3941Svenki 		while (count > 1) {
287*3941Svenki 			while (p[i++] != '\0');
288*3941Svenki 			count--;
289*3941Svenki 		}
290*3941Svenki 		(void) strcpy(card->slot_str, (char *)(p+i));
291*3941Svenki 	}
292*3941Svenki 	free(pval);
293*3941Svenki }
294*3941Svenki 
295*3941Svenki /*
296*3941Svenki  * add all io devices under pci in io list
297*3941Svenki  */
298*3941Svenki /* ARGSUSED */
299*3941Svenki static int
300*3941Svenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args)
301*3941Svenki {
302*3941Svenki 	char path[PICL_PROPNAMELEN_MAX];
303*3941Svenki 	char class[PICL_CLASSNAMELEN_MAX];
304*3941Svenki 	char name[PICL_PROPNAMELEN_MAX];
305*3941Svenki 	char model[PICL_PROPNAMELEN_MAX];
306*3941Svenki 	char binding_name[PICL_PROPNAMELEN_MAX];
307*3941Svenki 	char val[PICL_PROPNAMELEN_MAX];
308*3941Svenki 	char *compatible;
309*3941Svenki 	picl_errno_t err;
310*3941Svenki 	picl_nodehdl_t nodeh;
311*3941Svenki 	struct io_card pci_card;
312*3941Svenki 
313*3941Svenki 	/* Walk through the children */
314*3941Svenki 
315*3941Svenki 	err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
316*3941Svenki 		sizeof (picl_nodehdl_t));
317*3941Svenki 
318*3941Svenki 	while (err == PICL_SUCCESS) {
319*3941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
320*3941Svenki 			class, sizeof (class));
321*3941Svenki 		if (err !=  PICL_SUCCESS)
322*3941Svenki 			return (err);
323*3941Svenki 
324*3941Svenki 		if (args) {
325*3941Svenki 			char *val = args;
326*3941Svenki 			if (strcmp(class, val) == 0) {
327*3941Svenki 				err = picl_get_propval_by_name(nodeh,
328*3941Svenki 					PICL_PROP_PEER, &nodeh,
329*3941Svenki 					sizeof (picl_nodehdl_t));
330*3941Svenki 				continue;
331*3941Svenki 			} else if (strcmp(val, PICL_CLASS_PCIEX) == 0 &&
332*3941Svenki 				strcmp(class, PICL_CLASS_PCI) == 0) {
333*3941Svenki 				err = picl_get_propval_by_name(nodeh,
334*3941Svenki 					PICL_PROP_PEER, &nodeh,
335*3941Svenki 					sizeof (picl_nodehdl_t));
336*3941Svenki 				continue;
337*3941Svenki 			} else if (strcmp(val, PICL_CLASS_PCI) == 0 &&
338*3941Svenki 				strcmp(class, PICL_CLASS_PCIEX) == 0) {
339*3941Svenki 				err = picl_get_propval_by_name(nodeh,
340*3941Svenki 					PICL_PROP_PEER, &nodeh,
341*3941Svenki 					sizeof (picl_nodehdl_t));
342*3941Svenki 				continue;
343*3941Svenki 			}
344*3941Svenki 		}
345*3941Svenki 
346*3941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
347*3941Svenki 			path, sizeof (path));
348*3941Svenki 		if (err != PICL_SUCCESS)
349*3941Svenki 			return (err);
350*3941Svenki 
351*3941Svenki 		(void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
352*3941Svenki 
353*3941Svenki 		get_bus_type(nodeh, &pci_card);
354*3941Svenki 		get_slot_number(nodeh, &pci_card);
355*3941Svenki 
356*3941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name,
357*3941Svenki 			sizeof (name));
358*3941Svenki 		if (err == PICL_PROPNOTFOUND)
359*3941Svenki 			(void) strcpy(name, "");
360*3941Svenki 		else if (err != PICL_SUCCESS)
361*3941Svenki 			return (err);
362*3941Svenki 
363*3941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val,
364*3941Svenki 			sizeof (val));
365*3941Svenki 		if (err == PICL_PROPNOTFOUND)
366*3941Svenki 			(void) strcpy(val, "");
367*3941Svenki 		else if (err != PICL_SUCCESS)
368*3941Svenki 			return (err);
369*3941Svenki 
370*3941Svenki 		/* Figure NAC name */
371*3941Svenki 		if (pci_card.slot != -1)
372*3941Svenki 			(void) snprintf(pci_card.status,
373*3941Svenki 					sizeof (pci_card.status),
374*3941Svenki 					"%s%d", pci_card.slot_str,
375*3941Svenki 					pci_card.slot);
376*3941Svenki 		else
377*3941Svenki 			(void) snprintf(pci_card.status,
378*3941Svenki 					sizeof (pci_card.status),
379*3941Svenki 					"%s", pci_card.slot_str);
380*3941Svenki 
381*3941Svenki 		/*
382*3941Svenki 		 * Get the name of this card. If binding_name is found,
383*3941Svenki 		 * name will be <nodename>-<binding_name>.
384*3941Svenki 		 */
385*3941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
386*3941Svenki 			binding_name, sizeof (binding_name));
387*3941Svenki 		if (err == PICL_SUCCESS) {
388*3941Svenki 			if (strcmp(name, binding_name) != 0) {
389*3941Svenki 				(void) strlcat(name, "-", sizeof (name));
390*3941Svenki 				(void) strlcat(name, binding_name,
391*3941Svenki 					sizeof (name));
392*3941Svenki 			}
393*3941Svenki 		} else if (err == PICL_PROPNOTFOUND) {
394*3941Svenki 			/*
395*3941Svenki 			 * if compatible prop is not found, name will be
396*3941Svenki 			 * <nodename>-<compatible>
397*3941Svenki 			 */
398*3941Svenki 			err = sun4v_get_first_compatible_value(nodeh,
399*3941Svenki 				&compatible);
400*3941Svenki 			if (err == PICL_SUCCESS) {
401*3941Svenki 				(void) strlcat(name, "-", sizeof (name));
402*3941Svenki 				(void) strlcat(name, compatible, sizeof (name));
403*3941Svenki 				free(compatible);
404*3941Svenki 			}
405*3941Svenki 		} else
406*3941Svenki 			return (err);
407*3941Svenki 
408*3941Svenki 		(void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
409*3941Svenki 
410*3941Svenki 		/* Get the model of this card */
411*3941Svenki 
412*3941Svenki 		err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
413*3941Svenki 			model, sizeof (model));
414*3941Svenki 		if (err == PICL_PROPNOTFOUND)
415*3941Svenki 			(void) strcpy(model, "");
416*3941Svenki 		else if (err != PICL_SUCCESS)
417*3941Svenki 			return (err);
418*3941Svenki 		(void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
419*3941Svenki 
420*3941Svenki 		/* Print NAC name */
421*3941Svenki 		log_printf("%-12s", pci_card.status);
422*3941Svenki 		/* Print IO Type */
423*3941Svenki 		log_printf("%-6s", pci_card.bus_type);
424*3941Svenki 		/* Printf Card Name */
425*3941Svenki 		log_printf("%-46s", pci_card.name);
426*3941Svenki 		/* Print Card Model */
427*3941Svenki 		log_printf("%-8s", pci_card.model);
428*3941Svenki 		log_printf("\n");
429*3941Svenki 		/* Print Status */
430*3941Svenki 		log_printf("%-12s", val);
431*3941Svenki 		/* Print IO Type */
432*3941Svenki 		log_printf("%-6s", "");
433*3941Svenki 		/* Print Parent Path */
434*3941Svenki 		log_printf("%-46s", pci_card.notes);
435*3941Svenki 		log_printf("\n");
436*3941Svenki 
437*3941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
438*3941Svenki 			sizeof (picl_nodehdl_t));
439*3941Svenki 	}
440*3941Svenki 	return (PICL_WALK_CONTINUE);
4411708Sstevel }
4421708Sstevel 
4431708Sstevel /*
4441708Sstevel  * display_pci
4451708Sstevel  * Display all the PCI IO cards on this board.
4461708Sstevel  */
4471708Sstevel void
4481708Sstevel sun4v_display_pci(picl_nodehdl_t plafh)
4491708Sstevel {
450*3941Svenki 	char *fmt = "%-11s %-5s %-45s %-8s";
451*3941Svenki 	/* Have we printed the column headings? */
452*3941Svenki 	static int banner = FALSE;
453*3941Svenki 
454*3941Svenki 	if (banner == FALSE) {
455*3941Svenki 		log_printf("\n");
456*3941Svenki 		log_printf("============================");
457*3941Svenki 		log_printf(" IO Devices ");
458*3941Svenki 		log_printf("============================");
459*3941Svenki 		log_printf("\n");
460*3941Svenki 		log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0);
461*3941Svenki 		log_printf("\n");
462*3941Svenki 		log_printf(fmt, "Status", "Type", "Path", "", 0);
463*3941Svenki 		log_printf("\n");
464*3941Svenki 		log_printf("---------------------------------"
465*3941Svenki 			"------------------------------------\n");
466*3941Svenki 		banner = TRUE;
467*3941Svenki 	}
468*3941Svenki 
469*3941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
470*3941Svenki 		PICL_CLASS_PCIEX, sun4v_pci_callback);
471*3941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
472*3941Svenki 		PICL_CLASS_PCI, sun4v_pci_callback);
473*3941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V,
474*3941Svenki 		PICL_CLASS_SUN4V, sun4v_pci_callback);
475*3941Svenki }
476*3941Svenki 
477*3941Svenki /*
478*3941Svenki  * return the first compatible value
479*3941Svenki  */
480*3941Svenki static int
481*3941Svenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
482*3941Svenki {
483*3941Svenki 	picl_errno_t err;
484*3941Svenki 	picl_prophdl_t proph;
485*3941Svenki 	picl_propinfo_t pinfo;
486*3941Svenki 	picl_prophdl_t tblh;
487*3941Svenki 	picl_prophdl_t rowproph;
488*3941Svenki 	char *pval;
489*3941Svenki 
490*3941Svenki 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
491*3941Svenki 		&pinfo, &proph);
492*3941Svenki 	if (err != PICL_SUCCESS)
493*3941Svenki 		return (err);
494*3941Svenki 
495*3941Svenki 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
496*3941Svenki 		pval = malloc(pinfo.size);
497*3941Svenki 		if (pval == NULL)
498*3941Svenki 			return (PICL_FAILURE);
499*3941Svenki 		err = picl_get_propval(proph, pval, pinfo.size);
500*3941Svenki 		if (err != PICL_SUCCESS) {
501*3941Svenki 			free(pval);
502*3941Svenki 			return (err);
503*3941Svenki 		}
504*3941Svenki 		*outbuf = pval;
505*3941Svenki 		return (PICL_SUCCESS);
506*3941Svenki 	}
507*3941Svenki 
508*3941Svenki 	if (pinfo.type != PICL_PTYPE_TABLE)
509*3941Svenki 		return (PICL_FAILURE);
510*3941Svenki 
511*3941Svenki 	/* get first string from table */
512*3941Svenki 	err = picl_get_propval(proph, &tblh, pinfo.size);
513*3941Svenki 	if (err != PICL_SUCCESS)
514*3941Svenki 		return (err);
515*3941Svenki 
516*3941Svenki 	err = picl_get_next_by_row(tblh, &rowproph);
517*3941Svenki 	if (err != PICL_SUCCESS)
518*3941Svenki 		return (err);
519*3941Svenki 
520*3941Svenki 	err = picl_get_propinfo(rowproph, &pinfo);
521*3941Svenki 	if (err != PICL_SUCCESS)
522*3941Svenki 		return (err);
523*3941Svenki 
524*3941Svenki 	pval = malloc(pinfo.size);
525*3941Svenki 	if (pval == NULL)
526*3941Svenki 		return (PICL_FAILURE);
527*3941Svenki 
528*3941Svenki 	err = picl_get_propval(rowproph, pval, pinfo.size);
529*3941Svenki 	if (err != PICL_SUCCESS) {
530*3941Svenki 		free(pval);
531*3941Svenki 		return (err);
532*3941Svenki 	}
533*3941Svenki 
534*3941Svenki 	*outbuf = pval;
535*3941Svenki 	return (PICL_SUCCESS);
5361708Sstevel }
5371708Sstevel 
538*3941Svenki /*
539*3941Svenki  * print size of a memory segment
540*3941Svenki  */
541*3941Svenki static void
542*3941Svenki print_memory_segment_size(uint64_t size)
543*3941Svenki {
544*3941Svenki 	uint64_t kbyte = 1024;
545*3941Svenki 	uint64_t mbyte = kbyte * kbyte;
546*3941Svenki 	uint64_t gbyte = kbyte * mbyte;
547*3941Svenki 	char buf[MEMORY_SIZE_FIELD];
548*3941Svenki 
549*3941Svenki 	if (size >= gbyte) {
550*3941Svenki 		if (size % gbyte == 0)
551*3941Svenki 			(void) snprintf(buf, sizeof (buf), "%d GB",
552*3941Svenki 				(int)(size / gbyte));
553*3941Svenki 		else
554*3941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f GB",
555*3941Svenki 				(float)size / gbyte);
556*3941Svenki 	} else if (size >= mbyte) {
557*3941Svenki 		if (size % mbyte == 0)
558*3941Svenki 			(void) snprintf(buf, sizeof (buf), "%d MB",
559*3941Svenki 				(int)(size / mbyte));
560*3941Svenki 		else
561*3941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f MB",
562*3941Svenki 				(float)size / mbyte);
563*3941Svenki 	} else {
564*3941Svenki 		if (size % kbyte == 0)
565*3941Svenki 			(void) snprintf(buf, sizeof (buf), "%d KB",
566*3941Svenki 				(int)(size / kbyte));
567*3941Svenki 		else
568*3941Svenki 			(void) snprintf(buf, sizeof (buf), "%.2f KB",
569*3941Svenki 				(float)size / kbyte);
570*3941Svenki 	}
571*3941Svenki 	log_printf("%-7s ", buf);
572*3941Svenki }
573*3941Svenki 
574*3941Svenki /*
575*3941Svenki  * print bank IDs of a memory segment
576*3941Svenki  */
577*3941Svenki static void
578*3941Svenki print_memory_segment_contain(picl_nodehdl_t nodeh)
5791708Sstevel {
580*3941Svenki 	char val[PICL_PROPNAMELEN_MAX];
581*3941Svenki 	picl_errno_t err = picl_get_propval_by_name(nodeh,
582*3941Svenki 		PICL_PROP_NAC, val, sizeof (val));
583*3941Svenki 	if (err != PICL_SUCCESS)
584*3941Svenki 		return;
585*3941Svenki 	log_printf("%-30s", val);
586*3941Svenki 	while ((err = picl_get_propval_by_name(nodeh,
587*3941Svenki 			PICL_PROP_PEER, &nodeh,
588*3941Svenki 			sizeof (nodeh))) == PICL_SUCCESS) {
589*3941Svenki 		err = picl_get_propval_by_name(nodeh,
590*3941Svenki 			PICL_PROP_NAC, val, sizeof (val));
591*3941Svenki 		if (err == PICL_SUCCESS) {
592*3941Svenki 			log_printf("\n");
593*3941Svenki 			log_printf("%-30s", val);
594*3941Svenki 		}
595*3941Svenki 	}
596*3941Svenki }
597*3941Svenki 
598*3941Svenki /*
599*3941Svenki  * Search node where _class=="memory-segment"
600*3941Svenki  * print "Base Address", "Size", etc
601*3941Svenki  */
602*3941Svenki /*ARGSUSED*/
603*3941Svenki static int
604*3941Svenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args)
605*3941Svenki {
606*3941Svenki 	uint64_t base;
607*3941Svenki 	uint64_t size;
608*3941Svenki 	uint64_t ifactor;
609*3941Svenki 	picl_errno_t err = PICL_SUCCESS;
610*3941Svenki 
611*3941Svenki 	if (class_node_found == 0) {
612*3941Svenki 		class_node_found = 1;
613*3941Svenki 		return (PICL_WALK_TERMINATE);
614*3941Svenki 	}
615*3941Svenki 	while (err == PICL_SUCCESS) {
616*3941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS,
617*3941Svenki 			&base, sizeof (base));
618*3941Svenki 		if (err !=  PICL_SUCCESS)
619*3941Svenki 			break;
620*3941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE,
621*3941Svenki 			&size, sizeof (size));
622*3941Svenki 		if (err !=  PICL_SUCCESS)
623*3941Svenki 			break;
624*3941Svenki 		err = picl_get_propval_by_name(nodeh,
625*3941Svenki 			PICL_PROP_INTERLEAVE_FACTOR, &ifactor,
626*3941Svenki 			sizeof (ifactor));
627*3941Svenki 		if (err !=  PICL_SUCCESS)
628*3941Svenki 			break;
629*3941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
630*3941Svenki 			&nodeh, sizeof (nodeh));
631*3941Svenki 		if (err !=  PICL_SUCCESS)
632*3941Svenki 			break;
633*3941Svenki 		log_printf("%-13llx", base);
634*3941Svenki 		print_memory_segment_size(size);
635*3941Svenki 		log_printf("%-18d", ifactor);
636*3941Svenki 		print_memory_segment_contain(nodeh);
637*3941Svenki 		log_printf("\n");
638*3941Svenki 		err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
639*3941Svenki 			sizeof (picl_nodehdl_t));
640*3941Svenki 	}
641*3941Svenki 
642*3941Svenki 	return (PICL_WALK_CONTINUE);
643*3941Svenki }
644*3941Svenki 
645*3941Svenki /*ARGSUSED*/
646*3941Svenki void
647*3941Svenki sun4v_display_memory_conf(picl_nodehdl_t plafh)
648*3941Svenki {
649*3941Svenki 	char *fmt = "%-12s %-7s %-9s %-20s";
650*3941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
651*3941Svenki 		NULL, sun4v_memory_conf_callback);
652*3941Svenki 	if (class_node_found == 0)
653*3941Svenki 		return;
654*3941Svenki 	log_printf("\n");
655*3941Svenki 	log_printf("============================");
656*3941Svenki 	log_printf(" Memory Configuration ");
657*3941Svenki 	log_printf("============================");
658*3941Svenki 	log_printf("\n");
659*3941Svenki 	log_printf("Segment Table:\n");
660*3941Svenki 	log_printf("-----------------------------------------------\n");
661*3941Svenki 	log_printf(fmt, "Base Address", "Size", "Interleave Factor",
662*3941Svenki 		"Contains", 0);
663*3941Svenki 	log_printf("\n");
664*3941Svenki 	log_printf("-----------------------------------------------\n");
665*3941Svenki 	(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
666*3941Svenki 		NULL, sun4v_memory_conf_callback);
6671708Sstevel }
6681708Sstevel 
6691708Sstevel void
6701708Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh)
6711708Sstevel {
672*3941Svenki 	char *fmt = "%-12s %-5s %-8s %-19s %-5s";
6731708Sstevel 
6741708Sstevel 	/*
6751708Sstevel 	 * Display the table header for CPUs . Then display the CPU
6761708Sstevel 	 * frequency, cache size, and processor revision of all cpus.
6771708Sstevel 	 */
6781708Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
6791708Sstevel 		"\n"
6801708Sstevel 		"========================="
6811708Sstevel 		" CPUs "
6821708Sstevel 		"==============================================="
6831708Sstevel 		"\n"
6841708Sstevel 		"\n"));
6851708Sstevel 	log_printf(fmt, "", "", "", "CPU", "CPU", 0);
6861708Sstevel 	log_printf("\n");
6871708Sstevel 	log_printf(fmt, "Location", "CPU", "Freq",
688*3941Svenki 		"Implementation", "Mask", 0);
6891708Sstevel 	log_printf("\n");
6901708Sstevel 	log_printf(fmt, "------------", "-----", "--------",
691*3941Svenki 		"-------------------", "-----", 0);
6921708Sstevel 	log_printf("\n");
6931708Sstevel 
6941708Sstevel 	(void) picl_walk_tree_by_class(plafh, "cpu", "cpu", sun4v_display_cpus);
6951708Sstevel }
6961708Sstevel 
6971708Sstevel /*
6981708Sstevel  * Display the CPUs present on this board.
6991708Sstevel  */
7001708Sstevel /*ARGSUSED*/
7011708Sstevel int
7021708Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
7031708Sstevel {
7041708Sstevel 	int status;
705*3941Svenki 	picl_prophdl_t proph;
706*3941Svenki 	picl_prophdl_t tblh;
707*3941Svenki 	picl_prophdl_t rowproph;
7081708Sstevel 	picl_propinfo_t propinfo;
709*3941Svenki 	int *int_value;
710*3941Svenki 	uint64_t cpuid, mask_no;
711*3941Svenki 	char *comp_value;
712*3941Svenki 	char *no_prop_value = "   ";
713*3941Svenki 	char freq_str[MAXSTRLEN];
714*3941Svenki 	char fru_name[MAXSTRLEN];
7151708Sstevel 
7161708Sstevel 	/*
7171708Sstevel 	 * Get cpuid property and print it and the NAC name
7181708Sstevel 	 */
7191708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "cpuid", &propinfo, &proph);
7201708Sstevel 	if (status == PICL_SUCCESS) {
7211708Sstevel 		status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
7221708Sstevel 		if (status != PICL_SUCCESS) {
723*3941Svenki 			log_printf("%-13s", no_prop_value);
724*3941Svenki 			log_printf("%-6s", no_prop_value);
7251708Sstevel 		} else {
7261708Sstevel 			(void) snprintf(fru_name, sizeof (fru_name), "%s%d",
7271708Sstevel 			    CPU_STRAND_NAC, (int)cpuid);
728*3941Svenki 			log_printf("%-13s", fru_name);
729*3941Svenki 			log_printf("%-6d", (int)cpuid);
7301708Sstevel 		}
7311708Sstevel 	} else {
732*3941Svenki 		log_printf("%-13s", no_prop_value);
733*3941Svenki 		log_printf("%-6s", no_prop_value);
7341708Sstevel 	}
7351708Sstevel 
7361708Sstevel clock_freq:
7371708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
738*3941Svenki 		&proph);
7391708Sstevel 	if (status == PICL_SUCCESS) {
7401708Sstevel 		int_value = malloc(propinfo.size);
7411708Sstevel 		if (int_value == NULL) {
742*3941Svenki 			log_printf("%-9s", no_prop_value);
7431708Sstevel 			goto compatible;
7441708Sstevel 		}
7451708Sstevel 		status = picl_get_propval(proph, int_value, propinfo.size);
7461708Sstevel 		if (status != PICL_SUCCESS) {
747*3941Svenki 			log_printf("%-9s", no_prop_value);
7481708Sstevel 		} else {
7491708Sstevel 			/* Running frequency */
7501708Sstevel 			(void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
7511708Sstevel 			    CLK_FREQ_TO_MHZ(*int_value));
752*3941Svenki 			log_printf("%-9s", freq_str);
7531708Sstevel 		}
7541708Sstevel 		free(int_value);
7551708Sstevel 	} else
756*3941Svenki 		log_printf("%-9s", no_prop_value);
7571708Sstevel 
7581708Sstevel compatible:
7591708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
760*3941Svenki 		&proph);
7611708Sstevel 	if (status == PICL_SUCCESS) {
7621708Sstevel 		if (propinfo.type == PICL_PTYPE_CHARSTRING) {
7631708Sstevel 			/*
7641708Sstevel 			 * Compatible Property only has 1 value
7651708Sstevel 			 */
7661708Sstevel 			comp_value = malloc(propinfo.size);
7671708Sstevel 			if (comp_value == NULL) {
768*3941Svenki 				log_printf("%-20s", no_prop_value, 0);
7691708Sstevel 				goto mask;
7701708Sstevel 			}
7711708Sstevel 			status = picl_get_propval(proph, comp_value,
772*3941Svenki 				propinfo.size);
773*3941Svenki 			if (status != PICL_SUCCESS)
774*3941Svenki 				log_printf("%-20s", no_prop_value, 0);
775*3941Svenki 			else
776*3941Svenki 				log_printf("%-20s", comp_value, 0);
777*3941Svenki 			free(comp_value);
7781708Sstevel 		} else if (propinfo.type == PICL_PTYPE_TABLE) {
7791708Sstevel 			/*
7801708Sstevel 			 * Compatible Property has multiple values
7811708Sstevel 			 */
7821708Sstevel 			status = picl_get_propval(proph, &tblh, propinfo.size);
7831708Sstevel 			if (status != PICL_SUCCESS) {
784*3941Svenki 				log_printf("%-20s", no_prop_value, 0);
7851708Sstevel 				goto mask;
7861708Sstevel 			}
7871708Sstevel 			status = picl_get_next_by_row(tblh, &rowproph);
7881708Sstevel 			if (status != PICL_SUCCESS) {
789*3941Svenki 				log_printf("%-20s", no_prop_value, 0);
7901708Sstevel 				goto mask;
7911708Sstevel 			}
7921708Sstevel 
7931708Sstevel 			status = picl_get_propinfo(rowproph, &propinfo);
7941708Sstevel 			if (status != PICL_SUCCESS) {
795*3941Svenki 				log_printf("%-20s", no_prop_value, 0);
7961708Sstevel 				goto mask;
7971708Sstevel 			}
7981708Sstevel 
7991708Sstevel 			comp_value = malloc(propinfo.size);
8001708Sstevel 			if (comp_value == NULL) {
801*3941Svenki 				log_printf("%-20s", no_prop_value, 0);
8021708Sstevel 				goto mask;
8031708Sstevel 			}
8041708Sstevel 			status = picl_get_propval(rowproph, comp_value,
805*3941Svenki 				propinfo.size);
806*3941Svenki 			if (status != PICL_SUCCESS)
807*3941Svenki 				log_printf("%-20s", no_prop_value, 0);
808*3941Svenki 			else
809*3941Svenki 				log_printf("%-20s", comp_value, 0);
8101708Sstevel 			free(comp_value);
8111708Sstevel 		}
8121708Sstevel 	} else
813*3941Svenki 		log_printf("%-20s", no_prop_value, 0);
8141708Sstevel 
8151708Sstevel mask:
8161708Sstevel 	status = picl_get_propinfo_by_name(cpuh, "mask#", &propinfo, &proph);
8171708Sstevel 	if (status == PICL_SUCCESS) {
8181708Sstevel 		status = picl_get_propval(proph, &mask_no, sizeof (mask_no));
8191708Sstevel 		if (status != PICL_SUCCESS) {
820*3941Svenki 			log_printf("%-9s", no_prop_value);
8211708Sstevel 		} else {
8221708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, " %2d.%d"),
823*3941Svenki 				(mask_no>> 4) & 0xf, mask_no & 0xf);
8241708Sstevel 		}
8251708Sstevel 	} else
826*3941Svenki 		log_printf("%-9s", no_prop_value);
8271708Sstevel 
8281708Sstevel done:
8291708Sstevel 	log_printf("\n");
8301708Sstevel 	return (PICL_WALK_CONTINUE);
8311708Sstevel }
8321708Sstevel 
8331708Sstevel void
8341708Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
8351708Sstevel {
8361708Sstevel #ifdef	lint
8371708Sstevel 	flag = flag;
8381708Sstevel 	root = root;
8391708Sstevel 	plafh = plafh;
8401708Sstevel #endif
8411708Sstevel 	/*
8421708Sstevel 	 * This function is intentionally empty
8431708Sstevel 	 */
8441708Sstevel }
8451708Sstevel 
8461708Sstevel void
8471708Sstevel display_boardnum(int num)
8481708Sstevel {
8491708Sstevel 	log_printf("%2d   ", num, 0);
8501708Sstevel }
851*3941Svenki 
852*3941Svenki static void
853*3941Svenki sun4v_disp_env_status()
854*3941Svenki {
855*3941Svenki 	if (phyplatformh == 0)
856*3941Svenki 		return;
857*3941Svenki 	log_printf("\n");
858*3941Svenki 	log_printf("============================");
859*3941Svenki 	log_printf(" Environmental Status ");
860*3941Svenki 	log_printf("============================");
861*3941Svenki 	log_printf("\n");
862*3941Svenki 
863*3941Svenki 	class_node_found = 0;
864*3941Svenki 	all_status_ok = 1;
865*3941Svenki 	sun4v_env_print_fan_sensors();
866*3941Svenki 
867*3941Svenki 	class_node_found = 0;
868*3941Svenki 	all_status_ok = 1;
869*3941Svenki 	sun4v_env_print_fan_indicators();
870*3941Svenki 
871*3941Svenki 	class_node_found = 0;
872*3941Svenki 	all_status_ok = 1;
873*3941Svenki 	sun4v_env_print_temp_sensors();
874*3941Svenki 
875*3941Svenki 	class_node_found = 0;
876*3941Svenki 	all_status_ok = 1;
877*3941Svenki 	sun4v_env_print_temp_indicators();
878*3941Svenki 
879*3941Svenki 	class_node_found = 0;
880*3941Svenki 	all_status_ok = 1;
881*3941Svenki 	sun4v_env_print_current_sensors();
882*3941Svenki 
883*3941Svenki 	class_node_found = 0;
884*3941Svenki 	all_status_ok = 1;
885*3941Svenki 	sun4v_env_print_current_indicators();
886*3941Svenki 
887*3941Svenki 	class_node_found = 0;
888*3941Svenki 	all_status_ok = 1;
889*3941Svenki 	sun4v_env_print_voltage_sensors();
890*3941Svenki 
891*3941Svenki 	class_node_found = 0;
892*3941Svenki 	all_status_ok = 1;
893*3941Svenki 	sun4v_env_print_voltage_indicators();
894*3941Svenki 
895*3941Svenki 	class_node_found = 0;
896*3941Svenki 	sun4v_env_print_LEDs();
897*3941Svenki 
898*3941Svenki 	class_node_found = 0;
899*3941Svenki 	all_status_ok = 1;
900*3941Svenki 	sun4v_print_fru_status();
901*3941Svenki 
902*3941Svenki 	class_node_found = 0;
903*3941Svenki 	sun4v_print_fw_rev();
904*3941Svenki 
905*3941Svenki 	sun4v_print_chassis_serial_no();
906*3941Svenki }
907*3941Svenki 
908*3941Svenki /*ARGSUSED*/
909*3941Svenki static int
910*3941Svenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args)
911*3941Svenki {
912*3941Svenki 	char val[PICL_PROPNAMELEN_MAX];
913*3941Svenki 	picl_nodehdl_t parenth;
914*3941Svenki 	char *names[PARENT_NAMES];
915*3941Svenki 	char *loc;
916*3941Svenki 	int i;
917*3941Svenki 	char *prop;
918*3941Svenki 	picl_errno_t err;
919*3941Svenki 	int32_t lo_warning, lo_shutdown;
920*3941Svenki 	int32_t hi_warning, hi_shutdown;
921*3941Svenki 	int32_t current_val;
922*3941Svenki 
923*3941Svenki 	if (class_node_found == 0) {
924*3941Svenki 		class_node_found = 1;
925*3941Svenki 		return (PICL_WALK_TERMINATE);
926*3941Svenki 	}
927*3941Svenki 
928*3941Svenki 	if (syserrlog == 0) {
929*3941Svenki 		err = picl_get_propval_by_name(nodeh,
930*3941Svenki 			PICL_PROP_OPERATIONAL_STATUS, val,
931*3941Svenki 			sizeof (val));
932*3941Svenki 		if (err == PICL_SUCCESS) {
933*3941Svenki 			if (strcmp(val, "disabled") == 0) {
934*3941Svenki 				if (all_status_ok) {
935*3941Svenki 					all_status_ok = 0;
936*3941Svenki 					return (PICL_WALK_TERMINATE);
937*3941Svenki 				}
938*3941Svenki 			} else
939*3941Svenki 				return (PICL_WALK_CONTINUE);
940*3941Svenki 		} else {
941*3941Svenki 			all_status_ok = 0;
942*3941Svenki 			return (PICL_WALK_TERMINATE);
943*3941Svenki 		}
944*3941Svenki 	}
945*3941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
946*3941Svenki 		sizeof (parenth));
947*3941Svenki 	if (err != PICL_SUCCESS) {
948*3941Svenki 		log_printf("\n");
949*3941Svenki 		return (PICL_WALK_CONTINUE);
950*3941Svenki 	}
951*3941Svenki 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
952*3941Svenki 		return (PICL_WALK_TERMINATE);
953*3941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
954*3941Svenki 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
955*3941Svenki 			while (--i > -1)
956*3941Svenki 				free(names[i]);
957*3941Svenki 			free(loc);
958*3941Svenki 			return (PICL_WALK_TERMINATE);
959*3941Svenki 		}
960*3941Svenki 	i = 0;
961*3941Svenki 	while (err == PICL_SUCCESS) {
962*3941Svenki 		if (parenth == chassish || parenth == phyplatformh)
963*3941Svenki 			break;
964*3941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
965*3941Svenki 			names[i++], PICL_PROPNAMELEN_MAX);
966*3941Svenki 		if (err != PICL_SUCCESS) {
967*3941Svenki 			i--;
968*3941Svenki 			break;
969*3941Svenki 		}
970*3941Svenki 		if (i == PARENT_NAMES)
971*3941Svenki 			break;
972*3941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
973*3941Svenki 			&parenth, sizeof (parenth));
974*3941Svenki 	}
975*3941Svenki 	loc[0] = '\0';
976*3941Svenki 	if (--i > -1)
977*3941Svenki 		loc = strncat(loc, names[i], strlen(names[i]));
978*3941Svenki 	while (--i > -1) {
979*3941Svenki 		loc = strncat(loc, "/", 1);
980*3941Svenki 		loc = strncat(loc, names[i], strlen(names[i]));
981*3941Svenki 	}
982*3941Svenki 	log_printf("%-12s", loc);
983*3941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
984*3941Svenki 		free(names[i]);
985*3941Svenki 	free(loc);
986*3941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
987*3941Svenki 		sizeof (val));
988*3941Svenki 	if (err == PICL_SUCCESS)
989*3941Svenki 		log_printf("%-15s", val);
990*3941Svenki 
991*3941Svenki 	prop = (char *)args;
992*3941Svenki 	if (!prop) {
993*3941Svenki 		log_printf("\n");
994*3941Svenki 		return (PICL_WALK_CONTINUE);
995*3941Svenki 	}
996*3941Svenki 	if (picl_get_propval_by_name(nodeh, prop, &current_val,
997*3941Svenki 		sizeof (current_val)) != PICL_SUCCESS) {
998*3941Svenki 		log_printf("\n");
999*3941Svenki 		return (PICL_WALK_CONTINUE);
1000*3941Svenki 	}
1001*3941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_WARNING,
1002*3941Svenki 		&lo_warning, sizeof (lo_warning)) != PICL_SUCCESS)
1003*3941Svenki 		lo_warning = INVALID_THRESHOLD;
1004*3941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_SHUTDOWN,
1005*3941Svenki 		&lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS)
1006*3941Svenki 		lo_shutdown = INVALID_THRESHOLD;
1007*3941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_WARNING,
1008*3941Svenki 		&hi_warning, sizeof (hi_warning)) != PICL_SUCCESS)
1009*3941Svenki 		hi_warning = INVALID_THRESHOLD;
1010*3941Svenki 	if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_SHUTDOWN,
1011*3941Svenki 		&hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS)
1012*3941Svenki 		hi_shutdown = INVALID_THRESHOLD;
1013*3941Svenki 
1014*3941Svenki 	if ((lo_shutdown != INVALID_THRESHOLD &&
1015*3941Svenki 		current_val <= lo_shutdown) ||
1016*3941Svenki 		(hi_shutdown != INVALID_THRESHOLD &&
1017*3941Svenki 		current_val >= hi_shutdown)) {
1018*3941Svenki 		log_printf("%-s", "failed (");
1019*3941Svenki 		log_printf("%-d", current_val);
1020*3941Svenki 		log_printf("%-s", ")");
1021*3941Svenki 	} else if ((lo_warning != INVALID_THRESHOLD &&
1022*3941Svenki 		current_val <= lo_warning) ||
1023*3941Svenki 		(hi_warning != INVALID_THRESHOLD &&
1024*3941Svenki 		current_val >= hi_warning)) {
1025*3941Svenki 		log_printf("%-s", "warning (");
1026*3941Svenki 		log_printf("%-d", current_val);
1027*3941Svenki 		log_printf("%-s", ")");
1028*3941Svenki 	} else
1029*3941Svenki 		log_printf("%-s", "ok");
1030*3941Svenki 
1031*3941Svenki 	log_printf("\n");
1032*3941Svenki 	return (PICL_WALK_CONTINUE);
1033*3941Svenki }
1034*3941Svenki 
1035*3941Svenki /*ARGSUSED*/
1036*3941Svenki static int
1037*3941Svenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args)
1038*3941Svenki {
1039*3941Svenki 	char val[PICL_PROPNAMELEN_MAX];
1040*3941Svenki 	char status[PICL_PROPNAMELEN_MAX];
1041*3941Svenki 	picl_nodehdl_t parenth;
1042*3941Svenki 	char *names[PARENT_NAMES];
1043*3941Svenki 	char *loc;
1044*3941Svenki 	int i = 0;
1045*3941Svenki 	char *prop = (char *)args;
1046*3941Svenki 	picl_errno_t err = PICL_SUCCESS;
1047*3941Svenki 
1048*3941Svenki 	if (class_node_found == 0) {
1049*3941Svenki 		class_node_found = 1;
1050*3941Svenki 		return (PICL_WALK_TERMINATE);
1051*3941Svenki 	}
1052*3941Svenki 	if (syserrlog == 0) {
1053*3941Svenki 		err = picl_get_propval_by_name(nodeh,
1054*3941Svenki 			PICL_PROP_OPERATIONAL_STATUS, status,
1055*3941Svenki 			sizeof (status));
1056*3941Svenki 		if (err == PICL_SUCCESS) {
1057*3941Svenki 			if (strcmp(status, "disabled") == 0) {
1058*3941Svenki 				if (all_status_ok) {
1059*3941Svenki 					all_status_ok = 0;
1060*3941Svenki 					return (PICL_WALK_TERMINATE);
1061*3941Svenki 				}
1062*3941Svenki 			} else
1063*3941Svenki 				return (PICL_WALK_CONTINUE);
1064*3941Svenki 		} else {
1065*3941Svenki 			all_status_ok = 0;
1066*3941Svenki 			return (PICL_WALK_TERMINATE);
1067*3941Svenki 		}
1068*3941Svenki 	}
1069*3941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1070*3941Svenki 		sizeof (parenth));
1071*3941Svenki 	if (err != PICL_SUCCESS) {
1072*3941Svenki 		log_printf("\n");
1073*3941Svenki 		return (PICL_WALK_CONTINUE);
1074*3941Svenki 	}
1075*3941Svenki 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
1076*3941Svenki 		return (PICL_WALK_TERMINATE);
1077*3941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
1078*3941Svenki 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
1079*3941Svenki 			while (--i > -1)
1080*3941Svenki 				free(names[i]);
1081*3941Svenki 			free(loc);
1082*3941Svenki 			return (PICL_WALK_TERMINATE);
1083*3941Svenki 		}
1084*3941Svenki 	i = 0;
1085*3941Svenki 	while (err == PICL_SUCCESS) {
1086*3941Svenki 		if (parenth == chassish || parenth == phyplatformh)
1087*3941Svenki 			break;
1088*3941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1089*3941Svenki 			names[i++], PICL_PROPNAMELEN_MAX);
1090*3941Svenki 		if (err != PICL_SUCCESS) {
1091*3941Svenki 			i--;
1092*3941Svenki 			break;
1093*3941Svenki 		}
1094*3941Svenki 		if (i == PARENT_NAMES)
1095*3941Svenki 			break;
1096*3941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
1097*3941Svenki 			&parenth, sizeof (parenth));
1098*3941Svenki 	}
1099*3941Svenki 	loc[0] = '\0';
1100*3941Svenki 	if (--i > -1)
1101*3941Svenki 		loc = strncat(loc, names[i], strlen(names[i]));
1102*3941Svenki 	while (--i > -1) {
1103*3941Svenki 		loc = strncat(loc, "/", 1);
1104*3941Svenki 		loc = strncat(loc, names[i], strlen(names[i]));
1105*3941Svenki 	}
1106*3941Svenki 	log_printf("%-12s", loc);
1107*3941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
1108*3941Svenki 		free(names[i]);
1109*3941Svenki 	free(loc);
1110*3941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
1111*3941Svenki 		sizeof (val));
1112*3941Svenki 	if (err == PICL_SUCCESS)
1113*3941Svenki 		log_printf("%-15s", val);
1114*3941Svenki 	if (syserrlog == 0) {
1115*3941Svenki 		log_printf("%-8s", status);
1116*3941Svenki 		return (PICL_WALK_CONTINUE);
1117*3941Svenki 	}
1118*3941Svenki 	err = picl_get_propval_by_name(nodeh, prop, val,
1119*3941Svenki 		sizeof (val));
1120*3941Svenki 	if (err == PICL_SUCCESS)
1121*3941Svenki 		log_printf("%-8s", val);
1122*3941Svenki 	log_printf("\n");
1123*3941Svenki 	return (PICL_WALK_CONTINUE);
1124*3941Svenki }
1125*3941Svenki 
1126*3941Svenki static void
1127*3941Svenki sun4v_env_print_fan_sensors()
1128*3941Svenki {
1129*3941Svenki 	char *fmt = "%-11s %-14s %-10s\n";
1130*3941Svenki 	/*
1131*3941Svenki 	 * If there isn't any fan sensor node, return now.
1132*3941Svenki 	 */
1133*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1134*3941Svenki 		PICL_CLASS_RPM_SENSOR, (void *)PICL_CLASS_RPM_SENSOR,
1135*3941Svenki 		sun4v_env_print_sensor_callback);
1136*3941Svenki 	if (!class_node_found)
1137*3941Svenki 		return;
1138*3941Svenki 	log_printf("Fan sensors:\n");
1139*3941Svenki 	if (syserrlog == 0) {
1140*3941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1141*3941Svenki 			PICL_CLASS_RPM_SENSOR,
1142*3941Svenki 			NULL, sun4v_env_print_sensor_callback);
1143*3941Svenki 		if (all_status_ok) {
1144*3941Svenki 			log_printf("All fan sensors are OK.\n");
1145*3941Svenki 			return;
1146*3941Svenki 		}
1147*3941Svenki 	}
1148*3941Svenki 	log_printf("---------------------------------\n");
1149*3941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1150*3941Svenki 	log_printf("---------------------------------\n");
1151*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR,
1152*3941Svenki 		PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
1153*3941Svenki }
1154*3941Svenki 
1155*3941Svenki static void
1156*3941Svenki sun4v_env_print_fan_indicators()
1157*3941Svenki {
1158*3941Svenki 	char *fmt = "%-11s %-14s %-10s\n";
1159*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1160*3941Svenki 		PICL_CLASS_RPM_INDICATOR, (void *)PICL_CLASS_RPM_INDICATOR,
1161*3941Svenki 		sun4v_env_print_indicator_callback);
1162*3941Svenki 	if (!class_node_found)
1163*3941Svenki 		return;
1164*3941Svenki 	log_printf("\nFan indicators:\n");
1165*3941Svenki 	if (syserrlog == 0) {
1166*3941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1167*3941Svenki 			PICL_CLASS_RPM_INDICATOR,
1168*3941Svenki 			NULL, sun4v_env_print_indicator_callback);
1169*3941Svenki 		if (all_status_ok) {
1170*3941Svenki 			log_printf("All fan indicators are OK.\n");
1171*3941Svenki 			return;
1172*3941Svenki 		}
1173*3941Svenki 	}
1174*3941Svenki 	log_printf("------------------------------------\n");
1175*3941Svenki 	log_printf(fmt, "Location", "Sensor", "Condition", 0);
1176*3941Svenki 	log_printf("------------------------------------\n");
1177*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR,
1178*3941Svenki 		PICL_CLASS_RPM_INDICATOR, sun4v_env_print_indicator_callback);
1179*3941Svenki }
1180*3941Svenki 
1181*3941Svenki static void
1182*3941Svenki sun4v_env_print_temp_sensors()
1183*3941Svenki {
1184*3941Svenki 	char *fmt = "%-11s %-14s %-10s\n";
1185*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1186*3941Svenki 		PICL_CLASS_TEMPERATURE_SENSOR,
1187*3941Svenki 		(void *)PICL_PROP_TEMPERATURE,
1188*3941Svenki 		sun4v_env_print_sensor_callback);
1189*3941Svenki 	if (!class_node_found)
1190*3941Svenki 		return;
1191*3941Svenki 
1192*3941Svenki 	log_printf("\nTemperature sensors:\n");
1193*3941Svenki 	if (syserrlog == 0) {
1194*3941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1195*3941Svenki 			PICL_CLASS_TEMPERATURE_SENSOR,
1196*3941Svenki 			NULL, sun4v_env_print_sensor_callback);
1197*3941Svenki 		if (all_status_ok) {
1198*3941Svenki 			log_printf("All temperature sensors are OK.\n");
1199*3941Svenki 			return;
1200*3941Svenki 		}
1201*3941Svenki 	}
1202*3941Svenki 	log_printf("---------------------------------\n");
1203*3941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1204*3941Svenki 	log_printf("---------------------------------\n");
1205*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1206*3941Svenki 		PICL_CLASS_TEMPERATURE_SENSOR,
1207*3941Svenki 		(void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
1208*3941Svenki }
1209*3941Svenki 
1210*3941Svenki static void
1211*3941Svenki sun4v_env_print_temp_indicators()
1212*3941Svenki {
1213*3941Svenki 	char *fmt = "%-11s %-14s %-8s\n";
1214*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1215*3941Svenki 		PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION,
1216*3941Svenki 		sun4v_env_print_indicator_callback);
1217*3941Svenki 	if (!class_node_found)
1218*3941Svenki 		return;
1219*3941Svenki 	log_printf("\nTemperature indicators:\n");
1220*3941Svenki 	if (syserrlog == 0) {
1221*3941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1222*3941Svenki 			PICL_CLASS_TEMPERATURE_INDICATOR, NULL,
1223*3941Svenki 			sun4v_env_print_indicator_callback);
1224*3941Svenki 		if (all_status_ok) {
1225*3941Svenki 			log_printf("All temperature indicators are OK.\n");
1226*3941Svenki 			return;
1227*3941Svenki 		}
1228*3941Svenki 	}
1229*3941Svenki 	log_printf("------------------------------\n");
1230*3941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
1231*3941Svenki 	log_printf("------------------------------\n");
1232*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1233*3941Svenki 		PICL_CLASS_TEMPERATURE_INDICATOR,
1234*3941Svenki 		(void *)PICL_PROP_CONDITION,
1235*3941Svenki 		sun4v_env_print_indicator_callback);
1236*3941Svenki }
1237*3941Svenki 
1238*3941Svenki static void
1239*3941Svenki sun4v_env_print_current_sensors()
1240*3941Svenki {
1241*3941Svenki 	char *fmt = "%-11s %-14s %-10s\n";
1242*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR,
1243*3941Svenki 		(void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
1244*3941Svenki 	if (!class_node_found)
1245*3941Svenki 		return;
1246*3941Svenki 	log_printf("\nCurrent sensors:\n");
1247*3941Svenki 	if (syserrlog == 0) {
1248*3941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1249*3941Svenki 			PICL_CLASS_CURRENT_SENSOR,
1250*3941Svenki 			NULL, sun4v_env_print_sensor_callback);
1251*3941Svenki 		if (all_status_ok) {
1252*3941Svenki 			log_printf("All current sensors are OK.\n");
1253*3941Svenki 			return;
1254*3941Svenki 		}
1255*3941Svenki 	}
1256*3941Svenki 	log_printf("---------------------------------\n");
1257*3941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1258*3941Svenki 	log_printf("---------------------------------\n");
1259*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1260*3941Svenki 		PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
1261*3941Svenki 		sun4v_env_print_sensor_callback);
1262*3941Svenki }
1263*3941Svenki 
1264*3941Svenki static void
1265*3941Svenki sun4v_env_print_current_indicators()
1266*3941Svenki {
1267*3941Svenki 	char *fmt = "%-11s %-14s %-8s\n";
1268*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1269*3941Svenki 		PICL_CLASS_CURRENT_INDICATOR,
1270*3941Svenki 		(void *)PICL_PROP_CONDITION,
1271*3941Svenki 		sun4v_env_print_indicator_callback);
1272*3941Svenki 	if (!class_node_found)
1273*3941Svenki 		return;
1274*3941Svenki 	log_printf("\nCurrent indicators:\n");
1275*3941Svenki 	if (syserrlog == 0) {
1276*3941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1277*3941Svenki 			PICL_CLASS_CURRENT_INDICATOR, NULL,
1278*3941Svenki 			sun4v_env_print_indicator_callback);
1279*3941Svenki 		if (all_status_ok) {
1280*3941Svenki 			log_printf("All current indicators are OK.\n");
1281*3941Svenki 			return;
1282*3941Svenki 		}
1283*3941Svenki 	}
1284*3941Svenki 	log_printf("------------------------------------\n");
1285*3941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
1286*3941Svenki 	log_printf("------------------------------------\n");
1287*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1288*3941Svenki 		PICL_CLASS_CURRENT_INDICATOR,
1289*3941Svenki 		(void *)PICL_PROP_CONDITION,
1290*3941Svenki 		sun4v_env_print_indicator_callback);
1291*3941Svenki }
1292*3941Svenki 
1293*3941Svenki static void
1294*3941Svenki sun4v_env_print_voltage_sensors()
1295*3941Svenki {
1296*3941Svenki 	char *fmt = "%-11s %-14s %-10s\n";
1297*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1298*3941Svenki 		PICL_CLASS_VOLTAGE_SENSOR,
1299*3941Svenki 		PICL_PROP_VOLTAGE,
1300*3941Svenki 		sun4v_env_print_sensor_callback);
1301*3941Svenki 	if (!class_node_found)
1302*3941Svenki 		return;
1303*3941Svenki 	log_printf("\nVoltage sensors:\n");
1304*3941Svenki 	if (syserrlog == 0) {
1305*3941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1306*3941Svenki 			PICL_CLASS_VOLTAGE_SENSOR,
1307*3941Svenki 			NULL, sun4v_env_print_sensor_callback);
1308*3941Svenki 		if (all_status_ok) {
1309*3941Svenki 			log_printf("All voltage sensors are OK.\n");
1310*3941Svenki 			return;
1311*3941Svenki 		}
1312*3941Svenki 	}
1313*3941Svenki 	log_printf("---------------------------------\n");
1314*3941Svenki 	log_printf(fmt, "Location", "Sensor", "Status", 0);
1315*3941Svenki 	log_printf("---------------------------------\n");
1316*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1317*3941Svenki 		PICL_CLASS_VOLTAGE_SENSOR,
1318*3941Svenki 		(void *)PICL_PROP_VOLTAGE,
1319*3941Svenki 		sun4v_env_print_sensor_callback);
1320*3941Svenki }
1321*3941Svenki 
1322*3941Svenki static void
1323*3941Svenki sun4v_env_print_voltage_indicators()
1324*3941Svenki {
1325*3941Svenki 	char *fmt = "%-11s %-14s %-8s\n";
1326*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1327*3941Svenki 		PICL_CLASS_VOLTAGE_INDICATOR,
1328*3941Svenki 		(void *)PICL_PROP_CONDITION,
1329*3941Svenki 		sun4v_env_print_indicator_callback);
1330*3941Svenki 	if (!class_node_found)
1331*3941Svenki 		return;
1332*3941Svenki 	log_printf("\nVoltage indicators:\n");
1333*3941Svenki 	if (syserrlog == 0) {
1334*3941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1335*3941Svenki 			PICL_CLASS_VOLTAGE_INDICATOR, NULL,
1336*3941Svenki 			sun4v_env_print_indicator_callback);
1337*3941Svenki 		if (all_status_ok) {
1338*3941Svenki 			log_printf("All voltage indicators are OK.\n");
1339*3941Svenki 			return;
1340*3941Svenki 		}
1341*3941Svenki 	}
1342*3941Svenki 	log_printf("------------------------------------\n");
1343*3941Svenki 	log_printf(fmt, "Location", "Indicator", "Condition", 0);
1344*3941Svenki 	log_printf("------------------------------------\n");
1345*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh,
1346*3941Svenki 		PICL_CLASS_VOLTAGE_INDICATOR,
1347*3941Svenki 		(void *)PICL_PROP_CONDITION,
1348*3941Svenki 		sun4v_env_print_indicator_callback);
1349*3941Svenki }
1350*3941Svenki 
1351*3941Svenki static void
1352*3941Svenki sun4v_env_print_LEDs()
1353*3941Svenki {
1354*3941Svenki 	char *fmt = "%-11s %-14s %-8s\n";
1355*3941Svenki 	if (syserrlog == 0)
1356*3941Svenki 		return;
1357*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
1358*3941Svenki 		(void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
1359*3941Svenki 	if (!class_node_found)
1360*3941Svenki 		return;
1361*3941Svenki 	log_printf("\nLEDs:\n");
1362*3941Svenki 	log_printf("--------------------------------\n");
1363*3941Svenki 	log_printf(fmt, "Location", "LED", "State", 0);
1364*3941Svenki 	log_printf("--------------------------------\n");
1365*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
1366*3941Svenki 		(void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
1367*3941Svenki }
1368*3941Svenki 
1369*3941Svenki /*ARGSUSED*/
1370*3941Svenki static int
1371*3941Svenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args)
1372*3941Svenki {
1373*3941Svenki 	char label[PICL_PROPNAMELEN_MAX];
1374*3941Svenki 	char status[PICL_PROPNAMELEN_MAX];
1375*3941Svenki 	picl_errno_t err;
1376*3941Svenki 	picl_prophdl_t proph;
1377*3941Svenki 	picl_nodehdl_t parenth;
1378*3941Svenki 	char *names[PARENT_NAMES];
1379*3941Svenki 	char *loc;
1380*3941Svenki 	int i;
1381*3941Svenki 
1382*3941Svenki 	if (!class_node_found) {
1383*3941Svenki 		class_node_found = 1;
1384*3941Svenki 		return (PICL_WALK_TERMINATE);
1385*3941Svenki 	}
1386*3941Svenki 	err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph);
1387*3941Svenki 	if (err != PICL_SUCCESS)
1388*3941Svenki 		return (PICL_WALK_CONTINUE);
1389*3941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1390*3941Svenki 		sizeof (label));
1391*3941Svenki 	if (err != PICL_SUCCESS)
1392*3941Svenki 		return (PICL_WALK_CONTINUE);
1393*3941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
1394*3941Svenki 		status, sizeof (status));
1395*3941Svenki 	if (err != PICL_SUCCESS)
1396*3941Svenki 		return (PICL_WALK_CONTINUE);
1397*3941Svenki 	if (syserrlog == 0) {
1398*3941Svenki 		if (strcmp(status, "disabled") == 0) {
1399*3941Svenki 			if (all_status_ok) {
1400*3941Svenki 				all_status_ok = 0;
1401*3941Svenki 				return (PICL_WALK_TERMINATE);
1402*3941Svenki 			}
1403*3941Svenki 		} else
1404*3941Svenki 			return (PICL_WALK_CONTINUE);
1405*3941Svenki 	}
1406*3941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1407*3941Svenki 		sizeof (parenth));
1408*3941Svenki 	if (err != PICL_SUCCESS) {
1409*3941Svenki 		log_printf("\n");
1410*3941Svenki 		return (PICL_WALK_CONTINUE);
1411*3941Svenki 	}
1412*3941Svenki 	if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
1413*3941Svenki 		return (PICL_WALK_TERMINATE);
1414*3941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
1415*3941Svenki 		if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
1416*3941Svenki 			while (--i > -1)
1417*3941Svenki 				free(names[i]);
1418*3941Svenki 			free(loc);
1419*3941Svenki 			return (PICL_WALK_TERMINATE);
1420*3941Svenki 		}
1421*3941Svenki 	i = 0;
1422*3941Svenki 	while (err == PICL_SUCCESS) {
1423*3941Svenki 		if (parenth == chassish || parenth == phyplatformh)
1424*3941Svenki 			break;
1425*3941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1426*3941Svenki 			names[i++], PICL_PROPNAMELEN_MAX);
1427*3941Svenki 		if (err != PICL_SUCCESS) {
1428*3941Svenki 			i--;
1429*3941Svenki 			break;
1430*3941Svenki 		}
1431*3941Svenki 		if (i == PARENT_NAMES)
1432*3941Svenki 			break;
1433*3941Svenki 		err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
1434*3941Svenki 			&parenth, sizeof (parenth));
1435*3941Svenki 	}
1436*3941Svenki 	loc[0] = '\0';
1437*3941Svenki 	if (--i > -1)
1438*3941Svenki 		loc = strncat(loc, names[i], strlen(names[i]));
1439*3941Svenki 	while (--i > -1) {
1440*3941Svenki 		loc = strncat(loc, "/", 1);
1441*3941Svenki 		loc = strncat(loc, names[i], strlen(names[i]));
1442*3941Svenki 	}
1443*3941Svenki 	log_printf("%-21s", loc);
1444*3941Svenki 	for (i = 0; i < PARENT_NAMES; i++)
1445*3941Svenki 		free(names[i]);
1446*3941Svenki 	free(loc);
1447*3941Svenki 	log_printf("%-10s", label);
1448*3941Svenki 	log_printf("%-9s", status);
1449*3941Svenki 	log_printf("\n");
1450*3941Svenki 	return (PICL_WALK_CONTINUE);
1451*3941Svenki }
1452*3941Svenki 
1453*3941Svenki static void
1454*3941Svenki sun4v_print_fru_status()
1455*3941Svenki {
1456*3941Svenki 	char *fmt = "%-20s %-9s %-8s\n";
1457*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1458*3941Svenki 		sun4v_print_fru_status_callback);
1459*3941Svenki 	if (!class_node_found)
1460*3941Svenki 		return;
1461*3941Svenki 	log_printf("\n");
1462*3941Svenki 	log_printf("============================");
1463*3941Svenki 	log_printf(" FRU Status ");
1464*3941Svenki 	log_printf("============================");
1465*3941Svenki 	log_printf("\n");
1466*3941Svenki 
1467*3941Svenki 	if (syserrlog == 0) {
1468*3941Svenki 		(void) picl_walk_tree_by_class(phyplatformh,
1469*3941Svenki 			PICL_CLASS_MODULE, NULL,
1470*3941Svenki 			sun4v_print_fru_status_callback);
1471*3941Svenki 		if (all_status_ok) {
1472*3941Svenki 			log_printf("All FRUs are enabled.\n");
1473*3941Svenki 			return;
1474*3941Svenki 		}
1475*3941Svenki 	}
1476*3941Svenki 	log_printf(fmt, "Location", "Name", "Status", 0);
1477*3941Svenki 	log_printf("-------------------------------------\n");
1478*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_MODULE, NULL,
1479*3941Svenki 		sun4v_print_fru_status_callback);
1480*3941Svenki }
1481*3941Svenki 
1482*3941Svenki /*ARGSUSED*/
1483*3941Svenki static int
1484*3941Svenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args)
1485*3941Svenki {
1486*3941Svenki 	char label[PICL_PROPNAMELEN_MAX];
1487*3941Svenki 	char rev[PICL_PROPNAMELEN_MAX];
1488*3941Svenki 	picl_errno_t err;
1489*3941Svenki 
1490*3941Svenki 	if (!class_node_found) {
1491*3941Svenki 		class_node_found = 1;
1492*3941Svenki 		return (PICL_WALK_TERMINATE);
1493*3941Svenki 	}
1494*3941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1495*3941Svenki 		sizeof (label));
1496*3941Svenki 	if (err != PICL_SUCCESS)
1497*3941Svenki 		return (PICL_WALK_CONTINUE);
1498*3941Svenki 	err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev,
1499*3941Svenki 		sizeof (rev));
1500*3941Svenki 	if (err != PICL_SUCCESS)
1501*3941Svenki 		return (PICL_WALK_CONTINUE);
1502*3941Svenki 	if (strlen(rev) == 0)
1503*3941Svenki 		return (PICL_WALK_CONTINUE);
1504*3941Svenki 	log_printf("%-21s", label);
1505*3941Svenki 	log_printf("%-40s", rev);
1506*3941Svenki 	log_printf("\n");
1507*3941Svenki 	return (PICL_WALK_CONTINUE);
1508*3941Svenki }
1509*3941Svenki 
1510*3941Svenki static void
1511*3941Svenki sun4v_print_fw_rev()
1512*3941Svenki {
1513*3941Svenki 	char *fmt = "%-20s %-10s\n";
1514*3941Svenki 	if (syserrlog == 0)
1515*3941Svenki 		return;
1516*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1517*3941Svenki 		sun4v_print_fw_rev_callback);
1518*3941Svenki 	if (!class_node_found)
1519*3941Svenki 		return;
1520*3941Svenki 	log_printf("\n");
1521*3941Svenki 	log_printf("============================");
1522*3941Svenki 	log_printf(" FW Version ");
1523*3941Svenki 	log_printf("============================");
1524*3941Svenki 	log_printf("\n");
1525*3941Svenki 	log_printf(fmt, "Name", "Version", 0);
1526*3941Svenki 	log_printf("----------------------------\n");
1527*3941Svenki 	(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1528*3941Svenki 		sun4v_print_fw_rev_callback);
1529*3941Svenki }
1530*3941Svenki 
1531*3941Svenki static void
1532*3941Svenki sun4v_print_chassis_serial_no()
1533*3941Svenki {
1534*3941Svenki 	char val[PICL_PROPNAMELEN_MAX];
1535*3941Svenki 	picl_errno_t err;
1536*3941Svenki 	if (syserrlog == 0 || chassish == 0)
1537*3941Svenki 		return;
1538*3941Svenki 
1539*3941Svenki 	log_printf("\n");
1540*3941Svenki 	log_printf("Chassis Serial Number");
1541*3941Svenki 	log_printf("\n");
1542*3941Svenki 	log_printf("---------------------\n");
1543*3941Svenki 	err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER,
1544*3941Svenki 		val, sizeof (val));
1545*3941Svenki 	if (err == PICL_SUCCESS)
1546*3941Svenki 		log_printf("%s", val);
1547*3941Svenki 	log_printf("\n");
1548*3941Svenki }
1549