11708Sstevel /*
21708Sstevel * CDDL HEADER START
31708Sstevel *
41708Sstevel * The contents of this file are subject to the terms of the
53941Svenki * Common Development and Distribution License (the "License").
63941Svenki * You may not use this file except in compliance with the License.
71708Sstevel *
81708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel * or http://www.opensolaris.org/os/licensing.
101708Sstevel * See the License for the specific language governing permissions
111708Sstevel * and limitations under the License.
121708Sstevel *
131708Sstevel * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel *
191708Sstevel * CDDL HEADER END
201708Sstevel */
211708Sstevel /*
2212046SMichael.Bergknoff@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
231708Sstevel */
241708Sstevel
251708Sstevel #include <stdio.h>
261708Sstevel #include <stdlib.h>
275436Sfw157321 #include <alloca.h>
281708Sstevel #include <unistd.h>
291708Sstevel #include <ctype.h>
301708Sstevel #include <string.h>
311708Sstevel #include <kvm.h>
321708Sstevel #include <varargs.h>
331708Sstevel #include <time.h>
341708Sstevel #include <dirent.h>
351708Sstevel #include <fcntl.h>
361708Sstevel #include <sys/param.h>
371708Sstevel #include <sys/stat.h>
381708Sstevel #include <sys/types.h>
391708Sstevel #include <sys/utsname.h>
401708Sstevel #include <sys/openpromio.h>
411708Sstevel #include <libintl.h>
421708Sstevel #include <syslog.h>
431708Sstevel #include <sys/dkio.h>
443941Svenki #include <sys/systeminfo.h>
453941Svenki #include <picldefs.h>
464802Sfw157321 #include <math.h>
474802Sfw157321 #include <errno.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
574669Sfw157321 #define MOTHERBOARD "MB"
583941Svenki #define NETWORK "network"
593941Svenki #define SUN4V_MACHINE "sun4v"
603941Svenki #define PARENT_NAMES 10
613941Svenki
623941Svenki /*
633941Svenki * Additional OBP properties
643941Svenki */
653941Svenki #define OBP_PROP_COMPATIBLE "compatible"
663941Svenki #define OBP_PROP_MODEL "model"
673941Svenki #define OBP_PROP_SLOT_NAMES "slot-names"
685436Sfw157321 #define OBP_PROP_VERSION "version"
693941Svenki
703941Svenki #define PICL_NODE_PHYSICAL_PLATFORM "physical-platform"
713941Svenki #define PICL_NODE_CHASSIS "chassis"
723941Svenki #define MEMORY_SIZE_FIELD 11
733941Svenki #define INVALID_THRESHOLD 1000000
743941Svenki
753941Svenki /*
763941Svenki * Additional picl classes
773941Svenki */
783941Svenki #ifndef PICL_CLASS_SUN4V
793941Svenki #define PICL_CLASS_SUN4V "sun4v"
803941Svenki #endif
813941Svenki
823941Svenki #ifndef PICL_PROP_NAC
833941Svenki #define PICL_PROP_NAC "nac"
843941Svenki #endif
853941Svenki
863941Svenki extern int sys_clk;
873941Svenki extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *,
883941Svenki picl_nodehdl_t *);
893941Svenki
903941Svenki static picl_nodehdl_t rooth = 0, phyplatformh = 0;
913941Svenki static picl_nodehdl_t chassish = 0;
923941Svenki static int class_node_found;
933941Svenki static int syserrlog;
943941Svenki static int all_status_ok;
953941Svenki
963941Svenki /* local functions */
973941Svenki static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **);
983941Svenki static void sun4v_display_memory_conf(picl_nodehdl_t);
995547Smb158278 static int sun4v_disp_env_status();
1003941Svenki static void sun4v_env_print_fan_sensors();
1013941Svenki static void sun4v_env_print_fan_indicators();
1023941Svenki static void sun4v_env_print_temp_sensors();
1033941Svenki static void sun4v_env_print_temp_indicators();
1043941Svenki static void sun4v_env_print_current_sensors();
1053941Svenki static void sun4v_env_print_current_indicators();
1063941Svenki static void sun4v_env_print_voltage_sensors();
1073941Svenki static void sun4v_env_print_voltage_indicators();
1083941Svenki static void sun4v_env_print_LEDs();
1093941Svenki static void sun4v_print_fru_status();
11010070SBirva.Shah@Sun.COM static int is_fru_absent(picl_nodehdl_t);
1113941Svenki static void sun4v_print_fw_rev();
1123941Svenki static void sun4v_print_chassis_serial_no();
1135436Sfw157321 static int openprom_callback(picl_nodehdl_t openpromh, void *arg);
1145436Sfw157321 static void sun4v_print_openprom_rev();
1151708Sstevel
1161708Sstevel int
sun4v_display(Sys_tree * tree,Prom_node * root,int log,picl_nodehdl_t plafh)1173941Svenki sun4v_display(Sys_tree *tree, Prom_node *root, int log,
1183941Svenki picl_nodehdl_t plafh)
1191708Sstevel {
1201708Sstevel void *value; /* used for opaque PROM data */
1211708Sstevel struct mem_total memory_total; /* Total memory in system */
1221708Sstevel struct grp_info grps; /* Info on all groups in system */
1233941Svenki char machine[MAXSTRLEN];
1245547Smb158278 int exit_code = 0;
1253941Svenki
1263941Svenki if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1)
1273941Svenki return (1);
1283941Svenki if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0)
1293941Svenki return (1);
1301708Sstevel
1311708Sstevel sys_clk = -1; /* System clock freq. (in MHz) */
1321708Sstevel
1331708Sstevel /*
1341708Sstevel * Now display the machine's configuration. We do this if we
1351708Sstevel * are not logging.
1361708Sstevel */
1371708Sstevel if (!logging) {
1381708Sstevel struct utsname uts_buf;
1391708Sstevel
1401708Sstevel /*
1411708Sstevel * Display system banner
1421708Sstevel */
1431708Sstevel (void) uname(&uts_buf);
1441708Sstevel
1453941Svenki log_printf(dgettext(TEXT_DOMAIN, "System Configuration: "
146*13019SMichael.Bergknoff@Oracle.COM "Oracle Corporation %s %s\n"), uts_buf.machine,
1474669Sfw157321 get_prop_val(find_prop(root, "banner-name")), 0);
1481708Sstevel
1491708Sstevel /* display system clock frequency */
1501708Sstevel value = get_prop_val(find_prop(root, "clock-frequency"));
1511708Sstevel if (value != NULL) {
1521708Sstevel sys_clk = ((*((int *)value)) + 500000) / 1000000;
1531708Sstevel log_printf(dgettext(TEXT_DOMAIN, "System clock "
1544669Sfw157321 "frequency: %d MHz\n"), sys_clk, 0);
1551708Sstevel }
1561708Sstevel
1571708Sstevel /* Display the Memory Size */
1581708Sstevel display_memorysize(tree, NULL, &grps, &memory_total);
1591708Sstevel
1601708Sstevel /* Display the CPU devices */
1611708Sstevel sun4v_display_cpu_devices(plafh);
1621708Sstevel
1631708Sstevel /* Display the Memory configuration */
1643941Svenki class_node_found = 0;
1653941Svenki sun4v_display_memory_conf(plafh);
1661708Sstevel
1671708Sstevel /* Display all the IO cards. */
1681708Sstevel (void) sun4v_display_pci(plafh);
1693941Svenki sun4v_display_diaginfo((log || (logging)), root, plafh);
1701708Sstevel
1713941Svenki if (picl_get_root(&rooth) != PICL_SUCCESS)
1723941Svenki return (1);
1735547Smb158278
1745547Smb158278 /*
1755547Smb158278 * The physical-platform node may be missing on systems with
1765547Smb158278 * older firmware so don't consider that an error.
1775547Smb158278 */
1783941Svenki if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM,
1794669Sfw157321 &phyplatformh) != PICL_SUCCESS)
1805547Smb158278 return (0);
1813941Svenki
1823941Svenki if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME,
1834669Sfw157321 PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
1844669Sfw157321 strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS)
1853941Svenki return (1);
1863941Svenki
1873941Svenki syserrlog = log;
1885547Smb158278 exit_code = sun4v_disp_env_status();
1893941Svenki }
1905547Smb158278 return (exit_code);
1913941Svenki }
1923941Svenki
1935819Sfw157321 /*
1945819Sfw157321 * The binding-name property encodes the bus type.
1955819Sfw157321 */
1963941Svenki static void
get_bus_type(picl_nodehdl_t nodeh,struct io_card * card)1973941Svenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card)
1983941Svenki {
1995819Sfw157321 char val[PICL_PROPNAMELEN_MAX], *p, *q;
2005819Sfw157321
2015819Sfw157321 card->bus_type[0] = '\0';
2023941Svenki
2035819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, val,
2045819Sfw157321 sizeof (val)) == PICL_SUCCESS) {
2055819Sfw157321 if (strstr(val, PICL_CLASS_PCIEX))
2064003Svivek (void) strlcpy(card->bus_type, "PCIE",
2074669Sfw157321 sizeof (card->bus_type));
2085819Sfw157321 else if (strstr(val, PICL_CLASS_PCI))
2095819Sfw157321 (void) strlcpy(card->bus_type, "PCIX",
2105819Sfw157321 sizeof (card->bus_type));
2115819Sfw157321 else {
2125819Sfw157321 /*
2135819Sfw157321 * Not perfect: process the binding-name until
2145819Sfw157321 * we encounter something that we don't think would
2155819Sfw157321 * be part of a bus type. This may get confused a bit
2165819Sfw157321 * if a device or vendor id is encoded right after
2175819Sfw157321 * the bus class since there's no delimiter. If the
2185819Sfw157321 * id number begins with a hex digit [abcdef] then
2195819Sfw157321 * this will become part of the bus type string
2205819Sfw157321 * reported by prtdiag. This is all an effort to
2215819Sfw157321 * print something potentially useful for bus types
2225819Sfw157321 * other than PCI/PCIe.
2235819Sfw157321 *
2245819Sfw157321 * We do this because this code will get called for
2255819Sfw157321 * non-PCI class devices like the xaui (class sun4v.)
2265819Sfw157321 */
2275819Sfw157321 if (strstr(val, "SUNW,") != NULL)
2285819Sfw157321 p = strchr(val, ',') + 1;
2295819Sfw157321 else
2305819Sfw157321 p = val;
2315819Sfw157321 q = p;
2325819Sfw157321 while (*p != '\0') {
2335819Sfw157321 if (isdigit((char)*p) || ispunct((char)*p)) {
2345819Sfw157321 *p = '\0';
2355819Sfw157321 break;
2365819Sfw157321 }
2375819Sfw157321 *p = (char)_toupper((int)*p);
2385819Sfw157321 ++p;
2395819Sfw157321 }
2405819Sfw157321 (void) strlcpy(card->bus_type, q,
2415819Sfw157321 sizeof (card->bus_type));
2425819Sfw157321 }
2433941Svenki }
2443941Svenki }
2453941Svenki
2465819Sfw157321 /*
2475819Sfw157321 * Fetch the Label property for this device. If none is found then
2485819Sfw157321 * search all the siblings with the same device ID for a
2495819Sfw157321 * Label and return that Label. The plug-in can only match the canonical
2505819Sfw157321 * path from the PRI with a specific devfs path. So we take care of
2515819Sfw157321 * devices with multiple functions here. A leaf device downstream of
2525819Sfw157321 * a bridge should fall out of here with PICL_PROPNOTFOUND, and the
2535819Sfw157321 * caller can walk back up the tree in search of the slot's Label.
2545819Sfw157321 */
2553941Svenki static picl_errno_t
get_slot_label(picl_nodehdl_t nodeh,struct io_card * card)2563941Svenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card)
2573941Svenki {
2583941Svenki char val[PICL_PROPNAMELEN_MAX];
2593941Svenki picl_errno_t err;
2605436Sfw157321 picl_nodehdl_t pnodeh;
2615819Sfw157321 uint32_t devid, sib_devid;
2625819Sfw157321 int32_t instance;
2633941Svenki
2645436Sfw157321 /*
2655819Sfw157321 * If there's a Label at this node then return it - we're
2665819Sfw157321 * done.
2675436Sfw157321 */
2683941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
2694669Sfw157321 sizeof (val));
2705819Sfw157321 if (err == PICL_SUCCESS) {
2715819Sfw157321 (void) strlcpy(card->slot_str, val, sizeof (card->slot_str));
2725819Sfw157321 return (err);
2735819Sfw157321 } else if (err != PICL_PROPNOTFOUND)
2745819Sfw157321 return (err);
2755819Sfw157321
2765819Sfw157321 /*
2775819Sfw157321 * At this point we're starting to extrapolate what the Label
2785819Sfw157321 * should be since there is none at this specific node.
2795819Sfw157321 * Note that until the value of "err" is overwritten in the
2805819Sfw157321 * loop below, its value should be PICL_PROPNOTFOUND.
2815819Sfw157321 */
2825819Sfw157321
2835819Sfw157321 /*
2845819Sfw157321 * The device must be attached, and we can figure that out if
2855819Sfw157321 * the instance number is present and is not equal to -1.
2865819Sfw157321 * This will prevent is from returning a Label for a sibling
2875819Sfw157321 * node when the node passed in would have a unique Label if the
2885819Sfw157321 * device were attached. But if the device is downstream of a
2895819Sfw157321 * node with a Label then pci_callback() will still find that
2905819Sfw157321 * and use it.
2915819Sfw157321 */
2925819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_INSTANCE, &instance,
2935819Sfw157321 sizeof (instance)) != PICL_SUCCESS)
2945819Sfw157321 return (err);
2955819Sfw157321 if (instance == -1)
2965819Sfw157321 return (err);
2973941Svenki
2985819Sfw157321 /*
2995819Sfw157321 * Narrow the search to just the one device ID.
3005819Sfw157321 */
3015819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_DEVICE_ID, &devid,
3025819Sfw157321 sizeof (devid)) != PICL_SUCCESS)
3035819Sfw157321 return (err);
3045819Sfw157321
3055819Sfw157321 /*
3065819Sfw157321 * Go find the first child of the parent so we can search
3075819Sfw157321 * all of the siblings.
3085819Sfw157321 */
3095819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
3105819Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS)
3115819Sfw157321 return (err);
3125819Sfw157321 if (picl_get_propval_by_name(pnodeh, PICL_PROP_CHILD, &pnodeh,
3135819Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS)
3145819Sfw157321 return (err);
3155436Sfw157321
3165819Sfw157321 /*
3175819Sfw157321 * If the child's device ID matches, then fetch the Label and
3185819Sfw157321 * return it. The first child/device ID should have a Label
3195819Sfw157321 * associated with it.
3205819Sfw157321 */
3215819Sfw157321 do {
3225819Sfw157321 if (picl_get_propval_by_name(pnodeh, PICL_PROP_DEVICE_ID,
3235819Sfw157321 &sib_devid, sizeof (sib_devid)) == PICL_SUCCESS) {
3245819Sfw157321 if (sib_devid == devid) {
3255819Sfw157321 if ((err = picl_get_propval_by_name(pnodeh,
3265819Sfw157321 PICL_PROP_LABEL, val, sizeof (val))) ==
3275819Sfw157321 PICL_SUCCESS) {
3285819Sfw157321 (void) strlcpy(card->slot_str, val,
3295819Sfw157321 sizeof (card->slot_str));
3305819Sfw157321 break;
3315819Sfw157321 }
3325819Sfw157321 }
3335819Sfw157321 }
3345819Sfw157321 } while (picl_get_propval_by_name(pnodeh, PICL_PROP_PEER, &pnodeh,
3355819Sfw157321 sizeof (pnodeh)) == PICL_SUCCESS);
3365819Sfw157321
3375436Sfw157321 return (err);
3383941Svenki }
3393941Svenki
3403941Svenki static void
get_slot_number(picl_nodehdl_t nodeh,struct io_card * card)3413941Svenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card)
3423941Svenki {
3433941Svenki picl_errno_t err;
3443941Svenki picl_prophdl_t proph;
3453941Svenki picl_propinfo_t pinfo;
3463941Svenki picl_nodehdl_t pnodeh;
3473941Svenki uint8_t *pval;
3483941Svenki uint32_t dev_mask;
3493941Svenki char uaddr[MAXSTRLEN];
3503941Svenki int i;
3513941Svenki
3523941Svenki err = PICL_SUCCESS;
3533941Svenki while (err == PICL_SUCCESS) {
3543941Svenki if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
3554669Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS) {
3564669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD,
3574669Sfw157321 sizeof (card->slot_str));
3583941Svenki card->slot = -1;
3593941Svenki return;
3603941Svenki }
3613941Svenki if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES,
3624669Sfw157321 &pinfo, &proph) == PICL_SUCCESS) {
3633941Svenki break;
3643941Svenki }
3653941Svenki nodeh = pnodeh;
3663941Svenki }
3673941Svenki if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr,
3684669Sfw157321 sizeof (uaddr)) != PICL_SUCCESS) {
3694669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD,
3704669Sfw157321 sizeof (card->slot_str));
3713941Svenki card->slot = -1;
3723941Svenki return;
3733941Svenki }
3743941Svenki pval = (uint8_t *)malloc(pinfo.size);
3753941Svenki if (!pval) {
3764669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD,
3774669Sfw157321 sizeof (card->slot_str));
3783941Svenki card->slot = -1;
3793941Svenki return;
3803941Svenki }
3813941Svenki if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) {
3824669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD,
3834669Sfw157321 sizeof (card->slot_str));
3843941Svenki card->slot = -1;
3853941Svenki free(pval);
3863941Svenki return;
3871708Sstevel }
3881708Sstevel
3893941Svenki dev_mask = 0;
3903941Svenki for (i = 0; i < sizeof (dev_mask); i++)
3913941Svenki dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i));
3923941Svenki for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) {
3933941Svenki if (uaddr[i] == ',') {
3943941Svenki uaddr[i] = '\0';
3953941Svenki break;
3963941Svenki }
3973941Svenki }
3983941Svenki card->slot = atol(uaddr);
3993941Svenki if (((1 << card->slot) & dev_mask) == 0) {
4004669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD,
4014669Sfw157321 sizeof (card->slot_str));
4023941Svenki card->slot = -1;
4033941Svenki } else {
4043941Svenki char *p = (char *)(pval+sizeof (dev_mask));
4053941Svenki int shift = sizeof (uint32_t)*8-1-card->slot;
4063941Svenki uint32_t x = (dev_mask << shift) >> shift;
4073941Svenki int count = 0; /* count # of 1's in x */
4083941Svenki int i = 0;
4093941Svenki while (x != 0) {
4103941Svenki count++;
4113941Svenki x &= x-1;
4123941Svenki }
4133941Svenki while (count > 1) {
4144669Sfw157321 while (p[i++] != '\0')
4154669Sfw157321 ;
4163941Svenki count--;
4173941Svenki }
4184003Svivek (void) strlcpy(card->slot_str, (char *)(p+i),
4194669Sfw157321 sizeof (card->slot_str));
4203941Svenki }
4213941Svenki free(pval);
4223941Svenki }
4233941Svenki
4243941Svenki /*
4253941Svenki * add all io devices under pci in io list
4263941Svenki */
4273941Svenki /* ARGSUSED */
4283941Svenki static int
sun4v_pci_callback(picl_nodehdl_t pcih,void * args)4293941Svenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args)
4303941Svenki {
4313941Svenki char path[PICL_PROPNAMELEN_MAX];
4323941Svenki char class[PICL_CLASSNAMELEN_MAX];
4333941Svenki char name[PICL_PROPNAMELEN_MAX];
4343941Svenki char model[PICL_PROPNAMELEN_MAX];
4353941Svenki char binding_name[PICL_PROPNAMELEN_MAX];
4363941Svenki char val[PICL_PROPNAMELEN_MAX];
4373941Svenki char *compatible;
4383941Svenki picl_errno_t err;
4395819Sfw157321 picl_nodehdl_t nodeh, pnodeh;
4403941Svenki struct io_card pci_card;
4413941Svenki
4423941Svenki /* Walk through the children */
4433941Svenki
4443941Svenki err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
4454669Sfw157321 sizeof (picl_nodehdl_t));
4463941Svenki
4473941Svenki while (err == PICL_SUCCESS) {
4483941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
4494669Sfw157321 class, sizeof (class));
4503941Svenki if (err != PICL_SUCCESS)
4513941Svenki return (err);
4523941Svenki
4533941Svenki if (args) {
4543941Svenki char *val = args;
4553941Svenki if (strcmp(class, val) == 0) {
4563941Svenki err = picl_get_propval_by_name(nodeh,
4574669Sfw157321 PICL_PROP_PEER, &nodeh,
4584669Sfw157321 sizeof (picl_nodehdl_t));
4593941Svenki continue;
4603941Svenki } else if (strcmp(val, PICL_CLASS_PCIEX) == 0 &&
4614669Sfw157321 strcmp(class, PICL_CLASS_PCI) == 0) {
4623941Svenki err = picl_get_propval_by_name(nodeh,
4634669Sfw157321 PICL_PROP_PEER, &nodeh,
4644669Sfw157321 sizeof (picl_nodehdl_t));
4653941Svenki continue;
4663941Svenki } else if (strcmp(val, PICL_CLASS_PCI) == 0 &&
4674669Sfw157321 strcmp(class, PICL_CLASS_PCIEX) == 0) {
4683941Svenki err = picl_get_propval_by_name(nodeh,
4694669Sfw157321 PICL_PROP_PEER, &nodeh,
4704669Sfw157321 sizeof (picl_nodehdl_t));
4713941Svenki continue;
4723941Svenki }
4733941Svenki }
4743941Svenki
4753941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
4764669Sfw157321 path, sizeof (path));
4773941Svenki if (err != PICL_SUCCESS)
4783941Svenki return (err);
4793941Svenki
4803941Svenki (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
4813941Svenki
4825819Sfw157321 pnodeh = nodeh;
4835819Sfw157321 err = get_slot_label(nodeh, &pci_card);
4845819Sfw157321
4855819Sfw157321 /*
4865819Sfw157321 * No Label at this node, maybe we're looking at a device
4875819Sfw157321 * downstream of a bridge. Walk back up and find a Label and
4885819Sfw157321 * record that node in "pnodeh".
4895819Sfw157321 */
4905819Sfw157321 while (err != PICL_SUCCESS) {
4915819Sfw157321 if (err != PICL_PROPNOTFOUND)
4925819Sfw157321 break;
4935819Sfw157321 else if (picl_get_propval_by_name(pnodeh,
4945819Sfw157321 PICL_PROP_PARENT, &pnodeh, sizeof (pnodeh)) ==
4955819Sfw157321 PICL_SUCCESS)
4965819Sfw157321 err = get_slot_label(pnodeh, &pci_card);
4975819Sfw157321 else
4985819Sfw157321 break;
4995819Sfw157321 }
5005819Sfw157321
5015819Sfw157321 /*
5025819Sfw157321 * Can't find a Label for this device in the PCI heirarchy.
5035819Sfw157321 * Try to synthesize a slot name from atoms. This depends
5045819Sfw157321 * on the OBP slot_names property being implemented, and this
5055819Sfw157321 * so far doesn't seem to be on sun4v. But just in case that
5065819Sfw157321 * is resurrected, the code is here.
5075819Sfw157321 */
5085819Sfw157321 if (err != PICL_SUCCESS) {
5095819Sfw157321 pnodeh = nodeh;
5105819Sfw157321 get_slot_number(nodeh, &pci_card);
5115819Sfw157321 }
5125819Sfw157321
5135819Sfw157321 /*
5145819Sfw157321 * Passing in pnodeh instead of nodeh will cause prtdiag
5155819Sfw157321 * to display the type of IO slot for the leaf node. For
5165819Sfw157321 * built-in devices and a lot of IO cards these will be
5175819Sfw157321 * the same thing. But for IO cards with bridge chips or
5185819Sfw157321 * for things like expansion chassis, prtdiag will report
5195819Sfw157321 * the bus type of the IO slot and not the leaf, which
5205819Sfw157321 * could be different things.
5215819Sfw157321 */
5225819Sfw157321 get_bus_type(pnodeh, &pci_card);
5233941Svenki
5243941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name,
5254669Sfw157321 sizeof (name));
5263941Svenki if (err == PICL_PROPNOTFOUND)
5274003Svivek (void) strlcpy(name, "", sizeof (name));
5283941Svenki else if (err != PICL_SUCCESS)
5293941Svenki return (err);
5303941Svenki
5313941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val,
5324669Sfw157321 sizeof (val));
5333941Svenki if (err == PICL_PROPNOTFOUND)
5344003Svivek (void) strlcpy(val, "", sizeof (val));
5353941Svenki else if (err != PICL_SUCCESS)
5363941Svenki return (err);
5373941Svenki
5385436Sfw157321 (void) snprintf(pci_card.status, sizeof (pci_card.status),
5395436Sfw157321 "%s", pci_card.slot_str);
5403941Svenki
5413941Svenki /*
5423941Svenki * Get the name of this card. If binding_name is found,
5433941Svenki * name will be <nodename>-<binding_name>.
5443941Svenki */
5453941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
5464669Sfw157321 binding_name, sizeof (binding_name));
5473941Svenki if (err == PICL_SUCCESS) {
5483941Svenki if (strcmp(name, binding_name) != 0) {
5493941Svenki (void) strlcat(name, "-", sizeof (name));
5503941Svenki (void) strlcat(name, binding_name,
5514669Sfw157321 sizeof (name));
5523941Svenki }
5533941Svenki } else if (err == PICL_PROPNOTFOUND) {
5543941Svenki /*
5553941Svenki * if compatible prop is not found, name will be
5563941Svenki * <nodename>-<compatible>
5573941Svenki */
5583941Svenki err = sun4v_get_first_compatible_value(nodeh,
5594669Sfw157321 &compatible);
5603941Svenki if (err == PICL_SUCCESS) {
5613941Svenki (void) strlcat(name, "-", sizeof (name));
5624003Svivek (void) strlcat(name, compatible,
5634669Sfw157321 sizeof (name));
5643941Svenki free(compatible);
5653941Svenki }
5663941Svenki } else
5673941Svenki return (err);
5683941Svenki
5693941Svenki (void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
5703941Svenki
5713941Svenki /* Get the model of this card */
5723941Svenki
5733941Svenki err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
5744669Sfw157321 model, sizeof (model));
5753941Svenki if (err == PICL_PROPNOTFOUND)
5764003Svivek (void) strlcpy(model, "", sizeof (model));
5773941Svenki else if (err != PICL_SUCCESS)
5783941Svenki return (err);
5793941Svenki (void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
5803941Svenki
5813941Svenki /* Print NAC name */
5824802Sfw157321 log_printf("%-18s", pci_card.status);
5833941Svenki /* Print IO Type */
5843941Svenki log_printf("%-6s", pci_card.bus_type);
5853941Svenki /* Printf Card Name */
5865544Sfw157321 log_printf("%-34s", pci_card.name);
5873941Svenki /* Print Card Model */
5883941Svenki log_printf("%-8s", pci_card.model);
5893941Svenki log_printf("\n");
5903941Svenki /* Print Status */
5914802Sfw157321 log_printf("%-18s", val);
5923941Svenki /* Print IO Type */
5933941Svenki log_printf("%-6s", "");
5943941Svenki /* Print Parent Path */
5954802Sfw157321 log_printf("%-44s", pci_card.notes);
5963941Svenki log_printf("\n");
5973941Svenki
5983941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
5994669Sfw157321 sizeof (picl_nodehdl_t));
6003941Svenki }
6013941Svenki return (PICL_WALK_CONTINUE);
6021708Sstevel }
6031708Sstevel
6041708Sstevel /*
6051708Sstevel * display_pci
6061708Sstevel * Display all the PCI IO cards on this board.
6071708Sstevel */
6081708Sstevel void
sun4v_display_pci(picl_nodehdl_t plafh)6091708Sstevel sun4v_display_pci(picl_nodehdl_t plafh)
6101708Sstevel {
6115544Sfw157321 char *fmt = "%-17s %-5s %-33s %-8s";
6123941Svenki /* Have we printed the column headings? */
6133941Svenki static int banner = FALSE;
6143941Svenki
6153941Svenki if (banner == FALSE) {
6163941Svenki log_printf("\n");
6174802Sfw157321 log_printf("================================");
6183941Svenki log_printf(" IO Devices ");
6194802Sfw157321 log_printf("================================");
6203941Svenki log_printf("\n");
6213941Svenki log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0);
6223941Svenki log_printf("\n");
6233941Svenki log_printf(fmt, "Status", "Type", "Path", "", 0);
6243941Svenki log_printf("\n");
6253941Svenki log_printf("---------------------------------"
6264802Sfw157321 "-------------------------------------------\n");
6273941Svenki banner = TRUE;
6283941Svenki }
6293941Svenki
6303941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
6314669Sfw157321 PICL_CLASS_PCIEX, sun4v_pci_callback);
6323941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
6334669Sfw157321 PICL_CLASS_PCI, sun4v_pci_callback);
6343941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V,
6354669Sfw157321 PICL_CLASS_SUN4V, sun4v_pci_callback);
6363941Svenki }
6373941Svenki
6383941Svenki /*
6393941Svenki * return the first compatible value
6403941Svenki */
6413941Svenki static int
sun4v_get_first_compatible_value(picl_nodehdl_t nodeh,char ** outbuf)6423941Svenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
6433941Svenki {
6443941Svenki picl_errno_t err;
6453941Svenki picl_prophdl_t proph;
6463941Svenki picl_propinfo_t pinfo;
6473941Svenki picl_prophdl_t tblh;
6483941Svenki picl_prophdl_t rowproph;
6493941Svenki char *pval;
6503941Svenki
6513941Svenki err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
6524669Sfw157321 &pinfo, &proph);
6533941Svenki if (err != PICL_SUCCESS)
6543941Svenki return (err);
6553941Svenki
6563941Svenki if (pinfo.type == PICL_PTYPE_CHARSTRING) {
6573941Svenki pval = malloc(pinfo.size);
6583941Svenki if (pval == NULL)
6593941Svenki return (PICL_FAILURE);
6603941Svenki err = picl_get_propval(proph, pval, pinfo.size);
6613941Svenki if (err != PICL_SUCCESS) {
6623941Svenki free(pval);
6633941Svenki return (err);
6643941Svenki }
6653941Svenki *outbuf = pval;
6663941Svenki return (PICL_SUCCESS);
6673941Svenki }
6683941Svenki
6693941Svenki if (pinfo.type != PICL_PTYPE_TABLE)
6703941Svenki return (PICL_FAILURE);
6713941Svenki
6723941Svenki /* get first string from table */
6733941Svenki err = picl_get_propval(proph, &tblh, pinfo.size);
6743941Svenki if (err != PICL_SUCCESS)
6753941Svenki return (err);
6763941Svenki
6773941Svenki err = picl_get_next_by_row(tblh, &rowproph);
6783941Svenki if (err != PICL_SUCCESS)
6793941Svenki return (err);
6803941Svenki
6813941Svenki err = picl_get_propinfo(rowproph, &pinfo);
6823941Svenki if (err != PICL_SUCCESS)
6833941Svenki return (err);
6843941Svenki
6853941Svenki pval = malloc(pinfo.size);
6863941Svenki if (pval == NULL)
6873941Svenki return (PICL_FAILURE);
6883941Svenki
6893941Svenki err = picl_get_propval(rowproph, pval, pinfo.size);
6903941Svenki if (err != PICL_SUCCESS) {
6913941Svenki free(pval);
6923941Svenki return (err);
6933941Svenki }
6943941Svenki
6953941Svenki *outbuf = pval;
6963941Svenki return (PICL_SUCCESS);
6971708Sstevel }
6981708Sstevel
6993941Svenki /*
7003941Svenki * print size of a memory segment
7013941Svenki */
7023941Svenki static void
print_memory_segment_size(uint64_t size)7033941Svenki print_memory_segment_size(uint64_t size)
7043941Svenki {
7053941Svenki uint64_t kbyte = 1024;
7063941Svenki uint64_t mbyte = kbyte * kbyte;
7073941Svenki uint64_t gbyte = kbyte * mbyte;
7085544Sfw157321 uint64_t tbyte = kbyte * gbyte;
7093941Svenki char buf[MEMORY_SIZE_FIELD];
7103941Svenki
7115544Sfw157321 if (size >= tbyte) {
7125544Sfw157321 if (size % tbyte == 0)
7135544Sfw157321 (void) snprintf(buf, sizeof (buf), "%d TB",
7145544Sfw157321 (int)(size / tbyte));
7155544Sfw157321 else
7165544Sfw157321 (void) snprintf(buf, sizeof (buf), "%.2f TB",
7175544Sfw157321 (float)size / tbyte);
7185544Sfw157321 } else if (size >= gbyte) {
7193941Svenki if (size % gbyte == 0)
7203941Svenki (void) snprintf(buf, sizeof (buf), "%d GB",
7214669Sfw157321 (int)(size / gbyte));
7223941Svenki else
7233941Svenki (void) snprintf(buf, sizeof (buf), "%.2f GB",
7244669Sfw157321 (float)size / gbyte);
7253941Svenki } else if (size >= mbyte) {
7263941Svenki if (size % mbyte == 0)
7273941Svenki (void) snprintf(buf, sizeof (buf), "%d MB",
7284669Sfw157321 (int)(size / mbyte));
7293941Svenki else
7303941Svenki (void) snprintf(buf, sizeof (buf), "%.2f MB",
7314669Sfw157321 (float)size / mbyte);
7323941Svenki } else {
7333941Svenki if (size % kbyte == 0)
7343941Svenki (void) snprintf(buf, sizeof (buf), "%d KB",
7354669Sfw157321 (int)(size / kbyte));
7363941Svenki else
7373941Svenki (void) snprintf(buf, sizeof (buf), "%.2f KB",
7384669Sfw157321 (float)size / kbyte);
7393941Svenki }
7405544Sfw157321 log_printf("%-9s", buf);
7413941Svenki }
7423941Svenki
7433941Svenki /*
7444669Sfw157321 * Enumerate banks and dimms within a memory segment. We're handed
7454669Sfw157321 * the first bank within the segment - we assume there are dimms
7464669Sfw157321 * (memory-module) nodes underneath.
7473941Svenki */
7483941Svenki static void
print_memory_segment_contain(picl_nodehdl_t bank_nodeh)7494669Sfw157321 print_memory_segment_contain(picl_nodehdl_t bank_nodeh)
7501708Sstevel {
7513941Svenki char val[PICL_PROPNAMELEN_MAX];
7524669Sfw157321 picl_nodehdl_t module_nodeh;
7534669Sfw157321 int flag = 0;
7545544Sfw157321 uint64_t size;
7554669Sfw157321
7564669Sfw157321 do {
7574669Sfw157321 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD,
7584669Sfw157321 &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS)
7594669Sfw157321 continue;
7605544Sfw157321 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_SIZE,
7615544Sfw157321 &size, sizeof (size)) == PICL_SUCCESS) {
7625544Sfw157321 if (!flag) {
7635544Sfw157321 print_memory_segment_size(size);
7645544Sfw157321 } else {
7655544Sfw157321 log_printf(" "
7665544Sfw157321 " ");
7675544Sfw157321 print_memory_segment_size(size);
7685544Sfw157321 flag = 0;
7695544Sfw157321 }
7705544Sfw157321 }
7714669Sfw157321 do {
7724669Sfw157321 if (picl_get_propval_by_name(module_nodeh,
7734669Sfw157321 PICL_PROP_NAC, val, sizeof (val)) !=
7744669Sfw157321 PICL_SUCCESS)
7754669Sfw157321 continue;
7764669Sfw157321 else {
7774669Sfw157321 if (!flag) {
7785544Sfw157321 log_printf("%s\n", val);
7794669Sfw157321 flag = 1;
7805544Sfw157321 } else {
7815544Sfw157321 log_printf("%s%s\n",
7825544Sfw157321 " "
7835544Sfw157321 " ",
7845544Sfw157321 val);
7855544Sfw157321 }
7864669Sfw157321 }
7874669Sfw157321 } while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER,
7884669Sfw157321 &module_nodeh, sizeof (picl_nodehdl_t)) ==
7894669Sfw157321 PICL_SUCCESS);
7904669Sfw157321 } while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER,
7914669Sfw157321 &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS);
7923941Svenki }
7933941Svenki
7943941Svenki /*
7953941Svenki * Search node where _class=="memory-segment"
7963941Svenki * print "Base Address", "Size", etc
7973941Svenki */
7983941Svenki /*ARGSUSED*/
7993941Svenki static int
sun4v_memory_conf_callback(picl_nodehdl_t nodeh,void * args)8003941Svenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args)
8013941Svenki {
8023941Svenki uint64_t base;
8033941Svenki uint64_t size;
8043941Svenki uint64_t ifactor;
8053941Svenki picl_errno_t err = PICL_SUCCESS;
8063941Svenki
8073941Svenki if (class_node_found == 0) {
8083941Svenki class_node_found = 1;
8093941Svenki return (PICL_WALK_TERMINATE);
8103941Svenki }
8113941Svenki while (err == PICL_SUCCESS) {
8123941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS,
8134669Sfw157321 &base, sizeof (base));
8143941Svenki if (err != PICL_SUCCESS)
8153941Svenki break;
8163941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE,
8174669Sfw157321 &size, sizeof (size));
8183941Svenki if (err != PICL_SUCCESS)
8193941Svenki break;
8203941Svenki err = picl_get_propval_by_name(nodeh,
8214669Sfw157321 PICL_PROP_INTERLEAVE_FACTOR, &ifactor,
8224669Sfw157321 sizeof (ifactor));
8233941Svenki if (err != PICL_SUCCESS)
8243941Svenki break;
8255544Sfw157321 log_printf("0x%-13llx", base);
8263941Svenki print_memory_segment_size(size);
8275544Sfw157321 log_printf("%-12lld", ifactor);
8284669Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
8294669Sfw157321 &nodeh, sizeof (nodeh));
8304669Sfw157321 if (err == PICL_SUCCESS)
8314669Sfw157321 print_memory_segment_contain(nodeh);
8323941Svenki log_printf("\n");
8333941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
8344669Sfw157321 sizeof (picl_nodehdl_t));
8353941Svenki }
8363941Svenki
8373941Svenki return (PICL_WALK_CONTINUE);
8383941Svenki }
8393941Svenki
8403941Svenki /*ARGSUSED*/
8413941Svenki void
sun4v_display_memory_conf(picl_nodehdl_t plafh)8423941Svenki sun4v_display_memory_conf(picl_nodehdl_t plafh)
8433941Svenki {
8445544Sfw157321 char *fmt = "%-14s %-8s %-11s %-8s %-s";
8453941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
8464669Sfw157321 NULL, sun4v_memory_conf_callback);
8473941Svenki if (class_node_found == 0)
8483941Svenki return;
8493941Svenki log_printf("\n");
8505544Sfw157321 log_printf("=======================");
8515544Sfw157321 log_printf(" Physical Memory Configuration ");
8525544Sfw157321 log_printf("========================");
8533941Svenki log_printf("\n");
8543941Svenki log_printf("Segment Table:\n");
8554669Sfw157321 log_printf(
8565544Sfw157321 "--------------------------------------------------------------\n");
8575544Sfw157321 log_printf(fmt, "Base", "Segment", "Interleave", "Bank", "Contains", 0);
8585544Sfw157321 log_printf("\n");
8595544Sfw157321 log_printf(fmt, "Address", "Size", "Factor", "Size", "Modules", 0);
8603941Svenki log_printf("\n");
8614669Sfw157321 log_printf(
8625544Sfw157321 "--------------------------------------------------------------\n");
8633941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
8644669Sfw157321 NULL, sun4v_memory_conf_callback);
8651708Sstevel }
8661708Sstevel
8671708Sstevel void
sun4v_display_cpu_devices(picl_nodehdl_t plafh)8681708Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh)
8691708Sstevel {
8705544Sfw157321 char *fmt = "%-6s %-9s %-22s %-6s";
8711708Sstevel
8721708Sstevel /*
8731708Sstevel * Display the table header for CPUs . Then display the CPU
8741708Sstevel * frequency, cache size, and processor revision of all cpus.
8751708Sstevel */
8761708Sstevel log_printf(dgettext(TEXT_DOMAIN,
8774669Sfw157321 "\n"
8785544Sfw157321 "================================"
8795544Sfw157321 " Virtual CPUs "
8805544Sfw157321 "================================"
8814669Sfw157321 "\n"
8824669Sfw157321 "\n"));
8831708Sstevel log_printf("\n");
8845544Sfw157321 log_printf(fmt, "CPU ID", "Frequency", "Implementation",
8855544Sfw157321 "Status", 0);
8861708Sstevel log_printf("\n");
8875544Sfw157321 log_printf(fmt, "------", "---------",
8885544Sfw157321 "----------------------", "-------", 0);
8891708Sstevel log_printf("\n");
8901708Sstevel
8915544Sfw157321 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU,
8925544Sfw157321 sun4v_display_cpus);
8931708Sstevel }
8941708Sstevel
8951708Sstevel /*
8961708Sstevel * Display the CPUs present on this board.
8971708Sstevel */
8981708Sstevel /*ARGSUSED*/
8991708Sstevel int
sun4v_display_cpus(picl_nodehdl_t cpuh,void * args)9001708Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
9011708Sstevel {
9021708Sstevel int status;
9033941Svenki picl_prophdl_t proph;
9043941Svenki picl_prophdl_t tblh;
9053941Svenki picl_prophdl_t rowproph;
9061708Sstevel picl_propinfo_t propinfo;
9073941Svenki int *int_value;
9085028Sfw157321 int cpuid;
9093941Svenki char *comp_value;
9103941Svenki char *no_prop_value = " ";
9113941Svenki char freq_str[MAXSTRLEN];
9125028Sfw157321 char state[MAXSTRLEN];
9131708Sstevel
9141708Sstevel /*
9151708Sstevel * Get cpuid property and print it and the NAC name
9161708Sstevel */
9175544Sfw157321 status = picl_get_propinfo_by_name(cpuh, OBP_PROP_CPUID, &propinfo,
9185544Sfw157321 &proph);
9191708Sstevel if (status == PICL_SUCCESS) {
9201708Sstevel status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
9211708Sstevel if (status != PICL_SUCCESS) {
9225544Sfw157321 log_printf("%-7s", no_prop_value);
9231708Sstevel } else {
9245544Sfw157321 log_printf("%-7d", cpuid);
9251708Sstevel }
9261708Sstevel } else {
9275544Sfw157321 log_printf("%-7s", no_prop_value);
9281708Sstevel }
9291708Sstevel
9301708Sstevel clock_freq:
9311708Sstevel status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
9324669Sfw157321 &proph);
9331708Sstevel if (status == PICL_SUCCESS) {
9341708Sstevel int_value = malloc(propinfo.size);
9351708Sstevel if (int_value == NULL) {
9365544Sfw157321 log_printf("%-10s", no_prop_value);
9371708Sstevel goto compatible;
9381708Sstevel }
9391708Sstevel status = picl_get_propval(proph, int_value, propinfo.size);
9401708Sstevel if (status != PICL_SUCCESS) {
9415544Sfw157321 log_printf("%-10s", no_prop_value);
9421708Sstevel } else {
9431708Sstevel /* Running frequency */
9441708Sstevel (void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
9451708Sstevel CLK_FREQ_TO_MHZ(*int_value));
9465544Sfw157321 log_printf("%-10s", freq_str);
9471708Sstevel }
9481708Sstevel free(int_value);
9491708Sstevel } else
9505544Sfw157321 log_printf("%-10s", no_prop_value);
9511708Sstevel
9521708Sstevel compatible:
9531708Sstevel status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
9544669Sfw157321 &proph);
9551708Sstevel if (status == PICL_SUCCESS) {
9561708Sstevel if (propinfo.type == PICL_PTYPE_CHARSTRING) {
9571708Sstevel /*
9581708Sstevel * Compatible Property only has 1 value
9591708Sstevel */
9601708Sstevel comp_value = malloc(propinfo.size);
9611708Sstevel if (comp_value == NULL) {
9625544Sfw157321 log_printf("%-23s", no_prop_value, 0);
9635028Sfw157321 goto state;
9641708Sstevel }
9651708Sstevel status = picl_get_propval(proph, comp_value,
9664669Sfw157321 propinfo.size);
9673941Svenki if (status != PICL_SUCCESS)
9685544Sfw157321 log_printf("%-23s", no_prop_value, 0);
9693941Svenki else
9705544Sfw157321 log_printf("%-23s", comp_value, 0);
9713941Svenki free(comp_value);
9721708Sstevel } else if (propinfo.type == PICL_PTYPE_TABLE) {
9731708Sstevel /*
9741708Sstevel * Compatible Property has multiple values
9751708Sstevel */
9761708Sstevel status = picl_get_propval(proph, &tblh, propinfo.size);
9771708Sstevel if (status != PICL_SUCCESS) {
9785544Sfw157321 log_printf("%-23s", no_prop_value, 0);
9795028Sfw157321 goto state;
9801708Sstevel }
9811708Sstevel status = picl_get_next_by_row(tblh, &rowproph);
9821708Sstevel if (status != PICL_SUCCESS) {
9835544Sfw157321 log_printf("%-23s", no_prop_value, 0);
9845028Sfw157321 goto state;
9851708Sstevel }
9861708Sstevel
9871708Sstevel status = picl_get_propinfo(rowproph, &propinfo);
9881708Sstevel if (status != PICL_SUCCESS) {
9895544Sfw157321 log_printf("%-23s", no_prop_value, 0);
9905028Sfw157321 goto state;
9911708Sstevel }
9921708Sstevel
9931708Sstevel comp_value = malloc(propinfo.size);
9941708Sstevel if (comp_value == NULL) {
9955544Sfw157321 log_printf("%-23s", no_prop_value, 0);
9965028Sfw157321 goto state;
9971708Sstevel }
9981708Sstevel status = picl_get_propval(rowproph, comp_value,
9994669Sfw157321 propinfo.size);
10003941Svenki if (status != PICL_SUCCESS)
10015544Sfw157321 log_printf("%-23s", no_prop_value, 0);
10023941Svenki else
10035544Sfw157321 log_printf("%-23s", comp_value, 0);
10041708Sstevel free(comp_value);
10051708Sstevel }
10061708Sstevel } else
10075544Sfw157321 log_printf("%-23s", no_prop_value, 0);
10081708Sstevel
10095028Sfw157321 state:
10105028Sfw157321 status = picl_get_propinfo_by_name(cpuh, PICL_PROP_STATE,
10115028Sfw157321 &propinfo, &proph);
10121708Sstevel if (status == PICL_SUCCESS) {
10135028Sfw157321 status = picl_get_propval(proph, state, sizeof (state));
10141708Sstevel if (status != PICL_SUCCESS) {
10153941Svenki log_printf("%-9s", no_prop_value);
10161708Sstevel } else {
10175028Sfw157321 log_printf("%-9s", state);
10181708Sstevel }
10191708Sstevel } else
10203941Svenki log_printf("%-9s", no_prop_value);
10211708Sstevel
10221708Sstevel done:
10231708Sstevel log_printf("\n");
10241708Sstevel return (PICL_WALK_CONTINUE);
10251708Sstevel }
10261708Sstevel
10271708Sstevel void
sun4v_display_diaginfo(int flag,Prom_node * root,picl_nodehdl_t plafh)10281708Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
10291708Sstevel {
10301708Sstevel #ifdef lint
10311708Sstevel flag = flag;
10321708Sstevel root = root;
10331708Sstevel plafh = plafh;
10341708Sstevel #endif
10351708Sstevel /*
10361708Sstevel * This function is intentionally empty
10371708Sstevel */
10381708Sstevel }
10391708Sstevel
10401708Sstevel void
display_boardnum(int num)10411708Sstevel display_boardnum(int num)
10421708Sstevel {
10431708Sstevel log_printf("%2d ", num, 0);
10441708Sstevel }
10453941Svenki
10465547Smb158278 static int
sun4v_disp_env_status()10473941Svenki sun4v_disp_env_status()
10483941Svenki {
10495547Smb158278 int exit_code = 0;
10505547Smb158278
10513941Svenki if (phyplatformh == 0)
10525547Smb158278 return (0);
10533941Svenki log_printf("\n");
10543941Svenki log_printf("============================");
10553941Svenki log_printf(" Environmental Status ");
10563941Svenki log_printf("============================");
10573941Svenki log_printf("\n");
10583941Svenki
10593941Svenki class_node_found = 0;
10603941Svenki all_status_ok = 1;
10613941Svenki sun4v_env_print_fan_sensors();
10625547Smb158278 exit_code |= (!all_status_ok);
10633941Svenki
10643941Svenki class_node_found = 0;
10653941Svenki all_status_ok = 1;
10663941Svenki sun4v_env_print_fan_indicators();
10675547Smb158278 exit_code |= (!all_status_ok);
10683941Svenki
10693941Svenki class_node_found = 0;
10703941Svenki all_status_ok = 1;
10713941Svenki sun4v_env_print_temp_sensors();
10725547Smb158278 exit_code |= (!all_status_ok);
10733941Svenki
10743941Svenki class_node_found = 0;
10753941Svenki all_status_ok = 1;
10763941Svenki sun4v_env_print_temp_indicators();
10775547Smb158278 exit_code |= (!all_status_ok);
10783941Svenki
10793941Svenki class_node_found = 0;
10803941Svenki all_status_ok = 1;
10813941Svenki sun4v_env_print_current_sensors();
10825547Smb158278 exit_code |= (!all_status_ok);
10833941Svenki
10843941Svenki class_node_found = 0;
10853941Svenki all_status_ok = 1;
10863941Svenki sun4v_env_print_current_indicators();
10875547Smb158278 exit_code |= (!all_status_ok);
10883941Svenki
10893941Svenki class_node_found = 0;
10903941Svenki all_status_ok = 1;
10913941Svenki sun4v_env_print_voltage_sensors();
10925547Smb158278 exit_code |= (!all_status_ok);
10933941Svenki
10943941Svenki class_node_found = 0;
10953941Svenki all_status_ok = 1;
10963941Svenki sun4v_env_print_voltage_indicators();
10975547Smb158278 exit_code |= (!all_status_ok);
10983941Svenki
10993941Svenki class_node_found = 0;
11005547Smb158278 all_status_ok = 1;
11013941Svenki sun4v_env_print_LEDs();
11025547Smb158278 exit_code |= (!all_status_ok);
11033941Svenki
11043941Svenki class_node_found = 0;
11053941Svenki all_status_ok = 1;
11063941Svenki sun4v_print_fru_status();
11075547Smb158278 exit_code |= (!all_status_ok);
11083941Svenki
11093941Svenki class_node_found = 0;
11103941Svenki sun4v_print_fw_rev();
11113941Svenki
11125436Sfw157321 class_node_found = 0;
11135436Sfw157321 sun4v_print_openprom_rev();
11145436Sfw157321
11153941Svenki sun4v_print_chassis_serial_no();
11165547Smb158278
11175547Smb158278 return (exit_code);
11183941Svenki }
11193941Svenki
11203941Svenki /*ARGSUSED*/
11213941Svenki static int
sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh,void * args)11223941Svenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args)
11233941Svenki {
11243941Svenki char val[PICL_PROPNAMELEN_MAX];
11253941Svenki picl_nodehdl_t parenth;
11263941Svenki char *names[PARENT_NAMES];
11274802Sfw157321 char *base_units[PICL_PROPNAMELEN_MAX];
11283941Svenki char *loc;
11293941Svenki int i;
11303941Svenki char *prop;
11313941Svenki picl_errno_t err;
11325436Sfw157321 int32_t lo_warning, lo_shutdown, lo_poweroff;
11335436Sfw157321 int32_t hi_warning, hi_shutdown, hi_poweroff;
11343941Svenki int32_t current_val;
11354802Sfw157321 int32_t exponent;
11364802Sfw157321 double display_val;
11374928Sfw157321 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
11384928Sfw157321 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
11394928Sfw157321 sensor_status_t sensor_status = SENSOR_OK;
11403941Svenki
11413941Svenki if (class_node_found == 0) {
11423941Svenki class_node_found = 1;
11433941Svenki return (PICL_WALK_TERMINATE);
11443941Svenki }
11453941Svenki
11464928Sfw157321 prop = (char *)args;
11474928Sfw157321 if (!prop) {
11484928Sfw157321 sensor_status = SENSOR_UNKNOWN;
11494928Sfw157321 all_status_ok = 0;
11504928Sfw157321 } else {
11513941Svenki err = picl_get_propval_by_name(nodeh,
11524669Sfw157321 PICL_PROP_OPERATIONAL_STATUS, val,
11534669Sfw157321 sizeof (val));
11543941Svenki if (err == PICL_SUCCESS) {
11553941Svenki if (strcmp(val, "disabled") == 0) {
11564928Sfw157321 sensor_status = SENSOR_DISABLED;
11574928Sfw157321 }
11584928Sfw157321 }
11594928Sfw157321 }
11604928Sfw157321
11614928Sfw157321 if (sensor_status != SENSOR_DISABLED &&
11624928Sfw157321 sensor_status != SENSOR_UNKNOWN) {
11634928Sfw157321 if (picl_get_propval_by_name(nodeh, prop, ¤t_val,
11644928Sfw157321 sizeof (current_val)) != PICL_SUCCESS) {
11654928Sfw157321 sensor_status = SENSOR_UNKNOWN;
11665436Sfw157321 } else {
11675436Sfw157321 if (picl_get_propval_by_name(nodeh,
11685436Sfw157321 PICL_PROP_LOW_WARNING,
11695436Sfw157321 &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS)
11705436Sfw157321 lo_warning = INVALID_THRESHOLD;
11715436Sfw157321 if (picl_get_propval_by_name(nodeh,
11725436Sfw157321 PICL_PROP_LOW_SHUTDOWN,
11735436Sfw157321 &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS)
11745436Sfw157321 lo_shutdown = INVALID_THRESHOLD;
11755436Sfw157321 if (picl_get_propval_by_name(nodeh,
11765436Sfw157321 PICL_PROP_LOW_POWER_OFF,
11775436Sfw157321 &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS)
11785436Sfw157321 lo_poweroff = INVALID_THRESHOLD;
11795436Sfw157321 if (picl_get_propval_by_name(nodeh,
11805436Sfw157321 PICL_PROP_HIGH_WARNING,
11815436Sfw157321 &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS)
11825436Sfw157321 hi_warning = INVALID_THRESHOLD;
11835436Sfw157321 if (picl_get_propval_by_name(nodeh,
11845436Sfw157321 PICL_PROP_HIGH_SHUTDOWN,
11855436Sfw157321 &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS)
11865436Sfw157321 hi_shutdown = INVALID_THRESHOLD;
11875436Sfw157321 if (picl_get_propval_by_name(nodeh,
11885436Sfw157321 PICL_PROP_HIGH_POWER_OFF,
11895436Sfw157321 &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS)
11905436Sfw157321 hi_poweroff = INVALID_THRESHOLD;
11914928Sfw157321
11925436Sfw157321 if ((lo_poweroff != INVALID_THRESHOLD &&
11935436Sfw157321 current_val <= lo_poweroff) ||
11945436Sfw157321 (hi_poweroff != INVALID_THRESHOLD &&
11955436Sfw157321 current_val >= hi_poweroff)) {
11965436Sfw157321 sensor_status = SENSOR_FAILED;
11975436Sfw157321 } else if ((lo_shutdown != INVALID_THRESHOLD &&
11985436Sfw157321 current_val <= lo_shutdown) ||
11995436Sfw157321 (hi_shutdown != INVALID_THRESHOLD &&
12005436Sfw157321 current_val >= hi_shutdown)) {
12015436Sfw157321 sensor_status = SENSOR_FAILED;
12025436Sfw157321 } else if ((lo_warning != INVALID_THRESHOLD &&
12035436Sfw157321 current_val <= lo_warning) ||
12045436Sfw157321 (hi_warning != INVALID_THRESHOLD &&
12055436Sfw157321 current_val >= hi_warning)) {
12065436Sfw157321 sensor_status = SENSOR_WARN;
12075436Sfw157321 } else {
12085436Sfw157321 sensor_status = SENSOR_OK;
12095436Sfw157321 }
12104928Sfw157321 }
12114928Sfw157321 }
12124928Sfw157321
12134928Sfw157321 if (syserrlog == 0) {
12144928Sfw157321 if (sensor_status != SENSOR_OK && all_status_ok == 1) {
12153941Svenki all_status_ok = 0;
12163941Svenki return (PICL_WALK_TERMINATE);
12173941Svenki }
12184928Sfw157321 if (sensor_status == SENSOR_OK) {
12194928Sfw157321 return (PICL_WALK_CONTINUE);
12204928Sfw157321 }
122112046SMichael.Bergknoff@Sun.COM } else {
122212046SMichael.Bergknoff@Sun.COM if (sensor_status != SENSOR_OK && all_status_ok == 1) {
122312046SMichael.Bergknoff@Sun.COM all_status_ok = 0;
122412046SMichael.Bergknoff@Sun.COM }
12253941Svenki }
12264928Sfw157321
12274928Sfw157321 /*
12284928Sfw157321 * If we're here then prtdiag was invoked with "-v" or we have
12294928Sfw157321 * a sensor that is beyond a threshold, so give them a book to
12304928Sfw157321 * read instead of the Cliff Notes.
12314928Sfw157321 */
12323941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
12334669Sfw157321 sizeof (parenth));
12343941Svenki if (err != PICL_SUCCESS) {
12353941Svenki log_printf("\n");
12363941Svenki return (PICL_WALK_CONTINUE);
12373941Svenki }
12384003Svivek
12394928Sfw157321 /* gather up the path name for the sensor */
12404928Sfw157321 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
12414928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) {
12424928Sfw157321 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
12434928Sfw157321 NULL) {
12444928Sfw157321 while (--i > -1)
12454928Sfw157321 free(names[i]);
12464928Sfw157321 free(loc);
12474928Sfw157321 loc = NULL;
12484928Sfw157321 }
12493941Svenki }
12504003Svivek }
12514928Sfw157321 i = 0;
12524928Sfw157321 if (loc != 0) {
12534928Sfw157321 while (err == PICL_SUCCESS) {
12544928Sfw157321 if (parenth == phyplatformh)
12554928Sfw157321 break;
12564928Sfw157321 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
12574928Sfw157321 names[i++], PICL_PROPNAMELEN_MAX);
12584928Sfw157321 if (err != PICL_SUCCESS) {
12594928Sfw157321 i--;
12604928Sfw157321 break;
12614928Sfw157321 }
12624928Sfw157321 if (i == PARENT_NAMES)
12634928Sfw157321 break;
12644928Sfw157321 err = picl_get_propval_by_name(parenth,
12654928Sfw157321 PICL_PROP_PARENT, &parenth, sizeof (parenth));
12664928Sfw157321 }
12674928Sfw157321 loc[0] = '\0';
12684928Sfw157321 if (--i > -1) {
12694928Sfw157321 (void) strlcat(loc, names[i],
12704928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
12714928Sfw157321 }
12724928Sfw157321 while (--i > -1) {
12734928Sfw157321 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
12744928Sfw157321 PARENT_NAMES);
12754928Sfw157321 (void) strlcat(loc, names[i],
12764928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
12774928Sfw157321 }
12785028Sfw157321 log_printf("%-35s", loc);
12794928Sfw157321 for (i = 0; i < PARENT_NAMES; i++)
12804928Sfw157321 free(names[i]);
12814928Sfw157321 free(loc);
12824928Sfw157321 } else {
12835028Sfw157321 log_printf("%-35s", " ");
12843941Svenki }
12853941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
12864669Sfw157321 sizeof (val));
12873941Svenki if (err == PICL_SUCCESS)
128811659SSree.Vemuri@Sun.COM log_printf("%-19s", val);
12893941Svenki
12904928Sfw157321 /*
12914928Sfw157321 * Get the exponent if present, and do a little math so that
12924928Sfw157321 * if we need to we can print a normalized value for the
12934928Sfw157321 * sensor reading.
12944928Sfw157321 */
12954802Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT,
12964802Sfw157321 &exponent, sizeof (exponent)) != PICL_SUCCESS)
12974802Sfw157321 exponent = 0;
12984802Sfw157321 if (exponent == 0)
12994802Sfw157321 display_val = (double)current_val;
13005436Sfw157321 else {
13014802Sfw157321 display_val = (double)current_val *
13024802Sfw157321 pow((double)10, (double)exponent);
13035436Sfw157321
13045436Sfw157321 /*
13055436Sfw157321 * Sometimes ILOM will scale a sensor reading but
13065436Sfw157321 * there will be nothing to the right of the decimal
13075436Sfw157321 * once that value is normalized. Setting the
13085436Sfw157321 * exponent to zero will prevent the printf below
13095436Sfw157321 * from printing extraneous zeros. Otherwise a
13105436Sfw157321 * negative exponent is used to set the precision
13115436Sfw157321 * for the printf.
13125436Sfw157321 */
13135436Sfw157321 if ((int)display_val == display_val || exponent > 0)
13145436Sfw157321 exponent = 0;
13155436Sfw157321 }
13165436Sfw157321
13174928Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS,
13184928Sfw157321 base_units, sizeof (base_units));
13194802Sfw157321 if (err != PICL_SUCCESS)
13204802Sfw157321 base_units[0] = '\0';
13213941Svenki
13224928Sfw157321 switch (sensor_status) {
13234928Sfw157321 case SENSOR_FAILED:
13243941Svenki log_printf("%-s", "failed (");
13254802Sfw157321 log_printf("%-.*f", abs(exponent), display_val);
13264802Sfw157321 log_printf("%-s %s", base_units, ")");
13274928Sfw157321 break;
13284928Sfw157321 case SENSOR_WARN:
13293941Svenki log_printf("%-s", "warning (");
13304802Sfw157321 log_printf("%-.*f", abs(exponent), display_val);
13314802Sfw157321 log_printf("%-s %s", base_units, ")");
13324928Sfw157321 break;
13334928Sfw157321 case SENSOR_DISABLED:
13344928Sfw157321 log_printf("%-s", "disabled");
13354928Sfw157321 break;
13364928Sfw157321 case SENSOR_OK:
13373941Svenki log_printf("%-s", "ok");
13384928Sfw157321 break;
13394928Sfw157321 default:
13404928Sfw157321 log_printf("%-s", "unknown");
13414928Sfw157321 break;
13424928Sfw157321 }
13433941Svenki
13443941Svenki log_printf("\n");
13453941Svenki return (PICL_WALK_CONTINUE);
13463941Svenki }
13473941Svenki
13483941Svenki /*ARGSUSED*/
13493941Svenki static int
sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh,void * args)13503941Svenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args)
13513941Svenki {
13524928Sfw157321 char current_val[PICL_PROPNAMELEN_MAX];
13534928Sfw157321 char expected_val[PICL_PROPNAMELEN_MAX];
13544928Sfw157321 char label[PICL_PROPNAMELEN_MAX];
13553941Svenki picl_nodehdl_t parenth;
13563941Svenki char *names[PARENT_NAMES];
13573941Svenki char *loc;
13583941Svenki int i = 0;
13593941Svenki char *prop = (char *)args;
13603941Svenki picl_errno_t err = PICL_SUCCESS;
13614928Sfw157321 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED,
13624928Sfw157321 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t;
13634928Sfw157321 sensor_status_t sensor_status = SENSOR_OK;
13643941Svenki
13653941Svenki if (class_node_found == 0) {
13663941Svenki class_node_found = 1;
13673941Svenki return (PICL_WALK_TERMINATE);
13683941Svenki }
13694928Sfw157321
13704928Sfw157321 prop = (char *)args;
13714928Sfw157321 if (!prop) {
13724928Sfw157321 sensor_status = SENSOR_UNKNOWN;
13734928Sfw157321 all_status_ok = 0;
13744928Sfw157321 } else {
13753941Svenki err = picl_get_propval_by_name(nodeh,
13764928Sfw157321 PICL_PROP_OPERATIONAL_STATUS, current_val,
13774928Sfw157321 sizeof (current_val));
13783941Svenki if (err == PICL_SUCCESS) {
13794928Sfw157321 if (strcmp(current_val, "disabled") == 0) {
13804928Sfw157321 sensor_status = SENSOR_DISABLED;
13814928Sfw157321 }
13824928Sfw157321 }
13834928Sfw157321 }
13844928Sfw157321
13854928Sfw157321 if (sensor_status != SENSOR_DISABLED &&
13864928Sfw157321 sensor_status != SENSOR_UNKNOWN) {
13874928Sfw157321 if (picl_get_propval_by_name(nodeh, prop, ¤t_val,
13884928Sfw157321 sizeof (current_val)) != PICL_SUCCESS) {
13894928Sfw157321 (void) strlcpy(current_val, "unknown",
13904928Sfw157321 sizeof (current_val));
13914928Sfw157321 sensor_status = SENSOR_UNKNOWN;
13924928Sfw157321 } else {
13934928Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED,
139412046SMichael.Bergknoff@Sun.COM &expected_val, sizeof (expected_val)) ==
13954928Sfw157321 PICL_SUCCESS) {
13964928Sfw157321 if (strncmp(current_val, expected_val,
13974928Sfw157321 sizeof (current_val)) == 0) {
13984928Sfw157321 sensor_status = SENSOR_OK;
13994928Sfw157321 } else {
14004928Sfw157321 sensor_status = SENSOR_FAILED;
14013941Svenki }
14024928Sfw157321 }
14034928Sfw157321 }
14044928Sfw157321 }
14054928Sfw157321
14064928Sfw157321 if (syserrlog == 0) {
14074928Sfw157321 if (sensor_status != SENSOR_OK && all_status_ok == 1) {
14083941Svenki all_status_ok = 0;
14093941Svenki return (PICL_WALK_TERMINATE);
14103941Svenki }
14114928Sfw157321 if (sensor_status == SENSOR_OK) {
14124928Sfw157321 return (PICL_WALK_CONTINUE);
14134928Sfw157321 }
141412046SMichael.Bergknoff@Sun.COM } else {
141512046SMichael.Bergknoff@Sun.COM if (sensor_status != SENSOR_OK && all_status_ok == 1) {
141612046SMichael.Bergknoff@Sun.COM all_status_ok = 0;
141712046SMichael.Bergknoff@Sun.COM }
14183941Svenki }
14194928Sfw157321
14204928Sfw157321 /*
14214928Sfw157321 * If we're here then prtdiag was invoked with "-v" or we have
14224928Sfw157321 * a sensor that is beyond a threshold, so give them a book to
14234928Sfw157321 * read instead of the Cliff Notes.
14244928Sfw157321 */
14253941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
14264669Sfw157321 sizeof (parenth));
14273941Svenki if (err != PICL_SUCCESS) {
14283941Svenki log_printf("\n");
14293941Svenki return (PICL_WALK_CONTINUE);
14303941Svenki }
14314928Sfw157321 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) {
14324928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) {
14334928Sfw157321 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) ==
14344928Sfw157321 NULL) {
14354928Sfw157321 while (--i > -1)
14364928Sfw157321 free(names[i]);
14374928Sfw157321 free(loc);
14384928Sfw157321 loc = NULL;
14394928Sfw157321 }
14403941Svenki }
14413941Svenki }
14424928Sfw157321 i = 0;
14434928Sfw157321 if (loc) {
14444928Sfw157321 while (err == PICL_SUCCESS) {
14454928Sfw157321 if (parenth == phyplatformh)
14464928Sfw157321 break;
14474928Sfw157321 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
14484928Sfw157321 names[i++], PICL_PROPNAMELEN_MAX);
14494928Sfw157321 if (err != PICL_SUCCESS) {
14504928Sfw157321 i--;
14514928Sfw157321 break;
14524928Sfw157321 }
14534928Sfw157321 if (i == PARENT_NAMES)
14544928Sfw157321 break;
14554928Sfw157321 err = picl_get_propval_by_name(parenth,
14564928Sfw157321 PICL_PROP_PARENT, &parenth, sizeof (parenth));
14574928Sfw157321 }
14584928Sfw157321 loc[0] = '\0';
14594928Sfw157321 if (--i > -1) {
14604928Sfw157321 (void) strlcat(loc, names[i],
14614928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
14624928Sfw157321 }
14634928Sfw157321 while (--i > -1) {
14644928Sfw157321 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX *
14654928Sfw157321 PARENT_NAMES);
14664928Sfw157321 (void) strlcat(loc, names[i],
14674928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
14684928Sfw157321 }
14695028Sfw157321 log_printf("%-35s", loc);
14704928Sfw157321 for (i = 0; i < PARENT_NAMES; i++)
14714928Sfw157321 free(names[i]);
14724928Sfw157321 free(loc);
14734928Sfw157321 } else {
14745028Sfw157321 log_printf("%-35s", "");
14753941Svenki }
14764928Sfw157321
14774928Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
14784928Sfw157321 sizeof (label));
14794928Sfw157321 if (err != PICL_SUCCESS)
14804928Sfw157321 (void) strlcpy(label, "", sizeof (label));
148111659SSree.Vemuri@Sun.COM log_printf("%-19s", label);
14824928Sfw157321
14834928Sfw157321 log_printf("%-8s", current_val);
14844928Sfw157321
14853941Svenki log_printf("\n");
14863941Svenki return (PICL_WALK_CONTINUE);
14873941Svenki }
14883941Svenki
14893941Svenki static void
sun4v_env_print_fan_sensors()14903941Svenki sun4v_env_print_fan_sensors()
14913941Svenki {
149211659SSree.Vemuri@Sun.COM char *fmt = "%-34s %-18s %-10s\n";
14933941Svenki /*
14943941Svenki * If there isn't any fan sensor node, return now.
14953941Svenki */
14963941Svenki (void) picl_walk_tree_by_class(phyplatformh,
14974928Sfw157321 PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED,
14984669Sfw157321 sun4v_env_print_sensor_callback);
14993941Svenki if (!class_node_found)
15003941Svenki return;
15013941Svenki log_printf("Fan sensors:\n");
15023941Svenki if (syserrlog == 0) {
15033941Svenki (void) picl_walk_tree_by_class(phyplatformh,
15044669Sfw157321 PICL_CLASS_RPM_SENSOR,
15054928Sfw157321 PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
15063941Svenki if (all_status_ok) {
15073941Svenki log_printf("All fan sensors are OK.\n");
15083941Svenki return;
15093941Svenki }
15103941Svenki }
15115028Sfw157321 log_printf("-------------------------------------------------"
151211659SSree.Vemuri@Sun.COM "---------------\n");
15133941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0);
15145028Sfw157321 log_printf("-------------------------------------------------"
151511659SSree.Vemuri@Sun.COM "---------------\n");
15163941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR,
15174669Sfw157321 PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
15183941Svenki }
15193941Svenki
15203941Svenki static void
sun4v_env_print_fan_indicators()15213941Svenki sun4v_env_print_fan_indicators()
15223941Svenki {
152311659SSree.Vemuri@Sun.COM char *fmt = "%-34s %-18s %-10s\n";
15243941Svenki (void) picl_walk_tree_by_class(phyplatformh,
15254928Sfw157321 PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION,
15264669Sfw157321 sun4v_env_print_indicator_callback);
15273941Svenki if (!class_node_found)
15283941Svenki return;
15293941Svenki log_printf("\nFan indicators:\n");
15303941Svenki if (syserrlog == 0) {
15313941Svenki (void) picl_walk_tree_by_class(phyplatformh,
15324669Sfw157321 PICL_CLASS_RPM_INDICATOR,
15334928Sfw157321 (void *)PICL_PROP_CONDITION,
15344928Sfw157321 sun4v_env_print_indicator_callback);
15353941Svenki if (all_status_ok) {
15363941Svenki log_printf("All fan indicators are OK.\n");
15373941Svenki return;
15383941Svenki }
15393941Svenki }
15405028Sfw157321 log_printf("-------------------------------------------------"
154111659SSree.Vemuri@Sun.COM "---------------\n");
15423941Svenki log_printf(fmt, "Location", "Sensor", "Condition", 0);
15435028Sfw157321 log_printf("-------------------------------------------------"
154411659SSree.Vemuri@Sun.COM "---------------\n");
15453941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR,
15464802Sfw157321 (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback);
15473941Svenki }
15483941Svenki
15493941Svenki static void
sun4v_env_print_temp_sensors()15503941Svenki sun4v_env_print_temp_sensors()
15513941Svenki {
155211659SSree.Vemuri@Sun.COM char *fmt = "%-34s %-18s %-10s\n";
15533941Svenki (void) picl_walk_tree_by_class(phyplatformh,
15544669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR,
15554669Sfw157321 (void *)PICL_PROP_TEMPERATURE,
15564669Sfw157321 sun4v_env_print_sensor_callback);
15573941Svenki if (!class_node_found)
15583941Svenki return;
15593941Svenki
15603941Svenki log_printf("\nTemperature sensors:\n");
15613941Svenki if (syserrlog == 0) {
15623941Svenki (void) picl_walk_tree_by_class(phyplatformh,
15634669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR,
15644928Sfw157321 PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
15653941Svenki if (all_status_ok) {
15663941Svenki log_printf("All temperature sensors are OK.\n");
15673941Svenki return;
15683941Svenki }
15693941Svenki }
15705028Sfw157321 log_printf("-------------------------------------------------"
157111659SSree.Vemuri@Sun.COM "---------------\n");
15723941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0);
15735028Sfw157321 log_printf("-------------------------------------------------"
157411659SSree.Vemuri@Sun.COM "---------------\n");
15753941Svenki (void) picl_walk_tree_by_class(phyplatformh,
15764669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR,
15774669Sfw157321 (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
15783941Svenki }
15793941Svenki
15803941Svenki static void
sun4v_env_print_temp_indicators()15813941Svenki sun4v_env_print_temp_indicators()
15823941Svenki {
158311659SSree.Vemuri@Sun.COM char *fmt = "%-34s %-18s %-8s\n";
15843941Svenki (void) picl_walk_tree_by_class(phyplatformh,
15854669Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION,
15864669Sfw157321 sun4v_env_print_indicator_callback);
15873941Svenki if (!class_node_found)
15883941Svenki return;
15893941Svenki log_printf("\nTemperature indicators:\n");
15903941Svenki if (syserrlog == 0) {
15913941Svenki (void) picl_walk_tree_by_class(phyplatformh,
15924928Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR,
15934928Sfw157321 (void *)PICL_PROP_CONDITION,
15944669Sfw157321 sun4v_env_print_indicator_callback);
15953941Svenki if (all_status_ok) {
15963941Svenki log_printf("All temperature indicators are OK.\n");
15973941Svenki return;
15983941Svenki }
15993941Svenki }
16005028Sfw157321 log_printf("-------------------------------------------------"
160111659SSree.Vemuri@Sun.COM "---------------\n");
16023941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0);
16035028Sfw157321 log_printf("-------------------------------------------------"
160411659SSree.Vemuri@Sun.COM "---------------\n");
16053941Svenki (void) picl_walk_tree_by_class(phyplatformh,
16064669Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR,
16074669Sfw157321 (void *)PICL_PROP_CONDITION,
16084669Sfw157321 sun4v_env_print_indicator_callback);
16093941Svenki }
16103941Svenki
16113941Svenki static void
sun4v_env_print_current_sensors()16123941Svenki sun4v_env_print_current_sensors()
16133941Svenki {
161411659SSree.Vemuri@Sun.COM char *fmt = "%-34s %-18s %-10s\n";
16153941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR,
16164669Sfw157321 (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
16173941Svenki if (!class_node_found)
16183941Svenki return;
16193941Svenki log_printf("\nCurrent sensors:\n");
16203941Svenki if (syserrlog == 0) {
16213941Svenki (void) picl_walk_tree_by_class(phyplatformh,
16224669Sfw157321 PICL_CLASS_CURRENT_SENSOR,
16234928Sfw157321 PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
16243941Svenki if (all_status_ok) {
16253941Svenki log_printf("All current sensors are OK.\n");
16263941Svenki return;
16273941Svenki }
16283941Svenki }
16295028Sfw157321 log_printf("-------------------------------------------------"
163011659SSree.Vemuri@Sun.COM "---------------\n");
16313941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0);
16325028Sfw157321 log_printf("-------------------------------------------------"
163311659SSree.Vemuri@Sun.COM "---------------\n");
16343941Svenki (void) picl_walk_tree_by_class(phyplatformh,
16354669Sfw157321 PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
16364669Sfw157321 sun4v_env_print_sensor_callback);
16373941Svenki }
16383941Svenki
16393941Svenki static void
sun4v_env_print_current_indicators()16403941Svenki sun4v_env_print_current_indicators()
16413941Svenki {
164211659SSree.Vemuri@Sun.COM char *fmt = "%-34s %-18s %-8s\n";
16433941Svenki (void) picl_walk_tree_by_class(phyplatformh,
16444669Sfw157321 PICL_CLASS_CURRENT_INDICATOR,
16454669Sfw157321 (void *)PICL_PROP_CONDITION,
16464669Sfw157321 sun4v_env_print_indicator_callback);
16473941Svenki if (!class_node_found)
16483941Svenki return;
16493941Svenki log_printf("\nCurrent indicators:\n");
16503941Svenki if (syserrlog == 0) {
16513941Svenki (void) picl_walk_tree_by_class(phyplatformh,
16524928Sfw157321 PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION,
16534669Sfw157321 sun4v_env_print_indicator_callback);
16543941Svenki if (all_status_ok) {
16553941Svenki log_printf("All current indicators are OK.\n");
16563941Svenki return;
16573941Svenki }
16583941Svenki }
16595028Sfw157321 log_printf("-------------------------------------------------"
166011659SSree.Vemuri@Sun.COM "---------------\n");
16613941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0);
16625028Sfw157321 log_printf("-------------------------------------------------"
166311659SSree.Vemuri@Sun.COM "---------------\n");
16643941Svenki (void) picl_walk_tree_by_class(phyplatformh,
16654669Sfw157321 PICL_CLASS_CURRENT_INDICATOR,
16664669Sfw157321 (void *)PICL_PROP_CONDITION,
16674669Sfw157321 sun4v_env_print_indicator_callback);
16683941Svenki }
16693941Svenki
16703941Svenki static void
sun4v_env_print_voltage_sensors()16713941Svenki sun4v_env_print_voltage_sensors()
16723941Svenki {
167311659SSree.Vemuri@Sun.COM char *fmt = "%-34s %-18s %-10s\n";
16743941Svenki (void) picl_walk_tree_by_class(phyplatformh,
16754669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR,
16764669Sfw157321 PICL_PROP_VOLTAGE,
16774669Sfw157321 sun4v_env_print_sensor_callback);
16783941Svenki if (!class_node_found)
16793941Svenki return;
16803941Svenki log_printf("\nVoltage sensors:\n");
16813941Svenki if (syserrlog == 0) {
16823941Svenki (void) picl_walk_tree_by_class(phyplatformh,
16834669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR,
16844928Sfw157321 PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback);
16853941Svenki if (all_status_ok) {
16863941Svenki log_printf("All voltage sensors are OK.\n");
16873941Svenki return;
16883941Svenki }
16893941Svenki }
16905028Sfw157321 log_printf("-------------------------------------------------"
169111659SSree.Vemuri@Sun.COM "---------------\n");
16923941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0);
16935028Sfw157321 log_printf("-------------------------------------------------"
169411659SSree.Vemuri@Sun.COM "---------------\n");
16953941Svenki (void) picl_walk_tree_by_class(phyplatformh,
16964669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR,
16974669Sfw157321 (void *)PICL_PROP_VOLTAGE,
16984669Sfw157321 sun4v_env_print_sensor_callback);
16993941Svenki }
17003941Svenki
17013941Svenki static void
sun4v_env_print_voltage_indicators()17023941Svenki sun4v_env_print_voltage_indicators()
17033941Svenki {
170411659SSree.Vemuri@Sun.COM char *fmt = "%-34s %-18s %-8s\n";
17053941Svenki (void) picl_walk_tree_by_class(phyplatformh,
17064669Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR,
17074669Sfw157321 (void *)PICL_PROP_CONDITION,
17084669Sfw157321 sun4v_env_print_indicator_callback);
17093941Svenki if (!class_node_found)
17103941Svenki return;
17113941Svenki log_printf("\nVoltage indicators:\n");
17123941Svenki if (syserrlog == 0) {
17133941Svenki (void) picl_walk_tree_by_class(phyplatformh,
17144928Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION,
17154669Sfw157321 sun4v_env_print_indicator_callback);
17163941Svenki if (all_status_ok) {
17173941Svenki log_printf("All voltage indicators are OK.\n");
17183941Svenki return;
17193941Svenki }
17203941Svenki }
17215028Sfw157321 log_printf("-------------------------------------------------"
172211659SSree.Vemuri@Sun.COM "---------------\n");
17233941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0);
17245028Sfw157321 log_printf("-------------------------------------------------"
172511659SSree.Vemuri@Sun.COM "---------------\n");
17263941Svenki (void) picl_walk_tree_by_class(phyplatformh,
17274669Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR,
17284669Sfw157321 (void *)PICL_PROP_CONDITION,
17294669Sfw157321 sun4v_env_print_indicator_callback);
17303941Svenki }
17313941Svenki
17323941Svenki static void
sun4v_env_print_LEDs()17333941Svenki sun4v_env_print_LEDs()
17343941Svenki {
173511659SSree.Vemuri@Sun.COM char *fmt = "%-34s %-18s %-8s\n";
17363941Svenki if (syserrlog == 0)
17373941Svenki return;
17383941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
17394669Sfw157321 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
17403941Svenki if (!class_node_found)
17413941Svenki return;
17423941Svenki log_printf("\nLEDs:\n");
17435028Sfw157321 log_printf("-------------------------------------------------"
174411659SSree.Vemuri@Sun.COM "---------------\n");
17453941Svenki log_printf(fmt, "Location", "LED", "State", 0);
17465028Sfw157321 log_printf("-------------------------------------------------"
174711659SSree.Vemuri@Sun.COM "---------------\n");
17483941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
17494669Sfw157321 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
17503941Svenki }
17513941Svenki
17523941Svenki /*ARGSUSED*/
17533941Svenki static int
sun4v_print_fru_status_callback(picl_nodehdl_t nodeh,void * args)17543941Svenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args)
17553941Svenki {
17563941Svenki char label[PICL_PROPNAMELEN_MAX];
17573941Svenki char status[PICL_PROPNAMELEN_MAX];
17583941Svenki picl_errno_t err;
17593941Svenki picl_prophdl_t proph;
17603941Svenki picl_nodehdl_t parenth;
17613941Svenki char *names[PARENT_NAMES];
17623941Svenki char *loc;
17633941Svenki int i;
17643941Svenki
17653941Svenki if (!class_node_found) {
17663941Svenki class_node_found = 1;
17673941Svenki return (PICL_WALK_TERMINATE);
17683941Svenki }
17693941Svenki err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph);
17703941Svenki if (err != PICL_SUCCESS)
17713941Svenki return (PICL_WALK_CONTINUE);
17723941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
17734669Sfw157321 sizeof (label));
17743941Svenki if (err != PICL_SUCCESS)
17753941Svenki return (PICL_WALK_CONTINUE);
17763941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
17774669Sfw157321 status, sizeof (status));
17783941Svenki if (err != PICL_SUCCESS)
17793941Svenki return (PICL_WALK_CONTINUE);
17803941Svenki if (syserrlog == 0) {
17813941Svenki if (strcmp(status, "disabled") == 0) {
17823941Svenki if (all_status_ok) {
17833941Svenki all_status_ok = 0;
17843941Svenki return (PICL_WALK_TERMINATE);
17853941Svenki }
17863941Svenki } else
17873941Svenki return (PICL_WALK_CONTINUE);
178812046SMichael.Bergknoff@Sun.COM } else {
178912046SMichael.Bergknoff@Sun.COM if (all_status_ok && (strcmp(status, "disabled") == 0)) {
179012046SMichael.Bergknoff@Sun.COM all_status_ok = 0;
179112046SMichael.Bergknoff@Sun.COM }
17923941Svenki }
179310070SBirva.Shah@Sun.COM
179410070SBirva.Shah@Sun.COM if (is_fru_absent(nodeh))
179510070SBirva.Shah@Sun.COM strcpy(status, "Not present");
179610070SBirva.Shah@Sun.COM
17973941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
17984669Sfw157321 sizeof (parenth));
17993941Svenki if (err != PICL_SUCCESS) {
18003941Svenki log_printf("\n");
18013941Svenki return (PICL_WALK_CONTINUE);
18023941Svenki }
18033941Svenki if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
18043941Svenki return (PICL_WALK_TERMINATE);
18053941Svenki for (i = 0; i < PARENT_NAMES; i++)
18063941Svenki if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
18073941Svenki while (--i > -1)
18083941Svenki free(names[i]);
18093941Svenki free(loc);
18103941Svenki return (PICL_WALK_TERMINATE);
18113941Svenki }
18123941Svenki i = 0;
18133941Svenki while (err == PICL_SUCCESS) {
18144802Sfw157321 if (parenth == phyplatformh)
18153941Svenki break;
18163941Svenki err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
18174669Sfw157321 names[i++], PICL_PROPNAMELEN_MAX);
18183941Svenki if (err != PICL_SUCCESS) {
18193941Svenki i--;
18203941Svenki break;
18213941Svenki }
18223941Svenki if (i == PARENT_NAMES)
18233941Svenki break;
18243941Svenki err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
18254669Sfw157321 &parenth, sizeof (parenth));
18263941Svenki }
18273941Svenki loc[0] = '\0';
18284003Svivek if (--i > -1) {
18294003Svivek (void) strlcat(loc, names[i],
18304669Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18314003Svivek }
18323941Svenki while (--i > -1) {
18334003Svivek (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18344003Svivek (void) strlcat(loc, names[i],
18354669Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES);
18363941Svenki }
18375028Sfw157321 log_printf("%-35s", loc);
18383941Svenki for (i = 0; i < PARENT_NAMES; i++)
18393941Svenki free(names[i]);
18403941Svenki free(loc);
18413941Svenki log_printf("%-10s", label);
18423941Svenki log_printf("%-9s", status);
18433941Svenki log_printf("\n");
18443941Svenki return (PICL_WALK_CONTINUE);
18453941Svenki }
18463941Svenki
18473941Svenki static void
sun4v_print_fru_status()18483941Svenki sun4v_print_fru_status()
18493941Svenki {
18505028Sfw157321 char *fmt = "%-34s %-9s %-8s\n";
18515436Sfw157321
18523941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
18534669Sfw157321 sun4v_print_fru_status_callback);
18543941Svenki if (!class_node_found)
18553941Svenki return;
18565436Sfw157321
18573941Svenki log_printf("\n");
18583941Svenki log_printf("============================");
18593941Svenki log_printf(" FRU Status ");
18603941Svenki log_printf("============================");
18613941Svenki log_printf("\n");
18623941Svenki
18633941Svenki if (syserrlog == 0) {
18643941Svenki (void) picl_walk_tree_by_class(phyplatformh,
18654802Sfw157321 NULL, NULL,
18664669Sfw157321 sun4v_print_fru_status_callback);
18673941Svenki if (all_status_ok) {
18683941Svenki log_printf("All FRUs are enabled.\n");
18693941Svenki return;
18703941Svenki }
18713941Svenki }
18723941Svenki log_printf(fmt, "Location", "Name", "Status", 0);
18735028Sfw157321 log_printf("------------------------------------------------------\n");
18744802Sfw157321 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
18754669Sfw157321 sun4v_print_fru_status_callback);
18763941Svenki }
18773941Svenki
187810070SBirva.Shah@Sun.COM /* Check the children of the FRU node for a presence indicator */
187910070SBirva.Shah@Sun.COM static int
is_fru_absent(picl_nodehdl_t fruh)188010070SBirva.Shah@Sun.COM is_fru_absent(picl_nodehdl_t fruh)
188110070SBirva.Shah@Sun.COM {
188210070SBirva.Shah@Sun.COM char class [PICL_CLASSNAMELEN_MAX];
188310070SBirva.Shah@Sun.COM char condition [PICL_PROPNAMELEN_MAX];
188410070SBirva.Shah@Sun.COM picl_errno_t err;
188510070SBirva.Shah@Sun.COM picl_nodehdl_t nodeh;
188610070SBirva.Shah@Sun.COM
188710070SBirva.Shah@Sun.COM err = picl_get_propval_by_name(fruh, PICL_PROP_CHILD, &nodeh,
188810070SBirva.Shah@Sun.COM sizeof (picl_nodehdl_t));
188910070SBirva.Shah@Sun.COM while (err == PICL_SUCCESS) {
189010070SBirva.Shah@Sun.COM err = picl_get_propval_by_name(nodeh,
189110070SBirva.Shah@Sun.COM PICL_PROP_CLASSNAME, class, sizeof (class));
189210070SBirva.Shah@Sun.COM if (err == PICL_SUCCESS &&
189310070SBirva.Shah@Sun.COM strcmp(class, "presence-indicator") == 0) {
189410070SBirva.Shah@Sun.COM err = picl_get_propval_by_name(nodeh,
189510070SBirva.Shah@Sun.COM PICL_PROP_CONDITION, condition,
189610070SBirva.Shah@Sun.COM sizeof (condition));
189710070SBirva.Shah@Sun.COM if (err == PICL_SUCCESS) {
189810070SBirva.Shah@Sun.COM if (strcmp(condition, "Absent") == 0) {
189910070SBirva.Shah@Sun.COM return (1);
190010070SBirva.Shah@Sun.COM } else {
190110070SBirva.Shah@Sun.COM return (0);
190210070SBirva.Shah@Sun.COM }
190310070SBirva.Shah@Sun.COM }
190410070SBirva.Shah@Sun.COM }
190510070SBirva.Shah@Sun.COM err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
190610070SBirva.Shah@Sun.COM &nodeh, sizeof (picl_nodehdl_t));
190710070SBirva.Shah@Sun.COM }
190810070SBirva.Shah@Sun.COM return (0);
190910070SBirva.Shah@Sun.COM }
191010070SBirva.Shah@Sun.COM
19113941Svenki /*ARGSUSED*/
19123941Svenki static int
sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh,void * args)19133941Svenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args)
19143941Svenki {
19153941Svenki char rev[PICL_PROPNAMELEN_MAX];
19163941Svenki picl_errno_t err;
19173941Svenki
19183941Svenki if (!class_node_found) {
19193941Svenki class_node_found = 1;
19203941Svenki return (PICL_WALK_TERMINATE);
19213941Svenki }
19225436Sfw157321
19233941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev,
19244669Sfw157321 sizeof (rev));
19253941Svenki if (err != PICL_SUCCESS)
19263941Svenki return (PICL_WALK_CONTINUE);
19273941Svenki if (strlen(rev) == 0)
19283941Svenki return (PICL_WALK_CONTINUE);
19295436Sfw157321 log_printf("%s", rev);
19303941Svenki log_printf("\n");
19313941Svenki return (PICL_WALK_CONTINUE);
19323941Svenki }
19333941Svenki
19343941Svenki static void
sun4v_print_fw_rev()19353941Svenki sun4v_print_fw_rev()
19363941Svenki {
19373941Svenki if (syserrlog == 0)
19383941Svenki return;
19395436Sfw157321
19403941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
19414669Sfw157321 sun4v_print_fw_rev_callback);
19423941Svenki if (!class_node_found)
19433941Svenki return;
19445436Sfw157321
19453941Svenki log_printf("\n");
19463941Svenki log_printf("============================");
19473941Svenki log_printf(" FW Version ");
19483941Svenki log_printf("============================");
19493941Svenki log_printf("\n");
19505436Sfw157321 log_printf("Version\n");
19515028Sfw157321 log_printf("-------------------------------------------------"
19525028Sfw157321 "-----------\n");
19533941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
19544669Sfw157321 sun4v_print_fw_rev_callback);
19553941Svenki }
19563941Svenki
19573941Svenki static void
sun4v_print_openprom_rev()19585436Sfw157321 sun4v_print_openprom_rev()
19595436Sfw157321 {
19605436Sfw157321 if (syserrlog == 0)
19615436Sfw157321 return;
19625436Sfw157321
19635436Sfw157321 (void) picl_walk_tree_by_class(rooth, "openprom", NULL,
19645436Sfw157321 openprom_callback);
19655436Sfw157321 if (!class_node_found)
19665436Sfw157321 return;
19675436Sfw157321
19685436Sfw157321 log_printf("\n");
19695436Sfw157321 log_printf("======================");
19705436Sfw157321 log_printf(" System PROM revisions ");
19715436Sfw157321 log_printf("=======================");
19725436Sfw157321 log_printf("\n");
19735436Sfw157321 log_printf("Version\n");
19745436Sfw157321 log_printf("-------------------------------------------------"
19755436Sfw157321 "-----------\n");
19765436Sfw157321 (void) picl_walk_tree_by_class(rooth, "openprom", NULL,
19775436Sfw157321 openprom_callback);
19785436Sfw157321 }
19795436Sfw157321
19805436Sfw157321 /*
19815436Sfw157321 * display the OBP and POST prom revisions (if present)
19825436Sfw157321 */
19835436Sfw157321 /* ARGSUSED */
19845436Sfw157321 static int
openprom_callback(picl_nodehdl_t openpromh,void * arg)19855436Sfw157321 openprom_callback(picl_nodehdl_t openpromh, void *arg)
19865436Sfw157321 {
19875436Sfw157321 picl_prophdl_t proph;
19885436Sfw157321 picl_prophdl_t tblh;
19895436Sfw157321 picl_prophdl_t rowproph;
19905436Sfw157321 picl_propinfo_t pinfo;
19915436Sfw157321 char *prom_version = NULL;
19925436Sfw157321 char *obp_version = NULL;
19935436Sfw157321 int err;
19945436Sfw157321
19955436Sfw157321 if (!class_node_found) {
19965436Sfw157321 class_node_found = 1;
19975436Sfw157321 return (PICL_WALK_TERMINATE);
19985436Sfw157321 }
19995436Sfw157321
20005436Sfw157321 err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION,
20015436Sfw157321 &pinfo, &proph);
20025436Sfw157321 if (err == PICL_PROPNOTFOUND)
20035436Sfw157321 return (PICL_WALK_TERMINATE);
20045436Sfw157321 else if (err != PICL_SUCCESS)
20055436Sfw157321 return (err);
20065436Sfw157321
20075436Sfw157321 /*
20085436Sfw157321 * If it's a table prop, the first element is OBP revision
20095436Sfw157321 * The second one is POST revision.
20105436Sfw157321 * If it's a charstring prop, the value will be only OBP revision
20115436Sfw157321 */
20125436Sfw157321 if (pinfo.type == PICL_PTYPE_CHARSTRING) {
20135436Sfw157321 prom_version = (char *)alloca(pinfo.size);
20145436Sfw157321 if (prom_version == NULL)
20155436Sfw157321 return (PICL_FAILURE);
20165436Sfw157321 err = picl_get_propval(proph, prom_version, pinfo.size);
20175436Sfw157321 if (err != PICL_SUCCESS)
20185436Sfw157321 return (err);
20195436Sfw157321 log_printf("%s\n", prom_version);
20205436Sfw157321 }
20215436Sfw157321
20225436Sfw157321 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */
20235436Sfw157321 return (PICL_WALK_TERMINATE);
20245436Sfw157321
20255436Sfw157321 err = picl_get_propval(proph, &tblh, pinfo.size);
20265436Sfw157321 if (err != PICL_SUCCESS)
20275436Sfw157321 return (err);
20285436Sfw157321
20295436Sfw157321 err = picl_get_next_by_row(tblh, &rowproph);
20305436Sfw157321 if (err == PICL_SUCCESS) {
20315436Sfw157321 /* get first row */
20325436Sfw157321 err = picl_get_propinfo(rowproph, &pinfo);
20335436Sfw157321 if (err != PICL_SUCCESS)
20345436Sfw157321 return (err);
20355436Sfw157321
20365436Sfw157321 prom_version = (char *)alloca(pinfo.size);
20375436Sfw157321 if (prom_version == NULL)
20385436Sfw157321 return (PICL_FAILURE);
20395436Sfw157321
20405436Sfw157321 err = picl_get_propval(rowproph, prom_version, pinfo.size);
20415436Sfw157321 if (err != PICL_SUCCESS)
20425436Sfw157321 return (err);
20435436Sfw157321 log_printf("%s\n", prom_version);
20445436Sfw157321
20455436Sfw157321 /* get second row */
20465436Sfw157321 err = picl_get_next_by_col(rowproph, &rowproph);
20475436Sfw157321 if (err == PICL_SUCCESS) {
20485436Sfw157321 err = picl_get_propinfo(rowproph, &pinfo);
20495436Sfw157321 if (err != PICL_SUCCESS)
20505436Sfw157321 return (err);
20515436Sfw157321
20525436Sfw157321 obp_version = (char *)alloca(pinfo.size);
20535436Sfw157321 if (obp_version == NULL)
20545436Sfw157321 return (PICL_FAILURE);
20555436Sfw157321 err = picl_get_propval(rowproph, obp_version,
20565436Sfw157321 pinfo.size);
20575436Sfw157321 if (err != PICL_SUCCESS)
20585436Sfw157321 return (err);
20595436Sfw157321 log_printf("%s\n", obp_version);
20605436Sfw157321 }
20615436Sfw157321 }
20625436Sfw157321
20635436Sfw157321 return (PICL_WALK_TERMINATE);
20645436Sfw157321 }
20655436Sfw157321
20665436Sfw157321 static void
sun4v_print_chassis_serial_no()20673941Svenki sun4v_print_chassis_serial_no()
20683941Svenki {
20693941Svenki char val[PICL_PROPNAMELEN_MAX];
20703941Svenki picl_errno_t err;
20713941Svenki if (syserrlog == 0 || chassish == 0)
20723941Svenki return;
20733941Svenki
20743941Svenki log_printf("\n");
20756014Ssuha log_printf("Chassis Serial Number");
20763941Svenki log_printf("\n");
20773941Svenki log_printf("---------------------\n");
20783941Svenki err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER,
20794669Sfw157321 val, sizeof (val));
20803941Svenki if (err == PICL_SUCCESS)
20813941Svenki log_printf("%s", val);
20823941Svenki log_printf("\n");
20833941Svenki }
2084