1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <alloca.h> 31 #include <unistd.h> 32 #include <ctype.h> 33 #include <string.h> 34 #include <kvm.h> 35 #include <varargs.h> 36 #include <time.h> 37 #include <dirent.h> 38 #include <fcntl.h> 39 #include <sys/param.h> 40 #include <sys/stat.h> 41 #include <sys/types.h> 42 #include <sys/utsname.h> 43 #include <sys/openpromio.h> 44 #include <libintl.h> 45 #include <syslog.h> 46 #include <sys/dkio.h> 47 #include <sys/systeminfo.h> 48 #include <picldefs.h> 49 #include <math.h> 50 #include <errno.h> 51 #include "pdevinfo.h" 52 #include "display.h" 53 #include "display_sun4v.h" 54 #include "libprtdiag.h" 55 56 #if !defined(TEXT_DOMAIN) 57 #define TEXT_DOMAIN "SYS_TEST" 58 #endif 59 60 #define MOTHERBOARD "MB" 61 #define NETWORK "network" 62 #define PCIE_COMPATIBLE_STR "pciex" 63 #define PCIX_COMPATIBLE_STR "pci" 64 #define SUN4V_MACHINE "sun4v" 65 #define PARENT_NAMES 10 66 67 /* 68 * Additional OBP properties 69 */ 70 #define OBP_PROP_COMPATIBLE "compatible" 71 #define OBP_PROP_MODEL "model" 72 #define OBP_PROP_SLOT_NAMES "slot-names" 73 #define OBP_PROP_VERSION "version" 74 75 #define PICL_NODE_PHYSICAL_PLATFORM "physical-platform" 76 #define PICL_NODE_CHASSIS "chassis" 77 #define MEMORY_SIZE_FIELD 11 78 #define INVALID_THRESHOLD 1000000 79 80 /* 81 * Additional picl classes 82 */ 83 #ifndef PICL_CLASS_SUN4V 84 #define PICL_CLASS_SUN4V "sun4v" 85 #endif 86 87 #ifndef PICL_PROP_NAC 88 #define PICL_PROP_NAC "nac" 89 #endif 90 91 extern int sys_clk; 92 extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *, 93 picl_nodehdl_t *); 94 95 static picl_nodehdl_t rooth = 0, phyplatformh = 0; 96 static picl_nodehdl_t chassish = 0; 97 static int class_node_found; 98 static int syserrlog; 99 static int all_status_ok; 100 101 /* local functions */ 102 static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **); 103 static void sun4v_display_memory_conf(picl_nodehdl_t); 104 static void sun4v_disp_env_status(); 105 static void sun4v_env_print_fan_sensors(); 106 static void sun4v_env_print_fan_indicators(); 107 static void sun4v_env_print_temp_sensors(); 108 static void sun4v_env_print_temp_indicators(); 109 static void sun4v_env_print_current_sensors(); 110 static void sun4v_env_print_current_indicators(); 111 static void sun4v_env_print_voltage_sensors(); 112 static void sun4v_env_print_voltage_indicators(); 113 static void sun4v_env_print_LEDs(); 114 static void sun4v_print_fru_status(); 115 static void sun4v_print_fw_rev(); 116 static void sun4v_print_chassis_serial_no(); 117 static int openprom_callback(picl_nodehdl_t openpromh, void *arg); 118 static void sun4v_print_openprom_rev(); 119 120 int 121 sun4v_display(Sys_tree *tree, Prom_node *root, int log, 122 picl_nodehdl_t plafh) 123 { 124 void *value; /* used for opaque PROM data */ 125 struct mem_total memory_total; /* Total memory in system */ 126 struct grp_info grps; /* Info on all groups in system */ 127 char machine[MAXSTRLEN]; 128 129 if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1) 130 return (1); 131 if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0) 132 return (1); 133 134 sys_clk = -1; /* System clock freq. (in MHz) */ 135 136 /* 137 * Now display the machine's configuration. We do this if we 138 * are not logging. 139 */ 140 if (!logging) { 141 struct utsname uts_buf; 142 143 /* 144 * Display system banner 145 */ 146 (void) uname(&uts_buf); 147 148 log_printf(dgettext(TEXT_DOMAIN, "System Configuration: " 149 "Sun Microsystems %s %s\n"), uts_buf.machine, 150 get_prop_val(find_prop(root, "banner-name")), 0); 151 152 /* display system clock frequency */ 153 value = get_prop_val(find_prop(root, "clock-frequency")); 154 if (value != NULL) { 155 sys_clk = ((*((int *)value)) + 500000) / 1000000; 156 log_printf(dgettext(TEXT_DOMAIN, "System clock " 157 "frequency: %d MHz\n"), sys_clk, 0); 158 } 159 160 /* Display the Memory Size */ 161 display_memorysize(tree, NULL, &grps, &memory_total); 162 163 /* Display the CPU devices */ 164 sun4v_display_cpu_devices(plafh); 165 166 /* Display the Memory configuration */ 167 class_node_found = 0; 168 sun4v_display_memory_conf(plafh); 169 170 /* Display all the IO cards. */ 171 (void) sun4v_display_pci(plafh); 172 sun4v_display_diaginfo((log || (logging)), root, plafh); 173 174 if (picl_get_root(&rooth) != PICL_SUCCESS) 175 return (1); 176 if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM, 177 &phyplatformh) != PICL_SUCCESS) 178 return (1); 179 180 if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME, 181 PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS, 182 strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS) 183 return (1); 184 185 syserrlog = log; 186 sun4v_disp_env_status(); 187 } 188 return (0); 189 } 190 191 static void 192 get_bus_type(picl_nodehdl_t nodeh, struct io_card *card) 193 { 194 char *compatible; 195 196 (void) strlcpy(card->bus_type, "PCIX", sizeof (card->bus_type)); 197 if (sun4v_get_first_compatible_value(nodeh, &compatible) 198 == PICL_SUCCESS) { 199 if (strncmp(compatible, PCIE_COMPATIBLE_STR, 200 strlen(PCIE_COMPATIBLE_STR)) == 0) 201 (void) strlcpy(card->bus_type, "PCIE", 202 sizeof (card->bus_type)); 203 free(compatible); 204 } 205 } 206 207 static picl_errno_t 208 get_slot_label(picl_nodehdl_t nodeh, struct io_card *card) 209 { 210 char val[PICL_PROPNAMELEN_MAX]; 211 picl_errno_t err; 212 picl_nodehdl_t pnodeh; 213 214 /* 215 * Look for a Label first in the node corresponding to the IO 216 * device. If there's no Label then we might be on the downstream 217 * side of a bridge (i.e. the IO device/card has a bridge on it). 218 * So look at the parent and see if it has a Label. 219 */ 220 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 221 sizeof (val)); 222 if (err == PICL_PROPNOTFOUND) { 223 if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh, 224 sizeof (pnodeh)) == PICL_SUCCESS) 225 err = picl_get_propval_by_name(pnodeh, PICL_PROP_LABEL, 226 val, sizeof (val)); 227 } 228 229 if (err == PICL_SUCCESS) 230 (void) strlcpy(card->slot_str, val, sizeof (card->slot_str)); 231 232 card->slot = -1; 233 return (err); 234 } 235 236 static void 237 get_slot_number(picl_nodehdl_t nodeh, struct io_card *card) 238 { 239 picl_errno_t err; 240 picl_prophdl_t proph; 241 picl_propinfo_t pinfo; 242 picl_nodehdl_t pnodeh; 243 uint8_t *pval; 244 uint32_t dev_mask; 245 char uaddr[MAXSTRLEN]; 246 int i; 247 248 if (get_slot_label(nodeh, card) == PICL_SUCCESS) 249 return; 250 err = PICL_SUCCESS; 251 while (err == PICL_SUCCESS) { 252 if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh, 253 sizeof (pnodeh)) != PICL_SUCCESS) { 254 (void) strlcpy(card->slot_str, MOTHERBOARD, 255 sizeof (card->slot_str)); 256 card->slot = -1; 257 return; 258 } 259 if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES, 260 &pinfo, &proph) == PICL_SUCCESS) { 261 break; 262 } 263 nodeh = pnodeh; 264 } 265 if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr, 266 sizeof (uaddr)) != PICL_SUCCESS) { 267 (void) strlcpy(card->slot_str, MOTHERBOARD, 268 sizeof (card->slot_str)); 269 card->slot = -1; 270 return; 271 } 272 pval = (uint8_t *)malloc(pinfo.size); 273 if (!pval) { 274 (void) strlcpy(card->slot_str, MOTHERBOARD, 275 sizeof (card->slot_str)); 276 card->slot = -1; 277 return; 278 } 279 if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) { 280 (void) strlcpy(card->slot_str, MOTHERBOARD, 281 sizeof (card->slot_str)); 282 card->slot = -1; 283 free(pval); 284 return; 285 } 286 287 dev_mask = 0; 288 for (i = 0; i < sizeof (dev_mask); i++) 289 dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i)); 290 for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) { 291 if (uaddr[i] == ',') { 292 uaddr[i] = '\0'; 293 break; 294 } 295 } 296 card->slot = atol(uaddr); 297 if (((1 << card->slot) & dev_mask) == 0) { 298 (void) strlcpy(card->slot_str, MOTHERBOARD, 299 sizeof (card->slot_str)); 300 card->slot = -1; 301 } else { 302 char *p = (char *)(pval+sizeof (dev_mask)); 303 int shift = sizeof (uint32_t)*8-1-card->slot; 304 uint32_t x = (dev_mask << shift) >> shift; 305 int count = 0; /* count # of 1's in x */ 306 int i = 0; 307 while (x != 0) { 308 count++; 309 x &= x-1; 310 } 311 while (count > 1) { 312 while (p[i++] != '\0') 313 ; 314 count--; 315 } 316 (void) strlcpy(card->slot_str, (char *)(p+i), 317 sizeof (card->slot_str)); 318 } 319 free(pval); 320 } 321 322 /* 323 * add all io devices under pci in io list 324 */ 325 /* ARGSUSED */ 326 static int 327 sun4v_pci_callback(picl_nodehdl_t pcih, void *args) 328 { 329 char path[PICL_PROPNAMELEN_MAX]; 330 char class[PICL_CLASSNAMELEN_MAX]; 331 char name[PICL_PROPNAMELEN_MAX]; 332 char model[PICL_PROPNAMELEN_MAX]; 333 char binding_name[PICL_PROPNAMELEN_MAX]; 334 char val[PICL_PROPNAMELEN_MAX]; 335 char *compatible; 336 picl_errno_t err; 337 picl_nodehdl_t nodeh; 338 struct io_card pci_card; 339 340 /* Walk through the children */ 341 342 err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 343 sizeof (picl_nodehdl_t)); 344 345 while (err == PICL_SUCCESS) { 346 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 347 class, sizeof (class)); 348 if (err != PICL_SUCCESS) 349 return (err); 350 351 if (args) { 352 char *val = args; 353 if (strcmp(class, val) == 0) { 354 err = picl_get_propval_by_name(nodeh, 355 PICL_PROP_PEER, &nodeh, 356 sizeof (picl_nodehdl_t)); 357 continue; 358 } else if (strcmp(val, PICL_CLASS_PCIEX) == 0 && 359 strcmp(class, PICL_CLASS_PCI) == 0) { 360 err = picl_get_propval_by_name(nodeh, 361 PICL_PROP_PEER, &nodeh, 362 sizeof (picl_nodehdl_t)); 363 continue; 364 } else if (strcmp(val, PICL_CLASS_PCI) == 0 && 365 strcmp(class, PICL_CLASS_PCIEX) == 0) { 366 err = picl_get_propval_by_name(nodeh, 367 PICL_PROP_PEER, &nodeh, 368 sizeof (picl_nodehdl_t)); 369 continue; 370 } 371 } 372 373 err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH, 374 path, sizeof (path)); 375 if (err != PICL_SUCCESS) 376 return (err); 377 378 (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes)); 379 380 get_bus_type(nodeh, &pci_card); 381 get_slot_number(nodeh, &pci_card); 382 383 err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name, 384 sizeof (name)); 385 if (err == PICL_PROPNOTFOUND) 386 (void) strlcpy(name, "", sizeof (name)); 387 else if (err != PICL_SUCCESS) 388 return (err); 389 390 err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val, 391 sizeof (val)); 392 if (err == PICL_PROPNOTFOUND) 393 (void) strlcpy(val, "", sizeof (val)); 394 else if (err != PICL_SUCCESS) 395 return (err); 396 397 (void) snprintf(pci_card.status, sizeof (pci_card.status), 398 "%s", pci_card.slot_str); 399 400 /* 401 * Get the name of this card. If binding_name is found, 402 * name will be <nodename>-<binding_name>. 403 */ 404 err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, 405 binding_name, sizeof (binding_name)); 406 if (err == PICL_SUCCESS) { 407 if (strcmp(name, binding_name) != 0) { 408 (void) strlcat(name, "-", sizeof (name)); 409 (void) strlcat(name, binding_name, 410 sizeof (name)); 411 } 412 } else if (err == PICL_PROPNOTFOUND) { 413 /* 414 * if compatible prop is not found, name will be 415 * <nodename>-<compatible> 416 */ 417 err = sun4v_get_first_compatible_value(nodeh, 418 &compatible); 419 if (err == PICL_SUCCESS) { 420 (void) strlcat(name, "-", sizeof (name)); 421 (void) strlcat(name, compatible, 422 sizeof (name)); 423 free(compatible); 424 } 425 } else 426 return (err); 427 428 (void) strlcpy(pci_card.name, name, sizeof (pci_card.name)); 429 430 /* Get the model of this card */ 431 432 err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL, 433 model, sizeof (model)); 434 if (err == PICL_PROPNOTFOUND) 435 (void) strlcpy(model, "", sizeof (model)); 436 else if (err != PICL_SUCCESS) 437 return (err); 438 (void) strlcpy(pci_card.model, model, sizeof (pci_card.model)); 439 440 /* Print NAC name */ 441 log_printf("%-18s", pci_card.status); 442 /* Print IO Type */ 443 log_printf("%-6s", pci_card.bus_type); 444 /* Printf Card Name */ 445 log_printf("%-44s", pci_card.name); 446 /* Print Card Model */ 447 log_printf("%-8s", pci_card.model); 448 log_printf("\n"); 449 /* Print Status */ 450 log_printf("%-18s", val); 451 /* Print IO Type */ 452 log_printf("%-6s", ""); 453 /* Print Parent Path */ 454 log_printf("%-44s", pci_card.notes); 455 log_printf("\n"); 456 457 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 458 sizeof (picl_nodehdl_t)); 459 } 460 return (PICL_WALK_CONTINUE); 461 } 462 463 /* 464 * display_pci 465 * Display all the PCI IO cards on this board. 466 */ 467 void 468 sun4v_display_pci(picl_nodehdl_t plafh) 469 { 470 char *fmt = "%-17s %-5s %-44s %-8s"; 471 /* Have we printed the column headings? */ 472 static int banner = FALSE; 473 474 if (banner == FALSE) { 475 log_printf("\n"); 476 log_printf("================================"); 477 log_printf(" IO Devices "); 478 log_printf("================================"); 479 log_printf("\n"); 480 log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0); 481 log_printf("\n"); 482 log_printf(fmt, "Status", "Type", "Path", "", 0); 483 log_printf("\n"); 484 log_printf("---------------------------------" 485 "-------------------------------------------\n"); 486 banner = TRUE; 487 } 488 489 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, 490 PICL_CLASS_PCIEX, sun4v_pci_callback); 491 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI, 492 PICL_CLASS_PCI, sun4v_pci_callback); 493 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V, 494 PICL_CLASS_SUN4V, sun4v_pci_callback); 495 } 496 497 /* 498 * return the first compatible value 499 */ 500 static int 501 sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf) 502 { 503 picl_errno_t err; 504 picl_prophdl_t proph; 505 picl_propinfo_t pinfo; 506 picl_prophdl_t tblh; 507 picl_prophdl_t rowproph; 508 char *pval; 509 510 err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE, 511 &pinfo, &proph); 512 if (err != PICL_SUCCESS) 513 return (err); 514 515 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 516 pval = malloc(pinfo.size); 517 if (pval == NULL) 518 return (PICL_FAILURE); 519 err = picl_get_propval(proph, pval, pinfo.size); 520 if (err != PICL_SUCCESS) { 521 free(pval); 522 return (err); 523 } 524 *outbuf = pval; 525 return (PICL_SUCCESS); 526 } 527 528 if (pinfo.type != PICL_PTYPE_TABLE) 529 return (PICL_FAILURE); 530 531 /* get first string from table */ 532 err = picl_get_propval(proph, &tblh, pinfo.size); 533 if (err != PICL_SUCCESS) 534 return (err); 535 536 err = picl_get_next_by_row(tblh, &rowproph); 537 if (err != PICL_SUCCESS) 538 return (err); 539 540 err = picl_get_propinfo(rowproph, &pinfo); 541 if (err != PICL_SUCCESS) 542 return (err); 543 544 pval = malloc(pinfo.size); 545 if (pval == NULL) 546 return (PICL_FAILURE); 547 548 err = picl_get_propval(rowproph, pval, pinfo.size); 549 if (err != PICL_SUCCESS) { 550 free(pval); 551 return (err); 552 } 553 554 *outbuf = pval; 555 return (PICL_SUCCESS); 556 } 557 558 /* 559 * print size of a memory segment 560 */ 561 static void 562 print_memory_segment_size(uint64_t size) 563 { 564 uint64_t kbyte = 1024; 565 uint64_t mbyte = kbyte * kbyte; 566 uint64_t gbyte = kbyte * mbyte; 567 char buf[MEMORY_SIZE_FIELD]; 568 569 if (size >= gbyte) { 570 if (size % gbyte == 0) 571 (void) snprintf(buf, sizeof (buf), "%d GB", 572 (int)(size / gbyte)); 573 else 574 (void) snprintf(buf, sizeof (buf), "%.2f GB", 575 (float)size / gbyte); 576 } else if (size >= mbyte) { 577 if (size % mbyte == 0) 578 (void) snprintf(buf, sizeof (buf), "%d MB", 579 (int)(size / mbyte)); 580 else 581 (void) snprintf(buf, sizeof (buf), "%.2f MB", 582 (float)size / mbyte); 583 } else { 584 if (size % kbyte == 0) 585 (void) snprintf(buf, sizeof (buf), "%d KB", 586 (int)(size / kbyte)); 587 else 588 (void) snprintf(buf, sizeof (buf), "%.2f KB", 589 (float)size / kbyte); 590 } 591 log_printf("%-7s ", buf); 592 } 593 594 /* 595 * Enumerate banks and dimms within a memory segment. We're handed 596 * the first bank within the segment - we assume there are dimms 597 * (memory-module) nodes underneath. 598 */ 599 static void 600 print_memory_segment_contain(picl_nodehdl_t bank_nodeh) 601 { 602 char val[PICL_PROPNAMELEN_MAX]; 603 picl_nodehdl_t module_nodeh; 604 int flag = 0; 605 606 do { 607 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD, 608 &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS) 609 continue; 610 do { 611 if (picl_get_propval_by_name(module_nodeh, 612 PICL_PROP_NAC, val, sizeof (val)) != 613 PICL_SUCCESS) 614 continue; 615 else { 616 if (!flag) { 617 log_printf("%-30s\n", val); 618 flag = 1; 619 } else 620 log_printf("%57s\n", val); 621 } 622 } while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER, 623 &module_nodeh, sizeof (picl_nodehdl_t)) == 624 PICL_SUCCESS); 625 } while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER, 626 &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS); 627 } 628 629 /* 630 * Search node where _class=="memory-segment" 631 * print "Base Address", "Size", etc 632 */ 633 /*ARGSUSED*/ 634 static int 635 sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args) 636 { 637 uint64_t base; 638 uint64_t size; 639 uint64_t ifactor; 640 picl_errno_t err = PICL_SUCCESS; 641 642 if (class_node_found == 0) { 643 class_node_found = 1; 644 return (PICL_WALK_TERMINATE); 645 } 646 while (err == PICL_SUCCESS) { 647 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS, 648 &base, sizeof (base)); 649 if (err != PICL_SUCCESS) 650 break; 651 err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE, 652 &size, sizeof (size)); 653 if (err != PICL_SUCCESS) 654 break; 655 err = picl_get_propval_by_name(nodeh, 656 PICL_PROP_INTERLEAVE_FACTOR, &ifactor, 657 sizeof (ifactor)); 658 if (err != PICL_SUCCESS) 659 break; 660 log_printf("%-13llx", base); 661 print_memory_segment_size(size); 662 log_printf("%-18lld", ifactor); 663 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, 664 &nodeh, sizeof (nodeh)); 665 if (err == PICL_SUCCESS) 666 print_memory_segment_contain(nodeh); 667 log_printf("\n"); 668 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 669 sizeof (picl_nodehdl_t)); 670 } 671 672 return (PICL_WALK_CONTINUE); 673 } 674 675 /*ARGSUSED*/ 676 void 677 sun4v_display_memory_conf(picl_nodehdl_t plafh) 678 { 679 char *fmt = "%-12s %-7s %-9s %-20s"; 680 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 681 NULL, sun4v_memory_conf_callback); 682 if (class_node_found == 0) 683 return; 684 log_printf("\n"); 685 log_printf("============================"); 686 log_printf(" Memory Configuration "); 687 log_printf("============================"); 688 log_printf("\n"); 689 log_printf("Segment Table:\n"); 690 log_printf( 691 "---------------------------------------------------------\n"); 692 log_printf(fmt, "Base Address", "Size", "Interleave Factor", 693 "Contains", 0); 694 log_printf("\n"); 695 log_printf( 696 "---------------------------------------------------------\n"); 697 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 698 NULL, sun4v_memory_conf_callback); 699 } 700 701 void 702 sun4v_display_cpu_devices(picl_nodehdl_t plafh) 703 { 704 char *fmt = "%-12s %-5s %-8s %-19s %-5s"; 705 706 /* 707 * Display the table header for CPUs . Then display the CPU 708 * frequency, cache size, and processor revision of all cpus. 709 */ 710 log_printf(dgettext(TEXT_DOMAIN, 711 "\n" 712 "=========================" 713 " CPUs " 714 "===============================================" 715 "\n" 716 "\n")); 717 log_printf(fmt, "", "", "", "CPU", "CPU", 0); 718 log_printf("\n"); 719 log_printf(fmt, "Location", "CPU", "Freq", 720 "Implementation", "State", 0); 721 log_printf("\n"); 722 log_printf(fmt, "------------", "-----", "--------", 723 "-------------------", "-----", 0); 724 log_printf("\n"); 725 726 (void) picl_walk_tree_by_class(plafh, "cpu", "cpu", sun4v_display_cpus); 727 } 728 729 /* 730 * Display the CPUs present on this board. 731 */ 732 /*ARGSUSED*/ 733 int 734 sun4v_display_cpus(picl_nodehdl_t cpuh, void* args) 735 { 736 int status; 737 picl_prophdl_t proph; 738 picl_prophdl_t tblh; 739 picl_prophdl_t rowproph; 740 picl_propinfo_t propinfo; 741 int *int_value; 742 int cpuid; 743 char *comp_value; 744 char *no_prop_value = " "; 745 char freq_str[MAXSTRLEN]; 746 char fru_name[MAXSTRLEN]; 747 char state[MAXSTRLEN]; 748 749 /* 750 * Get cpuid property and print it and the NAC name 751 */ 752 status = picl_get_propinfo_by_name(cpuh, "cpuid", &propinfo, &proph); 753 if (status == PICL_SUCCESS) { 754 status = picl_get_propval(proph, &cpuid, sizeof (cpuid)); 755 if (status != PICL_SUCCESS) { 756 log_printf("%-13s", no_prop_value); 757 log_printf("%-6s", no_prop_value); 758 } else { 759 (void) snprintf(fru_name, sizeof (fru_name), "%s%d", 760 CPU_STRAND_NAC, cpuid); 761 log_printf("%-13s", fru_name); 762 log_printf("%-6d", cpuid); 763 } 764 } else { 765 log_printf("%-13s", no_prop_value); 766 log_printf("%-6s", no_prop_value); 767 } 768 769 clock_freq: 770 status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo, 771 &proph); 772 if (status == PICL_SUCCESS) { 773 int_value = malloc(propinfo.size); 774 if (int_value == NULL) { 775 log_printf("%-9s", no_prop_value); 776 goto compatible; 777 } 778 status = picl_get_propval(proph, int_value, propinfo.size); 779 if (status != PICL_SUCCESS) { 780 log_printf("%-9s", no_prop_value); 781 } else { 782 /* Running frequency */ 783 (void) snprintf(freq_str, sizeof (freq_str), "%d MHz", 784 CLK_FREQ_TO_MHZ(*int_value)); 785 log_printf("%-9s", freq_str); 786 } 787 free(int_value); 788 } else 789 log_printf("%-9s", no_prop_value); 790 791 compatible: 792 status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo, 793 &proph); 794 if (status == PICL_SUCCESS) { 795 if (propinfo.type == PICL_PTYPE_CHARSTRING) { 796 /* 797 * Compatible Property only has 1 value 798 */ 799 comp_value = malloc(propinfo.size); 800 if (comp_value == NULL) { 801 log_printf("%-20s", no_prop_value, 0); 802 goto state; 803 } 804 status = picl_get_propval(proph, comp_value, 805 propinfo.size); 806 if (status != PICL_SUCCESS) 807 log_printf("%-20s", no_prop_value, 0); 808 else 809 log_printf("%-20s", comp_value, 0); 810 free(comp_value); 811 } else if (propinfo.type == PICL_PTYPE_TABLE) { 812 /* 813 * Compatible Property has multiple values 814 */ 815 status = picl_get_propval(proph, &tblh, propinfo.size); 816 if (status != PICL_SUCCESS) { 817 log_printf("%-20s", no_prop_value, 0); 818 goto state; 819 } 820 status = picl_get_next_by_row(tblh, &rowproph); 821 if (status != PICL_SUCCESS) { 822 log_printf("%-20s", no_prop_value, 0); 823 goto state; 824 } 825 826 status = picl_get_propinfo(rowproph, &propinfo); 827 if (status != PICL_SUCCESS) { 828 log_printf("%-20s", no_prop_value, 0); 829 goto state; 830 } 831 832 comp_value = malloc(propinfo.size); 833 if (comp_value == NULL) { 834 log_printf("%-20s", no_prop_value, 0); 835 goto state; 836 } 837 status = picl_get_propval(rowproph, comp_value, 838 propinfo.size); 839 if (status != PICL_SUCCESS) 840 log_printf("%-20s", no_prop_value, 0); 841 else 842 log_printf("%-20s", comp_value, 0); 843 free(comp_value); 844 } 845 } else 846 log_printf("%-20s", no_prop_value, 0); 847 848 state: 849 status = picl_get_propinfo_by_name(cpuh, PICL_PROP_STATE, 850 &propinfo, &proph); 851 if (status == PICL_SUCCESS) { 852 status = picl_get_propval(proph, state, sizeof (state)); 853 if (status != PICL_SUCCESS) { 854 log_printf("%-9s", no_prop_value); 855 } else { 856 log_printf("%-9s", state); 857 } 858 } else 859 log_printf("%-9s", no_prop_value); 860 861 done: 862 log_printf("\n"); 863 return (PICL_WALK_CONTINUE); 864 } 865 866 void 867 sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh) 868 { 869 #ifdef lint 870 flag = flag; 871 root = root; 872 plafh = plafh; 873 #endif 874 /* 875 * This function is intentionally empty 876 */ 877 } 878 879 void 880 display_boardnum(int num) 881 { 882 log_printf("%2d ", num, 0); 883 } 884 885 static void 886 sun4v_disp_env_status() 887 { 888 if (phyplatformh == 0) 889 return; 890 log_printf("\n"); 891 log_printf("============================"); 892 log_printf(" Environmental Status "); 893 log_printf("============================"); 894 log_printf("\n"); 895 896 class_node_found = 0; 897 all_status_ok = 1; 898 sun4v_env_print_fan_sensors(); 899 900 class_node_found = 0; 901 all_status_ok = 1; 902 sun4v_env_print_fan_indicators(); 903 904 class_node_found = 0; 905 all_status_ok = 1; 906 sun4v_env_print_temp_sensors(); 907 908 class_node_found = 0; 909 all_status_ok = 1; 910 sun4v_env_print_temp_indicators(); 911 912 class_node_found = 0; 913 all_status_ok = 1; 914 sun4v_env_print_current_sensors(); 915 916 class_node_found = 0; 917 all_status_ok = 1; 918 sun4v_env_print_current_indicators(); 919 920 class_node_found = 0; 921 all_status_ok = 1; 922 sun4v_env_print_voltage_sensors(); 923 924 class_node_found = 0; 925 all_status_ok = 1; 926 sun4v_env_print_voltage_indicators(); 927 928 class_node_found = 0; 929 sun4v_env_print_LEDs(); 930 931 class_node_found = 0; 932 all_status_ok = 1; 933 sun4v_print_fru_status(); 934 935 class_node_found = 0; 936 sun4v_print_fw_rev(); 937 938 class_node_found = 0; 939 sun4v_print_openprom_rev(); 940 941 sun4v_print_chassis_serial_no(); 942 } 943 944 /*ARGSUSED*/ 945 static int 946 sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args) 947 { 948 char val[PICL_PROPNAMELEN_MAX]; 949 picl_nodehdl_t parenth; 950 char *names[PARENT_NAMES]; 951 char *base_units[PICL_PROPNAMELEN_MAX]; 952 char *loc; 953 int i; 954 char *prop; 955 picl_errno_t err; 956 int32_t lo_warning, lo_shutdown, lo_poweroff; 957 int32_t hi_warning, hi_shutdown, hi_poweroff; 958 int32_t current_val; 959 int32_t exponent; 960 double display_val; 961 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 962 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 963 sensor_status_t sensor_status = SENSOR_OK; 964 965 if (class_node_found == 0) { 966 class_node_found = 1; 967 return (PICL_WALK_TERMINATE); 968 } 969 970 prop = (char *)args; 971 if (!prop) { 972 sensor_status = SENSOR_UNKNOWN; 973 all_status_ok = 0; 974 } else { 975 err = picl_get_propval_by_name(nodeh, 976 PICL_PROP_OPERATIONAL_STATUS, val, 977 sizeof (val)); 978 if (err == PICL_SUCCESS) { 979 if (strcmp(val, "disabled") == 0) { 980 sensor_status = SENSOR_DISABLED; 981 } 982 } 983 } 984 985 if (sensor_status != SENSOR_DISABLED && 986 sensor_status != SENSOR_UNKNOWN) { 987 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 988 sizeof (current_val)) != PICL_SUCCESS) { 989 sensor_status = SENSOR_UNKNOWN; 990 } else { 991 if (picl_get_propval_by_name(nodeh, 992 PICL_PROP_LOW_WARNING, 993 &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS) 994 lo_warning = INVALID_THRESHOLD; 995 if (picl_get_propval_by_name(nodeh, 996 PICL_PROP_LOW_SHUTDOWN, 997 &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS) 998 lo_shutdown = INVALID_THRESHOLD; 999 if (picl_get_propval_by_name(nodeh, 1000 PICL_PROP_LOW_POWER_OFF, 1001 &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS) 1002 lo_poweroff = INVALID_THRESHOLD; 1003 if (picl_get_propval_by_name(nodeh, 1004 PICL_PROP_HIGH_WARNING, 1005 &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS) 1006 hi_warning = INVALID_THRESHOLD; 1007 if (picl_get_propval_by_name(nodeh, 1008 PICL_PROP_HIGH_SHUTDOWN, 1009 &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS) 1010 hi_shutdown = INVALID_THRESHOLD; 1011 if (picl_get_propval_by_name(nodeh, 1012 PICL_PROP_HIGH_POWER_OFF, 1013 &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS) 1014 hi_poweroff = INVALID_THRESHOLD; 1015 1016 if ((lo_poweroff != INVALID_THRESHOLD && 1017 current_val <= lo_poweroff) || 1018 (hi_poweroff != INVALID_THRESHOLD && 1019 current_val >= hi_poweroff)) { 1020 sensor_status = SENSOR_FAILED; 1021 } else if ((lo_shutdown != INVALID_THRESHOLD && 1022 current_val <= lo_shutdown) || 1023 (hi_shutdown != INVALID_THRESHOLD && 1024 current_val >= hi_shutdown)) { 1025 sensor_status = SENSOR_FAILED; 1026 } else if ((lo_warning != INVALID_THRESHOLD && 1027 current_val <= lo_warning) || 1028 (hi_warning != INVALID_THRESHOLD && 1029 current_val >= hi_warning)) { 1030 sensor_status = SENSOR_WARN; 1031 } else { 1032 sensor_status = SENSOR_OK; 1033 } 1034 } 1035 } 1036 1037 if (syserrlog == 0) { 1038 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 1039 all_status_ok = 0; 1040 return (PICL_WALK_TERMINATE); 1041 } 1042 if (sensor_status == SENSOR_OK) { 1043 return (PICL_WALK_CONTINUE); 1044 } 1045 } 1046 1047 /* 1048 * If we're here then prtdiag was invoked with "-v" or we have 1049 * a sensor that is beyond a threshold, so give them a book to 1050 * read instead of the Cliff Notes. 1051 */ 1052 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 1053 sizeof (parenth)); 1054 if (err != PICL_SUCCESS) { 1055 log_printf("\n"); 1056 return (PICL_WALK_CONTINUE); 1057 } 1058 1059 /* gather up the path name for the sensor */ 1060 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 1061 for (i = 0; i < PARENT_NAMES; i++) { 1062 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 1063 NULL) { 1064 while (--i > -1) 1065 free(names[i]); 1066 free(loc); 1067 loc = NULL; 1068 } 1069 } 1070 } 1071 i = 0; 1072 if (loc != 0) { 1073 while (err == PICL_SUCCESS) { 1074 if (parenth == phyplatformh) 1075 break; 1076 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1077 names[i++], PICL_PROPNAMELEN_MAX); 1078 if (err != PICL_SUCCESS) { 1079 i--; 1080 break; 1081 } 1082 if (i == PARENT_NAMES) 1083 break; 1084 err = picl_get_propval_by_name(parenth, 1085 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 1086 } 1087 loc[0] = '\0'; 1088 if (--i > -1) { 1089 (void) strlcat(loc, names[i], 1090 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1091 } 1092 while (--i > -1) { 1093 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 1094 PARENT_NAMES); 1095 (void) strlcat(loc, names[i], 1096 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1097 } 1098 log_printf("%-35s", loc); 1099 for (i = 0; i < PARENT_NAMES; i++) 1100 free(names[i]); 1101 free(loc); 1102 } else { 1103 log_printf("%-35s", " "); 1104 } 1105 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 1106 sizeof (val)); 1107 if (err == PICL_SUCCESS) 1108 log_printf("%-15s", val); 1109 1110 /* 1111 * Get the exponent if present, and do a little math so that 1112 * if we need to we can print a normalized value for the 1113 * sensor reading. 1114 */ 1115 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT, 1116 &exponent, sizeof (exponent)) != PICL_SUCCESS) 1117 exponent = 0; 1118 if (exponent == 0) 1119 display_val = (double)current_val; 1120 else { 1121 display_val = (double)current_val * 1122 pow((double)10, (double)exponent); 1123 1124 /* 1125 * Sometimes ILOM will scale a sensor reading but 1126 * there will be nothing to the right of the decimal 1127 * once that value is normalized. Setting the 1128 * exponent to zero will prevent the printf below 1129 * from printing extraneous zeros. Otherwise a 1130 * negative exponent is used to set the precision 1131 * for the printf. 1132 */ 1133 if ((int)display_val == display_val || exponent > 0) 1134 exponent = 0; 1135 } 1136 1137 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS, 1138 base_units, sizeof (base_units)); 1139 if (err != PICL_SUCCESS) 1140 base_units[0] = '\0'; 1141 1142 switch (sensor_status) { 1143 case SENSOR_FAILED: 1144 log_printf("%-s", "failed ("); 1145 log_printf("%-.*f", abs(exponent), display_val); 1146 log_printf("%-s %s", base_units, ")"); 1147 break; 1148 case SENSOR_WARN: 1149 log_printf("%-s", "warning ("); 1150 log_printf("%-.*f", abs(exponent), display_val); 1151 log_printf("%-s %s", base_units, ")"); 1152 break; 1153 case SENSOR_DISABLED: 1154 log_printf("%-s", "disabled"); 1155 break; 1156 case SENSOR_OK: 1157 log_printf("%-s", "ok"); 1158 break; 1159 default: 1160 log_printf("%-s", "unknown"); 1161 break; 1162 } 1163 1164 log_printf("\n"); 1165 return (PICL_WALK_CONTINUE); 1166 } 1167 1168 /*ARGSUSED*/ 1169 static int 1170 sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args) 1171 { 1172 char current_val[PICL_PROPNAMELEN_MAX]; 1173 char expected_val[PICL_PROPNAMELEN_MAX]; 1174 char label[PICL_PROPNAMELEN_MAX]; 1175 picl_nodehdl_t parenth; 1176 char *names[PARENT_NAMES]; 1177 char *loc; 1178 int i = 0; 1179 char *prop = (char *)args; 1180 picl_errno_t err = PICL_SUCCESS; 1181 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 1182 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 1183 sensor_status_t sensor_status = SENSOR_OK; 1184 1185 if (class_node_found == 0) { 1186 class_node_found = 1; 1187 return (PICL_WALK_TERMINATE); 1188 } 1189 1190 prop = (char *)args; 1191 if (!prop) { 1192 sensor_status = SENSOR_UNKNOWN; 1193 all_status_ok = 0; 1194 } else { 1195 err = picl_get_propval_by_name(nodeh, 1196 PICL_PROP_OPERATIONAL_STATUS, current_val, 1197 sizeof (current_val)); 1198 if (err == PICL_SUCCESS) { 1199 if (strcmp(current_val, "disabled") == 0) { 1200 sensor_status = SENSOR_DISABLED; 1201 } 1202 } 1203 } 1204 1205 if (sensor_status != SENSOR_DISABLED && 1206 sensor_status != SENSOR_UNKNOWN) { 1207 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 1208 sizeof (current_val)) != PICL_SUCCESS) { 1209 (void) strlcpy(current_val, "unknown", 1210 sizeof (current_val)); 1211 sensor_status = SENSOR_UNKNOWN; 1212 } else { 1213 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED, 1214 &expected_val, sizeof (expected_val)) != 1215 PICL_SUCCESS) { 1216 sensor_status = SENSOR_UNKNOWN; 1217 } else { 1218 if (strncmp(current_val, expected_val, 1219 sizeof (current_val)) == 0) { 1220 sensor_status = SENSOR_OK; 1221 } else { 1222 sensor_status = SENSOR_FAILED; 1223 } 1224 } 1225 } 1226 } 1227 1228 if (syserrlog == 0) { 1229 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 1230 all_status_ok = 0; 1231 return (PICL_WALK_TERMINATE); 1232 } 1233 if (sensor_status == SENSOR_OK) { 1234 return (PICL_WALK_CONTINUE); 1235 } 1236 } 1237 1238 /* 1239 * If we're here then prtdiag was invoked with "-v" or we have 1240 * a sensor that is beyond a threshold, so give them a book to 1241 * read instead of the Cliff Notes. 1242 */ 1243 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 1244 sizeof (parenth)); 1245 if (err != PICL_SUCCESS) { 1246 log_printf("\n"); 1247 return (PICL_WALK_CONTINUE); 1248 } 1249 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 1250 for (i = 0; i < PARENT_NAMES; i++) { 1251 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 1252 NULL) { 1253 while (--i > -1) 1254 free(names[i]); 1255 free(loc); 1256 loc = NULL; 1257 } 1258 } 1259 } 1260 i = 0; 1261 if (loc) { 1262 while (err == PICL_SUCCESS) { 1263 if (parenth == phyplatformh) 1264 break; 1265 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1266 names[i++], PICL_PROPNAMELEN_MAX); 1267 if (err != PICL_SUCCESS) { 1268 i--; 1269 break; 1270 } 1271 if (i == PARENT_NAMES) 1272 break; 1273 err = picl_get_propval_by_name(parenth, 1274 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 1275 } 1276 loc[0] = '\0'; 1277 if (--i > -1) { 1278 (void) strlcat(loc, names[i], 1279 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1280 } 1281 while (--i > -1) { 1282 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 1283 PARENT_NAMES); 1284 (void) strlcat(loc, names[i], 1285 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1286 } 1287 log_printf("%-35s", loc); 1288 for (i = 0; i < PARENT_NAMES; i++) 1289 free(names[i]); 1290 free(loc); 1291 } else { 1292 log_printf("%-35s", ""); 1293 } 1294 1295 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 1296 sizeof (label)); 1297 if (err != PICL_SUCCESS) 1298 (void) strlcpy(label, "", sizeof (label)); 1299 log_printf("%-15s", label); 1300 1301 log_printf("%-8s", current_val); 1302 1303 log_printf("\n"); 1304 return (PICL_WALK_CONTINUE); 1305 } 1306 1307 static void 1308 sun4v_env_print_fan_sensors() 1309 { 1310 char *fmt = "%-34s %-14s %-10s\n"; 1311 /* 1312 * If there isn't any fan sensor node, return now. 1313 */ 1314 (void) picl_walk_tree_by_class(phyplatformh, 1315 PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED, 1316 sun4v_env_print_sensor_callback); 1317 if (!class_node_found) 1318 return; 1319 log_printf("Fan sensors:\n"); 1320 if (syserrlog == 0) { 1321 (void) picl_walk_tree_by_class(phyplatformh, 1322 PICL_CLASS_RPM_SENSOR, 1323 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 1324 if (all_status_ok) { 1325 log_printf("All fan sensors are OK.\n"); 1326 return; 1327 } 1328 } 1329 log_printf("-------------------------------------------------" 1330 "-----------\n"); 1331 log_printf(fmt, "Location", "Sensor", "Status", 0); 1332 log_printf("-------------------------------------------------" 1333 "-----------\n"); 1334 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR, 1335 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 1336 } 1337 1338 static void 1339 sun4v_env_print_fan_indicators() 1340 { 1341 char *fmt = "%-34s %-14s %-10s\n"; 1342 (void) picl_walk_tree_by_class(phyplatformh, 1343 PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION, 1344 sun4v_env_print_indicator_callback); 1345 if (!class_node_found) 1346 return; 1347 log_printf("\nFan indicators:\n"); 1348 if (syserrlog == 0) { 1349 (void) picl_walk_tree_by_class(phyplatformh, 1350 PICL_CLASS_RPM_INDICATOR, 1351 (void *)PICL_PROP_CONDITION, 1352 sun4v_env_print_indicator_callback); 1353 if (all_status_ok) { 1354 log_printf("All fan indicators are OK.\n"); 1355 return; 1356 } 1357 } 1358 log_printf("-------------------------------------------------" 1359 "-----------\n"); 1360 log_printf(fmt, "Location", "Sensor", "Condition", 0); 1361 log_printf("-------------------------------------------------" 1362 "-----------\n"); 1363 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR, 1364 (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback); 1365 } 1366 1367 static void 1368 sun4v_env_print_temp_sensors() 1369 { 1370 char *fmt = "%-34s %-14s %-10s\n"; 1371 (void) picl_walk_tree_by_class(phyplatformh, 1372 PICL_CLASS_TEMPERATURE_SENSOR, 1373 (void *)PICL_PROP_TEMPERATURE, 1374 sun4v_env_print_sensor_callback); 1375 if (!class_node_found) 1376 return; 1377 1378 log_printf("\nTemperature sensors:\n"); 1379 if (syserrlog == 0) { 1380 (void) picl_walk_tree_by_class(phyplatformh, 1381 PICL_CLASS_TEMPERATURE_SENSOR, 1382 PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 1383 if (all_status_ok) { 1384 log_printf("All temperature sensors are OK.\n"); 1385 return; 1386 } 1387 } 1388 log_printf("-------------------------------------------------" 1389 "-----------\n"); 1390 log_printf(fmt, "Location", "Sensor", "Status", 0); 1391 log_printf("-------------------------------------------------" 1392 "-----------\n"); 1393 (void) picl_walk_tree_by_class(phyplatformh, 1394 PICL_CLASS_TEMPERATURE_SENSOR, 1395 (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 1396 } 1397 1398 static void 1399 sun4v_env_print_temp_indicators() 1400 { 1401 char *fmt = "%-34s %-14s %-8s\n"; 1402 (void) picl_walk_tree_by_class(phyplatformh, 1403 PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION, 1404 sun4v_env_print_indicator_callback); 1405 if (!class_node_found) 1406 return; 1407 log_printf("\nTemperature indicators:\n"); 1408 if (syserrlog == 0) { 1409 (void) picl_walk_tree_by_class(phyplatformh, 1410 PICL_CLASS_TEMPERATURE_INDICATOR, 1411 (void *)PICL_PROP_CONDITION, 1412 sun4v_env_print_indicator_callback); 1413 if (all_status_ok) { 1414 log_printf("All temperature indicators are OK.\n"); 1415 return; 1416 } 1417 } 1418 log_printf("-------------------------------------------------" 1419 "-----------\n"); 1420 log_printf(fmt, "Location", "Indicator", "Condition", 0); 1421 log_printf("-------------------------------------------------" 1422 "-----------\n"); 1423 (void) picl_walk_tree_by_class(phyplatformh, 1424 PICL_CLASS_TEMPERATURE_INDICATOR, 1425 (void *)PICL_PROP_CONDITION, 1426 sun4v_env_print_indicator_callback); 1427 } 1428 1429 static void 1430 sun4v_env_print_current_sensors() 1431 { 1432 char *fmt = "%-34s %-14s %-10s\n"; 1433 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR, 1434 (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 1435 if (!class_node_found) 1436 return; 1437 log_printf("\nCurrent sensors:\n"); 1438 if (syserrlog == 0) { 1439 (void) picl_walk_tree_by_class(phyplatformh, 1440 PICL_CLASS_CURRENT_SENSOR, 1441 PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 1442 if (all_status_ok) { 1443 log_printf("All current sensors are OK.\n"); 1444 return; 1445 } 1446 } 1447 log_printf("-------------------------------------------------" 1448 "-----------\n"); 1449 log_printf(fmt, "Location", "Sensor", "Status", 0); 1450 log_printf("-------------------------------------------------" 1451 "-----------\n"); 1452 (void) picl_walk_tree_by_class(phyplatformh, 1453 PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT, 1454 sun4v_env_print_sensor_callback); 1455 } 1456 1457 static void 1458 sun4v_env_print_current_indicators() 1459 { 1460 char *fmt = "%-34s %-14s %-8s\n"; 1461 (void) picl_walk_tree_by_class(phyplatformh, 1462 PICL_CLASS_CURRENT_INDICATOR, 1463 (void *)PICL_PROP_CONDITION, 1464 sun4v_env_print_indicator_callback); 1465 if (!class_node_found) 1466 return; 1467 log_printf("\nCurrent indicators:\n"); 1468 if (syserrlog == 0) { 1469 (void) picl_walk_tree_by_class(phyplatformh, 1470 PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION, 1471 sun4v_env_print_indicator_callback); 1472 if (all_status_ok) { 1473 log_printf("All current indicators are OK.\n"); 1474 return; 1475 } 1476 } 1477 log_printf("-------------------------------------------------" 1478 "-----------\n"); 1479 log_printf(fmt, "Location", "Indicator", "Condition", 0); 1480 log_printf("-------------------------------------------------" 1481 "-----------\n"); 1482 (void) picl_walk_tree_by_class(phyplatformh, 1483 PICL_CLASS_CURRENT_INDICATOR, 1484 (void *)PICL_PROP_CONDITION, 1485 sun4v_env_print_indicator_callback); 1486 } 1487 1488 static void 1489 sun4v_env_print_voltage_sensors() 1490 { 1491 char *fmt = "%-34s %-14s %-10s\n"; 1492 (void) picl_walk_tree_by_class(phyplatformh, 1493 PICL_CLASS_VOLTAGE_SENSOR, 1494 PICL_PROP_VOLTAGE, 1495 sun4v_env_print_sensor_callback); 1496 if (!class_node_found) 1497 return; 1498 log_printf("\nVoltage sensors:\n"); 1499 if (syserrlog == 0) { 1500 (void) picl_walk_tree_by_class(phyplatformh, 1501 PICL_CLASS_VOLTAGE_SENSOR, 1502 PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback); 1503 if (all_status_ok) { 1504 log_printf("All voltage sensors are OK.\n"); 1505 return; 1506 } 1507 } 1508 log_printf("-------------------------------------------------" 1509 "-----------\n"); 1510 log_printf(fmt, "Location", "Sensor", "Status", 0); 1511 log_printf("-------------------------------------------------" 1512 "-----------\n"); 1513 (void) picl_walk_tree_by_class(phyplatformh, 1514 PICL_CLASS_VOLTAGE_SENSOR, 1515 (void *)PICL_PROP_VOLTAGE, 1516 sun4v_env_print_sensor_callback); 1517 } 1518 1519 static void 1520 sun4v_env_print_voltage_indicators() 1521 { 1522 char *fmt = "%-34s %-14s %-8s\n"; 1523 (void) picl_walk_tree_by_class(phyplatformh, 1524 PICL_CLASS_VOLTAGE_INDICATOR, 1525 (void *)PICL_PROP_CONDITION, 1526 sun4v_env_print_indicator_callback); 1527 if (!class_node_found) 1528 return; 1529 log_printf("\nVoltage indicators:\n"); 1530 if (syserrlog == 0) { 1531 (void) picl_walk_tree_by_class(phyplatformh, 1532 PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION, 1533 sun4v_env_print_indicator_callback); 1534 if (all_status_ok) { 1535 log_printf("All voltage indicators are OK.\n"); 1536 return; 1537 } 1538 } 1539 log_printf("-------------------------------------------------" 1540 "-----------\n"); 1541 log_printf(fmt, "Location", "Indicator", "Condition", 0); 1542 log_printf("-------------------------------------------------" 1543 "-----------\n"); 1544 (void) picl_walk_tree_by_class(phyplatformh, 1545 PICL_CLASS_VOLTAGE_INDICATOR, 1546 (void *)PICL_PROP_CONDITION, 1547 sun4v_env_print_indicator_callback); 1548 } 1549 1550 static void 1551 sun4v_env_print_LEDs() 1552 { 1553 char *fmt = "%-34s %-14s %-8s\n"; 1554 if (syserrlog == 0) 1555 return; 1556 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 1557 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 1558 if (!class_node_found) 1559 return; 1560 log_printf("\nLEDs:\n"); 1561 log_printf("-------------------------------------------------" 1562 "-----------\n"); 1563 log_printf(fmt, "Location", "LED", "State", 0); 1564 log_printf("-------------------------------------------------" 1565 "-----------\n"); 1566 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 1567 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 1568 } 1569 1570 /*ARGSUSED*/ 1571 static int 1572 sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args) 1573 { 1574 char label[PICL_PROPNAMELEN_MAX]; 1575 char status[PICL_PROPNAMELEN_MAX]; 1576 picl_errno_t err; 1577 picl_prophdl_t proph; 1578 picl_nodehdl_t parenth; 1579 char *names[PARENT_NAMES]; 1580 char *loc; 1581 int i; 1582 1583 if (!class_node_found) { 1584 class_node_found = 1; 1585 return (PICL_WALK_TERMINATE); 1586 } 1587 err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph); 1588 if (err != PICL_SUCCESS) 1589 return (PICL_WALK_CONTINUE); 1590 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 1591 sizeof (label)); 1592 if (err != PICL_SUCCESS) 1593 return (PICL_WALK_CONTINUE); 1594 err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS, 1595 status, sizeof (status)); 1596 if (err != PICL_SUCCESS) 1597 return (PICL_WALK_CONTINUE); 1598 if (syserrlog == 0) { 1599 if (strcmp(status, "disabled") == 0) { 1600 if (all_status_ok) { 1601 all_status_ok = 0; 1602 return (PICL_WALK_TERMINATE); 1603 } 1604 } else 1605 return (PICL_WALK_CONTINUE); 1606 } 1607 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 1608 sizeof (parenth)); 1609 if (err != PICL_SUCCESS) { 1610 log_printf("\n"); 1611 return (PICL_WALK_CONTINUE); 1612 } 1613 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL) 1614 return (PICL_WALK_TERMINATE); 1615 for (i = 0; i < PARENT_NAMES; i++) 1616 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) { 1617 while (--i > -1) 1618 free(names[i]); 1619 free(loc); 1620 return (PICL_WALK_TERMINATE); 1621 } 1622 i = 0; 1623 while (err == PICL_SUCCESS) { 1624 if (parenth == phyplatformh) 1625 break; 1626 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1627 names[i++], PICL_PROPNAMELEN_MAX); 1628 if (err != PICL_SUCCESS) { 1629 i--; 1630 break; 1631 } 1632 if (i == PARENT_NAMES) 1633 break; 1634 err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT, 1635 &parenth, sizeof (parenth)); 1636 } 1637 loc[0] = '\0'; 1638 if (--i > -1) { 1639 (void) strlcat(loc, names[i], 1640 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1641 } 1642 while (--i > -1) { 1643 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1644 (void) strlcat(loc, names[i], 1645 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1646 } 1647 log_printf("%-35s", loc); 1648 for (i = 0; i < PARENT_NAMES; i++) 1649 free(names[i]); 1650 free(loc); 1651 log_printf("%-10s", label); 1652 log_printf("%-9s", status); 1653 log_printf("\n"); 1654 return (PICL_WALK_CONTINUE); 1655 } 1656 1657 static void 1658 sun4v_print_fru_status() 1659 { 1660 char *fmt = "%-34s %-9s %-8s\n"; 1661 1662 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1663 sun4v_print_fru_status_callback); 1664 if (!class_node_found) 1665 return; 1666 1667 log_printf("\n"); 1668 log_printf("============================"); 1669 log_printf(" FRU Status "); 1670 log_printf("============================"); 1671 log_printf("\n"); 1672 1673 if (syserrlog == 0) { 1674 (void) picl_walk_tree_by_class(phyplatformh, 1675 NULL, NULL, 1676 sun4v_print_fru_status_callback); 1677 if (all_status_ok) { 1678 log_printf("All FRUs are enabled.\n"); 1679 return; 1680 } 1681 } 1682 log_printf(fmt, "Location", "Name", "Status", 0); 1683 log_printf("------------------------------------------------------\n"); 1684 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1685 sun4v_print_fru_status_callback); 1686 } 1687 1688 /*ARGSUSED*/ 1689 static int 1690 sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args) 1691 { 1692 char rev[PICL_PROPNAMELEN_MAX]; 1693 picl_errno_t err; 1694 1695 if (!class_node_found) { 1696 class_node_found = 1; 1697 return (PICL_WALK_TERMINATE); 1698 } 1699 1700 err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev, 1701 sizeof (rev)); 1702 if (err != PICL_SUCCESS) 1703 return (PICL_WALK_CONTINUE); 1704 if (strlen(rev) == 0) 1705 return (PICL_WALK_CONTINUE); 1706 log_printf("%s", rev); 1707 log_printf("\n"); 1708 return (PICL_WALK_CONTINUE); 1709 } 1710 1711 static void 1712 sun4v_print_fw_rev() 1713 { 1714 if (syserrlog == 0) 1715 return; 1716 1717 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1718 sun4v_print_fw_rev_callback); 1719 if (!class_node_found) 1720 return; 1721 1722 log_printf("\n"); 1723 log_printf("============================"); 1724 log_printf(" FW Version "); 1725 log_printf("============================"); 1726 log_printf("\n"); 1727 log_printf("Version\n"); 1728 log_printf("-------------------------------------------------" 1729 "-----------\n"); 1730 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1731 sun4v_print_fw_rev_callback); 1732 } 1733 1734 static void 1735 sun4v_print_openprom_rev() 1736 { 1737 if (syserrlog == 0) 1738 return; 1739 1740 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 1741 openprom_callback); 1742 if (!class_node_found) 1743 return; 1744 1745 log_printf("\n"); 1746 log_printf("======================"); 1747 log_printf(" System PROM revisions "); 1748 log_printf("======================="); 1749 log_printf("\n"); 1750 log_printf("Version\n"); 1751 log_printf("-------------------------------------------------" 1752 "-----------\n"); 1753 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 1754 openprom_callback); 1755 } 1756 1757 /* 1758 * display the OBP and POST prom revisions (if present) 1759 */ 1760 /* ARGSUSED */ 1761 static int 1762 openprom_callback(picl_nodehdl_t openpromh, void *arg) 1763 { 1764 picl_prophdl_t proph; 1765 picl_prophdl_t tblh; 1766 picl_prophdl_t rowproph; 1767 picl_propinfo_t pinfo; 1768 char *prom_version = NULL; 1769 char *obp_version = NULL; 1770 int err; 1771 1772 if (!class_node_found) { 1773 class_node_found = 1; 1774 return (PICL_WALK_TERMINATE); 1775 } 1776 1777 err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION, 1778 &pinfo, &proph); 1779 if (err == PICL_PROPNOTFOUND) 1780 return (PICL_WALK_TERMINATE); 1781 else if (err != PICL_SUCCESS) 1782 return (err); 1783 1784 /* 1785 * If it's a table prop, the first element is OBP revision 1786 * The second one is POST revision. 1787 * If it's a charstring prop, the value will be only OBP revision 1788 */ 1789 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 1790 prom_version = (char *)alloca(pinfo.size); 1791 if (prom_version == NULL) 1792 return (PICL_FAILURE); 1793 err = picl_get_propval(proph, prom_version, pinfo.size); 1794 if (err != PICL_SUCCESS) 1795 return (err); 1796 log_printf("%s\n", prom_version); 1797 } 1798 1799 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */ 1800 return (PICL_WALK_TERMINATE); 1801 1802 err = picl_get_propval(proph, &tblh, pinfo.size); 1803 if (err != PICL_SUCCESS) 1804 return (err); 1805 1806 err = picl_get_next_by_row(tblh, &rowproph); 1807 if (err == PICL_SUCCESS) { 1808 /* get first row */ 1809 err = picl_get_propinfo(rowproph, &pinfo); 1810 if (err != PICL_SUCCESS) 1811 return (err); 1812 1813 prom_version = (char *)alloca(pinfo.size); 1814 if (prom_version == NULL) 1815 return (PICL_FAILURE); 1816 1817 err = picl_get_propval(rowproph, prom_version, pinfo.size); 1818 if (err != PICL_SUCCESS) 1819 return (err); 1820 log_printf("%s\n", prom_version); 1821 1822 /* get second row */ 1823 err = picl_get_next_by_col(rowproph, &rowproph); 1824 if (err == PICL_SUCCESS) { 1825 err = picl_get_propinfo(rowproph, &pinfo); 1826 if (err != PICL_SUCCESS) 1827 return (err); 1828 1829 obp_version = (char *)alloca(pinfo.size); 1830 if (obp_version == NULL) 1831 return (PICL_FAILURE); 1832 err = picl_get_propval(rowproph, obp_version, 1833 pinfo.size); 1834 if (err != PICL_SUCCESS) 1835 return (err); 1836 log_printf("%s\n", obp_version); 1837 } 1838 } 1839 1840 return (PICL_WALK_TERMINATE); 1841 } 1842 1843 static void 1844 sun4v_print_chassis_serial_no() 1845 { 1846 char val[PICL_PROPNAMELEN_MAX]; 1847 picl_errno_t err; 1848 if (syserrlog == 0 || chassish == 0) 1849 return; 1850 1851 log_printf("\n"); 1852 log_printf("Chassis Serial Number"); 1853 log_printf("\n"); 1854 log_printf("---------------------\n"); 1855 err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER, 1856 val, sizeof (val)); 1857 if (err == PICL_SUCCESS) 1858 log_printf("%s", val); 1859 log_printf("\n"); 1860 } 1861