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