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