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 /* 228574SJason.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(); 1098574SJason.Beloro@Sun.COM static void sun4v_env_print_humidity_sensors(); 1108574SJason.Beloro@Sun.COM static void sun4v_env_print_humidity_indicators(); 1113941Svenki static void sun4v_env_print_LEDs(); 1123941Svenki static void sun4v_print_fru_status(); 113*10070SBirva.Shah@Sun.COM static int is_fru_absent(picl_nodehdl_t); 1143941Svenki static void sun4v_print_fw_rev(); 1153941Svenki static void sun4v_print_chassis_serial_no(); 1165436Sfw157321 static int openprom_callback(picl_nodehdl_t openpromh, void *arg); 1175436Sfw157321 static void sun4v_print_openprom_rev(); 1181708Sstevel 1191708Sstevel int 1203941Svenki sun4v_display(Sys_tree *tree, Prom_node *root, int log, 1213941Svenki picl_nodehdl_t plafh) 1221708Sstevel { 1231708Sstevel void *value; /* used for opaque PROM data */ 1241708Sstevel struct mem_total memory_total; /* Total memory in system */ 1251708Sstevel struct grp_info grps; /* Info on all groups in system */ 1263941Svenki char machine[MAXSTRLEN]; 1275547Smb158278 int exit_code = 0; 1283941Svenki 1293941Svenki if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1) 1303941Svenki return (1); 1313941Svenki if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0) 1323941Svenki return (1); 1331708Sstevel 1341708Sstevel sys_clk = -1; /* System clock freq. (in MHz) */ 1351708Sstevel 1361708Sstevel /* 1371708Sstevel * Now display the machine's configuration. We do this if we 1381708Sstevel * are not logging. 1391708Sstevel */ 1401708Sstevel if (!logging) { 1411708Sstevel struct utsname uts_buf; 1421708Sstevel 1431708Sstevel /* 1441708Sstevel * Display system banner 1451708Sstevel */ 1461708Sstevel (void) uname(&uts_buf); 1471708Sstevel 1483941Svenki log_printf(dgettext(TEXT_DOMAIN, "System Configuration: " 1494669Sfw157321 "Sun Microsystems %s %s\n"), uts_buf.machine, 1504669Sfw157321 get_prop_val(find_prop(root, "banner-name")), 0); 1511708Sstevel 1521708Sstevel /* display system clock frequency */ 1531708Sstevel value = get_prop_val(find_prop(root, "clock-frequency")); 1541708Sstevel if (value != NULL) { 1551708Sstevel sys_clk = ((*((int *)value)) + 500000) / 1000000; 1561708Sstevel log_printf(dgettext(TEXT_DOMAIN, "System clock " 1574669Sfw157321 "frequency: %d MHz\n"), sys_clk, 0); 1581708Sstevel } 1591708Sstevel 1601708Sstevel /* Display the Memory Size */ 1611708Sstevel display_memorysize(tree, NULL, &grps, &memory_total); 1621708Sstevel 1631708Sstevel /* Display the CPU devices */ 1641708Sstevel sun4v_display_cpu_devices(plafh); 1651708Sstevel 1661708Sstevel /* Display the Memory configuration */ 1673941Svenki class_node_found = 0; 1683941Svenki sun4v_display_memory_conf(plafh); 1691708Sstevel 1701708Sstevel /* Display all the IO cards. */ 1711708Sstevel (void) sun4v_display_pci(plafh); 1723941Svenki sun4v_display_diaginfo((log || (logging)), root, plafh); 1731708Sstevel 1743941Svenki if (picl_get_root(&rooth) != PICL_SUCCESS) 1753941Svenki return (1); 1765547Smb158278 1775547Smb158278 /* 1785547Smb158278 * The physical-platform node may be missing on systems with 1795547Smb158278 * older firmware so don't consider that an error. 1805547Smb158278 */ 1813941Svenki if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM, 1824669Sfw157321 &phyplatformh) != PICL_SUCCESS) 1835547Smb158278 return (0); 1843941Svenki 1853941Svenki if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME, 1864669Sfw157321 PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS, 1874669Sfw157321 strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS) 1883941Svenki return (1); 1893941Svenki 1903941Svenki syserrlog = log; 1915547Smb158278 exit_code = sun4v_disp_env_status(); 1923941Svenki } 1935547Smb158278 return (exit_code); 1943941Svenki } 1953941Svenki 1965819Sfw157321 /* 1975819Sfw157321 * The binding-name property encodes the bus type. 1985819Sfw157321 */ 1993941Svenki static void 2003941Svenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card) 2013941Svenki { 2025819Sfw157321 char val[PICL_PROPNAMELEN_MAX], *p, *q; 2035819Sfw157321 2045819Sfw157321 card->bus_type[0] = '\0'; 2053941Svenki 2065819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, val, 2075819Sfw157321 sizeof (val)) == PICL_SUCCESS) { 2085819Sfw157321 if (strstr(val, PICL_CLASS_PCIEX)) 2094003Svivek (void) strlcpy(card->bus_type, "PCIE", 2104669Sfw157321 sizeof (card->bus_type)); 2115819Sfw157321 else if (strstr(val, PICL_CLASS_PCI)) 2125819Sfw157321 (void) strlcpy(card->bus_type, "PCIX", 2135819Sfw157321 sizeof (card->bus_type)); 2145819Sfw157321 else { 2155819Sfw157321 /* 2165819Sfw157321 * Not perfect: process the binding-name until 2175819Sfw157321 * we encounter something that we don't think would 2185819Sfw157321 * be part of a bus type. This may get confused a bit 2195819Sfw157321 * if a device or vendor id is encoded right after 2205819Sfw157321 * the bus class since there's no delimiter. If the 2215819Sfw157321 * id number begins with a hex digit [abcdef] then 2225819Sfw157321 * this will become part of the bus type string 2235819Sfw157321 * reported by prtdiag. This is all an effort to 2245819Sfw157321 * print something potentially useful for bus types 2255819Sfw157321 * other than PCI/PCIe. 2265819Sfw157321 * 2275819Sfw157321 * We do this because this code will get called for 2285819Sfw157321 * non-PCI class devices like the xaui (class sun4v.) 2295819Sfw157321 */ 2305819Sfw157321 if (strstr(val, "SUNW,") != NULL) 2315819Sfw157321 p = strchr(val, ',') + 1; 2325819Sfw157321 else 2335819Sfw157321 p = val; 2345819Sfw157321 q = p; 2355819Sfw157321 while (*p != '\0') { 2365819Sfw157321 if (isdigit((char)*p) || ispunct((char)*p)) { 2375819Sfw157321 *p = '\0'; 2385819Sfw157321 break; 2395819Sfw157321 } 2405819Sfw157321 *p = (char)_toupper((int)*p); 2415819Sfw157321 ++p; 2425819Sfw157321 } 2435819Sfw157321 (void) strlcpy(card->bus_type, q, 2445819Sfw157321 sizeof (card->bus_type)); 2455819Sfw157321 } 2463941Svenki } 2473941Svenki } 2483941Svenki 2495819Sfw157321 /* 2505819Sfw157321 * Fetch the Label property for this device. If none is found then 2515819Sfw157321 * search all the siblings with the same device ID for a 2525819Sfw157321 * Label and return that Label. The plug-in can only match the canonical 2535819Sfw157321 * path from the PRI with a specific devfs path. So we take care of 2545819Sfw157321 * devices with multiple functions here. A leaf device downstream of 2555819Sfw157321 * a bridge should fall out of here with PICL_PROPNOTFOUND, and the 2565819Sfw157321 * caller can walk back up the tree in search of the slot's Label. 2575819Sfw157321 */ 2583941Svenki static picl_errno_t 2593941Svenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card) 2603941Svenki { 2613941Svenki char val[PICL_PROPNAMELEN_MAX]; 2623941Svenki picl_errno_t err; 2635436Sfw157321 picl_nodehdl_t pnodeh; 2645819Sfw157321 uint32_t devid, sib_devid; 2655819Sfw157321 int32_t instance; 2663941Svenki 2675436Sfw157321 /* 2685819Sfw157321 * If there's a Label at this node then return it - we're 2695819Sfw157321 * done. 2705436Sfw157321 */ 2713941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 2724669Sfw157321 sizeof (val)); 2735819Sfw157321 if (err == PICL_SUCCESS) { 2745819Sfw157321 (void) strlcpy(card->slot_str, val, sizeof (card->slot_str)); 2755819Sfw157321 return (err); 2765819Sfw157321 } else if (err != PICL_PROPNOTFOUND) 2775819Sfw157321 return (err); 2785819Sfw157321 2795819Sfw157321 /* 2805819Sfw157321 * At this point we're starting to extrapolate what the Label 2815819Sfw157321 * should be since there is none at this specific node. 2825819Sfw157321 * Note that until the value of "err" is overwritten in the 2835819Sfw157321 * loop below, its value should be PICL_PROPNOTFOUND. 2845819Sfw157321 */ 2855819Sfw157321 2865819Sfw157321 /* 2875819Sfw157321 * The device must be attached, and we can figure that out if 2885819Sfw157321 * the instance number is present and is not equal to -1. 2895819Sfw157321 * This will prevent is from returning a Label for a sibling 2905819Sfw157321 * node when the node passed in would have a unique Label if the 2915819Sfw157321 * device were attached. But if the device is downstream of a 2925819Sfw157321 * node with a Label then pci_callback() will still find that 2935819Sfw157321 * and use it. 2945819Sfw157321 */ 2955819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_INSTANCE, &instance, 2965819Sfw157321 sizeof (instance)) != PICL_SUCCESS) 2975819Sfw157321 return (err); 2985819Sfw157321 if (instance == -1) 2995819Sfw157321 return (err); 3003941Svenki 3015819Sfw157321 /* 3025819Sfw157321 * Narrow the search to just the one device ID. 3035819Sfw157321 */ 3045819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_DEVICE_ID, &devid, 3055819Sfw157321 sizeof (devid)) != PICL_SUCCESS) 3065819Sfw157321 return (err); 3075819Sfw157321 3085819Sfw157321 /* 3095819Sfw157321 * Go find the first child of the parent so we can search 3105819Sfw157321 * all of the siblings. 3115819Sfw157321 */ 3125819Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh, 3135819Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS) 3145819Sfw157321 return (err); 3155819Sfw157321 if (picl_get_propval_by_name(pnodeh, PICL_PROP_CHILD, &pnodeh, 3165819Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS) 3175819Sfw157321 return (err); 3185436Sfw157321 3195819Sfw157321 /* 3205819Sfw157321 * If the child's device ID matches, then fetch the Label and 3215819Sfw157321 * return it. The first child/device ID should have a Label 3225819Sfw157321 * associated with it. 3235819Sfw157321 */ 3245819Sfw157321 do { 3255819Sfw157321 if (picl_get_propval_by_name(pnodeh, PICL_PROP_DEVICE_ID, 3265819Sfw157321 &sib_devid, sizeof (sib_devid)) == PICL_SUCCESS) { 3275819Sfw157321 if (sib_devid == devid) { 3285819Sfw157321 if ((err = picl_get_propval_by_name(pnodeh, 3295819Sfw157321 PICL_PROP_LABEL, val, sizeof (val))) == 3305819Sfw157321 PICL_SUCCESS) { 3315819Sfw157321 (void) strlcpy(card->slot_str, val, 3325819Sfw157321 sizeof (card->slot_str)); 3335819Sfw157321 break; 3345819Sfw157321 } 3355819Sfw157321 } 3365819Sfw157321 } 3375819Sfw157321 } while (picl_get_propval_by_name(pnodeh, PICL_PROP_PEER, &pnodeh, 3385819Sfw157321 sizeof (pnodeh)) == PICL_SUCCESS); 3395819Sfw157321 3405436Sfw157321 return (err); 3413941Svenki } 3423941Svenki 3433941Svenki static void 3443941Svenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card) 3453941Svenki { 3463941Svenki picl_errno_t err; 3473941Svenki picl_prophdl_t proph; 3483941Svenki picl_propinfo_t pinfo; 3493941Svenki picl_nodehdl_t pnodeh; 3503941Svenki uint8_t *pval; 3513941Svenki uint32_t dev_mask; 3523941Svenki char uaddr[MAXSTRLEN]; 3533941Svenki int i; 3543941Svenki 3553941Svenki err = PICL_SUCCESS; 3563941Svenki while (err == PICL_SUCCESS) { 3573941Svenki if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh, 3584669Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS) { 3594669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 3604669Sfw157321 sizeof (card->slot_str)); 3613941Svenki card->slot = -1; 3623941Svenki return; 3633941Svenki } 3643941Svenki if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES, 3654669Sfw157321 &pinfo, &proph) == PICL_SUCCESS) { 3663941Svenki break; 3673941Svenki } 3683941Svenki nodeh = pnodeh; 3693941Svenki } 3703941Svenki if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr, 3714669Sfw157321 sizeof (uaddr)) != PICL_SUCCESS) { 3724669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 3734669Sfw157321 sizeof (card->slot_str)); 3743941Svenki card->slot = -1; 3753941Svenki return; 3763941Svenki } 3773941Svenki pval = (uint8_t *)malloc(pinfo.size); 3783941Svenki if (!pval) { 3794669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 3804669Sfw157321 sizeof (card->slot_str)); 3813941Svenki card->slot = -1; 3823941Svenki return; 3833941Svenki } 3843941Svenki if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) { 3854669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 3864669Sfw157321 sizeof (card->slot_str)); 3873941Svenki card->slot = -1; 3883941Svenki free(pval); 3893941Svenki return; 3901708Sstevel } 3911708Sstevel 3923941Svenki dev_mask = 0; 3933941Svenki for (i = 0; i < sizeof (dev_mask); i++) 3943941Svenki dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i)); 3953941Svenki for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) { 3963941Svenki if (uaddr[i] == ',') { 3973941Svenki uaddr[i] = '\0'; 3983941Svenki break; 3993941Svenki } 4003941Svenki } 4013941Svenki card->slot = atol(uaddr); 4023941Svenki if (((1 << card->slot) & dev_mask) == 0) { 4034669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 4044669Sfw157321 sizeof (card->slot_str)); 4053941Svenki card->slot = -1; 4063941Svenki } else { 4073941Svenki char *p = (char *)(pval+sizeof (dev_mask)); 4083941Svenki int shift = sizeof (uint32_t)*8-1-card->slot; 4093941Svenki uint32_t x = (dev_mask << shift) >> shift; 4103941Svenki int count = 0; /* count # of 1's in x */ 4113941Svenki int i = 0; 4123941Svenki while (x != 0) { 4133941Svenki count++; 4143941Svenki x &= x-1; 4153941Svenki } 4163941Svenki while (count > 1) { 4174669Sfw157321 while (p[i++] != '\0') 4184669Sfw157321 ; 4193941Svenki count--; 4203941Svenki } 4214003Svivek (void) strlcpy(card->slot_str, (char *)(p+i), 4224669Sfw157321 sizeof (card->slot_str)); 4233941Svenki } 4243941Svenki free(pval); 4253941Svenki } 4263941Svenki 4273941Svenki /* 4283941Svenki * add all io devices under pci in io list 4293941Svenki */ 4303941Svenki /* ARGSUSED */ 4313941Svenki static int 4323941Svenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args) 4333941Svenki { 4343941Svenki char path[PICL_PROPNAMELEN_MAX]; 4353941Svenki char class[PICL_CLASSNAMELEN_MAX]; 4363941Svenki char name[PICL_PROPNAMELEN_MAX]; 4373941Svenki char model[PICL_PROPNAMELEN_MAX]; 4383941Svenki char binding_name[PICL_PROPNAMELEN_MAX]; 4393941Svenki char val[PICL_PROPNAMELEN_MAX]; 4403941Svenki char *compatible; 4413941Svenki picl_errno_t err; 4425819Sfw157321 picl_nodehdl_t nodeh, pnodeh; 4433941Svenki struct io_card pci_card; 4443941Svenki 4453941Svenki /* Walk through the children */ 4463941Svenki 4473941Svenki err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 4484669Sfw157321 sizeof (picl_nodehdl_t)); 4493941Svenki 4503941Svenki while (err == PICL_SUCCESS) { 4513941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 4524669Sfw157321 class, sizeof (class)); 4533941Svenki if (err != PICL_SUCCESS) 4543941Svenki return (err); 4553941Svenki 4563941Svenki if (args) { 4573941Svenki char *val = args; 4583941Svenki if (strcmp(class, val) == 0) { 4593941Svenki err = picl_get_propval_by_name(nodeh, 4604669Sfw157321 PICL_PROP_PEER, &nodeh, 4614669Sfw157321 sizeof (picl_nodehdl_t)); 4623941Svenki continue; 4633941Svenki } else if (strcmp(val, PICL_CLASS_PCIEX) == 0 && 4644669Sfw157321 strcmp(class, PICL_CLASS_PCI) == 0) { 4653941Svenki err = picl_get_propval_by_name(nodeh, 4664669Sfw157321 PICL_PROP_PEER, &nodeh, 4674669Sfw157321 sizeof (picl_nodehdl_t)); 4683941Svenki continue; 4693941Svenki } else if (strcmp(val, PICL_CLASS_PCI) == 0 && 4704669Sfw157321 strcmp(class, PICL_CLASS_PCIEX) == 0) { 4713941Svenki err = picl_get_propval_by_name(nodeh, 4724669Sfw157321 PICL_PROP_PEER, &nodeh, 4734669Sfw157321 sizeof (picl_nodehdl_t)); 4743941Svenki continue; 4753941Svenki } 4763941Svenki } 4773941Svenki 4783941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH, 4794669Sfw157321 path, sizeof (path)); 4803941Svenki if (err != PICL_SUCCESS) 4813941Svenki return (err); 4823941Svenki 4833941Svenki (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes)); 4843941Svenki 4855819Sfw157321 pnodeh = nodeh; 4865819Sfw157321 err = get_slot_label(nodeh, &pci_card); 4875819Sfw157321 4885819Sfw157321 /* 4895819Sfw157321 * No Label at this node, maybe we're looking at a device 4905819Sfw157321 * downstream of a bridge. Walk back up and find a Label and 4915819Sfw157321 * record that node in "pnodeh". 4925819Sfw157321 */ 4935819Sfw157321 while (err != PICL_SUCCESS) { 4945819Sfw157321 if (err != PICL_PROPNOTFOUND) 4955819Sfw157321 break; 4965819Sfw157321 else if (picl_get_propval_by_name(pnodeh, 4975819Sfw157321 PICL_PROP_PARENT, &pnodeh, sizeof (pnodeh)) == 4985819Sfw157321 PICL_SUCCESS) 4995819Sfw157321 err = get_slot_label(pnodeh, &pci_card); 5005819Sfw157321 else 5015819Sfw157321 break; 5025819Sfw157321 } 5035819Sfw157321 5045819Sfw157321 /* 5055819Sfw157321 * Can't find a Label for this device in the PCI heirarchy. 5065819Sfw157321 * Try to synthesize a slot name from atoms. This depends 5075819Sfw157321 * on the OBP slot_names property being implemented, and this 5085819Sfw157321 * so far doesn't seem to be on sun4v. But just in case that 5095819Sfw157321 * is resurrected, the code is here. 5105819Sfw157321 */ 5115819Sfw157321 if (err != PICL_SUCCESS) { 5125819Sfw157321 pnodeh = nodeh; 5135819Sfw157321 get_slot_number(nodeh, &pci_card); 5145819Sfw157321 } 5155819Sfw157321 5165819Sfw157321 /* 5175819Sfw157321 * Passing in pnodeh instead of nodeh will cause prtdiag 5185819Sfw157321 * to display the type of IO slot for the leaf node. For 5195819Sfw157321 * built-in devices and a lot of IO cards these will be 5205819Sfw157321 * the same thing. But for IO cards with bridge chips or 5215819Sfw157321 * for things like expansion chassis, prtdiag will report 5225819Sfw157321 * the bus type of the IO slot and not the leaf, which 5235819Sfw157321 * could be different things. 5245819Sfw157321 */ 5255819Sfw157321 get_bus_type(pnodeh, &pci_card); 5263941Svenki 5273941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name, 5284669Sfw157321 sizeof (name)); 5293941Svenki if (err == PICL_PROPNOTFOUND) 5304003Svivek (void) strlcpy(name, "", sizeof (name)); 5313941Svenki else if (err != PICL_SUCCESS) 5323941Svenki return (err); 5333941Svenki 5343941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val, 5354669Sfw157321 sizeof (val)); 5363941Svenki if (err == PICL_PROPNOTFOUND) 5374003Svivek (void) strlcpy(val, "", sizeof (val)); 5383941Svenki else if (err != PICL_SUCCESS) 5393941Svenki return (err); 5403941Svenki 5415436Sfw157321 (void) snprintf(pci_card.status, sizeof (pci_card.status), 5425436Sfw157321 "%s", pci_card.slot_str); 5433941Svenki 5443941Svenki /* 5453941Svenki * Get the name of this card. If binding_name is found, 5463941Svenki * name will be <nodename>-<binding_name>. 5473941Svenki */ 5483941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, 5494669Sfw157321 binding_name, sizeof (binding_name)); 5503941Svenki if (err == PICL_SUCCESS) { 5513941Svenki if (strcmp(name, binding_name) != 0) { 5523941Svenki (void) strlcat(name, "-", sizeof (name)); 5533941Svenki (void) strlcat(name, binding_name, 5544669Sfw157321 sizeof (name)); 5553941Svenki } 5563941Svenki } else if (err == PICL_PROPNOTFOUND) { 5573941Svenki /* 5583941Svenki * if compatible prop is not found, name will be 5593941Svenki * <nodename>-<compatible> 5603941Svenki */ 5613941Svenki err = sun4v_get_first_compatible_value(nodeh, 5624669Sfw157321 &compatible); 5633941Svenki if (err == PICL_SUCCESS) { 5643941Svenki (void) strlcat(name, "-", sizeof (name)); 5654003Svivek (void) strlcat(name, compatible, 5664669Sfw157321 sizeof (name)); 5673941Svenki free(compatible); 5683941Svenki } 5693941Svenki } else 5703941Svenki return (err); 5713941Svenki 5723941Svenki (void) strlcpy(pci_card.name, name, sizeof (pci_card.name)); 5733941Svenki 5743941Svenki /* Get the model of this card */ 5753941Svenki 5763941Svenki err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL, 5774669Sfw157321 model, sizeof (model)); 5783941Svenki if (err == PICL_PROPNOTFOUND) 5794003Svivek (void) strlcpy(model, "", sizeof (model)); 5803941Svenki else if (err != PICL_SUCCESS) 5813941Svenki return (err); 5823941Svenki (void) strlcpy(pci_card.model, model, sizeof (pci_card.model)); 5833941Svenki 5843941Svenki /* Print NAC name */ 5854802Sfw157321 log_printf("%-18s", pci_card.status); 5863941Svenki /* Print IO Type */ 5873941Svenki log_printf("%-6s", pci_card.bus_type); 5883941Svenki /* Printf Card Name */ 5895544Sfw157321 log_printf("%-34s", pci_card.name); 5903941Svenki /* Print Card Model */ 5913941Svenki log_printf("%-8s", pci_card.model); 5923941Svenki log_printf("\n"); 5933941Svenki /* Print Status */ 5944802Sfw157321 log_printf("%-18s", val); 5953941Svenki /* Print IO Type */ 5963941Svenki log_printf("%-6s", ""); 5973941Svenki /* Print Parent Path */ 5984802Sfw157321 log_printf("%-44s", pci_card.notes); 5993941Svenki log_printf("\n"); 6003941Svenki 6013941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 6024669Sfw157321 sizeof (picl_nodehdl_t)); 6033941Svenki } 6043941Svenki return (PICL_WALK_CONTINUE); 6051708Sstevel } 6061708Sstevel 6071708Sstevel /* 6081708Sstevel * display_pci 6091708Sstevel * Display all the PCI IO cards on this board. 6101708Sstevel */ 6111708Sstevel void 6121708Sstevel sun4v_display_pci(picl_nodehdl_t plafh) 6131708Sstevel { 6145544Sfw157321 char *fmt = "%-17s %-5s %-33s %-8s"; 6153941Svenki /* Have we printed the column headings? */ 6163941Svenki static int banner = FALSE; 6173941Svenki 6183941Svenki if (banner == FALSE) { 6193941Svenki log_printf("\n"); 6204802Sfw157321 log_printf("================================"); 6213941Svenki log_printf(" IO Devices "); 6224802Sfw157321 log_printf("================================"); 6233941Svenki log_printf("\n"); 6243941Svenki log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0); 6253941Svenki log_printf("\n"); 6263941Svenki log_printf(fmt, "Status", "Type", "Path", "", 0); 6273941Svenki log_printf("\n"); 6283941Svenki log_printf("---------------------------------" 6294802Sfw157321 "-------------------------------------------\n"); 6303941Svenki banner = TRUE; 6313941Svenki } 6323941Svenki 6333941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, 6344669Sfw157321 PICL_CLASS_PCIEX, sun4v_pci_callback); 6353941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI, 6364669Sfw157321 PICL_CLASS_PCI, sun4v_pci_callback); 6373941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V, 6384669Sfw157321 PICL_CLASS_SUN4V, sun4v_pci_callback); 6393941Svenki } 6403941Svenki 6413941Svenki /* 6423941Svenki * return the first compatible value 6433941Svenki */ 6443941Svenki static int 6453941Svenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf) 6463941Svenki { 6473941Svenki picl_errno_t err; 6483941Svenki picl_prophdl_t proph; 6493941Svenki picl_propinfo_t pinfo; 6503941Svenki picl_prophdl_t tblh; 6513941Svenki picl_prophdl_t rowproph; 6523941Svenki char *pval; 6533941Svenki 6543941Svenki err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE, 6554669Sfw157321 &pinfo, &proph); 6563941Svenki if (err != PICL_SUCCESS) 6573941Svenki return (err); 6583941Svenki 6593941Svenki if (pinfo.type == PICL_PTYPE_CHARSTRING) { 6603941Svenki pval = malloc(pinfo.size); 6613941Svenki if (pval == NULL) 6623941Svenki return (PICL_FAILURE); 6633941Svenki err = picl_get_propval(proph, pval, pinfo.size); 6643941Svenki if (err != PICL_SUCCESS) { 6653941Svenki free(pval); 6663941Svenki return (err); 6673941Svenki } 6683941Svenki *outbuf = pval; 6693941Svenki return (PICL_SUCCESS); 6703941Svenki } 6713941Svenki 6723941Svenki if (pinfo.type != PICL_PTYPE_TABLE) 6733941Svenki return (PICL_FAILURE); 6743941Svenki 6753941Svenki /* get first string from table */ 6763941Svenki err = picl_get_propval(proph, &tblh, pinfo.size); 6773941Svenki if (err != PICL_SUCCESS) 6783941Svenki return (err); 6793941Svenki 6803941Svenki err = picl_get_next_by_row(tblh, &rowproph); 6813941Svenki if (err != PICL_SUCCESS) 6823941Svenki return (err); 6833941Svenki 6843941Svenki err = picl_get_propinfo(rowproph, &pinfo); 6853941Svenki if (err != PICL_SUCCESS) 6863941Svenki return (err); 6873941Svenki 6883941Svenki pval = malloc(pinfo.size); 6893941Svenki if (pval == NULL) 6903941Svenki return (PICL_FAILURE); 6913941Svenki 6923941Svenki err = picl_get_propval(rowproph, pval, pinfo.size); 6933941Svenki if (err != PICL_SUCCESS) { 6943941Svenki free(pval); 6953941Svenki return (err); 6963941Svenki } 6973941Svenki 6983941Svenki *outbuf = pval; 6993941Svenki return (PICL_SUCCESS); 7001708Sstevel } 7011708Sstevel 7023941Svenki /* 7033941Svenki * print size of a memory segment 7043941Svenki */ 7053941Svenki static void 7063941Svenki print_memory_segment_size(uint64_t size) 7073941Svenki { 7083941Svenki uint64_t kbyte = 1024; 7093941Svenki uint64_t mbyte = kbyte * kbyte; 7103941Svenki uint64_t gbyte = kbyte * mbyte; 7115544Sfw157321 uint64_t tbyte = kbyte * gbyte; 7123941Svenki char buf[MEMORY_SIZE_FIELD]; 7133941Svenki 7145544Sfw157321 if (size >= tbyte) { 7155544Sfw157321 if (size % tbyte == 0) 7165544Sfw157321 (void) snprintf(buf, sizeof (buf), "%d TB", 7175544Sfw157321 (int)(size / tbyte)); 7185544Sfw157321 else 7195544Sfw157321 (void) snprintf(buf, sizeof (buf), "%.2f TB", 7205544Sfw157321 (float)size / tbyte); 7215544Sfw157321 } else if (size >= gbyte) { 7223941Svenki if (size % gbyte == 0) 7233941Svenki (void) snprintf(buf, sizeof (buf), "%d GB", 7244669Sfw157321 (int)(size / gbyte)); 7253941Svenki else 7263941Svenki (void) snprintf(buf, sizeof (buf), "%.2f GB", 7274669Sfw157321 (float)size / gbyte); 7283941Svenki } else if (size >= mbyte) { 7293941Svenki if (size % mbyte == 0) 7303941Svenki (void) snprintf(buf, sizeof (buf), "%d MB", 7314669Sfw157321 (int)(size / mbyte)); 7323941Svenki else 7333941Svenki (void) snprintf(buf, sizeof (buf), "%.2f MB", 7344669Sfw157321 (float)size / mbyte); 7353941Svenki } else { 7363941Svenki if (size % kbyte == 0) 7373941Svenki (void) snprintf(buf, sizeof (buf), "%d KB", 7384669Sfw157321 (int)(size / kbyte)); 7393941Svenki else 7403941Svenki (void) snprintf(buf, sizeof (buf), "%.2f KB", 7414669Sfw157321 (float)size / kbyte); 7423941Svenki } 7435544Sfw157321 log_printf("%-9s", buf); 7443941Svenki } 7453941Svenki 7463941Svenki /* 7474669Sfw157321 * Enumerate banks and dimms within a memory segment. We're handed 7484669Sfw157321 * the first bank within the segment - we assume there are dimms 7494669Sfw157321 * (memory-module) nodes underneath. 7503941Svenki */ 7513941Svenki static void 7524669Sfw157321 print_memory_segment_contain(picl_nodehdl_t bank_nodeh) 7531708Sstevel { 7543941Svenki char val[PICL_PROPNAMELEN_MAX]; 7554669Sfw157321 picl_nodehdl_t module_nodeh; 7564669Sfw157321 int flag = 0; 7575544Sfw157321 uint64_t size; 7584669Sfw157321 7594669Sfw157321 do { 7604669Sfw157321 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD, 7614669Sfw157321 &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS) 7624669Sfw157321 continue; 7635544Sfw157321 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_SIZE, 7645544Sfw157321 &size, sizeof (size)) == PICL_SUCCESS) { 7655544Sfw157321 if (!flag) { 7665544Sfw157321 print_memory_segment_size(size); 7675544Sfw157321 } else { 7685544Sfw157321 log_printf(" " 7695544Sfw157321 " "); 7705544Sfw157321 print_memory_segment_size(size); 7715544Sfw157321 flag = 0; 7725544Sfw157321 } 7735544Sfw157321 } 7744669Sfw157321 do { 7754669Sfw157321 if (picl_get_propval_by_name(module_nodeh, 7764669Sfw157321 PICL_PROP_NAC, val, sizeof (val)) != 7774669Sfw157321 PICL_SUCCESS) 7784669Sfw157321 continue; 7794669Sfw157321 else { 7804669Sfw157321 if (!flag) { 7815544Sfw157321 log_printf("%s\n", val); 7824669Sfw157321 flag = 1; 7835544Sfw157321 } else { 7845544Sfw157321 log_printf("%s%s\n", 7855544Sfw157321 " " 7865544Sfw157321 " ", 7875544Sfw157321 val); 7885544Sfw157321 } 7894669Sfw157321 } 7904669Sfw157321 } while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER, 7914669Sfw157321 &module_nodeh, sizeof (picl_nodehdl_t)) == 7924669Sfw157321 PICL_SUCCESS); 7934669Sfw157321 } while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER, 7944669Sfw157321 &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS); 7953941Svenki } 7963941Svenki 7973941Svenki /* 7983941Svenki * Search node where _class=="memory-segment" 7993941Svenki * print "Base Address", "Size", etc 8003941Svenki */ 8013941Svenki /*ARGSUSED*/ 8023941Svenki static int 8033941Svenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args) 8043941Svenki { 8053941Svenki uint64_t base; 8063941Svenki uint64_t size; 8073941Svenki uint64_t ifactor; 8083941Svenki picl_errno_t err = PICL_SUCCESS; 8093941Svenki 8103941Svenki if (class_node_found == 0) { 8113941Svenki class_node_found = 1; 8123941Svenki return (PICL_WALK_TERMINATE); 8133941Svenki } 8143941Svenki while (err == PICL_SUCCESS) { 8153941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS, 8164669Sfw157321 &base, sizeof (base)); 8173941Svenki if (err != PICL_SUCCESS) 8183941Svenki break; 8193941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE, 8204669Sfw157321 &size, sizeof (size)); 8213941Svenki if (err != PICL_SUCCESS) 8223941Svenki break; 8233941Svenki err = picl_get_propval_by_name(nodeh, 8244669Sfw157321 PICL_PROP_INTERLEAVE_FACTOR, &ifactor, 8254669Sfw157321 sizeof (ifactor)); 8263941Svenki if (err != PICL_SUCCESS) 8273941Svenki break; 8285544Sfw157321 log_printf("0x%-13llx", base); 8293941Svenki print_memory_segment_size(size); 8305544Sfw157321 log_printf("%-12lld", ifactor); 8314669Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, 8324669Sfw157321 &nodeh, sizeof (nodeh)); 8334669Sfw157321 if (err == PICL_SUCCESS) 8344669Sfw157321 print_memory_segment_contain(nodeh); 8353941Svenki log_printf("\n"); 8363941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 8374669Sfw157321 sizeof (picl_nodehdl_t)); 8383941Svenki } 8393941Svenki 8403941Svenki return (PICL_WALK_CONTINUE); 8413941Svenki } 8423941Svenki 8433941Svenki /*ARGSUSED*/ 8443941Svenki void 8453941Svenki sun4v_display_memory_conf(picl_nodehdl_t plafh) 8463941Svenki { 8475544Sfw157321 char *fmt = "%-14s %-8s %-11s %-8s %-s"; 8483941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 8494669Sfw157321 NULL, sun4v_memory_conf_callback); 8503941Svenki if (class_node_found == 0) 8513941Svenki return; 8523941Svenki log_printf("\n"); 8535544Sfw157321 log_printf("======================="); 8545544Sfw157321 log_printf(" Physical Memory Configuration "); 8555544Sfw157321 log_printf("========================"); 8563941Svenki log_printf("\n"); 8573941Svenki log_printf("Segment Table:\n"); 8584669Sfw157321 log_printf( 8595544Sfw157321 "--------------------------------------------------------------\n"); 8605544Sfw157321 log_printf(fmt, "Base", "Segment", "Interleave", "Bank", "Contains", 0); 8615544Sfw157321 log_printf("\n"); 8625544Sfw157321 log_printf(fmt, "Address", "Size", "Factor", "Size", "Modules", 0); 8633941Svenki log_printf("\n"); 8644669Sfw157321 log_printf( 8655544Sfw157321 "--------------------------------------------------------------\n"); 8663941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 8674669Sfw157321 NULL, sun4v_memory_conf_callback); 8681708Sstevel } 8691708Sstevel 8701708Sstevel void 8711708Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh) 8721708Sstevel { 8735544Sfw157321 char *fmt = "%-6s %-9s %-22s %-6s"; 8741708Sstevel 8751708Sstevel /* 8761708Sstevel * Display the table header for CPUs . Then display the CPU 8771708Sstevel * frequency, cache size, and processor revision of all cpus. 8781708Sstevel */ 8791708Sstevel log_printf(dgettext(TEXT_DOMAIN, 8804669Sfw157321 "\n" 8815544Sfw157321 "================================" 8825544Sfw157321 " Virtual CPUs " 8835544Sfw157321 "================================" 8844669Sfw157321 "\n" 8854669Sfw157321 "\n")); 8861708Sstevel log_printf("\n"); 8875544Sfw157321 log_printf(fmt, "CPU ID", "Frequency", "Implementation", 8885544Sfw157321 "Status", 0); 8891708Sstevel log_printf("\n"); 8905544Sfw157321 log_printf(fmt, "------", "---------", 8915544Sfw157321 "----------------------", "-------", 0); 8921708Sstevel log_printf("\n"); 8931708Sstevel 8945544Sfw157321 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU, 8955544Sfw157321 sun4v_display_cpus); 8961708Sstevel } 8971708Sstevel 8981708Sstevel /* 8991708Sstevel * Display the CPUs present on this board. 9001708Sstevel */ 9011708Sstevel /*ARGSUSED*/ 9021708Sstevel int 9031708Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args) 9041708Sstevel { 9051708Sstevel int status; 9063941Svenki picl_prophdl_t proph; 9073941Svenki picl_prophdl_t tblh; 9083941Svenki picl_prophdl_t rowproph; 9091708Sstevel picl_propinfo_t propinfo; 9103941Svenki int *int_value; 9115028Sfw157321 int cpuid; 9123941Svenki char *comp_value; 9133941Svenki char *no_prop_value = " "; 9143941Svenki char freq_str[MAXSTRLEN]; 9155028Sfw157321 char state[MAXSTRLEN]; 9161708Sstevel 9171708Sstevel /* 9181708Sstevel * Get cpuid property and print it and the NAC name 9191708Sstevel */ 9205544Sfw157321 status = picl_get_propinfo_by_name(cpuh, OBP_PROP_CPUID, &propinfo, 9215544Sfw157321 &proph); 9221708Sstevel if (status == PICL_SUCCESS) { 9231708Sstevel status = picl_get_propval(proph, &cpuid, sizeof (cpuid)); 9241708Sstevel if (status != PICL_SUCCESS) { 9255544Sfw157321 log_printf("%-7s", no_prop_value); 9261708Sstevel } else { 9275544Sfw157321 log_printf("%-7d", cpuid); 9281708Sstevel } 9291708Sstevel } else { 9305544Sfw157321 log_printf("%-7s", no_prop_value); 9311708Sstevel } 9321708Sstevel 9331708Sstevel clock_freq: 9341708Sstevel status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo, 9354669Sfw157321 &proph); 9361708Sstevel if (status == PICL_SUCCESS) { 9371708Sstevel int_value = malloc(propinfo.size); 9381708Sstevel if (int_value == NULL) { 9395544Sfw157321 log_printf("%-10s", no_prop_value); 9401708Sstevel goto compatible; 9411708Sstevel } 9421708Sstevel status = picl_get_propval(proph, int_value, propinfo.size); 9431708Sstevel if (status != PICL_SUCCESS) { 9445544Sfw157321 log_printf("%-10s", no_prop_value); 9451708Sstevel } else { 9461708Sstevel /* Running frequency */ 9471708Sstevel (void) snprintf(freq_str, sizeof (freq_str), "%d MHz", 9481708Sstevel CLK_FREQ_TO_MHZ(*int_value)); 9495544Sfw157321 log_printf("%-10s", freq_str); 9501708Sstevel } 9511708Sstevel free(int_value); 9521708Sstevel } else 9535544Sfw157321 log_printf("%-10s", no_prop_value); 9541708Sstevel 9551708Sstevel compatible: 9561708Sstevel status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo, 9574669Sfw157321 &proph); 9581708Sstevel if (status == PICL_SUCCESS) { 9591708Sstevel if (propinfo.type == PICL_PTYPE_CHARSTRING) { 9601708Sstevel /* 9611708Sstevel * Compatible Property only has 1 value 9621708Sstevel */ 9631708Sstevel comp_value = malloc(propinfo.size); 9641708Sstevel if (comp_value == NULL) { 9655544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9665028Sfw157321 goto state; 9671708Sstevel } 9681708Sstevel status = picl_get_propval(proph, comp_value, 9694669Sfw157321 propinfo.size); 9703941Svenki if (status != PICL_SUCCESS) 9715544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9723941Svenki else 9735544Sfw157321 log_printf("%-23s", comp_value, 0); 9743941Svenki free(comp_value); 9751708Sstevel } else if (propinfo.type == PICL_PTYPE_TABLE) { 9761708Sstevel /* 9771708Sstevel * Compatible Property has multiple values 9781708Sstevel */ 9791708Sstevel status = picl_get_propval(proph, &tblh, propinfo.size); 9801708Sstevel if (status != PICL_SUCCESS) { 9815544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9825028Sfw157321 goto state; 9831708Sstevel } 9841708Sstevel status = picl_get_next_by_row(tblh, &rowproph); 9851708Sstevel if (status != PICL_SUCCESS) { 9865544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9875028Sfw157321 goto state; 9881708Sstevel } 9891708Sstevel 9901708Sstevel status = picl_get_propinfo(rowproph, &propinfo); 9911708Sstevel if (status != PICL_SUCCESS) { 9925544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9935028Sfw157321 goto state; 9941708Sstevel } 9951708Sstevel 9961708Sstevel comp_value = malloc(propinfo.size); 9971708Sstevel if (comp_value == NULL) { 9985544Sfw157321 log_printf("%-23s", no_prop_value, 0); 9995028Sfw157321 goto state; 10001708Sstevel } 10011708Sstevel status = picl_get_propval(rowproph, comp_value, 10024669Sfw157321 propinfo.size); 10033941Svenki if (status != PICL_SUCCESS) 10045544Sfw157321 log_printf("%-23s", no_prop_value, 0); 10053941Svenki else 10065544Sfw157321 log_printf("%-23s", comp_value, 0); 10071708Sstevel free(comp_value); 10081708Sstevel } 10091708Sstevel } else 10105544Sfw157321 log_printf("%-23s", no_prop_value, 0); 10111708Sstevel 10125028Sfw157321 state: 10135028Sfw157321 status = picl_get_propinfo_by_name(cpuh, PICL_PROP_STATE, 10145028Sfw157321 &propinfo, &proph); 10151708Sstevel if (status == PICL_SUCCESS) { 10165028Sfw157321 status = picl_get_propval(proph, state, sizeof (state)); 10171708Sstevel if (status != PICL_SUCCESS) { 10183941Svenki log_printf("%-9s", no_prop_value); 10191708Sstevel } else { 10205028Sfw157321 log_printf("%-9s", state); 10211708Sstevel } 10221708Sstevel } else 10233941Svenki log_printf("%-9s", no_prop_value); 10241708Sstevel 10251708Sstevel done: 10261708Sstevel log_printf("\n"); 10271708Sstevel return (PICL_WALK_CONTINUE); 10281708Sstevel } 10291708Sstevel 10301708Sstevel void 10311708Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh) 10321708Sstevel { 10331708Sstevel #ifdef lint 10341708Sstevel flag = flag; 10351708Sstevel root = root; 10361708Sstevel plafh = plafh; 10371708Sstevel #endif 10381708Sstevel /* 10391708Sstevel * This function is intentionally empty 10401708Sstevel */ 10411708Sstevel } 10421708Sstevel 10431708Sstevel void 10441708Sstevel display_boardnum(int num) 10451708Sstevel { 10461708Sstevel log_printf("%2d ", num, 0); 10471708Sstevel } 10483941Svenki 10495547Smb158278 static int 10503941Svenki sun4v_disp_env_status() 10513941Svenki { 10525547Smb158278 int exit_code = 0; 10535547Smb158278 10543941Svenki if (phyplatformh == 0) 10555547Smb158278 return (0); 10563941Svenki log_printf("\n"); 10573941Svenki log_printf("============================"); 10583941Svenki log_printf(" Environmental Status "); 10593941Svenki log_printf("============================"); 10603941Svenki log_printf("\n"); 10613941Svenki 10623941Svenki class_node_found = 0; 10633941Svenki all_status_ok = 1; 10643941Svenki sun4v_env_print_fan_sensors(); 10655547Smb158278 exit_code |= (!all_status_ok); 10663941Svenki 10673941Svenki class_node_found = 0; 10683941Svenki all_status_ok = 1; 10693941Svenki sun4v_env_print_fan_indicators(); 10705547Smb158278 exit_code |= (!all_status_ok); 10713941Svenki 10723941Svenki class_node_found = 0; 10733941Svenki all_status_ok = 1; 10743941Svenki sun4v_env_print_temp_sensors(); 10755547Smb158278 exit_code |= (!all_status_ok); 10763941Svenki 10773941Svenki class_node_found = 0; 10783941Svenki all_status_ok = 1; 10793941Svenki sun4v_env_print_temp_indicators(); 10805547Smb158278 exit_code |= (!all_status_ok); 10813941Svenki 10823941Svenki class_node_found = 0; 10833941Svenki all_status_ok = 1; 10843941Svenki sun4v_env_print_current_sensors(); 10855547Smb158278 exit_code |= (!all_status_ok); 10863941Svenki 10873941Svenki class_node_found = 0; 10883941Svenki all_status_ok = 1; 10893941Svenki sun4v_env_print_current_indicators(); 10905547Smb158278 exit_code |= (!all_status_ok); 10913941Svenki 10923941Svenki class_node_found = 0; 10933941Svenki all_status_ok = 1; 10943941Svenki sun4v_env_print_voltage_sensors(); 10955547Smb158278 exit_code |= (!all_status_ok); 10963941Svenki 10973941Svenki class_node_found = 0; 10983941Svenki all_status_ok = 1; 10993941Svenki sun4v_env_print_voltage_indicators(); 11005547Smb158278 exit_code |= (!all_status_ok); 11013941Svenki 11023941Svenki class_node_found = 0; 11035547Smb158278 all_status_ok = 1; 11048574SJason.Beloro@Sun.COM sun4v_env_print_humidity_sensors(); 11058574SJason.Beloro@Sun.COM exit_code |= (!all_status_ok); 11068574SJason.Beloro@Sun.COM 11078574SJason.Beloro@Sun.COM class_node_found = 0; 11088574SJason.Beloro@Sun.COM all_status_ok = 1; 11098574SJason.Beloro@Sun.COM sun4v_env_print_humidity_indicators(); 11108574SJason.Beloro@Sun.COM exit_code |= (!all_status_ok); 11118574SJason.Beloro@Sun.COM 11128574SJason.Beloro@Sun.COM class_node_found = 0; 11138574SJason.Beloro@Sun.COM all_status_ok = 1; 11143941Svenki sun4v_env_print_LEDs(); 11155547Smb158278 exit_code |= (!all_status_ok); 11163941Svenki 11173941Svenki class_node_found = 0; 11183941Svenki all_status_ok = 1; 11193941Svenki sun4v_print_fru_status(); 11205547Smb158278 exit_code |= (!all_status_ok); 11213941Svenki 11223941Svenki class_node_found = 0; 11233941Svenki sun4v_print_fw_rev(); 11243941Svenki 11255436Sfw157321 class_node_found = 0; 11265436Sfw157321 sun4v_print_openprom_rev(); 11275436Sfw157321 11283941Svenki sun4v_print_chassis_serial_no(); 11295547Smb158278 11305547Smb158278 return (exit_code); 11313941Svenki } 11323941Svenki 11333941Svenki /*ARGSUSED*/ 11343941Svenki static int 11353941Svenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args) 11363941Svenki { 11373941Svenki char val[PICL_PROPNAMELEN_MAX]; 11383941Svenki picl_nodehdl_t parenth; 11393941Svenki char *names[PARENT_NAMES]; 11404802Sfw157321 char *base_units[PICL_PROPNAMELEN_MAX]; 11413941Svenki char *loc; 11423941Svenki int i; 11433941Svenki char *prop; 11443941Svenki picl_errno_t err; 11455436Sfw157321 int32_t lo_warning, lo_shutdown, lo_poweroff; 11465436Sfw157321 int32_t hi_warning, hi_shutdown, hi_poweroff; 11473941Svenki int32_t current_val; 11484802Sfw157321 int32_t exponent; 11494802Sfw157321 double display_val; 11504928Sfw157321 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 11514928Sfw157321 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 11524928Sfw157321 sensor_status_t sensor_status = SENSOR_OK; 11533941Svenki 11543941Svenki if (class_node_found == 0) { 11553941Svenki class_node_found = 1; 11563941Svenki return (PICL_WALK_TERMINATE); 11573941Svenki } 11583941Svenki 11594928Sfw157321 prop = (char *)args; 11604928Sfw157321 if (!prop) { 11614928Sfw157321 sensor_status = SENSOR_UNKNOWN; 11624928Sfw157321 all_status_ok = 0; 11634928Sfw157321 } else { 11643941Svenki err = picl_get_propval_by_name(nodeh, 11654669Sfw157321 PICL_PROP_OPERATIONAL_STATUS, val, 11664669Sfw157321 sizeof (val)); 11673941Svenki if (err == PICL_SUCCESS) { 11683941Svenki if (strcmp(val, "disabled") == 0) { 11694928Sfw157321 sensor_status = SENSOR_DISABLED; 11704928Sfw157321 } 11714928Sfw157321 } 11724928Sfw157321 } 11734928Sfw157321 11744928Sfw157321 if (sensor_status != SENSOR_DISABLED && 11754928Sfw157321 sensor_status != SENSOR_UNKNOWN) { 11764928Sfw157321 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 11774928Sfw157321 sizeof (current_val)) != PICL_SUCCESS) { 11784928Sfw157321 sensor_status = SENSOR_UNKNOWN; 11795436Sfw157321 } else { 11805436Sfw157321 if (picl_get_propval_by_name(nodeh, 11815436Sfw157321 PICL_PROP_LOW_WARNING, 11825436Sfw157321 &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS) 11835436Sfw157321 lo_warning = INVALID_THRESHOLD; 11845436Sfw157321 if (picl_get_propval_by_name(nodeh, 11855436Sfw157321 PICL_PROP_LOW_SHUTDOWN, 11865436Sfw157321 &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS) 11875436Sfw157321 lo_shutdown = INVALID_THRESHOLD; 11885436Sfw157321 if (picl_get_propval_by_name(nodeh, 11895436Sfw157321 PICL_PROP_LOW_POWER_OFF, 11905436Sfw157321 &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS) 11915436Sfw157321 lo_poweroff = INVALID_THRESHOLD; 11925436Sfw157321 if (picl_get_propval_by_name(nodeh, 11935436Sfw157321 PICL_PROP_HIGH_WARNING, 11945436Sfw157321 &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS) 11955436Sfw157321 hi_warning = INVALID_THRESHOLD; 11965436Sfw157321 if (picl_get_propval_by_name(nodeh, 11975436Sfw157321 PICL_PROP_HIGH_SHUTDOWN, 11985436Sfw157321 &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS) 11995436Sfw157321 hi_shutdown = INVALID_THRESHOLD; 12005436Sfw157321 if (picl_get_propval_by_name(nodeh, 12015436Sfw157321 PICL_PROP_HIGH_POWER_OFF, 12025436Sfw157321 &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS) 12035436Sfw157321 hi_poweroff = INVALID_THRESHOLD; 12044928Sfw157321 12055436Sfw157321 if ((lo_poweroff != INVALID_THRESHOLD && 12065436Sfw157321 current_val <= lo_poweroff) || 12075436Sfw157321 (hi_poweroff != INVALID_THRESHOLD && 12085436Sfw157321 current_val >= hi_poweroff)) { 12095436Sfw157321 sensor_status = SENSOR_FAILED; 12105436Sfw157321 } else if ((lo_shutdown != INVALID_THRESHOLD && 12115436Sfw157321 current_val <= lo_shutdown) || 12125436Sfw157321 (hi_shutdown != INVALID_THRESHOLD && 12135436Sfw157321 current_val >= hi_shutdown)) { 12145436Sfw157321 sensor_status = SENSOR_FAILED; 12155436Sfw157321 } else if ((lo_warning != INVALID_THRESHOLD && 12165436Sfw157321 current_val <= lo_warning) || 12175436Sfw157321 (hi_warning != INVALID_THRESHOLD && 12185436Sfw157321 current_val >= hi_warning)) { 12195436Sfw157321 sensor_status = SENSOR_WARN; 12205436Sfw157321 } else { 12215436Sfw157321 sensor_status = SENSOR_OK; 12225436Sfw157321 } 12234928Sfw157321 } 12244928Sfw157321 } 12254928Sfw157321 12264928Sfw157321 if (syserrlog == 0) { 12274928Sfw157321 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 12283941Svenki all_status_ok = 0; 12293941Svenki return (PICL_WALK_TERMINATE); 12303941Svenki } 12314928Sfw157321 if (sensor_status == SENSOR_OK) { 12324928Sfw157321 return (PICL_WALK_CONTINUE); 12334928Sfw157321 } 12343941Svenki } 12354928Sfw157321 12364928Sfw157321 /* 12374928Sfw157321 * If we're here then prtdiag was invoked with "-v" or we have 12384928Sfw157321 * a sensor that is beyond a threshold, so give them a book to 12394928Sfw157321 * read instead of the Cliff Notes. 12404928Sfw157321 */ 12413941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 12424669Sfw157321 sizeof (parenth)); 12433941Svenki if (err != PICL_SUCCESS) { 12443941Svenki log_printf("\n"); 12453941Svenki return (PICL_WALK_CONTINUE); 12463941Svenki } 12474003Svivek 12484928Sfw157321 /* gather up the path name for the sensor */ 12494928Sfw157321 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 12504928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) { 12514928Sfw157321 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 12524928Sfw157321 NULL) { 12534928Sfw157321 while (--i > -1) 12544928Sfw157321 free(names[i]); 12554928Sfw157321 free(loc); 12564928Sfw157321 loc = NULL; 12574928Sfw157321 } 12583941Svenki } 12594003Svivek } 12604928Sfw157321 i = 0; 12614928Sfw157321 if (loc != 0) { 12624928Sfw157321 while (err == PICL_SUCCESS) { 12634928Sfw157321 if (parenth == phyplatformh) 12644928Sfw157321 break; 12654928Sfw157321 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 12664928Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 12674928Sfw157321 if (err != PICL_SUCCESS) { 12684928Sfw157321 i--; 12694928Sfw157321 break; 12704928Sfw157321 } 12714928Sfw157321 if (i == PARENT_NAMES) 12724928Sfw157321 break; 12734928Sfw157321 err = picl_get_propval_by_name(parenth, 12744928Sfw157321 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 12754928Sfw157321 } 12764928Sfw157321 loc[0] = '\0'; 12774928Sfw157321 if (--i > -1) { 12784928Sfw157321 (void) strlcat(loc, names[i], 12794928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 12804928Sfw157321 } 12814928Sfw157321 while (--i > -1) { 12824928Sfw157321 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 12834928Sfw157321 PARENT_NAMES); 12844928Sfw157321 (void) strlcat(loc, names[i], 12854928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 12864928Sfw157321 } 12875028Sfw157321 log_printf("%-35s", loc); 12884928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) 12894928Sfw157321 free(names[i]); 12904928Sfw157321 free(loc); 12914928Sfw157321 } else { 12925028Sfw157321 log_printf("%-35s", " "); 12933941Svenki } 12943941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 12954669Sfw157321 sizeof (val)); 12963941Svenki if (err == PICL_SUCCESS) 12973941Svenki log_printf("%-15s", val); 12983941Svenki 12994928Sfw157321 /* 13004928Sfw157321 * Get the exponent if present, and do a little math so that 13014928Sfw157321 * if we need to we can print a normalized value for the 13024928Sfw157321 * sensor reading. 13034928Sfw157321 */ 13044802Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT, 13054802Sfw157321 &exponent, sizeof (exponent)) != PICL_SUCCESS) 13064802Sfw157321 exponent = 0; 13074802Sfw157321 if (exponent == 0) 13084802Sfw157321 display_val = (double)current_val; 13095436Sfw157321 else { 13104802Sfw157321 display_val = (double)current_val * 13114802Sfw157321 pow((double)10, (double)exponent); 13125436Sfw157321 13135436Sfw157321 /* 13145436Sfw157321 * Sometimes ILOM will scale a sensor reading but 13155436Sfw157321 * there will be nothing to the right of the decimal 13165436Sfw157321 * once that value is normalized. Setting the 13175436Sfw157321 * exponent to zero will prevent the printf below 13185436Sfw157321 * from printing extraneous zeros. Otherwise a 13195436Sfw157321 * negative exponent is used to set the precision 13205436Sfw157321 * for the printf. 13215436Sfw157321 */ 13225436Sfw157321 if ((int)display_val == display_val || exponent > 0) 13235436Sfw157321 exponent = 0; 13245436Sfw157321 } 13255436Sfw157321 13264928Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS, 13274928Sfw157321 base_units, sizeof (base_units)); 13284802Sfw157321 if (err != PICL_SUCCESS) 13294802Sfw157321 base_units[0] = '\0'; 13303941Svenki 13314928Sfw157321 switch (sensor_status) { 13324928Sfw157321 case SENSOR_FAILED: 13333941Svenki log_printf("%-s", "failed ("); 13344802Sfw157321 log_printf("%-.*f", abs(exponent), display_val); 13354802Sfw157321 log_printf("%-s %s", base_units, ")"); 13364928Sfw157321 break; 13374928Sfw157321 case SENSOR_WARN: 13383941Svenki log_printf("%-s", "warning ("); 13394802Sfw157321 log_printf("%-.*f", abs(exponent), display_val); 13404802Sfw157321 log_printf("%-s %s", base_units, ")"); 13414928Sfw157321 break; 13424928Sfw157321 case SENSOR_DISABLED: 13434928Sfw157321 log_printf("%-s", "disabled"); 13444928Sfw157321 break; 13454928Sfw157321 case SENSOR_OK: 13463941Svenki log_printf("%-s", "ok"); 13474928Sfw157321 break; 13484928Sfw157321 default: 13494928Sfw157321 log_printf("%-s", "unknown"); 13504928Sfw157321 break; 13514928Sfw157321 } 13523941Svenki 13533941Svenki log_printf("\n"); 13543941Svenki return (PICL_WALK_CONTINUE); 13553941Svenki } 13563941Svenki 13573941Svenki /*ARGSUSED*/ 13583941Svenki static int 13593941Svenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args) 13603941Svenki { 13614928Sfw157321 char current_val[PICL_PROPNAMELEN_MAX]; 13624928Sfw157321 char expected_val[PICL_PROPNAMELEN_MAX]; 13634928Sfw157321 char label[PICL_PROPNAMELEN_MAX]; 13643941Svenki picl_nodehdl_t parenth; 13653941Svenki char *names[PARENT_NAMES]; 13663941Svenki char *loc; 13673941Svenki int i = 0; 13683941Svenki char *prop = (char *)args; 13693941Svenki picl_errno_t err = PICL_SUCCESS; 13704928Sfw157321 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 13714928Sfw157321 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 13724928Sfw157321 sensor_status_t sensor_status = SENSOR_OK; 13733941Svenki 13743941Svenki if (class_node_found == 0) { 13753941Svenki class_node_found = 1; 13763941Svenki return (PICL_WALK_TERMINATE); 13773941Svenki } 13784928Sfw157321 13794928Sfw157321 prop = (char *)args; 13804928Sfw157321 if (!prop) { 13814928Sfw157321 sensor_status = SENSOR_UNKNOWN; 13824928Sfw157321 all_status_ok = 0; 13834928Sfw157321 } else { 13843941Svenki err = picl_get_propval_by_name(nodeh, 13854928Sfw157321 PICL_PROP_OPERATIONAL_STATUS, current_val, 13864928Sfw157321 sizeof (current_val)); 13873941Svenki if (err == PICL_SUCCESS) { 13884928Sfw157321 if (strcmp(current_val, "disabled") == 0) { 13894928Sfw157321 sensor_status = SENSOR_DISABLED; 13904928Sfw157321 } 13914928Sfw157321 } 13924928Sfw157321 } 13934928Sfw157321 13944928Sfw157321 if (sensor_status != SENSOR_DISABLED && 13954928Sfw157321 sensor_status != SENSOR_UNKNOWN) { 13964928Sfw157321 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 13974928Sfw157321 sizeof (current_val)) != PICL_SUCCESS) { 13984928Sfw157321 (void) strlcpy(current_val, "unknown", 13994928Sfw157321 sizeof (current_val)); 14004928Sfw157321 sensor_status = SENSOR_UNKNOWN; 14014928Sfw157321 } else { 14024928Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED, 14034928Sfw157321 &expected_val, sizeof (expected_val)) != 14044928Sfw157321 PICL_SUCCESS) { 14054928Sfw157321 sensor_status = SENSOR_UNKNOWN; 14064928Sfw157321 } else { 14074928Sfw157321 if (strncmp(current_val, expected_val, 14084928Sfw157321 sizeof (current_val)) == 0) { 14094928Sfw157321 sensor_status = SENSOR_OK; 14104928Sfw157321 } else { 14114928Sfw157321 sensor_status = SENSOR_FAILED; 14123941Svenki } 14134928Sfw157321 } 14144928Sfw157321 } 14154928Sfw157321 } 14164928Sfw157321 14174928Sfw157321 if (syserrlog == 0) { 14184928Sfw157321 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 14193941Svenki all_status_ok = 0; 14203941Svenki return (PICL_WALK_TERMINATE); 14213941Svenki } 14224928Sfw157321 if (sensor_status == SENSOR_OK) { 14234928Sfw157321 return (PICL_WALK_CONTINUE); 14244928Sfw157321 } 14253941Svenki } 14264928Sfw157321 14274928Sfw157321 /* 14284928Sfw157321 * If we're here then prtdiag was invoked with "-v" or we have 14294928Sfw157321 * a sensor that is beyond a threshold, so give them a book to 14304928Sfw157321 * read instead of the Cliff Notes. 14314928Sfw157321 */ 14323941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 14334669Sfw157321 sizeof (parenth)); 14343941Svenki if (err != PICL_SUCCESS) { 14353941Svenki log_printf("\n"); 14363941Svenki return (PICL_WALK_CONTINUE); 14373941Svenki } 14384928Sfw157321 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 14394928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) { 14404928Sfw157321 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 14414928Sfw157321 NULL) { 14424928Sfw157321 while (--i > -1) 14434928Sfw157321 free(names[i]); 14444928Sfw157321 free(loc); 14454928Sfw157321 loc = NULL; 14464928Sfw157321 } 14473941Svenki } 14483941Svenki } 14494928Sfw157321 i = 0; 14504928Sfw157321 if (loc) { 14514928Sfw157321 while (err == PICL_SUCCESS) { 14524928Sfw157321 if (parenth == phyplatformh) 14534928Sfw157321 break; 14544928Sfw157321 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 14554928Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 14564928Sfw157321 if (err != PICL_SUCCESS) { 14574928Sfw157321 i--; 14584928Sfw157321 break; 14594928Sfw157321 } 14604928Sfw157321 if (i == PARENT_NAMES) 14614928Sfw157321 break; 14624928Sfw157321 err = picl_get_propval_by_name(parenth, 14634928Sfw157321 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 14644928Sfw157321 } 14654928Sfw157321 loc[0] = '\0'; 14664928Sfw157321 if (--i > -1) { 14674928Sfw157321 (void) strlcat(loc, names[i], 14684928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 14694928Sfw157321 } 14704928Sfw157321 while (--i > -1) { 14714928Sfw157321 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 14724928Sfw157321 PARENT_NAMES); 14734928Sfw157321 (void) strlcat(loc, names[i], 14744928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 14754928Sfw157321 } 14765028Sfw157321 log_printf("%-35s", loc); 14774928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) 14784928Sfw157321 free(names[i]); 14794928Sfw157321 free(loc); 14804928Sfw157321 } else { 14815028Sfw157321 log_printf("%-35s", ""); 14823941Svenki } 14834928Sfw157321 14844928Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 14854928Sfw157321 sizeof (label)); 14864928Sfw157321 if (err != PICL_SUCCESS) 14874928Sfw157321 (void) strlcpy(label, "", sizeof (label)); 14884928Sfw157321 log_printf("%-15s", label); 14894928Sfw157321 14904928Sfw157321 log_printf("%-8s", current_val); 14914928Sfw157321 14923941Svenki log_printf("\n"); 14933941Svenki return (PICL_WALK_CONTINUE); 14943941Svenki } 14953941Svenki 14963941Svenki static void 14973941Svenki sun4v_env_print_fan_sensors() 14983941Svenki { 14995028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 15003941Svenki /* 15013941Svenki * If there isn't any fan sensor node, return now. 15023941Svenki */ 15033941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15044928Sfw157321 PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED, 15054669Sfw157321 sun4v_env_print_sensor_callback); 15063941Svenki if (!class_node_found) 15073941Svenki return; 15083941Svenki log_printf("Fan sensors:\n"); 15093941Svenki if (syserrlog == 0) { 15103941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15114669Sfw157321 PICL_CLASS_RPM_SENSOR, 15124928Sfw157321 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 15133941Svenki if (all_status_ok) { 15143941Svenki log_printf("All fan sensors are OK.\n"); 15153941Svenki return; 15163941Svenki } 15173941Svenki } 15185028Sfw157321 log_printf("-------------------------------------------------" 15195028Sfw157321 "-----------\n"); 15203941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 15215028Sfw157321 log_printf("-------------------------------------------------" 15225028Sfw157321 "-----------\n"); 15233941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR, 15244669Sfw157321 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 15253941Svenki } 15263941Svenki 15273941Svenki static void 15283941Svenki sun4v_env_print_fan_indicators() 15293941Svenki { 15305028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 15313941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15324928Sfw157321 PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION, 15334669Sfw157321 sun4v_env_print_indicator_callback); 15343941Svenki if (!class_node_found) 15353941Svenki return; 15363941Svenki log_printf("\nFan indicators:\n"); 15373941Svenki if (syserrlog == 0) { 15383941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15394669Sfw157321 PICL_CLASS_RPM_INDICATOR, 15404928Sfw157321 (void *)PICL_PROP_CONDITION, 15414928Sfw157321 sun4v_env_print_indicator_callback); 15423941Svenki if (all_status_ok) { 15433941Svenki log_printf("All fan indicators are OK.\n"); 15443941Svenki return; 15453941Svenki } 15463941Svenki } 15475028Sfw157321 log_printf("-------------------------------------------------" 15485028Sfw157321 "-----------\n"); 15493941Svenki log_printf(fmt, "Location", "Sensor", "Condition", 0); 15505028Sfw157321 log_printf("-------------------------------------------------" 15515028Sfw157321 "-----------\n"); 15523941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR, 15534802Sfw157321 (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback); 15543941Svenki } 15553941Svenki 15563941Svenki static void 15573941Svenki sun4v_env_print_temp_sensors() 15583941Svenki { 15595028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 15603941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15614669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 15624669Sfw157321 (void *)PICL_PROP_TEMPERATURE, 15634669Sfw157321 sun4v_env_print_sensor_callback); 15643941Svenki if (!class_node_found) 15653941Svenki return; 15663941Svenki 15673941Svenki log_printf("\nTemperature sensors:\n"); 15683941Svenki if (syserrlog == 0) { 15693941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15704669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 15714928Sfw157321 PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 15723941Svenki if (all_status_ok) { 15733941Svenki log_printf("All temperature sensors are OK.\n"); 15743941Svenki return; 15753941Svenki } 15763941Svenki } 15775028Sfw157321 log_printf("-------------------------------------------------" 15785028Sfw157321 "-----------\n"); 15793941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 15805028Sfw157321 log_printf("-------------------------------------------------" 15815028Sfw157321 "-----------\n"); 15823941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15834669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 15844669Sfw157321 (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 15853941Svenki } 15863941Svenki 15873941Svenki static void 15883941Svenki sun4v_env_print_temp_indicators() 15893941Svenki { 15905028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 15913941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15924669Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION, 15934669Sfw157321 sun4v_env_print_indicator_callback); 15943941Svenki if (!class_node_found) 15953941Svenki return; 15963941Svenki log_printf("\nTemperature indicators:\n"); 15973941Svenki if (syserrlog == 0) { 15983941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15994928Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, 16004928Sfw157321 (void *)PICL_PROP_CONDITION, 16014669Sfw157321 sun4v_env_print_indicator_callback); 16023941Svenki if (all_status_ok) { 16033941Svenki log_printf("All temperature indicators are OK.\n"); 16043941Svenki return; 16053941Svenki } 16063941Svenki } 16075028Sfw157321 log_printf("-------------------------------------------------" 16085028Sfw157321 "-----------\n"); 16093941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 16105028Sfw157321 log_printf("-------------------------------------------------" 16115028Sfw157321 "-----------\n"); 16123941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16134669Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, 16144669Sfw157321 (void *)PICL_PROP_CONDITION, 16154669Sfw157321 sun4v_env_print_indicator_callback); 16163941Svenki } 16173941Svenki 16183941Svenki static void 16193941Svenki sun4v_env_print_current_sensors() 16203941Svenki { 16215028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 16223941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR, 16234669Sfw157321 (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 16243941Svenki if (!class_node_found) 16253941Svenki return; 16263941Svenki log_printf("\nCurrent sensors:\n"); 16273941Svenki if (syserrlog == 0) { 16283941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16294669Sfw157321 PICL_CLASS_CURRENT_SENSOR, 16304928Sfw157321 PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 16313941Svenki if (all_status_ok) { 16323941Svenki log_printf("All current sensors are OK.\n"); 16333941Svenki return; 16343941Svenki } 16353941Svenki } 16365028Sfw157321 log_printf("-------------------------------------------------" 16375028Sfw157321 "-----------\n"); 16383941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 16395028Sfw157321 log_printf("-------------------------------------------------" 16405028Sfw157321 "-----------\n"); 16413941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16424669Sfw157321 PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT, 16434669Sfw157321 sun4v_env_print_sensor_callback); 16443941Svenki } 16453941Svenki 16463941Svenki static void 16473941Svenki sun4v_env_print_current_indicators() 16483941Svenki { 16495028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 16503941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16514669Sfw157321 PICL_CLASS_CURRENT_INDICATOR, 16524669Sfw157321 (void *)PICL_PROP_CONDITION, 16534669Sfw157321 sun4v_env_print_indicator_callback); 16543941Svenki if (!class_node_found) 16553941Svenki return; 16563941Svenki log_printf("\nCurrent indicators:\n"); 16573941Svenki if (syserrlog == 0) { 16583941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16594928Sfw157321 PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION, 16604669Sfw157321 sun4v_env_print_indicator_callback); 16613941Svenki if (all_status_ok) { 16623941Svenki log_printf("All current indicators are OK.\n"); 16633941Svenki return; 16643941Svenki } 16653941Svenki } 16665028Sfw157321 log_printf("-------------------------------------------------" 16675028Sfw157321 "-----------\n"); 16683941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 16695028Sfw157321 log_printf("-------------------------------------------------" 16705028Sfw157321 "-----------\n"); 16713941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16724669Sfw157321 PICL_CLASS_CURRENT_INDICATOR, 16734669Sfw157321 (void *)PICL_PROP_CONDITION, 16744669Sfw157321 sun4v_env_print_indicator_callback); 16753941Svenki } 16763941Svenki 16773941Svenki static void 16783941Svenki sun4v_env_print_voltage_sensors() 16793941Svenki { 16805028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 16813941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16824669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 16834669Sfw157321 PICL_PROP_VOLTAGE, 16844669Sfw157321 sun4v_env_print_sensor_callback); 16853941Svenki if (!class_node_found) 16863941Svenki return; 16873941Svenki log_printf("\nVoltage sensors:\n"); 16883941Svenki if (syserrlog == 0) { 16893941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16904669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 16914928Sfw157321 PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback); 16923941Svenki if (all_status_ok) { 16933941Svenki log_printf("All voltage sensors are OK.\n"); 16943941Svenki return; 16953941Svenki } 16963941Svenki } 16975028Sfw157321 log_printf("-------------------------------------------------" 16985028Sfw157321 "-----------\n"); 16993941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 17005028Sfw157321 log_printf("-------------------------------------------------" 17015028Sfw157321 "-----------\n"); 17023941Svenki (void) picl_walk_tree_by_class(phyplatformh, 17034669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 17044669Sfw157321 (void *)PICL_PROP_VOLTAGE, 17054669Sfw157321 sun4v_env_print_sensor_callback); 17063941Svenki } 17073941Svenki 17083941Svenki static void 17093941Svenki sun4v_env_print_voltage_indicators() 17103941Svenki { 17115028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 17123941Svenki (void) picl_walk_tree_by_class(phyplatformh, 17134669Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, 17144669Sfw157321 (void *)PICL_PROP_CONDITION, 17154669Sfw157321 sun4v_env_print_indicator_callback); 17163941Svenki if (!class_node_found) 17173941Svenki return; 17183941Svenki log_printf("\nVoltage indicators:\n"); 17193941Svenki if (syserrlog == 0) { 17203941Svenki (void) picl_walk_tree_by_class(phyplatformh, 17214928Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION, 17224669Sfw157321 sun4v_env_print_indicator_callback); 17233941Svenki if (all_status_ok) { 17243941Svenki log_printf("All voltage indicators are OK.\n"); 17253941Svenki return; 17263941Svenki } 17273941Svenki } 17285028Sfw157321 log_printf("-------------------------------------------------" 17295028Sfw157321 "-----------\n"); 17303941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 17315028Sfw157321 log_printf("-------------------------------------------------" 17325028Sfw157321 "-----------\n"); 17333941Svenki (void) picl_walk_tree_by_class(phyplatformh, 17344669Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, 17354669Sfw157321 (void *)PICL_PROP_CONDITION, 17364669Sfw157321 sun4v_env_print_indicator_callback); 17373941Svenki } 17383941Svenki 17393941Svenki static void 17408574SJason.Beloro@Sun.COM sun4v_env_print_humidity_sensors() 17418574SJason.Beloro@Sun.COM { 17428574SJason.Beloro@Sun.COM char *fmt = "%-34s %-14s %-10s\n"; 17438574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 17448574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_SENSOR, 17458574SJason.Beloro@Sun.COM (void *)PICL_PROP_HUMIDITY, 17468574SJason.Beloro@Sun.COM sun4v_env_print_sensor_callback); 17478574SJason.Beloro@Sun.COM if (!class_node_found) 17488574SJason.Beloro@Sun.COM return; 17498574SJason.Beloro@Sun.COM log_printf("\nHumidity sensors:\n"); 17508574SJason.Beloro@Sun.COM if (syserrlog == 0) { 17518574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 17528574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_SENSOR, 17538574SJason.Beloro@Sun.COM PICL_PROP_HUMIDITY, sun4v_env_print_sensor_callback); 17548574SJason.Beloro@Sun.COM if (all_status_ok) { 17558574SJason.Beloro@Sun.COM log_printf("All humidity sensors are OK.\n"); 17568574SJason.Beloro@Sun.COM return; 17578574SJason.Beloro@Sun.COM } 17588574SJason.Beloro@Sun.COM } 17598574SJason.Beloro@Sun.COM log_printf("-------------------------------------------------" 17608574SJason.Beloro@Sun.COM "-----------\n"); 17618574SJason.Beloro@Sun.COM log_printf(fmt, "Location", "Sensor", "Status", 0); 17628574SJason.Beloro@Sun.COM log_printf("-------------------------------------------------" 17638574SJason.Beloro@Sun.COM "-----------\n"); 17648574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 17658574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_SENSOR, 17668574SJason.Beloro@Sun.COM (void *)PICL_PROP_HUMIDITY, 17678574SJason.Beloro@Sun.COM sun4v_env_print_sensor_callback); 17688574SJason.Beloro@Sun.COM } 17698574SJason.Beloro@Sun.COM 17708574SJason.Beloro@Sun.COM static void 17718574SJason.Beloro@Sun.COM sun4v_env_print_humidity_indicators() 17728574SJason.Beloro@Sun.COM { 17738574SJason.Beloro@Sun.COM char *fmt = "%-34s %-14s %-8s\n"; 17748574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 17758574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_INDICATOR, 17768574SJason.Beloro@Sun.COM (void *)PICL_PROP_CONDITION, 17778574SJason.Beloro@Sun.COM sun4v_env_print_indicator_callback); 17788574SJason.Beloro@Sun.COM if (!class_node_found) 17798574SJason.Beloro@Sun.COM return; 17808574SJason.Beloro@Sun.COM log_printf("\nHumidity indicators:\n"); 17818574SJason.Beloro@Sun.COM if (syserrlog == 0) { 17828574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 17838574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_INDICATOR, (void *)PICL_PROP_CONDITION, 17848574SJason.Beloro@Sun.COM sun4v_env_print_indicator_callback); 17858574SJason.Beloro@Sun.COM if (all_status_ok) { 17868574SJason.Beloro@Sun.COM log_printf("All humidity indicators are OK.\n"); 17878574SJason.Beloro@Sun.COM return; 17888574SJason.Beloro@Sun.COM } 17898574SJason.Beloro@Sun.COM } 17908574SJason.Beloro@Sun.COM log_printf("-------------------------------------------------" 17918574SJason.Beloro@Sun.COM "-----------\n"); 17928574SJason.Beloro@Sun.COM log_printf(fmt, "Location", "Indicator", "Condition", 0); 17938574SJason.Beloro@Sun.COM log_printf("-------------------------------------------------" 17948574SJason.Beloro@Sun.COM "-----------\n"); 17958574SJason.Beloro@Sun.COM (void) picl_walk_tree_by_class(phyplatformh, 17968574SJason.Beloro@Sun.COM PICL_CLASS_HUMIDITY_INDICATOR, 17978574SJason.Beloro@Sun.COM (void *)PICL_PROP_CONDITION, 17988574SJason.Beloro@Sun.COM sun4v_env_print_indicator_callback); 17998574SJason.Beloro@Sun.COM } 18008574SJason.Beloro@Sun.COM 18018574SJason.Beloro@Sun.COM static void 18023941Svenki sun4v_env_print_LEDs() 18033941Svenki { 18045028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 18053941Svenki if (syserrlog == 0) 18063941Svenki return; 18073941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 18084669Sfw157321 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 18093941Svenki if (!class_node_found) 18103941Svenki return; 18113941Svenki log_printf("\nLEDs:\n"); 18125028Sfw157321 log_printf("-------------------------------------------------" 18135028Sfw157321 "-----------\n"); 18143941Svenki log_printf(fmt, "Location", "LED", "State", 0); 18155028Sfw157321 log_printf("-------------------------------------------------" 18165028Sfw157321 "-----------\n"); 18173941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 18184669Sfw157321 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 18193941Svenki } 18203941Svenki 18213941Svenki /*ARGSUSED*/ 18223941Svenki static int 18233941Svenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args) 18243941Svenki { 18253941Svenki char label[PICL_PROPNAMELEN_MAX]; 18263941Svenki char status[PICL_PROPNAMELEN_MAX]; 18273941Svenki picl_errno_t err; 18283941Svenki picl_prophdl_t proph; 18293941Svenki picl_nodehdl_t parenth; 18303941Svenki char *names[PARENT_NAMES]; 18313941Svenki char *loc; 18323941Svenki int i; 18333941Svenki 18343941Svenki if (!class_node_found) { 18353941Svenki class_node_found = 1; 18363941Svenki return (PICL_WALK_TERMINATE); 18373941Svenki } 18383941Svenki err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph); 18393941Svenki if (err != PICL_SUCCESS) 18403941Svenki return (PICL_WALK_CONTINUE); 18413941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 18424669Sfw157321 sizeof (label)); 18433941Svenki if (err != PICL_SUCCESS) 18443941Svenki return (PICL_WALK_CONTINUE); 18453941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS, 18464669Sfw157321 status, sizeof (status)); 18473941Svenki if (err != PICL_SUCCESS) 18483941Svenki return (PICL_WALK_CONTINUE); 18493941Svenki if (syserrlog == 0) { 18503941Svenki if (strcmp(status, "disabled") == 0) { 18513941Svenki if (all_status_ok) { 18523941Svenki all_status_ok = 0; 18533941Svenki return (PICL_WALK_TERMINATE); 18543941Svenki } 18553941Svenki } else 18563941Svenki return (PICL_WALK_CONTINUE); 18573941Svenki } 1858*10070SBirva.Shah@Sun.COM 1859*10070SBirva.Shah@Sun.COM if (is_fru_absent(nodeh)) 1860*10070SBirva.Shah@Sun.COM strcpy(status, "Not present"); 1861*10070SBirva.Shah@Sun.COM 18623941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 18634669Sfw157321 sizeof (parenth)); 18643941Svenki if (err != PICL_SUCCESS) { 18653941Svenki log_printf("\n"); 18663941Svenki return (PICL_WALK_CONTINUE); 18673941Svenki } 18683941Svenki if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL) 18693941Svenki return (PICL_WALK_TERMINATE); 18703941Svenki for (i = 0; i < PARENT_NAMES; i++) 18713941Svenki if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) { 18723941Svenki while (--i > -1) 18733941Svenki free(names[i]); 18743941Svenki free(loc); 18753941Svenki return (PICL_WALK_TERMINATE); 18763941Svenki } 18773941Svenki i = 0; 18783941Svenki while (err == PICL_SUCCESS) { 18794802Sfw157321 if (parenth == phyplatformh) 18803941Svenki break; 18813941Svenki err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 18824669Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 18833941Svenki if (err != PICL_SUCCESS) { 18843941Svenki i--; 18853941Svenki break; 18863941Svenki } 18873941Svenki if (i == PARENT_NAMES) 18883941Svenki break; 18893941Svenki err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT, 18904669Sfw157321 &parenth, sizeof (parenth)); 18913941Svenki } 18923941Svenki loc[0] = '\0'; 18934003Svivek if (--i > -1) { 18944003Svivek (void) strlcat(loc, names[i], 18954669Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 18964003Svivek } 18973941Svenki while (--i > -1) { 18984003Svivek (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES); 18994003Svivek (void) strlcat(loc, names[i], 19004669Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 19013941Svenki } 19025028Sfw157321 log_printf("%-35s", loc); 19033941Svenki for (i = 0; i < PARENT_NAMES; i++) 19043941Svenki free(names[i]); 19053941Svenki free(loc); 19063941Svenki log_printf("%-10s", label); 19073941Svenki log_printf("%-9s", status); 19083941Svenki log_printf("\n"); 19093941Svenki return (PICL_WALK_CONTINUE); 19103941Svenki } 19113941Svenki 19123941Svenki static void 19133941Svenki sun4v_print_fru_status() 19143941Svenki { 19155028Sfw157321 char *fmt = "%-34s %-9s %-8s\n"; 19165436Sfw157321 19173941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 19184669Sfw157321 sun4v_print_fru_status_callback); 19193941Svenki if (!class_node_found) 19203941Svenki return; 19215436Sfw157321 19223941Svenki log_printf("\n"); 19233941Svenki log_printf("============================"); 19243941Svenki log_printf(" FRU Status "); 19253941Svenki log_printf("============================"); 19263941Svenki log_printf("\n"); 19273941Svenki 19283941Svenki if (syserrlog == 0) { 19293941Svenki (void) picl_walk_tree_by_class(phyplatformh, 19304802Sfw157321 NULL, NULL, 19314669Sfw157321 sun4v_print_fru_status_callback); 19323941Svenki if (all_status_ok) { 19333941Svenki log_printf("All FRUs are enabled.\n"); 19343941Svenki return; 19353941Svenki } 19363941Svenki } 19373941Svenki log_printf(fmt, "Location", "Name", "Status", 0); 19385028Sfw157321 log_printf("------------------------------------------------------\n"); 19394802Sfw157321 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 19404669Sfw157321 sun4v_print_fru_status_callback); 19413941Svenki } 19423941Svenki 1943*10070SBirva.Shah@Sun.COM /* Check the children of the FRU node for a presence indicator */ 1944*10070SBirva.Shah@Sun.COM static int 1945*10070SBirva.Shah@Sun.COM is_fru_absent(picl_nodehdl_t fruh) 1946*10070SBirva.Shah@Sun.COM { 1947*10070SBirva.Shah@Sun.COM char class [PICL_CLASSNAMELEN_MAX]; 1948*10070SBirva.Shah@Sun.COM char condition [PICL_PROPNAMELEN_MAX]; 1949*10070SBirva.Shah@Sun.COM picl_errno_t err; 1950*10070SBirva.Shah@Sun.COM picl_nodehdl_t nodeh; 1951*10070SBirva.Shah@Sun.COM 1952*10070SBirva.Shah@Sun.COM err = picl_get_propval_by_name(fruh, PICL_PROP_CHILD, &nodeh, 1953*10070SBirva.Shah@Sun.COM sizeof (picl_nodehdl_t)); 1954*10070SBirva.Shah@Sun.COM while (err == PICL_SUCCESS) { 1955*10070SBirva.Shah@Sun.COM err = picl_get_propval_by_name(nodeh, 1956*10070SBirva.Shah@Sun.COM PICL_PROP_CLASSNAME, class, sizeof (class)); 1957*10070SBirva.Shah@Sun.COM if (err == PICL_SUCCESS && 1958*10070SBirva.Shah@Sun.COM strcmp(class, "presence-indicator") == 0) { 1959*10070SBirva.Shah@Sun.COM err = picl_get_propval_by_name(nodeh, 1960*10070SBirva.Shah@Sun.COM PICL_PROP_CONDITION, condition, 1961*10070SBirva.Shah@Sun.COM sizeof (condition)); 1962*10070SBirva.Shah@Sun.COM if (err == PICL_SUCCESS) { 1963*10070SBirva.Shah@Sun.COM if (strcmp(condition, "Absent") == 0) { 1964*10070SBirva.Shah@Sun.COM return (1); 1965*10070SBirva.Shah@Sun.COM } else { 1966*10070SBirva.Shah@Sun.COM return (0); 1967*10070SBirva.Shah@Sun.COM } 1968*10070SBirva.Shah@Sun.COM } 1969*10070SBirva.Shah@Sun.COM } 1970*10070SBirva.Shah@Sun.COM err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, 1971*10070SBirva.Shah@Sun.COM &nodeh, sizeof (picl_nodehdl_t)); 1972*10070SBirva.Shah@Sun.COM } 1973*10070SBirva.Shah@Sun.COM return (0); 1974*10070SBirva.Shah@Sun.COM } 1975*10070SBirva.Shah@Sun.COM 19763941Svenki /*ARGSUSED*/ 19773941Svenki static int 19783941Svenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args) 19793941Svenki { 19803941Svenki char rev[PICL_PROPNAMELEN_MAX]; 19813941Svenki picl_errno_t err; 19823941Svenki 19833941Svenki if (!class_node_found) { 19843941Svenki class_node_found = 1; 19853941Svenki return (PICL_WALK_TERMINATE); 19863941Svenki } 19875436Sfw157321 19883941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev, 19894669Sfw157321 sizeof (rev)); 19903941Svenki if (err != PICL_SUCCESS) 19913941Svenki return (PICL_WALK_CONTINUE); 19923941Svenki if (strlen(rev) == 0) 19933941Svenki return (PICL_WALK_CONTINUE); 19945436Sfw157321 log_printf("%s", rev); 19953941Svenki log_printf("\n"); 19963941Svenki return (PICL_WALK_CONTINUE); 19973941Svenki } 19983941Svenki 19993941Svenki static void 20003941Svenki sun4v_print_fw_rev() 20013941Svenki { 20023941Svenki if (syserrlog == 0) 20033941Svenki return; 20045436Sfw157321 20053941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 20064669Sfw157321 sun4v_print_fw_rev_callback); 20073941Svenki if (!class_node_found) 20083941Svenki return; 20095436Sfw157321 20103941Svenki log_printf("\n"); 20113941Svenki log_printf("============================"); 20123941Svenki log_printf(" FW Version "); 20133941Svenki log_printf("============================"); 20143941Svenki log_printf("\n"); 20155436Sfw157321 log_printf("Version\n"); 20165028Sfw157321 log_printf("-------------------------------------------------" 20175028Sfw157321 "-----------\n"); 20183941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 20194669Sfw157321 sun4v_print_fw_rev_callback); 20203941Svenki } 20213941Svenki 20223941Svenki static void 20235436Sfw157321 sun4v_print_openprom_rev() 20245436Sfw157321 { 20255436Sfw157321 if (syserrlog == 0) 20265436Sfw157321 return; 20275436Sfw157321 20285436Sfw157321 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 20295436Sfw157321 openprom_callback); 20305436Sfw157321 if (!class_node_found) 20315436Sfw157321 return; 20325436Sfw157321 20335436Sfw157321 log_printf("\n"); 20345436Sfw157321 log_printf("======================"); 20355436Sfw157321 log_printf(" System PROM revisions "); 20365436Sfw157321 log_printf("======================="); 20375436Sfw157321 log_printf("\n"); 20385436Sfw157321 log_printf("Version\n"); 20395436Sfw157321 log_printf("-------------------------------------------------" 20405436Sfw157321 "-----------\n"); 20415436Sfw157321 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 20425436Sfw157321 openprom_callback); 20435436Sfw157321 } 20445436Sfw157321 20455436Sfw157321 /* 20465436Sfw157321 * display the OBP and POST prom revisions (if present) 20475436Sfw157321 */ 20485436Sfw157321 /* ARGSUSED */ 20495436Sfw157321 static int 20505436Sfw157321 openprom_callback(picl_nodehdl_t openpromh, void *arg) 20515436Sfw157321 { 20525436Sfw157321 picl_prophdl_t proph; 20535436Sfw157321 picl_prophdl_t tblh; 20545436Sfw157321 picl_prophdl_t rowproph; 20555436Sfw157321 picl_propinfo_t pinfo; 20565436Sfw157321 char *prom_version = NULL; 20575436Sfw157321 char *obp_version = NULL; 20585436Sfw157321 int err; 20595436Sfw157321 20605436Sfw157321 if (!class_node_found) { 20615436Sfw157321 class_node_found = 1; 20625436Sfw157321 return (PICL_WALK_TERMINATE); 20635436Sfw157321 } 20645436Sfw157321 20655436Sfw157321 err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION, 20665436Sfw157321 &pinfo, &proph); 20675436Sfw157321 if (err == PICL_PROPNOTFOUND) 20685436Sfw157321 return (PICL_WALK_TERMINATE); 20695436Sfw157321 else if (err != PICL_SUCCESS) 20705436Sfw157321 return (err); 20715436Sfw157321 20725436Sfw157321 /* 20735436Sfw157321 * If it's a table prop, the first element is OBP revision 20745436Sfw157321 * The second one is POST revision. 20755436Sfw157321 * If it's a charstring prop, the value will be only OBP revision 20765436Sfw157321 */ 20775436Sfw157321 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 20785436Sfw157321 prom_version = (char *)alloca(pinfo.size); 20795436Sfw157321 if (prom_version == NULL) 20805436Sfw157321 return (PICL_FAILURE); 20815436Sfw157321 err = picl_get_propval(proph, prom_version, pinfo.size); 20825436Sfw157321 if (err != PICL_SUCCESS) 20835436Sfw157321 return (err); 20845436Sfw157321 log_printf("%s\n", prom_version); 20855436Sfw157321 } 20865436Sfw157321 20875436Sfw157321 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */ 20885436Sfw157321 return (PICL_WALK_TERMINATE); 20895436Sfw157321 20905436Sfw157321 err = picl_get_propval(proph, &tblh, pinfo.size); 20915436Sfw157321 if (err != PICL_SUCCESS) 20925436Sfw157321 return (err); 20935436Sfw157321 20945436Sfw157321 err = picl_get_next_by_row(tblh, &rowproph); 20955436Sfw157321 if (err == PICL_SUCCESS) { 20965436Sfw157321 /* get first row */ 20975436Sfw157321 err = picl_get_propinfo(rowproph, &pinfo); 20985436Sfw157321 if (err != PICL_SUCCESS) 20995436Sfw157321 return (err); 21005436Sfw157321 21015436Sfw157321 prom_version = (char *)alloca(pinfo.size); 21025436Sfw157321 if (prom_version == NULL) 21035436Sfw157321 return (PICL_FAILURE); 21045436Sfw157321 21055436Sfw157321 err = picl_get_propval(rowproph, prom_version, pinfo.size); 21065436Sfw157321 if (err != PICL_SUCCESS) 21075436Sfw157321 return (err); 21085436Sfw157321 log_printf("%s\n", prom_version); 21095436Sfw157321 21105436Sfw157321 /* get second row */ 21115436Sfw157321 err = picl_get_next_by_col(rowproph, &rowproph); 21125436Sfw157321 if (err == PICL_SUCCESS) { 21135436Sfw157321 err = picl_get_propinfo(rowproph, &pinfo); 21145436Sfw157321 if (err != PICL_SUCCESS) 21155436Sfw157321 return (err); 21165436Sfw157321 21175436Sfw157321 obp_version = (char *)alloca(pinfo.size); 21185436Sfw157321 if (obp_version == NULL) 21195436Sfw157321 return (PICL_FAILURE); 21205436Sfw157321 err = picl_get_propval(rowproph, obp_version, 21215436Sfw157321 pinfo.size); 21225436Sfw157321 if (err != PICL_SUCCESS) 21235436Sfw157321 return (err); 21245436Sfw157321 log_printf("%s\n", obp_version); 21255436Sfw157321 } 21265436Sfw157321 } 21275436Sfw157321 21285436Sfw157321 return (PICL_WALK_TERMINATE); 21295436Sfw157321 } 21305436Sfw157321 21315436Sfw157321 static void 21323941Svenki sun4v_print_chassis_serial_no() 21333941Svenki { 21343941Svenki char val[PICL_PROPNAMELEN_MAX]; 21353941Svenki picl_errno_t err; 21363941Svenki if (syserrlog == 0 || chassish == 0) 21373941Svenki return; 21383941Svenki 21393941Svenki log_printf("\n"); 21406014Ssuha log_printf("Chassis Serial Number"); 21413941Svenki log_printf("\n"); 21423941Svenki log_printf("---------------------\n"); 21433941Svenki err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER, 21444669Sfw157321 val, sizeof (val)); 21453941Svenki if (err == PICL_SUCCESS) 21463941Svenki log_printf("%s", val); 21473941Svenki log_printf("\n"); 21483941Svenki } 2149