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