103831d35Sstevel /*
203831d35Sstevel * CDDL HEADER START
303831d35Sstevel *
403831d35Sstevel * The contents of this file are subject to the terms of the
50d63ce2bSvenki * Common Development and Distribution License (the "License").
60d63ce2bSvenki * You may not use this file except in compliance with the License.
703831d35Sstevel *
803831d35Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
903831d35Sstevel * or http://www.opensolaris.org/os/licensing.
1003831d35Sstevel * See the License for the specific language governing permissions
1103831d35Sstevel * and limitations under the License.
1203831d35Sstevel *
1303831d35Sstevel * When distributing Covered Code, include this CDDL HEADER in each
1403831d35Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1503831d35Sstevel * If applicable, add the following below this CDDL HEADER, with the
1603831d35Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
1703831d35Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
1803831d35Sstevel *
1903831d35Sstevel * CDDL HEADER END
2003831d35Sstevel */
2103831d35Sstevel /*
227ae8c7a8SMichael Bergknoff * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
232bcbf80cSPeter Tribble * Copyright (c) 2020 Peter Tribble.
2403831d35Sstevel */
2503831d35Sstevel
2603831d35Sstevel #include <stdio.h>
2703831d35Sstevel #include <stdlib.h>
28dc6ca969Sfw #include <alloca.h>
2903831d35Sstevel #include <unistd.h>
3003831d35Sstevel #include <ctype.h>
3103831d35Sstevel #include <string.h>
3203831d35Sstevel #include <kvm.h>
3303831d35Sstevel #include <varargs.h>
3403831d35Sstevel #include <time.h>
3503831d35Sstevel #include <dirent.h>
3603831d35Sstevel #include <fcntl.h>
3703831d35Sstevel #include <sys/param.h>
3803831d35Sstevel #include <sys/stat.h>
3903831d35Sstevel #include <sys/types.h>
4003831d35Sstevel #include <sys/utsname.h>
4103831d35Sstevel #include <sys/openpromio.h>
4203831d35Sstevel #include <libintl.h>
4303831d35Sstevel #include <syslog.h>
4403831d35Sstevel #include <sys/dkio.h>
450d63ce2bSvenki #include <sys/systeminfo.h>
460d63ce2bSvenki #include <picldefs.h>
47aaba19e2Sfw #include <math.h>
48aaba19e2Sfw #include <errno.h>
4903831d35Sstevel #include "pdevinfo.h"
5003831d35Sstevel #include "display.h"
5103831d35Sstevel #include "display_sun4v.h"
5203831d35Sstevel #include "libprtdiag.h"
5303831d35Sstevel
5403831d35Sstevel #if !defined(TEXT_DOMAIN)
5503831d35Sstevel #define TEXT_DOMAIN "SYS_TEST"
5603831d35Sstevel #endif
5703831d35Sstevel
58a90d965dSfw #define MOTHERBOARD "MB"
590d63ce2bSvenki #define NETWORK "network"
600d63ce2bSvenki #define SUN4V_MACHINE "sun4v"
610d63ce2bSvenki #define PARENT_NAMES 10
620d63ce2bSvenki
630d63ce2bSvenki /*
640d63ce2bSvenki * Additional OBP properties
650d63ce2bSvenki */
660d63ce2bSvenki #define OBP_PROP_COMPATIBLE "compatible"
670d63ce2bSvenki #define OBP_PROP_MODEL "model"
680d63ce2bSvenki #define OBP_PROP_SLOT_NAMES "slot-names"
69dc6ca969Sfw #define OBP_PROP_VERSION "version"
700d63ce2bSvenki
710d63ce2bSvenki #define PICL_NODE_PHYSICAL_PLATFORM "physical-platform"
720d63ce2bSvenki #define PICL_NODE_CHASSIS "chassis"
730d63ce2bSvenki #define MEMORY_SIZE_FIELD 11
740d63ce2bSvenki #define INVALID_THRESHOLD 1000000
750d63ce2bSvenki
760d63ce2bSvenki /*
770d63ce2bSvenki * Additional picl classes
780d63ce2bSvenki */
790d63ce2bSvenki #ifndef PICL_CLASS_SUN4V
800d63ce2bSvenki #define PICL_CLASS_SUN4V "sun4v"
810d63ce2bSvenki #endif
820d63ce2bSvenki
830d63ce2bSvenki #ifndef PICL_PROP_NAC
840d63ce2bSvenki #define PICL_PROP_NAC "nac"
850d63ce2bSvenki #endif
860d63ce2bSvenki
870d63ce2bSvenki extern int sys_clk;
880d63ce2bSvenki extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *,
890d63ce2bSvenki picl_nodehdl_t *);
900d63ce2bSvenki
910d63ce2bSvenki static picl_nodehdl_t rooth = 0, phyplatformh = 0;
920d63ce2bSvenki static picl_nodehdl_t chassish = 0;
930d63ce2bSvenki static int class_node_found;
940d63ce2bSvenki static int syserrlog;
950d63ce2bSvenki static int all_status_ok;
960d63ce2bSvenki
970d63ce2bSvenki /* local functions */
980d63ce2bSvenki static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **);
990d63ce2bSvenki static void sun4v_display_memory_conf(picl_nodehdl_t);
100d776656fSmb static int sun4v_disp_env_status();
1010d63ce2bSvenki static void sun4v_env_print_fan_sensors();
1020d63ce2bSvenki static void sun4v_env_print_fan_indicators();
1030d63ce2bSvenki static void sun4v_env_print_temp_sensors();
1040d63ce2bSvenki static void sun4v_env_print_temp_indicators();
1050d63ce2bSvenki static void sun4v_env_print_current_sensors();
1060d63ce2bSvenki static void sun4v_env_print_current_indicators();
1070d63ce2bSvenki static void sun4v_env_print_voltage_sensors();
1080d63ce2bSvenki static void sun4v_env_print_voltage_indicators();
1090d63ce2bSvenki static void sun4v_env_print_LEDs();
1100d63ce2bSvenki static void sun4v_print_fru_status();
1118a31bd2bSBirva Shah static int is_fru_absent(picl_nodehdl_t);
1120d63ce2bSvenki static void sun4v_print_fw_rev();
1130d63ce2bSvenki static void sun4v_print_chassis_serial_no();
114dc6ca969Sfw static int openprom_callback(picl_nodehdl_t openpromh, void *arg);
115dc6ca969Sfw static void sun4v_print_openprom_rev();
11603831d35Sstevel
11703831d35Sstevel int
sun4v_display(Sys_tree * tree,Prom_node * root,int log,picl_nodehdl_t plafh)1180d63ce2bSvenki sun4v_display(Sys_tree *tree, Prom_node *root, int log,
119*6fb59094SToomas Soome picl_nodehdl_t plafh)
12003831d35Sstevel {
12103831d35Sstevel void *value; /* used for opaque PROM data */
12203831d35Sstevel struct mem_total memory_total; /* Total memory in system */
1230d63ce2bSvenki char machine[MAXSTRLEN];
124d776656fSmb int exit_code = 0;
1250d63ce2bSvenki
1260d63ce2bSvenki if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1)
1270d63ce2bSvenki return (1);
1280d63ce2bSvenki if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0)
1290d63ce2bSvenki return (1);
13003831d35Sstevel
13103831d35Sstevel sys_clk = -1; /* System clock freq. (in MHz) */
13203831d35Sstevel
13303831d35Sstevel /*
13403831d35Sstevel * Now display the machine's configuration. We do this if we
13503831d35Sstevel * are not logging.
13603831d35Sstevel */
13703831d35Sstevel if (!logging) {
13803831d35Sstevel struct utsname uts_buf;
13903831d35Sstevel
14003831d35Sstevel /*
14103831d35Sstevel * Display system banner
14203831d35Sstevel */
14303831d35Sstevel (void) uname(&uts_buf);
14403831d35Sstevel
1450d63ce2bSvenki log_printf(dgettext(TEXT_DOMAIN, "System Configuration: "
1462983dda7SMichael Bergknoff "Oracle Corporation %s %s\n"), uts_buf.machine,
147a90d965dSfw get_prop_val(find_prop(root, "banner-name")), 0);
14803831d35Sstevel
14903831d35Sstevel /* display system clock frequency */
15003831d35Sstevel value = get_prop_val(find_prop(root, "clock-frequency"));
15103831d35Sstevel if (value != NULL) {
15203831d35Sstevel sys_clk = ((*((int *)value)) + 500000) / 1000000;
15303831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "System clock "
154a90d965dSfw "frequency: %d MHz\n"), sys_clk, 0);
15503831d35Sstevel }
15603831d35Sstevel
15703831d35Sstevel /* Display the Memory Size */
1582bcbf80cSPeter Tribble display_memorysize(tree, NULL, &memory_total);
15903831d35Sstevel
16003831d35Sstevel /* Display the CPU devices */
16103831d35Sstevel sun4v_display_cpu_devices(plafh);
16203831d35Sstevel
16303831d35Sstevel /* Display the Memory configuration */
1640d63ce2bSvenki class_node_found = 0;
1650d63ce2bSvenki sun4v_display_memory_conf(plafh);
16603831d35Sstevel
16703831d35Sstevel /* Display all the IO cards. */
16803831d35Sstevel (void) sun4v_display_pci(plafh);
1690d63ce2bSvenki sun4v_display_diaginfo((log || (logging)), root, plafh);
17003831d35Sstevel
1710d63ce2bSvenki if (picl_get_root(&rooth) != PICL_SUCCESS)
1720d63ce2bSvenki return (1);
173d776656fSmb
174d776656fSmb /*
175d776656fSmb * The physical-platform node may be missing on systems with
176d776656fSmb * older firmware so don't consider that an error.
177d776656fSmb */
1780d63ce2bSvenki if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM,
179a90d965dSfw &phyplatformh) != PICL_SUCCESS)
180d776656fSmb return (0);
1810d63ce2bSvenki
1820d63ce2bSvenki if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME,
183a90d965dSfw PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
184a90d965dSfw strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS)
1850d63ce2bSvenki return (1);
1860d63ce2bSvenki
1870d63ce2bSvenki syserrlog = log;
188d776656fSmb exit_code = sun4v_disp_env_status();
1890d63ce2bSvenki }
190d776656fSmb return (exit_code);
1910d63ce2bSvenki }
1920d63ce2bSvenki
193db8f0877Sfw /*
194db8f0877Sfw * The binding-name property encodes the bus type.
195db8f0877Sfw */
1960d63ce2bSvenki static void
get_bus_type(picl_nodehdl_t nodeh,struct io_card * card)1970d63ce2bSvenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card)
1980d63ce2bSvenki {
199db8f0877Sfw char val[PICL_PROPNAMELEN_MAX], *p, *q;
2000d63ce2bSvenki
201db8f0877Sfw card->bus_type[0] = '\0';
202db8f0877Sfw
203db8f0877Sfw if (picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, val,
204db8f0877Sfw sizeof (val)) == PICL_SUCCESS) {
205db8f0877Sfw if (strstr(val, PICL_CLASS_PCIEX))
2064c5e0fdeSvivek (void) strlcpy(card->bus_type, "PCIE",
207a90d965dSfw sizeof (card->bus_type));
208db8f0877Sfw else if (strstr(val, PICL_CLASS_PCI))
209db8f0877Sfw (void) strlcpy(card->bus_type, "PCIX",
210db8f0877Sfw sizeof (card->bus_type));
211db8f0877Sfw else {
212db8f0877Sfw /*
213db8f0877Sfw * Not perfect: process the binding-name until
214db8f0877Sfw * we encounter something that we don't think would
215db8f0877Sfw * be part of a bus type. This may get confused a bit
216db8f0877Sfw * if a device or vendor id is encoded right after
217db8f0877Sfw * the bus class since there's no delimiter. If the
218db8f0877Sfw * id number begins with a hex digit [abcdef] then
219db8f0877Sfw * this will become part of the bus type string
220db8f0877Sfw * reported by prtdiag. This is all an effort to
221db8f0877Sfw * print something potentially useful for bus types
222db8f0877Sfw * other than PCI/PCIe.
223db8f0877Sfw *
224db8f0877Sfw * We do this because this code will get called for
225db8f0877Sfw * non-PCI class devices like the xaui (class sun4v.)
226db8f0877Sfw */
227db8f0877Sfw if (strstr(val, "SUNW,") != NULL)
228db8f0877Sfw p = strchr(val, ',') + 1;
229db8f0877Sfw else
230db8f0877Sfw p = val;
231db8f0877Sfw q = p;
232db8f0877Sfw while (*p != '\0') {
233db8f0877Sfw if (isdigit((char)*p) || ispunct((char)*p)) {
234db8f0877Sfw *p = '\0';
235db8f0877Sfw break;
236db8f0877Sfw }
237db8f0877Sfw *p = (char)_toupper((int)*p);
238db8f0877Sfw ++p;
239db8f0877Sfw }
240db8f0877Sfw (void) strlcpy(card->bus_type, q,
241db8f0877Sfw sizeof (card->bus_type));
242db8f0877Sfw }
2430d63ce2bSvenki }
2440d63ce2bSvenki }
2450d63ce2bSvenki
246db8f0877Sfw /*
247db8f0877Sfw * Fetch the Label property for this device. If none is found then
248db8f0877Sfw * search all the siblings with the same device ID for a
249db8f0877Sfw * Label and return that Label. The plug-in can only match the canonical
250db8f0877Sfw * path from the PRI with a specific devfs path. So we take care of
251db8f0877Sfw * devices with multiple functions here. A leaf device downstream of
252db8f0877Sfw * a bridge should fall out of here with PICL_PROPNOTFOUND, and the
253db8f0877Sfw * caller can walk back up the tree in search of the slot's Label.
254db8f0877Sfw */
2550d63ce2bSvenki static picl_errno_t
get_slot_label(picl_nodehdl_t nodeh,struct io_card * card)2560d63ce2bSvenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card)
2570d63ce2bSvenki {
2580d63ce2bSvenki char val[PICL_PROPNAMELEN_MAX];
2590d63ce2bSvenki picl_errno_t err;
260dc6ca969Sfw picl_nodehdl_t pnodeh;
261db8f0877Sfw uint32_t devid, sib_devid;
262db8f0877Sfw int32_t instance;
2630d63ce2bSvenki
264dc6ca969Sfw /*
265db8f0877Sfw * If there's a Label at this node then return it - we're
266db8f0877Sfw * done.
267dc6ca969Sfw */
2680d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
269a90d965dSfw sizeof (val));
270db8f0877Sfw if (err == PICL_SUCCESS) {
271dc6ca969Sfw (void) strlcpy(card->slot_str, val, sizeof (card->slot_str));
272db8f0877Sfw return (err);
273db8f0877Sfw } else if (err != PICL_PROPNOTFOUND)
274db8f0877Sfw return (err);
275db8f0877Sfw
276db8f0877Sfw /*
277db8f0877Sfw * At this point we're starting to extrapolate what the Label
278db8f0877Sfw * should be since there is none at this specific node.
279db8f0877Sfw * Note that until the value of "err" is overwritten in the
280db8f0877Sfw * loop below, its value should be PICL_PROPNOTFOUND.
281db8f0877Sfw */
282db8f0877Sfw
283db8f0877Sfw /*
284db8f0877Sfw * The device must be attached, and we can figure that out if
285db8f0877Sfw * the instance number is present and is not equal to -1.
286db8f0877Sfw * This will prevent is from returning a Label for a sibling
287db8f0877Sfw * node when the node passed in would have a unique Label if the
288db8f0877Sfw * device were attached. But if the device is downstream of a
289db8f0877Sfw * node with a Label then pci_callback() will still find that
290db8f0877Sfw * and use it.
291db8f0877Sfw */
292db8f0877Sfw if (picl_get_propval_by_name(nodeh, PICL_PROP_INSTANCE, &instance,
293db8f0877Sfw sizeof (instance)) != PICL_SUCCESS)
294db8f0877Sfw return (err);
295db8f0877Sfw if (instance == -1)
296db8f0877Sfw return (err);
297db8f0877Sfw
298db8f0877Sfw /*
299db8f0877Sfw * Narrow the search to just the one device ID.
300db8f0877Sfw */
301db8f0877Sfw if (picl_get_propval_by_name(nodeh, PICL_PROP_DEVICE_ID, &devid,
302db8f0877Sfw sizeof (devid)) != PICL_SUCCESS)
303db8f0877Sfw return (err);
304db8f0877Sfw
305db8f0877Sfw /*
306db8f0877Sfw * Go find the first child of the parent so we can search
307db8f0877Sfw * all of the siblings.
308db8f0877Sfw */
309db8f0877Sfw if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
310db8f0877Sfw sizeof (pnodeh)) != PICL_SUCCESS)
311db8f0877Sfw return (err);
312db8f0877Sfw if (picl_get_propval_by_name(pnodeh, PICL_PROP_CHILD, &pnodeh,
313db8f0877Sfw sizeof (pnodeh)) != PICL_SUCCESS)
314db8f0877Sfw return (err);
315db8f0877Sfw
316db8f0877Sfw /*
317db8f0877Sfw * If the child's device ID matches, then fetch the Label and
318db8f0877Sfw * return it. The first child/device ID should have a Label
319db8f0877Sfw * associated with it.
320db8f0877Sfw */
321db8f0877Sfw do {
322db8f0877Sfw if (picl_get_propval_by_name(pnodeh, PICL_PROP_DEVICE_ID,
323db8f0877Sfw &sib_devid, sizeof (sib_devid)) == PICL_SUCCESS) {
324db8f0877Sfw if (sib_devid == devid) {
325db8f0877Sfw if ((err = picl_get_propval_by_name(pnodeh,
326db8f0877Sfw PICL_PROP_LABEL, val, sizeof (val))) ==
327db8f0877Sfw PICL_SUCCESS) {
328db8f0877Sfw (void) strlcpy(card->slot_str, val,
329db8f0877Sfw sizeof (card->slot_str));
330db8f0877Sfw break;
331db8f0877Sfw }
332db8f0877Sfw }
333db8f0877Sfw }
334db8f0877Sfw } while (picl_get_propval_by_name(pnodeh, PICL_PROP_PEER, &pnodeh,
335db8f0877Sfw sizeof (pnodeh)) == PICL_SUCCESS);
3360d63ce2bSvenki
337dc6ca969Sfw return (err);
3380d63ce2bSvenki }
3390d63ce2bSvenki
3400d63ce2bSvenki static void
get_slot_number(picl_nodehdl_t nodeh,struct io_card * card)3410d63ce2bSvenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card)
3420d63ce2bSvenki {
3430d63ce2bSvenki picl_errno_t err;
3440d63ce2bSvenki picl_prophdl_t proph;
3450d63ce2bSvenki picl_propinfo_t pinfo;
3460d63ce2bSvenki picl_nodehdl_t pnodeh;
3470d63ce2bSvenki uint8_t *pval;
3480d63ce2bSvenki uint32_t dev_mask;
3490d63ce2bSvenki char uaddr[MAXSTRLEN];
3500d63ce2bSvenki int i;
3510d63ce2bSvenki
3520d63ce2bSvenki err = PICL_SUCCESS;
3530d63ce2bSvenki while (err == PICL_SUCCESS) {
3540d63ce2bSvenki if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
355a90d965dSfw sizeof (pnodeh)) != PICL_SUCCESS) {
356a90d965dSfw (void) strlcpy(card->slot_str, MOTHERBOARD,
357a90d965dSfw sizeof (card->slot_str));
3580d63ce2bSvenki card->slot = -1;
3590d63ce2bSvenki return;
3600d63ce2bSvenki }
3610d63ce2bSvenki if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES,
362a90d965dSfw &pinfo, &proph) == PICL_SUCCESS) {
3630d63ce2bSvenki break;
3640d63ce2bSvenki }
3650d63ce2bSvenki nodeh = pnodeh;
3660d63ce2bSvenki }
3670d63ce2bSvenki if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr,
368a90d965dSfw sizeof (uaddr)) != PICL_SUCCESS) {
369a90d965dSfw (void) strlcpy(card->slot_str, MOTHERBOARD,
370a90d965dSfw sizeof (card->slot_str));
3710d63ce2bSvenki card->slot = -1;
3720d63ce2bSvenki return;
3730d63ce2bSvenki }
3740d63ce2bSvenki pval = (uint8_t *)malloc(pinfo.size);
3750d63ce2bSvenki if (!pval) {
376a90d965dSfw (void) strlcpy(card->slot_str, MOTHERBOARD,
377a90d965dSfw sizeof (card->slot_str));
3780d63ce2bSvenki card->slot = -1;
3790d63ce2bSvenki return;
3800d63ce2bSvenki }
3810d63ce2bSvenki if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) {
382a90d965dSfw (void) strlcpy(card->slot_str, MOTHERBOARD,
383a90d965dSfw sizeof (card->slot_str));
3840d63ce2bSvenki card->slot = -1;
3850d63ce2bSvenki free(pval);
3860d63ce2bSvenki return;
38703831d35Sstevel }
38803831d35Sstevel
3890d63ce2bSvenki dev_mask = 0;
3900d63ce2bSvenki for (i = 0; i < sizeof (dev_mask); i++)
3910d63ce2bSvenki dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i));
3920d63ce2bSvenki for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) {
3930d63ce2bSvenki if (uaddr[i] == ',') {
3940d63ce2bSvenki uaddr[i] = '\0';
3950d63ce2bSvenki break;
3960d63ce2bSvenki }
3970d63ce2bSvenki }
3980d63ce2bSvenki card->slot = atol(uaddr);
3990d63ce2bSvenki if (((1 << card->slot) & dev_mask) == 0) {
400a90d965dSfw (void) strlcpy(card->slot_str, MOTHERBOARD,
401a90d965dSfw sizeof (card->slot_str));
4020d63ce2bSvenki card->slot = -1;
4030d63ce2bSvenki } else {
4040d63ce2bSvenki char *p = (char *)(pval+sizeof (dev_mask));
4050d63ce2bSvenki int shift = sizeof (uint32_t)*8-1-card->slot;
4060d63ce2bSvenki uint32_t x = (dev_mask << shift) >> shift;
4070d63ce2bSvenki int count = 0; /* count # of 1's in x */
4080d63ce2bSvenki int i = 0;
4090d63ce2bSvenki while (x != 0) {
4100d63ce2bSvenki count++;
4110d63ce2bSvenki x &= x-1;
4120d63ce2bSvenki }
4130d63ce2bSvenki while (count > 1) {
414a90d965dSfw while (p[i++] != '\0')
415a90d965dSfw ;
4160d63ce2bSvenki count--;
4170d63ce2bSvenki }
4184c5e0fdeSvivek (void) strlcpy(card->slot_str, (char *)(p+i),
419a90d965dSfw sizeof (card->slot_str));
4200d63ce2bSvenki }
4210d63ce2bSvenki free(pval);
4220d63ce2bSvenki }
4230d63ce2bSvenki
4240d63ce2bSvenki /*
4250d63ce2bSvenki * add all io devices under pci in io list
4260d63ce2bSvenki */
4270d63ce2bSvenki /* ARGSUSED */
4280d63ce2bSvenki static int
sun4v_pci_callback(picl_nodehdl_t pcih,void * args)4290d63ce2bSvenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args)
4300d63ce2bSvenki {
4310d63ce2bSvenki char path[PICL_PROPNAMELEN_MAX];
4320d63ce2bSvenki char class[PICL_CLASSNAMELEN_MAX];
4330d63ce2bSvenki char name[PICL_PROPNAMELEN_MAX];
4340d63ce2bSvenki char model[PICL_PROPNAMELEN_MAX];
4350d63ce2bSvenki char binding_name[PICL_PROPNAMELEN_MAX];
4360d63ce2bSvenki char val[PICL_PROPNAMELEN_MAX];
4370d63ce2bSvenki char *compatible;
4380d63ce2bSvenki picl_errno_t err;
439db8f0877Sfw picl_nodehdl_t nodeh, pnodeh;
4400d63ce2bSvenki struct io_card pci_card;
4410d63ce2bSvenki
4420d63ce2bSvenki /* Walk through the children */
4430d63ce2bSvenki
4440d63ce2bSvenki err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
445a90d965dSfw sizeof (picl_nodehdl_t));
4460d63ce2bSvenki
4470d63ce2bSvenki while (err == PICL_SUCCESS) {
4480d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
449a90d965dSfw class, sizeof (class));
4500d63ce2bSvenki if (err != PICL_SUCCESS)
4510d63ce2bSvenki return (err);
4520d63ce2bSvenki
4530d63ce2bSvenki if (args) {
4540d63ce2bSvenki char *val = args;
4550d63ce2bSvenki if (strcmp(class, val) == 0) {
4560d63ce2bSvenki err = picl_get_propval_by_name(nodeh,
457a90d965dSfw PICL_PROP_PEER, &nodeh,
458a90d965dSfw sizeof (picl_nodehdl_t));
4590d63ce2bSvenki continue;
4600d63ce2bSvenki } else if (strcmp(val, PICL_CLASS_PCIEX) == 0 &&
461a90d965dSfw strcmp(class, PICL_CLASS_PCI) == 0) {
4620d63ce2bSvenki err = picl_get_propval_by_name(nodeh,
463a90d965dSfw PICL_PROP_PEER, &nodeh,
464a90d965dSfw sizeof (picl_nodehdl_t));
4650d63ce2bSvenki continue;
4660d63ce2bSvenki } else if (strcmp(val, PICL_CLASS_PCI) == 0 &&
467a90d965dSfw strcmp(class, PICL_CLASS_PCIEX) == 0) {
4680d63ce2bSvenki err = picl_get_propval_by_name(nodeh,
469a90d965dSfw PICL_PROP_PEER, &nodeh,
470a90d965dSfw sizeof (picl_nodehdl_t));
4710d63ce2bSvenki continue;
4720d63ce2bSvenki }
4730d63ce2bSvenki }
4740d63ce2bSvenki
4750d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
476a90d965dSfw path, sizeof (path));
4770d63ce2bSvenki if (err != PICL_SUCCESS)
4780d63ce2bSvenki return (err);
4790d63ce2bSvenki
4800d63ce2bSvenki (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
4810d63ce2bSvenki
482db8f0877Sfw pnodeh = nodeh;
483db8f0877Sfw err = get_slot_label(nodeh, &pci_card);
484db8f0877Sfw
485db8f0877Sfw /*
486db8f0877Sfw * No Label at this node, maybe we're looking at a device
487db8f0877Sfw * downstream of a bridge. Walk back up and find a Label and
488db8f0877Sfw * record that node in "pnodeh".
489db8f0877Sfw */
490db8f0877Sfw while (err != PICL_SUCCESS) {
491db8f0877Sfw if (err != PICL_PROPNOTFOUND)
492db8f0877Sfw break;
493db8f0877Sfw else if (picl_get_propval_by_name(pnodeh,
494db8f0877Sfw PICL_PROP_PARENT, &pnodeh, sizeof (pnodeh)) ==
495db8f0877Sfw PICL_SUCCESS)
496db8f0877Sfw err = get_slot_label(pnodeh, &pci_card);
497db8f0877Sfw else
498db8f0877Sfw break;
499db8f0877Sfw }
500db8f0877Sfw
501db8f0877Sfw /*
502db8f0877Sfw * Can't find a Label for this device in the PCI heirarchy.
503db8f0877Sfw * Try to synthesize a slot name from atoms. This depends
504db8f0877Sfw * on the OBP slot_names property being implemented, and this
505db8f0877Sfw * so far doesn't seem to be on sun4v. But just in case that
506db8f0877Sfw * is resurrected, the code is here.
507db8f0877Sfw */
508db8f0877Sfw if (err != PICL_SUCCESS) {
509db8f0877Sfw pnodeh = nodeh;
510db8f0877Sfw get_slot_number(nodeh, &pci_card);
511db8f0877Sfw }
512db8f0877Sfw
513db8f0877Sfw /*
514db8f0877Sfw * Passing in pnodeh instead of nodeh will cause prtdiag
515db8f0877Sfw * to display the type of IO slot for the leaf node. For
516db8f0877Sfw * built-in devices and a lot of IO cards these will be
517db8f0877Sfw * the same thing. But for IO cards with bridge chips or
518db8f0877Sfw * for things like expansion chassis, prtdiag will report
519db8f0877Sfw * the bus type of the IO slot and not the leaf, which
520db8f0877Sfw * could be different things.
521db8f0877Sfw */
522db8f0877Sfw get_bus_type(pnodeh, &pci_card);
5230d63ce2bSvenki
5240d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name,
525a90d965dSfw sizeof (name));
5260d63ce2bSvenki if (err == PICL_PROPNOTFOUND)
5274c5e0fdeSvivek (void) strlcpy(name, "", sizeof (name));
5280d63ce2bSvenki else if (err != PICL_SUCCESS)
5290d63ce2bSvenki return (err);
5300d63ce2bSvenki
5310d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val,
532a90d965dSfw sizeof (val));
5330d63ce2bSvenki if (err == PICL_PROPNOTFOUND)
5344c5e0fdeSvivek (void) strlcpy(val, "", sizeof (val));
5350d63ce2bSvenki else if (err != PICL_SUCCESS)
5360d63ce2bSvenki return (err);
5370d63ce2bSvenki
538dc6ca969Sfw (void) snprintf(pci_card.status, sizeof (pci_card.status),
539dc6ca969Sfw "%s", pci_card.slot_str);
5400d63ce2bSvenki
5410d63ce2bSvenki /*
5420d63ce2bSvenki * Get the name of this card. If binding_name is found,
5430d63ce2bSvenki * name will be <nodename>-<binding_name>.
5440d63ce2bSvenki */
5450d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
546a90d965dSfw binding_name, sizeof (binding_name));
5470d63ce2bSvenki if (err == PICL_SUCCESS) {
5480d63ce2bSvenki if (strcmp(name, binding_name) != 0) {
5490d63ce2bSvenki (void) strlcat(name, "-", sizeof (name));
5500d63ce2bSvenki (void) strlcat(name, binding_name,
551a90d965dSfw sizeof (name));
5520d63ce2bSvenki }
5530d63ce2bSvenki } else if (err == PICL_PROPNOTFOUND) {
5540d63ce2bSvenki /*
5550d63ce2bSvenki * if compatible prop is not found, name will be
5560d63ce2bSvenki * <nodename>-<compatible>
5570d63ce2bSvenki */
5580d63ce2bSvenki err = sun4v_get_first_compatible_value(nodeh,
559a90d965dSfw &compatible);
5600d63ce2bSvenki if (err == PICL_SUCCESS) {
5610d63ce2bSvenki (void) strlcat(name, "-", sizeof (name));
5624c5e0fdeSvivek (void) strlcat(name, compatible,
563a90d965dSfw sizeof (name));
5640d63ce2bSvenki free(compatible);
5650d63ce2bSvenki }
5660d63ce2bSvenki } else
5670d63ce2bSvenki return (err);
5680d63ce2bSvenki
5690d63ce2bSvenki (void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
5700d63ce2bSvenki
5710d63ce2bSvenki /* Get the model of this card */
5720d63ce2bSvenki
5730d63ce2bSvenki err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
574a90d965dSfw model, sizeof (model));
5750d63ce2bSvenki if (err == PICL_PROPNOTFOUND)
5764c5e0fdeSvivek (void) strlcpy(model, "", sizeof (model));
5770d63ce2bSvenki else if (err != PICL_SUCCESS)
5780d63ce2bSvenki return (err);
5790d63ce2bSvenki (void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
5800d63ce2bSvenki
5810d63ce2bSvenki /* Print NAC name */
582aaba19e2Sfw log_printf("%-18s", pci_card.status);
5830d63ce2bSvenki /* Print IO Type */
5840d63ce2bSvenki log_printf("%-6s", pci_card.bus_type);
5850d63ce2bSvenki /* Printf Card Name */
5867ae4bfcbSfw log_printf("%-34s", pci_card.name);
5870d63ce2bSvenki /* Print Card Model */
5880d63ce2bSvenki log_printf("%-8s", pci_card.model);
5890d63ce2bSvenki log_printf("\n");
5900d63ce2bSvenki /* Print Status */
591aaba19e2Sfw log_printf("%-18s", val);
5920d63ce2bSvenki /* Print IO Type */
5930d63ce2bSvenki log_printf("%-6s", "");
5940d63ce2bSvenki /* Print Parent Path */
595aaba19e2Sfw log_printf("%-44s", pci_card.notes);
5960d63ce2bSvenki log_printf("\n");
5970d63ce2bSvenki
5980d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
599a90d965dSfw sizeof (picl_nodehdl_t));
6000d63ce2bSvenki }
6010d63ce2bSvenki return (PICL_WALK_CONTINUE);
60203831d35Sstevel }
60303831d35Sstevel
60403831d35Sstevel /*
60503831d35Sstevel * display_pci
60603831d35Sstevel * Display all the PCI IO cards on this board.
60703831d35Sstevel */
60803831d35Sstevel void
sun4v_display_pci(picl_nodehdl_t plafh)60903831d35Sstevel sun4v_display_pci(picl_nodehdl_t plafh)
61003831d35Sstevel {
6117ae4bfcbSfw char *fmt = "%-17s %-5s %-33s %-8s";
6120d63ce2bSvenki /* Have we printed the column headings? */
6130d63ce2bSvenki static int banner = FALSE;
6140d63ce2bSvenki
6150d63ce2bSvenki if (banner == FALSE) {
6160d63ce2bSvenki log_printf("\n");
617aaba19e2Sfw log_printf("================================");
6180d63ce2bSvenki log_printf(" IO Devices ");
619aaba19e2Sfw log_printf("================================");
6200d63ce2bSvenki log_printf("\n");
6210d63ce2bSvenki log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0);
6220d63ce2bSvenki log_printf("\n");
6230d63ce2bSvenki log_printf(fmt, "Status", "Type", "Path", "", 0);
6240d63ce2bSvenki log_printf("\n");
6250d63ce2bSvenki log_printf("---------------------------------"
626aaba19e2Sfw "-------------------------------------------\n");
6270d63ce2bSvenki banner = TRUE;
6280d63ce2bSvenki }
6290d63ce2bSvenki
6300d63ce2bSvenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
631a90d965dSfw PICL_CLASS_PCIEX, sun4v_pci_callback);
6320d63ce2bSvenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
633a90d965dSfw PICL_CLASS_PCI, sun4v_pci_callback);
6340d63ce2bSvenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V,
635a90d965dSfw PICL_CLASS_SUN4V, sun4v_pci_callback);
63603831d35Sstevel }
63703831d35Sstevel
6380d63ce2bSvenki /*
6390d63ce2bSvenki * return the first compatible value
6400d63ce2bSvenki */
6410d63ce2bSvenki static int
sun4v_get_first_compatible_value(picl_nodehdl_t nodeh,char ** outbuf)6420d63ce2bSvenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
6430d63ce2bSvenki {
6440d63ce2bSvenki picl_errno_t err;
6450d63ce2bSvenki picl_prophdl_t proph;
6460d63ce2bSvenki picl_propinfo_t pinfo;
6470d63ce2bSvenki picl_prophdl_t tblh;
6480d63ce2bSvenki picl_prophdl_t rowproph;
6490d63ce2bSvenki char *pval;
6500d63ce2bSvenki
6510d63ce2bSvenki err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
652a90d965dSfw &pinfo, &proph);
6530d63ce2bSvenki if (err != PICL_SUCCESS)
6540d63ce2bSvenki return (err);
6550d63ce2bSvenki
6560d63ce2bSvenki if (pinfo.type == PICL_PTYPE_CHARSTRING) {
6570d63ce2bSvenki pval = malloc(pinfo.size);
6580d63ce2bSvenki if (pval == NULL)
6590d63ce2bSvenki return (PICL_FAILURE);
6600d63ce2bSvenki err = picl_get_propval(proph, pval, pinfo.size);
6610d63ce2bSvenki if (err != PICL_SUCCESS) {
6620d63ce2bSvenki free(pval);
6630d63ce2bSvenki return (err);
6640d63ce2bSvenki }
6650d63ce2bSvenki *outbuf = pval;
6660d63ce2bSvenki return (PICL_SUCCESS);
6670d63ce2bSvenki }
6680d63ce2bSvenki
6690d63ce2bSvenki if (pinfo.type != PICL_PTYPE_TABLE)
6700d63ce2bSvenki return (PICL_FAILURE);
6710d63ce2bSvenki
6720d63ce2bSvenki /* get first string from table */
6730d63ce2bSvenki err = picl_get_propval(proph, &tblh, pinfo.size);
6740d63ce2bSvenki if (err != PICL_SUCCESS)
6750d63ce2bSvenki return (err);
6760d63ce2bSvenki
6770d63ce2bSvenki err = picl_get_next_by_row(tblh, &rowproph);
6780d63ce2bSvenki if (err != PICL_SUCCESS)
6790d63ce2bSvenki return (err);
6800d63ce2bSvenki
6810d63ce2bSvenki err = picl_get_propinfo(rowproph, &pinfo);
6820d63ce2bSvenki if (err != PICL_SUCCESS)
6830d63ce2bSvenki return (err);
6840d63ce2bSvenki
6850d63ce2bSvenki pval = malloc(pinfo.size);
6860d63ce2bSvenki if (pval == NULL)
6870d63ce2bSvenki return (PICL_FAILURE);
6880d63ce2bSvenki
6890d63ce2bSvenki err = picl_get_propval(rowproph, pval, pinfo.size);
6900d63ce2bSvenki if (err != PICL_SUCCESS) {
6910d63ce2bSvenki free(pval);
6920d63ce2bSvenki return (err);
6930d63ce2bSvenki }
6940d63ce2bSvenki
6950d63ce2bSvenki *outbuf = pval;
6960d63ce2bSvenki return (PICL_SUCCESS);
6970d63ce2bSvenki }
6980d63ce2bSvenki
6990d63ce2bSvenki /*
7000d63ce2bSvenki * print size of a memory segment
7010d63ce2bSvenki */
7020d63ce2bSvenki static void
print_memory_segment_size(uint64_t size)7030d63ce2bSvenki print_memory_segment_size(uint64_t size)
7040d63ce2bSvenki {
7050d63ce2bSvenki uint64_t kbyte = 1024;
7060d63ce2bSvenki uint64_t mbyte = kbyte * kbyte;
7070d63ce2bSvenki uint64_t gbyte = kbyte * mbyte;
7087ae4bfcbSfw uint64_t tbyte = kbyte * gbyte;
7090d63ce2bSvenki char buf[MEMORY_SIZE_FIELD];
7100d63ce2bSvenki
7117ae4bfcbSfw if (size >= tbyte) {
7127ae4bfcbSfw if (size % tbyte == 0)
7137ae4bfcbSfw (void) snprintf(buf, sizeof (buf), "%d TB",
7147ae4bfcbSfw (int)(size / tbyte));
7157ae4bfcbSfw else
7167ae4bfcbSfw (void) snprintf(buf, sizeof (buf), "%.2f TB",
7177ae4bfcbSfw (float)size / tbyte);
7187ae4bfcbSfw } else if (size >= gbyte) {
7190d63ce2bSvenki if (size % gbyte == 0)
7200d63ce2bSvenki (void) snprintf(buf, sizeof (buf), "%d GB",
721a90d965dSfw (int)(size / gbyte));
7220d63ce2bSvenki else
7230d63ce2bSvenki (void) snprintf(buf, sizeof (buf), "%.2f GB",
724a90d965dSfw (float)size / gbyte);
7250d63ce2bSvenki } else if (size >= mbyte) {
7260d63ce2bSvenki if (size % mbyte == 0)
7270d63ce2bSvenki (void) snprintf(buf, sizeof (buf), "%d MB",
728a90d965dSfw (int)(size / mbyte));
7290d63ce2bSvenki else
7300d63ce2bSvenki (void) snprintf(buf, sizeof (buf), "%.2f MB",
731a90d965dSfw (float)size / mbyte);
7320d63ce2bSvenki } else {
7330d63ce2bSvenki if (size % kbyte == 0)
7340d63ce2bSvenki (void) snprintf(buf, sizeof (buf), "%d KB",
735a90d965dSfw (int)(size / kbyte));
7360d63ce2bSvenki else
7370d63ce2bSvenki (void) snprintf(buf, sizeof (buf), "%.2f KB",
738a90d965dSfw (float)size / kbyte);
7390d63ce2bSvenki }
7407ae4bfcbSfw log_printf("%-9s", buf);
7410d63ce2bSvenki }
7420d63ce2bSvenki
7430d63ce2bSvenki /*
744a90d965dSfw * Enumerate banks and dimms within a memory segment. We're handed
745a90d965dSfw * the first bank within the segment - we assume there are dimms
746a90d965dSfw * (memory-module) nodes underneath.
7470d63ce2bSvenki */
7480d63ce2bSvenki static void
print_memory_segment_contain(picl_nodehdl_t bank_nodeh)749a90d965dSfw print_memory_segment_contain(picl_nodehdl_t bank_nodeh)
7500d63ce2bSvenki {
7510d63ce2bSvenki char val[PICL_PROPNAMELEN_MAX];
752a90d965dSfw picl_nodehdl_t module_nodeh;
753a90d965dSfw int flag = 0;
7547ae4bfcbSfw uint64_t size;
755a90d965dSfw
756a90d965dSfw do {
757a90d965dSfw if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD,
758a90d965dSfw &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS)
759a90d965dSfw continue;
7607ae4bfcbSfw if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_SIZE,
7617ae4bfcbSfw &size, sizeof (size)) == PICL_SUCCESS) {
7627ae4bfcbSfw if (!flag) {
7637ae4bfcbSfw print_memory_segment_size(size);
7647ae4bfcbSfw } else {
7657ae4bfcbSfw log_printf(" "
7667ae4bfcbSfw " ");
7677ae4bfcbSfw print_memory_segment_size(size);
7687ae4bfcbSfw flag = 0;
7697ae4bfcbSfw }
7707ae4bfcbSfw }
771a90d965dSfw do {
772a90d965dSfw if (picl_get_propval_by_name(module_nodeh,
773a90d965dSfw PICL_PROP_NAC, val, sizeof (val)) !=
774a90d965dSfw PICL_SUCCESS)
775a90d965dSfw continue;
776a90d965dSfw else {
777a90d965dSfw if (!flag) {
7787ae4bfcbSfw log_printf("%s\n", val);
779a90d965dSfw flag = 1;
7807ae4bfcbSfw } else {
7817ae4bfcbSfw log_printf("%s%s\n",
7827ae4bfcbSfw " "
7837ae4bfcbSfw " ",
7847ae4bfcbSfw val);
7857ae4bfcbSfw }
786a90d965dSfw }
787a90d965dSfw } while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER,
788a90d965dSfw &module_nodeh, sizeof (picl_nodehdl_t)) ==
789a90d965dSfw PICL_SUCCESS);
790a90d965dSfw } while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER,
791a90d965dSfw &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS);
7920d63ce2bSvenki }
7930d63ce2bSvenki
7940d63ce2bSvenki /*
7950d63ce2bSvenki * Search node where _class=="memory-segment"
7960d63ce2bSvenki * print "Base Address", "Size", etc
7970d63ce2bSvenki */
7980d63ce2bSvenki /*ARGSUSED*/
7990d63ce2bSvenki static int
sun4v_memory_conf_callback(picl_nodehdl_t nodeh,void * args)8000d63ce2bSvenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args)
8010d63ce2bSvenki {
8020d63ce2bSvenki uint64_t base;
8030d63ce2bSvenki uint64_t size;
8040d63ce2bSvenki uint64_t ifactor;
8050d63ce2bSvenki picl_errno_t err = PICL_SUCCESS;
8060d63ce2bSvenki
8070d63ce2bSvenki if (class_node_found == 0) {
8080d63ce2bSvenki class_node_found = 1;
8090d63ce2bSvenki return (PICL_WALK_TERMINATE);
8100d63ce2bSvenki }
8110d63ce2bSvenki while (err == PICL_SUCCESS) {
8120d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS,
813a90d965dSfw &base, sizeof (base));
8140d63ce2bSvenki if (err != PICL_SUCCESS)
8150d63ce2bSvenki break;
8160d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE,
817a90d965dSfw &size, sizeof (size));
8180d63ce2bSvenki if (err != PICL_SUCCESS)
8190d63ce2bSvenki break;
8200d63ce2bSvenki err = picl_get_propval_by_name(nodeh,
821a90d965dSfw PICL_PROP_INTERLEAVE_FACTOR, &ifactor,
822a90d965dSfw sizeof (ifactor));
8230d63ce2bSvenki if (err != PICL_SUCCESS)
8240d63ce2bSvenki break;
8257ae4bfcbSfw log_printf("0x%-13llx", base);
8260d63ce2bSvenki print_memory_segment_size(size);
8277ae4bfcbSfw log_printf("%-12lld", ifactor);
828a90d965dSfw err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
829a90d965dSfw &nodeh, sizeof (nodeh));
830a90d965dSfw if (err == PICL_SUCCESS)
831a90d965dSfw print_memory_segment_contain(nodeh);
8320d63ce2bSvenki log_printf("\n");
8330d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
834a90d965dSfw sizeof (picl_nodehdl_t));
8350d63ce2bSvenki }
8360d63ce2bSvenki
8370d63ce2bSvenki return (PICL_WALK_CONTINUE);
8380d63ce2bSvenki }
8390d63ce2bSvenki
8400d63ce2bSvenki /*ARGSUSED*/
84103831d35Sstevel void
sun4v_display_memory_conf(picl_nodehdl_t plafh)8420d63ce2bSvenki sun4v_display_memory_conf(picl_nodehdl_t plafh)
84303831d35Sstevel {
8447ae4bfcbSfw char *fmt = "%-14s %-8s %-11s %-8s %-s";
8450d63ce2bSvenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
846a90d965dSfw NULL, sun4v_memory_conf_callback);
8470d63ce2bSvenki if (class_node_found == 0)
8480d63ce2bSvenki return;
8490d63ce2bSvenki log_printf("\n");
8507ae4bfcbSfw log_printf("=======================");
8517ae4bfcbSfw log_printf(" Physical Memory Configuration ");
8527ae4bfcbSfw log_printf("========================");
8530d63ce2bSvenki log_printf("\n");
8540d63ce2bSvenki log_printf("Segment Table:\n");
855a90d965dSfw log_printf(
8567ae4bfcbSfw "--------------------------------------------------------------\n");
8577ae4bfcbSfw log_printf(fmt, "Base", "Segment", "Interleave", "Bank", "Contains", 0);
8587ae4bfcbSfw log_printf("\n");
8597ae4bfcbSfw log_printf(fmt, "Address", "Size", "Factor", "Size", "Modules", 0);
8600d63ce2bSvenki log_printf("\n");
861a90d965dSfw log_printf(
8627ae4bfcbSfw "--------------------------------------------------------------\n");
8630d63ce2bSvenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
864a90d965dSfw NULL, sun4v_memory_conf_callback);
86503831d35Sstevel }
86603831d35Sstevel
86703831d35Sstevel void
sun4v_display_cpu_devices(picl_nodehdl_t plafh)86803831d35Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh)
86903831d35Sstevel {
8707ae4bfcbSfw char *fmt = "%-6s %-9s %-22s %-6s";
87103831d35Sstevel
87203831d35Sstevel /*
87303831d35Sstevel * Display the table header for CPUs . Then display the CPU
87403831d35Sstevel * frequency, cache size, and processor revision of all cpus.
87503831d35Sstevel */
87603831d35Sstevel log_printf(dgettext(TEXT_DOMAIN,
877a90d965dSfw "\n"
8787ae4bfcbSfw "================================"
8797ae4bfcbSfw " Virtual CPUs "
8807ae4bfcbSfw "================================"
881a90d965dSfw "\n"
882a90d965dSfw "\n"));
88303831d35Sstevel log_printf("\n");
8847ae4bfcbSfw log_printf(fmt, "CPU ID", "Frequency", "Implementation",
8857ae4bfcbSfw "Status", 0);
88603831d35Sstevel log_printf("\n");
8877ae4bfcbSfw log_printf(fmt, "------", "---------",
8887ae4bfcbSfw "----------------------", "-------", 0);
88903831d35Sstevel log_printf("\n");
89003831d35Sstevel
8917ae4bfcbSfw (void) picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU,
8927ae4bfcbSfw sun4v_display_cpus);
89303831d35Sstevel }
89403831d35Sstevel
89503831d35Sstevel /*
89603831d35Sstevel * Display the CPUs present on this board.
89703831d35Sstevel */
89803831d35Sstevel /*ARGSUSED*/
89903831d35Sstevel int
sun4v_display_cpus(picl_nodehdl_t cpuh,void * args)90003831d35Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
90103831d35Sstevel {
90203831d35Sstevel int status;
9030d63ce2bSvenki picl_prophdl_t proph;
9040d63ce2bSvenki picl_prophdl_t tblh;
9050d63ce2bSvenki picl_prophdl_t rowproph;
90603831d35Sstevel picl_propinfo_t propinfo;
9070d63ce2bSvenki int *int_value;
9085e3e415aSfw int cpuid;
9090d63ce2bSvenki char *comp_value;
9100d63ce2bSvenki char *no_prop_value = " ";
9110d63ce2bSvenki char freq_str[MAXSTRLEN];
9125e3e415aSfw char state[MAXSTRLEN];
91303831d35Sstevel
91403831d35Sstevel /*
91503831d35Sstevel * Get cpuid property and print it and the NAC name
91603831d35Sstevel */
9177ae4bfcbSfw status = picl_get_propinfo_by_name(cpuh, OBP_PROP_CPUID, &propinfo,
9187ae4bfcbSfw &proph);
91903831d35Sstevel if (status == PICL_SUCCESS) {
92003831d35Sstevel status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
92103831d35Sstevel if (status != PICL_SUCCESS) {
9227ae4bfcbSfw log_printf("%-7s", no_prop_value);
92303831d35Sstevel } else {
9247ae4bfcbSfw log_printf("%-7d", cpuid);
92503831d35Sstevel }
92603831d35Sstevel } else {
9277ae4bfcbSfw log_printf("%-7s", no_prop_value);
92803831d35Sstevel }
92903831d35Sstevel
93003831d35Sstevel clock_freq:
93103831d35Sstevel status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
932a90d965dSfw &proph);
93303831d35Sstevel if (status == PICL_SUCCESS) {
93403831d35Sstevel int_value = malloc(propinfo.size);
93503831d35Sstevel if (int_value == NULL) {
9367ae4bfcbSfw log_printf("%-10s", no_prop_value);
93703831d35Sstevel goto compatible;
93803831d35Sstevel }
93903831d35Sstevel status = picl_get_propval(proph, int_value, propinfo.size);
94003831d35Sstevel if (status != PICL_SUCCESS) {
9417ae4bfcbSfw log_printf("%-10s", no_prop_value);
94203831d35Sstevel } else {
94303831d35Sstevel /* Running frequency */
94403831d35Sstevel (void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
94503831d35Sstevel CLK_FREQ_TO_MHZ(*int_value));
9467ae4bfcbSfw log_printf("%-10s", freq_str);
94703831d35Sstevel }
94803831d35Sstevel free(int_value);
94903831d35Sstevel } else
9507ae4bfcbSfw log_printf("%-10s", no_prop_value);
95103831d35Sstevel
95203831d35Sstevel compatible:
95303831d35Sstevel status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
954a90d965dSfw &proph);
95503831d35Sstevel if (status == PICL_SUCCESS) {
95603831d35Sstevel if (propinfo.type == PICL_PTYPE_CHARSTRING) {
95703831d35Sstevel /*
95803831d35Sstevel * Compatible Property only has 1 value
95903831d35Sstevel */
96003831d35Sstevel comp_value = malloc(propinfo.size);
96103831d35Sstevel if (comp_value == NULL) {
9627ae4bfcbSfw log_printf("%-23s", no_prop_value, 0);
9635e3e415aSfw goto state;
96403831d35Sstevel }
96503831d35Sstevel status = picl_get_propval(proph, comp_value,
966a90d965dSfw propinfo.size);
9670d63ce2bSvenki if (status != PICL_SUCCESS)
9687ae4bfcbSfw log_printf("%-23s", no_prop_value, 0);
9690d63ce2bSvenki else
9707ae4bfcbSfw log_printf("%-23s", comp_value, 0);
9710d63ce2bSvenki free(comp_value);
97203831d35Sstevel } else if (propinfo.type == PICL_PTYPE_TABLE) {
97303831d35Sstevel /*
97403831d35Sstevel * Compatible Property has multiple values
97503831d35Sstevel */
97603831d35Sstevel status = picl_get_propval(proph, &tblh, propinfo.size);
97703831d35Sstevel if (status != PICL_SUCCESS) {
9787ae4bfcbSfw log_printf("%-23s", no_prop_value, 0);
9795e3e415aSfw goto state;
98003831d35Sstevel }
98103831d35Sstevel status = picl_get_next_by_row(tblh, &rowproph);
98203831d35Sstevel if (status != PICL_SUCCESS) {
9837ae4bfcbSfw log_printf("%-23s", no_prop_value, 0);
9845e3e415aSfw goto state;
98503831d35Sstevel }
98603831d35Sstevel
98703831d35Sstevel status = picl_get_propinfo(rowproph, &propinfo);
98803831d35Sstevel if (status != PICL_SUCCESS) {
9897ae4bfcbSfw log_printf("%-23s", no_prop_value, 0);
9905e3e415aSfw goto state;
99103831d35Sstevel }
99203831d35Sstevel
99303831d35Sstevel comp_value = malloc(propinfo.size);
99403831d35Sstevel if (comp_value == NULL) {
9957ae4bfcbSfw log_printf("%-23s", no_prop_value, 0);
9965e3e415aSfw goto state;
99703831d35Sstevel }
99803831d35Sstevel status = picl_get_propval(rowproph, comp_value,
999a90d965dSfw propinfo.size);
10000d63ce2bSvenki if (status != PICL_SUCCESS)
10017ae4bfcbSfw log_printf("%-23s", no_prop_value, 0);
10020d63ce2bSvenki else
10037ae4bfcbSfw log_printf("%-23s", comp_value, 0);
100403831d35Sstevel free(comp_value);
100503831d35Sstevel }
100603831d35Sstevel } else
10077ae4bfcbSfw log_printf("%-23s", no_prop_value, 0);
100803831d35Sstevel
10095e3e415aSfw state:
10105e3e415aSfw status = picl_get_propinfo_by_name(cpuh, PICL_PROP_STATE,
10115e3e415aSfw &propinfo, &proph);
101203831d35Sstevel if (status == PICL_SUCCESS) {
10135e3e415aSfw status = picl_get_propval(proph, state, sizeof (state));
101403831d35Sstevel if (status != PICL_SUCCESS) {
10150d63ce2bSvenki log_printf("%-9s", no_prop_value);
101603831d35Sstevel } else {
10175e3e415aSfw log_printf("%-9s", state);
101803831d35Sstevel }
101903831d35Sstevel } else
10200d63ce2bSvenki log_printf("%-9s", no_prop_value);
102103831d35Sstevel
102203831d35Sstevel done:
102303831d35Sstevel log_printf("\n");
102403831d35Sstevel return (PICL_WALK_CONTINUE);
102503831d35Sstevel }
102603831d35Sstevel
102703831d35Sstevel void
sun4v_display_diaginfo(int flag,Prom_node * root,picl_nodehdl_t plafh)102803831d35Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
102903831d35Sstevel {
103003831d35Sstevel #ifdef lint
103103831d35Sstevel flag = flag;
103203831d35Sstevel root = root;
103303831d35Sstevel plafh = plafh;
103403831d35Sstevel #endif
103503831d35Sstevel /*
103603831d35Sstevel * This function is intentionally empty
103703831d35Sstevel */
103803831d35Sstevel }
103903831d35Sstevel
104003831d35Sstevel void
display_boardnum(int num)104103831d35Sstevel display_boardnum(int num)
104203831d35Sstevel {
104303831d35Sstevel log_printf("%2d ", num, 0);
104403831d35Sstevel }
10450d63ce2bSvenki
1046d776656fSmb static int
sun4v_disp_env_status()10470d63ce2bSvenki sun4v_disp_env_status()
10480d63ce2bSvenki {
1049d776656fSmb int exit_code = 0;
1050d776656fSmb
10510d63ce2bSvenki if (phyplatformh == 0)
1052d776656fSmb return (0);
10530d63ce2bSvenki log_printf("\n");
10540d63ce2bSvenki log_printf("============================");
10550d63ce2bSvenki log_printf(" Environmental Status ");
10560d63ce2bSvenki log_printf("============================");
10570d63ce2bSvenki log_printf("\n");
10580d63ce2bSvenki
10590d63ce2bSvenki class_node_found = 0;
10600d63ce2bSvenki all_status_ok = 1;
10610d63ce2bSvenki sun4v_env_print_fan_sensors();
1062d776656fSmb exit_code |= (!all_status_ok);
10630d63ce2bSvenki
10640d63ce2bSvenki class_node_found = 0;
10650d63ce2bSvenki all_status_ok = 1;
10660d63ce2bSvenki sun4v_env_print_fan_indicators();
1067d776656fSmb exit_code |= (!all_status_ok);
10680d63ce2bSvenki
10690d63ce2bSvenki class_node_found = 0;
10700d63ce2bSvenki all_status_ok = 1;
10710d63ce2bSvenki sun4v_env_print_temp_sensors();
1072d776656fSmb exit_code |= (!all_status_ok);
10730d63ce2bSvenki
10740d63ce2bSvenki class_node_found = 0;
10750d63ce2bSvenki all_status_ok = 1;
10760d63ce2bSvenki sun4v_env_print_temp_indicators();
1077d776656fSmb exit_code |= (!all_status_ok);
10780d63ce2bSvenki
10790d63ce2bSvenki class_node_found = 0;
10800d63ce2bSvenki all_status_ok = 1;
10810d63ce2bSvenki sun4v_env_print_current_sensors();
1082d776656fSmb exit_code |= (!all_status_ok);
10830d63ce2bSvenki
10840d63ce2bSvenki class_node_found = 0;
10850d63ce2bSvenki all_status_ok = 1;
10860d63ce2bSvenki sun4v_env_print_current_indicators();
1087d776656fSmb exit_code |= (!all_status_ok);
10880d63ce2bSvenki
10890d63ce2bSvenki class_node_found = 0;
10900d63ce2bSvenki all_status_ok = 1;
10910d63ce2bSvenki sun4v_env_print_voltage_sensors();
1092d776656fSmb exit_code |= (!all_status_ok);
10930d63ce2bSvenki
10940d63ce2bSvenki class_node_found = 0;
10950d63ce2bSvenki all_status_ok = 1;
10960d63ce2bSvenki sun4v_env_print_voltage_indicators();
1097d776656fSmb exit_code |= (!all_status_ok);
10980d63ce2bSvenki
10990d63ce2bSvenki class_node_found = 0;
1100d776656fSmb all_status_ok = 1;
11010d63ce2bSvenki sun4v_env_print_LEDs();
1102d776656fSmb exit_code |= (!all_status_ok);
11030d63ce2bSvenki
11040d63ce2bSvenki class_node_found = 0;
11050d63ce2bSvenki all_status_ok = 1;
11060d63ce2bSvenki sun4v_print_fru_status();
1107d776656fSmb exit_code |= (!all_status_ok);
11080d63ce2bSvenki
11090d63ce2bSvenki class_node_found = 0;
11100d63ce2bSvenki sun4v_print_fw_rev();
11110d63ce2bSvenki
1112dc6ca969Sfw class_node_found = 0;
1113dc6ca969Sfw sun4v_print_openprom_rev();
1114dc6ca969Sfw
11150d63ce2bSvenki sun4v_print_chassis_serial_no();
1116d776656fSmb
1117d776656fSmb return (exit_code);
11180d63ce2bSvenki }
11190d63ce2bSvenki
11200d63ce2bSvenki /*ARGSUSED*/
11210d63ce2bSvenki static int
sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh,void * args)11220d63ce2bSvenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args)
11230d63ce2bSvenki {
11240d63ce2bSvenki char val[PICL_PROPNAMELEN_MAX];
11250d63ce2bSvenki picl_nodehdl_t parenth;
11260d63ce2bSvenki char *names[PARENT_NAMES];
1127aaba19e2Sfw char *base_units[PICL_PROPNAMELEN_MAX];
11280d63ce2bSvenki char *loc;
11290d63ce2bSvenki int i;
11300d63ce2bSvenki char *prop;
11310d63ce2bSvenki picl_errno_t err;
1132dc6ca969Sfw int32_t lo_warning, lo_shutdown, lo_poweroff;
1133dc6ca969Sfw int32_t hi_warning, hi_shutdown, hi_poweroff;
11340d63ce2bSvenki int32_t current_val;
1135aaba19e2Sfw int32_t exponent;
1136aaba19e2Sfw double display_val;
1137a42ff480Sfw typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
1138a42ff480Sfw SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
1139a42ff480Sfw sensor_status_t sensor_status = SENSOR_OK;
11400d63ce2bSvenki
11410d63ce2bSvenki if (class_node_found == 0) {
11420d63ce2bSvenki class_node_found = 1;
11430d63ce2bSvenki return (PICL_WALK_TERMINATE);
11440d63ce2bSvenki }
11450d63ce2bSvenki
1146a42ff480Sfw prop = (char *)args;
1147a42ff480Sfw if (!prop) {
1148a42ff480Sfw sensor_status = SENSOR_UNKNOWN;
1149a42ff480Sfw all_status_ok = 0;
1150a42ff480Sfw } else {
11510d63ce2bSvenki err = picl_get_propval_by_name(nodeh,
1152a90d965dSfw PICL_PROP_OPERATIONAL_STATUS, val,
1153a90d965dSfw sizeof (val));
11540d63ce2bSvenki if (err == PICL_SUCCESS) {
11550d63ce2bSvenki if (strcmp(val, "disabled") == 0) {
1156a42ff480Sfw sensor_status = SENSOR_DISABLED;
1157a42ff480Sfw }
1158a42ff480Sfw }
1159a42ff480Sfw }
1160a42ff480Sfw
1161a42ff480Sfw if (sensor_status != SENSOR_DISABLED &&
1162a42ff480Sfw sensor_status != SENSOR_UNKNOWN) {
1163a42ff480Sfw if (picl_get_propval_by_name(nodeh, prop, ¤t_val,
1164a42ff480Sfw sizeof (current_val)) != PICL_SUCCESS) {
1165a42ff480Sfw sensor_status = SENSOR_UNKNOWN;
11660d63ce2bSvenki } else {
1167dc6ca969Sfw if (picl_get_propval_by_name(nodeh,
1168dc6ca969Sfw PICL_PROP_LOW_WARNING,
1169dc6ca969Sfw &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS)
1170dc6ca969Sfw lo_warning = INVALID_THRESHOLD;
1171dc6ca969Sfw if (picl_get_propval_by_name(nodeh,
1172dc6ca969Sfw PICL_PROP_LOW_SHUTDOWN,
1173dc6ca969Sfw &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS)
1174dc6ca969Sfw lo_shutdown = INVALID_THRESHOLD;
1175dc6ca969Sfw if (picl_get_propval_by_name(nodeh,
1176dc6ca969Sfw PICL_PROP_LOW_POWER_OFF,
1177dc6ca969Sfw &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS)
1178dc6ca969Sfw lo_poweroff = INVALID_THRESHOLD;
1179dc6ca969Sfw if (picl_get_propval_by_name(nodeh,
1180dc6ca969Sfw PICL_PROP_HIGH_WARNING,
1181dc6ca969Sfw &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS)
1182dc6ca969Sfw hi_warning = INVALID_THRESHOLD;
1183dc6ca969Sfw if (picl_get_propval_by_name(nodeh,
1184dc6ca969Sfw PICL_PROP_HIGH_SHUTDOWN,
1185dc6ca969Sfw &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS)
1186dc6ca969Sfw hi_shutdown = INVALID_THRESHOLD;
1187dc6ca969Sfw if (picl_get_propval_by_name(nodeh,
1188dc6ca969Sfw PICL_PROP_HIGH_POWER_OFF,
1189dc6ca969Sfw &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS)
1190dc6ca969Sfw hi_poweroff = INVALID_THRESHOLD;
1191dc6ca969Sfw
1192dc6ca969Sfw if ((lo_poweroff != INVALID_THRESHOLD &&
1193dc6ca969Sfw current_val <= lo_poweroff) ||
1194dc6ca969Sfw (hi_poweroff != INVALID_THRESHOLD &&
1195dc6ca969Sfw current_val >= hi_poweroff)) {
1196dc6ca969Sfw sensor_status = SENSOR_FAILED;
1197dc6ca969Sfw } else if ((lo_shutdown != INVALID_THRESHOLD &&
1198dc6ca969Sfw current_val <= lo_shutdown) ||
1199dc6ca969Sfw (hi_shutdown != INVALID_THRESHOLD &&
1200dc6ca969Sfw current_val >= hi_shutdown)) {
1201dc6ca969Sfw sensor_status = SENSOR_FAILED;
1202dc6ca969Sfw } else if ((lo_warning != INVALID_THRESHOLD &&
1203dc6ca969Sfw current_val <= lo_warning) ||
1204dc6ca969Sfw (hi_warning != INVALID_THRESHOLD &&
1205dc6ca969Sfw current_val >= hi_warning)) {
1206dc6ca969Sfw sensor_status = SENSOR_WARN;
1207dc6ca969Sfw } else {
1208dc6ca969Sfw sensor_status = SENSOR_OK;
1209dc6ca969Sfw }
1210a42ff480Sfw }
1211a42ff480Sfw }
1212a42ff480Sfw
1213a42ff480Sfw if (syserrlog == 0) {
1214a42ff480Sfw if (sensor_status != SENSOR_OK && all_status_ok == 1) {
12150d63ce2bSvenki all_status_ok = 0;
12160d63ce2bSvenki return (PICL_WALK_TERMINATE);
12170d63ce2bSvenki }
1218a42ff480Sfw if (sensor_status == SENSOR_OK) {
1219a42ff480Sfw return (PICL_WALK_CONTINUE);
1220a42ff480Sfw }
12217ae8c7a8SMichael Bergknoff } else {
12227ae8c7a8SMichael Bergknoff if (sensor_status != SENSOR_OK && all_status_ok == 1) {
12237ae8c7a8SMichael Bergknoff all_status_ok = 0;
12247ae8c7a8SMichael Bergknoff }
12250d63ce2bSvenki }
1226a42ff480Sfw
1227a42ff480Sfw /*
1228a42ff480Sfw * If we're here then prtdiag was invoked with "-v" or we have
1229a42ff480Sfw * a sensor that is beyond a threshold, so give them a book to
1230a42ff480Sfw * read instead of the Cliff Notes.
1231a42ff480Sfw */
12320d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1233a90d965dSfw sizeof (parenth));
12340d63ce2bSvenki if (err != PICL_SUCCESS) {
12350d63ce2bSvenki log_printf("\n");
12360d63ce2bSvenki return (PICL_WALK_CONTINUE);
12370d63ce2bSvenki }
12384c5e0fdeSvivek
1239a42ff480Sfw /* gather up the path name for the sensor */
1240a42ff480Sfw if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
1241a42ff480Sfw for (i = 0; i < PARENT_NAMES; i++) {
1242a42ff480Sfw if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
1243a42ff480Sfw NULL) {
1244a42ff480Sfw while (--i > -1)
1245a42ff480Sfw free(names[i]);
1246a42ff480Sfw free(loc);
1247a42ff480Sfw loc = NULL;
1248a42ff480Sfw }
12490d63ce2bSvenki }
1250a42ff480Sfw }
12510d63ce2bSvenki i = 0;
1252a42ff480Sfw if (loc != 0) {
1253a42ff480Sfw while (err == PICL_SUCCESS) {
1254a42ff480Sfw if (parenth == phyplatformh)
1255a42ff480Sfw break;
1256a42ff480Sfw err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1257a42ff480Sfw names[i++], PICL_PROPNAMELEN_MAX);
1258a42ff480Sfw if (err != PICL_SUCCESS) {
1259a42ff480Sfw i--;
1260a42ff480Sfw break;
1261a42ff480Sfw }
1262a42ff480Sfw if (i == PARENT_NAMES)
1263a42ff480Sfw break;
1264a42ff480Sfw err = picl_get_propval_by_name(parenth,
1265a42ff480Sfw PICL_PROP_PARENT, &parenth, sizeof (parenth));
12660d63ce2bSvenki }
1267a42ff480Sfw loc[0] = '\0';
1268a42ff480Sfw if (--i > -1) {
1269a42ff480Sfw (void) strlcat(loc, names[i],
1270a42ff480Sfw PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1271a42ff480Sfw }
1272a42ff480Sfw while (--i > -1) {
1273a42ff480Sfw (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
1274a42ff480Sfw PARENT_NAMES);
1275a42ff480Sfw (void) strlcat(loc, names[i],
1276a42ff480Sfw PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1277a42ff480Sfw }
12785e3e415aSfw log_printf("%-35s", loc);
1279a42ff480Sfw for (i = 0; i < PARENT_NAMES; i++)
1280a42ff480Sfw free(names[i]);
1281a42ff480Sfw free(loc);
1282a42ff480Sfw } else {
12835e3e415aSfw log_printf("%-35s", " ");
12840d63ce2bSvenki }
12850d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
1286a90d965dSfw sizeof (val));
12870d63ce2bSvenki if (err == PICL_SUCCESS)
1288bbda49b5SSree Vemuri log_printf("%-19s", val);
12890d63ce2bSvenki
1290a42ff480Sfw /*
1291a42ff480Sfw * Get the exponent if present, and do a little math so that
1292a42ff480Sfw * if we need to we can print a normalized value for the
1293a42ff480Sfw * sensor reading.
1294a42ff480Sfw */
1295aaba19e2Sfw if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT,
1296aaba19e2Sfw &exponent, sizeof (exponent)) != PICL_SUCCESS)
1297aaba19e2Sfw exponent = 0;
1298aaba19e2Sfw if (exponent == 0)
1299aaba19e2Sfw display_val = (double)current_val;
1300dc6ca969Sfw else {
1301aaba19e2Sfw display_val = (double)current_val *
1302aaba19e2Sfw pow((double)10, (double)exponent);
1303dc6ca969Sfw
1304dc6ca969Sfw /*
1305dc6ca969Sfw * Sometimes ILOM will scale a sensor reading but
1306dc6ca969Sfw * there will be nothing to the right of the decimal
1307dc6ca969Sfw * once that value is normalized. Setting the
1308dc6ca969Sfw * exponent to zero will prevent the printf below
1309dc6ca969Sfw * from printing extraneous zeros. Otherwise a
1310dc6ca969Sfw * negative exponent is used to set the precision
1311dc6ca969Sfw * for the printf.
1312dc6ca969Sfw */
1313dc6ca969Sfw if ((int)display_val == display_val || exponent > 0)
1314dc6ca969Sfw exponent = 0;
1315dc6ca969Sfw }
1316dc6ca969Sfw
1317a42ff480Sfw err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS,
1318a42ff480Sfw base_units, sizeof (base_units));
1319aaba19e2Sfw if (err != PICL_SUCCESS)
1320aaba19e2Sfw base_units[0] = '\0';
13210d63ce2bSvenki
1322a42ff480Sfw switch (sensor_status) {
1323a42ff480Sfw case SENSOR_FAILED:
13240d63ce2bSvenki log_printf("%-s", "failed (");
1325aaba19e2Sfw log_printf("%-.*f", abs(exponent), display_val);
1326aaba19e2Sfw log_printf("%-s %s", base_units, ")");
1327a42ff480Sfw break;
1328a42ff480Sfw case SENSOR_WARN:
13290d63ce2bSvenki log_printf("%-s", "warning (");
1330aaba19e2Sfw log_printf("%-.*f", abs(exponent), display_val);
1331aaba19e2Sfw log_printf("%-s %s", base_units, ")");
1332a42ff480Sfw break;
1333a42ff480Sfw case SENSOR_DISABLED:
1334a42ff480Sfw log_printf("%-s", "disabled");
1335a42ff480Sfw break;
1336a42ff480Sfw case SENSOR_OK:
13370d63ce2bSvenki log_printf("%-s", "ok");
1338a42ff480Sfw break;
1339a42ff480Sfw default:
1340a42ff480Sfw log_printf("%-s", "unknown");
1341a42ff480Sfw break;
1342a42ff480Sfw }
13430d63ce2bSvenki
13440d63ce2bSvenki log_printf("\n");
13450d63ce2bSvenki return (PICL_WALK_CONTINUE);
13460d63ce2bSvenki }
13470d63ce2bSvenki
13480d63ce2bSvenki /*ARGSUSED*/
13490d63ce2bSvenki static int
sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh,void * args)13500d63ce2bSvenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args)
13510d63ce2bSvenki {
1352a42ff480Sfw char current_val[PICL_PROPNAMELEN_MAX];
1353a42ff480Sfw char expected_val[PICL_PROPNAMELEN_MAX];
1354a42ff480Sfw char label[PICL_PROPNAMELEN_MAX];
13550d63ce2bSvenki picl_nodehdl_t parenth;
13560d63ce2bSvenki char *names[PARENT_NAMES];
13570d63ce2bSvenki char *loc;
13580d63ce2bSvenki int i = 0;
13590d63ce2bSvenki char *prop = (char *)args;
13600d63ce2bSvenki picl_errno_t err = PICL_SUCCESS;
1361a42ff480Sfw typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
1362a42ff480Sfw SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
1363a42ff480Sfw sensor_status_t sensor_status = SENSOR_OK;
13640d63ce2bSvenki
13650d63ce2bSvenki if (class_node_found == 0) {
13660d63ce2bSvenki class_node_found = 1;
13670d63ce2bSvenki return (PICL_WALK_TERMINATE);
13680d63ce2bSvenki }
1369a42ff480Sfw
1370a42ff480Sfw prop = (char *)args;
1371a42ff480Sfw if (!prop) {
1372a42ff480Sfw sensor_status = SENSOR_UNKNOWN;
1373a42ff480Sfw all_status_ok = 0;
1374a42ff480Sfw } else {
13750d63ce2bSvenki err = picl_get_propval_by_name(nodeh,
1376a42ff480Sfw PICL_PROP_OPERATIONAL_STATUS, current_val,
1377a42ff480Sfw sizeof (current_val));
13780d63ce2bSvenki if (err == PICL_SUCCESS) {
1379a42ff480Sfw if (strcmp(current_val, "disabled") == 0) {
1380a42ff480Sfw sensor_status = SENSOR_DISABLED;
1381a42ff480Sfw }
1382a42ff480Sfw }
1383a42ff480Sfw }
1384a42ff480Sfw
1385a42ff480Sfw if (sensor_status != SENSOR_DISABLED &&
1386a42ff480Sfw sensor_status != SENSOR_UNKNOWN) {
1387a42ff480Sfw if (picl_get_propval_by_name(nodeh, prop, ¤t_val,
1388a42ff480Sfw sizeof (current_val)) != PICL_SUCCESS) {
1389a42ff480Sfw (void) strlcpy(current_val, "unknown",
1390a42ff480Sfw sizeof (current_val));
1391a42ff480Sfw sensor_status = SENSOR_UNKNOWN;
13920d63ce2bSvenki } else {
1393a42ff480Sfw if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED,
13947ae8c7a8SMichael Bergknoff &expected_val, sizeof (expected_val)) ==
1395a42ff480Sfw PICL_SUCCESS) {
1396a42ff480Sfw if (strncmp(current_val, expected_val,
1397a42ff480Sfw sizeof (current_val)) == 0) {
1398a42ff480Sfw sensor_status = SENSOR_OK;
1399a42ff480Sfw } else {
1400a42ff480Sfw sensor_status = SENSOR_FAILED;
1401a42ff480Sfw }
1402a42ff480Sfw }
1403a42ff480Sfw }
1404a42ff480Sfw }
1405a42ff480Sfw
1406a42ff480Sfw if (syserrlog == 0) {
1407a42ff480Sfw if (sensor_status != SENSOR_OK && all_status_ok == 1) {
14080d63ce2bSvenki all_status_ok = 0;
14090d63ce2bSvenki return (PICL_WALK_TERMINATE);
14100d63ce2bSvenki }
1411a42ff480Sfw if (sensor_status == SENSOR_OK) {
1412a42ff480Sfw return (PICL_WALK_CONTINUE);
1413a42ff480Sfw }
14147ae8c7a8SMichael Bergknoff } else {
14157ae8c7a8SMichael Bergknoff if (sensor_status != SENSOR_OK && all_status_ok == 1) {
14167ae8c7a8SMichael Bergknoff all_status_ok = 0;
14177ae8c7a8SMichael Bergknoff }
14180d63ce2bSvenki }
1419a42ff480Sfw
1420a42ff480Sfw /*
1421a42ff480Sfw * If we're here then prtdiag was invoked with "-v" or we have
1422a42ff480Sfw * a sensor that is beyond a threshold, so give them a book to
1423a42ff480Sfw * read instead of the Cliff Notes.
1424a42ff480Sfw */
14250d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1426a90d965dSfw sizeof (parenth));
14270d63ce2bSvenki if (err != PICL_SUCCESS) {
14280d63ce2bSvenki log_printf("\n");
14290d63ce2bSvenki return (PICL_WALK_CONTINUE);
14300d63ce2bSvenki }
1431a42ff480Sfw if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
1432a42ff480Sfw for (i = 0; i < PARENT_NAMES; i++) {
1433a42ff480Sfw if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
1434a42ff480Sfw NULL) {
1435a42ff480Sfw while (--i > -1)
1436a42ff480Sfw free(names[i]);
1437a42ff480Sfw free(loc);
1438a42ff480Sfw loc = NULL;
1439a42ff480Sfw }
14400d63ce2bSvenki }
1441a42ff480Sfw }
14420d63ce2bSvenki i = 0;
1443a42ff480Sfw if (loc) {
1444a42ff480Sfw while (err == PICL_SUCCESS) {
1445a42ff480Sfw if (parenth == phyplatformh)
1446a42ff480Sfw break;
1447a42ff480Sfw err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1448a42ff480Sfw names[i++], PICL_PROPNAMELEN_MAX);
1449a42ff480Sfw if (err != PICL_SUCCESS) {
1450a42ff480Sfw i--;
1451a42ff480Sfw break;
1452a42ff480Sfw }
1453a42ff480Sfw if (i == PARENT_NAMES)
1454a42ff480Sfw break;
1455a42ff480Sfw err = picl_get_propval_by_name(parenth,
1456a42ff480Sfw PICL_PROP_PARENT, &parenth, sizeof (parenth));
14570d63ce2bSvenki }
1458a42ff480Sfw loc[0] = '\0';
1459a42ff480Sfw if (--i > -1) {
1460a42ff480Sfw (void) strlcat(loc, names[i],
1461a42ff480Sfw PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1462a42ff480Sfw }
1463a42ff480Sfw while (--i > -1) {
1464a42ff480Sfw (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
1465a42ff480Sfw PARENT_NAMES);
1466a42ff480Sfw (void) strlcat(loc, names[i],
1467a42ff480Sfw PICL_PROPNAMELEN_MAX * PARENT_NAMES);
1468a42ff480Sfw }
14695e3e415aSfw log_printf("%-35s", loc);
1470a42ff480Sfw for (i = 0; i < PARENT_NAMES; i++)
1471a42ff480Sfw free(names[i]);
1472a42ff480Sfw free(loc);
1473a42ff480Sfw } else {
14745e3e415aSfw log_printf("%-35s", "");
14750d63ce2bSvenki }
1476a42ff480Sfw
1477a42ff480Sfw err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1478a42ff480Sfw sizeof (label));
1479a42ff480Sfw if (err != PICL_SUCCESS)
1480a42ff480Sfw (void) strlcpy(label, "", sizeof (label));
1481bbda49b5SSree Vemuri log_printf("%-19s", label);
1482a42ff480Sfw
1483a42ff480Sfw log_printf("%-8s", current_val);
1484a42ff480Sfw
14850d63ce2bSvenki log_printf("\n");
14860d63ce2bSvenki return (PICL_WALK_CONTINUE);
14870d63ce2bSvenki }
14880d63ce2bSvenki
14890d63ce2bSvenki static void
sun4v_env_print_fan_sensors()14900d63ce2bSvenki sun4v_env_print_fan_sensors()
14910d63ce2bSvenki {
1492bbda49b5SSree Vemuri char *fmt = "%-34s %-18s %-10s\n";
14930d63ce2bSvenki /*
14940d63ce2bSvenki * If there isn't any fan sensor node, return now.
14950d63ce2bSvenki */
14960d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1497a42ff480Sfw PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED,
1498a90d965dSfw sun4v_env_print_sensor_callback);
14990d63ce2bSvenki if (!class_node_found)
15000d63ce2bSvenki return;
15010d63ce2bSvenki log_printf("Fan sensors:\n");
15020d63ce2bSvenki if (syserrlog == 0) {
15030d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1504a90d965dSfw PICL_CLASS_RPM_SENSOR,
1505a42ff480Sfw PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
15060d63ce2bSvenki if (all_status_ok) {
15070d63ce2bSvenki log_printf("All fan sensors are OK.\n");
15080d63ce2bSvenki return;
15090d63ce2bSvenki }
15100d63ce2bSvenki }
15115e3e415aSfw log_printf("-------------------------------------------------"
1512bbda49b5SSree Vemuri "---------------\n");
15130d63ce2bSvenki log_printf(fmt, "Location", "Sensor", "Status", 0);
15145e3e415aSfw log_printf("-------------------------------------------------"
1515bbda49b5SSree Vemuri "---------------\n");
15160d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR,
1517a90d965dSfw PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
15180d63ce2bSvenki }
15190d63ce2bSvenki
15200d63ce2bSvenki static void
sun4v_env_print_fan_indicators()15210d63ce2bSvenki sun4v_env_print_fan_indicators()
15220d63ce2bSvenki {
1523bbda49b5SSree Vemuri char *fmt = "%-34s %-18s %-10s\n";
15240d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1525a42ff480Sfw PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION,
1526a90d965dSfw sun4v_env_print_indicator_callback);
15270d63ce2bSvenki if (!class_node_found)
15280d63ce2bSvenki return;
15290d63ce2bSvenki log_printf("\nFan indicators:\n");
15300d63ce2bSvenki if (syserrlog == 0) {
15310d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1532a90d965dSfw PICL_CLASS_RPM_INDICATOR,
1533a42ff480Sfw (void *)PICL_PROP_CONDITION,
1534a42ff480Sfw sun4v_env_print_indicator_callback);
15350d63ce2bSvenki if (all_status_ok) {
15360d63ce2bSvenki log_printf("All fan indicators are OK.\n");
15370d63ce2bSvenki return;
15380d63ce2bSvenki }
15390d63ce2bSvenki }
15405e3e415aSfw log_printf("-------------------------------------------------"
1541bbda49b5SSree Vemuri "---------------\n");
15420d63ce2bSvenki log_printf(fmt, "Location", "Sensor", "Condition", 0);
15435e3e415aSfw log_printf("-------------------------------------------------"
1544bbda49b5SSree Vemuri "---------------\n");
15450d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR,
1546aaba19e2Sfw (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback);
15470d63ce2bSvenki }
15480d63ce2bSvenki
15490d63ce2bSvenki static void
sun4v_env_print_temp_sensors()15500d63ce2bSvenki sun4v_env_print_temp_sensors()
15510d63ce2bSvenki {
1552bbda49b5SSree Vemuri char *fmt = "%-34s %-18s %-10s\n";
15530d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1554a90d965dSfw PICL_CLASS_TEMPERATURE_SENSOR,
1555a90d965dSfw (void *)PICL_PROP_TEMPERATURE,
1556a90d965dSfw sun4v_env_print_sensor_callback);
15570d63ce2bSvenki if (!class_node_found)
15580d63ce2bSvenki return;
15590d63ce2bSvenki
15600d63ce2bSvenki log_printf("\nTemperature sensors:\n");
15610d63ce2bSvenki if (syserrlog == 0) {
15620d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1563a90d965dSfw PICL_CLASS_TEMPERATURE_SENSOR,
1564a42ff480Sfw PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
15650d63ce2bSvenki if (all_status_ok) {
15660d63ce2bSvenki log_printf("All temperature sensors are OK.\n");
15670d63ce2bSvenki return;
15680d63ce2bSvenki }
15690d63ce2bSvenki }
15705e3e415aSfw log_printf("-------------------------------------------------"
1571bbda49b5SSree Vemuri "---------------\n");
15720d63ce2bSvenki log_printf(fmt, "Location", "Sensor", "Status", 0);
15735e3e415aSfw log_printf("-------------------------------------------------"
1574bbda49b5SSree Vemuri "---------------\n");
15750d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1576a90d965dSfw PICL_CLASS_TEMPERATURE_SENSOR,
1577a90d965dSfw (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
15780d63ce2bSvenki }
15790d63ce2bSvenki
15800d63ce2bSvenki static void
sun4v_env_print_temp_indicators()15810d63ce2bSvenki sun4v_env_print_temp_indicators()
15820d63ce2bSvenki {
1583bbda49b5SSree Vemuri char *fmt = "%-34s %-18s %-8s\n";
15840d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1585a90d965dSfw PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION,
1586a90d965dSfw sun4v_env_print_indicator_callback);
15870d63ce2bSvenki if (!class_node_found)
15880d63ce2bSvenki return;
15890d63ce2bSvenki log_printf("\nTemperature indicators:\n");
15900d63ce2bSvenki if (syserrlog == 0) {
15910d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1592a42ff480Sfw PICL_CLASS_TEMPERATURE_INDICATOR,
1593a42ff480Sfw (void *)PICL_PROP_CONDITION,
1594a90d965dSfw sun4v_env_print_indicator_callback);
15950d63ce2bSvenki if (all_status_ok) {
15960d63ce2bSvenki log_printf("All temperature indicators are OK.\n");
15970d63ce2bSvenki return;
15980d63ce2bSvenki }
15990d63ce2bSvenki }
16005e3e415aSfw log_printf("-------------------------------------------------"
1601bbda49b5SSree Vemuri "---------------\n");
16020d63ce2bSvenki log_printf(fmt, "Location", "Indicator", "Condition", 0);
16035e3e415aSfw log_printf("-------------------------------------------------"
1604bbda49b5SSree Vemuri "---------------\n");
16050d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1606a90d965dSfw PICL_CLASS_TEMPERATURE_INDICATOR,
1607a90d965dSfw (void *)PICL_PROP_CONDITION,
1608a90d965dSfw sun4v_env_print_indicator_callback);
16090d63ce2bSvenki }
16100d63ce2bSvenki
16110d63ce2bSvenki static void
sun4v_env_print_current_sensors()16120d63ce2bSvenki sun4v_env_print_current_sensors()
16130d63ce2bSvenki {
1614bbda49b5SSree Vemuri char *fmt = "%-34s %-18s %-10s\n";
16150d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR,
1616a90d965dSfw (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
16170d63ce2bSvenki if (!class_node_found)
16180d63ce2bSvenki return;
16190d63ce2bSvenki log_printf("\nCurrent sensors:\n");
16200d63ce2bSvenki if (syserrlog == 0) {
16210d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1622a90d965dSfw PICL_CLASS_CURRENT_SENSOR,
1623a42ff480Sfw PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
16240d63ce2bSvenki if (all_status_ok) {
16250d63ce2bSvenki log_printf("All current sensors are OK.\n");
16260d63ce2bSvenki return;
16270d63ce2bSvenki }
16280d63ce2bSvenki }
16295e3e415aSfw log_printf("-------------------------------------------------"
1630bbda49b5SSree Vemuri "---------------\n");
16310d63ce2bSvenki log_printf(fmt, "Location", "Sensor", "Status", 0);
16325e3e415aSfw log_printf("-------------------------------------------------"
1633bbda49b5SSree Vemuri "---------------\n");
16340d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1635a90d965dSfw PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
1636a90d965dSfw sun4v_env_print_sensor_callback);
16370d63ce2bSvenki }
16380d63ce2bSvenki
16390d63ce2bSvenki static void
sun4v_env_print_current_indicators()16400d63ce2bSvenki sun4v_env_print_current_indicators()
16410d63ce2bSvenki {
1642bbda49b5SSree Vemuri char *fmt = "%-34s %-18s %-8s\n";
16430d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1644a90d965dSfw PICL_CLASS_CURRENT_INDICATOR,
1645a90d965dSfw (void *)PICL_PROP_CONDITION,
1646a90d965dSfw sun4v_env_print_indicator_callback);
16470d63ce2bSvenki if (!class_node_found)
16480d63ce2bSvenki return;
16490d63ce2bSvenki log_printf("\nCurrent indicators:\n");
16500d63ce2bSvenki if (syserrlog == 0) {
16510d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1652a42ff480Sfw PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION,
1653a90d965dSfw sun4v_env_print_indicator_callback);
16540d63ce2bSvenki if (all_status_ok) {
16550d63ce2bSvenki log_printf("All current indicators are OK.\n");
16560d63ce2bSvenki return;
16570d63ce2bSvenki }
16580d63ce2bSvenki }
16595e3e415aSfw log_printf("-------------------------------------------------"
1660bbda49b5SSree Vemuri "---------------\n");
16610d63ce2bSvenki log_printf(fmt, "Location", "Indicator", "Condition", 0);
16625e3e415aSfw log_printf("-------------------------------------------------"
1663bbda49b5SSree Vemuri "---------------\n");
16640d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1665a90d965dSfw PICL_CLASS_CURRENT_INDICATOR,
1666a90d965dSfw (void *)PICL_PROP_CONDITION,
1667a90d965dSfw sun4v_env_print_indicator_callback);
16680d63ce2bSvenki }
16690d63ce2bSvenki
16700d63ce2bSvenki static void
sun4v_env_print_voltage_sensors()16710d63ce2bSvenki sun4v_env_print_voltage_sensors()
16720d63ce2bSvenki {
1673bbda49b5SSree Vemuri char *fmt = "%-34s %-18s %-10s\n";
16740d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1675a90d965dSfw PICL_CLASS_VOLTAGE_SENSOR,
1676a90d965dSfw PICL_PROP_VOLTAGE,
1677a90d965dSfw sun4v_env_print_sensor_callback);
16780d63ce2bSvenki if (!class_node_found)
16790d63ce2bSvenki return;
16800d63ce2bSvenki log_printf("\nVoltage sensors:\n");
16810d63ce2bSvenki if (syserrlog == 0) {
16820d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1683a90d965dSfw PICL_CLASS_VOLTAGE_SENSOR,
1684a42ff480Sfw PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback);
16850d63ce2bSvenki if (all_status_ok) {
16860d63ce2bSvenki log_printf("All voltage sensors are OK.\n");
16870d63ce2bSvenki return;
16880d63ce2bSvenki }
16890d63ce2bSvenki }
16905e3e415aSfw log_printf("-------------------------------------------------"
1691bbda49b5SSree Vemuri "---------------\n");
16920d63ce2bSvenki log_printf(fmt, "Location", "Sensor", "Status", 0);
16935e3e415aSfw log_printf("-------------------------------------------------"
1694bbda49b5SSree Vemuri "---------------\n");
16950d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1696a90d965dSfw PICL_CLASS_VOLTAGE_SENSOR,
1697a90d965dSfw (void *)PICL_PROP_VOLTAGE,
1698a90d965dSfw sun4v_env_print_sensor_callback);
16990d63ce2bSvenki }
17000d63ce2bSvenki
17010d63ce2bSvenki static void
sun4v_env_print_voltage_indicators()17020d63ce2bSvenki sun4v_env_print_voltage_indicators()
17030d63ce2bSvenki {
1704bbda49b5SSree Vemuri char *fmt = "%-34s %-18s %-8s\n";
17050d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1706a90d965dSfw PICL_CLASS_VOLTAGE_INDICATOR,
1707a90d965dSfw (void *)PICL_PROP_CONDITION,
1708a90d965dSfw sun4v_env_print_indicator_callback);
17090d63ce2bSvenki if (!class_node_found)
17100d63ce2bSvenki return;
17110d63ce2bSvenki log_printf("\nVoltage indicators:\n");
17120d63ce2bSvenki if (syserrlog == 0) {
17130d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1714a42ff480Sfw PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION,
1715a90d965dSfw sun4v_env_print_indicator_callback);
17160d63ce2bSvenki if (all_status_ok) {
17170d63ce2bSvenki log_printf("All voltage indicators are OK.\n");
17180d63ce2bSvenki return;
17190d63ce2bSvenki }
17200d63ce2bSvenki }
17215e3e415aSfw log_printf("-------------------------------------------------"
1722bbda49b5SSree Vemuri "---------------\n");
17230d63ce2bSvenki log_printf(fmt, "Location", "Indicator", "Condition", 0);
17245e3e415aSfw log_printf("-------------------------------------------------"
1725bbda49b5SSree Vemuri "---------------\n");
17260d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1727a90d965dSfw PICL_CLASS_VOLTAGE_INDICATOR,
1728a90d965dSfw (void *)PICL_PROP_CONDITION,
1729a90d965dSfw sun4v_env_print_indicator_callback);
17300d63ce2bSvenki }
17310d63ce2bSvenki
17320d63ce2bSvenki static void
sun4v_env_print_LEDs()17330d63ce2bSvenki sun4v_env_print_LEDs()
17340d63ce2bSvenki {
1735bbda49b5SSree Vemuri char *fmt = "%-34s %-18s %-8s\n";
17360d63ce2bSvenki if (syserrlog == 0)
17370d63ce2bSvenki return;
17380d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
1739a90d965dSfw (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
17400d63ce2bSvenki if (!class_node_found)
17410d63ce2bSvenki return;
17420d63ce2bSvenki log_printf("\nLEDs:\n");
17435e3e415aSfw log_printf("-------------------------------------------------"
1744bbda49b5SSree Vemuri "---------------\n");
17450d63ce2bSvenki log_printf(fmt, "Location", "LED", "State", 0);
17465e3e415aSfw log_printf("-------------------------------------------------"
1747bbda49b5SSree Vemuri "---------------\n");
17480d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
1749a90d965dSfw (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
17500d63ce2bSvenki }
17510d63ce2bSvenki
17520d63ce2bSvenki /*ARGSUSED*/
17530d63ce2bSvenki static int
sun4v_print_fru_status_callback(picl_nodehdl_t nodeh,void * args)17540d63ce2bSvenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args)
17550d63ce2bSvenki {
17560d63ce2bSvenki char label[PICL_PROPNAMELEN_MAX];
17570d63ce2bSvenki char status[PICL_PROPNAMELEN_MAX];
17580d63ce2bSvenki picl_errno_t err;
17590d63ce2bSvenki picl_prophdl_t proph;
17600d63ce2bSvenki picl_nodehdl_t parenth;
17610d63ce2bSvenki char *names[PARENT_NAMES];
17620d63ce2bSvenki char *loc;
17630d63ce2bSvenki int i;
17640d63ce2bSvenki
17650d63ce2bSvenki if (!class_node_found) {
17660d63ce2bSvenki class_node_found = 1;
17670d63ce2bSvenki return (PICL_WALK_TERMINATE);
17680d63ce2bSvenki }
17690d63ce2bSvenki err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph);
17700d63ce2bSvenki if (err != PICL_SUCCESS)
17710d63ce2bSvenki return (PICL_WALK_CONTINUE);
17720d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
1773a90d965dSfw sizeof (label));
17740d63ce2bSvenki if (err != PICL_SUCCESS)
17750d63ce2bSvenki return (PICL_WALK_CONTINUE);
17760d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
1777a90d965dSfw status, sizeof (status));
17780d63ce2bSvenki if (err != PICL_SUCCESS)
17790d63ce2bSvenki return (PICL_WALK_CONTINUE);
17800d63ce2bSvenki if (syserrlog == 0) {
17810d63ce2bSvenki if (strcmp(status, "disabled") == 0) {
17820d63ce2bSvenki if (all_status_ok) {
17830d63ce2bSvenki all_status_ok = 0;
17840d63ce2bSvenki return (PICL_WALK_TERMINATE);
17850d63ce2bSvenki }
17860d63ce2bSvenki } else
17870d63ce2bSvenki return (PICL_WALK_CONTINUE);
17887ae8c7a8SMichael Bergknoff } else {
17897ae8c7a8SMichael Bergknoff if (all_status_ok && (strcmp(status, "disabled") == 0)) {
17907ae8c7a8SMichael Bergknoff all_status_ok = 0;
17917ae8c7a8SMichael Bergknoff }
17920d63ce2bSvenki }
17938a31bd2bSBirva Shah
17948a31bd2bSBirva Shah if (is_fru_absent(nodeh))
1795*6fb59094SToomas Soome (void) strcpy(status, "Not present");
17968a31bd2bSBirva Shah
17970d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
1798a90d965dSfw sizeof (parenth));
17990d63ce2bSvenki if (err != PICL_SUCCESS) {
18000d63ce2bSvenki log_printf("\n");
18010d63ce2bSvenki return (PICL_WALK_CONTINUE);
18020d63ce2bSvenki }
18030d63ce2bSvenki if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
18040d63ce2bSvenki return (PICL_WALK_TERMINATE);
18050d63ce2bSvenki for (i = 0; i < PARENT_NAMES; i++)
18060d63ce2bSvenki if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
18070d63ce2bSvenki while (--i > -1)
18080d63ce2bSvenki free(names[i]);
18090d63ce2bSvenki free(loc);
18100d63ce2bSvenki return (PICL_WALK_TERMINATE);
18110d63ce2bSvenki }
18120d63ce2bSvenki i = 0;
18130d63ce2bSvenki while (err == PICL_SUCCESS) {
1814aaba19e2Sfw if (parenth == phyplatformh)
18150d63ce2bSvenki break;
18160d63ce2bSvenki err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
1817a90d965dSfw names[i++], PICL_PROPNAMELEN_MAX);
18180d63ce2bSvenki if (err != PICL_SUCCESS) {
18190d63ce2bSvenki i--;
18200d63ce2bSvenki break;
18210d63ce2bSvenki }
18220d63ce2bSvenki if (i == PARENT_NAMES)
18230d63ce2bSvenki break;
18240d63ce2bSvenki err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
1825a90d965dSfw &parenth, sizeof (parenth));
18260d63ce2bSvenki }
18270d63ce2bSvenki loc[0] = '\0';
18284c5e0fdeSvivek if (--i > -1) {
18294c5e0fdeSvivek (void) strlcat(loc, names[i],
1830a90d965dSfw PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18314c5e0fdeSvivek }
18320d63ce2bSvenki while (--i > -1) {
18334c5e0fdeSvivek (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18344c5e0fdeSvivek (void) strlcat(loc, names[i],
1835a90d965dSfw PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18360d63ce2bSvenki }
18375e3e415aSfw log_printf("%-35s", loc);
18380d63ce2bSvenki for (i = 0; i < PARENT_NAMES; i++)
18390d63ce2bSvenki free(names[i]);
18400d63ce2bSvenki free(loc);
18410d63ce2bSvenki log_printf("%-10s", label);
18420d63ce2bSvenki log_printf("%-9s", status);
18430d63ce2bSvenki log_printf("\n");
18440d63ce2bSvenki return (PICL_WALK_CONTINUE);
18450d63ce2bSvenki }
18460d63ce2bSvenki
18470d63ce2bSvenki static void
sun4v_print_fru_status()18480d63ce2bSvenki sun4v_print_fru_status()
18490d63ce2bSvenki {
18505e3e415aSfw char *fmt = "%-34s %-9s %-8s\n";
1851dc6ca969Sfw
18520d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1853a90d965dSfw sun4v_print_fru_status_callback);
18540d63ce2bSvenki if (!class_node_found)
18550d63ce2bSvenki return;
1856dc6ca969Sfw
18570d63ce2bSvenki log_printf("\n");
18580d63ce2bSvenki log_printf("============================");
18590d63ce2bSvenki log_printf(" FRU Status ");
18600d63ce2bSvenki log_printf("============================");
18610d63ce2bSvenki log_printf("\n");
18620d63ce2bSvenki
18630d63ce2bSvenki if (syserrlog == 0) {
18640d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh,
1865aaba19e2Sfw NULL, NULL,
1866a90d965dSfw sun4v_print_fru_status_callback);
18670d63ce2bSvenki if (all_status_ok) {
18680d63ce2bSvenki log_printf("All FRUs are enabled.\n");
18690d63ce2bSvenki return;
18700d63ce2bSvenki }
18710d63ce2bSvenki }
18720d63ce2bSvenki log_printf(fmt, "Location", "Name", "Status", 0);
18735e3e415aSfw log_printf("------------------------------------------------------\n");
1874aaba19e2Sfw (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1875a90d965dSfw sun4v_print_fru_status_callback);
18760d63ce2bSvenki }
18770d63ce2bSvenki
18788a31bd2bSBirva Shah /* Check the children of the FRU node for a presence indicator */
18798a31bd2bSBirva Shah static int
is_fru_absent(picl_nodehdl_t fruh)18808a31bd2bSBirva Shah is_fru_absent(picl_nodehdl_t fruh)
18818a31bd2bSBirva Shah {
18828a31bd2bSBirva Shah char class [PICL_CLASSNAMELEN_MAX];
18838a31bd2bSBirva Shah char condition [PICL_PROPNAMELEN_MAX];
18848a31bd2bSBirva Shah picl_errno_t err;
18858a31bd2bSBirva Shah picl_nodehdl_t nodeh;
18868a31bd2bSBirva Shah
18878a31bd2bSBirva Shah err = picl_get_propval_by_name(fruh, PICL_PROP_CHILD, &nodeh,
18888a31bd2bSBirva Shah sizeof (picl_nodehdl_t));
18898a31bd2bSBirva Shah while (err == PICL_SUCCESS) {
18908a31bd2bSBirva Shah err = picl_get_propval_by_name(nodeh,
18918a31bd2bSBirva Shah PICL_PROP_CLASSNAME, class, sizeof (class));
18928a31bd2bSBirva Shah if (err == PICL_SUCCESS &&
18938a31bd2bSBirva Shah strcmp(class, "presence-indicator") == 0) {
18948a31bd2bSBirva Shah err = picl_get_propval_by_name(nodeh,
18958a31bd2bSBirva Shah PICL_PROP_CONDITION, condition,
18968a31bd2bSBirva Shah sizeof (condition));
18978a31bd2bSBirva Shah if (err == PICL_SUCCESS) {
18988a31bd2bSBirva Shah if (strcmp(condition, "Absent") == 0) {
18998a31bd2bSBirva Shah return (1);
19008a31bd2bSBirva Shah } else {
19018a31bd2bSBirva Shah return (0);
19028a31bd2bSBirva Shah }
19038a31bd2bSBirva Shah }
19048a31bd2bSBirva Shah }
19058a31bd2bSBirva Shah err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
19068a31bd2bSBirva Shah &nodeh, sizeof (picl_nodehdl_t));
19078a31bd2bSBirva Shah }
19088a31bd2bSBirva Shah return (0);
19098a31bd2bSBirva Shah }
19108a31bd2bSBirva Shah
19110d63ce2bSvenki /*ARGSUSED*/
19120d63ce2bSvenki static int
sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh,void * args)19130d63ce2bSvenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args)
19140d63ce2bSvenki {
19150d63ce2bSvenki char rev[PICL_PROPNAMELEN_MAX];
19160d63ce2bSvenki picl_errno_t err;
19170d63ce2bSvenki
19180d63ce2bSvenki if (!class_node_found) {
19190d63ce2bSvenki class_node_found = 1;
19200d63ce2bSvenki return (PICL_WALK_TERMINATE);
19210d63ce2bSvenki }
1922dc6ca969Sfw
19230d63ce2bSvenki err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev,
1924a90d965dSfw sizeof (rev));
19250d63ce2bSvenki if (err != PICL_SUCCESS)
19260d63ce2bSvenki return (PICL_WALK_CONTINUE);
19270d63ce2bSvenki if (strlen(rev) == 0)
19280d63ce2bSvenki return (PICL_WALK_CONTINUE);
1929dc6ca969Sfw log_printf("%s", rev);
19300d63ce2bSvenki log_printf("\n");
19310d63ce2bSvenki return (PICL_WALK_CONTINUE);
19320d63ce2bSvenki }
19330d63ce2bSvenki
19340d63ce2bSvenki static void
sun4v_print_fw_rev()19350d63ce2bSvenki sun4v_print_fw_rev()
19360d63ce2bSvenki {
19370d63ce2bSvenki if (syserrlog == 0)
19380d63ce2bSvenki return;
1939dc6ca969Sfw
19400d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1941a90d965dSfw sun4v_print_fw_rev_callback);
19420d63ce2bSvenki if (!class_node_found)
19430d63ce2bSvenki return;
1944dc6ca969Sfw
19450d63ce2bSvenki log_printf("\n");
19460d63ce2bSvenki log_printf("============================");
19470d63ce2bSvenki log_printf(" FW Version ");
19480d63ce2bSvenki log_printf("============================");
19490d63ce2bSvenki log_printf("\n");
1950dc6ca969Sfw log_printf("Version\n");
19515e3e415aSfw log_printf("-------------------------------------------------"
19525e3e415aSfw "-----------\n");
19530d63ce2bSvenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
1954a90d965dSfw sun4v_print_fw_rev_callback);
19550d63ce2bSvenki }
19560d63ce2bSvenki
1957dc6ca969Sfw static void
sun4v_print_openprom_rev()1958dc6ca969Sfw sun4v_print_openprom_rev()
1959dc6ca969Sfw {
1960dc6ca969Sfw if (syserrlog == 0)
1961dc6ca969Sfw return;
1962dc6ca969Sfw
1963dc6ca969Sfw (void) picl_walk_tree_by_class(rooth, "openprom", NULL,
1964dc6ca969Sfw openprom_callback);
1965dc6ca969Sfw if (!class_node_found)
1966dc6ca969Sfw return;
1967dc6ca969Sfw
1968dc6ca969Sfw log_printf("\n");
1969dc6ca969Sfw log_printf("======================");
1970dc6ca969Sfw log_printf(" System PROM revisions ");
1971dc6ca969Sfw log_printf("=======================");
1972dc6ca969Sfw log_printf("\n");
1973dc6ca969Sfw log_printf("Version\n");
1974dc6ca969Sfw log_printf("-------------------------------------------------"
1975dc6ca969Sfw "-----------\n");
1976dc6ca969Sfw (void) picl_walk_tree_by_class(rooth, "openprom", NULL,
1977dc6ca969Sfw openprom_callback);
1978dc6ca969Sfw }
1979dc6ca969Sfw
1980dc6ca969Sfw /*
1981dc6ca969Sfw * display the OBP and POST prom revisions (if present)
1982dc6ca969Sfw */
1983dc6ca969Sfw /* ARGSUSED */
1984dc6ca969Sfw static int
openprom_callback(picl_nodehdl_t openpromh,void * arg)1985dc6ca969Sfw openprom_callback(picl_nodehdl_t openpromh, void *arg)
1986dc6ca969Sfw {
1987dc6ca969Sfw picl_prophdl_t proph;
1988dc6ca969Sfw picl_prophdl_t tblh;
1989dc6ca969Sfw picl_prophdl_t rowproph;
1990dc6ca969Sfw picl_propinfo_t pinfo;
1991dc6ca969Sfw char *prom_version = NULL;
1992dc6ca969Sfw char *obp_version = NULL;
1993dc6ca969Sfw int err;
1994dc6ca969Sfw
1995dc6ca969Sfw if (!class_node_found) {
1996dc6ca969Sfw class_node_found = 1;
1997dc6ca969Sfw return (PICL_WALK_TERMINATE);
1998dc6ca969Sfw }
1999dc6ca969Sfw
2000dc6ca969Sfw err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION,
2001dc6ca969Sfw &pinfo, &proph);
2002dc6ca969Sfw if (err == PICL_PROPNOTFOUND)
2003dc6ca969Sfw return (PICL_WALK_TERMINATE);
2004dc6ca969Sfw else if (err != PICL_SUCCESS)
2005dc6ca969Sfw return (err);
2006dc6ca969Sfw
2007dc6ca969Sfw /*
2008dc6ca969Sfw * If it's a table prop, the first element is OBP revision
2009dc6ca969Sfw * The second one is POST revision.
2010dc6ca969Sfw * If it's a charstring prop, the value will be only OBP revision
2011dc6ca969Sfw */
2012dc6ca969Sfw if (pinfo.type == PICL_PTYPE_CHARSTRING) {
2013dc6ca969Sfw prom_version = (char *)alloca(pinfo.size);
2014dc6ca969Sfw if (prom_version == NULL)
2015dc6ca969Sfw return (PICL_FAILURE);
2016dc6ca969Sfw err = picl_get_propval(proph, prom_version, pinfo.size);
2017dc6ca969Sfw if (err != PICL_SUCCESS)
2018dc6ca969Sfw return (err);
2019dc6ca969Sfw log_printf("%s\n", prom_version);
2020dc6ca969Sfw }
2021dc6ca969Sfw
2022dc6ca969Sfw if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */
2023dc6ca969Sfw return (PICL_WALK_TERMINATE);
2024dc6ca969Sfw
2025dc6ca969Sfw err = picl_get_propval(proph, &tblh, pinfo.size);
2026dc6ca969Sfw if (err != PICL_SUCCESS)
2027dc6ca969Sfw return (err);
2028dc6ca969Sfw
2029dc6ca969Sfw err = picl_get_next_by_row(tblh, &rowproph);
2030dc6ca969Sfw if (err == PICL_SUCCESS) {
2031dc6ca969Sfw /* get first row */
2032dc6ca969Sfw err = picl_get_propinfo(rowproph, &pinfo);
2033dc6ca969Sfw if (err != PICL_SUCCESS)
2034dc6ca969Sfw return (err);
2035dc6ca969Sfw
2036dc6ca969Sfw prom_version = (char *)alloca(pinfo.size);
2037dc6ca969Sfw if (prom_version == NULL)
2038dc6ca969Sfw return (PICL_FAILURE);
2039dc6ca969Sfw
2040dc6ca969Sfw err = picl_get_propval(rowproph, prom_version, pinfo.size);
2041dc6ca969Sfw if (err != PICL_SUCCESS)
2042dc6ca969Sfw return (err);
2043dc6ca969Sfw log_printf("%s\n", prom_version);
2044dc6ca969Sfw
2045dc6ca969Sfw /* get second row */
2046dc6ca969Sfw err = picl_get_next_by_col(rowproph, &rowproph);
2047dc6ca969Sfw if (err == PICL_SUCCESS) {
2048dc6ca969Sfw err = picl_get_propinfo(rowproph, &pinfo);
2049dc6ca969Sfw if (err != PICL_SUCCESS)
2050dc6ca969Sfw return (err);
2051dc6ca969Sfw
2052dc6ca969Sfw obp_version = (char *)alloca(pinfo.size);
2053dc6ca969Sfw if (obp_version == NULL)
2054dc6ca969Sfw return (PICL_FAILURE);
2055dc6ca969Sfw err = picl_get_propval(rowproph, obp_version,
2056dc6ca969Sfw pinfo.size);
2057dc6ca969Sfw if (err != PICL_SUCCESS)
2058dc6ca969Sfw return (err);
2059dc6ca969Sfw log_printf("%s\n", obp_version);
2060dc6ca969Sfw }
2061dc6ca969Sfw }
2062dc6ca969Sfw
2063dc6ca969Sfw return (PICL_WALK_TERMINATE);
2064dc6ca969Sfw }
2065dc6ca969Sfw
20660d63ce2bSvenki static void
sun4v_print_chassis_serial_no()20670d63ce2bSvenki sun4v_print_chassis_serial_no()
20680d63ce2bSvenki {
20690d63ce2bSvenki char val[PICL_PROPNAMELEN_MAX];
20700d63ce2bSvenki picl_errno_t err;
20710d63ce2bSvenki if (syserrlog == 0 || chassish == 0)
20720d63ce2bSvenki return;
20730d63ce2bSvenki
20740d63ce2bSvenki log_printf("\n");
20751cf6ec7eSsuha log_printf("Chassis Serial Number");
20760d63ce2bSvenki log_printf("\n");
20770d63ce2bSvenki log_printf("---------------------\n");
20780d63ce2bSvenki err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER,
2079a90d965dSfw val, sizeof (val));
20800d63ce2bSvenki if (err == PICL_SUCCESS)
20810d63ce2bSvenki log_printf("%s", val);
20820d63ce2bSvenki log_printf("\n");
20830d63ce2bSvenki }
2084