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