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 int low_warn_flag = 0; 679 int32_t number; 680 char name[PICL_PROPNAMELEN_MAX]; 681 picl_nodehdl_t *ps; 682 picl_nodehdl_t *ps_fail[DAK_MAX_PS_FAULT_SENSORS]; 683 picl_nodehdl_t *ps_I_sensor[DAK_MAX_PS_VOLTAGE_SENSORS]; 684 int32_t volts[DAK_MAX_PS_VOLTAGE_SENSORS]; 685 int32_t lo_warn[DAK_MAX_PS_VOLTAGE_SENSORS]; 686 char fault_state 687 [DAK_MAX_PS_FAULT_SENSORS][PICL_PROPNAMELEN_MAX]; 688 char ps_state[PICL_PROPNAMELEN_MAX]; 689 /* Printing out the Power Supply Heading information */ 690 log_printf(dgettext(TEXT_DOMAIN, 691 "Power Supplies:\n" 692 "---------------\n" 693 " " 694 "Current Drain:\n" 695 "Supply Status Fan Fail Temp Fail CS Fail " 696 "3.3V 5V 12V 48V\n" 697 "------ ------------ -------- --------- " 698 "------- ---- -- --- ---\n")); 699 700 err = fill_device_array_from_id(system_node, "PSVC_PS", &number, 701 &ps); 702 if (err != PICL_SUCCESS) { 703 log_printf(dgettext(TEXT_DOMAIN, 704 "failed in fill_device_array_from_id for PS\n" 705 "%s\n"), picl_strerror(err)); 706 return (err); 707 } 708 /* Printing out the Power Supply Status information */ 709 for (i = 0; i < DAK_MAX_PS; i++) { 710 /* 711 * Re initialize the fail variable so that if 712 * one power supply fails, they don't all do also. 713 */ 714 fail = 0; 715 716 err = picl_get_propval_by_name(ps[i], PICL_PROP_NAME, name, 717 PICL_PROPNAMELEN_MAX); 718 if (err != PICL_SUCCESS) { 719 continue; 720 } 721 err = picl_get_propval_by_name(ps[i], "State", ps_state, 722 PICL_PROPNAMELEN_MAX); 723 if (err != PICL_SUCCESS) { 724 log_printf(dgettext(TEXT_DOMAIN, 725 "Error getting ps[%d]'s state: %s"), 726 i, picl_strerror(err)); 727 } 728 729 err = fill_device_array_from_id(ps[i], "PSVC_DEV_FAULT_SENSOR", 730 &number, &ps_fail[i]); 731 732 if (err != PICL_SUCCESS) { 733 log_printf(dgettext(TEXT_DOMAIN, 734 "failed to get present PS fault sensors\n" 735 "%s\n"), picl_strerror(err)); 736 return (err); 737 } 738 739 err = fill_device_array_from_id(ps[i], "PSVC_PS_I_SENSOR", 740 &number, &ps_I_sensor[i]); 741 742 if ((err != PICL_SUCCESS) && (err != PICL_INVALIDHANDLE)) { 743 log_printf(dgettext(TEXT_DOMAIN, 744 "failed to get present PS I sensors\n" 745 "%s\n"), picl_strerror(err)); 746 } 747 748 log_printf("%s", name); 749 750 /* 751 * If the AC cord is unplugged, then the power supply 752 * sensors will have unreliable values. In this case, 753 * skip to the next power supply. 754 */ 755 if (strcmp(ps_state, "HOTPLUGGED") == 0) { 756 log_printf(dgettext(TEXT_DOMAIN, 757 " UNPLUGGED\n")); 758 continue; 759 } 760 761 for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) { 762 err = picl_get_propval_by_name(ps_fail[i][r], "State", 763 fault_state[r], PICL_PROPNAMELEN_MAX); 764 if (err == PICL_SUCCESS) { 765 fail = 766 strcmp(fault_state[r], "OFF") 767 + fail; 768 } else { 769 log_printf(dgettext(TEXT_DOMAIN, 770 "picl_get_propval_by_name for ps " 771 "fault state failed\n" 772 "%s\n"), picl_strerror(err)); 773 return (err); 774 } 775 } 776 for (r = 0; r < DAK_MAX_PS_VOLTAGE_SENSORS; r++) { 777 err = picl_get_propval_by_name(ps_I_sensor[i][r], 778 "AtoDSensorValue", &volts[r], 779 sizeof (int32_t)); 780 if (err != PICL_SUCCESS) { 781 log_printf(dgettext(TEXT_DOMAIN, 782 "failed to get A to D sensor " 783 "value\n%s\n"), picl_strerror(err)); 784 return (err); 785 } 786 err = picl_get_propval_by_name(ps_I_sensor[i][r], 787 "LowWarningThreshold", &lo_warn[r], 788 sizeof (int32_t)); 789 if (err != PICL_SUCCESS) { 790 log_printf(dgettext(TEXT_DOMAIN, 791 "failed to get low warning threshold " 792 "value\n%s\n"), picl_strerror(err)); 793 return (err); 794 } 795 if (volts[r] <= lo_warn[r]) 796 low_warn_flag++; 797 } 798 799 if (fail != 0 || low_warn_flag != 0) { 800 log_printf(dgettext(TEXT_DOMAIN, 801 " FAIL ")); 802 } else { 803 log_printf(dgettext(TEXT_DOMAIN, " GOOD ")); 804 } 805 806 if (fail != 0) { 807 for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) { 808 log_printf(dgettext(TEXT_DOMAIN, " %-4s"), 809 fault_state[r]); 810 } 811 } else { 812 for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) { 813 log_printf(dgettext(TEXT_DOMAIN, " ")); 814 } 815 } 816 for (r = 0; r < DAK_MAX_PS_VOLTAGE_SENSORS; r++) { 817 log_printf(dgettext(TEXT_DOMAIN, " %2d"), volts[r]); 818 } 819 log_printf("\n"); 820 } 821 log_printf("\n"); 822 return (err); 823 } 824 825 int 826 dak_env_print_fans(picl_nodehdl_t system_node) 827 { 828 int i, err = 0; 829 int32_t number, fan_speed; 830 picl_nodehdl_t *fans; 831 char name[PICL_PROPNAMELEN_MAX]; 832 char enabled[PICL_PROPNAMELEN_MAX]; 833 834 err = fill_device_array_from_id(system_node, "PSVC_FAN", &number, 835 &fans); 836 if (err != PICL_SUCCESS) { 837 log_printf(dgettext(TEXT_DOMAIN, 838 "failed in fill_device_array_from_id " 839 "for FAN\n" 840 "%s\n"), picl_strerror(err)); 841 return (err); 842 } 843 844 log_printf("\n"); 845 log_printf(dgettext(TEXT_DOMAIN, 846 "=================================\n")); 847 log_printf("\n"); 848 log_printf(dgettext(TEXT_DOMAIN, "Fan Bank :\n")); 849 log_printf(dgettext(TEXT_DOMAIN, "----------\n")); 850 log_printf("\n"); 851 log_printf(dgettext(TEXT_DOMAIN, "Bank Speed " 852 " Status Fan State\n")); 853 log_printf(dgettext(TEXT_DOMAIN, " ( RPMS )" 854 " \n")); 855 log_printf(dgettext(TEXT_DOMAIN, "---- --------" 856 " --------- ---------\n")); 857 858 859 for (i = 0; i < DAK_MAX_FANS; i++) { 860 char fan_state[PICL_PROPNAMELEN_MAX]; 861 fan_speed = 0; 862 err = picl_get_propval_by_name(fans[i], PICL_PROP_NAME, name, 863 PICL_PROPNAMELEN_MAX); 864 if (err == PICL_SUCCESS) { 865 log_printf(dgettext(TEXT_DOMAIN, "%16-s"), name); 866 } else { 867 continue; 868 } 869 870 err = picl_get_propval_by_name(fans[i], "Fan-speed", 871 &fan_speed, sizeof (int32_t)); 872 if ((err != PICL_SUCCESS) && (err != PICL_INVALIDHANDLE)) { 873 log_printf(dgettext(TEXT_DOMAIN, 874 "failed in picl_get_propval_by_name for " 875 "fan speed\n" 876 "%s\n"), picl_strerror(err)); 877 return (err); 878 } 879 880 if ((strcmp(name, "CPU0_PRIM_FAN") != 0) && 881 (strcmp(name, "CPU1_PRIM_FAN") != 0)) { 882 err = picl_get_propval_by_name(fans[i], "Fan-switch", 883 enabled, PICL_PROPNAMELEN_MAX); 884 if ((err != PICL_SUCCESS) && 885 (err != PICL_INVALIDHANDLE)) { 886 log_printf(dgettext(TEXT_DOMAIN, 887 "failed in picl_get_propval_by_name for" 888 " fan enabled/disabled\n" 889 "%s\n"), picl_strerror(err)); 890 return (err); 891 } 892 /* 893 * Display the fan's speed and whether or not 894 * it's enabled. 895 */ 896 if (strcmp(enabled, "ON") == 0) { 897 log_printf(dgettext(TEXT_DOMAIN, 898 "\t %4d [ENABLED]"), 899 fan_speed); 900 } else { 901 log_printf(dgettext(TEXT_DOMAIN, 902 "\t 0 [DISABLED]")); 903 } 904 905 } else { 906 /* Display the fan's speed */ 907 log_printf(dgettext(TEXT_DOMAIN, "\t %4d"), 908 fan_speed); 909 log_printf(dgettext(TEXT_DOMAIN, 910 " [ENABLED]")); 911 } 912 913 err = picl_get_propval_by_name(fans[i], "State", fan_state, 914 PICL_PROPNAMELEN_MAX); 915 if (err != PICL_SUCCESS) { 916 log_printf(dgettext(TEXT_DOMAIN, 917 "picl_get_propval_by_name failed: %s"), 918 picl_strerror(err)); 919 return (err); 920 } 921 log_printf(dgettext(TEXT_DOMAIN, "\t %s\n"), fan_state); 922 } 923 log_printf("\n"); 924 log_printf(dgettext(TEXT_DOMAIN, 925 "=================================\n")); 926 log_printf("\n"); 927 928 return (err); 929 } 930 931 int 932 dak_env_print_disk(picl_nodehdl_t system_node) 933 { 934 int i, err; 935 int32_t number; 936 picl_nodehdl_t *disks; 937 picl_nodehdl_t disk_slots[DAK_MAX_DISKS]; 938 picl_nodehdl_t disk_fault_leds[DAK_MAX_DISKS]; 939 picl_nodehdl_t disk_remove_leds[DAK_MAX_DISKS]; 940 char led_state[PICL_PROPNAMELEN_MAX]; 941 char name[PICL_PROPNAMELEN_MAX]; 942 943 err = fill_device_array_from_id(system_node, "PSVC_DISK", &number, 944 &disks); 945 if (err != PICL_SUCCESS) { 946 log_printf(dgettext(TEXT_DOMAIN, 947 "failed in fill_device_array_from_id for " 948 "DISK\n" 949 "%s\n"), picl_strerror(err)); 950 return (err); 951 } 952 953 log_printf(dgettext(TEXT_DOMAIN, 954 "Disk Status:\n" 955 " Presence Fault LED Remove LED\n")); 956 957 for (i = 0; i < DAK_MAX_DISKS; i++) { 958 err = picl_get_propval_by_name(disks[i], PICL_PROP_NAME, name, 959 PICL_PROPNAMELEN_MAX); 960 switch (err) { 961 case PICL_SUCCESS: 962 log_printf(dgettext(TEXT_DOMAIN, "DISK %2d: [%7s]"), 963 i, "PRESENT"); 964 break; 965 case PICL_INVALIDHANDLE: 966 log_printf(dgettext(TEXT_DOMAIN, "DISK %2d: [%7s]"), 967 i, "EMPTY"); 968 log_printf("\n"); 969 continue; 970 default: 971 log_printf(dgettext(TEXT_DOMAIN, 972 "Failed picl_get_propval_by_name for " 973 "disk %d with %s\n"), i, picl_strerror(err)); 974 return (err); 975 } 976 977 err = fill_device_from_id(disks[i], "PSVC_PARENT", 978 &(disk_slots[i])); 979 switch (err) { 980 case PICL_SUCCESS: 981 break; 982 case PICL_INVALIDHANDLE: 983 continue; 984 default: 985 log_printf(dgettext(TEXT_DOMAIN, 986 "failed in fill_device_from_id for disk " 987 "slot\n" 988 "%s\n"), picl_strerror(err)); 989 return (err); 990 } 991 992 err = fill_device_from_id(disk_slots[i], "PSVC_SLOT_FAULT_LED", 993 &disk_fault_leds[i]); 994 if (err != PICL_SUCCESS) { 995 log_printf(dgettext(TEXT_DOMAIN, 996 "failed in fill_device_from_id for disk slot " 997 "fault led\n" 998 "%s\n"), picl_strerror(err)); 999 return (err); 1000 } 1001 err = picl_get_propval_by_name(disk_fault_leds[i], 1002 "State", led_state, PICL_PROPNAMELEN_MAX); 1003 if (err == PICL_SUCCESS) { 1004 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"), 1005 led_state); 1006 } else { 1007 log_printf(dgettext(TEXT_DOMAIN, 1008 "picl_get_propval_by_name for fault led_state" 1009 " failed\n" 1010 "%s\n"), picl_strerror(err)); 1011 return (err); 1012 } 1013 err = fill_device_from_id(disk_slots[i], "PSVC_SLOT_REMOVE_LED", 1014 &disk_remove_leds[i]); 1015 if (err != PICL_SUCCESS) { 1016 log_printf(dgettext(TEXT_DOMAIN, 1017 "failed in fill_device_from_id for disk slot " 1018 "remove led\n" 1019 "%s\n"), picl_strerror(err)); 1020 return (err); 1021 } 1022 1023 err = picl_get_propval_by_name(disk_remove_leds[i], 1024 "State", led_state, PICL_PROPNAMELEN_MAX); 1025 if (err == PICL_SUCCESS) { 1026 log_printf(dgettext(TEXT_DOMAIN, 1027 " [%3s]"), led_state); 1028 } else { 1029 log_printf(dgettext(TEXT_DOMAIN, 1030 "picl_get_propval_by_name for remove" 1031 " led_state failed\n" 1032 "%s\n"), picl_strerror(err)); 1033 return (err); 1034 } 1035 log_printf("\n"); 1036 } 1037 return (err); 1038 } 1039 1040 int 1041 dak_env_print_FSP_LEDS(picl_nodehdl_t system_node) 1042 { 1043 int i, err = 0; 1044 int32_t number; 1045 picl_nodehdl_t *fsp_leds; 1046 char led_state[PICL_PROPNAMELEN_MAX]; 1047 1048 err = fill_device_array_from_id(system_node, "PSVC_FSP_LED", &number, 1049 &fsp_leds); 1050 if (err != PICL_SUCCESS) { 1051 log_printf(dgettext(TEXT_DOMAIN, 1052 "failed in fill_device_array_from_id for " 1053 "FSP_LED\n" 1054 "%s\n"), picl_strerror(err)); 1055 return (err); 1056 } 1057 1058 log_printf(dgettext(TEXT_DOMAIN, 1059 "System LED Status:\n" 1060 " GEN FAULT REMOVE\n")); 1061 for (i = 0; i < DAK_MAX_FSP_LEDS; i++) { 1062 err = picl_get_propval_by_name(fsp_leds[i], "State", 1063 led_state, PICL_PROPNAMELEN_MAX); 1064 if (err != PICL_SUCCESS) { 1065 log_printf(dgettext(TEXT_DOMAIN, 1066 "picl_get_propval_by_name for led_state" 1067 " failed\n" 1068 "%s\n"), picl_strerror(err)); 1069 return (err); 1070 } 1071 1072 log_printf(dgettext(TEXT_DOMAIN, 1073 " [%3s]"), led_state); 1074 } 1075 log_printf("\n\n"); 1076 log_printf(dgettext(TEXT_DOMAIN, 1077 " DISK FAULT ")); 1078 log_printf(dgettext(TEXT_DOMAIN, "POWER FAULT\n")); 1079 for (i = 2; i < 4; i++) { 1080 err = picl_get_propval_by_name(fsp_leds[i], "State", 1081 led_state, PICL_PROPNAMELEN_MAX); 1082 if (err != PICL_SUCCESS) { 1083 log_printf(dgettext(TEXT_DOMAIN, 1084 "picl_get_propval_by_name for led_state" 1085 " failed\n" 1086 "%s\n"), picl_strerror(err)); 1087 return (err); 1088 } 1089 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"), 1090 led_state); 1091 } 1092 log_printf("\n\n"); 1093 log_printf(dgettext(TEXT_DOMAIN, 1094 " LEFT THERMAL FAULT " 1095 "RIGHT THERMAL FAULT\n")); 1096 for (i = 4; i < 6; i++) { 1097 err = picl_get_propval_by_name(fsp_leds[i], "State", 1098 led_state, PICL_PROPNAMELEN_MAX); 1099 if (err != PICL_SUCCESS) { 1100 log_printf(dgettext(TEXT_DOMAIN, 1101 "picl_get_propval_by_name for led_state " 1102 "failed\n" 1103 "%s\n"), picl_strerror(err)); 1104 return (err); 1105 } 1106 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"), 1107 led_state); 1108 } 1109 log_printf("\n\n"); 1110 log_printf(dgettext(TEXT_DOMAIN, 1111 " LEFT DOOR " 1112 "RIGHT DOOR\n")); 1113 for (i = 6; i < 8; i++) { 1114 err = picl_get_propval_by_name(fsp_leds[i], "State", 1115 led_state, PICL_PROPNAMELEN_MAX); 1116 if (err != PICL_SUCCESS) { 1117 log_printf(dgettext(TEXT_DOMAIN, 1118 "picl_get_propval_by_name for led_state" 1119 " failed\n" 1120 "%s\n"), picl_strerror(err)); 1121 return (err); 1122 } 1123 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"), 1124 led_state); 1125 } 1126 log_printf("\n\n"); 1127 log_printf(dgettext(TEXT_DOMAIN, 1128 "=================================\n")); 1129 log_printf("\n"); 1130 1131 return (err); 1132 } 1133 1134 int 1135 dak_env_print_keyswitch(picl_nodehdl_t system_node) 1136 { 1137 int err = 0; 1138 picl_nodehdl_t *keyswitch; 1139 int32_t number; 1140 char ks_pos[PICL_PROPNAMELEN_MAX]; 1141 1142 err = fill_device_array_from_id(system_node, "PSVC_KEYSWITCH", &number, 1143 &keyswitch); 1144 if (err != PICL_SUCCESS) { 1145 log_printf(dgettext(TEXT_DOMAIN, 1146 "failed in fill_device_array_from_id for " 1147 " PSVC_KEYSWITCH\n" 1148 "%s\n"), picl_strerror(err)); 1149 return (err); 1150 } 1151 1152 err = picl_get_propval_by_name(keyswitch[0], "State", ks_pos, 1153 PICL_PROPNAMELEN_MAX); 1154 if (err != PICL_SUCCESS) { 1155 log_printf(dgettext(TEXT_DOMAIN, 1156 "picl_get_propval_by_name for keyswitch state " 1157 "failed\n" 1158 "%s\n"), picl_strerror(err)); 1159 return (err); 1160 } 1161 1162 log_printf(dgettext(TEXT_DOMAIN, 1163 "Front Status Panel:\n" 1164 "-------------------\n" 1165 "Keyswitch position: " 1166 "%s\n"), ks_pos); 1167 log_printf("\n"); 1168 1169 return (err); 1170 } 1171 1172 int 1173 dak_env_print_temps(picl_nodehdl_t system_node) 1174 { 1175 int i; 1176 int err; 1177 picl_nodehdl_t *system_ts_nodes; 1178 int32_t temp; 1179 int32_t number; 1180 char label[PICL_PROPNAMELEN_MAX]; 1181 char state[PICL_PROPNAMELEN_MAX]; 1182 char *p; 1183 1184 err = fill_device_array_from_id(system_node, "PSVC_TS", &number, 1185 &system_ts_nodes); 1186 if (err != PICL_SUCCESS) { 1187 return (err); 1188 } 1189 1190 log_printf(dgettext(TEXT_DOMAIN, 1191 "System Temperatures (Celsius):\n" 1192 "-------------------------------\n" 1193 "Device\t\tTemperature\tStatus\n" 1194 "---------------------------------------\n")); 1195 1196 for (i = 0; i < number; i++) { 1197 err = picl_get_propval_by_name(system_ts_nodes[i], 1198 "State", state, sizeof (state)); 1199 if (err != PICL_SUCCESS) { 1200 if (err == PICL_INVALIDHANDLE) { 1201 strcpy(state, "n/a"); 1202 } else { 1203 log_printf("%s\n", picl_strerror(err)); 1204 return (err); 1205 } 1206 } 1207 err = picl_get_propval_by_name(system_ts_nodes[i], 1208 PICL_PROP_NAME, label, PICL_PROPNAMELEN_MAX); 1209 if (err != PICL_SUCCESS) { 1210 if (err == PICL_INVALIDHANDLE) 1211 /* This FRU isn't present. Skip it. */ 1212 continue; 1213 log_printf("%s\n", picl_strerror(err)); 1214 return (err); 1215 } 1216 1217 /* 1218 * The names in the tree are like "CPU0_DIE_TEMPERATURE_SENSOR". 1219 * All we want to print is up to the first underscore. 1220 */ 1221 p = strchr(label, '_'); 1222 if (p != NULL) 1223 *p = '\0'; 1224 1225 err = picl_get_propval_by_name(system_ts_nodes[i], 1226 "Temperature", &temp, sizeof (temp)); 1227 if (err != PICL_SUCCESS) { 1228 log_printf("%s\n", picl_strerror(err)); 1229 return (err); 1230 } 1231 log_printf("%s\t\t%3d\t\t%s\n", label, temp, state); 1232 } 1233 1234 log_printf(dgettext(TEXT_DOMAIN, 1235 "\n=================================\n\n")); 1236 1237 return (PICL_SUCCESS); 1238 } 1239 1240 static void 1241 dak_display_hw_revisions(Prom_node *root, Board_node *bdlist) 1242 { 1243 Prom_node *pnode; 1244 char *value; 1245 1246 log_printf(dgettext(TEXT_DOMAIN, "\n" 1247 "========================= HW Revisions " 1248 "=======================================\n\n")); 1249 1250 log_printf(dgettext(TEXT_DOMAIN, 1251 "System PROM revisions:\n" 1252 "----------------------\n")); 1253 1254 pnode = dev_find_node(root, "openprom"); 1255 if (pnode != NULL) { 1256 value = (char *)get_prop_val(find_prop(pnode, "version")); 1257 log_printf(value); 1258 } 1259 1260 log_printf(dgettext(TEXT_DOMAIN, "\n\n" 1261 "IO ASIC revisions:\n" 1262 "------------------\n" 1263 " Port\n" 1264 "Model ID Status Version\n" 1265 "-------- ---- ------ -------\n")); 1266 1267 display_schizo_revisions(bdlist); 1268 } 1269 1270 static void 1271 display_schizo_revisions(Board_node *bdlist) 1272 { 1273 Prom_node *pnode; 1274 int *int_val; 1275 int portid; 1276 int prev_portid = -1; 1277 char *status_a = NULL; 1278 char *status_b = NULL; 1279 int revision; 1280 #ifdef DEBUG 1281 uint32_t a_notes, b_notes; 1282 #endif 1283 int pci_bus; 1284 Board_node *bnode; 1285 bnode = bdlist; 1286 1287 while (bnode != NULL) { 1288 /* 1289 * search this board node for all Schizos 1290 */ 1291 for (pnode = dev_find_node_by_compat(bnode->nodes, 1292 SCHIZO_COMPAT_PROP); pnode != NULL; 1293 pnode = dev_next_node_by_compat(pnode, 1294 SCHIZO_COMPAT_PROP)) { 1295 1296 /* 1297 * get the reg property to determine 1298 * whether we are looking at side A or B 1299 */ 1300 int_val = (int *)get_prop_val 1301 (find_prop(pnode, "reg")); 1302 if (int_val != NULL) { 1303 int_val ++; /* second integer in array */ 1304 pci_bus = ((*int_val) & 0x7f0000); 1305 } 1306 1307 /* get portid */ 1308 int_val = (int *)get_prop_val 1309 (find_prop(pnode, "portid")); 1310 if (int_val == NULL) 1311 continue; 1312 1313 portid = *int_val; 1314 1315 /* 1316 * If this is a new portid and it is PCI bus B, 1317 * we skip onto the PCI bus A. 1318 */ 1319 if ((portid != prev_portid) && (pci_bus == 0x700000)) { 1320 prev_portid = portid; 1321 /* status */ 1322 status_b = (char *)get_prop_val 1323 (find_prop(pnode, "status")); 1324 #ifdef DEBUG 1325 b_notes = pci_bus; 1326 #endif 1327 continue; /* skip to the next schizo */ 1328 } 1329 1330 /* 1331 * This must be side A of the same Schizo. 1332 * Gather all its props and display them. 1333 */ 1334 #ifdef DEBUG 1335 a_notes = pci_bus; 1336 #endif 1337 1338 prev_portid = portid; 1339 1340 int_val = (int *)get_prop_val 1341 (find_prop(pnode, "version#")); 1342 if (int_val != NULL) 1343 revision = *int_val; 1344 else 1345 revision = -1; 1346 1347 status_a = (char *)get_prop_val(find_prop 1348 (pnode, "status")); 1349 1350 log_printf(dgettext(TEXT_DOMAIN, "Schizo ")); 1351 1352 log_printf(dgettext(TEXT_DOMAIN, "%-3d "), portid, 0); 1353 1354 1355 log_printf((status_a == NULL && status_b == NULL) ? 1356 dgettext(TEXT_DOMAIN, " ok ") : 1357 dgettext(TEXT_DOMAIN, " fail ")); 1358 1359 log_printf(dgettext(TEXT_DOMAIN, " %4d "), 1360 revision); 1361 #ifdef DEBUG 1362 log_printf(" 0x%x 0x%x", a_notes, b_notes); 1363 #endif 1364 log_printf("\n"); 1365 } 1366 bnode = bnode->next; 1367 } 1368 } 1369