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> 305436Sfw157321 #include <alloca.h> 311708Sstevel #include <unistd.h> 321708Sstevel #include <ctype.h> 331708Sstevel #include <string.h> 341708Sstevel #include <kvm.h> 351708Sstevel #include <varargs.h> 361708Sstevel #include <time.h> 371708Sstevel #include <dirent.h> 381708Sstevel #include <fcntl.h> 391708Sstevel #include <sys/param.h> 401708Sstevel #include <sys/stat.h> 411708Sstevel #include <sys/types.h> 421708Sstevel #include <sys/utsname.h> 431708Sstevel #include <sys/openpromio.h> 441708Sstevel #include <libintl.h> 451708Sstevel #include <syslog.h> 461708Sstevel #include <sys/dkio.h> 473941Svenki #include <sys/systeminfo.h> 483941Svenki #include <picldefs.h> 494802Sfw157321 #include <math.h> 504802Sfw157321 #include <errno.h> 511708Sstevel #include "pdevinfo.h" 521708Sstevel #include "display.h" 531708Sstevel #include "display_sun4v.h" 541708Sstevel #include "libprtdiag.h" 551708Sstevel 561708Sstevel #if !defined(TEXT_DOMAIN) 571708Sstevel #define TEXT_DOMAIN "SYS_TEST" 581708Sstevel #endif 591708Sstevel 604669Sfw157321 #define MOTHERBOARD "MB" 613941Svenki #define NETWORK "network" 623941Svenki #define PCIE_COMPATIBLE_STR "pciex" 633941Svenki #define PCIX_COMPATIBLE_STR "pci" 643941Svenki #define SUN4V_MACHINE "sun4v" 653941Svenki #define PARENT_NAMES 10 663941Svenki 673941Svenki /* 683941Svenki * Additional OBP properties 693941Svenki */ 703941Svenki #define OBP_PROP_COMPATIBLE "compatible" 713941Svenki #define OBP_PROP_MODEL "model" 723941Svenki #define OBP_PROP_SLOT_NAMES "slot-names" 735436Sfw157321 #define OBP_PROP_VERSION "version" 743941Svenki 753941Svenki #define PICL_NODE_PHYSICAL_PLATFORM "physical-platform" 763941Svenki #define PICL_NODE_CHASSIS "chassis" 773941Svenki #define MEMORY_SIZE_FIELD 11 783941Svenki #define INVALID_THRESHOLD 1000000 793941Svenki 803941Svenki /* 813941Svenki * Additional picl classes 823941Svenki */ 833941Svenki #ifndef PICL_CLASS_SUN4V 843941Svenki #define PICL_CLASS_SUN4V "sun4v" 853941Svenki #endif 863941Svenki 873941Svenki #ifndef PICL_PROP_NAC 883941Svenki #define PICL_PROP_NAC "nac" 893941Svenki #endif 903941Svenki 913941Svenki extern int sys_clk; 923941Svenki extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *, 933941Svenki picl_nodehdl_t *); 943941Svenki 953941Svenki static picl_nodehdl_t rooth = 0, phyplatformh = 0; 963941Svenki static picl_nodehdl_t chassish = 0; 973941Svenki static int class_node_found; 983941Svenki static int syserrlog; 993941Svenki static int all_status_ok; 1003941Svenki 1013941Svenki /* local functions */ 1023941Svenki static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **); 1033941Svenki static void sun4v_display_memory_conf(picl_nodehdl_t); 1043941Svenki static void sun4v_disp_env_status(); 1053941Svenki static void sun4v_env_print_fan_sensors(); 1063941Svenki static void sun4v_env_print_fan_indicators(); 1073941Svenki static void sun4v_env_print_temp_sensors(); 1083941Svenki static void sun4v_env_print_temp_indicators(); 1093941Svenki static void sun4v_env_print_current_sensors(); 1103941Svenki static void sun4v_env_print_current_indicators(); 1113941Svenki static void sun4v_env_print_voltage_sensors(); 1123941Svenki static void sun4v_env_print_voltage_indicators(); 1133941Svenki static void sun4v_env_print_LEDs(); 1143941Svenki static void sun4v_print_fru_status(); 1153941Svenki static void sun4v_print_fw_rev(); 1163941Svenki static void sun4v_print_chassis_serial_no(); 1175436Sfw157321 static int openprom_callback(picl_nodehdl_t openpromh, void *arg); 1185436Sfw157321 static void sun4v_print_openprom_rev(); 1191708Sstevel 1201708Sstevel int 1213941Svenki sun4v_display(Sys_tree *tree, Prom_node *root, int log, 1223941Svenki picl_nodehdl_t plafh) 1231708Sstevel { 1241708Sstevel void *value; /* used for opaque PROM data */ 1251708Sstevel struct mem_total memory_total; /* Total memory in system */ 1261708Sstevel struct grp_info grps; /* Info on all groups in system */ 1273941Svenki char machine[MAXSTRLEN]; 1283941Svenki 1293941Svenki if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1) 1303941Svenki return (1); 1313941Svenki if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0) 1323941Svenki return (1); 1331708Sstevel 1341708Sstevel sys_clk = -1; /* System clock freq. (in MHz) */ 1351708Sstevel 1361708Sstevel /* 1371708Sstevel * Now display the machine's configuration. We do this if we 1381708Sstevel * are not logging. 1391708Sstevel */ 1401708Sstevel if (!logging) { 1411708Sstevel struct utsname uts_buf; 1421708Sstevel 1431708Sstevel /* 1441708Sstevel * Display system banner 1451708Sstevel */ 1461708Sstevel (void) uname(&uts_buf); 1471708Sstevel 1483941Svenki log_printf(dgettext(TEXT_DOMAIN, "System Configuration: " 1494669Sfw157321 "Sun Microsystems %s %s\n"), uts_buf.machine, 1504669Sfw157321 get_prop_val(find_prop(root, "banner-name")), 0); 1511708Sstevel 1521708Sstevel /* display system clock frequency */ 1531708Sstevel value = get_prop_val(find_prop(root, "clock-frequency")); 1541708Sstevel if (value != NULL) { 1551708Sstevel sys_clk = ((*((int *)value)) + 500000) / 1000000; 1561708Sstevel log_printf(dgettext(TEXT_DOMAIN, "System clock " 1574669Sfw157321 "frequency: %d MHz\n"), sys_clk, 0); 1581708Sstevel } 1591708Sstevel 1601708Sstevel /* Display the Memory Size */ 1611708Sstevel display_memorysize(tree, NULL, &grps, &memory_total); 1621708Sstevel 1631708Sstevel /* Display the CPU devices */ 1641708Sstevel sun4v_display_cpu_devices(plafh); 1651708Sstevel 1661708Sstevel /* Display the Memory configuration */ 1673941Svenki class_node_found = 0; 1683941Svenki sun4v_display_memory_conf(plafh); 1691708Sstevel 1701708Sstevel /* Display all the IO cards. */ 1711708Sstevel (void) sun4v_display_pci(plafh); 1723941Svenki sun4v_display_diaginfo((log || (logging)), root, plafh); 1731708Sstevel 1743941Svenki if (picl_get_root(&rooth) != PICL_SUCCESS) 1753941Svenki return (1); 1763941Svenki if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM, 1774669Sfw157321 &phyplatformh) != PICL_SUCCESS) 1783941Svenki return (1); 1793941Svenki 1803941Svenki if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME, 1814669Sfw157321 PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS, 1824669Sfw157321 strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS) 1833941Svenki return (1); 1843941Svenki 1853941Svenki syserrlog = log; 1863941Svenki sun4v_disp_env_status(); 1873941Svenki } 1883941Svenki return (0); 1893941Svenki } 1903941Svenki 1913941Svenki static void 1923941Svenki get_bus_type(picl_nodehdl_t nodeh, struct io_card *card) 1933941Svenki { 1943941Svenki char *compatible; 1953941Svenki 1964003Svivek (void) strlcpy(card->bus_type, "PCIX", sizeof (card->bus_type)); 1973941Svenki if (sun4v_get_first_compatible_value(nodeh, &compatible) 1984669Sfw157321 == PICL_SUCCESS) { 1993941Svenki if (strncmp(compatible, PCIE_COMPATIBLE_STR, 2004669Sfw157321 strlen(PCIE_COMPATIBLE_STR)) == 0) 2014003Svivek (void) strlcpy(card->bus_type, "PCIE", 2024669Sfw157321 sizeof (card->bus_type)); 2033941Svenki free(compatible); 2043941Svenki } 2053941Svenki } 2063941Svenki 2073941Svenki static picl_errno_t 2083941Svenki get_slot_label(picl_nodehdl_t nodeh, struct io_card *card) 2093941Svenki { 2103941Svenki char val[PICL_PROPNAMELEN_MAX]; 2113941Svenki picl_errno_t err; 2125436Sfw157321 picl_nodehdl_t pnodeh; 2133941Svenki 2145436Sfw157321 /* 2155436Sfw157321 * Look for a Label first in the node corresponding to the IO 2165436Sfw157321 * device. If there's no Label then we might be on the downstream 2175436Sfw157321 * side of a bridge (i.e. the IO device/card has a bridge on it). 2185436Sfw157321 * So look at the parent and see if it has a Label. 2195436Sfw157321 */ 2203941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 2214669Sfw157321 sizeof (val)); 2225436Sfw157321 if (err == PICL_PROPNOTFOUND) { 2235436Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh, 2245436Sfw157321 sizeof (pnodeh)) == PICL_SUCCESS) 2255436Sfw157321 err = picl_get_propval_by_name(pnodeh, PICL_PROP_LABEL, 2265436Sfw157321 val, sizeof (val)); 2275436Sfw157321 } 2283941Svenki 2295436Sfw157321 if (err == PICL_SUCCESS) 2305436Sfw157321 (void) strlcpy(card->slot_str, val, sizeof (card->slot_str)); 2315436Sfw157321 2323941Svenki card->slot = -1; 2335436Sfw157321 return (err); 2343941Svenki } 2353941Svenki 2363941Svenki static void 2373941Svenki get_slot_number(picl_nodehdl_t nodeh, struct io_card *card) 2383941Svenki { 2393941Svenki picl_errno_t err; 2403941Svenki picl_prophdl_t proph; 2413941Svenki picl_propinfo_t pinfo; 2423941Svenki picl_nodehdl_t pnodeh; 2433941Svenki uint8_t *pval; 2443941Svenki uint32_t dev_mask; 2453941Svenki char uaddr[MAXSTRLEN]; 2463941Svenki int i; 2473941Svenki 2483941Svenki if (get_slot_label(nodeh, card) == PICL_SUCCESS) 2493941Svenki return; 2503941Svenki err = PICL_SUCCESS; 2513941Svenki while (err == PICL_SUCCESS) { 2523941Svenki if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh, 2534669Sfw157321 sizeof (pnodeh)) != PICL_SUCCESS) { 2544669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 2554669Sfw157321 sizeof (card->slot_str)); 2563941Svenki card->slot = -1; 2573941Svenki return; 2583941Svenki } 2593941Svenki if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES, 2604669Sfw157321 &pinfo, &proph) == PICL_SUCCESS) { 2613941Svenki break; 2623941Svenki } 2633941Svenki nodeh = pnodeh; 2643941Svenki } 2653941Svenki if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr, 2664669Sfw157321 sizeof (uaddr)) != PICL_SUCCESS) { 2674669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 2684669Sfw157321 sizeof (card->slot_str)); 2693941Svenki card->slot = -1; 2703941Svenki return; 2713941Svenki } 2723941Svenki pval = (uint8_t *)malloc(pinfo.size); 2733941Svenki if (!pval) { 2744669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 2754669Sfw157321 sizeof (card->slot_str)); 2763941Svenki card->slot = -1; 2773941Svenki return; 2783941Svenki } 2793941Svenki if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) { 2804669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 2814669Sfw157321 sizeof (card->slot_str)); 2823941Svenki card->slot = -1; 2833941Svenki free(pval); 2843941Svenki return; 2851708Sstevel } 2861708Sstevel 2873941Svenki dev_mask = 0; 2883941Svenki for (i = 0; i < sizeof (dev_mask); i++) 2893941Svenki dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i)); 2903941Svenki for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) { 2913941Svenki if (uaddr[i] == ',') { 2923941Svenki uaddr[i] = '\0'; 2933941Svenki break; 2943941Svenki } 2953941Svenki } 2963941Svenki card->slot = atol(uaddr); 2973941Svenki if (((1 << card->slot) & dev_mask) == 0) { 2984669Sfw157321 (void) strlcpy(card->slot_str, MOTHERBOARD, 2994669Sfw157321 sizeof (card->slot_str)); 3003941Svenki card->slot = -1; 3013941Svenki } else { 3023941Svenki char *p = (char *)(pval+sizeof (dev_mask)); 3033941Svenki int shift = sizeof (uint32_t)*8-1-card->slot; 3043941Svenki uint32_t x = (dev_mask << shift) >> shift; 3053941Svenki int count = 0; /* count # of 1's in x */ 3063941Svenki int i = 0; 3073941Svenki while (x != 0) { 3083941Svenki count++; 3093941Svenki x &= x-1; 3103941Svenki } 3113941Svenki while (count > 1) { 3124669Sfw157321 while (p[i++] != '\0') 3134669Sfw157321 ; 3143941Svenki count--; 3153941Svenki } 3164003Svivek (void) strlcpy(card->slot_str, (char *)(p+i), 3174669Sfw157321 sizeof (card->slot_str)); 3183941Svenki } 3193941Svenki free(pval); 3203941Svenki } 3213941Svenki 3223941Svenki /* 3233941Svenki * add all io devices under pci in io list 3243941Svenki */ 3253941Svenki /* ARGSUSED */ 3263941Svenki static int 3273941Svenki sun4v_pci_callback(picl_nodehdl_t pcih, void *args) 3283941Svenki { 3293941Svenki char path[PICL_PROPNAMELEN_MAX]; 3303941Svenki char class[PICL_CLASSNAMELEN_MAX]; 3313941Svenki char name[PICL_PROPNAMELEN_MAX]; 3323941Svenki char model[PICL_PROPNAMELEN_MAX]; 3333941Svenki char binding_name[PICL_PROPNAMELEN_MAX]; 3343941Svenki char val[PICL_PROPNAMELEN_MAX]; 3353941Svenki char *compatible; 3363941Svenki picl_errno_t err; 3373941Svenki picl_nodehdl_t nodeh; 3383941Svenki struct io_card pci_card; 3393941Svenki 3403941Svenki /* Walk through the children */ 3413941Svenki 3423941Svenki err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 3434669Sfw157321 sizeof (picl_nodehdl_t)); 3443941Svenki 3453941Svenki while (err == PICL_SUCCESS) { 3463941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 3474669Sfw157321 class, sizeof (class)); 3483941Svenki if (err != PICL_SUCCESS) 3493941Svenki return (err); 3503941Svenki 3513941Svenki if (args) { 3523941Svenki char *val = args; 3533941Svenki if (strcmp(class, val) == 0) { 3543941Svenki err = picl_get_propval_by_name(nodeh, 3554669Sfw157321 PICL_PROP_PEER, &nodeh, 3564669Sfw157321 sizeof (picl_nodehdl_t)); 3573941Svenki continue; 3583941Svenki } else if (strcmp(val, PICL_CLASS_PCIEX) == 0 && 3594669Sfw157321 strcmp(class, PICL_CLASS_PCI) == 0) { 3603941Svenki err = picl_get_propval_by_name(nodeh, 3614669Sfw157321 PICL_PROP_PEER, &nodeh, 3624669Sfw157321 sizeof (picl_nodehdl_t)); 3633941Svenki continue; 3643941Svenki } else if (strcmp(val, PICL_CLASS_PCI) == 0 && 3654669Sfw157321 strcmp(class, PICL_CLASS_PCIEX) == 0) { 3663941Svenki err = picl_get_propval_by_name(nodeh, 3674669Sfw157321 PICL_PROP_PEER, &nodeh, 3684669Sfw157321 sizeof (picl_nodehdl_t)); 3693941Svenki continue; 3703941Svenki } 3713941Svenki } 3723941Svenki 3733941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH, 3744669Sfw157321 path, sizeof (path)); 3753941Svenki if (err != PICL_SUCCESS) 3763941Svenki return (err); 3773941Svenki 3783941Svenki (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes)); 3793941Svenki 3803941Svenki get_bus_type(nodeh, &pci_card); 3813941Svenki get_slot_number(nodeh, &pci_card); 3823941Svenki 3833941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name, 3844669Sfw157321 sizeof (name)); 3853941Svenki if (err == PICL_PROPNOTFOUND) 3864003Svivek (void) strlcpy(name, "", sizeof (name)); 3873941Svenki else if (err != PICL_SUCCESS) 3883941Svenki return (err); 3893941Svenki 3903941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val, 3914669Sfw157321 sizeof (val)); 3923941Svenki if (err == PICL_PROPNOTFOUND) 3934003Svivek (void) strlcpy(val, "", sizeof (val)); 3943941Svenki else if (err != PICL_SUCCESS) 3953941Svenki return (err); 3963941Svenki 3975436Sfw157321 (void) snprintf(pci_card.status, sizeof (pci_card.status), 3985436Sfw157321 "%s", pci_card.slot_str); 3993941Svenki 4003941Svenki /* 4013941Svenki * Get the name of this card. If binding_name is found, 4023941Svenki * name will be <nodename>-<binding_name>. 4033941Svenki */ 4043941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, 4054669Sfw157321 binding_name, sizeof (binding_name)); 4063941Svenki if (err == PICL_SUCCESS) { 4073941Svenki if (strcmp(name, binding_name) != 0) { 4083941Svenki (void) strlcat(name, "-", sizeof (name)); 4093941Svenki (void) strlcat(name, binding_name, 4104669Sfw157321 sizeof (name)); 4113941Svenki } 4123941Svenki } else if (err == PICL_PROPNOTFOUND) { 4133941Svenki /* 4143941Svenki * if compatible prop is not found, name will be 4153941Svenki * <nodename>-<compatible> 4163941Svenki */ 4173941Svenki err = sun4v_get_first_compatible_value(nodeh, 4184669Sfw157321 &compatible); 4193941Svenki if (err == PICL_SUCCESS) { 4203941Svenki (void) strlcat(name, "-", sizeof (name)); 4214003Svivek (void) strlcat(name, compatible, 4224669Sfw157321 sizeof (name)); 4233941Svenki free(compatible); 4243941Svenki } 4253941Svenki } else 4263941Svenki return (err); 4273941Svenki 4283941Svenki (void) strlcpy(pci_card.name, name, sizeof (pci_card.name)); 4293941Svenki 4303941Svenki /* Get the model of this card */ 4313941Svenki 4323941Svenki err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL, 4334669Sfw157321 model, sizeof (model)); 4343941Svenki if (err == PICL_PROPNOTFOUND) 4354003Svivek (void) strlcpy(model, "", sizeof (model)); 4363941Svenki else if (err != PICL_SUCCESS) 4373941Svenki return (err); 4383941Svenki (void) strlcpy(pci_card.model, model, sizeof (pci_card.model)); 4393941Svenki 4403941Svenki /* Print NAC name */ 4414802Sfw157321 log_printf("%-18s", pci_card.status); 4423941Svenki /* Print IO Type */ 4433941Svenki log_printf("%-6s", pci_card.bus_type); 4443941Svenki /* Printf Card Name */ 445*5544Sfw157321 log_printf("%-34s", pci_card.name); 4463941Svenki /* Print Card Model */ 4473941Svenki log_printf("%-8s", pci_card.model); 4483941Svenki log_printf("\n"); 4493941Svenki /* Print Status */ 4504802Sfw157321 log_printf("%-18s", val); 4513941Svenki /* Print IO Type */ 4523941Svenki log_printf("%-6s", ""); 4533941Svenki /* Print Parent Path */ 4544802Sfw157321 log_printf("%-44s", pci_card.notes); 4553941Svenki log_printf("\n"); 4563941Svenki 4573941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 4584669Sfw157321 sizeof (picl_nodehdl_t)); 4593941Svenki } 4603941Svenki return (PICL_WALK_CONTINUE); 4611708Sstevel } 4621708Sstevel 4631708Sstevel /* 4641708Sstevel * display_pci 4651708Sstevel * Display all the PCI IO cards on this board. 4661708Sstevel */ 4671708Sstevel void 4681708Sstevel sun4v_display_pci(picl_nodehdl_t plafh) 4691708Sstevel { 470*5544Sfw157321 char *fmt = "%-17s %-5s %-33s %-8s"; 4713941Svenki /* Have we printed the column headings? */ 4723941Svenki static int banner = FALSE; 4733941Svenki 4743941Svenki if (banner == FALSE) { 4753941Svenki log_printf("\n"); 4764802Sfw157321 log_printf("================================"); 4773941Svenki log_printf(" IO Devices "); 4784802Sfw157321 log_printf("================================"); 4793941Svenki log_printf("\n"); 4803941Svenki log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0); 4813941Svenki log_printf("\n"); 4823941Svenki log_printf(fmt, "Status", "Type", "Path", "", 0); 4833941Svenki log_printf("\n"); 4843941Svenki log_printf("---------------------------------" 4854802Sfw157321 "-------------------------------------------\n"); 4863941Svenki banner = TRUE; 4873941Svenki } 4883941Svenki 4893941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, 4904669Sfw157321 PICL_CLASS_PCIEX, sun4v_pci_callback); 4913941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI, 4924669Sfw157321 PICL_CLASS_PCI, sun4v_pci_callback); 4933941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V, 4944669Sfw157321 PICL_CLASS_SUN4V, sun4v_pci_callback); 4953941Svenki } 4963941Svenki 4973941Svenki /* 4983941Svenki * return the first compatible value 4993941Svenki */ 5003941Svenki static int 5013941Svenki sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf) 5023941Svenki { 5033941Svenki picl_errno_t err; 5043941Svenki picl_prophdl_t proph; 5053941Svenki picl_propinfo_t pinfo; 5063941Svenki picl_prophdl_t tblh; 5073941Svenki picl_prophdl_t rowproph; 5083941Svenki char *pval; 5093941Svenki 5103941Svenki err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE, 5114669Sfw157321 &pinfo, &proph); 5123941Svenki if (err != PICL_SUCCESS) 5133941Svenki return (err); 5143941Svenki 5153941Svenki if (pinfo.type == PICL_PTYPE_CHARSTRING) { 5163941Svenki pval = malloc(pinfo.size); 5173941Svenki if (pval == NULL) 5183941Svenki return (PICL_FAILURE); 5193941Svenki err = picl_get_propval(proph, pval, pinfo.size); 5203941Svenki if (err != PICL_SUCCESS) { 5213941Svenki free(pval); 5223941Svenki return (err); 5233941Svenki } 5243941Svenki *outbuf = pval; 5253941Svenki return (PICL_SUCCESS); 5263941Svenki } 5273941Svenki 5283941Svenki if (pinfo.type != PICL_PTYPE_TABLE) 5293941Svenki return (PICL_FAILURE); 5303941Svenki 5313941Svenki /* get first string from table */ 5323941Svenki err = picl_get_propval(proph, &tblh, pinfo.size); 5333941Svenki if (err != PICL_SUCCESS) 5343941Svenki return (err); 5353941Svenki 5363941Svenki err = picl_get_next_by_row(tblh, &rowproph); 5373941Svenki if (err != PICL_SUCCESS) 5383941Svenki return (err); 5393941Svenki 5403941Svenki err = picl_get_propinfo(rowproph, &pinfo); 5413941Svenki if (err != PICL_SUCCESS) 5423941Svenki return (err); 5433941Svenki 5443941Svenki pval = malloc(pinfo.size); 5453941Svenki if (pval == NULL) 5463941Svenki return (PICL_FAILURE); 5473941Svenki 5483941Svenki err = picl_get_propval(rowproph, pval, pinfo.size); 5493941Svenki if (err != PICL_SUCCESS) { 5503941Svenki free(pval); 5513941Svenki return (err); 5523941Svenki } 5533941Svenki 5543941Svenki *outbuf = pval; 5553941Svenki return (PICL_SUCCESS); 5561708Sstevel } 5571708Sstevel 5583941Svenki /* 5593941Svenki * print size of a memory segment 5603941Svenki */ 5613941Svenki static void 5623941Svenki print_memory_segment_size(uint64_t size) 5633941Svenki { 5643941Svenki uint64_t kbyte = 1024; 5653941Svenki uint64_t mbyte = kbyte * kbyte; 5663941Svenki uint64_t gbyte = kbyte * mbyte; 567*5544Sfw157321 uint64_t tbyte = kbyte * gbyte; 5683941Svenki char buf[MEMORY_SIZE_FIELD]; 5693941Svenki 570*5544Sfw157321 if (size >= tbyte) { 571*5544Sfw157321 if (size % tbyte == 0) 572*5544Sfw157321 (void) snprintf(buf, sizeof (buf), "%d TB", 573*5544Sfw157321 (int)(size / tbyte)); 574*5544Sfw157321 else 575*5544Sfw157321 (void) snprintf(buf, sizeof (buf), "%.2f TB", 576*5544Sfw157321 (float)size / tbyte); 577*5544Sfw157321 } else if (size >= gbyte) { 5783941Svenki if (size % gbyte == 0) 5793941Svenki (void) snprintf(buf, sizeof (buf), "%d GB", 5804669Sfw157321 (int)(size / gbyte)); 5813941Svenki else 5823941Svenki (void) snprintf(buf, sizeof (buf), "%.2f GB", 5834669Sfw157321 (float)size / gbyte); 5843941Svenki } else if (size >= mbyte) { 5853941Svenki if (size % mbyte == 0) 5863941Svenki (void) snprintf(buf, sizeof (buf), "%d MB", 5874669Sfw157321 (int)(size / mbyte)); 5883941Svenki else 5893941Svenki (void) snprintf(buf, sizeof (buf), "%.2f MB", 5904669Sfw157321 (float)size / mbyte); 5913941Svenki } else { 5923941Svenki if (size % kbyte == 0) 5933941Svenki (void) snprintf(buf, sizeof (buf), "%d KB", 5944669Sfw157321 (int)(size / kbyte)); 5953941Svenki else 5963941Svenki (void) snprintf(buf, sizeof (buf), "%.2f KB", 5974669Sfw157321 (float)size / kbyte); 5983941Svenki } 599*5544Sfw157321 log_printf("%-9s", buf); 6003941Svenki } 6013941Svenki 6023941Svenki /* 6034669Sfw157321 * Enumerate banks and dimms within a memory segment. We're handed 6044669Sfw157321 * the first bank within the segment - we assume there are dimms 6054669Sfw157321 * (memory-module) nodes underneath. 6063941Svenki */ 6073941Svenki static void 6084669Sfw157321 print_memory_segment_contain(picl_nodehdl_t bank_nodeh) 6091708Sstevel { 6103941Svenki char val[PICL_PROPNAMELEN_MAX]; 6114669Sfw157321 picl_nodehdl_t module_nodeh; 6124669Sfw157321 int flag = 0; 613*5544Sfw157321 uint64_t size; 6144669Sfw157321 6154669Sfw157321 do { 6164669Sfw157321 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD, 6174669Sfw157321 &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS) 6184669Sfw157321 continue; 619*5544Sfw157321 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_SIZE, 620*5544Sfw157321 &size, sizeof (size)) == PICL_SUCCESS) { 621*5544Sfw157321 if (!flag) { 622*5544Sfw157321 print_memory_segment_size(size); 623*5544Sfw157321 } else { 624*5544Sfw157321 log_printf(" " 625*5544Sfw157321 " "); 626*5544Sfw157321 print_memory_segment_size(size); 627*5544Sfw157321 flag = 0; 628*5544Sfw157321 } 629*5544Sfw157321 } 6304669Sfw157321 do { 6314669Sfw157321 if (picl_get_propval_by_name(module_nodeh, 6324669Sfw157321 PICL_PROP_NAC, val, sizeof (val)) != 6334669Sfw157321 PICL_SUCCESS) 6344669Sfw157321 continue; 6354669Sfw157321 else { 6364669Sfw157321 if (!flag) { 637*5544Sfw157321 log_printf("%s\n", val); 6384669Sfw157321 flag = 1; 639*5544Sfw157321 } else { 640*5544Sfw157321 log_printf("%s%s\n", 641*5544Sfw157321 " " 642*5544Sfw157321 " ", 643*5544Sfw157321 val); 644*5544Sfw157321 } 6454669Sfw157321 } 6464669Sfw157321 } while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER, 6474669Sfw157321 &module_nodeh, sizeof (picl_nodehdl_t)) == 6484669Sfw157321 PICL_SUCCESS); 6494669Sfw157321 } while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER, 6504669Sfw157321 &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS); 6513941Svenki } 6523941Svenki 6533941Svenki /* 6543941Svenki * Search node where _class=="memory-segment" 6553941Svenki * print "Base Address", "Size", etc 6563941Svenki */ 6573941Svenki /*ARGSUSED*/ 6583941Svenki static int 6593941Svenki sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args) 6603941Svenki { 6613941Svenki uint64_t base; 6623941Svenki uint64_t size; 6633941Svenki uint64_t ifactor; 6643941Svenki picl_errno_t err = PICL_SUCCESS; 6653941Svenki 6663941Svenki if (class_node_found == 0) { 6673941Svenki class_node_found = 1; 6683941Svenki return (PICL_WALK_TERMINATE); 6693941Svenki } 6703941Svenki while (err == PICL_SUCCESS) { 6713941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS, 6724669Sfw157321 &base, sizeof (base)); 6733941Svenki if (err != PICL_SUCCESS) 6743941Svenki break; 6753941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE, 6764669Sfw157321 &size, sizeof (size)); 6773941Svenki if (err != PICL_SUCCESS) 6783941Svenki break; 6793941Svenki err = picl_get_propval_by_name(nodeh, 6804669Sfw157321 PICL_PROP_INTERLEAVE_FACTOR, &ifactor, 6814669Sfw157321 sizeof (ifactor)); 6823941Svenki if (err != PICL_SUCCESS) 6833941Svenki break; 684*5544Sfw157321 log_printf("0x%-13llx", base); 6853941Svenki print_memory_segment_size(size); 686*5544Sfw157321 log_printf("%-12lld", ifactor); 6874669Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, 6884669Sfw157321 &nodeh, sizeof (nodeh)); 6894669Sfw157321 if (err == PICL_SUCCESS) 6904669Sfw157321 print_memory_segment_contain(nodeh); 6913941Svenki log_printf("\n"); 6923941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 6934669Sfw157321 sizeof (picl_nodehdl_t)); 6943941Svenki } 6953941Svenki 6963941Svenki return (PICL_WALK_CONTINUE); 6973941Svenki } 6983941Svenki 6993941Svenki /*ARGSUSED*/ 7003941Svenki void 7013941Svenki sun4v_display_memory_conf(picl_nodehdl_t plafh) 7023941Svenki { 703*5544Sfw157321 char *fmt = "%-14s %-8s %-11s %-8s %-s"; 7043941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 7054669Sfw157321 NULL, sun4v_memory_conf_callback); 7063941Svenki if (class_node_found == 0) 7073941Svenki return; 7083941Svenki log_printf("\n"); 709*5544Sfw157321 log_printf("======================="); 710*5544Sfw157321 log_printf(" Physical Memory Configuration "); 711*5544Sfw157321 log_printf("========================"); 7123941Svenki log_printf("\n"); 7133941Svenki log_printf("Segment Table:\n"); 7144669Sfw157321 log_printf( 715*5544Sfw157321 "--------------------------------------------------------------\n"); 716*5544Sfw157321 log_printf(fmt, "Base", "Segment", "Interleave", "Bank", "Contains", 0); 717*5544Sfw157321 log_printf("\n"); 718*5544Sfw157321 log_printf(fmt, "Address", "Size", "Factor", "Size", "Modules", 0); 7193941Svenki log_printf("\n"); 7204669Sfw157321 log_printf( 721*5544Sfw157321 "--------------------------------------------------------------\n"); 7223941Svenki (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 7234669Sfw157321 NULL, sun4v_memory_conf_callback); 7241708Sstevel } 7251708Sstevel 7261708Sstevel void 7271708Sstevel sun4v_display_cpu_devices(picl_nodehdl_t plafh) 7281708Sstevel { 729*5544Sfw157321 char *fmt = "%-6s %-9s %-22s %-6s"; 7301708Sstevel 7311708Sstevel /* 7321708Sstevel * Display the table header for CPUs . Then display the CPU 7331708Sstevel * frequency, cache size, and processor revision of all cpus. 7341708Sstevel */ 7351708Sstevel log_printf(dgettext(TEXT_DOMAIN, 7364669Sfw157321 "\n" 737*5544Sfw157321 "================================" 738*5544Sfw157321 " Virtual CPUs " 739*5544Sfw157321 "================================" 7404669Sfw157321 "\n" 7414669Sfw157321 "\n")); 7421708Sstevel log_printf("\n"); 743*5544Sfw157321 log_printf(fmt, "CPU ID", "Frequency", "Implementation", 744*5544Sfw157321 "Status", 0); 7451708Sstevel log_printf("\n"); 746*5544Sfw157321 log_printf(fmt, "------", "---------", 747*5544Sfw157321 "----------------------", "-------", 0); 7481708Sstevel log_printf("\n"); 7491708Sstevel 750*5544Sfw157321 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU, 751*5544Sfw157321 sun4v_display_cpus); 7521708Sstevel } 7531708Sstevel 7541708Sstevel /* 7551708Sstevel * Display the CPUs present on this board. 7561708Sstevel */ 7571708Sstevel /*ARGSUSED*/ 7581708Sstevel int 7591708Sstevel sun4v_display_cpus(picl_nodehdl_t cpuh, void* args) 7601708Sstevel { 7611708Sstevel int status; 7623941Svenki picl_prophdl_t proph; 7633941Svenki picl_prophdl_t tblh; 7643941Svenki picl_prophdl_t rowproph; 7651708Sstevel picl_propinfo_t propinfo; 7663941Svenki int *int_value; 7675028Sfw157321 int cpuid; 7683941Svenki char *comp_value; 7693941Svenki char *no_prop_value = " "; 7703941Svenki char freq_str[MAXSTRLEN]; 7715028Sfw157321 char state[MAXSTRLEN]; 7721708Sstevel 7731708Sstevel /* 7741708Sstevel * Get cpuid property and print it and the NAC name 7751708Sstevel */ 776*5544Sfw157321 status = picl_get_propinfo_by_name(cpuh, OBP_PROP_CPUID, &propinfo, 777*5544Sfw157321 &proph); 7781708Sstevel if (status == PICL_SUCCESS) { 7791708Sstevel status = picl_get_propval(proph, &cpuid, sizeof (cpuid)); 7801708Sstevel if (status != PICL_SUCCESS) { 781*5544Sfw157321 log_printf("%-7s", no_prop_value); 7821708Sstevel } else { 783*5544Sfw157321 log_printf("%-7d", cpuid); 7841708Sstevel } 7851708Sstevel } else { 786*5544Sfw157321 log_printf("%-7s", no_prop_value); 7871708Sstevel } 7881708Sstevel 7891708Sstevel clock_freq: 7901708Sstevel status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo, 7914669Sfw157321 &proph); 7921708Sstevel if (status == PICL_SUCCESS) { 7931708Sstevel int_value = malloc(propinfo.size); 7941708Sstevel if (int_value == NULL) { 795*5544Sfw157321 log_printf("%-10s", no_prop_value); 7961708Sstevel goto compatible; 7971708Sstevel } 7981708Sstevel status = picl_get_propval(proph, int_value, propinfo.size); 7991708Sstevel if (status != PICL_SUCCESS) { 800*5544Sfw157321 log_printf("%-10s", no_prop_value); 8011708Sstevel } else { 8021708Sstevel /* Running frequency */ 8031708Sstevel (void) snprintf(freq_str, sizeof (freq_str), "%d MHz", 8041708Sstevel CLK_FREQ_TO_MHZ(*int_value)); 805*5544Sfw157321 log_printf("%-10s", freq_str); 8061708Sstevel } 8071708Sstevel free(int_value); 8081708Sstevel } else 809*5544Sfw157321 log_printf("%-10s", no_prop_value); 8101708Sstevel 8111708Sstevel compatible: 8121708Sstevel status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo, 8134669Sfw157321 &proph); 8141708Sstevel if (status == PICL_SUCCESS) { 8151708Sstevel if (propinfo.type == PICL_PTYPE_CHARSTRING) { 8161708Sstevel /* 8171708Sstevel * Compatible Property only has 1 value 8181708Sstevel */ 8191708Sstevel comp_value = malloc(propinfo.size); 8201708Sstevel if (comp_value == NULL) { 821*5544Sfw157321 log_printf("%-23s", no_prop_value, 0); 8225028Sfw157321 goto state; 8231708Sstevel } 8241708Sstevel status = picl_get_propval(proph, comp_value, 8254669Sfw157321 propinfo.size); 8263941Svenki if (status != PICL_SUCCESS) 827*5544Sfw157321 log_printf("%-23s", no_prop_value, 0); 8283941Svenki else 829*5544Sfw157321 log_printf("%-23s", comp_value, 0); 8303941Svenki free(comp_value); 8311708Sstevel } else if (propinfo.type == PICL_PTYPE_TABLE) { 8321708Sstevel /* 8331708Sstevel * Compatible Property has multiple values 8341708Sstevel */ 8351708Sstevel status = picl_get_propval(proph, &tblh, propinfo.size); 8361708Sstevel if (status != PICL_SUCCESS) { 837*5544Sfw157321 log_printf("%-23s", no_prop_value, 0); 8385028Sfw157321 goto state; 8391708Sstevel } 8401708Sstevel status = picl_get_next_by_row(tblh, &rowproph); 8411708Sstevel if (status != PICL_SUCCESS) { 842*5544Sfw157321 log_printf("%-23s", no_prop_value, 0); 8435028Sfw157321 goto state; 8441708Sstevel } 8451708Sstevel 8461708Sstevel status = picl_get_propinfo(rowproph, &propinfo); 8471708Sstevel if (status != PICL_SUCCESS) { 848*5544Sfw157321 log_printf("%-23s", no_prop_value, 0); 8495028Sfw157321 goto state; 8501708Sstevel } 8511708Sstevel 8521708Sstevel comp_value = malloc(propinfo.size); 8531708Sstevel if (comp_value == NULL) { 854*5544Sfw157321 log_printf("%-23s", no_prop_value, 0); 8555028Sfw157321 goto state; 8561708Sstevel } 8571708Sstevel status = picl_get_propval(rowproph, comp_value, 8584669Sfw157321 propinfo.size); 8593941Svenki if (status != PICL_SUCCESS) 860*5544Sfw157321 log_printf("%-23s", no_prop_value, 0); 8613941Svenki else 862*5544Sfw157321 log_printf("%-23s", comp_value, 0); 8631708Sstevel free(comp_value); 8641708Sstevel } 8651708Sstevel } else 866*5544Sfw157321 log_printf("%-23s", no_prop_value, 0); 8671708Sstevel 8685028Sfw157321 state: 8695028Sfw157321 status = picl_get_propinfo_by_name(cpuh, PICL_PROP_STATE, 8705028Sfw157321 &propinfo, &proph); 8711708Sstevel if (status == PICL_SUCCESS) { 8725028Sfw157321 status = picl_get_propval(proph, state, sizeof (state)); 8731708Sstevel if (status != PICL_SUCCESS) { 8743941Svenki log_printf("%-9s", no_prop_value); 8751708Sstevel } else { 8765028Sfw157321 log_printf("%-9s", state); 8771708Sstevel } 8781708Sstevel } else 8793941Svenki log_printf("%-9s", no_prop_value); 8801708Sstevel 8811708Sstevel done: 8821708Sstevel log_printf("\n"); 8831708Sstevel return (PICL_WALK_CONTINUE); 8841708Sstevel } 8851708Sstevel 8861708Sstevel void 8871708Sstevel sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh) 8881708Sstevel { 8891708Sstevel #ifdef lint 8901708Sstevel flag = flag; 8911708Sstevel root = root; 8921708Sstevel plafh = plafh; 8931708Sstevel #endif 8941708Sstevel /* 8951708Sstevel * This function is intentionally empty 8961708Sstevel */ 8971708Sstevel } 8981708Sstevel 8991708Sstevel void 9001708Sstevel display_boardnum(int num) 9011708Sstevel { 9021708Sstevel log_printf("%2d ", num, 0); 9031708Sstevel } 9043941Svenki 9053941Svenki static void 9063941Svenki sun4v_disp_env_status() 9073941Svenki { 9083941Svenki if (phyplatformh == 0) 9093941Svenki return; 9103941Svenki log_printf("\n"); 9113941Svenki log_printf("============================"); 9123941Svenki log_printf(" Environmental Status "); 9133941Svenki log_printf("============================"); 9143941Svenki log_printf("\n"); 9153941Svenki 9163941Svenki class_node_found = 0; 9173941Svenki all_status_ok = 1; 9183941Svenki sun4v_env_print_fan_sensors(); 9193941Svenki 9203941Svenki class_node_found = 0; 9213941Svenki all_status_ok = 1; 9223941Svenki sun4v_env_print_fan_indicators(); 9233941Svenki 9243941Svenki class_node_found = 0; 9253941Svenki all_status_ok = 1; 9263941Svenki sun4v_env_print_temp_sensors(); 9273941Svenki 9283941Svenki class_node_found = 0; 9293941Svenki all_status_ok = 1; 9303941Svenki sun4v_env_print_temp_indicators(); 9313941Svenki 9323941Svenki class_node_found = 0; 9333941Svenki all_status_ok = 1; 9343941Svenki sun4v_env_print_current_sensors(); 9353941Svenki 9363941Svenki class_node_found = 0; 9373941Svenki all_status_ok = 1; 9383941Svenki sun4v_env_print_current_indicators(); 9393941Svenki 9403941Svenki class_node_found = 0; 9413941Svenki all_status_ok = 1; 9423941Svenki sun4v_env_print_voltage_sensors(); 9433941Svenki 9443941Svenki class_node_found = 0; 9453941Svenki all_status_ok = 1; 9463941Svenki sun4v_env_print_voltage_indicators(); 9473941Svenki 9483941Svenki class_node_found = 0; 9493941Svenki sun4v_env_print_LEDs(); 9503941Svenki 9513941Svenki class_node_found = 0; 9523941Svenki all_status_ok = 1; 9533941Svenki sun4v_print_fru_status(); 9543941Svenki 9553941Svenki class_node_found = 0; 9563941Svenki sun4v_print_fw_rev(); 9573941Svenki 9585436Sfw157321 class_node_found = 0; 9595436Sfw157321 sun4v_print_openprom_rev(); 9605436Sfw157321 9613941Svenki sun4v_print_chassis_serial_no(); 9623941Svenki } 9633941Svenki 9643941Svenki /*ARGSUSED*/ 9653941Svenki static int 9663941Svenki sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args) 9673941Svenki { 9683941Svenki char val[PICL_PROPNAMELEN_MAX]; 9693941Svenki picl_nodehdl_t parenth; 9703941Svenki char *names[PARENT_NAMES]; 9714802Sfw157321 char *base_units[PICL_PROPNAMELEN_MAX]; 9723941Svenki char *loc; 9733941Svenki int i; 9743941Svenki char *prop; 9753941Svenki picl_errno_t err; 9765436Sfw157321 int32_t lo_warning, lo_shutdown, lo_poweroff; 9775436Sfw157321 int32_t hi_warning, hi_shutdown, hi_poweroff; 9783941Svenki int32_t current_val; 9794802Sfw157321 int32_t exponent; 9804802Sfw157321 double display_val; 9814928Sfw157321 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 9824928Sfw157321 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 9834928Sfw157321 sensor_status_t sensor_status = SENSOR_OK; 9843941Svenki 9853941Svenki if (class_node_found == 0) { 9863941Svenki class_node_found = 1; 9873941Svenki return (PICL_WALK_TERMINATE); 9883941Svenki } 9893941Svenki 9904928Sfw157321 prop = (char *)args; 9914928Sfw157321 if (!prop) { 9924928Sfw157321 sensor_status = SENSOR_UNKNOWN; 9934928Sfw157321 all_status_ok = 0; 9944928Sfw157321 } else { 9953941Svenki err = picl_get_propval_by_name(nodeh, 9964669Sfw157321 PICL_PROP_OPERATIONAL_STATUS, val, 9974669Sfw157321 sizeof (val)); 9983941Svenki if (err == PICL_SUCCESS) { 9993941Svenki if (strcmp(val, "disabled") == 0) { 10004928Sfw157321 sensor_status = SENSOR_DISABLED; 10014928Sfw157321 } 10024928Sfw157321 } 10034928Sfw157321 } 10044928Sfw157321 10054928Sfw157321 if (sensor_status != SENSOR_DISABLED && 10064928Sfw157321 sensor_status != SENSOR_UNKNOWN) { 10074928Sfw157321 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 10084928Sfw157321 sizeof (current_val)) != PICL_SUCCESS) { 10094928Sfw157321 sensor_status = SENSOR_UNKNOWN; 10105436Sfw157321 } else { 10115436Sfw157321 if (picl_get_propval_by_name(nodeh, 10125436Sfw157321 PICL_PROP_LOW_WARNING, 10135436Sfw157321 &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS) 10145436Sfw157321 lo_warning = INVALID_THRESHOLD; 10155436Sfw157321 if (picl_get_propval_by_name(nodeh, 10165436Sfw157321 PICL_PROP_LOW_SHUTDOWN, 10175436Sfw157321 &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS) 10185436Sfw157321 lo_shutdown = INVALID_THRESHOLD; 10195436Sfw157321 if (picl_get_propval_by_name(nodeh, 10205436Sfw157321 PICL_PROP_LOW_POWER_OFF, 10215436Sfw157321 &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS) 10225436Sfw157321 lo_poweroff = INVALID_THRESHOLD; 10235436Sfw157321 if (picl_get_propval_by_name(nodeh, 10245436Sfw157321 PICL_PROP_HIGH_WARNING, 10255436Sfw157321 &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS) 10265436Sfw157321 hi_warning = INVALID_THRESHOLD; 10275436Sfw157321 if (picl_get_propval_by_name(nodeh, 10285436Sfw157321 PICL_PROP_HIGH_SHUTDOWN, 10295436Sfw157321 &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS) 10305436Sfw157321 hi_shutdown = INVALID_THRESHOLD; 10315436Sfw157321 if (picl_get_propval_by_name(nodeh, 10325436Sfw157321 PICL_PROP_HIGH_POWER_OFF, 10335436Sfw157321 &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS) 10345436Sfw157321 hi_poweroff = INVALID_THRESHOLD; 10354928Sfw157321 10365436Sfw157321 if ((lo_poweroff != INVALID_THRESHOLD && 10375436Sfw157321 current_val <= lo_poweroff) || 10385436Sfw157321 (hi_poweroff != INVALID_THRESHOLD && 10395436Sfw157321 current_val >= hi_poweroff)) { 10405436Sfw157321 sensor_status = SENSOR_FAILED; 10415436Sfw157321 } else if ((lo_shutdown != INVALID_THRESHOLD && 10425436Sfw157321 current_val <= lo_shutdown) || 10435436Sfw157321 (hi_shutdown != INVALID_THRESHOLD && 10445436Sfw157321 current_val >= hi_shutdown)) { 10455436Sfw157321 sensor_status = SENSOR_FAILED; 10465436Sfw157321 } else if ((lo_warning != INVALID_THRESHOLD && 10475436Sfw157321 current_val <= lo_warning) || 10485436Sfw157321 (hi_warning != INVALID_THRESHOLD && 10495436Sfw157321 current_val >= hi_warning)) { 10505436Sfw157321 sensor_status = SENSOR_WARN; 10515436Sfw157321 } else { 10525436Sfw157321 sensor_status = SENSOR_OK; 10535436Sfw157321 } 10544928Sfw157321 } 10554928Sfw157321 } 10564928Sfw157321 10574928Sfw157321 if (syserrlog == 0) { 10584928Sfw157321 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 10593941Svenki all_status_ok = 0; 10603941Svenki return (PICL_WALK_TERMINATE); 10613941Svenki } 10624928Sfw157321 if (sensor_status == SENSOR_OK) { 10634928Sfw157321 return (PICL_WALK_CONTINUE); 10644928Sfw157321 } 10653941Svenki } 10664928Sfw157321 10674928Sfw157321 /* 10684928Sfw157321 * If we're here then prtdiag was invoked with "-v" or we have 10694928Sfw157321 * a sensor that is beyond a threshold, so give them a book to 10704928Sfw157321 * read instead of the Cliff Notes. 10714928Sfw157321 */ 10723941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 10734669Sfw157321 sizeof (parenth)); 10743941Svenki if (err != PICL_SUCCESS) { 10753941Svenki log_printf("\n"); 10763941Svenki return (PICL_WALK_CONTINUE); 10773941Svenki } 10784003Svivek 10794928Sfw157321 /* gather up the path name for the sensor */ 10804928Sfw157321 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 10814928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) { 10824928Sfw157321 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 10834928Sfw157321 NULL) { 10844928Sfw157321 while (--i > -1) 10854928Sfw157321 free(names[i]); 10864928Sfw157321 free(loc); 10874928Sfw157321 loc = NULL; 10884928Sfw157321 } 10893941Svenki } 10904003Svivek } 10914928Sfw157321 i = 0; 10924928Sfw157321 if (loc != 0) { 10934928Sfw157321 while (err == PICL_SUCCESS) { 10944928Sfw157321 if (parenth == phyplatformh) 10954928Sfw157321 break; 10964928Sfw157321 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 10974928Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 10984928Sfw157321 if (err != PICL_SUCCESS) { 10994928Sfw157321 i--; 11004928Sfw157321 break; 11014928Sfw157321 } 11024928Sfw157321 if (i == PARENT_NAMES) 11034928Sfw157321 break; 11044928Sfw157321 err = picl_get_propval_by_name(parenth, 11054928Sfw157321 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 11064928Sfw157321 } 11074928Sfw157321 loc[0] = '\0'; 11084928Sfw157321 if (--i > -1) { 11094928Sfw157321 (void) strlcat(loc, names[i], 11104928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 11114928Sfw157321 } 11124928Sfw157321 while (--i > -1) { 11134928Sfw157321 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 11144928Sfw157321 PARENT_NAMES); 11154928Sfw157321 (void) strlcat(loc, names[i], 11164928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 11174928Sfw157321 } 11185028Sfw157321 log_printf("%-35s", loc); 11194928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) 11204928Sfw157321 free(names[i]); 11214928Sfw157321 free(loc); 11224928Sfw157321 } else { 11235028Sfw157321 log_printf("%-35s", " "); 11243941Svenki } 11253941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 11264669Sfw157321 sizeof (val)); 11273941Svenki if (err == PICL_SUCCESS) 11283941Svenki log_printf("%-15s", val); 11293941Svenki 11304928Sfw157321 /* 11314928Sfw157321 * Get the exponent if present, and do a little math so that 11324928Sfw157321 * if we need to we can print a normalized value for the 11334928Sfw157321 * sensor reading. 11344928Sfw157321 */ 11354802Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT, 11364802Sfw157321 &exponent, sizeof (exponent)) != PICL_SUCCESS) 11374802Sfw157321 exponent = 0; 11384802Sfw157321 if (exponent == 0) 11394802Sfw157321 display_val = (double)current_val; 11405436Sfw157321 else { 11414802Sfw157321 display_val = (double)current_val * 11424802Sfw157321 pow((double)10, (double)exponent); 11435436Sfw157321 11445436Sfw157321 /* 11455436Sfw157321 * Sometimes ILOM will scale a sensor reading but 11465436Sfw157321 * there will be nothing to the right of the decimal 11475436Sfw157321 * once that value is normalized. Setting the 11485436Sfw157321 * exponent to zero will prevent the printf below 11495436Sfw157321 * from printing extraneous zeros. Otherwise a 11505436Sfw157321 * negative exponent is used to set the precision 11515436Sfw157321 * for the printf. 11525436Sfw157321 */ 11535436Sfw157321 if ((int)display_val == display_val || exponent > 0) 11545436Sfw157321 exponent = 0; 11555436Sfw157321 } 11565436Sfw157321 11574928Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS, 11584928Sfw157321 base_units, sizeof (base_units)); 11594802Sfw157321 if (err != PICL_SUCCESS) 11604802Sfw157321 base_units[0] = '\0'; 11613941Svenki 11624928Sfw157321 switch (sensor_status) { 11634928Sfw157321 case SENSOR_FAILED: 11643941Svenki log_printf("%-s", "failed ("); 11654802Sfw157321 log_printf("%-.*f", abs(exponent), display_val); 11664802Sfw157321 log_printf("%-s %s", base_units, ")"); 11674928Sfw157321 break; 11684928Sfw157321 case SENSOR_WARN: 11693941Svenki log_printf("%-s", "warning ("); 11704802Sfw157321 log_printf("%-.*f", abs(exponent), display_val); 11714802Sfw157321 log_printf("%-s %s", base_units, ")"); 11724928Sfw157321 break; 11734928Sfw157321 case SENSOR_DISABLED: 11744928Sfw157321 log_printf("%-s", "disabled"); 11754928Sfw157321 break; 11764928Sfw157321 case SENSOR_OK: 11773941Svenki log_printf("%-s", "ok"); 11784928Sfw157321 break; 11794928Sfw157321 default: 11804928Sfw157321 log_printf("%-s", "unknown"); 11814928Sfw157321 break; 11824928Sfw157321 } 11833941Svenki 11843941Svenki log_printf("\n"); 11853941Svenki return (PICL_WALK_CONTINUE); 11863941Svenki } 11873941Svenki 11883941Svenki /*ARGSUSED*/ 11893941Svenki static int 11903941Svenki sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args) 11913941Svenki { 11924928Sfw157321 char current_val[PICL_PROPNAMELEN_MAX]; 11934928Sfw157321 char expected_val[PICL_PROPNAMELEN_MAX]; 11944928Sfw157321 char label[PICL_PROPNAMELEN_MAX]; 11953941Svenki picl_nodehdl_t parenth; 11963941Svenki char *names[PARENT_NAMES]; 11973941Svenki char *loc; 11983941Svenki int i = 0; 11993941Svenki char *prop = (char *)args; 12003941Svenki picl_errno_t err = PICL_SUCCESS; 12014928Sfw157321 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 12024928Sfw157321 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 12034928Sfw157321 sensor_status_t sensor_status = SENSOR_OK; 12043941Svenki 12053941Svenki if (class_node_found == 0) { 12063941Svenki class_node_found = 1; 12073941Svenki return (PICL_WALK_TERMINATE); 12083941Svenki } 12094928Sfw157321 12104928Sfw157321 prop = (char *)args; 12114928Sfw157321 if (!prop) { 12124928Sfw157321 sensor_status = SENSOR_UNKNOWN; 12134928Sfw157321 all_status_ok = 0; 12144928Sfw157321 } else { 12153941Svenki err = picl_get_propval_by_name(nodeh, 12164928Sfw157321 PICL_PROP_OPERATIONAL_STATUS, current_val, 12174928Sfw157321 sizeof (current_val)); 12183941Svenki if (err == PICL_SUCCESS) { 12194928Sfw157321 if (strcmp(current_val, "disabled") == 0) { 12204928Sfw157321 sensor_status = SENSOR_DISABLED; 12214928Sfw157321 } 12224928Sfw157321 } 12234928Sfw157321 } 12244928Sfw157321 12254928Sfw157321 if (sensor_status != SENSOR_DISABLED && 12264928Sfw157321 sensor_status != SENSOR_UNKNOWN) { 12274928Sfw157321 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 12284928Sfw157321 sizeof (current_val)) != PICL_SUCCESS) { 12294928Sfw157321 (void) strlcpy(current_val, "unknown", 12304928Sfw157321 sizeof (current_val)); 12314928Sfw157321 sensor_status = SENSOR_UNKNOWN; 12324928Sfw157321 } else { 12334928Sfw157321 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED, 12344928Sfw157321 &expected_val, sizeof (expected_val)) != 12354928Sfw157321 PICL_SUCCESS) { 12364928Sfw157321 sensor_status = SENSOR_UNKNOWN; 12374928Sfw157321 } else { 12384928Sfw157321 if (strncmp(current_val, expected_val, 12394928Sfw157321 sizeof (current_val)) == 0) { 12404928Sfw157321 sensor_status = SENSOR_OK; 12414928Sfw157321 } else { 12424928Sfw157321 sensor_status = SENSOR_FAILED; 12433941Svenki } 12444928Sfw157321 } 12454928Sfw157321 } 12464928Sfw157321 } 12474928Sfw157321 12484928Sfw157321 if (syserrlog == 0) { 12494928Sfw157321 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 12503941Svenki all_status_ok = 0; 12513941Svenki return (PICL_WALK_TERMINATE); 12523941Svenki } 12534928Sfw157321 if (sensor_status == SENSOR_OK) { 12544928Sfw157321 return (PICL_WALK_CONTINUE); 12554928Sfw157321 } 12563941Svenki } 12574928Sfw157321 12584928Sfw157321 /* 12594928Sfw157321 * If we're here then prtdiag was invoked with "-v" or we have 12604928Sfw157321 * a sensor that is beyond a threshold, so give them a book to 12614928Sfw157321 * read instead of the Cliff Notes. 12624928Sfw157321 */ 12633941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 12644669Sfw157321 sizeof (parenth)); 12653941Svenki if (err != PICL_SUCCESS) { 12663941Svenki log_printf("\n"); 12673941Svenki return (PICL_WALK_CONTINUE); 12683941Svenki } 12694928Sfw157321 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 12704928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) { 12714928Sfw157321 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 12724928Sfw157321 NULL) { 12734928Sfw157321 while (--i > -1) 12744928Sfw157321 free(names[i]); 12754928Sfw157321 free(loc); 12764928Sfw157321 loc = NULL; 12774928Sfw157321 } 12783941Svenki } 12793941Svenki } 12804928Sfw157321 i = 0; 12814928Sfw157321 if (loc) { 12824928Sfw157321 while (err == PICL_SUCCESS) { 12834928Sfw157321 if (parenth == phyplatformh) 12844928Sfw157321 break; 12854928Sfw157321 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 12864928Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 12874928Sfw157321 if (err != PICL_SUCCESS) { 12884928Sfw157321 i--; 12894928Sfw157321 break; 12904928Sfw157321 } 12914928Sfw157321 if (i == PARENT_NAMES) 12924928Sfw157321 break; 12934928Sfw157321 err = picl_get_propval_by_name(parenth, 12944928Sfw157321 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 12954928Sfw157321 } 12964928Sfw157321 loc[0] = '\0'; 12974928Sfw157321 if (--i > -1) { 12984928Sfw157321 (void) strlcat(loc, names[i], 12994928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 13004928Sfw157321 } 13014928Sfw157321 while (--i > -1) { 13024928Sfw157321 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 13034928Sfw157321 PARENT_NAMES); 13044928Sfw157321 (void) strlcat(loc, names[i], 13054928Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 13064928Sfw157321 } 13075028Sfw157321 log_printf("%-35s", loc); 13084928Sfw157321 for (i = 0; i < PARENT_NAMES; i++) 13094928Sfw157321 free(names[i]); 13104928Sfw157321 free(loc); 13114928Sfw157321 } else { 13125028Sfw157321 log_printf("%-35s", ""); 13133941Svenki } 13144928Sfw157321 13154928Sfw157321 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 13164928Sfw157321 sizeof (label)); 13174928Sfw157321 if (err != PICL_SUCCESS) 13184928Sfw157321 (void) strlcpy(label, "", sizeof (label)); 13194928Sfw157321 log_printf("%-15s", label); 13204928Sfw157321 13214928Sfw157321 log_printf("%-8s", current_val); 13224928Sfw157321 13233941Svenki log_printf("\n"); 13243941Svenki return (PICL_WALK_CONTINUE); 13253941Svenki } 13263941Svenki 13273941Svenki static void 13283941Svenki sun4v_env_print_fan_sensors() 13293941Svenki { 13305028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 13313941Svenki /* 13323941Svenki * If there isn't any fan sensor node, return now. 13333941Svenki */ 13343941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13354928Sfw157321 PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED, 13364669Sfw157321 sun4v_env_print_sensor_callback); 13373941Svenki if (!class_node_found) 13383941Svenki return; 13393941Svenki log_printf("Fan sensors:\n"); 13403941Svenki if (syserrlog == 0) { 13413941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13424669Sfw157321 PICL_CLASS_RPM_SENSOR, 13434928Sfw157321 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 13443941Svenki if (all_status_ok) { 13453941Svenki log_printf("All fan sensors are OK.\n"); 13463941Svenki return; 13473941Svenki } 13483941Svenki } 13495028Sfw157321 log_printf("-------------------------------------------------" 13505028Sfw157321 "-----------\n"); 13513941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 13525028Sfw157321 log_printf("-------------------------------------------------" 13535028Sfw157321 "-----------\n"); 13543941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR, 13554669Sfw157321 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 13563941Svenki } 13573941Svenki 13583941Svenki static void 13593941Svenki sun4v_env_print_fan_indicators() 13603941Svenki { 13615028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 13623941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13634928Sfw157321 PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION, 13644669Sfw157321 sun4v_env_print_indicator_callback); 13653941Svenki if (!class_node_found) 13663941Svenki return; 13673941Svenki log_printf("\nFan indicators:\n"); 13683941Svenki if (syserrlog == 0) { 13693941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13704669Sfw157321 PICL_CLASS_RPM_INDICATOR, 13714928Sfw157321 (void *)PICL_PROP_CONDITION, 13724928Sfw157321 sun4v_env_print_indicator_callback); 13733941Svenki if (all_status_ok) { 13743941Svenki log_printf("All fan indicators are OK.\n"); 13753941Svenki return; 13763941Svenki } 13773941Svenki } 13785028Sfw157321 log_printf("-------------------------------------------------" 13795028Sfw157321 "-----------\n"); 13803941Svenki log_printf(fmt, "Location", "Sensor", "Condition", 0); 13815028Sfw157321 log_printf("-------------------------------------------------" 13825028Sfw157321 "-----------\n"); 13833941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR, 13844802Sfw157321 (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback); 13853941Svenki } 13863941Svenki 13873941Svenki static void 13883941Svenki sun4v_env_print_temp_sensors() 13893941Svenki { 13905028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 13913941Svenki (void) picl_walk_tree_by_class(phyplatformh, 13924669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 13934669Sfw157321 (void *)PICL_PROP_TEMPERATURE, 13944669Sfw157321 sun4v_env_print_sensor_callback); 13953941Svenki if (!class_node_found) 13963941Svenki return; 13973941Svenki 13983941Svenki log_printf("\nTemperature sensors:\n"); 13993941Svenki if (syserrlog == 0) { 14003941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14014669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 14024928Sfw157321 PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 14033941Svenki if (all_status_ok) { 14043941Svenki log_printf("All temperature sensors are OK.\n"); 14053941Svenki return; 14063941Svenki } 14073941Svenki } 14085028Sfw157321 log_printf("-------------------------------------------------" 14095028Sfw157321 "-----------\n"); 14103941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 14115028Sfw157321 log_printf("-------------------------------------------------" 14125028Sfw157321 "-----------\n"); 14133941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14144669Sfw157321 PICL_CLASS_TEMPERATURE_SENSOR, 14154669Sfw157321 (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 14163941Svenki } 14173941Svenki 14183941Svenki static void 14193941Svenki sun4v_env_print_temp_indicators() 14203941Svenki { 14215028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 14223941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14234669Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION, 14244669Sfw157321 sun4v_env_print_indicator_callback); 14253941Svenki if (!class_node_found) 14263941Svenki return; 14273941Svenki log_printf("\nTemperature indicators:\n"); 14283941Svenki if (syserrlog == 0) { 14293941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14304928Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, 14314928Sfw157321 (void *)PICL_PROP_CONDITION, 14324669Sfw157321 sun4v_env_print_indicator_callback); 14333941Svenki if (all_status_ok) { 14343941Svenki log_printf("All temperature indicators are OK.\n"); 14353941Svenki return; 14363941Svenki } 14373941Svenki } 14385028Sfw157321 log_printf("-------------------------------------------------" 14395028Sfw157321 "-----------\n"); 14403941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 14415028Sfw157321 log_printf("-------------------------------------------------" 14425028Sfw157321 "-----------\n"); 14433941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14444669Sfw157321 PICL_CLASS_TEMPERATURE_INDICATOR, 14454669Sfw157321 (void *)PICL_PROP_CONDITION, 14464669Sfw157321 sun4v_env_print_indicator_callback); 14473941Svenki } 14483941Svenki 14493941Svenki static void 14503941Svenki sun4v_env_print_current_sensors() 14513941Svenki { 14525028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 14533941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR, 14544669Sfw157321 (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 14553941Svenki if (!class_node_found) 14563941Svenki return; 14573941Svenki log_printf("\nCurrent sensors:\n"); 14583941Svenki if (syserrlog == 0) { 14593941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14604669Sfw157321 PICL_CLASS_CURRENT_SENSOR, 14614928Sfw157321 PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 14623941Svenki if (all_status_ok) { 14633941Svenki log_printf("All current sensors are OK.\n"); 14643941Svenki return; 14653941Svenki } 14663941Svenki } 14675028Sfw157321 log_printf("-------------------------------------------------" 14685028Sfw157321 "-----------\n"); 14693941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 14705028Sfw157321 log_printf("-------------------------------------------------" 14715028Sfw157321 "-----------\n"); 14723941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14734669Sfw157321 PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT, 14744669Sfw157321 sun4v_env_print_sensor_callback); 14753941Svenki } 14763941Svenki 14773941Svenki static void 14783941Svenki sun4v_env_print_current_indicators() 14793941Svenki { 14805028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 14813941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14824669Sfw157321 PICL_CLASS_CURRENT_INDICATOR, 14834669Sfw157321 (void *)PICL_PROP_CONDITION, 14844669Sfw157321 sun4v_env_print_indicator_callback); 14853941Svenki if (!class_node_found) 14863941Svenki return; 14873941Svenki log_printf("\nCurrent indicators:\n"); 14883941Svenki if (syserrlog == 0) { 14893941Svenki (void) picl_walk_tree_by_class(phyplatformh, 14904928Sfw157321 PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION, 14914669Sfw157321 sun4v_env_print_indicator_callback); 14923941Svenki if (all_status_ok) { 14933941Svenki log_printf("All current indicators are OK.\n"); 14943941Svenki return; 14953941Svenki } 14963941Svenki } 14975028Sfw157321 log_printf("-------------------------------------------------" 14985028Sfw157321 "-----------\n"); 14993941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 15005028Sfw157321 log_printf("-------------------------------------------------" 15015028Sfw157321 "-----------\n"); 15023941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15034669Sfw157321 PICL_CLASS_CURRENT_INDICATOR, 15044669Sfw157321 (void *)PICL_PROP_CONDITION, 15054669Sfw157321 sun4v_env_print_indicator_callback); 15063941Svenki } 15073941Svenki 15083941Svenki static void 15093941Svenki sun4v_env_print_voltage_sensors() 15103941Svenki { 15115028Sfw157321 char *fmt = "%-34s %-14s %-10s\n"; 15123941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15134669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 15144669Sfw157321 PICL_PROP_VOLTAGE, 15154669Sfw157321 sun4v_env_print_sensor_callback); 15163941Svenki if (!class_node_found) 15173941Svenki return; 15183941Svenki log_printf("\nVoltage sensors:\n"); 15193941Svenki if (syserrlog == 0) { 15203941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15214669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 15224928Sfw157321 PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback); 15233941Svenki if (all_status_ok) { 15243941Svenki log_printf("All voltage sensors are OK.\n"); 15253941Svenki return; 15263941Svenki } 15273941Svenki } 15285028Sfw157321 log_printf("-------------------------------------------------" 15295028Sfw157321 "-----------\n"); 15303941Svenki log_printf(fmt, "Location", "Sensor", "Status", 0); 15315028Sfw157321 log_printf("-------------------------------------------------" 15325028Sfw157321 "-----------\n"); 15333941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15344669Sfw157321 PICL_CLASS_VOLTAGE_SENSOR, 15354669Sfw157321 (void *)PICL_PROP_VOLTAGE, 15364669Sfw157321 sun4v_env_print_sensor_callback); 15373941Svenki } 15383941Svenki 15393941Svenki static void 15403941Svenki sun4v_env_print_voltage_indicators() 15413941Svenki { 15425028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 15433941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15444669Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, 15454669Sfw157321 (void *)PICL_PROP_CONDITION, 15464669Sfw157321 sun4v_env_print_indicator_callback); 15473941Svenki if (!class_node_found) 15483941Svenki return; 15493941Svenki log_printf("\nVoltage indicators:\n"); 15503941Svenki if (syserrlog == 0) { 15513941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15524928Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION, 15534669Sfw157321 sun4v_env_print_indicator_callback); 15543941Svenki if (all_status_ok) { 15553941Svenki log_printf("All voltage indicators are OK.\n"); 15563941Svenki return; 15573941Svenki } 15583941Svenki } 15595028Sfw157321 log_printf("-------------------------------------------------" 15605028Sfw157321 "-----------\n"); 15613941Svenki log_printf(fmt, "Location", "Indicator", "Condition", 0); 15625028Sfw157321 log_printf("-------------------------------------------------" 15635028Sfw157321 "-----------\n"); 15643941Svenki (void) picl_walk_tree_by_class(phyplatformh, 15654669Sfw157321 PICL_CLASS_VOLTAGE_INDICATOR, 15664669Sfw157321 (void *)PICL_PROP_CONDITION, 15674669Sfw157321 sun4v_env_print_indicator_callback); 15683941Svenki } 15693941Svenki 15703941Svenki static void 15713941Svenki sun4v_env_print_LEDs() 15723941Svenki { 15735028Sfw157321 char *fmt = "%-34s %-14s %-8s\n"; 15743941Svenki if (syserrlog == 0) 15753941Svenki return; 15763941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 15774669Sfw157321 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 15783941Svenki if (!class_node_found) 15793941Svenki return; 15803941Svenki log_printf("\nLEDs:\n"); 15815028Sfw157321 log_printf("-------------------------------------------------" 15825028Sfw157321 "-----------\n"); 15833941Svenki log_printf(fmt, "Location", "LED", "State", 0); 15845028Sfw157321 log_printf("-------------------------------------------------" 15855028Sfw157321 "-----------\n"); 15863941Svenki (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 15874669Sfw157321 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 15883941Svenki } 15893941Svenki 15903941Svenki /*ARGSUSED*/ 15913941Svenki static int 15923941Svenki sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args) 15933941Svenki { 15943941Svenki char label[PICL_PROPNAMELEN_MAX]; 15953941Svenki char status[PICL_PROPNAMELEN_MAX]; 15963941Svenki picl_errno_t err; 15973941Svenki picl_prophdl_t proph; 15983941Svenki picl_nodehdl_t parenth; 15993941Svenki char *names[PARENT_NAMES]; 16003941Svenki char *loc; 16013941Svenki int i; 16023941Svenki 16033941Svenki if (!class_node_found) { 16043941Svenki class_node_found = 1; 16053941Svenki return (PICL_WALK_TERMINATE); 16063941Svenki } 16073941Svenki err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph); 16083941Svenki if (err != PICL_SUCCESS) 16093941Svenki return (PICL_WALK_CONTINUE); 16103941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 16114669Sfw157321 sizeof (label)); 16123941Svenki if (err != PICL_SUCCESS) 16133941Svenki return (PICL_WALK_CONTINUE); 16143941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS, 16154669Sfw157321 status, sizeof (status)); 16163941Svenki if (err != PICL_SUCCESS) 16173941Svenki return (PICL_WALK_CONTINUE); 16183941Svenki if (syserrlog == 0) { 16193941Svenki if (strcmp(status, "disabled") == 0) { 16203941Svenki if (all_status_ok) { 16213941Svenki all_status_ok = 0; 16223941Svenki return (PICL_WALK_TERMINATE); 16233941Svenki } 16243941Svenki } else 16253941Svenki return (PICL_WALK_CONTINUE); 16263941Svenki } 16273941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 16284669Sfw157321 sizeof (parenth)); 16293941Svenki if (err != PICL_SUCCESS) { 16303941Svenki log_printf("\n"); 16313941Svenki return (PICL_WALK_CONTINUE); 16323941Svenki } 16333941Svenki if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL) 16343941Svenki return (PICL_WALK_TERMINATE); 16353941Svenki for (i = 0; i < PARENT_NAMES; i++) 16363941Svenki if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) { 16373941Svenki while (--i > -1) 16383941Svenki free(names[i]); 16393941Svenki free(loc); 16403941Svenki return (PICL_WALK_TERMINATE); 16413941Svenki } 16423941Svenki i = 0; 16433941Svenki while (err == PICL_SUCCESS) { 16444802Sfw157321 if (parenth == phyplatformh) 16453941Svenki break; 16463941Svenki err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 16474669Sfw157321 names[i++], PICL_PROPNAMELEN_MAX); 16483941Svenki if (err != PICL_SUCCESS) { 16493941Svenki i--; 16503941Svenki break; 16513941Svenki } 16523941Svenki if (i == PARENT_NAMES) 16533941Svenki break; 16543941Svenki err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT, 16554669Sfw157321 &parenth, sizeof (parenth)); 16563941Svenki } 16573941Svenki loc[0] = '\0'; 16584003Svivek if (--i > -1) { 16594003Svivek (void) strlcat(loc, names[i], 16604669Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 16614003Svivek } 16623941Svenki while (--i > -1) { 16634003Svivek (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES); 16644003Svivek (void) strlcat(loc, names[i], 16654669Sfw157321 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 16663941Svenki } 16675028Sfw157321 log_printf("%-35s", loc); 16683941Svenki for (i = 0; i < PARENT_NAMES; i++) 16693941Svenki free(names[i]); 16703941Svenki free(loc); 16713941Svenki log_printf("%-10s", label); 16723941Svenki log_printf("%-9s", status); 16733941Svenki log_printf("\n"); 16743941Svenki return (PICL_WALK_CONTINUE); 16753941Svenki } 16763941Svenki 16773941Svenki static void 16783941Svenki sun4v_print_fru_status() 16793941Svenki { 16805028Sfw157321 char *fmt = "%-34s %-9s %-8s\n"; 16815436Sfw157321 16823941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 16834669Sfw157321 sun4v_print_fru_status_callback); 16843941Svenki if (!class_node_found) 16853941Svenki return; 16865436Sfw157321 16873941Svenki log_printf("\n"); 16883941Svenki log_printf("============================"); 16893941Svenki log_printf(" FRU Status "); 16903941Svenki log_printf("============================"); 16913941Svenki log_printf("\n"); 16923941Svenki 16933941Svenki if (syserrlog == 0) { 16943941Svenki (void) picl_walk_tree_by_class(phyplatformh, 16954802Sfw157321 NULL, NULL, 16964669Sfw157321 sun4v_print_fru_status_callback); 16973941Svenki if (all_status_ok) { 16983941Svenki log_printf("All FRUs are enabled.\n"); 16993941Svenki return; 17003941Svenki } 17013941Svenki } 17023941Svenki log_printf(fmt, "Location", "Name", "Status", 0); 17035028Sfw157321 log_printf("------------------------------------------------------\n"); 17044802Sfw157321 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 17054669Sfw157321 sun4v_print_fru_status_callback); 17063941Svenki } 17073941Svenki 17083941Svenki /*ARGSUSED*/ 17093941Svenki static int 17103941Svenki sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args) 17113941Svenki { 17123941Svenki char rev[PICL_PROPNAMELEN_MAX]; 17133941Svenki picl_errno_t err; 17143941Svenki 17153941Svenki if (!class_node_found) { 17163941Svenki class_node_found = 1; 17173941Svenki return (PICL_WALK_TERMINATE); 17183941Svenki } 17195436Sfw157321 17203941Svenki err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev, 17214669Sfw157321 sizeof (rev)); 17223941Svenki if (err != PICL_SUCCESS) 17233941Svenki return (PICL_WALK_CONTINUE); 17243941Svenki if (strlen(rev) == 0) 17253941Svenki return (PICL_WALK_CONTINUE); 17265436Sfw157321 log_printf("%s", rev); 17273941Svenki log_printf("\n"); 17283941Svenki return (PICL_WALK_CONTINUE); 17293941Svenki } 17303941Svenki 17313941Svenki static void 17323941Svenki sun4v_print_fw_rev() 17333941Svenki { 17343941Svenki if (syserrlog == 0) 17353941Svenki return; 17365436Sfw157321 17373941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 17384669Sfw157321 sun4v_print_fw_rev_callback); 17393941Svenki if (!class_node_found) 17403941Svenki return; 17415436Sfw157321 17423941Svenki log_printf("\n"); 17433941Svenki log_printf("============================"); 17443941Svenki log_printf(" FW Version "); 17453941Svenki log_printf("============================"); 17463941Svenki log_printf("\n"); 17475436Sfw157321 log_printf("Version\n"); 17485028Sfw157321 log_printf("-------------------------------------------------" 17495028Sfw157321 "-----------\n"); 17503941Svenki (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 17514669Sfw157321 sun4v_print_fw_rev_callback); 17523941Svenki } 17533941Svenki 17543941Svenki static void 17555436Sfw157321 sun4v_print_openprom_rev() 17565436Sfw157321 { 17575436Sfw157321 if (syserrlog == 0) 17585436Sfw157321 return; 17595436Sfw157321 17605436Sfw157321 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 17615436Sfw157321 openprom_callback); 17625436Sfw157321 if (!class_node_found) 17635436Sfw157321 return; 17645436Sfw157321 17655436Sfw157321 log_printf("\n"); 17665436Sfw157321 log_printf("======================"); 17675436Sfw157321 log_printf(" System PROM revisions "); 17685436Sfw157321 log_printf("======================="); 17695436Sfw157321 log_printf("\n"); 17705436Sfw157321 log_printf("Version\n"); 17715436Sfw157321 log_printf("-------------------------------------------------" 17725436Sfw157321 "-----------\n"); 17735436Sfw157321 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 17745436Sfw157321 openprom_callback); 17755436Sfw157321 } 17765436Sfw157321 17775436Sfw157321 /* 17785436Sfw157321 * display the OBP and POST prom revisions (if present) 17795436Sfw157321 */ 17805436Sfw157321 /* ARGSUSED */ 17815436Sfw157321 static int 17825436Sfw157321 openprom_callback(picl_nodehdl_t openpromh, void *arg) 17835436Sfw157321 { 17845436Sfw157321 picl_prophdl_t proph; 17855436Sfw157321 picl_prophdl_t tblh; 17865436Sfw157321 picl_prophdl_t rowproph; 17875436Sfw157321 picl_propinfo_t pinfo; 17885436Sfw157321 char *prom_version = NULL; 17895436Sfw157321 char *obp_version = NULL; 17905436Sfw157321 int err; 17915436Sfw157321 17925436Sfw157321 if (!class_node_found) { 17935436Sfw157321 class_node_found = 1; 17945436Sfw157321 return (PICL_WALK_TERMINATE); 17955436Sfw157321 } 17965436Sfw157321 17975436Sfw157321 err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION, 17985436Sfw157321 &pinfo, &proph); 17995436Sfw157321 if (err == PICL_PROPNOTFOUND) 18005436Sfw157321 return (PICL_WALK_TERMINATE); 18015436Sfw157321 else if (err != PICL_SUCCESS) 18025436Sfw157321 return (err); 18035436Sfw157321 18045436Sfw157321 /* 18055436Sfw157321 * If it's a table prop, the first element is OBP revision 18065436Sfw157321 * The second one is POST revision. 18075436Sfw157321 * If it's a charstring prop, the value will be only OBP revision 18085436Sfw157321 */ 18095436Sfw157321 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 18105436Sfw157321 prom_version = (char *)alloca(pinfo.size); 18115436Sfw157321 if (prom_version == NULL) 18125436Sfw157321 return (PICL_FAILURE); 18135436Sfw157321 err = picl_get_propval(proph, prom_version, pinfo.size); 18145436Sfw157321 if (err != PICL_SUCCESS) 18155436Sfw157321 return (err); 18165436Sfw157321 log_printf("%s\n", prom_version); 18175436Sfw157321 } 18185436Sfw157321 18195436Sfw157321 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */ 18205436Sfw157321 return (PICL_WALK_TERMINATE); 18215436Sfw157321 18225436Sfw157321 err = picl_get_propval(proph, &tblh, pinfo.size); 18235436Sfw157321 if (err != PICL_SUCCESS) 18245436Sfw157321 return (err); 18255436Sfw157321 18265436Sfw157321 err = picl_get_next_by_row(tblh, &rowproph); 18275436Sfw157321 if (err == PICL_SUCCESS) { 18285436Sfw157321 /* get first row */ 18295436Sfw157321 err = picl_get_propinfo(rowproph, &pinfo); 18305436Sfw157321 if (err != PICL_SUCCESS) 18315436Sfw157321 return (err); 18325436Sfw157321 18335436Sfw157321 prom_version = (char *)alloca(pinfo.size); 18345436Sfw157321 if (prom_version == NULL) 18355436Sfw157321 return (PICL_FAILURE); 18365436Sfw157321 18375436Sfw157321 err = picl_get_propval(rowproph, prom_version, pinfo.size); 18385436Sfw157321 if (err != PICL_SUCCESS) 18395436Sfw157321 return (err); 18405436Sfw157321 log_printf("%s\n", prom_version); 18415436Sfw157321 18425436Sfw157321 /* get second row */ 18435436Sfw157321 err = picl_get_next_by_col(rowproph, &rowproph); 18445436Sfw157321 if (err == PICL_SUCCESS) { 18455436Sfw157321 err = picl_get_propinfo(rowproph, &pinfo); 18465436Sfw157321 if (err != PICL_SUCCESS) 18475436Sfw157321 return (err); 18485436Sfw157321 18495436Sfw157321 obp_version = (char *)alloca(pinfo.size); 18505436Sfw157321 if (obp_version == NULL) 18515436Sfw157321 return (PICL_FAILURE); 18525436Sfw157321 err = picl_get_propval(rowproph, obp_version, 18535436Sfw157321 pinfo.size); 18545436Sfw157321 if (err != PICL_SUCCESS) 18555436Sfw157321 return (err); 18565436Sfw157321 log_printf("%s\n", obp_version); 18575436Sfw157321 } 18585436Sfw157321 } 18595436Sfw157321 18605436Sfw157321 return (PICL_WALK_TERMINATE); 18615436Sfw157321 } 18625436Sfw157321 18635436Sfw157321 static void 18643941Svenki sun4v_print_chassis_serial_no() 18653941Svenki { 18663941Svenki char val[PICL_PROPNAMELEN_MAX]; 18673941Svenki picl_errno_t err; 18683941Svenki if (syserrlog == 0 || chassish == 0) 18693941Svenki return; 18703941Svenki 18713941Svenki log_printf("\n"); 18723941Svenki log_printf("Chassis Serial Number"); 18733941Svenki log_printf("\n"); 18743941Svenki log_printf("---------------------\n"); 18753941Svenki err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER, 18764669Sfw157321 val, sizeof (val)); 18773941Svenki if (err == PICL_SUCCESS) 18783941Svenki log_printf("%s", val); 18793941Svenki log_printf("\n"); 18803941Svenki } 1881