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 /* 22*8574SJason.Beloro@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 231708Sstevel * Use is subject to license terms. 241708Sstevel */ 251708Sstevel 261708Sstevel #include <stdio.h> 271708Sstevel #include <stdlib.h> 285436Sfw157321 #include <alloca.h> 291708Sstevel #include <unistd.h> 301708Sstevel #include <ctype.h> 311708Sstevel #include <string.h> 321708Sstevel #include <kvm.h> 331708Sstevel #include <varargs.h> 341708Sstevel #include <time.h> 351708Sstevel #include <dirent.h> 361708Sstevel #include <fcntl.h> 371708Sstevel #include <sys/param.h> 381708Sstevel #include <sys/stat.h> 391708Sstevel #include <sys/types.h> 401708Sstevel #include <sys/utsname.h> 411708Sstevel #include <sys/openpromio.h> 421708Sstevel #include <libintl.h> 431708Sstevel #include <syslog.h> 441708Sstevel #include <sys/dkio.h> 453941Svenki #include <sys/systeminfo.h> 463941Svenki #include <picldefs.h> 474802Sfw157321 #include <math.h> 484802Sfw157321 #include <errno.h> 491708Sstevel #include "pdevinfo.h" 501708Sstevel #include "display.h" 511708Sstevel #include "display_sun4v.h" 521708Sstevel #include "libprtdiag.h" 531708Sstevel 541708Sstevel #if !defined(TEXT_DOMAIN) 551708Sstevel #define TEXT_DOMAIN "SYS_TEST" 561708Sstevel #endif 571708Sstevel 584669Sfw157321 #define MOTHERBOARD "MB" 593941Svenki #define NETWORK "network" 603941Svenki #define SUN4V_MACHINE "sun4v" 613941Svenki #define PARENT_NAMES 10 623941Svenki 633941Svenki /* 643941Svenki * Additional OBP properties 653941Svenki */ 663941Svenki #define OBP_PROP_COMPATIBLE "compatible" 673941Svenki #define OBP_PROP_MODEL "model" 683941Svenki #define OBP_PROP_SLOT_NAMES "slot-names" 695436Sfw157321 #define OBP_PROP_VERSION "version" 703941Svenki 713941Svenki #define PICL_NODE_PHYSICAL_PLATFORM "physical-platform" 723941Svenki #define PICL_NODE_CHASSIS "chassis" 733941Svenki #define MEMORY_SIZE_FIELD 11 743941Svenki #define INVALID_THRESHOLD 1000000 753941Svenki 763941Svenki /* 773941Svenki * Additional picl classes 783941Svenki */ 793941Svenki #ifndef PICL_CLASS_SUN4V 803941Svenki #define PICL_CLASS_SUN4V "sun4v" 813941Svenki #endif 823941Svenki 833941Svenki #ifndef PICL_PROP_NAC 843941Svenki #define PICL_PROP_NAC "nac" 853941Svenki #endif 863941Svenki 873941Svenki extern int sys_clk; 883941Svenki extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *, 893941Svenki picl_nodehdl_t *); 903941Svenki 913941Svenki static picl_nodehdl_t rooth = 0, phyplatformh = 0; 923941Svenki static picl_nodehdl_t chassish = 0; 933941Svenki static int class_node_found; 943941Svenki static int syserrlog; 953941Svenki static int all_status_ok; 963941Svenki 973941Svenki /* local functions */ 983941Svenki static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **); 993941Svenki static void sun4v_display_memory_conf(picl_nodehdl_t); 1005547Smb158278 static int sun4v_disp_env_status(); 1013941Svenki static void sun4v_env_print_fan_sensors(); 1023941Svenki static void sun4v_env_print_fan_indicators(); 1033941Svenki static void sun4v_env_print_temp_sensors(); 1043941Svenki static void sun4v_env_print_temp_indicators(); 1053941Svenki static void sun4v_env_print_current_sensors(); 1063941Svenki static void sun4v_env_print_current_indicators(); 1073941Svenki static void sun4v_env_print_voltage_sensors(); 1083941Svenki static void sun4v_env_print_voltage_indicators(); 109*8574SJason.Beloro@Sun.COM static void sun4v_env_print_humidity_sensors(); 110*8574SJason.Beloro@Sun.COM static void sun4v_env_print_humidity_indicators(); 1113941Svenki static void sun4v_env_print_LEDs(); 1123941Svenki static void sun4v_print_fru_status(); 1133941Svenki static void sun4v_print_fw_rev(); 1143941Svenki static void sun4v_print_chassis_serial_no(); 1155436Sfw157321 static int openprom_callback(picl_nodehdl_t openpromh, void *arg); 1165436Sfw157321 static void sun4v_print_openprom_rev(); 1171708Sstevel 1181708Sstevel int 1193941Svenki sun4v_display(Sys_tree *tree, Prom_node *root, int log, 1203941Svenki picl_nodehdl_t plafh) 1211708Sstevel { 1221708Sstevel void *value; /* used for opaque PROM data */ 1231708Sstevel struct mem_total memory_total; /* Total memory in system */ 1241708Sstevel struct grp_info grps; /* Info on all groups in system */ 1253941Svenki char machine[MAXSTRLEN]; 1265547Smb158278 int exit_code = 0; 1273941Svenki 1283941Svenki if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1) 1293941Svenki return (1); 1303941Svenki if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0) 1313941Svenki return (1); 1321708Sstevel 1331708Sstevel sys_clk = -1; /* System clock freq. (in MHz) */ 1341708Sstevel 1351708Sstevel /* 1361708Sstevel * Now display the machine's configuration. We do this if we 1371708Sstevel * are not logging. 1381708Sstevel */ 1391708Sstevel if (!logging) { 1401708Sstevel struct utsname uts_buf; 1411708Sstevel 1421708Sstevel /* 1431708Sstevel * Display system banner 1441708Sstevel */ 1451708Sstevel (void) uname(&uts_buf); 1461708Sstevel 1473941Svenki log_printf(dgettext(TEXT_DOMAIN, "System Configuration: " 1484669Sfw157321 "Sun Microsystems %s %s\n"), uts_buf.machine, 1494669Sfw157321 get_prop_val(find_prop(root, "banner-name")), 0); 1501708Sstevel 1511708Sstevel /* display system clock frequency */ 1521708Sstevel value = get_prop_val(find_prop(root, "clock-frequency")); 1531708Sstevel if (value != NULL) { 1541708Sstevel sys_clk = ((*((int *)value)) + 500000) / 1000000; 1551708Sstevel log_printf(dgettext(TEXT_DOMAIN, "System clock " 1564669Sfw157321 "frequency: %d MHz\n"), sys_clk, 0); 1571708Sstevel } 1581708Sstevel 1591708Sstevel /* Display the Memory Size */ 1601708Sstevel display_memorysize(tree, NULL, &grps, &memory_total); 1611708Sstevel 1621708Sstevel /* Display the CPU devices */ 1631708Sstevel sun4v_display_cpu_devices(plafh); 1641708Sstevel 1651708Sstevel /* Display the Memory configuration */ 1663941Svenki class_node_found = 0; 1673941Svenki sun4v_display_memory_conf(plafh); 1681708Sstevel 1691708Sstevel /* Display all the IO cards. */ 1701708Sstevel (void) sun4v_display_pci(plafh); 1713941Svenki sun4v_display_diaginfo((log || (logging)), root, plafh); 1721708Sstevel 1733941Svenki if (picl_get_root(&rooth) != PICL_SUCCESS) 1743941Svenki return (1); 1755547Smb158278 1765547Smb158278 /* 1775547Smb158278 * The physical-platform node may be missing on systems with 1785547Smb158278 * older firmware so don't consider that an error. 1795547Smb158278 */ 1803941Svenki if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM, 1814669Sfw157321 &phyplatformh) != PICL_SUCCESS) 1825547Smb158278 return (0); 1833941Svenki 1843941Svenki if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME, 1854669Sfw157321 PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS, 1864669Sfw157321 strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS) 1873941Svenki return (1); 1883941Svenki 1893941Svenki syserrlog = log; 1905547Smb158278 exit_code = sun4v_disp_env_status(); 1913941Svenki } 1925547Smb158278 return (exit_code); 1933941Svenki } 1943941Svenki 1955819Sfw157321 /* 1965819Sfw157321 * The binding-name property encodes the bus type. 1975819Sfw157321 */ 1983941Svenki static void 1993941Svenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card) 2003941Svenki { 2015819Sfw157321 char val[PICL_PROPNAMELEN_MAX], *p, *q; 2025819Sfw157321 2035819Sfw157321 card->bus_type[0] = '\0'; 2043941Svenki 2055819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, val, 2065819Sfw157321 sizeof (val)) == PICL_SUCCESS) { 2075819Sfw157321 if (strstr(val, PICL_CLASS_PCIEX)) 2084003Svivek (void) strlcpy(card->bus_type, "PCIE", 2094669Sfw157321 sizeof (card->bus_type)); 2105819Sfw157321 else if (strstr(val, PICL_CLASS_PCI)) 2115819Sfw157321 (void) strlcpy(card->bus_type, "PCIX", 2125819Sfw157321 sizeof (card->bus_type)); 2135819Sfw157321 else { 2145819Sfw157321 /* 2155819Sfw157321 * Not perfect: process the binding-name until 2165819Sfw157321 * we encounter something that we don't think would 2175819Sfw157321 * be part of a bus type. This may get confused a bit 2185819Sfw157321 * if a device or vendor id is encoded right after 2195819Sfw157321 * the bus class since there's no delimiter. If the 2205819Sfw157321 * id number begins with a hex digit [abcdef] then 2215819Sfw157321 * this will become part of the bus type string 2225819Sfw157321 * reported by prtdiag. This is all an effort to 2235819Sfw157321 * print something potentially useful for bus types 2245819Sfw157321 * other than PCI/PCIe. 2255819Sfw157321 * 2265819Sfw157321 * We do this because this code will get called for 2275819Sfw157321 * non-PCI class devices like the xaui (class sun4v.) 2285819Sfw157321 */ 2295819Sfw157321 if (strstr(val, "SUNW,") != NULL) 2305819Sfw157321 p = strchr(val, ',') + 1; 2315819Sfw157321 else 2325819Sfw157321 p = val; 2335819Sfw157321 q = p; 2345819Sfw157321 while (*p != '\0') { 2355819Sfw157321 if (isdigit((char)*p) || ispunct((char)*p)) { 2365819Sfw157321 *p = '\0'; 2375819Sfw157321 break; 2385819Sfw157321 } 2395819Sfw157321 *p = (char)_toupper((int)*p); 2405819Sfw157321 ++p; 2415819Sfw157321 } 2425819Sfw157321 (void) strlcpy(card->bus_type, q, 2435819Sfw157321 sizeof (card->bus_type)); 2445819Sfw157321 } 2453941Svenki } 2463941Svenki } 2473941Svenki 2485819Sfw157321 /* 2495819Sfw157321 * Fetch the Label property for this device. If none is found then 2505819Sfw157321 * search all the siblings with the same device ID for a 2515819Sfw157321 * Label and return that Label. The plug-in can only match the canonical 2525819Sfw157321 * path from the PRI with a specific devfs path. So we take care of 2535819Sfw157321 * devices with multiple functions here. A leaf device downstream of 2545819Sfw157321 * a bridge should fall out of here with PICL_PROPNOTFOUND, and the 2555819Sfw157321 * caller can walk back up the tree in search of the slot's Label. 2565819Sfw157321 */ 2573941Svenki static picl_errno_t 2583941Svenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card) 2593941Svenki { 2603941Svenki char val[PICL_PROPNAMELEN_MAX]; 2613941Svenki picl_errno_t err; 2625436Sfw157321 picl_nodehdl_t pnodeh; 2635819Sfw157321 uint32_t devid, sib_devid; 2645819Sfw157321 int32_t instance; 2653941Svenki 2665436Sfw157321 /* 2675819Sfw157321 * If there's a Label at this node then return it - we're 2685819Sfw157321 * done. 2695436Sfw157321 */ 2703941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 2714669Sfw157321 sizeof (val)); 2725819Sfw157321 if (err == PICL_SUCCESS) { 2735819Sfw157321 (void) strlcpy(card->slot_str, val, sizeof (card->slot_str)); 2745819Sfw157321 return (err); 2755819Sfw157321 } else if (err != PICL_PROPNOTFOUND) 2765819Sfw157321 return (err); 2775819Sfw157321 2785819Sfw157321 /* 2795819Sfw157321 * At this point we're starting to extrapolate what the Label 2805819Sfw157321 * should be since there is none at this specific node. 2815819Sfw157321 * Note that until the value of "err" is overwritten in the 2825819Sfw157321 * loop below, its value should be PICL_PROPNOTFOUND. 2835819Sfw157321 */ 2845819Sfw157321 2855819Sfw157321 /* 2865819Sfw157321 * The device must be attached, and we can figure that out if 2875819Sfw157321 * the instance number is present and is not equal to -1. 2885819Sfw157321 * This will prevent is from returning a Label for a sibling 2895819Sfw157321 * node when the node passed in would have a unique Label if the 2905819Sfw157321 * device were attached. But if the device is downstream of a 2915819Sfw157321 * node with a Label then pci_callback() will still find that 2925819Sfw157321 * and use it. 2935819Sfw157321 */ 2945819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_INSTANCE, &instance, 2955819Sfw157321 sizeof (instance)) != PICL_SUCCESS) 2965819Sfw157321 return (err); 2975819Sfw157321 if (instance == -1) 2985819Sfw157321 return (err); 2993941Svenki 3005819Sfw157321 /* 3015819Sfw157321 * Narrow the search to just the one device ID. 3025819Sfw157321 */ 3035819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_DEVICE_ID, &devid, 3045819Sfw157321 sizeof (devid)) != PICL_SUCCESS) 3055819Sfw157321 return (err); 3065819Sfw157321 3075819Sfw157321 /* 3085819Sfw157321 * Go find the first child of the parent so we can search 3095819Sfw157321 * all of the siblings. 3105819Sfw157321 */ 3115819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh, 3125819Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS) 3135819Sfw157321 return (err); 3145819Sfw157321 if (picl_get_propval_by_name(pnodeh, PICL_PROP_CHILD, &pnodeh, 3155819Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS) 3165819Sfw157321 return (err); 3175436Sfw157321 3185819Sfw157321 /* 3195819Sfw157321 * If the child's device ID matches, then fetch the Label and 3205819Sfw157321 * return it. The first child/device ID should have a Label 3215819Sfw157321 * associated with it. 3225819Sfw157321 */ 3235819Sfw157321 do { 3245819Sfw157321 if (picl_get_propval_by_name(pnodeh, PICL_PROP_DEVICE_ID, 3255819Sfw157321 &sib_devid, sizeof (sib_devid)) == PICL_SUCCESS) { 3265819Sfw157321 if (sib_devid == devid) { 3275819Sfw157321 if ((err = picl_get_propval_by_name(pnodeh, 3285819Sfw157321 PICL_PROP_LABEL, val, sizeof (val))) == 3295819Sfw157321 PICL_SUCCESS) { 3305819Sfw157321 (void) strlcpy(card->slot_str, val, 3315819Sfw157321 sizeof (card->slot_str)); 3325819Sfw157321 break; 3335819Sfw157321 } 3345819Sfw157321 } 3355819Sfw157321 } 3365819Sfw157321 } while (picl_get_propval_by_name(pnodeh, PICL_PROP_PEER, &pnodeh, 3375819Sfw157321 sizeof (pnodeh)) == PICL_SUCCESS); 3385819Sfw157321 3395436Sfw157321 return (err); 3403941Svenki } 3413941Svenki 3423941Svenki static void 3433941Svenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card) 3443941Svenki { 3453941Svenki picl_errno_t err; 3463941Svenki picl_prophdl_t proph; 3473941Svenki picl_propinfo_t pinfo; 3483941Svenki picl_nodehdl_t pnodeh; 3493941Svenki uint8_t *pval; 3503941Svenki uint32_t dev_mask; 3513941Svenki char uaddr[MAXSTRLEN]; 3523941Svenki int i; 3533941Svenki 3543941Svenki err = PICL_SUCCESS; 3553941Svenki while (err == PICL_SUCCESS) { 3563941Svenki if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh, 3574669Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS) { 3584669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 3594669Sfw157321 sizeof (card->slot_str)); 3603941Svenki card->slot = -1; 3613941Svenki return; 3623941Svenki } 3633941Svenki if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES, 3644669Sfw157321 &pinfo, &proph) == PICL_SUCCESS) { 3653941Svenki break; 3663941Svenki } 3673941Svenki nodeh = pnodeh; 3683941Svenki } 3693941Svenki if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr, 3704669Sfw157321 sizeof (uaddr)) != PICL_SUCCESS) { 3714669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 3724669Sfw157321 sizeof (card->slot_str)); 3733941Svenki card->slot = -1; 3743941Svenki return; 3753941Svenki } 3763941Svenki pval = (uint8_t *)malloc(pinfo.size); 3773941Svenki if (!pval) { 3784669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 3794669Sfw157321 sizeof (card->slot_str)); 3803941Svenki card->slot = -1; 3813941Svenki return; 3823941Svenki } 3833941Svenki if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) { 3844669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 3854669Sfw157321 sizeof (card->slot_str)); 3863941Svenki card->slot = -1; 3873941Svenki free(pval); 3883941Svenki return; 3891708Sstevel } 3901708Sstevel 3913941Svenki dev_mask = 0; 3923941Svenki for (i = 0; i < sizeof (dev_mask); i++) 3933941Svenki dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i)); 3943941Svenki for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) { 3953941Svenki if (uaddr[i] == ',') { 3963941Svenki uaddr[i] = '\0'; 3973941Svenki break; 3983941Svenki } 3993941Svenki } 4003941Svenki card->slot = atol(uaddr); 4013941Svenki if (((1 << card->slot) & dev_mask) == 0) { 4024669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 4034669Sfw157321 sizeof (card->slot_str)); 4043941Svenki card->slot = -1; 4053941Svenki } else { 4063941Svenki char *p = (char *)(pval+sizeof (dev_mask)); 4073941Svenki int shift = sizeof (uint32_t)*8-1-card->slot; 4083941Svenki uint32_t x = (dev_mask << shift) >> shift; 4093941Svenki int count = 0; /* count # of 1's in x */ 4103941Svenki int i = 0; 4113941Svenki while (x != 0) { 4123941Svenki count++; 4133941Svenki x &= x-1; 4143941Svenki } 4153941Svenki while (count > 1) { 4164669Sfw157321 while (p[i++] != '\0') 4174669Sfw157321 ; 4183941Svenki count--; 4193941Svenki } 4204003Svivek (void) strlcpy(card->slot_str, (char *)(p+i), 4214669Sfw157321 sizeof (card->slot_str)); 4223941Svenki } 4233941Svenki free(pval); 4243941Svenki } 4253941Svenki 4263941Svenki /* 4273941Svenki * add all io devices under pci in io list 4283941Svenki */ 4293941Svenki /* ARGSUSED */ 4303941Svenki static int 4313941Svenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args) 4323941Svenki { 4333941Svenki char path[PICL_PROPNAMELEN_MAX]; 4343941Svenki char class[PICL_CLASSNAMELEN_MAX]; 4353941Svenki char name[PICL_PROPNAMELEN_MAX]; 4363941Svenki char model[PICL_PROPNAMELEN_MAX]; 4373941Svenki char binding_name[PICL_PROPNAMELEN_MAX]; 4383941Svenki char val[PICL_PROPNAMELEN_MAX]; 4393941Svenki char *compatible; 4403941Svenki picl_errno_t err; 4415819Sfw157321 picl_nodehdl_t nodeh, pnodeh; 4423941Svenki struct io_card pci_card; 4433941Svenki 4443941Svenki /* Walk through the children */ 4453941Svenki 4463941Svenki err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 4474669Sfw157321 sizeof (picl_nodehdl_t)); 4483941Svenki 4493941Svenki while (err == PICL_SUCCESS) { 4503941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 4514669Sfw157321 class, sizeof (class)); 4523941Svenki if (err != PICL_SUCCESS) 4533941Svenki return (err); 4543941Svenki 4553941Svenki if (args) { 4563941Svenki char *val = args; 4573941Svenki if (strcmp(class, val) == 0) { 4583941Svenki err = picl_get_propval_by_name(nodeh, 4594669Sfw157321 PICL_PROP_PEER, &nodeh, 4604669Sfw157321 sizeof (picl_nodehdl_t)); 4613941Svenki continue; 4623941Svenki } else if (strcmp(val, PICL_CLASS_PCIEX) == 0 && 4634669Sfw157321 strcmp(class, PICL_CLASS_PCI) == 0) { 4643941Svenki err = picl_get_propval_by_name(nodeh, 4654669Sfw157321 PICL_PROP_PEER, &nodeh, 4664669Sfw157321 sizeof (picl_nodehdl_t)); 4673941Svenki continue; 4683941Svenki } else if (strcmp(val, PICL_CLASS_PCI) == 0 && 4694669Sfw157321 strcmp(class, PICL_CLASS_PCIEX) == 0) { 4703941Svenki err = picl_get_propval_by_name(nodeh, 4714669Sfw157321 PICL_PROP_PEER, &nodeh, 4724669Sfw157321 sizeof (picl_nodehdl_t)); 4733941Svenki continue; 4743941Svenki } 4753941Svenki } 4763941Svenki 4773941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH, 4784669Sfw157321 path, sizeof (path)); 4793941Svenki if (err != PICL_SUCCESS) 4803941Svenki return (err); 4813941Svenki 4823941Svenki (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes)); 4833941Svenki 4845819Sfw157321 pnodeh = nodeh; 4855819Sfw157321 err = get_slot_label(nodeh, &pci_card); 4865819Sfw157321 4875819Sfw157321 /* 4885819Sfw157321 * No Label at this node, maybe we're looking at a device 4895819Sfw157321 * downstream of a bridge. Walk back up and find a Label and 4905819Sfw157321 * record that node in "pnodeh". 4915819Sfw157321 */ 4925819Sfw157321 while (err != PICL_SUCCESS) { 4935819Sfw157321 if (err != PICL_PROPNOTFOUND) 4945819Sfw157321 break; 4955819Sfw157321 else if (picl_get_propval_by_name(pnodeh, 4965819Sfw157321 PICL_PROP_PARENT, &pnodeh, sizeof (pnodeh)) == 4975819Sfw157321 PICL_SUCCESS) 4985819Sfw157321 err = get_slot_label(pnodeh, &pci_card); 4995819Sfw157321 else 5005819Sfw157321 break; 5015819Sfw157321 } 5025819Sfw157321 5035819Sfw157321 /* 5045819Sfw157321 * Can't find a Label for this device in the PCI heirarchy. 5055819Sfw157321 * Try to synthesize a slot name from atoms. This depends 5065819Sfw157321 * on the OBP slot_names property being implemented, and this 5075819Sfw157321 * so far doesn't seem to be on sun4v. But just in case that 5085819Sfw157321 * is resurrected, the code is here. 5095819Sfw157321 */ 5105819Sfw157321 if (err != PICL_SUCCESS) { 5115819Sfw157321 pnodeh = nodeh; 5125819Sfw157321 get_slot_number(nodeh, &pci_card); 5135819Sfw157321 } 5145819Sfw157321 5155819Sfw157321 /* 5165819Sfw157321 * Passing in pnodeh instead of nodeh will cause prtdiag 5175819Sfw157321 * to display the type of IO slot for the leaf node. For 5185819Sfw157321 * built-in devices and a lot of IO cards these will be 5195819Sfw157321 * the same thing. But for IO cards with bridge chips or 5205819Sfw157321 * for things like expansion chassis, prtdiag will report 5215819Sfw157321 * the bus type of the IO slot and not the leaf, which 5225819Sfw157321 * could be different things. 5235819Sfw157321 */ 5245819Sfw157321 get_bus_type(pnodeh, &pci_card); 5253941Svenki 5263941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name, 5274669Sfw157321 sizeof (name)); 5283941Svenki if (err == PICL_PROPNOTFOUND) 5294003Svivek (void) strlcpy(name, "", sizeof (name)); 5303941Svenki else if (err != PICL_SUCCESS) 5313941Svenki return (err); 5323941Svenki 5333941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val, 5344669Sfw157321 sizeof (val)); 5353941Svenki if (err == PICL_PROPNOTFOUND) 5364003Svivek (void) strlcpy(val, "", sizeof (val)); 5373941Svenki else if (err != PICL_SUCCESS) 5383941Svenki return (err); 5393941Svenki 5405436Sfw157321 (void) snprintf(pci_card.status, sizeof (pci_card.status), 5415436Sfw157321 "%s", pci_card.slot_str); 5423941Svenki 5433941Svenki /* 5443941Svenki * Get the name of this card. If binding_name is found, 5453941Svenki * name will be <nodename>-<binding_name>. 5463941Svenki */ 5473941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, 5484669Sfw157321 binding_name, sizeof (binding_name)); 5493941Svenki if (err == PICL_SUCCESS) { 5503941Svenki if (strcmp(name, binding_name) != 0) { 5513941Svenki (void) strlcat(name, "-", sizeof (name)); 5523941Svenki (void) strlcat(name, binding_name, 5534669Sfw157321 sizeof (name)); 5543941Svenki } 5553941Svenki } else if (err == PICL_PROPNOTFOUND) { 5563941Svenki /* 5573941Svenki * if compatible prop is not found, name will be 5583941Svenki * <nodename>-<compatible> 5593941Svenki */ 5603941Svenki err = sun4v_get_first_compatible_value(nodeh, 5614669Sfw157321 &compatible); 5623941Svenki if (err == PICL_SUCCESS) { 5633941Svenki (void) strlcat(name, "-", sizeof (name)); 5644003Svivek (void) strlcat(name, compatible, 5654669Sfw157321 sizeof (name)); 5663941Svenki free(compatible); 5673941Svenki } 5683941Svenki } else 5693941Svenki return (err); 5703941Svenki 5713941Svenki (void) strlcpy(pci_card.name, name, sizeof (pci_card.name)); 5723941Svenki 5733941Svenki /* Get the model of this card */ 5743941Svenki 5753941Svenki err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL, 5764669Sfw157321 model, sizeof (model)); 5773941Svenki if (err == PICL_PROPNOTFOUND) 5784003Svivek (void) strlcpy(model, "", sizeof (model)); 5793941Svenki else if (err != PICL_SUCCESS) 5803941Svenki return (err); 5813941Svenki (void) strlcpy(pci_card.model, model, sizeof (pci_card.model)); 5823941Svenki 5833941Svenki /* Print NAC name */ 5844802Sfw157321 log_printf("%-18s", pci_card.status); 5853941Svenki /* Print IO Type */ 5863941Svenki log_printf("%-6s", pci_card.bus_type); 5873941Svenki /* Printf Card Name */ 5885544Sfw157321 log_printf("%-34s", pci_card.name); 5893941Svenki /* Print Card Model */ 5903941Svenki log_printf("%-8s", pci_card.model); 5913941Svenki log_printf("\n"); 5923941Svenki /* Print Status */ 5934802Sfw157321 log_printf("%-18s", val); 5943941Svenki /* Print IO Type */ 5953941Svenki log_printf("%-6s", ""); 5963941Svenki /* Print Parent Path */ 5974802Sfw157321 log_printf("%-44s", pci_card.notes); 5983941Svenki log_printf("\n"); 5993941Svenki 6003941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 6014669Sfw157321 sizeof (picl_nodehdl_t)); 6023941Svenki } 6033941Svenki return (PICL_WALK_CONTINUE); 6041708Sstevel } 6051708Sstevel 6061708Sstevel /* 6071708Sstevel * display_pci 6081708Sstevel * Display all the PCI IO cards on this board. 6091708Sstevel */ 6101708Sstevel void 6111708Sstevel sun4v_display_pci(picl_nodehdl_t plafh) 6121708Sstevel { 6135544Sfw157321 char *fmt = "%-17s %-5s %-33s %-8s"; 6143941Svenki /* Have we printed the column headings? */ 6153941Svenki static int banner = FALSE; 6163941Svenki 6173941Svenki if (banner == FALSE) { 6183941Svenki log_printf("\n"); 6194802Sfw157321 log_printf("================================"); 6203941Svenki log_printf(" IO Devices "); 6214802Sfw157321 log_printf("================================"); 6223941Svenki log_printf("\n"); 6233941Svenki log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0); 6243941Svenki log_printf("\n"); 6253941Svenki log_printf(fmt, "Status", "Type", "Path", "", 0); 6263941Svenki log_printf("\n"); 6273941Svenki log_printf("---------------------------------" 6284802Sfw157321 "-------------------------------------------\n"); 6293941Svenki banner = TRUE; 6303941Svenki } 6313941Svenki 6323941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, 6334669Sfw157321 PICL_CLASS_PCIEX, sun4v_pci_callback); 6343941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI, 6354669Sfw157321 PICL_CLASS_PCI, sun4v_pci_callback); 6363941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V, 6374669Sfw157321 PICL_CLASS_SUN4V, sun4v_pci_callback); 6383941Svenki } 6393941Svenki 6403941Svenki /* 6413941Svenki * return the first compatible value 6423941Svenki */ 6433941Svenki static int 6443941Svenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf) 6453941Svenki { 6463941Svenki picl_errno_t err; 6473941Svenki picl_prophdl_t proph; 6483941Svenki picl_propinfo_t pinfo; 6493941Svenki picl_prophdl_t tblh; 6503941Svenki picl_prophdl_t rowproph; 6513941Svenki char *pval; 6523941Svenki 6533941Svenki err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE, 6544669Sfw157321 &pinfo, &proph); 6553941Svenki if (err != PICL_SUCCESS) 6563941Svenki return (err); 6573941Svenki 6583941Svenki if (pinfo.type == PICL_PTYPE_CHARSTRING) { 6593941Svenki pval = malloc(pinfo.size); 6603941Svenki if (pval == NULL) 6613941Svenki return (PICL_FAILURE); 6623941Svenki err = picl_get_propval(proph, pval, pinfo.size); 6633941Svenki if (err != PICL_SUCCESS) { 6643941Svenki free(pval); 6653941Svenki return (err); 6663941Svenki } 6673941Svenki *outbuf = pval; 6683941Svenki return (PICL_SUCCESS); 6693941Svenki } 6703941Svenki 6713941Svenki if (pinfo.type != PICL_PTYPE_TABLE) 6723941Svenki return (PICL_FAILURE); 6733941Svenki 6743941Svenki /* get first string from table */ 6753941Svenki err = picl_get_propval(proph, &tblh, pinfo.size); 6763941Svenki if (err != PICL_SUCCESS) 6773941Svenki return (err); 6783941Svenki 6793941Svenki err = picl_get_next_by_row(tblh, &rowproph); 6803941Svenki if (err != PICL_SUCCESS) 6813941Svenki return (err); 6823941Svenki 6833941Svenki err = picl_get_propinfo(rowproph, &pinfo); 6843941Svenki if (err != PICL_SUCCESS) 6853941Svenki return (err); 6863941Svenki 6873941Svenki pval = malloc(pinfo.size); 6883941Svenki if (pval == NULL) 6893941Svenki return (PICL_FAILURE); 6903941Svenki 6913941Svenki err = picl_get_propval(rowproph, pval, pinfo.size); 6923941Svenki if (err != PICL_SUCCESS) { 6933941Svenki free(pval); 6943941Svenki return (err); 6953941Svenki } 6963941Svenki 6973941Svenki *outbuf = pval; 6983941Svenki return (PICL_SUCCESS); 6991708Sstevel } 7001708Sstevel 7013941Svenki /* 7023941Svenki * print size of a memory segment 7033941Svenki */ 7043941Svenki static void 7053941Svenki print_memory_segment_size(uint64_t size) 7063941Svenki { 7073941Svenki uint64_t kbyte = 1024; 7083941Svenki uint64_t mbyte = kbyte * kbyte; 7093941Svenki uint64_t gbyte = kbyte * mbyte; 7105544Sfw157321 uint64_t tbyte = kbyte * gbyte; 7113941Svenki char buf[MEMORY_SIZE_FIELD]; 7123941Svenki 7135544Sfw157321 if (size >= tbyte) { 7145544Sfw157321 if (size % tbyte == 0) 7155544Sfw157321 (void) snprintf(buf, sizeof (buf), "%d TB", 7165544Sfw157321 (int)(size / tbyte)); 7175544Sfw157321 else 7185544Sfw157321 (void) snprintf(buf, sizeof (buf), "%.2f TB", 7195544Sfw157321 (float)size / tbyte); 7205544Sfw157321 } else if (size >= gbyte) { 7213941Svenki if (size % gbyte == 0) 7223941Svenki (void) snprintf(buf, sizeof (buf), "%d GB", 7234669Sfw157321 (int)(size / gbyte)); 7243941Svenki else 7253941Svenki (void) snprintf(buf, sizeof (buf), "%.2f GB", 7264669Sfw157321 (float)size / gbyte); 7273941Svenki } else if (size >= mbyte) { 7283941Svenki if (size % mbyte == 0) 7293941Svenki (void) snprintf(buf, sizeof (buf), "%d MB", 7304669Sfw157321 (int)(size / mbyte)); 7313941Svenki else 7323941Svenki (void) snprintf(buf, sizeof (buf), "%.2f MB", 7334669Sfw157321 (float)size / mbyte); 7343941Svenki } else { 7353941Svenki if (size % kbyte == 0) 7363941Svenki (void) snprintf(buf, sizeof (buf), "%d KB", 7374669Sfw157321 (int)(size / kbyte)); 7383941Svenki else 7393941Svenki (void) snprintf(buf, sizeof (buf), "%.2f KB", 7404669Sfw157321 (float)size / kbyte); 7413941Svenki } 7425544Sfw157321 log_printf("%-9s", buf); 7433941Svenki } 7443941Svenki 7453941Svenki /* 7464669Sfw157321 * Enumerate banks and dimms within a memory segment. We're handed 7474669Sfw157321 * the first bank within the segment - we assume there are dimms 7484669Sfw157321 * (memory-module) nodes underneath. 7493941Svenki */ 7503941Svenki static void 7514669Sfw157321 print_memory_segment_contain(picl_nodehdl_t bank_nodeh) 7521708Sstevel { 7533941Svenki char val[PICL_PROPNAMELEN_MAX]; 7544669Sfw157321 picl_nodehdl_t module_nodeh; 7554669Sfw157321 int flag = 0; 7565544Sfw157321 uint64_t size; 7574669Sfw157321 7584669Sfw157321 do { 7594669Sfw157321 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD, 7604669Sfw157321 &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS) 7614669Sfw157321 continue; 7625544Sfw157321 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_SIZE, 7635544Sfw157321 &size, sizeof (size)) == PICL_SUCCESS) { 7645544Sfw157321 if (!flag) { 7655544Sfw157321 print_memory_segment_size(size); 7665544Sfw157321 } else { 7675544Sfw157321 log_printf(" " 7685544Sfw157321 " "); 7695544Sfw157321 print_memory_segment_size(size); 7705544Sfw157321 flag = 0; 7715544Sfw157321 } 7725544Sfw157321 } 7734669Sfw157321 do { 7744669Sfw157321 if (picl_get_propval_by_name(module_nodeh, 7754669Sfw157321 PICL_PROP_NAC, val, sizeof (val)) != 7764669Sfw157321 PICL_SUCCESS) 7774669Sfw157321 continue; 7784669Sfw157321 else { 7794669Sfw157321 if (!flag) { 7805544Sfw157321 log_printf("%s\n", val); 7814669Sfw157321 flag = 1; 7825544Sfw157321 } else { 7835544Sfw157321 log_printf("%s%s\n", 7845544Sfw157321 " " 7855544Sfw157321 " ", 7865544Sfw157321 val); 7875544Sfw157321 } 7884669Sfw157321 } 7894669Sfw157321 } while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER, 7904669Sfw157321 &module_nodeh, sizeof (picl_nodehdl_t)) == 7914669Sfw157321 PICL_SUCCESS); 7924669Sfw157321 } while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER, 7934669Sfw157321 &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS); 7943941Svenki } 7953941Svenki 7963941Svenki /* 7973941Svenki * Search node where _class=="memory-segment" 7983941Svenki * print "Base Address", "Size", etc 7993941Svenki */ 8003941Svenki /*ARGSUSED*/ 8013941Svenki static int 8023941Svenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args) 8033941Svenki { 8043941Svenki uint64_t base; 8053941Svenki uint64_t size; 8063941Svenki uint64_t ifactor; 8073941Svenki picl_errno_t err = PICL_SUCCESS; 8083941Svenki 8093941Svenki if (class_node_found == 0) { 8103941Svenki class_node_found = 1; 8113941Svenki return (PICL_WALK_TERMINATE); 8123941Svenki } 8133941Svenki while (err == PICL_SUCCESS) { 8143941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS, 8154669Sfw157321 &base, sizeof (base)); 8163941Svenki if (err != PICL_SUCCESS) 8173941Svenki break; 8183941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE, 8194669Sfw157321 &size, sizeof (size)); 8203941Svenki if (err != PICL_SUCCESS) 8213941Svenki break; 8223941Svenki err = picl_get_propval_by_name(nodeh, 8234669Sfw157321 PICL_PROP_INTERLEAVE_FACTOR, &ifactor, 8244669Sfw157321 sizeof (ifactor)); 8253941Svenki if (err != PICL_SUCCESS) 8263941Svenki break; 8275544Sfw157321 log_printf("0x%-13llx", base); 8283941Svenki print_memory_segment_size(size); 8295544Sfw157321 log_printf("%-12lld", ifactor); 8304669Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, 8314669Sfw157321 &nodeh, sizeof (nodeh)); 8324669Sfw157321 if (err == PICL_SUCCESS) 8334669Sfw157321 print_memory_segment_contain(nodeh); 8343941Svenki log_printf("\n"); 8353941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 8364669Sfw157321 sizeof (picl_nodehdl_t)); 8373941Svenki } 8383941Svenki 8393941Svenki return (PICL_WALK_CONTINUE); 8403941Svenki } 8413941Svenki 8423941Svenki /*ARGSUSED*/ 8433941Svenki void 8443941Svenki sun4v_display_memory_conf(picl_nodehdl_t plafh) 8453941Svenki { 8465544Sfw157321 char *fmt = "%-14s %-8s %-11s %-8s %-s"; 8473941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 8484669Sfw157321 NULL, sun4v_memory_conf_callback); 8493941Svenki if (class_node_found == 0) 8503941Svenki return; 8513941Svenki log_printf("\n"); 8525544Sfw157321 log_printf("======================="); 8535544Sfw157321 log_printf(" Physical Memory Configuration "); 8545544Sfw157321 log_printf("========================"); 8553941Svenki log_printf("\n"); 8563941Svenki log_printf("Segment Table:\n"); 8574669Sfw157321 log_printf( 8585544Sfw157321 "--------------------------------------------------------------\n"); 8595544Sfw157321 log_printf(fmt, "Base", "Segment", "Interleave", "Bank", "Contains", 0); 8605544Sfw157321 log_printf("\n"); 8615544Sfw157321 log_printf(fmt, "Address", "Size", "Factor", "Size", "Modules", 0); 8623941Svenki log_printf("\n"); 8634669Sfw157321 log_printf( 8645544Sfw157321 "--------------------------------------------------------------\n"); 8653941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 8664669Sfw157321 NULL, sun4v_memory_conf_callback); 8671708Sstevel } 8681708Sstevel 8691708Sstevel void 8701708Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh) 8711708Sstevel { 8725544Sfw157321 char *fmt = "%-6s %-9s %-22s %-6s"; 8731708Sstevel 8741708Sstevel /* 8751708Sstevel * Display the table header for CPUs . Then display the CPU 8761708Sstevel * frequency, cache size, and processor revision of all cpus. 8771708Sstevel */ 8781708Sstevel log_printf(dgettext(TEXT_DOMAIN, 8794669Sfw157321 "\n" 8805544Sfw157321 "================================" 8815544Sfw157321 " Virtual CPUs " 8825544Sfw157321 "================================" 8834669Sfw157321 "\n" 8844669Sfw157321 "\n")); 8851708Sstevel log_printf("\n"); 8865544Sfw157321 log_printf(fmt, "CPU ID", "Frequency", "Implementation", 8875544Sfw157321 "Status", 0); 8881708Sstevel log_printf("\n"); 8895544Sfw157321 log_printf(fmt, "------", "---------", 8905544Sfw157321 "----------------------", "-------", 0); 8911708Sstevel log_printf("\n"); 8921708Sstevel 8935544Sfw157321 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU, 8945544Sfw157321 sun4v_display_cpus); 8951708Sstevel } 8961708Sstevel 8971708Sstevel /* 8981708Sstevel * Display the CPUs present on this board. 8991708Sstevel */ 9001708Sstevel /*ARGSUSED*/ 9011708Sstevel int 9021708Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args) 9031708Sstevel { 9041708Sstevel int status; 9053941Svenki picl_prophdl_t proph; 9063941Svenki picl_prophdl_t tblh; 9073941Svenki picl_prophdl_t rowproph; 9081708Sstevel picl_propinfo_t propinfo; 9093941Svenki int *int_value; 9105028Sfw157321 int cpuid; 9113941Svenki char *comp_value; 9123941Svenki char *no_prop_value = " "; 9133941Svenki char freq_str[MAXSTRLEN]; 9145028Sfw157321 char state[MAXSTRLEN]; 9151708Sstevel 9161708Sstevel /* 9171708Sstevel * Get cpuid property and print it and the NAC name 9181708Sstevel */ 9195544Sfw157321 status = picl_get_propinfo_by_name(cpuh, OBP_PROP_CPUID, &propinfo, 9205544Sfw157321 &proph); 9211708Sstevel if (status == PICL_SUCCESS) { 9221708Sstevel status = picl_get_propval(proph, &cpuid, sizeof (cpuid)); 9231708Sstevel if (status != PICL_SUCCESS) { 9245544Sfw157321 log_printf("%-7s", no_prop_value); 9251708Sstevel } else { 9265544Sfw157321 log_printf("%-7d", cpuid); 9271708Sstevel } 9281708Sstevel } else { 9295544Sfw157321 log_printf("%-7s", no_prop_value); 9301708Sstevel } 9311708Sstevel 9321708Sstevel clock_freq: 9331708Sstevel status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo, 9344669Sfw157321 &proph); 9351708Sstevel if (status == PICL_SUCCESS) { 9361708Sstevel int_value = malloc(propinfo.size); 9371708Sstevel if (int_value == NULL) { 9385544Sfw157321 log_printf("%-10s", no_prop_value); 9391708Sstevel goto compatible; 9401708Sstevel } 9411708Sstevel status = picl_get_propval(proph, int_value, propinfo.size); 9421708Sstevel if (status != PICL_SUCCESS) { 9435544Sfw157321 log_printf("%-10s", no_prop_value); 9441708Sstevel } else { 9451708Sstevel /* Running frequency */ 9461708Sstevel (void) snprintf(freq_str, sizeof (freq_str), "%d MHz", 9471708Sstevel CLK_FREQ_TO_MHZ(*int_value)); 9485544Sfw157321 log_printf("%-10s", freq_str); 9491708Sstevel } 9501708Sstevel free(int_value); 9511708Sstevel } else 9525544Sfw157321 log_printf("%-10s", no_prop_value); 9531708Sstevel 9541708Sstevel compatible: 9551708Sstevel status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo, 9564669Sfw157321 &proph); 9571708Sstevel if (status == PICL_SUCCESS) { 9581708Sstevel if (propinfo.type == PICL_PTYPE_CHARSTRING) { 9591708Sstevel /* 9601708Sstevel * Compatible Property only has 1 value 9611708Sstevel */ 9621708Sstevel comp_value = malloc(propinfo.size); 9631708Sstevel if (comp_value == NULL) { 9645544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9655028Sfw157321 goto state; 9661708Sstevel } 9671708Sstevel status = picl_get_propval(proph, comp_value, 9684669Sfw157321 propinfo.size); 9693941Svenki if (status != PICL_SUCCESS) 9705544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9713941Svenki else 9725544Sfw157321 log_printf("%-23s", comp_value, 0); 9733941Svenki free(comp_value); 9741708Sstevel } else if (propinfo.type == PICL_PTYPE_TABLE) { 9751708Sstevel /* 9761708Sstevel * Compatible Property has multiple values 9771708Sstevel */ 9781708Sstevel status = picl_get_propval(proph, &tblh, propinfo.size); 9791708Sstevel if (status != PICL_SUCCESS) { 9805544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9815028Sfw157321 goto state; 9821708Sstevel } 9831708Sstevel status = picl_get_next_by_row(tblh, &rowproph); 9841708Sstevel if (status != PICL_SUCCESS) { 9855544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9865028Sfw157321 goto state; 9871708Sstevel } 9881708Sstevel 9891708Sstevel status = picl_get_propinfo(rowproph, &propinfo); 9901708Sstevel if (status != PICL_SUCCESS) { 9915544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9925028Sfw157321 goto state; 9931708Sstevel } 9941708Sstevel 9951708Sstevel comp_value = malloc(propinfo.size); 9961708Sstevel if (comp_value == NULL) { 9975544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9985028Sfw157321 goto state; 9991708Sstevel } 10001708Sstevel status = picl_get_propval(rowproph, comp_value, 10014669Sfw157321 propinfo.size); 10023941Svenki if (status != PICL_SUCCESS) 10035544Sfw157321 log_printf("%-23s", no_prop_value, 0); 10043941Svenki else 10055544Sfw157321 log_printf("%-23s", comp_value, 0); 10061708Sstevel free(comp_value); 10071708Sstevel } 10081708Sstevel } else 10095544Sfw157321 log_printf("%-23s", no_prop_value, 0); 10101708Sstevel 10115028Sfw157321 state: 10125028Sfw157321 status = picl_get_propinfo_by_name(cpuh, PICL_PROP_STATE, 10135028Sfw157321 &propinfo, &proph); 10141708Sstevel if (status == PICL_SUCCESS) { 10155028Sfw157321 status = picl_get_propval(proph, state, sizeof (state)); 10161708Sstevel if (status != PICL_SUCCESS) { 10173941Svenki log_printf("%-9s", no_prop_value); 10181708Sstevel } else { 10195028Sfw157321 log_printf("%-9s", state); 10201708Sstevel } 10211708Sstevel } else 10223941Svenki log_printf("%-9s", no_prop_value); 10231708Sstevel 10241708Sstevel done: 10251708Sstevel log_printf("\n"); 10261708Sstevel return (PICL_WALK_CONTINUE); 10271708Sstevel } 10281708Sstevel 10291708Sstevel void 10301708Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh) 10311708Sstevel { 10321708Sstevel #ifdef lint 10331708Sstevel flag = flag; 10341708Sstevel root = root; 10351708Sstevel plafh = plafh; 10361708Sstevel #endif 10371708Sstevel /* 10381708Sstevel * This function is intentionally empty 10391708Sstevel */ 10401708Sstevel } 10411708Sstevel 10421708Sstevel void 10431708Sstevel display_boardnum(int num) 10441708Sstevel { 10451708Sstevel log_printf("%2d ", num, 0); 10461708Sstevel } 10473941Svenki 10485547Smb158278 static int 10493941Svenki sun4v_disp_env_status() 10503941Svenki { 10515547Smb158278 int exit_code = 0; 10525547Smb158278 10533941Svenki if (phyplatformh == 0) 10545547Smb158278 return (0); 10553941Svenki log_printf("\n"); 10563941Svenki log_printf("============================"); 10573941Svenki log_printf(" Environmental Status "); 10583941Svenki log_printf("============================"); 10593941Svenki log_printf("\n"); 10603941Svenki 10613941Svenki class_node_found = 0; 10623941Svenki all_status_ok = 1; 10633941Svenki sun4v_env_print_fan_sensors(); 10645547Smb158278 exit_code |= (!all_status_ok); 10653941Svenki 10663941Svenki class_node_found = 0; 10673941Svenki all_status_ok = 1; 10683941Svenki sun4v_env_print_fan_indicators(); 10695547Smb158278 exit_code |= (!all_status_ok); 10703941Svenki 10713941Svenki class_node_found = 0; 10723941Svenki all_status_ok = 1; 10733941Svenki sun4v_env_print_temp_sensors(); 10745547Smb158278 exit_code |= (!all_status_ok); 10753941Svenki 10763941Svenki class_node_found = 0; 10773941Svenki all_status_ok = 1; 10783941Svenki sun4v_env_print_temp_indicators(); 10795547Smb158278 exit_code |= (!all_status_ok); 10803941Svenki 10813941Svenki class_node_found = 0; 10823941Svenki all_status_ok = 1; 10833941Svenki sun4v_env_print_current_sensors(); 10845547Smb158278 exit_code |= (!all_status_ok); 10853941Svenki 10863941Svenki class_node_found = 0; 10873941Svenki all_status_ok = 1; 10883941Svenki sun4v_env_print_current_indicators(); 10895547Smb158278 exit_code |= (!all_status_ok); 10903941Svenki 10913941Svenki class_node_found = 0; 10923941Svenki all_status_ok = 1; 10933941Svenki sun4v_env_print_voltage_sensors(); 10945547Smb158278 exit_code |= (!all_status_ok); 10953941Svenki 10963941Svenki class_node_found = 0; 10973941Svenki all_status_ok = 1; 10983941Svenki sun4v_env_print_voltage_indicators(); 10995547Smb158278 exit_code |= (!all_status_ok); 11003941Svenki 11013941Svenki class_node_found = 0; 11025547Smb158278 all_status_ok = 1; 1103*8574SJason.Beloro@Sun.COM sun4v_env_print_humidity_sensors(); 1104*8574SJason.Beloro@Sun.COM exit_code |= (!all_status_ok); 1105*8574SJason.Beloro@Sun.COM 1106*8574SJason.Beloro@Sun.COM class_node_found = 0; 1107*8574SJason.Beloro@Sun.COM all_status_ok = 1; 1108*8574SJason.Beloro@Sun.COM sun4v_env_print_humidity_indicators(); 1109*8574SJason.Beloro@Sun.COM exit_code |= (!all_status_ok); 1110*8574SJason.Beloro@Sun.COM 1111*8574SJason.Beloro@Sun.COM class_node_found = 0; 1112*8574SJason.Beloro@Sun.COM all_status_ok = 1; 11133941Svenki sun4v_env_print_LEDs(); 11145547Smb158278 exit_code |= (!all_status_ok); 11153941Svenki 11163941Svenki class_node_found = 0; 11173941Svenki all_status_ok = 1; 11183941Svenki sun4v_print_fru_status(); 11195547Smb158278 exit_code |= (!all_status_ok); 11203941Svenki 11213941Svenki class_node_found = 0; 11223941Svenki sun4v_print_fw_rev(); 11233941Svenki 11245436Sfw157321 class_node_found = 0; 11255436Sfw157321 sun4v_print_openprom_rev(); 11265436Sfw157321 11273941Svenki sun4v_print_chassis_serial_no(); 11285547Smb158278 11295547Smb158278 return (exit_code); 11303941Svenki } 11313941Svenki 11323941Svenki /*ARGSUSED*/ 11333941Svenki static int 11343941Svenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args) 11353941Svenki { 11363941Svenki char val[PICL_PROPNAMELEN_MAX]; 11373941Svenki picl_nodehdl_t parenth; 11383941Svenki char *names[PARENT_NAMES]; 11394802Sfw157321 char *base_units[PICL_PROPNAMELEN_MAX]; 11403941Svenki char *loc; 11413941Svenki int i; 11423941Svenki char *prop; 11433941Svenki picl_errno_t err; 11445436Sfw157321 int32_t lo_warning, lo_shutdown, lo_poweroff; 11455436Sfw157321 int32_t hi_warning, hi_shutdown, hi_poweroff; 11463941Svenki int32_t current_val; 11474802Sfw157321 int32_t exponent; 11484802Sfw157321 double display_val; 11494928Sfw157321 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 11504928Sfw157321 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 11514928Sfw157321 sensor_status_t sensor_status = SENSOR_OK; 11523941Svenki 11533941Svenki if (class_node_found == 0) { 11543941Svenki class_node_found = 1; 11553941Svenki return (PICL_WALK_TERMINATE); 11563941Svenki } 11573941Svenki 11584928Sfw157321 prop = (char *)args; 11594928Sfw157321 if (!prop) { 11604928Sfw157321 sensor_status = SENSOR_UNKNOWN; 11614928Sfw157321 all_status_ok = 0; 11624928Sfw157321 } else { 11633941Svenki err = picl_get_propval_by_name(nodeh, 11644669Sfw157321 PICL_PROP_OPERATIONAL_STATUS, val, 11654669Sfw157321 sizeof (val)); 11663941Svenki if (err == PICL_SUCCESS) { 11673941Svenki if (strcmp(val, "disabled") == 0) { 11684928Sfw157321 sensor_status = SENSOR_DISABLED; 11694928Sfw157321 } 11704928Sfw157321 } 11714928Sfw157321 } 11724928Sfw157321 11734928Sfw157321 if (sensor_status != SENSOR_DISABLED && 11744928Sfw157321 sensor_status != SENSOR_UNKNOWN) { 11754928Sfw157321 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 11764928Sfw157321 sizeof (current_val)) != PICL_SUCCESS) { 11774928Sfw157321 sensor_status = SENSOR_UNKNOWN; 11785436Sfw157321 } else { 11795436Sfw157321 if (picl_get_propval_by_name(nodeh, 11805436Sfw157321 PICL_PROP_LOW_WARNING, 11815436Sfw157321 &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS) 11825436Sfw157321 lo_warning = INVALID_THRESHOLD; 11835436Sfw157321 if (picl_get_propval_by_name(nodeh, 11845436Sfw157321 PICL_PROP_LOW_SHUTDOWN, 11855436Sfw157321 &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS) 11865436Sfw157321 lo_shutdown = INVALID_THRESHOLD; 11875436Sfw157321 if (picl_get_propval_by_name(nodeh, 11885436Sfw157321 PICL_PROP_LOW_POWER_OFF, 11895436Sfw157321 &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS) 11905436Sfw157321 lo_poweroff = INVALID_THRESHOLD; 11915436Sfw157321 if (picl_get_propval_by_name(nodeh, 11925436Sfw157321 PICL_PROP_HIGH_WARNING, 11935436Sfw157321 &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS) 11945436Sfw157321 hi_warning = INVALID_THRESHOLD; 11955436Sfw157321 if (picl_get_propval_by_name(nodeh, 11965436Sfw157321 PICL_PROP_HIGH_SHUTDOWN, 11975436Sfw157321 &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS) 11985436Sfw157321 hi_shutdown = INVALID_THRESHOLD; 11995436Sfw157321 if (picl_get_propval_by_name(nodeh, 12005436Sfw157321 PICL_PROP_HIGH_POWER_OFF, 12015436Sfw157321 &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS) 12025436Sfw157321 hi_poweroff = INVALID_THRESHOLD; 12034928Sfw157321 12045436Sfw157321 if ((lo_poweroff != INVALID_THRESHOLD && 12055436Sfw157321 current_val <= lo_poweroff) || 12065436Sfw157321 (hi_poweroff != INVALID_THRESHOLD && 12075436Sfw157321 current_val >= hi_poweroff)) { 12085436Sfw157321 sensor_status = SENSOR_FAILED; 12095436Sfw157321 } else if ((lo_shutdown != INVALID_THRESHOLD && 12105436Sfw157321 current_val <= lo_shutdown) || 12115436Sfw157321 (hi_shutdown != INVALID_THRESHOLD && 12125436Sfw157321 current_val >= hi_shutdown)) { 12135436Sfw157321 sensor_status = SENSOR_FAILED; 12145436Sfw157321 } else if ((lo_warning != INVALID_THRESHOLD && 12155436Sfw157321 current_val <= lo_warning) || 12165436Sfw157321 (hi_warning != INVALID_THRESHOLD && 12175436Sfw157321 current_val >= hi_warning)) { 12185436Sfw157321 sensor_status = SENSOR_WARN; 12195436Sfw157321 } else { 12205436Sfw157321 sensor_status = SENSOR_OK; 12215436Sfw157321 } 12224928Sfw157321 } 12234928Sfw157321 } 12244928Sfw157321 12254928Sfw157321 if (syserrlog == 0) { 12264928Sfw157321 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 12273941Svenki all_status_ok = 0; 12283941Svenki return (PICL_WALK_TERMINATE); 12293941Svenki } 12304928Sfw157321 if (sensor_status == SENSOR_OK) { 12314928Sfw157321 return (PICL_WALK_CONTINUE); 12324928Sfw157321 } 12333941Svenki } 12344928Sfw157321 12354928Sfw157321 /* 12364928Sfw157321 * If we're here then prtdiag was invoked with "-v" or we have 12374928Sfw157321 * a sensor that is beyond a threshold, so give them a book to 12384928Sfw157321 * read instead of the Cliff Notes. 12394928Sfw157321 */ 12403941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 12414669Sfw157321 sizeof (parenth)); 12423941Svenki if (err != PICL_SUCCESS) { 12433941Svenki log_printf("\n"); 12443941Svenki return (PICL_WALK_CONTINUE); 12453941Svenki } 12464003Svivek 12474928Sfw157321 /* gather up the path name for the sensor */ 12484928Sfw157321 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 12494928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) { 12504928Sfw157321 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 12514928Sfw157321 NULL) { 12524928Sfw157321 while (--i > -1) 12534928Sfw157321 free(names[i]); 12544928Sfw157321 free(loc); 12554928Sfw157321 loc = NULL; 12564928Sfw157321 } 12573941Svenki } 12584003Svivek } 12594928Sfw157321 i = 0; 12604928Sfw157321 if (loc != 0) { 12614928Sfw157321 while (err == PICL_SUCCESS) { 12624928Sfw157321 if (parenth == phyplatformh) 12634928Sfw157321 break; 12644928Sfw157321 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 12654928Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 12664928Sfw157321 if (err != PICL_SUCCESS) { 12674928Sfw157321 i--; 12684928Sfw157321 break; 12694928Sfw157321 } 12704928Sfw157321 if (i == PARENT_NAMES) 12714928Sfw157321 break; 12724928Sfw157321 err = picl_get_propval_by_name(parenth, 12734928Sfw157321 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 12744928Sfw157321 } 12754928Sfw157321 loc[0] = '\0'; 12764928Sfw157321 if (--i > -1) { 12774928Sfw157321 (void) strlcat(loc, names[i], 12784928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 12794928Sfw157321 } 12804928Sfw157321 while (--i > -1) { 12814928Sfw157321 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 12824928Sfw157321 PARENT_NAMES); 12834928Sfw157321 (void) strlcat(loc, names[i], 12844928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 12854928Sfw157321 } 12865028Sfw157321 log_printf("%-35s", loc); 12874928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) 12884928Sfw157321 free(names[i]); 12894928Sfw157321 free(loc); 12904928Sfw157321 } else { 12915028Sfw157321 log_printf("%-35s", " "); 12923941Svenki } 12933941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 12944669Sfw157321 sizeof (val)); 12953941Svenki if (err == PICL_SUCCESS) 12963941Svenki log_printf("%-15s", val); 12973941Svenki 12984928Sfw157321 /* 12994928Sfw157321 * Get the exponent if present, and do a little math so that 13004928Sfw157321 * if we need to we can print a normalized value for the 13014928Sfw157321 * sensor reading. 13024928Sfw157321 */ 13034802Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT, 13044802Sfw157321 &exponent, sizeof (exponent)) != PICL_SUCCESS) 13054802Sfw157321 exponent = 0; 13064802Sfw157321 if (exponent == 0) 13074802Sfw157321 display_val = (double)current_val; 13085436Sfw157321 else { 13094802Sfw157321 display_val = (double)current_val * 13104802Sfw157321 pow((double)10, (double)exponent); 13115436Sfw157321 13125436Sfw157321 /* 13135436Sfw157321 * Sometimes ILOM will scale a sensor reading but 13145436Sfw157321 * there will be nothing to the right of the decimal 13155436Sfw157321 * once that value is normalized. Setting the 13165436Sfw157321 * exponent to zero will prevent the printf below 13175436Sfw157321 * from printing extraneous zeros. Otherwise a 13185436Sfw157321 * negative exponent is used to set the precision 13195436Sfw157321 * for the printf. 13205436Sfw157321 */ 13215436Sfw157321 if ((int)display_val == display_val || exponent > 0) 13225436Sfw157321 exponent = 0; 13235436Sfw157321 } 13245436Sfw157321 13254928Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS, 13264928Sfw157321 base_units, sizeof (base_units)); 13274802Sfw157321 if (err != PICL_SUCCESS) 13284802Sfw157321 base_units[0] = '\0'; 13293941Svenki 13304928Sfw157321 switch (sensor_status) { 13314928Sfw157321 case SENSOR_FAILED: 13323941Svenki log_printf("%-s", "failed ("); 13334802Sfw157321 log_printf("%-.*f", abs(exponent), display_val); 13344802Sfw157321 log_printf("%-s %s", base_units, ")"); 13354928Sfw157321 break; 13364928Sfw157321 case SENSOR_WARN: 13373941Svenki log_printf("%-s", "warning ("); 13384802Sfw157321 log_printf("%-.*f", abs(exponent), display_val); 13394802Sfw157321 log_printf("%-s %s", base_units, ")"); 13404928Sfw157321 break; 13414928Sfw157321 case SENSOR_DISABLED: 13424928Sfw157321 log_printf("%-s", "disabled"); 13434928Sfw157321 break; 13444928Sfw157321 case SENSOR_OK: 13453941Svenki log_printf("%-s", "ok"); 13464928Sfw157321 break; 13474928Sfw157321 default: 13484928Sfw157321 log_printf("%-s", "unknown"); 13494928Sfw157321 break; 13504928Sfw157321 } 13513941Svenki 13523941Svenki log_printf("\n"); 13533941Svenki return (PICL_WALK_CONTINUE); 13543941Svenki } 13553941Svenki 13563941Svenki /*ARGSUSED*/ 13573941Svenki static int 13583941Svenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args) 13593941Svenki { 13604928Sfw157321 char current_val[PICL_PROPNAMELEN_MAX]; 13614928Sfw157321 char expected_val[PICL_PROPNAMELEN_MAX]; 13624928Sfw157321 char label[PICL_PROPNAMELEN_MAX]; 13633941Svenki picl_nodehdl_t parenth; 13643941Svenki char *names[PARENT_NAMES]; 13653941Svenki char *loc; 13663941Svenki int i = 0; 13673941Svenki char *prop = (char *)args; 13683941Svenki picl_errno_t err = PICL_SUCCESS; 13694928Sfw157321 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 13704928Sfw157321 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 13714928Sfw157321 sensor_status_t sensor_status = SENSOR_OK; 13723941Svenki 13733941Svenki if (class_node_found == 0) { 13743941Svenki class_node_found = 1; 13753941Svenki return (PICL_WALK_TERMINATE); 13763941Svenki } 13774928Sfw157321 13784928Sfw157321 prop = (char *)args; 13794928Sfw157321 if (!prop) { 13804928Sfw157321 sensor_status = SENSOR_UNKNOWN; 13814928Sfw157321 all_status_ok = 0; 13824928Sfw157321 } else { 13833941Svenki err = picl_get_propval_by_name(nodeh, 13844928Sfw157321 PICL_PROP_OPERATIONAL_STATUS, current_val, 13854928Sfw157321 sizeof (current_val)); 13863941Svenki if (err == PICL_SUCCESS) { 13874928Sfw157321 if (strcmp(current_val, "disabled") == 0) { 13884928Sfw157321 sensor_status = SENSOR_DISABLED; 13894928Sfw157321 } 13904928Sfw157321 } 13914928Sfw157321 } 13924928Sfw157321 13934928Sfw157321 if (sensor_status != SENSOR_DISABLED && 13944928Sfw157321 sensor_status != SENSOR_UNKNOWN) { 13954928Sfw157321 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 13964928Sfw157321 sizeof (current_val)) != PICL_SUCCESS) { 13974928Sfw157321 (void) strlcpy(current_val, "unknown", 13984928Sfw157321 sizeof (current_val)); 13994928Sfw157321 sensor_status = SENSOR_UNKNOWN; 14004928Sfw157321 } else { 14014928Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED, 14024928Sfw157321 &expected_val, sizeof (expected_val)) != 14034928Sfw157321 PICL_SUCCESS) { 14044928Sfw157321 sensor_status = SENSOR_UNKNOWN; 14054928Sfw157321 } else { 14064928Sfw157321 if (strncmp(current_val, expected_val, 14074928Sfw157321 sizeof (current_val)) == 0) { 14084928Sfw157321 sensor_status = SENSOR_OK; 14094928Sfw157321 } else { 14104928Sfw157321 sensor_status = SENSOR_FAILED; 14113941Svenki } 14124928Sfw157321 } 14134928Sfw157321 } 14144928Sfw157321 } 14154928Sfw157321 14164928Sfw157321 if (syserrlog == 0) { 14174928Sfw157321 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 14183941Svenki all_status_ok = 0; 14193941Svenki return (PICL_WALK_TERMINATE); 14203941Svenki } 14214928Sfw157321 if (sensor_status == SENSOR_OK) { 14224928Sfw157321 return (PICL_WALK_CONTINUE); 14234928Sfw157321 } 14243941Svenki } 14254928Sfw157321 14264928Sfw157321 /* 14274928Sfw157321 * If we're here then prtdiag was invoked with "-v" or we have 14284928Sfw157321 * a sensor that is beyond a threshold, so give them a book to 14294928Sfw157321 * read instead of the Cliff Notes. 14304928Sfw157321 */ 14313941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 14324669Sfw157321 sizeof (parenth)); 14333941Svenki if (err != PICL_SUCCESS) { 14343941Svenki log_printf("\n"); 14353941Svenki return (PICL_WALK_CONTINUE); 14363941Svenki } 14374928Sfw157321 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 14384928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) { 14394928Sfw157321 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 14404928Sfw157321 NULL) { 14414928Sfw157321 while (--i > -1) 14424928Sfw157321 free(names[i]); 14434928Sfw157321 free(loc); 14444928Sfw157321 loc = NULL; 14454928Sfw157321 } 14463941Svenki } 14473941Svenki } 14484928Sfw157321 i = 0; 14494928Sfw157321 if (loc) { 14504928Sfw157321 while (err == PICL_SUCCESS) { 14514928Sfw157321 if (parenth == phyplatformh) 14524928Sfw157321 break; 14534928Sfw157321 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 14544928Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 14554928Sfw157321 if (err != PICL_SUCCESS) { 14564928Sfw157321 i--; 14574928Sfw157321 break; 14584928Sfw157321 } 14594928Sfw157321 if (i == PARENT_NAMES) 14604928Sfw157321 break; 14614928Sfw157321 err = picl_get_propval_by_name(parenth, 14624928Sfw157321 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 14634928Sfw157321 } 14644928Sfw157321 loc[0] = '\0'; 14654928Sfw157321 if (--i > -1) { 14664928Sfw157321 (void) strlcat(loc, names[i], 14674928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 14684928Sfw157321 } 14694928Sfw157321 while (--i > -1) { 14704928Sfw157321 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 14714928Sfw157321 PARENT_NAMES); 14724928Sfw157321 (void) strlcat(loc, names[i], 14734928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 14744928Sfw157321 } 14755028Sfw157321 log_printf("%-35s", loc); 14764928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) 14774928Sfw157321 free(names[i]); 14784928Sfw157321 free(loc); 14794928Sfw157321 } else { 14805028Sfw157321 log_printf("%-35s", ""); 14813941Svenki } 14824928Sfw157321 14834928Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 14844928Sfw157321 sizeof (label)); 14854928Sfw157321 if (err != PICL_SUCCESS) 14864928Sfw157321 (void) strlcpy(label, "", sizeof (label)); 14874928Sfw157321 log_printf("%-15s", label); 14884928Sfw157321 14894928Sfw157321 log_printf("%-8s", current_val); 14904928Sfw157321 14913941Svenki log_printf("\n"); 14923941Svenki return (PICL_WALK_CONTINUE); 14933941Svenki } 14943941Svenki 14953941Svenki static void 14963941Svenki sun4v_env_print_fan_sensors() 14973941Svenki { 14985028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 14993941Svenki /* 15003941Svenki * If there isn't any fan sensor node, return now. 15013941Svenki */ 15023941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15034928Sfw157321 PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED, 15044669Sfw157321 sun4v_env_print_sensor_callback); 15053941Svenki if (!class_node_found) 15063941Svenki return; 15073941Svenki log_printf("Fan sensors:\n"); 15083941Svenki if (syserrlog == 0) { 15093941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15104669Sfw157321 PICL_CLASS_RPM_SENSOR, 15114928Sfw157321 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 15123941Svenki if (all_status_ok) { 15133941Svenki log_printf("All fan sensors are OK.\n"); 15143941Svenki return; 15153941Svenki } 15163941Svenki } 15175028Sfw157321 log_printf("-------------------------------------------------" 15185028Sfw157321 "-----------\n"); 15193941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 15205028Sfw157321 log_printf("-------------------------------------------------" 15215028Sfw157321 "-----------\n"); 15223941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR, 15234669Sfw157321 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 15243941Svenki } 15253941Svenki 15263941Svenki static void 15273941Svenki sun4v_env_print_fan_indicators() 15283941Svenki { 15295028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 15303941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15314928Sfw157321 PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION, 15324669Sfw157321 sun4v_env_print_indicator_callback); 15333941Svenki if (!class_node_found) 15343941Svenki return; 15353941Svenki log_printf("\nFan indicators:\n"); 15363941Svenki if (syserrlog == 0) { 15373941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15384669Sfw157321 PICL_CLASS_RPM_INDICATOR, 15394928Sfw157321 (void *)PICL_PROP_CONDITION, 15404928Sfw157321 sun4v_env_print_indicator_callback); 15413941Svenki if (all_status_ok) { 15423941Svenki log_printf("All fan indicators are OK.\n"); 15433941Svenki return; 15443941Svenki } 15453941Svenki } 15465028Sfw157321 log_printf("-------------------------------------------------" 15475028Sfw157321 "-----------\n"); 15483941Svenki log_printf(fmt, "Location", "Sensor", "Condition", 0); 15495028Sfw157321 log_printf("-------------------------------------------------" 15505028Sfw157321 "-----------\n"); 15513941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR, 15524802Sfw157321 (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback); 15533941Svenki } 15543941Svenki 15553941Svenki static void 15563941Svenki sun4v_env_print_temp_sensors() 15573941Svenki { 15585028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 15593941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15604669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 15614669Sfw157321 (void *)PICL_PROP_TEMPERATURE, 15624669Sfw157321 sun4v_env_print_sensor_callback); 15633941Svenki if (!class_node_found) 15643941Svenki return; 15653941Svenki 15663941Svenki log_printf("\nTemperature sensors:\n"); 15673941Svenki if (syserrlog == 0) { 15683941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15694669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 15704928Sfw157321 PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 15713941Svenki if (all_status_ok) { 15723941Svenki log_printf("All temperature sensors are OK.\n"); 15733941Svenki return; 15743941Svenki } 15753941Svenki } 15765028Sfw157321 log_printf("-------------------------------------------------" 15775028Sfw157321 "-----------\n"); 15783941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 15795028Sfw157321 log_printf("-------------------------------------------------" 15805028Sfw157321 "-----------\n"); 15813941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15824669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 15834669Sfw157321 (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 15843941Svenki } 15853941Svenki 15863941Svenki static void 15873941Svenki sun4v_env_print_temp_indicators() 15883941Svenki { 15895028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 15903941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15914669Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION, 15924669Sfw157321 sun4v_env_print_indicator_callback); 15933941Svenki if (!class_node_found) 15943941Svenki return; 15953941Svenki log_printf("\nTemperature indicators:\n"); 15963941Svenki if (syserrlog == 0) { 15973941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15984928Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, 15994928Sfw157321 (void *)PICL_PROP_CONDITION, 16004669Sfw157321 sun4v_env_print_indicator_callback); 16013941Svenki if (all_status_ok) { 16023941Svenki log_printf("All temperature indicators are OK.\n"); 16033941Svenki return; 16043941Svenki } 16053941Svenki } 16065028Sfw157321 log_printf("-------------------------------------------------" 16075028Sfw157321 "-----------\n"); 16083941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 16095028Sfw157321 log_printf("-------------------------------------------------" 16105028Sfw157321 "-----------\n"); 16113941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16124669Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, 16134669Sfw157321 (void *)PICL_PROP_CONDITION, 16144669Sfw157321 sun4v_env_print_indicator_callback); 16153941Svenki } 16163941Svenki 16173941Svenki static void 16183941Svenki sun4v_env_print_current_sensors() 16193941Svenki { 16205028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 16213941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR, 16224669Sfw157321 (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 16233941Svenki if (!class_node_found) 16243941Svenki return; 16253941Svenki log_printf("\nCurrent sensors:\n"); 16263941Svenki if (syserrlog == 0) { 16273941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16284669Sfw157321 PICL_CLASS_CURRENT_SENSOR, 16294928Sfw157321 PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 16303941Svenki if (all_status_ok) { 16313941Svenki log_printf("All current sensors are OK.\n"); 16323941Svenki return; 16333941Svenki } 16343941Svenki } 16355028Sfw157321 log_printf("-------------------------------------------------" 16365028Sfw157321 "-----------\n"); 16373941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 16385028Sfw157321 log_printf("-------------------------------------------------" 16395028Sfw157321 "-----------\n"); 16403941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16414669Sfw157321 PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT, 16424669Sfw157321 sun4v_env_print_sensor_callback); 16433941Svenki } 16443941Svenki 16453941Svenki static void 16463941Svenki sun4v_env_print_current_indicators() 16473941Svenki { 16485028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 16493941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16504669Sfw157321 PICL_CLASS_CURRENT_INDICATOR, 16514669Sfw157321 (void *)PICL_PROP_CONDITION, 16524669Sfw157321 sun4v_env_print_indicator_callback); 16533941Svenki if (!class_node_found) 16543941Svenki return; 16553941Svenki log_printf("\nCurrent indicators:\n"); 16563941Svenki if (syserrlog == 0) { 16573941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16584928Sfw157321 PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION, 16594669Sfw157321 sun4v_env_print_indicator_callback); 16603941Svenki if (all_status_ok) { 16613941Svenki log_printf("All current indicators are OK.\n"); 16623941Svenki return; 16633941Svenki } 16643941Svenki } 16655028Sfw157321 log_printf("-------------------------------------------------" 16665028Sfw157321 "-----------\n"); 16673941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 16685028Sfw157321 log_printf("-------------------------------------------------" 16695028Sfw157321 "-----------\n"); 16703941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16714669Sfw157321 PICL_CLASS_CURRENT_INDICATOR, 16724669Sfw157321 (void *)PICL_PROP_CONDITION, 16734669Sfw157321 sun4v_env_print_indicator_callback); 16743941Svenki } 16753941Svenki 16763941Svenki static void 16773941Svenki sun4v_env_print_voltage_sensors() 16783941Svenki { 16795028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 16803941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16814669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 16824669Sfw157321 PICL_PROP_VOLTAGE, 16834669Sfw157321 sun4v_env_print_sensor_callback); 16843941Svenki if (!class_node_found) 16853941Svenki return; 16863941Svenki log_printf("\nVoltage sensors:\n"); 16873941Svenki if (syserrlog == 0) { 16883941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16894669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 16904928Sfw157321 PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback); 16913941Svenki if (all_status_ok) { 16923941Svenki log_printf("All voltage sensors are OK.\n"); 16933941Svenki return; 16943941Svenki } 16953941Svenki } 16965028Sfw157321 log_printf("-------------------------------------------------" 16975028Sfw157321 "-----------\n"); 16983941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 16995028Sfw157321 log_printf("-------------------------------------------------" 17005028Sfw157321 "-----------\n"); 17013941Svenki (void) picl_walk_tree_by_class(phyplatformh, 17024669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 17034669Sfw157321 (void *)PICL_PROP_VOLTAGE, 17044669Sfw157321 sun4v_env_print_sensor_callback); 17053941Svenki } 17063941Svenki 17073941Svenki static void 17083941Svenki sun4v_env_print_voltage_indicators() 17093941Svenki { 17105028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 17113941Svenki (void) picl_walk_tree_by_class(phyplatformh, 17124669Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, 17134669Sfw157321 (void *)PICL_PROP_CONDITION, 17144669Sfw157321 sun4v_env_print_indicator_callback); 17153941Svenki if (!class_node_found) 17163941Svenki return; 17173941Svenki log_printf("\nVoltage indicators:\n"); 17183941Svenki if (syserrlog == 0) { 17193941Svenki (void) picl_walk_tree_by_class(phyplatformh, 17204928Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION, 17214669Sfw157321 sun4v_env_print_indicator_callback); 17223941Svenki if (all_status_ok) { 17233941Svenki log_printf("All voltage indicators are OK.\n"); 17243941Svenki return; 17253941Svenki } 17263941Svenki } 17275028Sfw157321 log_printf("-------------------------------------------------" 17285028Sfw157321 "-----------\n"); 17293941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 17305028Sfw157321 log_printf("-------------------------------------------------" 17315028Sfw157321 "-----------\n"); 17323941Svenki (void) picl_walk_tree_by_class(phyplatformh, 17334669Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, 17344669Sfw157321 (void *)PICL_PROP_CONDITION, 17354669Sfw157321 sun4v_env_print_indicator_callback); 17363941Svenki } 17373941Svenki 17383941Svenki static void 1739*8574SJason.Beloro@Sun.COM sun4v_env_print_humidity_sensors() 1740*8574SJason.Beloro@Sun.COM { 1741*8574SJason.Beloro@Sun.COM char *fmt = "%-34s %-14s %-10s\n"; 1742*8574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 1743*8574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_SENSOR, 1744*8574SJason.Beloro@Sun.COM (void *)PICL_PROP_HUMIDITY, 1745*8574SJason.Beloro@Sun.COM sun4v_env_print_sensor_callback); 1746*8574SJason.Beloro@Sun.COM if (!class_node_found) 1747*8574SJason.Beloro@Sun.COM return; 1748*8574SJason.Beloro@Sun.COM log_printf("\nHumidity sensors:\n"); 1749*8574SJason.Beloro@Sun.COM if (syserrlog == 0) { 1750*8574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 1751*8574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_SENSOR, 1752*8574SJason.Beloro@Sun.COM PICL_PROP_HUMIDITY, sun4v_env_print_sensor_callback); 1753*8574SJason.Beloro@Sun.COM if (all_status_ok) { 1754*8574SJason.Beloro@Sun.COM log_printf("All humidity sensors are OK.\n"); 1755*8574SJason.Beloro@Sun.COM return; 1756*8574SJason.Beloro@Sun.COM } 1757*8574SJason.Beloro@Sun.COM } 1758*8574SJason.Beloro@Sun.COM log_printf("-------------------------------------------------" 1759*8574SJason.Beloro@Sun.COM "-----------\n"); 1760*8574SJason.Beloro@Sun.COM log_printf(fmt, "Location", "Sensor", "Status", 0); 1761*8574SJason.Beloro@Sun.COM log_printf("-------------------------------------------------" 1762*8574SJason.Beloro@Sun.COM "-----------\n"); 1763*8574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 1764*8574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_SENSOR, 1765*8574SJason.Beloro@Sun.COM (void *)PICL_PROP_HUMIDITY, 1766*8574SJason.Beloro@Sun.COM sun4v_env_print_sensor_callback); 1767*8574SJason.Beloro@Sun.COM } 1768*8574SJason.Beloro@Sun.COM 1769*8574SJason.Beloro@Sun.COM static void 1770*8574SJason.Beloro@Sun.COM sun4v_env_print_humidity_indicators() 1771*8574SJason.Beloro@Sun.COM { 1772*8574SJason.Beloro@Sun.COM char *fmt = "%-34s %-14s %-8s\n"; 1773*8574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 1774*8574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_INDICATOR, 1775*8574SJason.Beloro@Sun.COM (void *)PICL_PROP_CONDITION, 1776*8574SJason.Beloro@Sun.COM sun4v_env_print_indicator_callback); 1777*8574SJason.Beloro@Sun.COM if (!class_node_found) 1778*8574SJason.Beloro@Sun.COM return; 1779*8574SJason.Beloro@Sun.COM log_printf("\nHumidity indicators:\n"); 1780*8574SJason.Beloro@Sun.COM if (syserrlog == 0) { 1781*8574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 1782*8574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_INDICATOR, (void *)PICL_PROP_CONDITION, 1783*8574SJason.Beloro@Sun.COM sun4v_env_print_indicator_callback); 1784*8574SJason.Beloro@Sun.COM if (all_status_ok) { 1785*8574SJason.Beloro@Sun.COM log_printf("All humidity indicators are OK.\n"); 1786*8574SJason.Beloro@Sun.COM return; 1787*8574SJason.Beloro@Sun.COM } 1788*8574SJason.Beloro@Sun.COM } 1789*8574SJason.Beloro@Sun.COM log_printf("-------------------------------------------------" 1790*8574SJason.Beloro@Sun.COM "-----------\n"); 1791*8574SJason.Beloro@Sun.COM log_printf(fmt, "Location", "Indicator", "Condition", 0); 1792*8574SJason.Beloro@Sun.COM log_printf("-------------------------------------------------" 1793*8574SJason.Beloro@Sun.COM "-----------\n"); 1794*8574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 1795*8574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_INDICATOR, 1796*8574SJason.Beloro@Sun.COM (void *)PICL_PROP_CONDITION, 1797*8574SJason.Beloro@Sun.COM sun4v_env_print_indicator_callback); 1798*8574SJason.Beloro@Sun.COM } 1799*8574SJason.Beloro@Sun.COM 1800*8574SJason.Beloro@Sun.COM static void 18013941Svenki sun4v_env_print_LEDs() 18023941Svenki { 18035028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 18043941Svenki if (syserrlog == 0) 18053941Svenki return; 18063941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 18074669Sfw157321 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 18083941Svenki if (!class_node_found) 18093941Svenki return; 18103941Svenki log_printf("\nLEDs:\n"); 18115028Sfw157321 log_printf("-------------------------------------------------" 18125028Sfw157321 "-----------\n"); 18133941Svenki log_printf(fmt, "Location", "LED", "State", 0); 18145028Sfw157321 log_printf("-------------------------------------------------" 18155028Sfw157321 "-----------\n"); 18163941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 18174669Sfw157321 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 18183941Svenki } 18193941Svenki 18203941Svenki /*ARGSUSED*/ 18213941Svenki static int 18223941Svenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args) 18233941Svenki { 18243941Svenki char label[PICL_PROPNAMELEN_MAX]; 18253941Svenki char status[PICL_PROPNAMELEN_MAX]; 18263941Svenki picl_errno_t err; 18273941Svenki picl_prophdl_t proph; 18283941Svenki picl_nodehdl_t parenth; 18293941Svenki char *names[PARENT_NAMES]; 18303941Svenki char *loc; 18313941Svenki int i; 18323941Svenki 18333941Svenki if (!class_node_found) { 18343941Svenki class_node_found = 1; 18353941Svenki return (PICL_WALK_TERMINATE); 18363941Svenki } 18373941Svenki err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph); 18383941Svenki if (err != PICL_SUCCESS) 18393941Svenki return (PICL_WALK_CONTINUE); 18403941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 18414669Sfw157321 sizeof (label)); 18423941Svenki if (err != PICL_SUCCESS) 18433941Svenki return (PICL_WALK_CONTINUE); 18443941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS, 18454669Sfw157321 status, sizeof (status)); 18463941Svenki if (err != PICL_SUCCESS) 18473941Svenki return (PICL_WALK_CONTINUE); 18483941Svenki if (syserrlog == 0) { 18493941Svenki if (strcmp(status, "disabled") == 0) { 18503941Svenki if (all_status_ok) { 18513941Svenki all_status_ok = 0; 18523941Svenki return (PICL_WALK_TERMINATE); 18533941Svenki } 18543941Svenki } else 18553941Svenki return (PICL_WALK_CONTINUE); 18563941Svenki } 18573941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 18584669Sfw157321 sizeof (parenth)); 18593941Svenki if (err != PICL_SUCCESS) { 18603941Svenki log_printf("\n"); 18613941Svenki return (PICL_WALK_CONTINUE); 18623941Svenki } 18633941Svenki if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL) 18643941Svenki return (PICL_WALK_TERMINATE); 18653941Svenki for (i = 0; i < PARENT_NAMES; i++) 18663941Svenki if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) { 18673941Svenki while (--i > -1) 18683941Svenki free(names[i]); 18693941Svenki free(loc); 18703941Svenki return (PICL_WALK_TERMINATE); 18713941Svenki } 18723941Svenki i = 0; 18733941Svenki while (err == PICL_SUCCESS) { 18744802Sfw157321 if (parenth == phyplatformh) 18753941Svenki break; 18763941Svenki err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 18774669Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 18783941Svenki if (err != PICL_SUCCESS) { 18793941Svenki i--; 18803941Svenki break; 18813941Svenki } 18823941Svenki if (i == PARENT_NAMES) 18833941Svenki break; 18843941Svenki err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT, 18854669Sfw157321 &parenth, sizeof (parenth)); 18863941Svenki } 18873941Svenki loc[0] = '\0'; 18884003Svivek if (--i > -1) { 18894003Svivek (void) strlcat(loc, names[i], 18904669Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 18914003Svivek } 18923941Svenki while (--i > -1) { 18934003Svivek (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES); 18944003Svivek (void) strlcat(loc, names[i], 18954669Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 18963941Svenki } 18975028Sfw157321 log_printf("%-35s", loc); 18983941Svenki for (i = 0; i < PARENT_NAMES; i++) 18993941Svenki free(names[i]); 19003941Svenki free(loc); 19013941Svenki log_printf("%-10s", label); 19023941Svenki log_printf("%-9s", status); 19033941Svenki log_printf("\n"); 19043941Svenki return (PICL_WALK_CONTINUE); 19053941Svenki } 19063941Svenki 19073941Svenki static void 19083941Svenki sun4v_print_fru_status() 19093941Svenki { 19105028Sfw157321 char *fmt = "%-34s %-9s %-8s\n"; 19115436Sfw157321 19123941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 19134669Sfw157321 sun4v_print_fru_status_callback); 19143941Svenki if (!class_node_found) 19153941Svenki return; 19165436Sfw157321 19173941Svenki log_printf("\n"); 19183941Svenki log_printf("============================"); 19193941Svenki log_printf(" FRU Status "); 19203941Svenki log_printf("============================"); 19213941Svenki log_printf("\n"); 19223941Svenki 19233941Svenki if (syserrlog == 0) { 19243941Svenki (void) picl_walk_tree_by_class(phyplatformh, 19254802Sfw157321 NULL, NULL, 19264669Sfw157321 sun4v_print_fru_status_callback); 19273941Svenki if (all_status_ok) { 19283941Svenki log_printf("All FRUs are enabled.\n"); 19293941Svenki return; 19303941Svenki } 19313941Svenki } 19323941Svenki log_printf(fmt, "Location", "Name", "Status", 0); 19335028Sfw157321 log_printf("------------------------------------------------------\n"); 19344802Sfw157321 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 19354669Sfw157321 sun4v_print_fru_status_callback); 19363941Svenki } 19373941Svenki 19383941Svenki /*ARGSUSED*/ 19393941Svenki static int 19403941Svenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args) 19413941Svenki { 19423941Svenki char rev[PICL_PROPNAMELEN_MAX]; 19433941Svenki picl_errno_t err; 19443941Svenki 19453941Svenki if (!class_node_found) { 19463941Svenki class_node_found = 1; 19473941Svenki return (PICL_WALK_TERMINATE); 19483941Svenki } 19495436Sfw157321 19503941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev, 19514669Sfw157321 sizeof (rev)); 19523941Svenki if (err != PICL_SUCCESS) 19533941Svenki return (PICL_WALK_CONTINUE); 19543941Svenki if (strlen(rev) == 0) 19553941Svenki return (PICL_WALK_CONTINUE); 19565436Sfw157321 log_printf("%s", rev); 19573941Svenki log_printf("\n"); 19583941Svenki return (PICL_WALK_CONTINUE); 19593941Svenki } 19603941Svenki 19613941Svenki static void 19623941Svenki sun4v_print_fw_rev() 19633941Svenki { 19643941Svenki if (syserrlog == 0) 19653941Svenki return; 19665436Sfw157321 19673941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 19684669Sfw157321 sun4v_print_fw_rev_callback); 19693941Svenki if (!class_node_found) 19703941Svenki return; 19715436Sfw157321 19723941Svenki log_printf("\n"); 19733941Svenki log_printf("============================"); 19743941Svenki log_printf(" FW Version "); 19753941Svenki log_printf("============================"); 19763941Svenki log_printf("\n"); 19775436Sfw157321 log_printf("Version\n"); 19785028Sfw157321 log_printf("-------------------------------------------------" 19795028Sfw157321 "-----------\n"); 19803941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 19814669Sfw157321 sun4v_print_fw_rev_callback); 19823941Svenki } 19833941Svenki 19843941Svenki static void 19855436Sfw157321 sun4v_print_openprom_rev() 19865436Sfw157321 { 19875436Sfw157321 if (syserrlog == 0) 19885436Sfw157321 return; 19895436Sfw157321 19905436Sfw157321 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 19915436Sfw157321 openprom_callback); 19925436Sfw157321 if (!class_node_found) 19935436Sfw157321 return; 19945436Sfw157321 19955436Sfw157321 log_printf("\n"); 19965436Sfw157321 log_printf("======================"); 19975436Sfw157321 log_printf(" System PROM revisions "); 19985436Sfw157321 log_printf("======================="); 19995436Sfw157321 log_printf("\n"); 20005436Sfw157321 log_printf("Version\n"); 20015436Sfw157321 log_printf("-------------------------------------------------" 20025436Sfw157321 "-----------\n"); 20035436Sfw157321 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 20045436Sfw157321 openprom_callback); 20055436Sfw157321 } 20065436Sfw157321 20075436Sfw157321 /* 20085436Sfw157321 * display the OBP and POST prom revisions (if present) 20095436Sfw157321 */ 20105436Sfw157321 /* ARGSUSED */ 20115436Sfw157321 static int 20125436Sfw157321 openprom_callback(picl_nodehdl_t openpromh, void *arg) 20135436Sfw157321 { 20145436Sfw157321 picl_prophdl_t proph; 20155436Sfw157321 picl_prophdl_t tblh; 20165436Sfw157321 picl_prophdl_t rowproph; 20175436Sfw157321 picl_propinfo_t pinfo; 20185436Sfw157321 char *prom_version = NULL; 20195436Sfw157321 char *obp_version = NULL; 20205436Sfw157321 int err; 20215436Sfw157321 20225436Sfw157321 if (!class_node_found) { 20235436Sfw157321 class_node_found = 1; 20245436Sfw157321 return (PICL_WALK_TERMINATE); 20255436Sfw157321 } 20265436Sfw157321 20275436Sfw157321 err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION, 20285436Sfw157321 &pinfo, &proph); 20295436Sfw157321 if (err == PICL_PROPNOTFOUND) 20305436Sfw157321 return (PICL_WALK_TERMINATE); 20315436Sfw157321 else if (err != PICL_SUCCESS) 20325436Sfw157321 return (err); 20335436Sfw157321 20345436Sfw157321 /* 20355436Sfw157321 * If it's a table prop, the first element is OBP revision 20365436Sfw157321 * The second one is POST revision. 20375436Sfw157321 * If it's a charstring prop, the value will be only OBP revision 20385436Sfw157321 */ 20395436Sfw157321 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 20405436Sfw157321 prom_version = (char *)alloca(pinfo.size); 20415436Sfw157321 if (prom_version == NULL) 20425436Sfw157321 return (PICL_FAILURE); 20435436Sfw157321 err = picl_get_propval(proph, prom_version, pinfo.size); 20445436Sfw157321 if (err != PICL_SUCCESS) 20455436Sfw157321 return (err); 20465436Sfw157321 log_printf("%s\n", prom_version); 20475436Sfw157321 } 20485436Sfw157321 20495436Sfw157321 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */ 20505436Sfw157321 return (PICL_WALK_TERMINATE); 20515436Sfw157321 20525436Sfw157321 err = picl_get_propval(proph, &tblh, pinfo.size); 20535436Sfw157321 if (err != PICL_SUCCESS) 20545436Sfw157321 return (err); 20555436Sfw157321 20565436Sfw157321 err = picl_get_next_by_row(tblh, &rowproph); 20575436Sfw157321 if (err == PICL_SUCCESS) { 20585436Sfw157321 /* get first row */ 20595436Sfw157321 err = picl_get_propinfo(rowproph, &pinfo); 20605436Sfw157321 if (err != PICL_SUCCESS) 20615436Sfw157321 return (err); 20625436Sfw157321 20635436Sfw157321 prom_version = (char *)alloca(pinfo.size); 20645436Sfw157321 if (prom_version == NULL) 20655436Sfw157321 return (PICL_FAILURE); 20665436Sfw157321 20675436Sfw157321 err = picl_get_propval(rowproph, prom_version, pinfo.size); 20685436Sfw157321 if (err != PICL_SUCCESS) 20695436Sfw157321 return (err); 20705436Sfw157321 log_printf("%s\n", prom_version); 20715436Sfw157321 20725436Sfw157321 /* get second row */ 20735436Sfw157321 err = picl_get_next_by_col(rowproph, &rowproph); 20745436Sfw157321 if (err == PICL_SUCCESS) { 20755436Sfw157321 err = picl_get_propinfo(rowproph, &pinfo); 20765436Sfw157321 if (err != PICL_SUCCESS) 20775436Sfw157321 return (err); 20785436Sfw157321 20795436Sfw157321 obp_version = (char *)alloca(pinfo.size); 20805436Sfw157321 if (obp_version == NULL) 20815436Sfw157321 return (PICL_FAILURE); 20825436Sfw157321 err = picl_get_propval(rowproph, obp_version, 20835436Sfw157321 pinfo.size); 20845436Sfw157321 if (err != PICL_SUCCESS) 20855436Sfw157321 return (err); 20865436Sfw157321 log_printf("%s\n", obp_version); 20875436Sfw157321 } 20885436Sfw157321 } 20895436Sfw157321 20905436Sfw157321 return (PICL_WALK_TERMINATE); 20915436Sfw157321 } 20925436Sfw157321 20935436Sfw157321 static void 20943941Svenki sun4v_print_chassis_serial_no() 20953941Svenki { 20963941Svenki char val[PICL_PROPNAMELEN_MAX]; 20973941Svenki picl_errno_t err; 20983941Svenki if (syserrlog == 0 || chassish == 0) 20993941Svenki return; 21003941Svenki 21013941Svenki log_printf("\n"); 21026014Ssuha log_printf("Chassis Serial Number"); 21033941Svenki log_printf("\n"); 21043941Svenki log_printf("---------------------\n"); 21053941Svenki err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER, 21064669Sfw157321 val, sizeof (val)); 21073941Svenki if (err == PICL_SUCCESS) 21083941Svenki log_printf("%s", val); 21093941Svenki log_printf("\n"); 21103941Svenki } 2111