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 * Daktari Platform specific functions. 28 * 29 * called when : 30 * machine_type == MTYPE_DAKTARI 31 * 32 */ 33 34 #pragma ident "%Z%%M% %I% %E% SMI" 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <kstat.h> 40 #include <string.h> 41 #include <assert.h> 42 #include <libintl.h> 43 #include <note.h> 44 45 #include <sys/openpromio.h> 46 #include <sys/sysmacros.h> 47 #include <sys/daktari.h> 48 49 #include <pdevinfo.h> 50 #include <display.h> 51 #include <pdevinfo_sun4u.h> 52 #include <display_sun4u.h> 53 #include <libprtdiag.h> 54 55 #include <picl.h> 56 #include "workfile.c" 57 58 #if !defined(TEXT_DOMAIN) 59 #define TEXT_DOMAIN "SYS_TEST" 60 #endif 61 62 #define DAK_MAX_SLOTS_PER_IO_BD 9 63 #define DAK_MAX_DISKS 12 64 #define DAK_MAX_FSP_LEDS 2 65 #define DAK_MAX_PS 3 66 #define DAK_MAX_PS_VOLTAGE_SENSORS 4 67 #define DAK_MAX_PS_FAULT_SENSORS 3 68 #define DAK_MAX_FANS 10 69 #ifndef SCHIZO_COMPAT_PROP 70 #define SCHIZO_COMPAT_PROP "pci108e,8001" 71 #endif 72 73 #define MULTIPLE_BITS_SET(x) ((x)&((x)-1)) 74 75 extern int print_flag; 76 77 /* 78 * these functions will overlay the symbol table of libprtdiag 79 * at runtime (workgroup server systems only) 80 */ 81 void display_cpu_devices(Sys_tree *tree); 82 void display_cpus(Board_node *board); 83 void display_pci(Board_node *board); 84 void display_io_cards(struct io_card *list); 85 void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 86 struct system_kstat_data *kstats); 87 void display_ffb(Board_node *board, int table); 88 void display_memoryconf(Sys_tree *tree, struct grp_info *grps); 89 90 /* local functions */ 91 static int disp_envc_status(void); 92 static int dak_env_print_temps(picl_nodehdl_t); 93 static int dak_env_print_keyswitch(picl_nodehdl_t); 94 static int dak_env_print_FSP_LEDS(picl_nodehdl_t); 95 static int dak_env_print_disk(picl_nodehdl_t); 96 static int dak_env_print_fans(picl_nodehdl_t); 97 static int dak_env_print_ps(picl_nodehdl_t); 98 99 static void dak_display_hw_revisions(Prom_node *root, 100 Board_node *bnode); 101 static void display_schizo_revisions(Board_node *bdlist); 102 103 104 /* 105 * Defining the error_check function in order to return the 106 * appropriate error code. 107 */ 108 /*ARGSUSED0*/ 109 int 110 error_check(Sys_tree *tree, struct system_kstat_data *kstats) 111 { 112 int exit_code = 0; /* init to all OK */ 113 /* 114 * silently check for any types of machine errors 115 */ 116 print_flag = 0; 117 if (disp_fail_parts(tree)) { 118 /* set exit_code to show failures */ 119 exit_code = 1; 120 } 121 print_flag = 1; 122 123 return (exit_code); 124 } 125 126 /* 127 * disp_fail_parts 128 * 129 * Display the failed parts in the system. This function looks for 130 * the status property in all PROM nodes. On systems where 131 * the PROM does not support passing diagnostic information 132 * through the device tree, this routine will be silent. 133 */ 134 int 135 disp_fail_parts(Sys_tree *tree) 136 { 137 int exit_code = 0; 138 int system_failed = 0; 139 Board_node *bnode = tree->bd_list; 140 Prom_node *pnode; 141 142 /* go through all of the boards looking for failed units. */ 143 while (bnode != NULL) { 144 /* find failed chips */ 145 pnode = find_failed_node(bnode->nodes); 146 if ((pnode != NULL) && !system_failed) { 147 system_failed = 1; 148 exit_code = 1; 149 if (print_flag == 0) { 150 return (exit_code); 151 } 152 log_printf("\n"); 153 log_printf(dgettext(TEXT_DOMAIN, "Failed Field " 154 "Replaceable Units (FRU) in System:\n")); 155 log_printf("==========================" 156 "====================\n"); 157 } 158 while (pnode != NULL) { 159 void *value; 160 char *name; /* node name string */ 161 char *type; /* node type string */ 162 char *board_type = NULL; 163 164 value = get_prop_val(find_prop(pnode, "status")); 165 name = get_node_name(pnode); 166 167 /* sanity check of data retrieved from PROM */ 168 if ((value == NULL) || (name == NULL)) { 169 pnode = next_failed_node(pnode); 170 continue; 171 } 172 173 /* Find the board type of this board */ 174 if (bnode->board_type == CPU_BOARD) { 175 board_type = "CPU"; 176 } else { 177 board_type = "IO"; 178 } 179 180 log_printf(dgettext(TEXT_DOMAIN, "%s unavailable " 181 "on %s Board #%d\n"), name, board_type, 182 bnode->board_num); 183 184 log_printf(dgettext(TEXT_DOMAIN, 185 "\tPROM fault string: %s\n"), value); 186 187 log_printf(dgettext(TEXT_DOMAIN, 188 "\tFailed Field Replaceable Unit is ")); 189 190 /* 191 * Determine whether FRU is CPU module, system 192 * board, or SBus card. 193 */ 194 if ((name != NULL) && (strstr(name, "sbus"))) { 195 196 log_printf(dgettext(TEXT_DOMAIN, 197 "SBus Card %d\n"), 198 get_sbus_slot(pnode)); 199 200 } else if (((name = get_node_name(pnode->parent)) != 201 NULL) && (strstr(name, "pci"))) { 202 203 log_printf(dgettext(TEXT_DOMAIN, 204 "PCI Card %d"), 205 get_pci_device(pnode)); 206 207 } else if (((type = get_node_type(pnode)) != NULL) && 208 (strstr(type, "cpu"))) { 209 210 log_printf(dgettext(TEXT_DOMAIN, "UltraSPARC " 211 "module Board %d Module %d\n"), 0, 212 get_id(pnode)); 213 214 } else { 215 log_printf(dgettext(TEXT_DOMAIN, 216 "%s board %d\n"), board_type, 217 bnode->board_num); 218 } 219 pnode = next_failed_node(pnode); 220 } 221 bnode = bnode->next; 222 } 223 224 if (!system_failed) { 225 log_printf(dgettext(TEXT_DOMAIN, 226 "No failures found in System\n")); 227 log_printf("===========================\n\n"); 228 } 229 230 if (system_failed) 231 return (1); 232 else 233 return (0); 234 } 235 236 /*ARGSUSED*/ 237 void 238 display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats) 239 { 240 /* Display failed units */ 241 (void) disp_fail_parts(tree); 242 } 243 244 /*ARGSUSED*/ 245 void 246 display_memoryconf(Sys_tree *tree, struct grp_info *grps) 247 { 248 Board_node *bnode = tree->bd_list; 249 250 log_printf(dgettext(TEXT_DOMAIN, 251 "========================= Memory Configuration" 252 " ===============================\n" 253 "\n Logical Logical" 254 " Logical " 255 "\n MC Bank Bank Bank" 256 " DIMM Interleave Interleaved" 257 "\n Brd ID num size " 258 "Status Size " 259 "Factor with" 260 "\n---- --- ---- ------ " 261 "----------- ------ " 262 "---------- -----------")); 263 264 while (bnode != NULL) { 265 if (get_us3_mem_regs(bnode)) { 266 log_printf(dgettext(TEXT_DOMAIN, 267 "\nFailed to get memory information.\n")); 268 return; 269 } 270 bnode = bnode->next; 271 } 272 273 /* Display what we have found */ 274 display_us3_banks(); 275 } 276 277 void 278 display_cpu_devices(Sys_tree *tree) 279 { 280 Board_node *bnode; 281 282 /* 283 * Display the table header for CPUs . Then display the CPU 284 * frequency, cache size, and processor revision of all cpus. 285 */ 286 log_printf(dgettext(TEXT_DOMAIN, 287 "\n" 288 "=========================" 289 " CPUs " 290 "===============================================" 291 "\n" 292 "\n" 293 " Run E$ CPU CPU \n" 294 "Brd CPU MHz MB Impl. Mask \n" 295 "--- ----- ---- ---- ------- ---- \n")); 296 297 /* Now display all of the cpus on each board */ 298 bnode = tree->bd_list; 299 if (bnode == NULL) { 300 log_printf(dgettext(TEXT_DOMAIN, 301 "CPU Board list was NULL\n")); 302 } 303 while (bnode != NULL) { 304 display_cpus(bnode); 305 bnode = bnode->next; 306 } 307 308 log_printf("\n"); 309 } 310 311 /* 312 * Display the CPUs present on this board. 313 */ 314 void 315 display_cpus(Board_node *board) 316 { 317 Prom_node *cpu; 318 uint_t freq; /* CPU clock frequency */ 319 int ecache_size; /* External cache size */ 320 int *l3_shares; 321 int *mid; 322 int *impl; 323 int *mask; 324 int *coreid; 325 char fru_prev = 'X'; /* Valid frus are 'A','B','C','D' */ 326 int mid_prev; 327 int ecache_size_prev = 0; 328 char fru_name; 329 330 /* 331 * display the CPUs' operating frequency, cache size, impl. field 332 * and mask revision. 333 */ 334 for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL; 335 cpu = dev_next_type(cpu, "cpu")) { 336 337 mid = (int *)get_prop_val(find_prop(cpu, "portid")); 338 if (mid == NULL) 339 mid = (int *)get_prop_val(find_prop(cpu, "cpuid")); 340 freq = DAK_CLK_FREQ_TO_MHZ(get_cpu_freq(cpu)); 341 ecache_size = get_ecache_size(cpu); 342 impl = (int *)get_prop_val(find_prop(cpu, "implementation#")); 343 mask = (int *)get_prop_val(find_prop(cpu, "mask#")); 344 l3_shares = (int *)get_prop_val(find_prop(cpu, 345 "l3-cache-sharing")); 346 347 /* Do not display a failed CPU node */ 348 if ((impl == NULL) || (freq == 0) || (node_failed(cpu))) 349 continue; 350 351 /* Board number */ 352 fru_name = (char)('A' + DAK_GETSLOT(*mid)); 353 354 if (CPU_IMPL_IS_CMP(*impl)) { 355 coreid = (int *)get_prop_val(find_prop(cpu, "reg")); 356 if (coreid == NULL) { 357 continue; 358 } 359 if ((fru_prev == 'X') || 360 ((fru_prev != 'X') && 361 (fru_name != fru_prev))) { 362 fru_prev = fru_name; 363 mid_prev = *mid; 364 ecache_size_prev = ecache_size; 365 continue; 366 } else { 367 /* 368 * Some CMP chips have a split E$, 369 * so the size for both cores is added 370 * together to get the total size for 371 * the chip. 372 * 373 * Still, other CMP chips have E$ (L3) 374 * which is logically shared, so the 375 * total size is equal to the core size. 376 */ 377 if ((l3_shares == NULL) || 378 ((l3_shares != NULL) && 379 MULTIPLE_BITS_SET(*l3_shares))) { 380 ecache_size += ecache_size_prev; 381 } 382 ecache_size_prev = 0; 383 fru_prev = 'X'; 384 } 385 } 386 387 log_printf("%2c", fru_name); 388 389 /* CPU Module ID */ 390 if (CPU_IMPL_IS_CMP(*impl)) { 391 log_printf("%3d,%3d", mid_prev, *mid, 0); 392 } else 393 log_printf(" %d ", *mid); 394 395 /* Running frequency */ 396 log_printf(" %4u ", freq); 397 398 /* Ecache size */ 399 if (ecache_size == 0) 400 log_printf(dgettext(TEXT_DOMAIN, "%3s "), 401 "N/A"); 402 else 403 log_printf("%4.1f ", 404 (float)ecache_size / (float)(1<<20)); 405 406 /* Implementation */ 407 if (impl == NULL) { 408 log_printf(dgettext(TEXT_DOMAIN, "%s "), 409 "N/A"); 410 } else { 411 if (IS_CHEETAH(*impl)) 412 log_printf("%7s", "US-III ", 0); 413 else if (IS_CHEETAH_PLUS(*impl)) 414 log_printf("%7s", "US-III+", 0); 415 else if (IS_JAGUAR(*impl)) 416 log_printf("%7s", "US-IV ", 0); 417 else if (IS_PANTHER(*impl)) 418 log_printf("%7s", "US-IV+ ", 0); 419 else 420 log_printf("%-7x", *impl, 0); 421 } 422 423 /* CPU Mask */ 424 if (mask == NULL) { 425 log_printf(dgettext(TEXT_DOMAIN, " %3s "), 426 "N/A"); 427 } else { 428 log_printf(dgettext(TEXT_DOMAIN, " %2d.%d"), 429 (*mask >> 4) & 0xf, *mask & 0xf); 430 } 431 432 log_printf("\n"); 433 } 434 } 435 436 /* 437 * display_pci 438 * Display all the PCI IO cards on this board. 439 */ 440 void 441 display_pci(Board_node *board) 442 { 443 struct io_card *card_list = NULL; 444 struct io_card card; 445 void *value; 446 Prom_node *pci; 447 Prom_node *card_node; 448 char *slot_name_arr[DAK_MAX_SLOTS_PER_IO_BD] = {NULL}; 449 int i; 450 #ifdef DEBUG 451 int slot_name_bits; 452 #endif 453 454 if (board == NULL) 455 return; 456 457 memset(&card, 0, sizeof (struct io_card)); 458 /* Initialize all the common information */ 459 card.display = TRUE; 460 card.board = board->board_num; 461 462 /* 463 * Search for each pci instance, then find/display all nodes under 464 * each instance node found. 465 */ 466 for (pci = dev_find_node_by_compat(board->nodes, SCHIZO_COMPAT_PROP); 467 pci != NULL; 468 pci = dev_next_node_by_compat(pci, SCHIZO_COMPAT_PROP)) { 469 (void) snprintf(card.bus_type, MAXSTRLEN, 470 dgettext(TEXT_DOMAIN, "PCI")); 471 /* 472 * Get slot-name properties from parent node and 473 * store them in an array. 474 */ 475 value = (char *)get_prop_val( 476 find_prop(pci, "slot-names")); 477 478 if (value != NULL) { 479 #ifdef DEBUG 480 /* save the 4 byte bitmask */ 481 slot_name_bits = *(int *)value; 482 #endif 483 484 /* array starts after first int */ 485 slot_name_arr[0] = (char *)value + sizeof (int); 486 for (i = 1; i < DAK_MAX_SLOTS_PER_IO_BD; i++) { 487 slot_name_arr[i] = (char *)slot_name_arr[i - 1] 488 + strlen(slot_name_arr[i - 1]) +1; 489 } 490 } 491 /* 492 * Search for Children of this node ie. Cards. 493 * Note: any of these cards can be a pci-bridge 494 * that itself has children. If we find a 495 * pci-bridge we need to handle it specially. 496 */ 497 card_node = pci->child; 498 /* Generate the list of pci cards on pci instance: pci */ 499 fill_pci_card_list(pci, card_node, &card, &card_list, 500 slot_name_arr); 501 } /* end-for */ 502 503 display_io_cards(card_list); 504 free_io_cards(card_list); 505 log_printf("\n"); 506 } 507 508 /* 509 * Print out all the io cards in the list. Also print the column 510 * headers if told to do so. 511 */ 512 void 513 display_io_cards(struct io_card *list) 514 { 515 static int banner = 0; /* Have we printed the column headings? */ 516 struct io_card *p; 517 518 if (list == NULL) 519 return; 520 521 if (banner == FALSE) { 522 log_printf(dgettext(TEXT_DOMAIN, 523 " Bus Max\n" 524 " IO Port Bus Freq Bus Dev," 525 "\n" 526 "Brd Type ID Side Slot MHz Freq " 527 "Func State Name " 528 "Model\n" 529 /* ---------Brd IO Port Bus Slot Bus Max Dev Stat */ 530 "---- ---- ---- ---- ---- ---- ---- ----" 531 " ----- " 532 "-------------------------------- " 533 "----------------------\n")); 534 banner = TRUE; 535 } 536 537 for (p = list; p != NULL; p = p -> next) { 538 log_printf(dgettext(TEXT_DOMAIN, "I/O ")); 539 log_printf("%-4s ", p->bus_type); 540 log_printf("%-3d ", p->schizo_portid); 541 log_printf("%c ", p->pci_bus); 542 log_printf("%-1s ", p->slot_str); 543 log_printf("%-3d ", p->freq); 544 switch (p->pci_bus) { 545 case 'A': 546 log_printf(dgettext(TEXT_DOMAIN, " 66 ")); 547 break; 548 case 'B': 549 log_printf(dgettext(TEXT_DOMAIN, " 33 ")); 550 break; 551 default: 552 log_printf(dgettext(TEXT_DOMAIN, " - ")); 553 break; 554 } 555 556 log_printf("%-1d,%-1d ", p->dev_no, p->func_no); 557 log_printf("%-5s ", p->status); 558 log_printf("%-32.32s", p->name); 559 if (strlen(p->name) > 32) 560 log_printf(dgettext(TEXT_DOMAIN, "+ ")); 561 else 562 log_printf(dgettext(TEXT_DOMAIN, " ")); 563 log_printf("%-22.22s", p->model); 564 if (strlen(p->model) > 22) 565 log_printf(dgettext(TEXT_DOMAIN, "+")); 566 567 #ifdef DEBUG 568 log_printf(dgettext(TEXT_DOMAIN, "%s "), p->notes); 569 #endif 570 log_printf("\n"); 571 } 572 } 573 574 /* 575 * display_ffb 576 * 577 * There are no FFB's on a Daktari, however in the generic library, 578 * the display_ffb() function is implemented so we have to define an 579 * empty function here. 580 */ 581 /* ARGSUSED */ 582 void 583 display_ffb(Board_node *board, int table) 584 {} 585 586 587 /* 588 * ---------------------------------------------------------------------------- 589 */ 590 591 /* ARGSUSED */ 592 void 593 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 594 struct system_kstat_data *kstats) 595 { 596 /* NOTE(ARGUNUSED(kstats)) */ 597 /* 598 * Now display the last powerfail time and the fatal hardware 599 * reset information. We do this under a couple of conditions. 600 * First if the user asks for it. The second is if the user 601 * told us to do logging, and we found a system failure. 602 */ 603 if (flag) { 604 /* 605 * display time of latest powerfail. Not all systems 606 * have this capability. For those that do not, this 607 * is just a no-op. 608 */ 609 disp_powerfail(root); 610 611 (void) disp_envc_status(); 612 613 /* platform_disp_prom_version(tree); */ 614 dak_display_hw_revisions(root, tree->bd_list); 615 } 616 } 617 618 /* 619 * local functions 620 */ 621 622 /* 623 * disp_envc_status 624 * 625 * This routine displays the environmental status passed up from 626 * device drivers via the envlibobj.so library. 627 * This is a Daktari specific environmental information display routine. 628 */ 629 int 630 disp_envc_status() 631 { 632 int err; 633 char *system = "SYSTEM"; 634 picl_nodehdl_t system_node, root; 635 636 err = picl_initialize(); 637 if (err != PICL_SUCCESS) { 638 log_printf(dgettext(TEXT_DOMAIN, 639 "picl_initialize failed\n" 640 "%s\nCannot display environmental status\n"), 641 picl_strerror(err)); 642 return (err); 643 } 644 err = picl_get_root(&root); 645 err = find_child_device(root, system, &system_node); 646 if (err != PICL_SUCCESS) { 647 log_printf(dgettext(TEXT_DOMAIN, 648 "picl_get_node_by_path for the SYSTEM node " 649 "failed\n" 650 "%s\nCannot display environmental status\n"), 651 picl_strerror(err)); 652 return (err); 653 } 654 655 log_printf(dgettext(TEXT_DOMAIN, 656 "\n" 657 "========================= " 658 "Environmental Status " 659 "=========================" 660 "\n" 661 "\n")); 662 663 dak_env_print_temps(system_node); 664 dak_env_print_keyswitch(system_node); 665 dak_env_print_FSP_LEDS(system_node); 666 dak_env_print_disk(system_node); 667 dak_env_print_fans(system_node); 668 dak_env_print_ps(system_node); 669 670 (void) picl_shutdown(); 671 return (0); 672 } 673 674 int 675 dak_env_print_ps(picl_nodehdl_t system_node) 676 { 677 int i, r, fail, err = 0; 678 int32_t number; 679 char name[PICL_PROPNAMELEN_MAX]; 680 picl_nodehdl_t *ps; 681 picl_nodehdl_t *ps_fail[DAK_MAX_PS_FAULT_SENSORS]; 682 picl_nodehdl_t *ps_I_sensor[DAK_MAX_PS_VOLTAGE_SENSORS]; 683 int32_t volts[DAK_MAX_PS_VOLTAGE_SENSORS]; 684 char fault_state 685 [DAK_MAX_PS_FAULT_SENSORS][PICL_PROPNAMELEN_MAX]; 686 char ps_state[PICL_PROPNAMELEN_MAX]; 687 /* Printing out the Power Supply Heading information */ 688 log_printf(dgettext(TEXT_DOMAIN, 689 "Power Supplies:\n" 690 "---------------\n" 691 " " 692 "Current Drain:\n" 693 "Supply Status Fan Fail Temp Fail CS Fail " 694 "3.3V 5V 12V 48V\n" 695 "------ ------------ -------- --------- " 696 "------- ---- -- --- ---\n")); 697 698 err = fill_device_array_from_id(system_node, "PSVC_PS", &number, 699 &ps); 700 if (err != PICL_SUCCESS) { 701 log_printf(dgettext(TEXT_DOMAIN, 702 "failed in fill_device_array_from_id for PS\n" 703 "%s\n"), picl_strerror(err)); 704 return (err); 705 } 706 /* Printing out the Power Supply Status information */ 707 for (i = 0; i < DAK_MAX_PS; i++) { 708 /* 709 * Re initialize the fail variable so that if 710 * one power supply fails, they don't all do also. 711 */ 712 fail = 0; 713 714 err = picl_get_propval_by_name(ps[i], PICL_PROP_NAME, name, 715 PICL_PROPNAMELEN_MAX); 716 if (err != PICL_SUCCESS) { 717 continue; 718 } 719 err = picl_get_propval_by_name(ps[i], "State", ps_state, 720 PICL_PROPNAMELEN_MAX); 721 if (err != PICL_SUCCESS) { 722 log_printf(dgettext(TEXT_DOMAIN, 723 "Error getting ps[%d]'s state: %s"), 724 i, picl_strerror(err)); 725 } 726 727 err = fill_device_array_from_id(ps[i], "PSVC_DEV_FAULT_SENSOR", 728 &number, &ps_fail[i]); 729 730 if (err != PICL_SUCCESS) { 731 log_printf(dgettext(TEXT_DOMAIN, 732 "failed to get present PS fault sensors\n" 733 "%s\n"), picl_strerror(err)); 734 return (err); 735 } 736 737 err = fill_device_array_from_id(ps[i], "PSVC_PS_I_SENSOR", 738 &number, &ps_I_sensor[i]); 739 740 if ((err != PICL_SUCCESS) && (err != PICL_INVALIDHANDLE)) { 741 log_printf(dgettext(TEXT_DOMAIN, 742 "failed to get present PS I sensors\n" 743 "%s\n"), picl_strerror(err)); 744 } 745 746 log_printf("%s", name); 747 748 /* 749 * If the AC cord is unplugged, then the power supply 750 * sensors will have unreliable values. In this case, 751 * skip to the next power supply. 752 */ 753 if (strcmp(ps_state, "HOTPLUGGED") == 0) { 754 log_printf(dgettext(TEXT_DOMAIN, 755 " UNPLUGGED\n")); 756 continue; 757 } 758 759 for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) { 760 err = picl_get_propval_by_name(ps_fail[i][r], "State", 761 fault_state[r], PICL_PROPNAMELEN_MAX); 762 if (err == PICL_SUCCESS) { 763 fail = 764 strcmp(fault_state[r], "OFF") 765 + fail; 766 } else { 767 log_printf(dgettext(TEXT_DOMAIN, 768 "picl_get_propval_by_name for ps " 769 "fault state failed\n" 770 "%s\n"), picl_strerror(err)); 771 return (err); 772 } 773 } 774 for (r = 0; r < DAK_MAX_PS_VOLTAGE_SENSORS; r++) { 775 err = picl_get_propval_by_name(ps_I_sensor[i][r], 776 "AtoDSensorValue", &volts[r], 777 sizeof (int32_t)); 778 } 779 780 if (fail != 0) { 781 log_printf(dgettext(TEXT_DOMAIN, 782 " FAIL ")); 783 for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) { 784 log_printf(dgettext(TEXT_DOMAIN, " %-4s"), 785 fault_state[r]); 786 } 787 } else { 788 log_printf(dgettext(TEXT_DOMAIN, " GOOD ")); 789 for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) { 790 log_printf(dgettext(TEXT_DOMAIN, " ")); 791 } 792 } 793 for (r = 0; r < DAK_MAX_PS_VOLTAGE_SENSORS; r++) { 794 log_printf(dgettext(TEXT_DOMAIN, " %2d"), volts[r]); 795 } 796 log_printf("\n"); 797 } 798 log_printf("\n"); 799 return (err); 800 } 801 802 int 803 dak_env_print_fans(picl_nodehdl_t system_node) 804 { 805 int i, err = 0; 806 int32_t number, fan_speed; 807 picl_nodehdl_t *fans; 808 char name[PICL_PROPNAMELEN_MAX]; 809 char enabled[PICL_PROPNAMELEN_MAX]; 810 811 err = fill_device_array_from_id(system_node, "PSVC_FAN", &number, 812 &fans); 813 if (err != PICL_SUCCESS) { 814 log_printf(dgettext(TEXT_DOMAIN, 815 "failed in fill_device_array_from_id " 816 "for FAN\n" 817 "%s\n"), picl_strerror(err)); 818 return (err); 819 } 820 821 log_printf("\n"); 822 log_printf(dgettext(TEXT_DOMAIN, 823 "=================================\n")); 824 log_printf("\n"); 825 log_printf(dgettext(TEXT_DOMAIN, "Fan Bank :\n")); 826 log_printf(dgettext(TEXT_DOMAIN, "----------\n")); 827 log_printf("\n"); 828 log_printf(dgettext(TEXT_DOMAIN, "Bank Speed " 829 " Status Fan State\n")); 830 log_printf(dgettext(TEXT_DOMAIN, " ( RPMS )" 831 " \n")); 832 log_printf(dgettext(TEXT_DOMAIN, "---- --------" 833 " --------- ---------\n")); 834 835 836 for (i = 0; i < DAK_MAX_FANS; i++) { 837 char fan_state[PICL_PROPNAMELEN_MAX]; 838 fan_speed = 0; 839 err = picl_get_propval_by_name(fans[i], PICL_PROP_NAME, name, 840 PICL_PROPNAMELEN_MAX); 841 if (err == PICL_SUCCESS) { 842 log_printf(dgettext(TEXT_DOMAIN, "%16-s"), name); 843 } else { 844 continue; 845 } 846 847 err = picl_get_propval_by_name(fans[i], "Fan-speed", 848 &fan_speed, sizeof (int32_t)); 849 if ((err != PICL_SUCCESS) && (err != PICL_INVALIDHANDLE)) { 850 log_printf(dgettext(TEXT_DOMAIN, 851 "failed in picl_get_propval_by_name for " 852 "fan speed\n" 853 "%s\n"), picl_strerror(err)); 854 return (err); 855 } 856 857 if ((strcmp(name, "CPU0_PRIM_FAN") != 0) && 858 (strcmp(name, "CPU1_PRIM_FAN") != 0)) { 859 err = picl_get_propval_by_name(fans[i], "Fan-switch", 860 enabled, PICL_PROPNAMELEN_MAX); 861 if ((err != PICL_SUCCESS) && 862 (err != PICL_INVALIDHANDLE)) { 863 log_printf(dgettext(TEXT_DOMAIN, 864 "failed in picl_get_propval_by_name for" 865 " fan enabled/disabled\n" 866 "%s\n"), picl_strerror(err)); 867 return (err); 868 } 869 /* 870 * Display the fan's speed and whether or not 871 * it's enabled. 872 */ 873 if (strcmp(enabled, "ON") == 0) { 874 log_printf(dgettext(TEXT_DOMAIN, 875 "\t %4d [ENABLED]"), 876 fan_speed); 877 } else { 878 log_printf(dgettext(TEXT_DOMAIN, 879 "\t 0 [DISABLED]")); 880 } 881 882 } else { 883 /* Display the fan's speed */ 884 log_printf(dgettext(TEXT_DOMAIN, "\t %4d"), 885 fan_speed); 886 log_printf(dgettext(TEXT_DOMAIN, 887 " [ENABLED]")); 888 } 889 890 err = picl_get_propval_by_name(fans[i], "State", fan_state, 891 PICL_PROPNAMELEN_MAX); 892 if (err != PICL_SUCCESS) { 893 log_printf(dgettext(TEXT_DOMAIN, 894 "picl_get_propval_by_name failed: %s"), 895 picl_strerror(err)); 896 return (err); 897 } 898 log_printf(dgettext(TEXT_DOMAIN, "\t %s\n"), fan_state); 899 } 900 log_printf("\n"); 901 log_printf(dgettext(TEXT_DOMAIN, 902 "=================================\n")); 903 log_printf("\n"); 904 905 return (err); 906 } 907 908 int 909 dak_env_print_disk(picl_nodehdl_t system_node) 910 { 911 int i, err; 912 int32_t number; 913 picl_nodehdl_t *disks; 914 picl_nodehdl_t disk_slots[DAK_MAX_DISKS]; 915 picl_nodehdl_t disk_fault_leds[DAK_MAX_DISKS]; 916 picl_nodehdl_t disk_remove_leds[DAK_MAX_DISKS]; 917 char led_state[PICL_PROPNAMELEN_MAX]; 918 char name[PICL_PROPNAMELEN_MAX]; 919 920 err = fill_device_array_from_id(system_node, "PSVC_DISK", &number, 921 &disks); 922 if (err != PICL_SUCCESS) { 923 log_printf(dgettext(TEXT_DOMAIN, 924 "failed in fill_device_array_from_id for " 925 "DISK\n" 926 "%s\n"), picl_strerror(err)); 927 return (err); 928 } 929 930 log_printf(dgettext(TEXT_DOMAIN, 931 "Disk Status:\n" 932 " Presence Fault LED Remove LED\n")); 933 934 for (i = 0; i < DAK_MAX_DISKS; i++) { 935 err = picl_get_propval_by_name(disks[i], PICL_PROP_NAME, name, 936 PICL_PROPNAMELEN_MAX); 937 switch (err) { 938 case PICL_SUCCESS: 939 log_printf(dgettext(TEXT_DOMAIN, "DISK %2d: [%7s]"), 940 i, "PRESENT"); 941 break; 942 case PICL_INVALIDHANDLE: 943 log_printf(dgettext(TEXT_DOMAIN, "DISK %2d: [%7s]"), 944 i, "EMPTY"); 945 log_printf("\n"); 946 continue; 947 default: 948 log_printf(dgettext(TEXT_DOMAIN, 949 "Failed picl_get_propval_by_name for " 950 "disk %d with %s\n"), i, picl_strerror(err)); 951 return (err); 952 } 953 954 err = fill_device_from_id(disks[i], "PSVC_PARENT", 955 &(disk_slots[i])); 956 switch (err) { 957 case PICL_SUCCESS: 958 break; 959 case PICL_INVALIDHANDLE: 960 continue; 961 default: 962 log_printf(dgettext(TEXT_DOMAIN, 963 "failed in fill_device_from_id for disk " 964 "slot\n" 965 "%s\n"), picl_strerror(err)); 966 return (err); 967 } 968 969 err = fill_device_from_id(disk_slots[i], "PSVC_SLOT_FAULT_LED", 970 &disk_fault_leds[i]); 971 if (err != PICL_SUCCESS) { 972 log_printf(dgettext(TEXT_DOMAIN, 973 "failed in fill_device_from_id for disk slot " 974 "fault led\n" 975 "%s\n"), picl_strerror(err)); 976 return (err); 977 } 978 err = picl_get_propval_by_name(disk_fault_leds[i], 979 "State", led_state, PICL_PROPNAMELEN_MAX); 980 if (err == PICL_SUCCESS) { 981 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"), 982 led_state); 983 } else { 984 log_printf(dgettext(TEXT_DOMAIN, 985 "picl_get_propval_by_name for fault led_state" 986 " failed\n" 987 "%s\n"), picl_strerror(err)); 988 return (err); 989 } 990 err = fill_device_from_id(disk_slots[i], "PSVC_SLOT_REMOVE_LED", 991 &disk_remove_leds[i]); 992 if (err != PICL_SUCCESS) { 993 log_printf(dgettext(TEXT_DOMAIN, 994 "failed in fill_device_from_id for disk slot " 995 "remove led\n" 996 "%s\n"), picl_strerror(err)); 997 return (err); 998 } 999 1000 err = picl_get_propval_by_name(disk_remove_leds[i], 1001 "State", led_state, PICL_PROPNAMELEN_MAX); 1002 if (err == PICL_SUCCESS) { 1003 log_printf(dgettext(TEXT_DOMAIN, 1004 " [%3s]"), led_state); 1005 } else { 1006 log_printf(dgettext(TEXT_DOMAIN, 1007 "picl_get_propval_by_name for remove" 1008 " led_state failed\n" 1009 "%s\n"), picl_strerror(err)); 1010 return (err); 1011 } 1012 log_printf("\n"); 1013 } 1014 return (err); 1015 } 1016 1017 int 1018 dak_env_print_FSP_LEDS(picl_nodehdl_t system_node) 1019 { 1020 int i, err = 0; 1021 int32_t number; 1022 picl_nodehdl_t *fsp_leds; 1023 char led_state[PICL_PROPNAMELEN_MAX]; 1024 1025 err = fill_device_array_from_id(system_node, "PSVC_FSP_LED", &number, 1026 &fsp_leds); 1027 if (err != PICL_SUCCESS) { 1028 log_printf(dgettext(TEXT_DOMAIN, 1029 "failed in fill_device_array_from_id for " 1030 "FSP_LED\n" 1031 "%s\n"), picl_strerror(err)); 1032 return (err); 1033 } 1034 1035 log_printf(dgettext(TEXT_DOMAIN, 1036 "System LED Status:\n" 1037 " GEN FAULT REMOVE\n")); 1038 for (i = 0; i < DAK_MAX_FSP_LEDS; i++) { 1039 err = picl_get_propval_by_name(fsp_leds[i], "State", 1040 led_state, PICL_PROPNAMELEN_MAX); 1041 if (err != PICL_SUCCESS) { 1042 log_printf(dgettext(TEXT_DOMAIN, 1043 "picl_get_propval_by_name for led_state" 1044 " failed\n" 1045 "%s\n"), picl_strerror(err)); 1046 return (err); 1047 } 1048 1049 log_printf(dgettext(TEXT_DOMAIN, 1050 " [%3s]"), led_state); 1051 } 1052 log_printf("\n\n"); 1053 log_printf(dgettext(TEXT_DOMAIN, 1054 " DISK FAULT ")); 1055 log_printf(dgettext(TEXT_DOMAIN, "POWER FAULT\n")); 1056 for (i = 2; i < 4; i++) { 1057 err = picl_get_propval_by_name(fsp_leds[i], "State", 1058 led_state, PICL_PROPNAMELEN_MAX); 1059 if (err != PICL_SUCCESS) { 1060 log_printf(dgettext(TEXT_DOMAIN, 1061 "picl_get_propval_by_name for led_state" 1062 " failed\n" 1063 "%s\n"), picl_strerror(err)); 1064 return (err); 1065 } 1066 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"), 1067 led_state); 1068 } 1069 log_printf("\n\n"); 1070 log_printf(dgettext(TEXT_DOMAIN, 1071 " LEFT THERMAL FAULT " 1072 "RIGHT THERMAL FAULT\n")); 1073 for (i = 4; i < 6; i++) { 1074 err = picl_get_propval_by_name(fsp_leds[i], "State", 1075 led_state, PICL_PROPNAMELEN_MAX); 1076 if (err != PICL_SUCCESS) { 1077 log_printf(dgettext(TEXT_DOMAIN, 1078 "picl_get_propval_by_name for led_state " 1079 "failed\n" 1080 "%s\n"), picl_strerror(err)); 1081 return (err); 1082 } 1083 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"), 1084 led_state); 1085 } 1086 log_printf("\n\n"); 1087 log_printf(dgettext(TEXT_DOMAIN, 1088 " LEFT DOOR " 1089 "RIGHT DOOR\n")); 1090 for (i = 6; i < 8; i++) { 1091 err = picl_get_propval_by_name(fsp_leds[i], "State", 1092 led_state, PICL_PROPNAMELEN_MAX); 1093 if (err != PICL_SUCCESS) { 1094 log_printf(dgettext(TEXT_DOMAIN, 1095 "picl_get_propval_by_name for led_state" 1096 " failed\n" 1097 "%s\n"), picl_strerror(err)); 1098 return (err); 1099 } 1100 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"), 1101 led_state); 1102 } 1103 log_printf("\n\n"); 1104 log_printf(dgettext(TEXT_DOMAIN, 1105 "=================================\n")); 1106 log_printf("\n"); 1107 1108 return (err); 1109 } 1110 1111 int 1112 dak_env_print_keyswitch(picl_nodehdl_t system_node) 1113 { 1114 int err = 0; 1115 picl_nodehdl_t *keyswitch; 1116 int32_t number; 1117 char ks_pos[PICL_PROPNAMELEN_MAX]; 1118 1119 err = fill_device_array_from_id(system_node, "PSVC_KEYSWITCH", &number, 1120 &keyswitch); 1121 if (err != PICL_SUCCESS) { 1122 log_printf(dgettext(TEXT_DOMAIN, 1123 "failed in fill_device_array_from_id for " 1124 " PSVC_KEYSWITCH\n" 1125 "%s\n"), picl_strerror(err)); 1126 return (err); 1127 } 1128 1129 err = picl_get_propval_by_name(keyswitch[0], "State", ks_pos, 1130 PICL_PROPNAMELEN_MAX); 1131 if (err != PICL_SUCCESS) { 1132 log_printf(dgettext(TEXT_DOMAIN, 1133 "picl_get_propval_by_name for keyswitch state " 1134 "failed\n" 1135 "%s\n"), picl_strerror(err)); 1136 return (err); 1137 } 1138 1139 log_printf(dgettext(TEXT_DOMAIN, 1140 "Front Status Panel:\n" 1141 "-------------------\n" 1142 "Keyswitch position: " 1143 "%s\n"), ks_pos); 1144 log_printf("\n"); 1145 1146 return (err); 1147 } 1148 1149 int 1150 dak_env_print_temps(picl_nodehdl_t system_node) 1151 { 1152 int i; 1153 int err; 1154 picl_nodehdl_t *system_ts_nodes; 1155 int32_t temp; 1156 int32_t number; 1157 char label[PICL_PROPNAMELEN_MAX]; 1158 char state[PICL_PROPNAMELEN_MAX]; 1159 char *p; 1160 1161 err = fill_device_array_from_id(system_node, "PSVC_TS", &number, 1162 &system_ts_nodes); 1163 if (err != PICL_SUCCESS) { 1164 return (err); 1165 } 1166 1167 log_printf(dgettext(TEXT_DOMAIN, 1168 "System Temperatures (Celsius):\n" 1169 "-------------------------------\n" 1170 "Device\t\tTemperature\tStatus\n" 1171 "---------------------------------------\n")); 1172 1173 for (i = 0; i < number; i++) { 1174 err = picl_get_propval_by_name(system_ts_nodes[i], 1175 "State", state, sizeof (state)); 1176 if (err != PICL_SUCCESS) { 1177 if (err == PICL_INVALIDHANDLE) { 1178 strcpy(state, "n/a"); 1179 } else { 1180 log_printf("%s\n", picl_strerror(err)); 1181 return (err); 1182 } 1183 } 1184 err = picl_get_propval_by_name(system_ts_nodes[i], 1185 PICL_PROP_NAME, label, PICL_PROPNAMELEN_MAX); 1186 if (err != PICL_SUCCESS) { 1187 if (err == PICL_INVALIDHANDLE) 1188 /* This FRU isn't present. Skip it. */ 1189 continue; 1190 log_printf("%s\n", picl_strerror(err)); 1191 return (err); 1192 } 1193 1194 /* 1195 * The names in the tree are like "CPU0_DIE_TEMPERATURE_SENSOR". 1196 * All we want to print is up to the first underscore. 1197 */ 1198 p = strchr(label, '_'); 1199 if (p != NULL) 1200 *p = '\0'; 1201 1202 err = picl_get_propval_by_name(system_ts_nodes[i], 1203 "Temperature", &temp, sizeof (temp)); 1204 if (err != PICL_SUCCESS) { 1205 log_printf("%s\n", picl_strerror(err)); 1206 return (err); 1207 } 1208 log_printf("%s\t\t%3d\t\t%s\n", label, temp, state); 1209 } 1210 1211 log_printf(dgettext(TEXT_DOMAIN, 1212 "\n=================================\n\n")); 1213 1214 return (PICL_SUCCESS); 1215 } 1216 1217 static void 1218 dak_display_hw_revisions(Prom_node *root, Board_node *bdlist) 1219 { 1220 Prom_node *pnode; 1221 char *value; 1222 1223 log_printf(dgettext(TEXT_DOMAIN, "\n" 1224 "========================= HW Revisions " 1225 "=======================================\n\n")); 1226 1227 log_printf(dgettext(TEXT_DOMAIN, 1228 "System PROM revisions:\n" 1229 "----------------------\n")); 1230 1231 pnode = dev_find_node(root, "openprom"); 1232 if (pnode != NULL) { 1233 value = (char *)get_prop_val(find_prop(pnode, "version")); 1234 log_printf(value); 1235 } 1236 1237 log_printf(dgettext(TEXT_DOMAIN, "\n\n" 1238 "IO ASIC revisions:\n" 1239 "------------------\n" 1240 " Port\n" 1241 "Model ID Status Version\n" 1242 "-------- ---- ------ -------\n")); 1243 1244 display_schizo_revisions(bdlist); 1245 } 1246 1247 static void 1248 display_schizo_revisions(Board_node *bdlist) 1249 { 1250 Prom_node *pnode; 1251 int *int_val; 1252 int portid; 1253 int prev_portid = -1; 1254 char *status_a = NULL; 1255 char *status_b = NULL; 1256 int revision; 1257 #ifdef DEBUG 1258 uint32_t a_notes, b_notes; 1259 #endif 1260 int pci_bus; 1261 Board_node *bnode; 1262 bnode = bdlist; 1263 1264 while (bnode != NULL) { 1265 /* 1266 * search this board node for all Schizos 1267 */ 1268 for (pnode = dev_find_node_by_compat(bnode->nodes, 1269 SCHIZO_COMPAT_PROP); pnode != NULL; 1270 pnode = dev_next_node_by_compat(pnode, 1271 SCHIZO_COMPAT_PROP)) { 1272 1273 /* 1274 * get the reg property to determine 1275 * whether we are looking at side A or B 1276 */ 1277 int_val = (int *)get_prop_val 1278 (find_prop(pnode, "reg")); 1279 if (int_val != NULL) { 1280 int_val ++; /* second integer in array */ 1281 pci_bus = ((*int_val) & 0x7f0000); 1282 } 1283 1284 /* get portid */ 1285 int_val = (int *)get_prop_val 1286 (find_prop(pnode, "portid")); 1287 if (int_val == NULL) 1288 continue; 1289 1290 portid = *int_val; 1291 1292 /* 1293 * If this is a new portid and it is PCI bus B, 1294 * we skip onto the PCI bus A. 1295 */ 1296 if ((portid != prev_portid) && (pci_bus == 0x700000)) { 1297 prev_portid = portid; 1298 /* status */ 1299 status_b = (char *)get_prop_val 1300 (find_prop(pnode, "status")); 1301 #ifdef DEBUG 1302 b_notes = pci_bus; 1303 #endif 1304 continue; /* skip to the next schizo */ 1305 } 1306 1307 /* 1308 * This must be side A of the same Schizo. 1309 * Gather all its props and display them. 1310 */ 1311 #ifdef DEBUG 1312 a_notes = pci_bus; 1313 #endif 1314 1315 prev_portid = portid; 1316 1317 int_val = (int *)get_prop_val 1318 (find_prop(pnode, "version#")); 1319 if (int_val != NULL) 1320 revision = *int_val; 1321 else 1322 revision = -1; 1323 1324 status_a = (char *)get_prop_val(find_prop 1325 (pnode, "status")); 1326 1327 log_printf(dgettext(TEXT_DOMAIN, "Schizo ")); 1328 1329 log_printf(dgettext(TEXT_DOMAIN, "%-3d "), portid, 0); 1330 1331 1332 log_printf((status_a == NULL && status_b == NULL) ? 1333 dgettext(TEXT_DOMAIN, " ok ") : 1334 dgettext(TEXT_DOMAIN, " fail ")); 1335 1336 log_printf(dgettext(TEXT_DOMAIN, " %4d "), 1337 revision); 1338 #ifdef DEBUG 1339 log_printf(" 0x%x 0x%x", a_notes, b_notes); 1340 #endif 1341 log_printf("\n"); 1342 } 1343 bnode = bnode->next; 1344 } 1345 } 1346