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("%-34s", 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 %-33s %-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 uint64_t tbyte = kbyte * gbyte; 568 char buf[MEMORY_SIZE_FIELD]; 569 570 if (size >= tbyte) { 571 if (size % tbyte == 0) 572 (void) snprintf(buf, sizeof (buf), "%d TB", 573 (int)(size / tbyte)); 574 else 575 (void) snprintf(buf, sizeof (buf), "%.2f TB", 576 (float)size / tbyte); 577 } else if (size >= gbyte) { 578 if (size % gbyte == 0) 579 (void) snprintf(buf, sizeof (buf), "%d GB", 580 (int)(size / gbyte)); 581 else 582 (void) snprintf(buf, sizeof (buf), "%.2f GB", 583 (float)size / gbyte); 584 } else if (size >= mbyte) { 585 if (size % mbyte == 0) 586 (void) snprintf(buf, sizeof (buf), "%d MB", 587 (int)(size / mbyte)); 588 else 589 (void) snprintf(buf, sizeof (buf), "%.2f MB", 590 (float)size / mbyte); 591 } else { 592 if (size % kbyte == 0) 593 (void) snprintf(buf, sizeof (buf), "%d KB", 594 (int)(size / kbyte)); 595 else 596 (void) snprintf(buf, sizeof (buf), "%.2f KB", 597 (float)size / kbyte); 598 } 599 log_printf("%-9s", buf); 600 } 601 602 /* 603 * Enumerate banks and dimms within a memory segment. We're handed 604 * the first bank within the segment - we assume there are dimms 605 * (memory-module) nodes underneath. 606 */ 607 static void 608 print_memory_segment_contain(picl_nodehdl_t bank_nodeh) 609 { 610 char val[PICL_PROPNAMELEN_MAX]; 611 picl_nodehdl_t module_nodeh; 612 int flag = 0; 613 uint64_t size; 614 615 do { 616 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_CHILD, 617 &module_nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS) 618 continue; 619 if (picl_get_propval_by_name(bank_nodeh, PICL_PROP_SIZE, 620 &size, sizeof (size)) == PICL_SUCCESS) { 621 if (!flag) { 622 print_memory_segment_size(size); 623 } else { 624 log_printf(" " 625 " "); 626 print_memory_segment_size(size); 627 flag = 0; 628 } 629 } 630 do { 631 if (picl_get_propval_by_name(module_nodeh, 632 PICL_PROP_NAC, val, sizeof (val)) != 633 PICL_SUCCESS) 634 continue; 635 else { 636 if (!flag) { 637 log_printf("%s\n", val); 638 flag = 1; 639 } else { 640 log_printf("%s%s\n", 641 " " 642 " ", 643 val); 644 } 645 } 646 } while (picl_get_propval_by_name(module_nodeh, PICL_PROP_PEER, 647 &module_nodeh, sizeof (picl_nodehdl_t)) == 648 PICL_SUCCESS); 649 } while (picl_get_propval_by_name(bank_nodeh, PICL_PROP_PEER, 650 &bank_nodeh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS); 651 } 652 653 /* 654 * Search node where _class=="memory-segment" 655 * print "Base Address", "Size", etc 656 */ 657 /*ARGSUSED*/ 658 static int 659 sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args) 660 { 661 uint64_t base; 662 uint64_t size; 663 uint64_t ifactor; 664 picl_errno_t err = PICL_SUCCESS; 665 666 if (class_node_found == 0) { 667 class_node_found = 1; 668 return (PICL_WALK_TERMINATE); 669 } 670 while (err == PICL_SUCCESS) { 671 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS, 672 &base, sizeof (base)); 673 if (err != PICL_SUCCESS) 674 break; 675 err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE, 676 &size, sizeof (size)); 677 if (err != PICL_SUCCESS) 678 break; 679 err = picl_get_propval_by_name(nodeh, 680 PICL_PROP_INTERLEAVE_FACTOR, &ifactor, 681 sizeof (ifactor)); 682 if (err != PICL_SUCCESS) 683 break; 684 log_printf("0x%-13llx", base); 685 print_memory_segment_size(size); 686 log_printf("%-12lld", ifactor); 687 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, 688 &nodeh, sizeof (nodeh)); 689 if (err == PICL_SUCCESS) 690 print_memory_segment_contain(nodeh); 691 log_printf("\n"); 692 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 693 sizeof (picl_nodehdl_t)); 694 } 695 696 return (PICL_WALK_CONTINUE); 697 } 698 699 /*ARGSUSED*/ 700 void 701 sun4v_display_memory_conf(picl_nodehdl_t plafh) 702 { 703 char *fmt = "%-14s %-8s %-11s %-8s %-s"; 704 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 705 NULL, sun4v_memory_conf_callback); 706 if (class_node_found == 0) 707 return; 708 log_printf("\n"); 709 log_printf("======================="); 710 log_printf(" Physical Memory Configuration "); 711 log_printf("========================"); 712 log_printf("\n"); 713 log_printf("Segment Table:\n"); 714 log_printf( 715 "--------------------------------------------------------------\n"); 716 log_printf(fmt, "Base", "Segment", "Interleave", "Bank", "Contains", 0); 717 log_printf("\n"); 718 log_printf(fmt, "Address", "Size", "Factor", "Size", "Modules", 0); 719 log_printf("\n"); 720 log_printf( 721 "--------------------------------------------------------------\n"); 722 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 723 NULL, sun4v_memory_conf_callback); 724 } 725 726 void 727 sun4v_display_cpu_devices(picl_nodehdl_t plafh) 728 { 729 char *fmt = "%-6s %-9s %-22s %-6s"; 730 731 /* 732 * Display the table header for CPUs . Then display the CPU 733 * frequency, cache size, and processor revision of all cpus. 734 */ 735 log_printf(dgettext(TEXT_DOMAIN, 736 "\n" 737 "================================" 738 " Virtual CPUs " 739 "================================" 740 "\n" 741 "\n")); 742 log_printf("\n"); 743 log_printf(fmt, "CPU ID", "Frequency", "Implementation", 744 "Status", 0); 745 log_printf("\n"); 746 log_printf(fmt, "------", "---------", 747 "----------------------", "-------", 0); 748 log_printf("\n"); 749 750 (void) picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU, 751 sun4v_display_cpus); 752 } 753 754 /* 755 * Display the CPUs present on this board. 756 */ 757 /*ARGSUSED*/ 758 int 759 sun4v_display_cpus(picl_nodehdl_t cpuh, void* args) 760 { 761 int status; 762 picl_prophdl_t proph; 763 picl_prophdl_t tblh; 764 picl_prophdl_t rowproph; 765 picl_propinfo_t propinfo; 766 int *int_value; 767 int cpuid; 768 char *comp_value; 769 char *no_prop_value = " "; 770 char freq_str[MAXSTRLEN]; 771 char state[MAXSTRLEN]; 772 773 /* 774 * Get cpuid property and print it and the NAC name 775 */ 776 status = picl_get_propinfo_by_name(cpuh, OBP_PROP_CPUID, &propinfo, 777 &proph); 778 if (status == PICL_SUCCESS) { 779 status = picl_get_propval(proph, &cpuid, sizeof (cpuid)); 780 if (status != PICL_SUCCESS) { 781 log_printf("%-7s", no_prop_value); 782 } else { 783 log_printf("%-7d", cpuid); 784 } 785 } else { 786 log_printf("%-7s", no_prop_value); 787 } 788 789 clock_freq: 790 status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo, 791 &proph); 792 if (status == PICL_SUCCESS) { 793 int_value = malloc(propinfo.size); 794 if (int_value == NULL) { 795 log_printf("%-10s", no_prop_value); 796 goto compatible; 797 } 798 status = picl_get_propval(proph, int_value, propinfo.size); 799 if (status != PICL_SUCCESS) { 800 log_printf("%-10s", no_prop_value); 801 } else { 802 /* Running frequency */ 803 (void) snprintf(freq_str, sizeof (freq_str), "%d MHz", 804 CLK_FREQ_TO_MHZ(*int_value)); 805 log_printf("%-10s", freq_str); 806 } 807 free(int_value); 808 } else 809 log_printf("%-10s", no_prop_value); 810 811 compatible: 812 status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo, 813 &proph); 814 if (status == PICL_SUCCESS) { 815 if (propinfo.type == PICL_PTYPE_CHARSTRING) { 816 /* 817 * Compatible Property only has 1 value 818 */ 819 comp_value = malloc(propinfo.size); 820 if (comp_value == NULL) { 821 log_printf("%-23s", no_prop_value, 0); 822 goto state; 823 } 824 status = picl_get_propval(proph, comp_value, 825 propinfo.size); 826 if (status != PICL_SUCCESS) 827 log_printf("%-23s", no_prop_value, 0); 828 else 829 log_printf("%-23s", comp_value, 0); 830 free(comp_value); 831 } else if (propinfo.type == PICL_PTYPE_TABLE) { 832 /* 833 * Compatible Property has multiple values 834 */ 835 status = picl_get_propval(proph, &tblh, propinfo.size); 836 if (status != PICL_SUCCESS) { 837 log_printf("%-23s", no_prop_value, 0); 838 goto state; 839 } 840 status = picl_get_next_by_row(tblh, &rowproph); 841 if (status != PICL_SUCCESS) { 842 log_printf("%-23s", no_prop_value, 0); 843 goto state; 844 } 845 846 status = picl_get_propinfo(rowproph, &propinfo); 847 if (status != PICL_SUCCESS) { 848 log_printf("%-23s", no_prop_value, 0); 849 goto state; 850 } 851 852 comp_value = malloc(propinfo.size); 853 if (comp_value == NULL) { 854 log_printf("%-23s", no_prop_value, 0); 855 goto state; 856 } 857 status = picl_get_propval(rowproph, comp_value, 858 propinfo.size); 859 if (status != PICL_SUCCESS) 860 log_printf("%-23s", no_prop_value, 0); 861 else 862 log_printf("%-23s", comp_value, 0); 863 free(comp_value); 864 } 865 } else 866 log_printf("%-23s", no_prop_value, 0); 867 868 state: 869 status = picl_get_propinfo_by_name(cpuh, PICL_PROP_STATE, 870 &propinfo, &proph); 871 if (status == PICL_SUCCESS) { 872 status = picl_get_propval(proph, state, sizeof (state)); 873 if (status != PICL_SUCCESS) { 874 log_printf("%-9s", no_prop_value); 875 } else { 876 log_printf("%-9s", state); 877 } 878 } else 879 log_printf("%-9s", no_prop_value); 880 881 done: 882 log_printf("\n"); 883 return (PICL_WALK_CONTINUE); 884 } 885 886 void 887 sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh) 888 { 889 #ifdef lint 890 flag = flag; 891 root = root; 892 plafh = plafh; 893 #endif 894 /* 895 * This function is intentionally empty 896 */ 897 } 898 899 void 900 display_boardnum(int num) 901 { 902 log_printf("%2d ", num, 0); 903 } 904 905 static void 906 sun4v_disp_env_status() 907 { 908 if (phyplatformh == 0) 909 return; 910 log_printf("\n"); 911 log_printf("============================"); 912 log_printf(" Environmental Status "); 913 log_printf("============================"); 914 log_printf("\n"); 915 916 class_node_found = 0; 917 all_status_ok = 1; 918 sun4v_env_print_fan_sensors(); 919 920 class_node_found = 0; 921 all_status_ok = 1; 922 sun4v_env_print_fan_indicators(); 923 924 class_node_found = 0; 925 all_status_ok = 1; 926 sun4v_env_print_temp_sensors(); 927 928 class_node_found = 0; 929 all_status_ok = 1; 930 sun4v_env_print_temp_indicators(); 931 932 class_node_found = 0; 933 all_status_ok = 1; 934 sun4v_env_print_current_sensors(); 935 936 class_node_found = 0; 937 all_status_ok = 1; 938 sun4v_env_print_current_indicators(); 939 940 class_node_found = 0; 941 all_status_ok = 1; 942 sun4v_env_print_voltage_sensors(); 943 944 class_node_found = 0; 945 all_status_ok = 1; 946 sun4v_env_print_voltage_indicators(); 947 948 class_node_found = 0; 949 sun4v_env_print_LEDs(); 950 951 class_node_found = 0; 952 all_status_ok = 1; 953 sun4v_print_fru_status(); 954 955 class_node_found = 0; 956 sun4v_print_fw_rev(); 957 958 class_node_found = 0; 959 sun4v_print_openprom_rev(); 960 961 sun4v_print_chassis_serial_no(); 962 } 963 964 /*ARGSUSED*/ 965 static int 966 sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args) 967 { 968 char val[PICL_PROPNAMELEN_MAX]; 969 picl_nodehdl_t parenth; 970 char *names[PARENT_NAMES]; 971 char *base_units[PICL_PROPNAMELEN_MAX]; 972 char *loc; 973 int i; 974 char *prop; 975 picl_errno_t err; 976 int32_t lo_warning, lo_shutdown, lo_poweroff; 977 int32_t hi_warning, hi_shutdown, hi_poweroff; 978 int32_t current_val; 979 int32_t exponent; 980 double display_val; 981 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 982 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 983 sensor_status_t sensor_status = SENSOR_OK; 984 985 if (class_node_found == 0) { 986 class_node_found = 1; 987 return (PICL_WALK_TERMINATE); 988 } 989 990 prop = (char *)args; 991 if (!prop) { 992 sensor_status = SENSOR_UNKNOWN; 993 all_status_ok = 0; 994 } else { 995 err = picl_get_propval_by_name(nodeh, 996 PICL_PROP_OPERATIONAL_STATUS, val, 997 sizeof (val)); 998 if (err == PICL_SUCCESS) { 999 if (strcmp(val, "disabled") == 0) { 1000 sensor_status = SENSOR_DISABLED; 1001 } 1002 } 1003 } 1004 1005 if (sensor_status != SENSOR_DISABLED && 1006 sensor_status != SENSOR_UNKNOWN) { 1007 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 1008 sizeof (current_val)) != PICL_SUCCESS) { 1009 sensor_status = SENSOR_UNKNOWN; 1010 } else { 1011 if (picl_get_propval_by_name(nodeh, 1012 PICL_PROP_LOW_WARNING, 1013 &lo_warning, sizeof (lo_warning)) != PICL_SUCCESS) 1014 lo_warning = INVALID_THRESHOLD; 1015 if (picl_get_propval_by_name(nodeh, 1016 PICL_PROP_LOW_SHUTDOWN, 1017 &lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS) 1018 lo_shutdown = INVALID_THRESHOLD; 1019 if (picl_get_propval_by_name(nodeh, 1020 PICL_PROP_LOW_POWER_OFF, 1021 &lo_poweroff, sizeof (lo_poweroff)) != PICL_SUCCESS) 1022 lo_poweroff = INVALID_THRESHOLD; 1023 if (picl_get_propval_by_name(nodeh, 1024 PICL_PROP_HIGH_WARNING, 1025 &hi_warning, sizeof (hi_warning)) != PICL_SUCCESS) 1026 hi_warning = INVALID_THRESHOLD; 1027 if (picl_get_propval_by_name(nodeh, 1028 PICL_PROP_HIGH_SHUTDOWN, 1029 &hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS) 1030 hi_shutdown = INVALID_THRESHOLD; 1031 if (picl_get_propval_by_name(nodeh, 1032 PICL_PROP_HIGH_POWER_OFF, 1033 &hi_poweroff, sizeof (hi_poweroff)) != PICL_SUCCESS) 1034 hi_poweroff = INVALID_THRESHOLD; 1035 1036 if ((lo_poweroff != INVALID_THRESHOLD && 1037 current_val <= lo_poweroff) || 1038 (hi_poweroff != INVALID_THRESHOLD && 1039 current_val >= hi_poweroff)) { 1040 sensor_status = SENSOR_FAILED; 1041 } else if ((lo_shutdown != INVALID_THRESHOLD && 1042 current_val <= lo_shutdown) || 1043 (hi_shutdown != INVALID_THRESHOLD && 1044 current_val >= hi_shutdown)) { 1045 sensor_status = SENSOR_FAILED; 1046 } else if ((lo_warning != INVALID_THRESHOLD && 1047 current_val <= lo_warning) || 1048 (hi_warning != INVALID_THRESHOLD && 1049 current_val >= hi_warning)) { 1050 sensor_status = SENSOR_WARN; 1051 } else { 1052 sensor_status = SENSOR_OK; 1053 } 1054 } 1055 } 1056 1057 if (syserrlog == 0) { 1058 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 1059 all_status_ok = 0; 1060 return (PICL_WALK_TERMINATE); 1061 } 1062 if (sensor_status == SENSOR_OK) { 1063 return (PICL_WALK_CONTINUE); 1064 } 1065 } 1066 1067 /* 1068 * If we're here then prtdiag was invoked with "-v" or we have 1069 * a sensor that is beyond a threshold, so give them a book to 1070 * read instead of the Cliff Notes. 1071 */ 1072 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 1073 sizeof (parenth)); 1074 if (err != PICL_SUCCESS) { 1075 log_printf("\n"); 1076 return (PICL_WALK_CONTINUE); 1077 } 1078 1079 /* gather up the path name for the sensor */ 1080 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 1081 for (i = 0; i < PARENT_NAMES; i++) { 1082 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 1083 NULL) { 1084 while (--i > -1) 1085 free(names[i]); 1086 free(loc); 1087 loc = NULL; 1088 } 1089 } 1090 } 1091 i = 0; 1092 if (loc != 0) { 1093 while (err == PICL_SUCCESS) { 1094 if (parenth == phyplatformh) 1095 break; 1096 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1097 names[i++], PICL_PROPNAMELEN_MAX); 1098 if (err != PICL_SUCCESS) { 1099 i--; 1100 break; 1101 } 1102 if (i == PARENT_NAMES) 1103 break; 1104 err = picl_get_propval_by_name(parenth, 1105 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 1106 } 1107 loc[0] = '\0'; 1108 if (--i > -1) { 1109 (void) strlcat(loc, names[i], 1110 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1111 } 1112 while (--i > -1) { 1113 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 1114 PARENT_NAMES); 1115 (void) strlcat(loc, names[i], 1116 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1117 } 1118 log_printf("%-35s", loc); 1119 for (i = 0; i < PARENT_NAMES; i++) 1120 free(names[i]); 1121 free(loc); 1122 } else { 1123 log_printf("%-35s", " "); 1124 } 1125 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val, 1126 sizeof (val)); 1127 if (err == PICL_SUCCESS) 1128 log_printf("%-15s", val); 1129 1130 /* 1131 * Get the exponent if present, and do a little math so that 1132 * if we need to we can print a normalized value for the 1133 * sensor reading. 1134 */ 1135 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPONENT, 1136 &exponent, sizeof (exponent)) != PICL_SUCCESS) 1137 exponent = 0; 1138 if (exponent == 0) 1139 display_val = (double)current_val; 1140 else { 1141 display_val = (double)current_val * 1142 pow((double)10, (double)exponent); 1143 1144 /* 1145 * Sometimes ILOM will scale a sensor reading but 1146 * there will be nothing to the right of the decimal 1147 * once that value is normalized. Setting the 1148 * exponent to zero will prevent the printf below 1149 * from printing extraneous zeros. Otherwise a 1150 * negative exponent is used to set the precision 1151 * for the printf. 1152 */ 1153 if ((int)display_val == display_val || exponent > 0) 1154 exponent = 0; 1155 } 1156 1157 err = picl_get_propval_by_name(nodeh, PICL_PROP_BASE_UNITS, 1158 base_units, sizeof (base_units)); 1159 if (err != PICL_SUCCESS) 1160 base_units[0] = '\0'; 1161 1162 switch (sensor_status) { 1163 case SENSOR_FAILED: 1164 log_printf("%-s", "failed ("); 1165 log_printf("%-.*f", abs(exponent), display_val); 1166 log_printf("%-s %s", base_units, ")"); 1167 break; 1168 case SENSOR_WARN: 1169 log_printf("%-s", "warning ("); 1170 log_printf("%-.*f", abs(exponent), display_val); 1171 log_printf("%-s %s", base_units, ")"); 1172 break; 1173 case SENSOR_DISABLED: 1174 log_printf("%-s", "disabled"); 1175 break; 1176 case SENSOR_OK: 1177 log_printf("%-s", "ok"); 1178 break; 1179 default: 1180 log_printf("%-s", "unknown"); 1181 break; 1182 } 1183 1184 log_printf("\n"); 1185 return (PICL_WALK_CONTINUE); 1186 } 1187 1188 /*ARGSUSED*/ 1189 static int 1190 sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args) 1191 { 1192 char current_val[PICL_PROPNAMELEN_MAX]; 1193 char expected_val[PICL_PROPNAMELEN_MAX]; 1194 char label[PICL_PROPNAMELEN_MAX]; 1195 picl_nodehdl_t parenth; 1196 char *names[PARENT_NAMES]; 1197 char *loc; 1198 int i = 0; 1199 char *prop = (char *)args; 1200 picl_errno_t err = PICL_SUCCESS; 1201 typedef enum {SENSOR_OK, SENSOR_WARN, SENSOR_FAILED, 1202 SENSOR_DISABLED, SENSOR_UNKNOWN} sensor_status_t; 1203 sensor_status_t sensor_status = SENSOR_OK; 1204 1205 if (class_node_found == 0) { 1206 class_node_found = 1; 1207 return (PICL_WALK_TERMINATE); 1208 } 1209 1210 prop = (char *)args; 1211 if (!prop) { 1212 sensor_status = SENSOR_UNKNOWN; 1213 all_status_ok = 0; 1214 } else { 1215 err = picl_get_propval_by_name(nodeh, 1216 PICL_PROP_OPERATIONAL_STATUS, current_val, 1217 sizeof (current_val)); 1218 if (err == PICL_SUCCESS) { 1219 if (strcmp(current_val, "disabled") == 0) { 1220 sensor_status = SENSOR_DISABLED; 1221 } 1222 } 1223 } 1224 1225 if (sensor_status != SENSOR_DISABLED && 1226 sensor_status != SENSOR_UNKNOWN) { 1227 if (picl_get_propval_by_name(nodeh, prop, ¤t_val, 1228 sizeof (current_val)) != PICL_SUCCESS) { 1229 (void) strlcpy(current_val, "unknown", 1230 sizeof (current_val)); 1231 sensor_status = SENSOR_UNKNOWN; 1232 } else { 1233 if (picl_get_propval_by_name(nodeh, PICL_PROP_EXPECTED, 1234 &expected_val, sizeof (expected_val)) != 1235 PICL_SUCCESS) { 1236 sensor_status = SENSOR_UNKNOWN; 1237 } else { 1238 if (strncmp(current_val, expected_val, 1239 sizeof (current_val)) == 0) { 1240 sensor_status = SENSOR_OK; 1241 } else { 1242 sensor_status = SENSOR_FAILED; 1243 } 1244 } 1245 } 1246 } 1247 1248 if (syserrlog == 0) { 1249 if (sensor_status != SENSOR_OK && all_status_ok == 1) { 1250 all_status_ok = 0; 1251 return (PICL_WALK_TERMINATE); 1252 } 1253 if (sensor_status == SENSOR_OK) { 1254 return (PICL_WALK_CONTINUE); 1255 } 1256 } 1257 1258 /* 1259 * If we're here then prtdiag was invoked with "-v" or we have 1260 * a sensor that is beyond a threshold, so give them a book to 1261 * read instead of the Cliff Notes. 1262 */ 1263 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 1264 sizeof (parenth)); 1265 if (err != PICL_SUCCESS) { 1266 log_printf("\n"); 1267 return (PICL_WALK_CONTINUE); 1268 } 1269 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) != NULL) { 1270 for (i = 0; i < PARENT_NAMES; i++) { 1271 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == 1272 NULL) { 1273 while (--i > -1) 1274 free(names[i]); 1275 free(loc); 1276 loc = NULL; 1277 } 1278 } 1279 } 1280 i = 0; 1281 if (loc) { 1282 while (err == PICL_SUCCESS) { 1283 if (parenth == phyplatformh) 1284 break; 1285 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1286 names[i++], PICL_PROPNAMELEN_MAX); 1287 if (err != PICL_SUCCESS) { 1288 i--; 1289 break; 1290 } 1291 if (i == PARENT_NAMES) 1292 break; 1293 err = picl_get_propval_by_name(parenth, 1294 PICL_PROP_PARENT, &parenth, sizeof (parenth)); 1295 } 1296 loc[0] = '\0'; 1297 if (--i > -1) { 1298 (void) strlcat(loc, names[i], 1299 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1300 } 1301 while (--i > -1) { 1302 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * 1303 PARENT_NAMES); 1304 (void) strlcat(loc, names[i], 1305 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1306 } 1307 log_printf("%-35s", loc); 1308 for (i = 0; i < PARENT_NAMES; i++) 1309 free(names[i]); 1310 free(loc); 1311 } else { 1312 log_printf("%-35s", ""); 1313 } 1314 1315 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 1316 sizeof (label)); 1317 if (err != PICL_SUCCESS) 1318 (void) strlcpy(label, "", sizeof (label)); 1319 log_printf("%-15s", label); 1320 1321 log_printf("%-8s", current_val); 1322 1323 log_printf("\n"); 1324 return (PICL_WALK_CONTINUE); 1325 } 1326 1327 static void 1328 sun4v_env_print_fan_sensors() 1329 { 1330 char *fmt = "%-34s %-14s %-10s\n"; 1331 /* 1332 * If there isn't any fan sensor node, return now. 1333 */ 1334 (void) picl_walk_tree_by_class(phyplatformh, 1335 PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED, 1336 sun4v_env_print_sensor_callback); 1337 if (!class_node_found) 1338 return; 1339 log_printf("Fan sensors:\n"); 1340 if (syserrlog == 0) { 1341 (void) picl_walk_tree_by_class(phyplatformh, 1342 PICL_CLASS_RPM_SENSOR, 1343 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 1344 if (all_status_ok) { 1345 log_printf("All fan sensors are OK.\n"); 1346 return; 1347 } 1348 } 1349 log_printf("-------------------------------------------------" 1350 "-----------\n"); 1351 log_printf(fmt, "Location", "Sensor", "Status", 0); 1352 log_printf("-------------------------------------------------" 1353 "-----------\n"); 1354 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR, 1355 PICL_PROP_SPEED, sun4v_env_print_sensor_callback); 1356 } 1357 1358 static void 1359 sun4v_env_print_fan_indicators() 1360 { 1361 char *fmt = "%-34s %-14s %-10s\n"; 1362 (void) picl_walk_tree_by_class(phyplatformh, 1363 PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION, 1364 sun4v_env_print_indicator_callback); 1365 if (!class_node_found) 1366 return; 1367 log_printf("\nFan indicators:\n"); 1368 if (syserrlog == 0) { 1369 (void) picl_walk_tree_by_class(phyplatformh, 1370 PICL_CLASS_RPM_INDICATOR, 1371 (void *)PICL_PROP_CONDITION, 1372 sun4v_env_print_indicator_callback); 1373 if (all_status_ok) { 1374 log_printf("All fan indicators are OK.\n"); 1375 return; 1376 } 1377 } 1378 log_printf("-------------------------------------------------" 1379 "-----------\n"); 1380 log_printf(fmt, "Location", "Sensor", "Condition", 0); 1381 log_printf("-------------------------------------------------" 1382 "-----------\n"); 1383 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR, 1384 (void *)PICL_PROP_CONDITION, sun4v_env_print_indicator_callback); 1385 } 1386 1387 static void 1388 sun4v_env_print_temp_sensors() 1389 { 1390 char *fmt = "%-34s %-14s %-10s\n"; 1391 (void) picl_walk_tree_by_class(phyplatformh, 1392 PICL_CLASS_TEMPERATURE_SENSOR, 1393 (void *)PICL_PROP_TEMPERATURE, 1394 sun4v_env_print_sensor_callback); 1395 if (!class_node_found) 1396 return; 1397 1398 log_printf("\nTemperature sensors:\n"); 1399 if (syserrlog == 0) { 1400 (void) picl_walk_tree_by_class(phyplatformh, 1401 PICL_CLASS_TEMPERATURE_SENSOR, 1402 PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 1403 if (all_status_ok) { 1404 log_printf("All temperature sensors are OK.\n"); 1405 return; 1406 } 1407 } 1408 log_printf("-------------------------------------------------" 1409 "-----------\n"); 1410 log_printf(fmt, "Location", "Sensor", "Status", 0); 1411 log_printf("-------------------------------------------------" 1412 "-----------\n"); 1413 (void) picl_walk_tree_by_class(phyplatformh, 1414 PICL_CLASS_TEMPERATURE_SENSOR, 1415 (void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback); 1416 } 1417 1418 static void 1419 sun4v_env_print_temp_indicators() 1420 { 1421 char *fmt = "%-34s %-14s %-8s\n"; 1422 (void) picl_walk_tree_by_class(phyplatformh, 1423 PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION, 1424 sun4v_env_print_indicator_callback); 1425 if (!class_node_found) 1426 return; 1427 log_printf("\nTemperature indicators:\n"); 1428 if (syserrlog == 0) { 1429 (void) picl_walk_tree_by_class(phyplatformh, 1430 PICL_CLASS_TEMPERATURE_INDICATOR, 1431 (void *)PICL_PROP_CONDITION, 1432 sun4v_env_print_indicator_callback); 1433 if (all_status_ok) { 1434 log_printf("All temperature indicators are OK.\n"); 1435 return; 1436 } 1437 } 1438 log_printf("-------------------------------------------------" 1439 "-----------\n"); 1440 log_printf(fmt, "Location", "Indicator", "Condition", 0); 1441 log_printf("-------------------------------------------------" 1442 "-----------\n"); 1443 (void) picl_walk_tree_by_class(phyplatformh, 1444 PICL_CLASS_TEMPERATURE_INDICATOR, 1445 (void *)PICL_PROP_CONDITION, 1446 sun4v_env_print_indicator_callback); 1447 } 1448 1449 static void 1450 sun4v_env_print_current_sensors() 1451 { 1452 char *fmt = "%-34s %-14s %-10s\n"; 1453 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR, 1454 (void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 1455 if (!class_node_found) 1456 return; 1457 log_printf("\nCurrent sensors:\n"); 1458 if (syserrlog == 0) { 1459 (void) picl_walk_tree_by_class(phyplatformh, 1460 PICL_CLASS_CURRENT_SENSOR, 1461 PICL_PROP_CURRENT, sun4v_env_print_sensor_callback); 1462 if (all_status_ok) { 1463 log_printf("All current sensors are OK.\n"); 1464 return; 1465 } 1466 } 1467 log_printf("-------------------------------------------------" 1468 "-----------\n"); 1469 log_printf(fmt, "Location", "Sensor", "Status", 0); 1470 log_printf("-------------------------------------------------" 1471 "-----------\n"); 1472 (void) picl_walk_tree_by_class(phyplatformh, 1473 PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT, 1474 sun4v_env_print_sensor_callback); 1475 } 1476 1477 static void 1478 sun4v_env_print_current_indicators() 1479 { 1480 char *fmt = "%-34s %-14s %-8s\n"; 1481 (void) picl_walk_tree_by_class(phyplatformh, 1482 PICL_CLASS_CURRENT_INDICATOR, 1483 (void *)PICL_PROP_CONDITION, 1484 sun4v_env_print_indicator_callback); 1485 if (!class_node_found) 1486 return; 1487 log_printf("\nCurrent indicators:\n"); 1488 if (syserrlog == 0) { 1489 (void) picl_walk_tree_by_class(phyplatformh, 1490 PICL_CLASS_CURRENT_INDICATOR, (void *)PICL_PROP_CONDITION, 1491 sun4v_env_print_indicator_callback); 1492 if (all_status_ok) { 1493 log_printf("All current indicators are OK.\n"); 1494 return; 1495 } 1496 } 1497 log_printf("-------------------------------------------------" 1498 "-----------\n"); 1499 log_printf(fmt, "Location", "Indicator", "Condition", 0); 1500 log_printf("-------------------------------------------------" 1501 "-----------\n"); 1502 (void) picl_walk_tree_by_class(phyplatformh, 1503 PICL_CLASS_CURRENT_INDICATOR, 1504 (void *)PICL_PROP_CONDITION, 1505 sun4v_env_print_indicator_callback); 1506 } 1507 1508 static void 1509 sun4v_env_print_voltage_sensors() 1510 { 1511 char *fmt = "%-34s %-14s %-10s\n"; 1512 (void) picl_walk_tree_by_class(phyplatformh, 1513 PICL_CLASS_VOLTAGE_SENSOR, 1514 PICL_PROP_VOLTAGE, 1515 sun4v_env_print_sensor_callback); 1516 if (!class_node_found) 1517 return; 1518 log_printf("\nVoltage sensors:\n"); 1519 if (syserrlog == 0) { 1520 (void) picl_walk_tree_by_class(phyplatformh, 1521 PICL_CLASS_VOLTAGE_SENSOR, 1522 PICL_PROP_VOLTAGE, sun4v_env_print_sensor_callback); 1523 if (all_status_ok) { 1524 log_printf("All voltage sensors are OK.\n"); 1525 return; 1526 } 1527 } 1528 log_printf("-------------------------------------------------" 1529 "-----------\n"); 1530 log_printf(fmt, "Location", "Sensor", "Status", 0); 1531 log_printf("-------------------------------------------------" 1532 "-----------\n"); 1533 (void) picl_walk_tree_by_class(phyplatformh, 1534 PICL_CLASS_VOLTAGE_SENSOR, 1535 (void *)PICL_PROP_VOLTAGE, 1536 sun4v_env_print_sensor_callback); 1537 } 1538 1539 static void 1540 sun4v_env_print_voltage_indicators() 1541 { 1542 char *fmt = "%-34s %-14s %-8s\n"; 1543 (void) picl_walk_tree_by_class(phyplatformh, 1544 PICL_CLASS_VOLTAGE_INDICATOR, 1545 (void *)PICL_PROP_CONDITION, 1546 sun4v_env_print_indicator_callback); 1547 if (!class_node_found) 1548 return; 1549 log_printf("\nVoltage indicators:\n"); 1550 if (syserrlog == 0) { 1551 (void) picl_walk_tree_by_class(phyplatformh, 1552 PICL_CLASS_VOLTAGE_INDICATOR, (void *)PICL_PROP_CONDITION, 1553 sun4v_env_print_indicator_callback); 1554 if (all_status_ok) { 1555 log_printf("All voltage indicators are OK.\n"); 1556 return; 1557 } 1558 } 1559 log_printf("-------------------------------------------------" 1560 "-----------\n"); 1561 log_printf(fmt, "Location", "Indicator", "Condition", 0); 1562 log_printf("-------------------------------------------------" 1563 "-----------\n"); 1564 (void) picl_walk_tree_by_class(phyplatformh, 1565 PICL_CLASS_VOLTAGE_INDICATOR, 1566 (void *)PICL_PROP_CONDITION, 1567 sun4v_env_print_indicator_callback); 1568 } 1569 1570 static void 1571 sun4v_env_print_LEDs() 1572 { 1573 char *fmt = "%-34s %-14s %-8s\n"; 1574 if (syserrlog == 0) 1575 return; 1576 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 1577 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 1578 if (!class_node_found) 1579 return; 1580 log_printf("\nLEDs:\n"); 1581 log_printf("-------------------------------------------------" 1582 "-----------\n"); 1583 log_printf(fmt, "Location", "LED", "State", 0); 1584 log_printf("-------------------------------------------------" 1585 "-----------\n"); 1586 (void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED, 1587 (void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback); 1588 } 1589 1590 /*ARGSUSED*/ 1591 static int 1592 sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args) 1593 { 1594 char label[PICL_PROPNAMELEN_MAX]; 1595 char status[PICL_PROPNAMELEN_MAX]; 1596 picl_errno_t err; 1597 picl_prophdl_t proph; 1598 picl_nodehdl_t parenth; 1599 char *names[PARENT_NAMES]; 1600 char *loc; 1601 int i; 1602 1603 if (!class_node_found) { 1604 class_node_found = 1; 1605 return (PICL_WALK_TERMINATE); 1606 } 1607 err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph); 1608 if (err != PICL_SUCCESS) 1609 return (PICL_WALK_CONTINUE); 1610 err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label, 1611 sizeof (label)); 1612 if (err != PICL_SUCCESS) 1613 return (PICL_WALK_CONTINUE); 1614 err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS, 1615 status, sizeof (status)); 1616 if (err != PICL_SUCCESS) 1617 return (PICL_WALK_CONTINUE); 1618 if (syserrlog == 0) { 1619 if (strcmp(status, "disabled") == 0) { 1620 if (all_status_ok) { 1621 all_status_ok = 0; 1622 return (PICL_WALK_TERMINATE); 1623 } 1624 } else 1625 return (PICL_WALK_CONTINUE); 1626 } 1627 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth, 1628 sizeof (parenth)); 1629 if (err != PICL_SUCCESS) { 1630 log_printf("\n"); 1631 return (PICL_WALK_CONTINUE); 1632 } 1633 if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL) 1634 return (PICL_WALK_TERMINATE); 1635 for (i = 0; i < PARENT_NAMES; i++) 1636 if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) { 1637 while (--i > -1) 1638 free(names[i]); 1639 free(loc); 1640 return (PICL_WALK_TERMINATE); 1641 } 1642 i = 0; 1643 while (err == PICL_SUCCESS) { 1644 if (parenth == phyplatformh) 1645 break; 1646 err = picl_get_propval_by_name(parenth, PICL_PROP_NAME, 1647 names[i++], PICL_PROPNAMELEN_MAX); 1648 if (err != PICL_SUCCESS) { 1649 i--; 1650 break; 1651 } 1652 if (i == PARENT_NAMES) 1653 break; 1654 err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT, 1655 &parenth, sizeof (parenth)); 1656 } 1657 loc[0] = '\0'; 1658 if (--i > -1) { 1659 (void) strlcat(loc, names[i], 1660 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1661 } 1662 while (--i > -1) { 1663 (void) strlcat(loc, "/", PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1664 (void) strlcat(loc, names[i], 1665 PICL_PROPNAMELEN_MAX * PARENT_NAMES); 1666 } 1667 log_printf("%-35s", loc); 1668 for (i = 0; i < PARENT_NAMES; i++) 1669 free(names[i]); 1670 free(loc); 1671 log_printf("%-10s", label); 1672 log_printf("%-9s", status); 1673 log_printf("\n"); 1674 return (PICL_WALK_CONTINUE); 1675 } 1676 1677 static void 1678 sun4v_print_fru_status() 1679 { 1680 char *fmt = "%-34s %-9s %-8s\n"; 1681 1682 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1683 sun4v_print_fru_status_callback); 1684 if (!class_node_found) 1685 return; 1686 1687 log_printf("\n"); 1688 log_printf("============================"); 1689 log_printf(" FRU Status "); 1690 log_printf("============================"); 1691 log_printf("\n"); 1692 1693 if (syserrlog == 0) { 1694 (void) picl_walk_tree_by_class(phyplatformh, 1695 NULL, NULL, 1696 sun4v_print_fru_status_callback); 1697 if (all_status_ok) { 1698 log_printf("All FRUs are enabled.\n"); 1699 return; 1700 } 1701 } 1702 log_printf(fmt, "Location", "Name", "Status", 0); 1703 log_printf("------------------------------------------------------\n"); 1704 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1705 sun4v_print_fru_status_callback); 1706 } 1707 1708 /*ARGSUSED*/ 1709 static int 1710 sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args) 1711 { 1712 char rev[PICL_PROPNAMELEN_MAX]; 1713 picl_errno_t err; 1714 1715 if (!class_node_found) { 1716 class_node_found = 1; 1717 return (PICL_WALK_TERMINATE); 1718 } 1719 1720 err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev, 1721 sizeof (rev)); 1722 if (err != PICL_SUCCESS) 1723 return (PICL_WALK_CONTINUE); 1724 if (strlen(rev) == 0) 1725 return (PICL_WALK_CONTINUE); 1726 log_printf("%s", rev); 1727 log_printf("\n"); 1728 return (PICL_WALK_CONTINUE); 1729 } 1730 1731 static void 1732 sun4v_print_fw_rev() 1733 { 1734 if (syserrlog == 0) 1735 return; 1736 1737 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1738 sun4v_print_fw_rev_callback); 1739 if (!class_node_found) 1740 return; 1741 1742 log_printf("\n"); 1743 log_printf("============================"); 1744 log_printf(" FW Version "); 1745 log_printf("============================"); 1746 log_printf("\n"); 1747 log_printf("Version\n"); 1748 log_printf("-------------------------------------------------" 1749 "-----------\n"); 1750 (void) picl_walk_tree_by_class(phyplatformh, NULL, NULL, 1751 sun4v_print_fw_rev_callback); 1752 } 1753 1754 static void 1755 sun4v_print_openprom_rev() 1756 { 1757 if (syserrlog == 0) 1758 return; 1759 1760 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 1761 openprom_callback); 1762 if (!class_node_found) 1763 return; 1764 1765 log_printf("\n"); 1766 log_printf("======================"); 1767 log_printf(" System PROM revisions "); 1768 log_printf("======================="); 1769 log_printf("\n"); 1770 log_printf("Version\n"); 1771 log_printf("-------------------------------------------------" 1772 "-----------\n"); 1773 (void) picl_walk_tree_by_class(rooth, "openprom", NULL, 1774 openprom_callback); 1775 } 1776 1777 /* 1778 * display the OBP and POST prom revisions (if present) 1779 */ 1780 /* ARGSUSED */ 1781 static int 1782 openprom_callback(picl_nodehdl_t openpromh, void *arg) 1783 { 1784 picl_prophdl_t proph; 1785 picl_prophdl_t tblh; 1786 picl_prophdl_t rowproph; 1787 picl_propinfo_t pinfo; 1788 char *prom_version = NULL; 1789 char *obp_version = NULL; 1790 int err; 1791 1792 if (!class_node_found) { 1793 class_node_found = 1; 1794 return (PICL_WALK_TERMINATE); 1795 } 1796 1797 err = picl_get_propinfo_by_name(openpromh, OBP_PROP_VERSION, 1798 &pinfo, &proph); 1799 if (err == PICL_PROPNOTFOUND) 1800 return (PICL_WALK_TERMINATE); 1801 else if (err != PICL_SUCCESS) 1802 return (err); 1803 1804 /* 1805 * If it's a table prop, the first element is OBP revision 1806 * The second one is POST revision. 1807 * If it's a charstring prop, the value will be only OBP revision 1808 */ 1809 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 1810 prom_version = (char *)alloca(pinfo.size); 1811 if (prom_version == NULL) 1812 return (PICL_FAILURE); 1813 err = picl_get_propval(proph, prom_version, pinfo.size); 1814 if (err != PICL_SUCCESS) 1815 return (err); 1816 log_printf("%s\n", prom_version); 1817 } 1818 1819 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */ 1820 return (PICL_WALK_TERMINATE); 1821 1822 err = picl_get_propval(proph, &tblh, pinfo.size); 1823 if (err != PICL_SUCCESS) 1824 return (err); 1825 1826 err = picl_get_next_by_row(tblh, &rowproph); 1827 if (err == PICL_SUCCESS) { 1828 /* get first row */ 1829 err = picl_get_propinfo(rowproph, &pinfo); 1830 if (err != PICL_SUCCESS) 1831 return (err); 1832 1833 prom_version = (char *)alloca(pinfo.size); 1834 if (prom_version == NULL) 1835 return (PICL_FAILURE); 1836 1837 err = picl_get_propval(rowproph, prom_version, pinfo.size); 1838 if (err != PICL_SUCCESS) 1839 return (err); 1840 log_printf("%s\n", prom_version); 1841 1842 /* get second row */ 1843 err = picl_get_next_by_col(rowproph, &rowproph); 1844 if (err == PICL_SUCCESS) { 1845 err = picl_get_propinfo(rowproph, &pinfo); 1846 if (err != PICL_SUCCESS) 1847 return (err); 1848 1849 obp_version = (char *)alloca(pinfo.size); 1850 if (obp_version == NULL) 1851 return (PICL_FAILURE); 1852 err = picl_get_propval(rowproph, obp_version, 1853 pinfo.size); 1854 if (err != PICL_SUCCESS) 1855 return (err); 1856 log_printf("%s\n", obp_version); 1857 } 1858 } 1859 1860 return (PICL_WALK_TERMINATE); 1861 } 1862 1863 static void 1864 sun4v_print_chassis_serial_no() 1865 { 1866 char val[PICL_PROPNAMELEN_MAX]; 1867 picl_errno_t err; 1868 if (syserrlog == 0 || chassish == 0) 1869 return; 1870 1871 log_printf("\n"); 1872 log_printf("Chassis Serial Number"); 1873 log_printf("\n"); 1874 log_printf("---------------------\n"); 1875 err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER, 1876 val, sizeof (val)); 1877 if (err == PICL_SUCCESS) 1878 log_printf("%s", val); 1879 log_printf("\n"); 1880 } 1881