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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * 28 * Cherrystone platform-specific functions 29 * 30 */ 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <kstat.h> 38 #include <string.h> 39 #include <assert.h> 40 #include <libintl.h> 41 #include <note.h> 42 #include <syslog.h> 43 44 #include <sys/openpromio.h> 45 #include <sys/sysmacros.h> 46 47 #include <pdevinfo.h> 48 #include <display.h> 49 #include <pdevinfo_sun4u.h> 50 #include <display_sun4u.h> 51 52 #include <picl.h> 53 54 #include <sys/cheetahregs.h> 55 #include <sys/cherrystone.h> 56 #include "workfile.c" 57 58 #define SCHIZO_COMPAT_PROP "pci108e,8001" 59 60 #define MULTIPLE_BITS_SET(x) ((x)&((x)-1)) 61 62 #define MAX_PS 2 63 #define MAX_PS_SENSORS 3 64 #define MAX_DISKS 2 65 #define MAX_FANS 5 66 #define NUM_PCI_SLOTS 5 67 68 /* 69 * these functions will overlay the symbol table of libprtdiag 70 * at runtime (workgroup server systems only) 71 */ 72 void display_cpu_devices(Sys_tree *tree); 73 void display_pci(Board_node *board); 74 void display_io_cards(struct io_card *list); 75 void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 76 struct system_kstat_data *kstats); 77 void display_ffb(Board_node *board, int table); 78 void display_memoryconf(Sys_tree *tree, struct grp_info *grps); 79 80 /* local functions */ 81 static void disp_envc_status(void); 82 static int print_temps(picl_nodehdl_t); 83 static int print_keyswitch(picl_nodehdl_t); 84 static int print_FSP_LEDS(picl_nodehdl_t); 85 static int print_disk(picl_nodehdl_t); 86 static int print_fans(picl_nodehdl_t); 87 static int print_ps(picl_nodehdl_t); 88 89 static void display_hw_revisions(Prom_node *root, 90 Board_node *bnode); 91 static void display_schizo_revisions(Board_node *bdlist); 92 93 94 void 95 display_cpu_devices(Sys_tree *tree) 96 { 97 Board_node *bnode; 98 99 log_printf(dgettext(TEXT_DOMAIN, 100 "\n========================= CPUs " 101 "===============================================\n\n" 102 " Run E$ CPU CPU \n" 103 "Brd CPU MHz MB Impl. Mask \n" 104 "--- ----- ---- ---- ------- ---- \n")); 105 106 bnode = tree->bd_list; 107 while (bnode != NULL) { 108 display_cpus(bnode); 109 bnode = bnode->next; 110 } 111 112 log_printf("\n"); 113 } 114 void 115 display_cpus(Board_node *board) 116 { 117 Prom_node *cpu; 118 uint_t freq; 119 int ecache_size; 120 int *l3_shares; 121 int *mid; 122 int *impl; 123 int *mask; 124 int *coreid; 125 char fru_prev = 'X'; /* Valid frus are 'A','B' */ 126 int mid_prev; 127 int ecache_size_prev = 0; 128 char fru_name; 129 130 /* 131 * display the CPUs' operating frequency, cache size, impl. field 132 * and mask revision. 133 */ 134 135 for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL; 136 cpu = dev_next_type(cpu, "cpu")) { 137 138 mid = (int *)get_prop_val(find_prop(cpu, "portid")); 139 if (mid == NULL) 140 mid = (int *)get_prop_val(find_prop(cpu, "cpuid")); 141 freq = HZ_TO_MHZ(get_cpu_freq(cpu)); 142 ecache_size = get_ecache_size(cpu); 143 impl = (int *)get_prop_val(find_prop(cpu, "implementation#")); 144 mask = (int *)get_prop_val(find_prop(cpu, "mask#")); 145 l3_shares = 146 (int *)get_prop_val(find_prop(cpu, "l3-cache-sharing")); 147 148 /* Do not display a failed CPU node */ 149 if ((impl == NULL) || (freq == 0) || (node_failed(cpu))) 150 continue; 151 152 fru_name = CHERRYSTONE_GETSLOT_LABEL(*mid); 153 if (CPU_IMPL_IS_CMP(*impl)) { 154 coreid = (int *)get_prop_val(find_prop(cpu, "reg")); 155 if (coreid == NULL) { 156 continue; 157 } 158 if ((fru_prev == 'X') || 159 ((fru_prev != 'X') && 160 (fru_name != fru_prev))) { 161 fru_prev = fru_name; 162 mid_prev = *mid; 163 ecache_size_prev = ecache_size; 164 continue; 165 } else { 166 /* 167 * Some CMP chips have a split E$, 168 * so the size for both cores is added 169 * together to get the total size for 170 * the chip. 171 * 172 * Still, other CMP chips have E$ (L3) 173 * which is logically shared, so the 174 * total size is equal to the core size. 175 */ 176 if ((l3_shares == NULL) || 177 ((l3_shares != NULL) && 178 MULTIPLE_BITS_SET(*l3_shares))) { 179 ecache_size += ecache_size_prev; 180 } 181 ecache_size_prev = 0; 182 fru_prev = 'X'; 183 } 184 } 185 186 log_printf(" %c", fru_name); 187 188 /* CPU Module ID */ 189 if (CPU_IMPL_IS_CMP(*impl)) { 190 log_printf("%3d,%3d ", mid_prev, *mid, 0); 191 } else 192 log_printf(" %2d ", *mid); 193 194 /* Running frequency */ 195 log_printf("%4u", freq); 196 197 if (ecache_size == 0) 198 log_printf(" N/A "); 199 else 200 log_printf(" %4.1f ", 201 (float)ecache_size / (float)(1<<20)); 202 /* Implementation */ 203 if (impl == NULL) { 204 log_printf(dgettext(TEXT_DOMAIN, " N/A ")); 205 } else { 206 if (IS_CHEETAH(*impl)) 207 log_printf(dgettext(TEXT_DOMAIN, 208 "US-III ")); 209 else if (IS_CHEETAH_PLUS(*impl)) 210 log_printf(dgettext(TEXT_DOMAIN, 211 "US-III+ ")); 212 else if (IS_JAGUAR(*impl)) 213 log_printf(dgettext(TEXT_DOMAIN, 214 "US-IV ")); 215 else if (IS_PANTHER(*impl)) 216 log_printf(dgettext(TEXT_DOMAIN, 217 "US-IV+ ")); 218 else 219 log_printf("%-6x ", *impl); 220 } 221 222 /* CPU Mask */ 223 if (mask == NULL) { 224 log_printf(dgettext(TEXT_DOMAIN, " N/A\n")); 225 } else { 226 log_printf(dgettext(TEXT_DOMAIN, " %d.%d\n"), 227 (*mask >> 4) & 0xf, *mask & 0xf); 228 } 229 } 230 } 231 232 /*ARGSUSED0*/ 233 void 234 display_memoryconf(Sys_tree *tree, struct grp_info *grps) 235 { 236 Board_node *bnode = tree->bd_list; 237 238 log_printf(dgettext(TEXT_DOMAIN, 239 "========================= Memory Configuration" 240 " ===============================\n\n" 241 " Logical Logical Logical\n" 242 " MC Bank Bank Bank DIMM " 243 "Interleave Interleaved\n" 244 "Brd ID num size Status Size " 245 "Factor with\n" 246 "--- --- ---- ------ ----------- ------ " 247 "---------- -----------")); 248 249 while (bnode != NULL) { 250 if (get_us3_mem_regs(bnode)) { 251 log_printf(dgettext(TEXT_DOMAIN, 252 "\nFailed to get memory information.\n")); 253 return; 254 } 255 bnode = bnode->next; 256 } 257 258 /* Display what we have found */ 259 display_us3_banks(); 260 } 261 262 /*ARGSUSED3*/ 263 void 264 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 265 struct system_kstat_data *kstats) 266 { 267 /* 268 * Now display the last powerfail time and the fatal hardware 269 * reset information. We do this under a couple of conditions. 270 * First if the user asks for it. The second is if the user 271 * told us to do logging, and we found a system failure. 272 */ 273 274 if (flag) { 275 /* 276 * display time of latest powerfail. Not all systems 277 * have this capability. For those that do not, this 278 * is just a no-op. 279 */ 280 disp_powerfail(root); 281 282 disp_envc_status(); 283 284 display_hw_revisions(root, tree->bd_list); 285 } 286 return; 287 288 } 289 290 /* 291 * display_pci 292 * Display all the PCI IO cards on this board. 293 */ 294 void 295 display_pci(Board_node *board) 296 { 297 struct io_card *card_list = NULL; 298 struct io_card card; 299 void *value; 300 Prom_node *pci; 301 Prom_node *card_node; 302 static int banner = FALSE; 303 304 char *slot_name_arr[NUM_PCI_SLOTS]; 305 int i; 306 307 if (board == NULL) 308 return; 309 310 (void) memset(&card, 0, sizeof (struct io_card)); 311 /* Initialize all the common information */ 312 card.display = TRUE; 313 card.board = board->board_num; 314 315 /* 316 * Search for each pci instance, then find/display all nodes under 317 * each instance node found. 318 */ 319 for (pci = dev_find_node_by_compat(board->nodes, SCHIZO_COMPAT_PROP); 320 pci != NULL; 321 pci = dev_next_node_by_compat(pci, SCHIZO_COMPAT_PROP)) { 322 (void) snprintf(card.bus_type, MAXSTRLEN, 323 dgettext(TEXT_DOMAIN, "PCI")); 324 /* 325 * Get slot-name properties from parent node and 326 * store them in an array. 327 */ 328 value = (char *)get_prop_val( 329 find_prop(pci, "slot-names")); 330 331 if (value != NULL) { 332 /* array starts after first int */ 333 slot_name_arr[0] = (char *)value + sizeof (int); 334 for (i = 1; i < NUM_PCI_SLOTS; i++) { 335 slot_name_arr[i] = (char *)slot_name_arr[i - 1] 336 + strlen(slot_name_arr[i - 1]) +1; 337 } 338 } 339 /* 340 * Search for Children of this node ie. Cards. 341 * Note: any of these cards can be a pci-bridge 342 * that itself has children. If we find a 343 * pci-bridge we need to handle it specially. 344 */ 345 card_node = pci->child; 346 /* Generate the list of pci cards on pci instance: pci */ 347 fill_pci_card_list(pci, card_node, &card, &card_list, 348 slot_name_arr); 349 } /* end-for */ 350 351 if (!banner && card_list != NULL) { 352 log_printf(dgettext(TEXT_DOMAIN, 353 " Bus Max\n" 354 " IO Port Bus Freq Bus Dev,\n" 355 "Type ID Side Slot MHz Freq Func State " 356 "Name Model" 357 #ifdef DEBUG 358 " Notes" 359 #endif 360 "\n" 361 "---- ---- ---- ---- ---- ---- ---- ----- " 362 "-------------------------------- " 363 #ifdef DEBUG 364 "---------------------- " 365 #endif 366 "----------------------\n")); 367 banner = TRUE; 368 } 369 370 display_io_cards(card_list); 371 free_io_cards(card_list); 372 } 373 374 /* 375 * Print out all the io cards in the list. Also print the column 376 * headers if told to do so. 377 */ 378 void 379 display_io_cards(struct io_card *list) 380 { 381 struct io_card *p; 382 383 for (p = list; p != NULL; p = p -> next) { 384 log_printf(dgettext(TEXT_DOMAIN, 385 "%-4s %-3d %c %-1s %-3d"), 386 p->bus_type, p->schizo_portid, p->pci_bus, 387 p->slot_str, p->freq); 388 389 switch (p->pci_bus) { 390 case 'A': 391 log_printf(dgettext(TEXT_DOMAIN, " 66 ")); 392 break; 393 case 'B': 394 log_printf(dgettext(TEXT_DOMAIN, " 33 ")); 395 break; 396 default: 397 assert(0); 398 break; 399 } 400 401 log_printf(dgettext(TEXT_DOMAIN, 402 "%-1d,%-1d %-5s %-32.32s"), 403 p->dev_no, p->func_no, p->status, p->name); 404 if (strlen(p->name) > 32) 405 log_printf(dgettext(TEXT_DOMAIN, "+ ")); 406 else 407 log_printf(dgettext(TEXT_DOMAIN, " ")); 408 log_printf(dgettext(TEXT_DOMAIN, "%-22.22s"), p->model); 409 if (strlen(p->model) > 22) 410 log_printf(dgettext(TEXT_DOMAIN, "+")); 411 #ifdef DEBUG 412 log_printf("%s", p->notes); 413 #endif 414 log_printf("\n"); 415 } 416 } 417 418 /*ARGSUSED*/ 419 void 420 display_ffb(Board_node *board, int table) 421 { 422 /* NOP, since there are no FFB's on this platform. */ 423 } 424 425 426 /* 427 * local functions 428 */ 429 430 431 static void 432 disp_envc_status() 433 { 434 int err; 435 char *system = "SYSTEM"; 436 picl_nodehdl_t system_node, root; 437 438 log_printf(dgettext(TEXT_DOMAIN, 439 "\n" 440 "========================= Environmental Status " 441 "=========================\n\n")); 442 443 err = picl_initialize(); 444 if (err != PICL_SUCCESS) { 445 exit_code = PD_INTERNAL_FAILURE; 446 goto err_out; 447 } 448 err = picl_get_root(&root); 449 if (err != PICL_SUCCESS) { 450 exit_code = PD_INTERNAL_FAILURE; 451 goto err_out; 452 } 453 err = find_child_device(root, system, &system_node); 454 if (err != PICL_SUCCESS) { 455 exit_code = PD_INTERNAL_FAILURE; 456 goto err_out; 457 } 458 459 err = print_temps(system_node); 460 err |= print_keyswitch(system_node); 461 err |= print_FSP_LEDS(system_node); 462 err |= print_disk(system_node); 463 err |= print_fans(system_node); 464 err |= print_ps(system_node); 465 466 if (err != PICL_SUCCESS) 467 goto err_out; 468 469 return; 470 471 err_out: 472 log_printf(dgettext(TEXT_DOMAIN, 473 "\nEnvironmental reporting error: %s\n"), 474 picl_strerror(err)); 475 } 476 477 static int 478 print_ps(picl_nodehdl_t system_node) 479 { 480 int i, j, err = 0; 481 int32_t number; 482 picl_nodehdl_t *ps; 483 picl_nodehdl_t *ps_fail_sensor; 484 char name[PICL_PROPNAMELEN_MAX]; 485 char fault_state[PICL_PROPNAMELEN_MAX]; 486 487 log_printf(dgettext(TEXT_DOMAIN, "\n\n" 488 "Power Supplies:\n" 489 "---------------\n" 490 "\n" 491 "Supply Status Fault Fan Fail Temp Fail\n" 492 "------ ------------ -------- --------- ---------\n")); 493 494 err = fill_device_array_from_id(system_node, "PSVC_PS", &number, &ps); 495 if (err != PICL_SUCCESS) { 496 return (err); 497 } 498 499 for (i = 0; i < MAX_PS; i++) { 500 err = picl_get_propval_by_name(ps[i], PICL_PROP_NAME, name, 501 PICL_PROPNAMELEN_MAX); 502 if (err != PICL_SUCCESS) 503 continue; 504 505 log_printf(dgettext(TEXT_DOMAIN, "%6-s"), name); 506 err = picl_get_propval_by_name(ps[i], "FaultInformation", 507 fault_state, PICL_PROPNAMELEN_MAX); 508 if (err != PICL_SUCCESS) { 509 free(ps); 510 return (err); 511 } 512 log_printf(dgettext(TEXT_DOMAIN, " [%-12s]"), fault_state); 513 if (strcmp(fault_state, "NO AC POWER") == 0) { 514 log_printf("\n"); 515 continue; 516 } 517 518 err = fill_device_array_from_id(ps[i], "PSVC_DEV_FAULT_SENSOR", 519 &number, &ps_fail_sensor); 520 521 if (err != PICL_SUCCESS) { 522 free(ps); 523 return (err); 524 } 525 log_printf(" "); 526 for (j = 0; j < MAX_PS_SENSORS; j++) { 527 err = picl_get_propval_by_name(ps_fail_sensor[j], 528 "State", fault_state, PICL_PROPNAMELEN_MAX); 529 if (err != PICL_SUCCESS) { 530 if (err == PICL_FAILURE) { 531 break; 532 } 533 free(ps); 534 free(ps_fail_sensor); 535 return (err); 536 } 537 log_printf(dgettext(TEXT_DOMAIN, "%-10s"), fault_state); 538 } 539 log_printf("\n"); 540 free(ps_fail_sensor); 541 } 542 543 log_printf(dgettext(TEXT_DOMAIN, 544 "\n=================================\n\n")); 545 546 free(ps); 547 return (PICL_SUCCESS); 548 } 549 550 static int 551 print_fans(picl_nodehdl_t system_node) 552 { 553 int i, err; 554 int32_t number; 555 picl_nodehdl_t *fans; 556 picl_nodehdl_t phdl; 557 char prop[PICL_PROPNAMELEN_MAX]; 558 char parent[PICL_PROPNAMELEN_MAX]; 559 int32_t rpm; 560 561 err = fill_device_array_from_id(system_node, "PSVC_FAN", &number, 562 &fans); 563 if (err != PICL_SUCCESS) { 564 return (err); 565 } 566 567 log_printf(dgettext(TEXT_DOMAIN, 568 "\n=================================\n\n" 569 "Fan Status:\n" 570 "-----------\n\n" 571 "Fan Tray Fan RPM Status\n" 572 "----------- ---- ----- ----------\n")); 573 574 for (i = 0; i < MAX_FANS; i++) { 575 err = picl_get_propval_by_name(fans[i], PICL_PROP_NAME, prop, 576 PICL_PROPNAMELEN_MAX); 577 if (err != PICL_SUCCESS) 578 continue; 579 580 err = fill_device_from_id(fans[i], "PSVC_PARENT", &phdl); 581 if (err != PICL_SUCCESS) 582 continue; 583 err = picl_get_propval_by_name(phdl, PICL_PROP_NAME, parent, 584 PICL_PROPNAMELEN_MAX); 585 if (err != PICL_SUCCESS) 586 continue; 587 588 log_printf(dgettext(TEXT_DOMAIN, "%-16s"), parent); 589 590 591 log_printf(dgettext(TEXT_DOMAIN, "%-16s"), prop); 592 593 err = picl_get_propval_by_name(fans[i], "Fan-speed", 594 &rpm, sizeof (rpm)); 595 if (err != PICL_SUCCESS) { 596 free(fans); 597 return (err); 598 } 599 log_printf(dgettext(TEXT_DOMAIN, "%5d "), rpm); 600 601 err = picl_get_propval_by_name(fans[i], "FaultInformation", 602 prop, PICL_PROPNAMELEN_MAX); 603 if (err != PICL_SUCCESS) { 604 free(fans); 605 return (err); 606 } 607 log_printf(dgettext(TEXT_DOMAIN, " [%s]\n"), prop); 608 } 609 log_printf(dgettext(TEXT_DOMAIN, 610 "\n=================================\n\n")); 611 free(fans); 612 return (PICL_SUCCESS); 613 } 614 615 static int 616 print_disk(picl_nodehdl_t system_node) 617 { 618 int i, err; 619 int32_t number; 620 picl_nodehdl_t *disks; 621 char state[PICL_PROPNAMELEN_MAX]; 622 623 err = fill_device_array_from_id(system_node, "PSVC_DISK", &number, 624 &disks); 625 if (err != PICL_SUCCESS) { 626 return (err); 627 } 628 629 log_printf(dgettext(TEXT_DOMAIN, 630 "Disk Status:\n" 631 "------------\n")); 632 for (i = 0; i < MAX_DISKS; i++) { 633 err = picl_get_propval_by_name(disks[i], "FaultInformation", 634 state, PICL_PROPNAMELEN_MAX); 635 636 switch (err) { 637 case PICL_SUCCESS: 638 log_printf(dgettext(TEXT_DOMAIN, 639 "DISK %d: [%3s]\n"), i, state); 640 break; 641 case PICL_INVALIDHANDLE: 642 log_printf(dgettext(TEXT_DOMAIN, 643 "DISK %d: [ NOT PRESENT ]\n"), i); 644 break; 645 default: 646 free(disks); 647 return (err); 648 } 649 } 650 free(disks); 651 return (PICL_SUCCESS); 652 } 653 654 static int 655 print_FSP_LEDS(picl_nodehdl_t system_node) 656 { 657 int err; 658 int32_t number; 659 picl_nodehdl_t *fsp_led; 660 char fault_state[PICL_PROPNAMELEN_MAX]; 661 char locate_state[PICL_PROPNAMELEN_MAX]; 662 663 err = fill_device_array_from_id(system_node, "PSVC_FSP_LED", &number, 664 &fsp_led); 665 if (err != PICL_SUCCESS) { 666 return (err); 667 } 668 669 assert(number == 2); 670 err = picl_get_propval_by_name(fsp_led[0], "State", &fault_state, 671 PICL_PROPNAMELEN_MAX); 672 if (err != PICL_SUCCESS) { 673 free(fsp_led); 674 return (err); 675 } 676 677 if (strcmp(fault_state, PSVC_LED_ON) == 0) 678 exit_code = PD_SYSTEM_FAILURE; 679 680 err = picl_get_propval_by_name(fsp_led[1], "State", &locate_state, 681 PICL_PROPNAMELEN_MAX); 682 if (err != PICL_SUCCESS) { 683 free(fsp_led); 684 return (err); 685 } 686 687 log_printf(dgettext(TEXT_DOMAIN, 688 "System LED Status:\n\n" 689 " LOCATOR FAULT POWER\n" 690 " ------- ------- -------\n" 691 " [%3s] [%3s] [ ON]"), 692 locate_state, fault_state); 693 694 log_printf(dgettext(TEXT_DOMAIN, 695 "\n\n=================================\n\n")); 696 free(fsp_led); 697 return (err); 698 } 699 700 static int 701 print_keyswitch(picl_nodehdl_t system_node) 702 { 703 int err; 704 picl_nodehdl_t *keyswitch; 705 int32_t number; 706 char ks_pos[PICL_PROPNAMELEN_MAX]; 707 708 err = fill_device_array_from_id(system_node, "PSVC_KEYSWITCH", &number, 709 &keyswitch); 710 if (err != PICL_SUCCESS) { 711 return (err); 712 } 713 err = picl_get_propval_by_name(keyswitch[0], "State", ks_pos, 714 PICL_PROPNAMELEN_MAX); 715 if (err != PICL_SUCCESS) { 716 free(keyswitch); 717 return (err); 718 } 719 720 log_printf(dgettext(TEXT_DOMAIN, 721 "Front Status Panel:\n" 722 "-------------------\n" 723 "Keyswitch position: %s\n\n"), ks_pos); 724 free(keyswitch); 725 return (err); 726 } 727 728 static int 729 print_temps(picl_nodehdl_t system_node) 730 { 731 int i; 732 int err; 733 picl_nodehdl_t *system_ts_nodes; 734 int32_t temp; 735 int32_t number; 736 char label[PICL_PROPNAMELEN_MAX]; 737 char state[PICL_PROPNAMELEN_MAX]; 738 char *p; 739 740 err = fill_device_array_from_id(system_node, "PSVC_TS", &number, 741 &system_ts_nodes); 742 if (err != PICL_SUCCESS) { 743 return (err); 744 } 745 746 log_printf(dgettext(TEXT_DOMAIN, 747 "System Temperatures (Celsius):\n" 748 "-------------------------------\n" 749 "Device\t\tTemperature\tStatus\n" 750 "---------------------------------------\n")); 751 752 for (i = 0; i < number; i++) { 753 err = picl_get_propval_by_name(system_ts_nodes[i], 754 "State", state, sizeof (state)); 755 if (err != PICL_SUCCESS) { 756 if (err == PICL_INVALIDHANDLE) { 757 (void) strcpy(state, "n/a"); 758 } else { 759 free(system_ts_nodes); 760 return (err); 761 } 762 } 763 err = picl_get_propval_by_name(system_ts_nodes[i], 764 PICL_PROP_NAME, label, PICL_PROPNAMELEN_MAX); 765 if (err != PICL_SUCCESS) { 766 if (err == PICL_INVALIDHANDLE) 767 /* This FRU isn't present. Skip it. */ 768 continue; 769 free(system_ts_nodes); 770 return (err); 771 } 772 773 /* 774 * The names in the tree are like "CPU0_DIE_TEMPERATURE_SENSOR". 775 * All we want to print is up to the first underscore. 776 */ 777 p = strchr(label, '_'); 778 if (p != NULL) 779 *p = '\0'; 780 781 err = picl_get_propval_by_name(system_ts_nodes[i], 782 "Temperature", &temp, sizeof (temp)); 783 if (err != PICL_SUCCESS) { 784 free(system_ts_nodes); 785 return (err); 786 } 787 log_printf("%s\t\t%3d\t\t%s\n", label, temp, state); 788 } 789 790 log_printf(dgettext(TEXT_DOMAIN, 791 "\n=================================\n\n")); 792 793 free(system_ts_nodes); 794 return (PICL_SUCCESS); 795 } 796 797 static void 798 display_hw_revisions(Prom_node *root, Board_node *bdlist) 799 { 800 Prom_node *pnode; 801 char *value; 802 803 log_printf(dgettext(TEXT_DOMAIN, "\n" 804 "========================= HW Revisions " 805 "=======================================\n\n")); 806 807 log_printf(dgettext(TEXT_DOMAIN, 808 "System PROM revisions:\n" 809 "----------------------\n")); 810 811 pnode = dev_find_node(root, "openprom"); 812 if (pnode != NULL) { 813 value = (char *)get_prop_val(find_prop(pnode, "version")); 814 log_printf(value); 815 } 816 817 log_printf(dgettext(TEXT_DOMAIN, "\n\n" 818 "IO ASIC revisions:\n" 819 "------------------\n" 820 " Port\n" 821 "Model ID Status Version\n" 822 "-------- ---- ------ -------\n")); 823 824 display_schizo_revisions(bdlist); 825 } 826 827 828 static void 829 display_schizo_revisions(Board_node *bdlist) 830 { 831 Prom_node *pnode; 832 int *int_val; 833 int portid; 834 int prev_portid = -1; 835 char *status_a = NULL; 836 char *status_b = NULL; 837 int revision; 838 #ifdef DEBUG 839 uint32_t a_notes, b_notes; 840 #endif 841 int pci_bus; 842 Board_node *bnode; 843 bnode = bdlist; 844 845 while (bnode != NULL) { 846 /* 847 * search this board node for all Schizos 848 */ 849 850 for (pnode = dev_find_node_by_compat(bnode->nodes, 851 SCHIZO_COMPAT_PROP); pnode != NULL; 852 pnode = dev_next_node_by_compat(pnode, 853 SCHIZO_COMPAT_PROP)) { 854 855 /* 856 * get the reg property to determine 857 * whether we are looking at side A or B 858 */ 859 860 int_val = (int *)get_prop_val 861 (find_prop(pnode, "reg")); 862 if (int_val != NULL) { 863 int_val ++; /* second integer in array */ 864 pci_bus = ((*int_val) & 0x7f0000); 865 } 866 867 /* get portid */ 868 int_val = (int *)get_prop_val 869 (find_prop(pnode, "portid")); 870 if (int_val == NULL) 871 continue; 872 873 portid = *int_val; 874 875 /* 876 * If this is a new portid and it is PCI bus B, 877 * we skip onto the PCI bus A. 878 */ 879 if ((portid != prev_portid) && (pci_bus == 0x700000)) { 880 prev_portid = portid; 881 /* status */ 882 status_b = (char *)get_prop_val 883 (find_prop(pnode, "status")); 884 #ifdef DEBUG 885 b_notes = pci_bus; 886 #endif 887 continue; /* skip to the next schizo */ 888 } 889 890 /* 891 * This must be side A of the same Schizo. 892 * Gather all its props and display them. 893 */ 894 #ifdef DEBUG 895 a_notes = pci_bus; 896 #endif 897 898 prev_portid = portid; 899 900 int_val = (int *)get_prop_val 901 (find_prop(pnode, "version#")); 902 if (int_val != NULL) 903 revision = *int_val; 904 else 905 revision = -1; 906 907 status_a = (char *)get_prop_val(find_prop 908 (pnode, "status")); 909 910 log_printf(dgettext(TEXT_DOMAIN, "Schizo ")); 911 912 log_printf(dgettext(TEXT_DOMAIN, "%-3d "), portid, 0); 913 914 915 log_printf((status_a == NULL && status_b == NULL) ? 916 dgettext(TEXT_DOMAIN, " ok ") : 917 dgettext(TEXT_DOMAIN, " fail ")); 918 919 log_printf(dgettext(TEXT_DOMAIN, " %4d "), 920 revision); 921 #ifdef DEBUG 922 log_printf(" 0x%x 0x%x", a_notes, b_notes); 923 #endif 924 log_printf("\n"); 925 } 926 bnode = bnode->next; 927 } 928 } 929