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 /* 223941Svenki * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 231708Sstevel * Use is subject to license terms. 241708Sstevel */ 251708Sstevel 261708Sstevel #pragma ident "%Z%%M% %I% %E% SMI" 271708Sstevel 281708Sstevel #include <stdio.h> 291708Sstevel #include <stdlib.h> 301708Sstevel #include <unistd.h> 311708Sstevel #include <ctype.h> 321708Sstevel #include <string.h> 331708Sstevel #include <kvm.h> 341708Sstevel #include <varargs.h> 351708Sstevel #include <time.h> 361708Sstevel #include <dirent.h> 371708Sstevel #include <fcntl.h> 381708Sstevel #include <sys/param.h> 391708Sstevel #include <sys/stat.h> 401708Sstevel #include <sys/types.h> 411708Sstevel #include <sys/utsname.h> 421708Sstevel #include <sys/openpromio.h> 431708Sstevel #include <libintl.h> 441708Sstevel #include <syslog.h> 451708Sstevel #include <sys/dkio.h> 463941Svenki #include <sys/systeminfo.h> 473941Svenki #include <picldefs.h> 484802Sfw157321 #include <math.h> 494802Sfw157321 #include <errno.h> 501708Sstevel #include "pdevinfo.h" 511708Sstevel #include "display.h" 521708Sstevel #include "display_sun4v.h" 531708Sstevel #include "libprtdiag.h" 541708Sstevel 551708Sstevel #if !defined(TEXT_DOMAIN) 561708Sstevel #define TEXT_DOMAIN "SYS_TEST" 571708Sstevel #endif 581708Sstevel 594669Sfw157321 #define MOTHERBOARD "MB" 603941Svenki #define NETWORK "network" 613941Svenki #define PCIE_COMPATIBLE_STR "pciex" 623941Svenki #define PCIX_COMPATIBLE_STR "pci" 633941Svenki #define SUN4V_MACHINE "sun4v" 643941Svenki #define PARENT_NAMES 10 653941Svenki 663941Svenki /* 673941Svenki * Additional OBP properties 683941Svenki */ 693941Svenki #define OBP_PROP_COMPATIBLE "compatible" 703941Svenki #define OBP_PROP_MODEL "model" 713941Svenki #define OBP_PROP_SLOT_NAMES "slot-names" 723941Svenki 733941Svenki #define PICL_NODE_PHYSICAL_PLATFORM "physical-platform" 743941Svenki #define PICL_NODE_CHASSIS "chassis" 753941Svenki #define MEMORY_SIZE_FIELD 11 763941Svenki #define INVALID_THRESHOLD 1000000 773941Svenki 783941Svenki /* 793941Svenki * Additional picl classes 803941Svenki */ 813941Svenki #ifndef PICL_CLASS_SUN4V 823941Svenki #define PICL_CLASS_SUN4V "sun4v" 833941Svenki #endif 843941Svenki 853941Svenki #ifndef PICL_PROP_NAC 863941Svenki #define PICL_PROP_NAC "nac" 873941Svenki #endif 883941Svenki 893941Svenki extern int sys_clk; 903941Svenki extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *, 913941Svenki picl_nodehdl_t *); 923941Svenki 933941Svenki static picl_nodehdl_t rooth = 0, phyplatformh = 0; 943941Svenki static picl_nodehdl_t chassish = 0; 953941Svenki static int class_node_found; 963941Svenki static int syserrlog; 973941Svenki static int all_status_ok; 983941Svenki 993941Svenki /* local functions */ 1003941Svenki static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **); 1013941Svenki static void sun4v_display_memory_conf(picl_nodehdl_t); 1023941Svenki static void sun4v_disp_env_status(); 1033941Svenki static void sun4v_env_print_fan_sensors(); 1043941Svenki static void sun4v_env_print_fan_indicators(); 1053941Svenki static void sun4v_env_print_temp_sensors(); 1063941Svenki static void sun4v_env_print_temp_indicators(); 1073941Svenki static void sun4v_env_print_current_sensors(); 1083941Svenki static void sun4v_env_print_current_indicators(); 1093941Svenki static void sun4v_env_print_voltage_sensors(); 1103941Svenki static void sun4v_env_print_voltage_indicators(); 1113941Svenki static void sun4v_env_print_LEDs(); 1123941Svenki static void sun4v_print_fru_status(); 1133941Svenki static void sun4v_print_fw_rev(); 1143941Svenki static void sun4v_print_chassis_serial_no(); 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]; 1243941Svenki 1253941Svenki if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1) 1263941Svenki return (1); 1273941Svenki if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0) 1283941Svenki return (1); 1291708Sstevel 1301708Sstevel sys_clk = -1; /* System clock freq. (in MHz) */ 1311708Sstevel 1321708Sstevel /* 1331708Sstevel * Now display the machine's configuration. We do this if we 1341708Sstevel * are not logging. 1351708Sstevel */ 1361708Sstevel if (!logging) { 1371708Sstevel struct utsname uts_buf; 1381708Sstevel 1391708Sstevel /* 1401708Sstevel * Display system banner 1411708Sstevel */ 1421708Sstevel (void) uname(&uts_buf); 1431708Sstevel 1443941Svenki log_printf(dgettext(TEXT_DOMAIN, "System Configuration: " 1454669Sfw157321 "Sun Microsystems %s %s\n"), uts_buf.machine, 1464669Sfw157321 get_prop_val(find_prop(root, "banner-name")), 0); 1471708Sstevel 1481708Sstevel /* display system clock frequency */ 1491708Sstevel value = get_prop_val(find_prop(root, "clock-frequency")); 1501708Sstevel if (value != NULL) { 1511708Sstevel sys_clk = ((*((int *)value)) + 500000) / 1000000; 1521708Sstevel log_printf(dgettext(TEXT_DOMAIN, "System clock " 1534669Sfw157321 "frequency: %d MHz\n"), sys_clk, 0); 1541708Sstevel } 1551708Sstevel 1561708Sstevel /* Display the Memory Size */ 1571708Sstevel display_memorysize(tree, NULL, &grps, &memory_total); 1581708Sstevel 1591708Sstevel /* Display the CPU devices */ 1601708Sstevel sun4v_display_cpu_devices(plafh); 1611708Sstevel 1621708Sstevel /* Display the Memory configuration */ 1633941Svenki class_node_found = 0; 1643941Svenki sun4v_display_memory_conf(plafh); 1651708Sstevel 1661708Sstevel /* Display all the IO cards. */ 1671708Sstevel (void) sun4v_display_pci(plafh); 1683941Svenki sun4v_display_diaginfo((log || (logging)), root, plafh); 1691708Sstevel 1703941Svenki if (picl_get_root(&rooth) != PICL_SUCCESS) 1713941Svenki return (1); 1723941Svenki if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM, 1734669Sfw157321 &phyplatformh) != PICL_SUCCESS) 1743941Svenki return (1); 1753941Svenki 1763941Svenki if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME, 1774669Sfw157321 PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS, 1784669Sfw157321 strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS) 1793941Svenki return (1); 1803941Svenki 1813941Svenki syserrlog = log; 1823941Svenki sun4v_disp_env_status(); 1833941Svenki } 1843941Svenki return (0); 1853941Svenki } 1863941Svenki 1873941Svenki static void 1883941Svenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card) 1893941Svenki { 1903941Svenki char *compatible; 1913941Svenki 1924003Svivek (void) strlcpy(card->bus_type, "PCIX", sizeof (card->bus_type)); 1933941Svenki if (sun4v_get_first_compatible_value(nodeh, &compatible) 1944669Sfw157321 == PICL_SUCCESS) { 1953941Svenki if (strncmp(compatible, PCIE_COMPATIBLE_STR, 1964669Sfw157321 strlen(PCIE_COMPATIBLE_STR)) == 0) 1974003Svivek (void) strlcpy(card->bus_type, "PCIE", 1984669Sfw157321 sizeof (card->bus_type)); 1993941Svenki free(compatible); 2003941Svenki } 2013941Svenki } 2023941Svenki 2033941Svenki static picl_errno_t 2043941Svenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card) 2053941Svenki { 2063941Svenki char val[PICL_PROPNAMELEN_MAX]; 2073941Svenki picl_errno_t err; 2083941Svenki 2093941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 2104669Sfw157321 sizeof (val)); 2113941Svenki if (err != PICL_SUCCESS) 2123941Svenki return (err); 2133941Svenki 2144003Svivek (void) strlcpy(card->slot_str, val, sizeof (card->slot_str)); 2153941Svenki card->slot = -1; 2163941Svenki return (PICL_SUCCESS); 2173941Svenki } 2183941Svenki 2193941Svenki static void 2203941Svenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card) 2213941Svenki { 2223941Svenki picl_errno_t err; 2233941Svenki picl_prophdl_t proph; 2243941Svenki picl_propinfo_t pinfo; 2253941Svenki picl_nodehdl_t pnodeh; 2263941Svenki uint8_t *pval; 2273941Svenki uint32_t dev_mask; 2283941Svenki char uaddr[MAXSTRLEN]; 2293941Svenki int i; 2303941Svenki 2313941Svenki if (get_slot_label(nodeh, card) == PICL_SUCCESS) 2323941Svenki return; 2333941Svenki err = PICL_SUCCESS; 2343941Svenki while (err == PICL_SUCCESS) { 2353941Svenki if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh, 2364669Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS) { 2374669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 2384669Sfw157321 sizeof (card->slot_str)); 2393941Svenki card->slot = -1; 2403941Svenki return; 2413941Svenki } 2423941Svenki if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES, 2434669Sfw157321 &pinfo, &proph) == PICL_SUCCESS) { 2443941Svenki break; 2453941Svenki } 2463941Svenki nodeh = pnodeh; 2473941Svenki } 2483941Svenki if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr, 2494669Sfw157321 sizeof (uaddr)) != PICL_SUCCESS) { 2504669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 2514669Sfw157321 sizeof (card->slot_str)); 2523941Svenki card->slot = -1; 2533941Svenki return; 2543941Svenki } 2553941Svenki pval = (uint8_t *)malloc(pinfo.size); 2563941Svenki if (!pval) { 2574669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 2584669Sfw157321 sizeof (card->slot_str)); 2593941Svenki card->slot = -1; 2603941Svenki return; 2613941Svenki } 2623941Svenki if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) { 2634669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 2644669Sfw157321 sizeof (card->slot_str)); 2653941Svenki card->slot = -1; 2663941Svenki free(pval); 2673941Svenki return; 2681708Sstevel } 2691708Sstevel 2703941Svenki dev_mask = 0; 2713941Svenki for (i = 0; i < sizeof (dev_mask); i++) 2723941Svenki dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i)); 2733941Svenki for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) { 2743941Svenki if (uaddr[i] == ',') { 2753941Svenki uaddr[i] = '\0'; 2763941Svenki break; 2773941Svenki } 2783941Svenki } 2793941Svenki card->slot = atol(uaddr); 2803941Svenki if (((1 << card->slot) & dev_mask) == 0) { 2814669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 2824669Sfw157321 sizeof (card->slot_str)); 2833941Svenki card->slot = -1; 2843941Svenki } else { 2853941Svenki char *p = (char *)(pval+sizeof (dev_mask)); 2863941Svenki int shift = sizeof (uint32_t)*8-1-card->slot; 2873941Svenki uint32_t x = (dev_mask << shift) >> shift; 2883941Svenki int count = 0; /* count # of 1's in x */ 2893941Svenki int i = 0; 2903941Svenki while (x != 0) { 2913941Svenki count++; 2923941Svenki x &= x-1; 2933941Svenki } 2943941Svenki while (count > 1) { 2954669Sfw157321 while (p[i++] != '\0') 2964669Sfw157321 ; 2973941Svenki count--; 2983941Svenki } 2994003Svivek (void) strlcpy(card->slot_str, (char *)(p+i), 3004669Sfw157321 sizeof (card->slot_str)); 3013941Svenki } 3023941Svenki free(pval); 3033941Svenki } 3043941Svenki 3053941Svenki /* 3063941Svenki * add all io devices under pci in io list 3073941Svenki */ 3083941Svenki /* ARGSUSED */ 3093941Svenki static int 3103941Svenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args) 3113941Svenki { 3123941Svenki char path[PICL_PROPNAMELEN_MAX]; 3133941Svenki char class[PICL_CLASSNAMELEN_MAX]; 3143941Svenki char name[PICL_PROPNAMELEN_MAX]; 3153941Svenki char model[PICL_PROPNAMELEN_MAX]; 3163941Svenki char binding_name[PICL_PROPNAMELEN_MAX]; 3173941Svenki char val[PICL_PROPNAMELEN_MAX]; 3183941Svenki char *compatible; 3193941Svenki picl_errno_t err; 3203941Svenki picl_nodehdl_t nodeh; 3213941Svenki struct io_card pci_card; 3223941Svenki 3233941Svenki /* Walk through the children */ 3243941Svenki 3253941Svenki err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 3264669Sfw157321 sizeof (picl_nodehdl_t)); 3273941Svenki 3283941Svenki while (err == PICL_SUCCESS) { 3293941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 3304669Sfw157321 class, sizeof (class)); 3313941Svenki if (err != PICL_SUCCESS) 3323941Svenki return (err); 3333941Svenki 3343941Svenki if (args) { 3353941Svenki char *val = args; 3363941Svenki if (strcmp(class, val) == 0) { 3373941Svenki err = picl_get_propval_by_name(nodeh, 3384669Sfw157321 PICL_PROP_PEER, &nodeh, 3394669Sfw157321 sizeof (picl_nodehdl_t)); 3403941Svenki continue; 3413941Svenki } else if (strcmp(val, PICL_CLASS_PCIEX) == 0 && 3424669Sfw157321 strcmp(class, PICL_CLASS_PCI) == 0) { 3433941Svenki err = picl_get_propval_by_name(nodeh, 3444669Sfw157321 PICL_PROP_PEER, &nodeh, 3454669Sfw157321 sizeof (picl_nodehdl_t)); 3463941Svenki continue; 3473941Svenki } else if (strcmp(val, PICL_CLASS_PCI) == 0 && 3484669Sfw157321 strcmp(class, PICL_CLASS_PCIEX) == 0) { 3493941Svenki err = picl_get_propval_by_name(nodeh, 3504669Sfw157321 PICL_PROP_PEER, &nodeh, 3514669Sfw157321 sizeof (picl_nodehdl_t)); 3523941Svenki continue; 3533941Svenki } 3543941Svenki } 3553941Svenki 3563941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH, 3574669Sfw157321 path, sizeof (path)); 3583941Svenki if (err != PICL_SUCCESS) 3593941Svenki return (err); 3603941Svenki 3613941Svenki (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes)); 3623941Svenki 3633941Svenki get_bus_type(nodeh, &pci_card); 3643941Svenki get_slot_number(nodeh, &pci_card); 3653941Svenki 3663941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name, 3674669Sfw157321 sizeof (name)); 3683941Svenki if (err == PICL_PROPNOTFOUND) 3694003Svivek (void) strlcpy(name, "", sizeof (name)); 3703941Svenki else if (err != PICL_SUCCESS) 3713941Svenki return (err); 3723941Svenki 3733941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val, 3744669Sfw157321 sizeof (val)); 3753941Svenki if (err == PICL_PROPNOTFOUND) 3764003Svivek (void) strlcpy(val, "", sizeof (val)); 3773941Svenki else if (err != PICL_SUCCESS) 3783941Svenki return (err); 3793941Svenki 3803941Svenki /* Figure NAC name */ 3813941Svenki if (pci_card.slot != -1) 3823941Svenki (void) snprintf(pci_card.status, 3834669Sfw157321 sizeof (pci_card.status), 3844669Sfw157321 "%s%d", pci_card.slot_str, 3854669Sfw157321 pci_card.slot); 3863941Svenki else 3873941Svenki (void) snprintf(pci_card.status, 3884669Sfw157321 sizeof (pci_card.status), 3894669Sfw157321 "%s", pci_card.slot_str); 3903941Svenki 3913941Svenki /* 3923941Svenki * Get the name of this card. If binding_name is found, 3933941Svenki * name will be <nodename>-<binding_name>. 3943941Svenki */ 3953941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, 3964669Sfw157321 binding_name, sizeof (binding_name)); 3973941Svenki if (err == PICL_SUCCESS) { 3983941Svenki if (strcmp(name, binding_name) != 0) { 3993941Svenki (void) strlcat(name, "-", sizeof (name)); 4003941Svenki (void) strlcat(name, binding_name, 4014669Sfw157321 sizeof (name)); 4023941Svenki } 4033941Svenki } else if (err == PICL_PROPNOTFOUND) { 4043941Svenki /* 4053941Svenki * if compatible prop is not found, name will be 4063941Svenki * <nodename>-<compatible> 4073941Svenki */ 4083941Svenki err = sun4v_get_first_compatible_value(nodeh, 4094669Sfw157321 &compatible); 4103941Svenki if (err == PICL_SUCCESS) { 4113941Svenki (void) strlcat(name, "-", sizeof (name)); 4124003Svivek (void) strlcat(name, compatible, 4134669Sfw157321 sizeof (name)); 4143941Svenki free(compatible); 4153941Svenki } 4163941Svenki } else 4173941Svenki return (err); 4183941Svenki 4193941Svenki (void) strlcpy(pci_card.name, name, sizeof (pci_card.name)); 4203941Svenki 4213941Svenki /* Get the model of this card */ 4223941Svenki 4233941Svenki err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL, 4244669Sfw157321 model, sizeof (model)); 4253941Svenki if (err == PICL_PROPNOTFOUND) 4264003Svivek (void) strlcpy(model, "", sizeof (model)); 4273941Svenki else if (err != PICL_SUCCESS) 4283941Svenki return (err); 4293941Svenki (void) strlcpy(pci_card.model, model, sizeof (pci_card.model)); 4303941Svenki 4313941Svenki /* Print NAC name */ 4324802Sfw157321 log_printf("%-18s", pci_card.status); 4333941Svenki /* Print IO Type */ 4343941Svenki log_printf("%-6s", pci_card.bus_type); 4353941Svenki /* Printf Card Name */ 4364802Sfw157321 log_printf("%-44s", pci_card.name); 4373941Svenki /* Print Card Model */ 4383941Svenki log_printf("%-8s", pci_card.model); 4393941Svenki log_printf("\n"); 4403941Svenki /* Print Status */ 4414802Sfw157321 log_printf("%-18s", val); 4423941Svenki /* Print IO Type */ 4433941Svenki log_printf("%-6s", ""); 4443941Svenki /* Print Parent Path */ 4454802Sfw157321 log_printf("%-44s", pci_card.notes); 4463941Svenki log_printf("\n"); 4473941Svenki 4483941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 4494669Sfw157321 sizeof (picl_nodehdl_t)); 4503941Svenki } 4513941Svenki return (PICL_WALK_CONTINUE); 4521708Sstevel } 4531708Sstevel 4541708Sstevel /* 4551708Sstevel * display_pci 4561708Sstevel * Display all the PCI IO cards on this board. 4571708Sstevel */ 4581708Sstevel void 4591708Sstevel sun4v_display_pci(picl_nodehdl_t plafh) 4601708Sstevel { 4614802Sfw157321 char *fmt = "%-17s %-5s %-44s %-8s"; 4623941Svenki /* Have we printed the column headings? */ 4633941Svenki static int banner = FALSE; 4643941Svenki 4653941Svenki if (banner == FALSE) { 4663941Svenki log_printf("\n"); 4674802Sfw157321 log_printf("================================"); 4683941Svenki log_printf(" IO Devices "); 4694802Sfw157321 log_printf("================================"); 4703941Svenki log_printf("\n"); 4713941Svenki log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0); 4723941Svenki log_printf("\n"); 4733941Svenki log_printf(fmt, "Status", "Type", "Path", "", 0); 4743941Svenki log_printf("\n"); 4753941Svenki log_printf("---------------------------------" 4764802Sfw157321 "-------------------------------------------\n"); 4773941Svenki banner = TRUE; 4783941Svenki } 4793941Svenki 4803941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, 4814669Sfw157321 PICL_CLASS_PCIEX, sun4v_pci_callback); 4823941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI, 4834669Sfw157321 PICL_CLASS_PCI, sun4v_pci_callback); 4843941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V, 4854669Sfw157321 PICL_CLASS_SUN4V, sun4v_pci_callback); 4863941Svenki } 4873941Svenki 4883941Svenki /* 4893941Svenki * return the first compatible value 4903941Svenki */ 4913941Svenki static int 4923941Svenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf) 4933941Svenki { 4943941Svenki picl_errno_t err; 4953941Svenki picl_prophdl_t proph; 4963941Svenki picl_propinfo_t pinfo; 4973941Svenki picl_prophdl_t tblh; 4983941Svenki picl_prophdl_t rowproph; 4993941Svenki char *pval; 5003941Svenki 5013941Svenki err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE, 5024669Sfw157321 &pinfo, &proph); 5033941Svenki if (err != PICL_SUCCESS) 5043941Svenki return (err); 5053941Svenki 5063941Svenki if (pinfo.type == PICL_PTYPE_CHARSTRING) { 5073941Svenki pval = malloc(pinfo.size); 5083941Svenki if (pval == NULL) 5093941Svenki return (PICL_FAILURE); 5103941Svenki err = picl_get_propval(proph, pval, pinfo.size); 5113941Svenki if (err != PICL_SUCCESS) { 5123941Svenki free(pval); 5133941Svenki return (err); 5143941Svenki } 5153941Svenki *outbuf = pval; 5163941Svenki return (PICL_SUCCESS); 5173941Svenki } 5183941Svenki 5193941Svenki if (pinfo.type != PICL_PTYPE_TABLE) 5203941Svenki return (PICL_FAILURE); 5213941Svenki 5223941Svenki /* get first string from table */ 5233941Svenki err = picl_get_propval(proph, &tblh, pinfo.size); 5243941Svenki if (err != PICL_SUCCESS) 5253941Svenki return (err); 5263941Svenki 5273941Svenki err = picl_get_next_by_row(tblh, &rowproph); 5283941Svenki if (err != PICL_SUCCESS) 5293941Svenki return (err); 5303941Svenki 5313941Svenki err = picl_get_propinfo(rowproph, &pinfo); 5323941Svenki if (err != PICL_SUCCESS) 5333941Svenki return (err); 5343941Svenki 5353941Svenki pval = malloc(pinfo.size); 5363941Svenki if (pval == NULL) 5373941Svenki return (PICL_FAILURE); 5383941Svenki 5393941Svenki err = picl_get_propval(rowproph, pval, pinfo.size); 5403941Svenki if (err != PICL_SUCCESS) { 5413941Svenki free(pval); 5423941Svenki return (err); 5433941Svenki } 5443941Svenki 5453941Svenki *outbuf = pval; 5463941Svenki return (PICL_SUCCESS); 5471708Sstevel } 5481708Sstevel 5493941Svenki /* 5503941Svenki * print size of a memory segment 5513941Svenki */ 5523941Svenki static void 5533941Svenki print_memory_segment_size(uint64_t size) 5543941Svenki { 5553941Svenki uint64_t kbyte = 1024; 5563941Svenki uint64_t mbyte = kbyte * kbyte; 5573941Svenki uint64_t gbyte = kbyte * mbyte; 5583941Svenki char buf[MEMORY_SIZE_FIELD]; 5593941Svenki 5603941Svenki if (size >= gbyte) { 5613941Svenki if (size % gbyte == 0) 5623941Svenki (void) snprintf(buf, sizeof (buf), "%d GB", 5634669Sfw157321 (int)(size / gbyte)); 5643941Svenki else 5653941Svenki (void) snprintf(buf, sizeof (buf), "%.2f GB", 5664669Sfw157321 (float)size / gbyte); 5673941Svenki } else if (size >= mbyte) { 5683941Svenki if (size % mbyte == 0) 5693941Svenki (void) snprintf(buf, sizeof (buf), "%d MB", 5704669Sfw157321 (int)(size / mbyte)); 5713941Svenki else 5723941Svenki (void) snprintf(buf, sizeof (buf), "%.2f MB", 5734669Sfw157321 (float)size / mbyte); 5743941Svenki } else { 5753941Svenki if (size % kbyte == 0) 5763941Svenki (void) snprintf(buf, sizeof (buf), "%d KB", 5774669Sfw157321 (int)(size / kbyte)); 5783941Svenki else 5793941Svenki (void) snprintf(buf, sizeof (buf), "%.2f KB", 5804669Sfw157321 (float)size / kbyte); 5813941Svenki } 5823941Svenki log_printf("%-7s ", buf); 5833941Svenki } 5843941Svenki 5853941Svenki /* 5864669Sfw157321 * Enumerate banks and dimms within a memory segment. We're handed 5874669Sfw157321 * the first bank within the segment - we assume there are dimms 5884669Sfw157321 * (memory-module) nodes underneath. 5893941Svenki */ 5903941Svenki static void 5914669Sfw157321 print_memory_segment_contain(picl_nodehdl_t bank_nodeh) 5921708Sstevel { 5933941Svenki char val[PICL_PROPNAMELEN_MAX]; 5944669Sfw157321 picl_nodehdl_t module_nodeh; 5954669Sfw157321 int flag = 0; 5964669Sfw157321 5974669Sfw157321 do { 5984669Sfw157321 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD, 5994669Sfw157321 &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS) 6004669Sfw157321 continue; 6014669Sfw157321 do { 6024669Sfw157321 if (picl_get_propval_by_name(module_nodeh, 6034669Sfw157321 PICL_PROP_NAC, val, sizeof (val)) != 6044669Sfw157321 PICL_SUCCESS) 6054669Sfw157321 continue; 6064669Sfw157321 else { 6074669Sfw157321 if (!flag) { 6084669Sfw157321 log_printf("%-30s\n", val); 6094669Sfw157321 flag = 1; 6104669Sfw157321 } else 6114669Sfw157321 log_printf("%57s\n", val); 6124669Sfw157321 } 6134669Sfw157321 } while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER, 6144669Sfw157321 &module_nodeh, sizeof (picl_nodehdl_t)) == 6154669Sfw157321 PICL_SUCCESS); 6164669Sfw157321 } while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER, 6174669Sfw157321 &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS); 6183941Svenki } 6193941Svenki 6203941Svenki /* 6213941Svenki * Search node where _class=="memory-segment" 6223941Svenki * print "Base Address", "Size", etc 6233941Svenki */ 6243941Svenki /*ARGSUSED*/ 6253941Svenki static int 6263941Svenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args) 6273941Svenki { 6283941Svenki uint64_t base; 6293941Svenki uint64_t size; 6303941Svenki uint64_t ifactor; 6313941Svenki picl_errno_t err = PICL_SUCCESS; 6323941Svenki 6333941Svenki if (class_node_found == 0) { 6343941Svenki class_node_found = 1; 6353941Svenki return (PICL_WALK_TERMINATE); 6363941Svenki } 6373941Svenki while (err == PICL_SUCCESS) { 6383941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS, 6394669Sfw157321 &base, sizeof (base)); 6403941Svenki if (err != PICL_SUCCESS) 6413941Svenki break; 6423941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE, 6434669Sfw157321 &size, sizeof (size)); 6443941Svenki if (err != PICL_SUCCESS) 6453941Svenki break; 6463941Svenki err = picl_get_propval_by_name(nodeh, 6474669Sfw157321 PICL_PROP_INTERLEAVE_FACTOR, &ifactor, 6484669Sfw157321 sizeof (ifactor)); 6493941Svenki if (err != PICL_SUCCESS) 6503941Svenki break; 6513941Svenki log_printf("%-13llx", base); 6523941Svenki print_memory_segment_size(size); 6534669Sfw157321 log_printf("%-18lld", ifactor); 6544669Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, 6554669Sfw157321 &nodeh, sizeof (nodeh)); 6564669Sfw157321 if (err == PICL_SUCCESS) 6574669Sfw157321 print_memory_segment_contain(nodeh); 6583941Svenki log_printf("\n"); 6593941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 6604669Sfw157321 sizeof (picl_nodehdl_t)); 6613941Svenki } 6623941Svenki 6633941Svenki return (PICL_WALK_CONTINUE); 6643941Svenki } 6653941Svenki 6663941Svenki /*ARGSUSED*/ 6673941Svenki void 6683941Svenki sun4v_display_memory_conf(picl_nodehdl_t plafh) 6693941Svenki { 6703941Svenki char *fmt = "%-12s %-7s %-9s %-20s"; 6713941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 6724669Sfw157321 NULL, sun4v_memory_conf_callback); 6733941Svenki if (class_node_found == 0) 6743941Svenki return; 6753941Svenki log_printf("\n"); 6763941Svenki log_printf("============================"); 6773941Svenki log_printf(" Memory Configuration "); 6783941Svenki log_printf("============================"); 6793941Svenki log_printf("\n"); 6803941Svenki log_printf("Segment Table:\n"); 6814669Sfw157321 log_printf( 6824669Sfw157321 "---------------------------------------------------------\n"); 6833941Svenki log_printf(fmt, "Base Address", "Size", "Interleave Factor", 6844669Sfw157321 "Contains", 0); 6853941Svenki log_printf("\n"); 6864669Sfw157321 log_printf( 6874669Sfw157321 "---------------------------------------------------------\n"); 6883941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 6894669Sfw157321 NULL, sun4v_memory_conf_callback); 6901708Sstevel } 6911708Sstevel 6921708Sstevel void 6931708Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh) 6941708Sstevel { 6953941Svenki char *fmt = "%-12s %-5s %-8s %-19s %-5s"; 6961708Sstevel 6971708Sstevel /* 6981708Sstevel * Display the table header for CPUs . Then display the CPU 6991708Sstevel * frequency, cache size, and processor revision of all cpus. 7001708Sstevel */ 7011708Sstevel log_printf(dgettext(TEXT_DOMAIN, 7024669Sfw157321 "\n" 7034669Sfw157321 "=========================" 7044669Sfw157321 " CPUs " 7054669Sfw157321 "===============================================" 7064669Sfw157321 "\n" 7074669Sfw157321 "\n")); 7081708Sstevel log_printf(fmt, "", "", "", "CPU", "CPU", 0); 7091708Sstevel log_printf("\n"); 7101708Sstevel log_printf(fmt, "Location", "CPU", "Freq", 7114669Sfw157321 "Implementation", "Mask", 0); 7121708Sstevel log_printf("\n"); 7131708Sstevel log_printf(fmt, "------------", "-----", "--------", 7144669Sfw157321 "-------------------", "-----", 0); 7151708Sstevel log_printf("\n"); 7161708Sstevel 7171708Sstevel (void) picl_walk_tree_by_class(plafh, "cpu", "cpu", sun4v_display_cpus); 7181708Sstevel } 7191708Sstevel 7201708Sstevel /* 7211708Sstevel * Display the CPUs present on this board. 7221708Sstevel */ 7231708Sstevel /*ARGSUSED*/ 7241708Sstevel int 7251708Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args) 7261708Sstevel { 7271708Sstevel int status; 7283941Svenki picl_prophdl_t proph; 7293941Svenki picl_prophdl_t tblh; 7303941Svenki picl_prophdl_t rowproph; 7311708Sstevel picl_propinfo_t propinfo; 7323941Svenki int *int_value; 7333941Svenki uint64_t cpuid, mask_no; 7343941Svenki char *comp_value; 7353941Svenki char *no_prop_value = " "; 7363941Svenki char freq_str[MAXSTRLEN]; 7373941Svenki char fru_name[MAXSTRLEN]; 7381708Sstevel 7391708Sstevel /* 7401708Sstevel * Get cpuid property and print it and the NAC name 7411708Sstevel */ 7421708Sstevel status = picl_get_propinfo_by_name(cpuh, "cpuid", &propinfo, &proph); 7431708Sstevel if (status == PICL_SUCCESS) { 7441708Sstevel status = picl_get_propval(proph, &cpuid, sizeof (cpuid)); 7451708Sstevel if (status != PICL_SUCCESS) { 7463941Svenki log_printf("%-13s", no_prop_value); 7473941Svenki log_printf("%-6s", no_prop_value); 7481708Sstevel } else { 7491708Sstevel (void) snprintf(fru_name, sizeof (fru_name), "%s%d", 7501708Sstevel CPU_STRAND_NAC, (int)cpuid); 7513941Svenki log_printf("%-13s", fru_name); 7523941Svenki log_printf("%-6d", (int)cpuid); 7531708Sstevel } 7541708Sstevel } else { 7553941Svenki log_printf("%-13s", no_prop_value); 7563941Svenki log_printf("%-6s", no_prop_value); 7571708Sstevel } 7581708Sstevel 7591708Sstevel clock_freq: 7601708Sstevel status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo, 7614669Sfw157321 &proph); 7621708Sstevel if (status == PICL_SUCCESS) { 7631708Sstevel int_value = malloc(propinfo.size); 7641708Sstevel if (int_value == NULL) { 7653941Svenki log_printf("%-9s", no_prop_value); 7661708Sstevel goto compatible; 7671708Sstevel } 7681708Sstevel status = picl_get_propval(proph, int_value, propinfo.size); 7691708Sstevel if (status != PICL_SUCCESS) { 7703941Svenki log_printf("%-9s", no_prop_value); 7711708Sstevel } else { 7721708Sstevel /* Running frequency */ 7731708Sstevel (void) snprintf(freq_str, sizeof (freq_str), "%d MHz", 7741708Sstevel CLK_FREQ_TO_MHZ(*int_value)); 7753941Svenki log_printf("%-9s", freq_str); 7761708Sstevel } 7771708Sstevel free(int_value); 7781708Sstevel } else 7793941Svenki log_printf("%-9s", no_prop_value); 7801708Sstevel 7811708Sstevel compatible: 7821708Sstevel status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo, 7834669Sfw157321 &proph); 7841708Sstevel if (status == PICL_SUCCESS) { 7851708Sstevel if (propinfo.type == PICL_PTYPE_CHARSTRING) { 7861708Sstevel /* 7871708Sstevel * Compatible Property only has 1 value 7881708Sstevel */ 7891708Sstevel comp_value = malloc(propinfo.size); 7901708Sstevel if (comp_value == NULL) { 7913941Svenki log_printf("%-20s", no_prop_value, 0); 7921708Sstevel goto mask; 7931708Sstevel } 7941708Sstevel status = picl_get_propval(proph, comp_value, 7954669Sfw157321 propinfo.size); 7963941Svenki if (status != PICL_SUCCESS) 7973941Svenki log_printf("%-20s", no_prop_value, 0); 7983941Svenki else 7993941Svenki log_printf("%-20s", comp_value, 0); 8003941Svenki free(comp_value); 8011708Sstevel } else if (propinfo.type == PICL_PTYPE_TABLE) { 8021708Sstevel /* 8031708Sstevel * Compatible Property has multiple values 8041708Sstevel */ 8051708Sstevel status = picl_get_propval(proph, &tblh, propinfo.size); 8061708Sstevel if (status != PICL_SUCCESS) { 8073941Svenki log_printf("%-20s", no_prop_value, 0); 8081708Sstevel goto mask; 8091708Sstevel } 8101708Sstevel status = picl_get_next_by_row(tblh, &rowproph); 8111708Sstevel if (status != PICL_SUCCESS) { 8123941Svenki log_printf("%-20s", no_prop_value, 0); 8131708Sstevel goto mask; 8141708Sstevel } 8151708Sstevel 8161708Sstevel status = picl_get_propinfo(rowproph, &propinfo); 8171708Sstevel if (status != PICL_SUCCESS) { 8183941Svenki log_printf("%-20s", no_prop_value, 0); 8191708Sstevel goto mask; 8201708Sstevel } 8211708Sstevel 8221708Sstevel comp_value = malloc(propinfo.size); 8231708Sstevel if (comp_value == NULL) { 8243941Svenki log_printf("%-20s", no_prop_value, 0); 8251708Sstevel goto mask; 8261708Sstevel } 8271708Sstevel status = picl_get_propval(rowproph, comp_value, 8284669Sfw157321 propinfo.size); 8293941Svenki if (status != PICL_SUCCESS) 8303941Svenki log_printf("%-20s", no_prop_value, 0); 8313941Svenki else 8323941Svenki log_printf("%-20s", comp_value, 0); 8331708Sstevel free(comp_value); 8341708Sstevel } 8351708Sstevel } else 8363941Svenki log_printf("%-20s", no_prop_value, 0); 8371708Sstevel 8381708Sstevel mask: 8391708Sstevel status = picl_get_propinfo_by_name(cpuh, "mask#", &propinfo, &proph); 8401708Sstevel if (status == PICL_SUCCESS) { 8411708Sstevel status = picl_get_propval(proph, &mask_no, sizeof (mask_no)); 8421708Sstevel if (status != PICL_SUCCESS) { 8433941Svenki log_printf("%-9s", no_prop_value); 8441708Sstevel } else { 8451708Sstevel log_printf(dgettext(TEXT_DOMAIN, " %2d.%d"), 8464669Sfw157321 (mask_no>> 4) & 0xf, mask_no & 0xf); 8471708Sstevel } 8481708Sstevel } else 8493941Svenki log_printf("%-9s", no_prop_value); 8501708Sstevel 8511708Sstevel done: 8521708Sstevel log_printf("\n"); 8531708Sstevel return (PICL_WALK_CONTINUE); 8541708Sstevel } 8551708Sstevel 8561708Sstevel void 8571708Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh) 8581708Sstevel { 8591708Sstevel #ifdef lint 8601708Sstevel flag = flag; 8611708Sstevel root = root; 8621708Sstevel plafh = plafh; 8631708Sstevel #endif 8641708Sstevel /* 8651708Sstevel * This function is intentionally empty 8661708Sstevel */ 8671708Sstevel } 8681708Sstevel 8691708Sstevel void 8701708Sstevel display_boardnum(int num) 8711708Sstevel { 8721708Sstevel log_printf("%2d ", num, 0); 8731708Sstevel } 8743941Svenki 8753941Svenki static void 8763941Svenki sun4v_disp_env_status() 8773941Svenki { 8783941Svenki if (phyplatformh == 0) 8793941Svenki return; 8803941Svenki log_printf("\n"); 8813941Svenki log_printf("============================"); 8823941Svenki log_printf(" Environmental Status "); 8833941Svenki log_printf("============================"); 8843941Svenki log_printf("\n"); 8853941Svenki 8863941Svenki class_node_found = 0; 8873941Svenki all_status_ok = 1; 8883941Svenki sun4v_env_print_fan_sensors(); 8893941Svenki 8903941Svenki class_node_found = 0; 8913941Svenki all_status_ok = 1; 8923941Svenki sun4v_env_print_fan_indicators(); 8933941Svenki 8943941Svenki class_node_found = 0; 8953941Svenki all_status_ok = 1; 8963941Svenki sun4v_env_print_temp_sensors(); 8973941Svenki 8983941Svenki class_node_found = 0; 8993941Svenki all_status_ok = 1; 9003941Svenki sun4v_env_print_temp_indicators(); 9013941Svenki 9023941Svenki class_node_found = 0; 9033941Svenki all_status_ok = 1; 9043941Svenki sun4v_env_print_current_sensors(); 9053941Svenki 9063941Svenki class_node_found = 0; 9073941Svenki all_status_ok = 1; 9083941Svenki sun4v_env_print_current_indicators(); 9093941Svenki 9103941Svenki class_node_found = 0; 9113941Svenki all_status_ok = 1; 9123941Svenki sun4v_env_print_voltage_sensors(); 9133941Svenki 9143941Svenki class_node_found = 0; 9153941Svenki all_status_ok = 1; 9163941Svenki sun4v_env_print_voltage_indicators(); 9173941Svenki 9183941Svenki class_node_found = 0; 9193941Svenki sun4v_env_print_LEDs(); 9203941Svenki 9213941Svenki class_node_found = 0; 9223941Svenki all_status_ok = 1; 9233941Svenki sun4v_print_fru_status(); 9243941Svenki 9253941Svenki class_node_found = 0; 9263941Svenki sun4v_print_fw_rev(); 9273941Svenki 9283941Svenki sun4v_print_chassis_serial_no(); 9293941Svenki } 9303941Svenki 9313941Svenki /*ARGSUSED*/ 9323941Svenki static int 9333941Svenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args) 9343941Svenki { 9353941Svenki char val[PICL_PROPNAMELEN_MAX]; 9363941Svenki picl_nodehdl_t parenth; 9373941Svenki char *names[PARENT_NAMES]; 9384802Sfw157321 char *base_units[PICL_PROPNAMELEN_MAX]; 9393941Svenki char *loc; 9403941Svenki int i; 9413941Svenki char *prop; 9423941Svenki picl_errno_t err; 9433941Svenki int32_t lo_warning, lo_shutdown; 9443941Svenki int32_t hi_warning, hi_shutdown; 9453941Svenki int32_t current_val; 9464802Sfw157321 int32_t exponent; 9474802Sfw157321 double display_val; 948*4928Sfw157321 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 949*4928Sfw157321 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 950*4928Sfw157321 sensor_status_t sensor_status = SENSOR_OK; 9513941Svenki 9523941Svenki if (class_node_found == 0) { 9533941Svenki class_node_found = 1; 9543941Svenki return (PICL_WALK_TERMINATE); 9553941Svenki } 9563941Svenki 957*4928Sfw157321 prop = (char *)args; 958*4928Sfw157321 if (!prop) { 959*4928Sfw157321 sensor_status = SENSOR_UNKNOWN; 960*4928Sfw157321 all_status_ok = 0; 961*4928Sfw157321 } else { 9623941Svenki err = picl_get_propval_by_name(nodeh, 9634669Sfw157321 PICL_PROP_OPERATIONAL_STATUS, val, 9644669Sfw157321 sizeof (val)); 9653941Svenki if (err == PICL_SUCCESS) { 9663941Svenki if (strcmp(val, "disabled") == 0) { 967*4928Sfw157321 sensor_status = SENSOR_DISABLED; 968*4928Sfw157321 } 969*4928Sfw157321 } 970*4928Sfw157321 } 971*4928Sfw157321 972*4928Sfw157321 if (sensor_status != SENSOR_DISABLED && 973*4928Sfw157321 sensor_status != SENSOR_UNKNOWN) { 974*4928Sfw157321 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 975*4928Sfw157321 sizeof (current_val)) != PICL_SUCCESS) { 976*4928Sfw157321 sensor_status = SENSOR_UNKNOWN; 977*4928Sfw157321 } 978*4928Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_WARNING, 979*4928Sfw157321 &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS) 980*4928Sfw157321 lo_warning = INVALID_THRESHOLD; 981*4928Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_SHUTDOWN, 982*4928Sfw157321 &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS) 983*4928Sfw157321 lo_shutdown = INVALID_THRESHOLD; 984*4928Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_WARNING, 985*4928Sfw157321 &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS) 986*4928Sfw157321 hi_warning = INVALID_THRESHOLD; 987*4928Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_SHUTDOWN, 988*4928Sfw157321 &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS) 989*4928Sfw157321 hi_shutdown = INVALID_THRESHOLD; 990*4928Sfw157321 991*4928Sfw157321 if ((lo_shutdown != INVALID_THRESHOLD && 992*4928Sfw157321 current_val <= lo_shutdown) || 993*4928Sfw157321 (hi_shutdown != INVALID_THRESHOLD && 994*4928Sfw157321 current_val >= hi_shutdown)) { 995*4928Sfw157321 sensor_status = SENSOR_FAILED; 996*4928Sfw157321 } else if ((lo_warning != INVALID_THRESHOLD && 997*4928Sfw157321 current_val <= lo_warning) || 998*4928Sfw157321 (hi_warning != INVALID_THRESHOLD && 999*4928Sfw157321 current_val >= hi_warning)) { 1000*4928Sfw157321 sensor_status = SENSOR_WARN; 10013941Svenki } else { 1002*4928Sfw157321 sensor_status = SENSOR_OK; 1003*4928Sfw157321 } 1004*4928Sfw157321 } 1005*4928Sfw157321 1006*4928Sfw157321 if (syserrlog == 0) { 1007*4928Sfw157321 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 10083941Svenki all_status_ok = 0; 10093941Svenki return (PICL_WALK_TERMINATE); 10103941Svenki } 1011*4928Sfw157321 if (sensor_status == SENSOR_OK) { 1012*4928Sfw157321 return (PICL_WALK_CONTINUE); 1013*4928Sfw157321 } 10143941Svenki } 1015*4928Sfw157321 1016*4928Sfw157321 /* 1017*4928Sfw157321 * If we're here then prtdiag was invoked with "-v" or we have 1018*4928Sfw157321 * a sensor that is beyond a threshold, so give them a book to 1019*4928Sfw157321 * read instead of the Cliff Notes. 1020*4928Sfw157321 */ 10213941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 10224669Sfw157321 sizeof (parenth)); 10233941Svenki if (err != PICL_SUCCESS) { 10243941Svenki log_printf("\n"); 10253941Svenki return (PICL_WALK_CONTINUE); 10263941Svenki } 10274003Svivek 1028*4928Sfw157321 /* gather up the path name for the sensor */ 1029*4928Sfw157321 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 1030*4928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) { 1031*4928Sfw157321 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 1032*4928Sfw157321 NULL) { 1033*4928Sfw157321 while (--i > -1) 1034*4928Sfw157321 free(names[i]); 1035*4928Sfw157321 free(loc); 1036*4928Sfw157321 loc = NULL; 1037*4928Sfw157321 } 10383941Svenki } 10394003Svivek } 1040*4928Sfw157321 i = 0; 1041*4928Sfw157321 if (loc != 0) { 1042*4928Sfw157321 while (err == PICL_SUCCESS) { 1043*4928Sfw157321 if (parenth == phyplatformh) 1044*4928Sfw157321 break; 1045*4928Sfw157321 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1046*4928Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 1047*4928Sfw157321 if (err != PICL_SUCCESS) { 1048*4928Sfw157321 i--; 1049*4928Sfw157321 break; 1050*4928Sfw157321 } 1051*4928Sfw157321 if (i == PARENT_NAMES) 1052*4928Sfw157321 break; 1053*4928Sfw157321 err = picl_get_propval_by_name(parenth, 1054*4928Sfw157321 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 1055*4928Sfw157321 } 1056*4928Sfw157321 loc[0] = '\0'; 1057*4928Sfw157321 if (--i > -1) { 1058*4928Sfw157321 (void) strlcat(loc, names[i], 1059*4928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1060*4928Sfw157321 } 1061*4928Sfw157321 while (--i > -1) { 1062*4928Sfw157321 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 1063*4928Sfw157321 PARENT_NAMES); 1064*4928Sfw157321 (void) strlcat(loc, names[i], 1065*4928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1066*4928Sfw157321 } 1067*4928Sfw157321 log_printf("%-31s", loc); 1068*4928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) 1069*4928Sfw157321 free(names[i]); 1070*4928Sfw157321 free(loc); 1071*4928Sfw157321 } else { 1072*4928Sfw157321 log_printf("%-31s", " "); 10733941Svenki } 10743941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 10754669Sfw157321 sizeof (val)); 10763941Svenki if (err == PICL_SUCCESS) 10773941Svenki log_printf("%-15s", val); 10783941Svenki 1079*4928Sfw157321 /* 1080*4928Sfw157321 * Get the exponent if present, and do a little math so that 1081*4928Sfw157321 * if we need to we can print a normalized value for the 1082*4928Sfw157321 * sensor reading. 1083*4928Sfw157321 */ 10844802Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT, 10854802Sfw157321 &exponent, sizeof (exponent)) != PICL_SUCCESS) 10864802Sfw157321 exponent = 0; 10874802Sfw157321 if (exponent == 0) 10884802Sfw157321 display_val = (double)current_val; 10894802Sfw157321 else 10904802Sfw157321 display_val = (double)current_val * 10914802Sfw157321 pow((double)10, (double)exponent); 1092*4928Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS, 1093*4928Sfw157321 base_units, sizeof (base_units)); 10944802Sfw157321 if (err != PICL_SUCCESS) 10954802Sfw157321 base_units[0] = '\0'; 10963941Svenki 1097*4928Sfw157321 switch (sensor_status) { 1098*4928Sfw157321 case SENSOR_FAILED: 10993941Svenki log_printf("%-s", "failed ("); 11004802Sfw157321 log_printf("%-.*f", abs(exponent), display_val); 11014802Sfw157321 log_printf("%-s %s", base_units, ")"); 1102*4928Sfw157321 break; 1103*4928Sfw157321 case SENSOR_WARN: 11043941Svenki log_printf("%-s", "warning ("); 11054802Sfw157321 log_printf("%-.*f", abs(exponent), display_val); 11064802Sfw157321 log_printf("%-s %s", base_units, ")"); 1107*4928Sfw157321 break; 1108*4928Sfw157321 case SENSOR_DISABLED: 1109*4928Sfw157321 log_printf("%-s", "disabled"); 1110*4928Sfw157321 break; 1111*4928Sfw157321 case SENSOR_OK: 11123941Svenki log_printf("%-s", "ok"); 1113*4928Sfw157321 break; 1114*4928Sfw157321 default: 1115*4928Sfw157321 log_printf("%-s", "unknown"); 1116*4928Sfw157321 break; 1117*4928Sfw157321 } 11183941Svenki 11193941Svenki log_printf("\n"); 11203941Svenki return (PICL_WALK_CONTINUE); 11213941Svenki } 11223941Svenki 11233941Svenki /*ARGSUSED*/ 11243941Svenki static int 11253941Svenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args) 11263941Svenki { 1127*4928Sfw157321 char current_val[PICL_PROPNAMELEN_MAX]; 1128*4928Sfw157321 char expected_val[PICL_PROPNAMELEN_MAX]; 1129*4928Sfw157321 char label[PICL_PROPNAMELEN_MAX]; 11303941Svenki picl_nodehdl_t parenth; 11313941Svenki char *names[PARENT_NAMES]; 11323941Svenki char *loc; 11333941Svenki int i = 0; 11343941Svenki char *prop = (char *)args; 11353941Svenki picl_errno_t err = PICL_SUCCESS; 1136*4928Sfw157321 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 1137*4928Sfw157321 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 1138*4928Sfw157321 sensor_status_t sensor_status = SENSOR_OK; 11393941Svenki 11403941Svenki if (class_node_found == 0) { 11413941Svenki class_node_found = 1; 11423941Svenki return (PICL_WALK_TERMINATE); 11433941Svenki } 1144*4928Sfw157321 1145*4928Sfw157321 prop = (char *)args; 1146*4928Sfw157321 if (!prop) { 1147*4928Sfw157321 sensor_status = SENSOR_UNKNOWN; 1148*4928Sfw157321 all_status_ok = 0; 1149*4928Sfw157321 } else { 11503941Svenki err = picl_get_propval_by_name(nodeh, 1151*4928Sfw157321 PICL_PROP_OPERATIONAL_STATUS, current_val, 1152*4928Sfw157321 sizeof (current_val)); 11533941Svenki if (err == PICL_SUCCESS) { 1154*4928Sfw157321 if (strcmp(current_val, "disabled") == 0) { 1155*4928Sfw157321 sensor_status = SENSOR_DISABLED; 1156*4928Sfw157321 } 1157*4928Sfw157321 } 1158*4928Sfw157321 } 1159*4928Sfw157321 1160*4928Sfw157321 if (sensor_status != SENSOR_DISABLED && 1161*4928Sfw157321 sensor_status != SENSOR_UNKNOWN) { 1162*4928Sfw157321 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 1163*4928Sfw157321 sizeof (current_val)) != PICL_SUCCESS) { 1164*4928Sfw157321 (void) strlcpy(current_val, "unknown", 1165*4928Sfw157321 sizeof (current_val)); 1166*4928Sfw157321 sensor_status = SENSOR_UNKNOWN; 1167*4928Sfw157321 } else { 1168*4928Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED, 1169*4928Sfw157321 &expected_val, sizeof (expected_val)) != 1170*4928Sfw157321 PICL_SUCCESS) { 1171*4928Sfw157321 sensor_status = SENSOR_UNKNOWN; 1172*4928Sfw157321 } else { 1173*4928Sfw157321 if (strncmp(current_val, expected_val, 1174*4928Sfw157321 sizeof (current_val)) == 0) { 1175*4928Sfw157321 sensor_status = SENSOR_OK; 1176*4928Sfw157321 } else { 1177*4928Sfw157321 sensor_status = SENSOR_FAILED; 11783941Svenki } 1179*4928Sfw157321 } 1180*4928Sfw157321 } 1181*4928Sfw157321 } 1182*4928Sfw157321 1183*4928Sfw157321 if (syserrlog == 0) { 1184*4928Sfw157321 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 11853941Svenki all_status_ok = 0; 11863941Svenki return (PICL_WALK_TERMINATE); 11873941Svenki } 1188*4928Sfw157321 if (sensor_status == SENSOR_OK) { 1189*4928Sfw157321 return (PICL_WALK_CONTINUE); 1190*4928Sfw157321 } 11913941Svenki } 1192*4928Sfw157321 1193*4928Sfw157321 /* 1194*4928Sfw157321 * If we're here then prtdiag was invoked with "-v" or we have 1195*4928Sfw157321 * a sensor that is beyond a threshold, so give them a book to 1196*4928Sfw157321 * read instead of the Cliff Notes. 1197*4928Sfw157321 */ 11983941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 11994669Sfw157321 sizeof (parenth)); 12003941Svenki if (err != PICL_SUCCESS) { 12013941Svenki log_printf("\n"); 12023941Svenki return (PICL_WALK_CONTINUE); 12033941Svenki } 1204*4928Sfw157321 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 1205*4928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) { 1206*4928Sfw157321 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 1207*4928Sfw157321 NULL) { 1208*4928Sfw157321 while (--i > -1) 1209*4928Sfw157321 free(names[i]); 1210*4928Sfw157321 free(loc); 1211*4928Sfw157321 loc = NULL; 1212*4928Sfw157321 } 12133941Svenki } 12143941Svenki } 1215*4928Sfw157321 i = 0; 1216*4928Sfw157321 if (loc) { 1217*4928Sfw157321 while (err == PICL_SUCCESS) { 1218*4928Sfw157321 if (parenth == phyplatformh) 1219*4928Sfw157321 break; 1220*4928Sfw157321 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1221*4928Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 1222*4928Sfw157321 if (err != PICL_SUCCESS) { 1223*4928Sfw157321 i--; 1224*4928Sfw157321 break; 1225*4928Sfw157321 } 1226*4928Sfw157321 if (i == PARENT_NAMES) 1227*4928Sfw157321 break; 1228*4928Sfw157321 err = picl_get_propval_by_name(parenth, 1229*4928Sfw157321 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 1230*4928Sfw157321 } 1231*4928Sfw157321 loc[0] = '\0'; 1232*4928Sfw157321 if (--i > -1) { 1233*4928Sfw157321 (void) strlcat(loc, names[i], 1234*4928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1235*4928Sfw157321 } 1236*4928Sfw157321 while (--i > -1) { 1237*4928Sfw157321 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 1238*4928Sfw157321 PARENT_NAMES); 1239*4928Sfw157321 (void) strlcat(loc, names[i], 1240*4928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1241*4928Sfw157321 } 1242*4928Sfw157321 log_printf("%-31s", loc); 1243*4928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) 1244*4928Sfw157321 free(names[i]); 1245*4928Sfw157321 free(loc); 1246*4928Sfw157321 } else { 1247*4928Sfw157321 log_printf("%-31s", ""); 12483941Svenki } 1249*4928Sfw157321 1250*4928Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 1251*4928Sfw157321 sizeof (label)); 1252*4928Sfw157321 if (err != PICL_SUCCESS) 1253*4928Sfw157321 (void) strlcpy(label, "", sizeof (label)); 1254*4928Sfw157321 log_printf("%-15s", label); 1255*4928Sfw157321 1256*4928Sfw157321 log_printf("%-8s", current_val); 1257*4928Sfw157321 12583941Svenki log_printf("\n"); 12593941Svenki return (PICL_WALK_CONTINUE); 12603941Svenki } 12613941Svenki 12623941Svenki static void 12633941Svenki sun4v_env_print_fan_sensors() 12643941Svenki { 12654802Sfw157321 char *fmt = "%-30s %-14s %-10s\n"; 12663941Svenki /* 12673941Svenki * If there isn't any fan sensor node, return now. 12683941Svenki */ 12693941Svenki (void) picl_walk_tree_by_class(phyplatformh, 1270*4928Sfw157321 PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED, 12714669Sfw157321 sun4v_env_print_sensor_callback); 12723941Svenki if (!class_node_found) 12733941Svenki return; 12743941Svenki log_printf("Fan sensors:\n"); 12753941Svenki if (syserrlog == 0) { 12763941Svenki (void) picl_walk_tree_by_class(phyplatformh, 12774669Sfw157321 PICL_CLASS_RPM_SENSOR, 1278*4928Sfw157321 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 12793941Svenki if (all_status_ok) { 12803941Svenki log_printf("All fan sensors are OK.\n"); 12813941Svenki return; 12823941Svenki } 12833941Svenki } 12844802Sfw157321 log_printf("----------------------------------------------------\n"); 12853941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 12864802Sfw157321 log_printf("----------------------------------------------------\n"); 12873941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR, 12884669Sfw157321 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 12893941Svenki } 12903941Svenki 12913941Svenki static void 12923941Svenki sun4v_env_print_fan_indicators() 12933941Svenki { 12944802Sfw157321 char *fmt = "%-30s %-14s %-10s\n"; 12953941Svenki (void) picl_walk_tree_by_class(phyplatformh, 1296*4928Sfw157321 PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION, 12974669Sfw157321 sun4v_env_print_indicator_callback); 12983941Svenki if (!class_node_found) 12993941Svenki return; 13003941Svenki log_printf("\nFan indicators:\n"); 13013941Svenki if (syserrlog == 0) { 13023941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13034669Sfw157321 PICL_CLASS_RPM_INDICATOR, 1304*4928Sfw157321 (void *)PICL_PROP_CONDITION, 1305*4928Sfw157321 sun4v_env_print_indicator_callback); 13063941Svenki if (all_status_ok) { 13073941Svenki log_printf("All fan indicators are OK.\n"); 13083941Svenki return; 13093941Svenki } 13103941Svenki } 13114802Sfw157321 log_printf("-------------------------------------------------------\n"); 13123941Svenki log_printf(fmt, "Location", "Sensor", "Condition", 0); 13134802Sfw157321 log_printf("-------------------------------------------------------\n"); 13143941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR, 13154802Sfw157321 (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback); 13163941Svenki } 13173941Svenki 13183941Svenki static void 13193941Svenki sun4v_env_print_temp_sensors() 13203941Svenki { 13214802Sfw157321 char *fmt = "%-30s %-14s %-10s\n"; 13223941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13234669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 13244669Sfw157321 (void *)PICL_PROP_TEMPERATURE, 13254669Sfw157321 sun4v_env_print_sensor_callback); 13263941Svenki if (!class_node_found) 13273941Svenki return; 13283941Svenki 13293941Svenki log_printf("\nTemperature sensors:\n"); 13303941Svenki if (syserrlog == 0) { 13313941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13324669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 1333*4928Sfw157321 PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 13343941Svenki if (all_status_ok) { 13353941Svenki log_printf("All temperature sensors are OK.\n"); 13363941Svenki return; 13373941Svenki } 13383941Svenki } 13394802Sfw157321 log_printf("----------------------------------------------------\n"); 13403941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 13414802Sfw157321 log_printf("----------------------------------------------------\n"); 13423941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13434669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 13444669Sfw157321 (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 13453941Svenki } 13463941Svenki 13473941Svenki static void 13483941Svenki sun4v_env_print_temp_indicators() 13493941Svenki { 13504802Sfw157321 char *fmt = "%-30s %-14s %-8s\n"; 13513941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13524669Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION, 13534669Sfw157321 sun4v_env_print_indicator_callback); 13543941Svenki if (!class_node_found) 13553941Svenki return; 13563941Svenki log_printf("\nTemperature indicators:\n"); 13573941Svenki if (syserrlog == 0) { 13583941Svenki (void) picl_walk_tree_by_class(phyplatformh, 1359*4928Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, 1360*4928Sfw157321 (void *)PICL_PROP_CONDITION, 13614669Sfw157321 sun4v_env_print_indicator_callback); 13623941Svenki if (all_status_ok) { 13633941Svenki log_printf("All temperature indicators are OK.\n"); 13643941Svenki return; 13653941Svenki } 13663941Svenki } 13674802Sfw157321 log_printf("-------------------------------------------------\n"); 13683941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 13694802Sfw157321 log_printf("-------------------------------------------------\n"); 13703941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13714669Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, 13724669Sfw157321 (void *)PICL_PROP_CONDITION, 13734669Sfw157321 sun4v_env_print_indicator_callback); 13743941Svenki } 13753941Svenki 13763941Svenki static void 13773941Svenki sun4v_env_print_current_sensors() 13783941Svenki { 13794802Sfw157321 char *fmt = "%-30s %-14s %-10s\n"; 13803941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR, 13814669Sfw157321 (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 13823941Svenki if (!class_node_found) 13833941Svenki return; 13843941Svenki log_printf("\nCurrent sensors:\n"); 13853941Svenki if (syserrlog == 0) { 13863941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13874669Sfw157321 PICL_CLASS_CURRENT_SENSOR, 1388*4928Sfw157321 PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 13893941Svenki if (all_status_ok) { 13903941Svenki log_printf("All current sensors are OK.\n"); 13913941Svenki return; 13923941Svenki } 13933941Svenki } 13944802Sfw157321 log_printf("----------------------------------------------------\n"); 13953941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 13964802Sfw157321 log_printf("----------------------------------------------------\n"); 13973941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13984669Sfw157321 PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT, 13994669Sfw157321 sun4v_env_print_sensor_callback); 14003941Svenki } 14013941Svenki 14023941Svenki static void 14033941Svenki sun4v_env_print_current_indicators() 14043941Svenki { 14054802Sfw157321 char *fmt = "%-30s %-14s %-8s\n"; 14063941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14074669Sfw157321 PICL_CLASS_CURRENT_INDICATOR, 14084669Sfw157321 (void *)PICL_PROP_CONDITION, 14094669Sfw157321 sun4v_env_print_indicator_callback); 14103941Svenki if (!class_node_found) 14113941Svenki return; 14123941Svenki log_printf("\nCurrent indicators:\n"); 14133941Svenki if (syserrlog == 0) { 14143941Svenki (void) picl_walk_tree_by_class(phyplatformh, 1415*4928Sfw157321 PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION, 14164669Sfw157321 sun4v_env_print_indicator_callback); 14173941Svenki if (all_status_ok) { 14183941Svenki log_printf("All current indicators are OK.\n"); 14193941Svenki return; 14203941Svenki } 14213941Svenki } 14224802Sfw157321 log_printf("-------------------------------------------------------\n"); 14233941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 14244802Sfw157321 log_printf("-------------------------------------------------------\n"); 14253941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14264669Sfw157321 PICL_CLASS_CURRENT_INDICATOR, 14274669Sfw157321 (void *)PICL_PROP_CONDITION, 14284669Sfw157321 sun4v_env_print_indicator_callback); 14293941Svenki } 14303941Svenki 14313941Svenki static void 14323941Svenki sun4v_env_print_voltage_sensors() 14333941Svenki { 14344802Sfw157321 char *fmt = "%-30s %-14s %-10s\n"; 14353941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14364669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 14374669Sfw157321 PICL_PROP_VOLTAGE, 14384669Sfw157321 sun4v_env_print_sensor_callback); 14393941Svenki if (!class_node_found) 14403941Svenki return; 14413941Svenki log_printf("\nVoltage sensors:\n"); 14423941Svenki if (syserrlog == 0) { 14433941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14444669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 1445*4928Sfw157321 PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback); 14463941Svenki if (all_status_ok) { 14473941Svenki log_printf("All voltage sensors are OK.\n"); 14483941Svenki return; 14493941Svenki } 14503941Svenki } 14514802Sfw157321 log_printf("----------------------------------------------------\n"); 14523941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 14534802Sfw157321 log_printf("----------------------------------------------------\n"); 14543941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14554669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 14564669Sfw157321 (void *)PICL_PROP_VOLTAGE, 14574669Sfw157321 sun4v_env_print_sensor_callback); 14583941Svenki } 14593941Svenki 14603941Svenki static void 14613941Svenki sun4v_env_print_voltage_indicators() 14623941Svenki { 14634802Sfw157321 char *fmt = "%-30s %-14s %-8s\n"; 14643941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14654669Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, 14664669Sfw157321 (void *)PICL_PROP_CONDITION, 14674669Sfw157321 sun4v_env_print_indicator_callback); 14683941Svenki if (!class_node_found) 14693941Svenki return; 14703941Svenki log_printf("\nVoltage indicators:\n"); 14713941Svenki if (syserrlog == 0) { 14723941Svenki (void) picl_walk_tree_by_class(phyplatformh, 1473*4928Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION, 14744669Sfw157321 sun4v_env_print_indicator_callback); 14753941Svenki if (all_status_ok) { 14763941Svenki log_printf("All voltage indicators are OK.\n"); 14773941Svenki return; 14783941Svenki } 14793941Svenki } 14804802Sfw157321 log_printf("-------------------------------------------------------\n"); 14813941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 14824802Sfw157321 log_printf("-------------------------------------------------------\n"); 14833941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14844669Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, 14854669Sfw157321 (void *)PICL_PROP_CONDITION, 14864669Sfw157321 sun4v_env_print_indicator_callback); 14873941Svenki } 14883941Svenki 14893941Svenki static void 14903941Svenki sun4v_env_print_LEDs() 14913941Svenki { 14924802Sfw157321 char *fmt = "%-30s %-14s %-8s\n"; 14933941Svenki if (syserrlog == 0) 14943941Svenki return; 14953941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 14964669Sfw157321 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 14973941Svenki if (!class_node_found) 14983941Svenki return; 14993941Svenki log_printf("\nLEDs:\n"); 15004802Sfw157321 log_printf("---------------------------------------------------\n"); 15013941Svenki log_printf(fmt, "Location", "LED", "State", 0); 15024802Sfw157321 log_printf("---------------------------------------------------\n"); 15033941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 15044669Sfw157321 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 15053941Svenki } 15063941Svenki 15073941Svenki /*ARGSUSED*/ 15083941Svenki static int 15093941Svenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args) 15103941Svenki { 15113941Svenki char label[PICL_PROPNAMELEN_MAX]; 15123941Svenki char status[PICL_PROPNAMELEN_MAX]; 15133941Svenki picl_errno_t err; 15143941Svenki picl_prophdl_t proph; 15153941Svenki picl_nodehdl_t parenth; 15163941Svenki char *names[PARENT_NAMES]; 15173941Svenki char *loc; 15183941Svenki int i; 15193941Svenki 15203941Svenki if (!class_node_found) { 15213941Svenki class_node_found = 1; 15223941Svenki return (PICL_WALK_TERMINATE); 15233941Svenki } 15243941Svenki err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph); 15253941Svenki if (err != PICL_SUCCESS) 15263941Svenki return (PICL_WALK_CONTINUE); 15273941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 15284669Sfw157321 sizeof (label)); 15293941Svenki if (err != PICL_SUCCESS) 15303941Svenki return (PICL_WALK_CONTINUE); 15313941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS, 15324669Sfw157321 status, sizeof (status)); 15333941Svenki if (err != PICL_SUCCESS) 15343941Svenki return (PICL_WALK_CONTINUE); 15353941Svenki if (syserrlog == 0) { 15363941Svenki if (strcmp(status, "disabled") == 0) { 15373941Svenki if (all_status_ok) { 15383941Svenki all_status_ok = 0; 15393941Svenki return (PICL_WALK_TERMINATE); 15403941Svenki } 15413941Svenki } else 15423941Svenki return (PICL_WALK_CONTINUE); 15433941Svenki } 15443941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 15454669Sfw157321 sizeof (parenth)); 15463941Svenki if (err != PICL_SUCCESS) { 15473941Svenki log_printf("\n"); 15483941Svenki return (PICL_WALK_CONTINUE); 15493941Svenki } 15503941Svenki if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL) 15513941Svenki return (PICL_WALK_TERMINATE); 15523941Svenki for (i = 0; i < PARENT_NAMES; i++) 15533941Svenki if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) { 15543941Svenki while (--i > -1) 15553941Svenki free(names[i]); 15563941Svenki free(loc); 15573941Svenki return (PICL_WALK_TERMINATE); 15583941Svenki } 15593941Svenki i = 0; 15603941Svenki while (err == PICL_SUCCESS) { 15614802Sfw157321 if (parenth == phyplatformh) 15623941Svenki break; 15633941Svenki err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 15644669Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 15653941Svenki if (err != PICL_SUCCESS) { 15663941Svenki i--; 15673941Svenki break; 15683941Svenki } 15693941Svenki if (i == PARENT_NAMES) 15703941Svenki break; 15713941Svenki err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT, 15724669Sfw157321 &parenth, sizeof (parenth)); 15733941Svenki } 15743941Svenki loc[0] = '\0'; 15754003Svivek if (--i > -1) { 15764003Svivek (void) strlcat(loc, names[i], 15774669Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 15784003Svivek } 15793941Svenki while (--i > -1) { 15804003Svivek (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES); 15814003Svivek (void) strlcat(loc, names[i], 15824669Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 15833941Svenki } 15844802Sfw157321 log_printf("%-31s", loc); 15853941Svenki for (i = 0; i < PARENT_NAMES; i++) 15863941Svenki free(names[i]); 15873941Svenki free(loc); 15883941Svenki log_printf("%-10s", label); 15893941Svenki log_printf("%-9s", status); 15903941Svenki log_printf("\n"); 15913941Svenki return (PICL_WALK_CONTINUE); 15923941Svenki } 15933941Svenki 15943941Svenki static void 15953941Svenki sun4v_print_fru_status() 15963941Svenki { 15974802Sfw157321 char *fmt = "%-30s %-9s %-8s\n"; 15983941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 15994669Sfw157321 sun4v_print_fru_status_callback); 16003941Svenki if (!class_node_found) 16013941Svenki return; 16023941Svenki log_printf("\n"); 16033941Svenki log_printf("============================"); 16043941Svenki log_printf(" FRU Status "); 16053941Svenki log_printf("============================"); 16063941Svenki log_printf("\n"); 16073941Svenki 16083941Svenki if (syserrlog == 0) { 16093941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16104802Sfw157321 NULL, NULL, 16114669Sfw157321 sun4v_print_fru_status_callback); 16123941Svenki if (all_status_ok) { 16133941Svenki log_printf("All FRUs are enabled.\n"); 16143941Svenki return; 16153941Svenki } 16163941Svenki } 16173941Svenki log_printf(fmt, "Location", "Name", "Status", 0); 16184802Sfw157321 log_printf("--------------------------------------------------\n"); 16194802Sfw157321 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 16204669Sfw157321 sun4v_print_fru_status_callback); 16213941Svenki } 16223941Svenki 16233941Svenki /*ARGSUSED*/ 16243941Svenki static int 16253941Svenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args) 16263941Svenki { 16273941Svenki char label[PICL_PROPNAMELEN_MAX]; 16283941Svenki char rev[PICL_PROPNAMELEN_MAX]; 16293941Svenki picl_errno_t err; 16303941Svenki 16313941Svenki if (!class_node_found) { 16323941Svenki class_node_found = 1; 16333941Svenki return (PICL_WALK_TERMINATE); 16343941Svenki } 16353941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 16364669Sfw157321 sizeof (label)); 16373941Svenki if (err != PICL_SUCCESS) 16383941Svenki return (PICL_WALK_CONTINUE); 16393941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev, 16404669Sfw157321 sizeof (rev)); 16413941Svenki if (err != PICL_SUCCESS) 16423941Svenki return (PICL_WALK_CONTINUE); 16433941Svenki if (strlen(rev) == 0) 16443941Svenki return (PICL_WALK_CONTINUE); 16453941Svenki log_printf("%-21s", label); 16463941Svenki log_printf("%-40s", rev); 16473941Svenki log_printf("\n"); 16483941Svenki return (PICL_WALK_CONTINUE); 16493941Svenki } 16503941Svenki 16513941Svenki static void 16523941Svenki sun4v_print_fw_rev() 16533941Svenki { 16543941Svenki char *fmt = "%-20s %-10s\n"; 16553941Svenki if (syserrlog == 0) 16563941Svenki return; 16573941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 16584669Sfw157321 sun4v_print_fw_rev_callback); 16593941Svenki if (!class_node_found) 16603941Svenki return; 16613941Svenki log_printf("\n"); 16623941Svenki log_printf("============================"); 16633941Svenki log_printf(" FW Version "); 16643941Svenki log_printf("============================"); 16653941Svenki log_printf("\n"); 16663941Svenki log_printf(fmt, "Name", "Version", 0); 16673941Svenki log_printf("----------------------------\n"); 16683941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 16694669Sfw157321 sun4v_print_fw_rev_callback); 16703941Svenki } 16713941Svenki 16723941Svenki static void 16733941Svenki sun4v_print_chassis_serial_no() 16743941Svenki { 16753941Svenki char val[PICL_PROPNAMELEN_MAX]; 16763941Svenki picl_errno_t err; 16773941Svenki if (syserrlog == 0 || chassish == 0) 16783941Svenki return; 16793941Svenki 16803941Svenki log_printf("\n"); 16813941Svenki log_printf("Chassis Serial Number"); 16823941Svenki log_printf("\n"); 16833941Svenki log_printf("---------------------\n"); 16843941Svenki err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER, 16854669Sfw157321 val, sizeof (val)); 16863941Svenki if (err == PICL_SUCCESS) 16873941Svenki log_printf("%s", val); 16883941Svenki log_printf("\n"); 16893941Svenki } 1690