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