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 * Littleneck Platform specific functions. 26 * 27 * called when : 28 * machine_type == MTYPE_LITTLENECK 29 * 30 */ 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <kstat.h> 38 #include <string.h> 39 #include <assert.h> 40 #include <libintl.h> 41 #include <note.h> 42 #include <syslog.h> 43 44 #include <sys/openpromio.h> 45 #include <sys/sysmacros.h> 46 47 #include <pdevinfo.h> 48 #include <display.h> 49 #include <pdevinfo_sun4u.h> 50 #include <display_sun4u.h> 51 #include <libprtdiag.h> 52 53 #include <picl.h> 54 #include "workfile.c" 55 56 #define LNECK_MAX_PS 2 57 #define LNECK_MAX_DISKS 2 58 #define LNECK_MAX_FANS 1 59 60 #ifndef SCHIZO_COMPAT_PROP 61 #define SCHIZO_COMPAT_PROP "pci108e,8001" 62 #endif 63 64 /* Count of failed PSU's found */ 65 int ps_failure = 0; 66 67 /* 68 * Ignore first entry into disp_envc_status() 69 * from libprtdiag/common/display_sun4u.c 70 */ 71 int print_flag = 0; 72 73 /* 74 * these functions will overlay the symbol table of libprtdiag 75 * at runtime (workgroup server systems only) 76 */ 77 int error_check(Sys_tree *tree, struct system_kstat_data *kstats); 78 void display_cpu_devices(Sys_tree *tree); 79 void display_pci(Board_node *board); 80 void display_io_cards(struct io_card *list); 81 void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 82 struct system_kstat_data *kstats); 83 void display_ffb(Board_node *board, int table); 84 void display_memoryconf(Sys_tree *tree, struct grp_info *grps); 85 86 /* local functions */ 87 static int disp_envc_status(void); 88 static int lneck_env_print_temps(picl_nodehdl_t); 89 static int lneck_env_print_keyswitch(picl_nodehdl_t); 90 static int lneck_env_print_FSP_LEDS(picl_nodehdl_t); 91 static int lneck_env_print_disk(picl_nodehdl_t); 92 static int lneck_env_print_fans(picl_nodehdl_t); 93 static int lneck_env_print_ps(picl_nodehdl_t); 94 95 static void lneck_display_hw_revisions(Prom_node *root, 96 Board_node *bnode); 97 static void display_schizo_revisions(Board_node *bdlist); 98 99 /* 100 * Defining the error_check function in order to return the 101 * appropriate error code. 102 */ 103 /*ARGSUSED0*/ 104 int 105 error_check(Sys_tree *tree, struct system_kstat_data *kstats) 106 { 107 int exit_code = 0; /* init to all OK */ 108 /* silently check for any types of machine errors */ 109 print_flag = 0; 110 if (disp_fail_parts(tree) || disp_envc_status()) 111 /* set exit_code to show failures */ 112 exit_code = 1; 113 114 print_flag = 1; 115 116 return (exit_code); 117 } 118 119 void 120 display_cpu_devices(Sys_tree *tree) 121 { 122 Board_node *bnode; 123 124 /* 125 * Display the table header for CPUs . Then display the CPU 126 * frequency, cache size, and processor revision of all cpus. 127 */ 128 log_printf(dgettext(TEXT_DOMAIN, 129 "\n" 130 "========================= CPUs " 131 "===============================================" 132 "\n" 133 "\n" 134 " Run E$ CPU CPU \n" 135 "Brd CPU MHz MB Impl. Mask \n" 136 "--- --- ---- ---- ------- ---- \n")); 137 138 /* Now display all of the cpus on each board */ 139 bnode = tree->bd_list; 140 while (bnode != NULL) { 141 display_cpus(bnode); 142 bnode = bnode->next; 143 } 144 145 log_printf("\n"); 146 } 147 148 149 /* 150 * Display the CPUs present on this board. 151 */ 152 void 153 display_cpus(Board_node *board) 154 { 155 Prom_node *cpu; 156 char cpu_name[] = "cpu"; 157 158 /* 159 * display the CPUs' operating frequency, cache size, impl. field 160 * and mask revision. 161 */ 162 163 for (cpu = dev_find_type(board->nodes, cpu_name); cpu != NULL; 164 cpu = dev_next_type(cpu, cpu_name)) { 165 uint_t freq; /* CPU clock frequency */ 166 int ecache_size; /* External cache size */ 167 int *mid; 168 int *impl; 169 int *mask; 170 171 mid = (int *)get_prop_val(find_prop(cpu, "portid")); 172 freq = LNECK_CLK_FREQ_TO_MHZ(get_cpu_freq(cpu)); 173 ecache_size = get_ecache_size(cpu); 174 impl = (int *)get_prop_val(find_prop(cpu, "implementation#")); 175 mask = (int *)get_prop_val(find_prop(cpu, "mask#")); 176 177 /* Do not display a failed CPU node */ 178 if ((freq != 0) && (node_failed(cpu) == 0)) { 179 /* Board number */ 180 switch (*mid) { 181 case 1: 182 log_printf(dgettext(TEXT_DOMAIN, 183 " B ")); 184 break; 185 case 0: 186 log_printf(dgettext(TEXT_DOMAIN, 187 " A ")); 188 break; 189 default: 190 log_printf(dgettext(TEXT_DOMAIN, "X ")); 191 } 192 193 /* CPU MID */ 194 log_printf("%2d ", *mid); 195 196 /* Module number */ 197 198 /* Running frequency */ 199 log_printf("%4u ", freq); 200 201 /* Ecache size */ 202 if (ecache_size == 0) 203 log_printf("N/A "); 204 else 205 log_printf("%4.1f ", 206 (float)ecache_size / (float)(1<<20)); 207 208 /* Implementation */ 209 if (impl == NULL) { 210 log_printf(dgettext(TEXT_DOMAIN, "%6s "), 211 " N/A"); 212 } else { 213 if (IS_CHEETAH(*impl)) 214 log_printf("%-7s ", "US-III", 0); 215 else if (IS_CHEETAH_PLUS(*impl)) 216 log_printf("%-7s ", "US-III+", 0); 217 else 218 log_printf("%-7x ", *impl, 0); 219 } 220 221 /* CPU Mask */ 222 if (mask == NULL) { 223 log_printf(dgettext(TEXT_DOMAIN, " N/A ")); 224 } else { 225 log_printf(dgettext(TEXT_DOMAIN, " %d.%d "), 226 (*mask >> 4) & 0xf, *mask & 0xf); 227 } 228 229 log_printf("\n"); 230 } 231 } 232 } 233 234 /*ARGSUSED0*/ 235 void 236 display_memoryconf(Sys_tree *tree, struct grp_info *grps) 237 { 238 Board_node *bnode = tree->bd_list; 239 240 log_printf(dgettext(TEXT_DOMAIN, 241 "========================= Memory Configuration" 242 " ===============================\n" 243 "\n Logical Logical Logical " 244 "\n MC Bank Bank Bank DIMM " 245 "Interleave Interleaved" 246 "\n Brd ID num size Status Size " 247 "Factor with" 248 "\n---- --- ---- ------ ----------- ------ " 249 "---------- -----------")); 250 251 while (bnode != NULL) { 252 if (get_us3_mem_regs(bnode)) { 253 log_printf(dgettext(TEXT_DOMAIN, 254 "\nFailed to get memory information.\n")); 255 return; 256 } 257 bnode = bnode->next; 258 } 259 260 /* Display what we have found */ 261 display_us3_banks(); 262 } 263 264 /*ARGSUSED2*/ 265 void 266 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 267 struct system_kstat_data *kstats) 268 { 269 /* 270 * Now display the last powerfail time and the fatal hardware 271 * reset information. We do this under a couple of conditions. 272 * First if the user asks for it. The second is iof the user 273 * told us to do logging, and we found a system failure. 274 */ 275 276 if (flag) { 277 /* 278 * display time of latest powerfail. Not all systems 279 * have this capability. For those that do not, this 280 * is just a no-op. 281 */ 282 disp_powerfail(root); 283 284 (void) disp_envc_status(); 285 286 /* Hardware revision function calls */ 287 lneck_display_hw_revisions(root, tree->bd_list); 288 log_printf("\n"); 289 } 290 return; 291 292 } 293 294 /* 295 * display_pci 296 * Display all the PCI IO cards on this board. 297 */ 298 void 299 display_pci(Board_node *board) 300 { 301 struct io_card *card_list = NULL; 302 struct io_card card; 303 void *value; 304 Prom_node *pci; 305 Prom_node *card_node; 306 307 char *slot_name_arr[LNECK_MAX_SLOTS_PER_IO_BD] = {NULL}; 308 int i; 309 310 if (board == NULL) 311 return; 312 313 memset(&card, 0, sizeof (struct io_card)); 314 /* Initialize all the common information */ 315 card.display = TRUE; 316 card.board = board->board_num; 317 318 /* 319 * Search for each pci instance, then find/display all nodes under 320 * each instance node found. 321 */ 322 for (pci = dev_find_node_by_compat(board->nodes, SCHIZO_COMPAT_PROP); 323 pci != NULL; 324 pci = dev_next_node_by_compat(pci, SCHIZO_COMPAT_PROP)) { 325 (void) snprintf(card.bus_type, MAXSTRLEN, 326 dgettext(TEXT_DOMAIN, "PCI")); 327 /* 328 * Get slot-name properties from parent node and 329 * store them in an array. 330 */ 331 value = (char *)get_prop_val( 332 find_prop(pci, "slot-names")); 333 334 if (value != NULL) { 335 /* array starts after first int */ 336 slot_name_arr[0] = (char *)value + sizeof (int); 337 for (i = 1; i < LNECK_MAX_SLOTS_PER_IO_BD; i++) { 338 slot_name_arr[i] = (char *)slot_name_arr[i - 1] 339 + strlen(slot_name_arr[i - 1]) +1; 340 } 341 } 342 /* 343 * Search for Children of this node ie. Cards. 344 * Note: any of these cards can be a pci-bridge 345 * that itself has children. If we find a 346 * pci-bridge we need to handle it specially. 347 */ 348 card_node = pci->child; 349 /* Generate the list of pci cards on pci instance: pci */ 350 fill_pci_card_list(pci, card_node, &card, &card_list, 351 slot_name_arr); 352 } /* end-for */ 353 354 display_io_cards(card_list); 355 free_io_cards(card_list); 356 log_printf("\n"); 357 } 358 359 /* 360 * Print out all the io cards in the list. Also print the column 361 * headers if told to do so. 362 */ 363 void 364 display_io_cards(struct io_card *list) 365 { 366 static int banner = 0; /* Have we printed the column headings? */ 367 struct io_card *p; 368 369 if (list == NULL) { 370 return; 371 } 372 373 if (banner == FALSE) { 374 log_printf(dgettext(TEXT_DOMAIN, 375 " Bus Max\n" 376 " IO Port Bus Freq Bus Dev,\n" 377 "Brd Type ID Side Slot MHz Freq Func State " 378 "Name ")); 379 #ifdef DEBUG 380 log_printf(dgettext(TEXT_DOMAIN, 381 "Model Notes\n")); 382 #else 383 log_printf(dgettext(TEXT_DOMAIN, "Model\n")); 384 #endif 385 /* ---------Node Brd IO Port Bus Slot Bus Max Dev Stat */ 386 log_printf(dgettext(TEXT_DOMAIN, 387 "---- ---- ---- ---- ---- ---- ---- ---- ----- " 388 "-------------------------------- " 389 #ifdef DEBUG 390 "---------------------- " 391 #endif 392 "----------------------\n")); 393 banner = TRUE; 394 } 395 396 for (p = list; p != NULL; p = p -> next) { 397 log_printf(dgettext(TEXT_DOMAIN, "I/O ")); 398 log_printf(dgettext(TEXT_DOMAIN, "%-4s "), p->bus_type); 399 log_printf(dgettext(TEXT_DOMAIN, "%-3d "), 400 p->schizo_portid); 401 log_printf(dgettext(TEXT_DOMAIN, "%c "), p->pci_bus); 402 log_printf(dgettext(TEXT_DOMAIN, "%-1s "), p->slot_str); 403 log_printf(dgettext(TEXT_DOMAIN, "%-3d "), p->freq); 404 switch (p->pci_bus) { 405 case 'A': 406 log_printf(dgettext(TEXT_DOMAIN, " 66 ")); 407 break; 408 case 'B': 409 log_printf(dgettext(TEXT_DOMAIN, " 33 ")); 410 break; 411 default: 412 log_printf(dgettext(TEXT_DOMAIN, " - ")); 413 break; 414 } 415 416 log_printf(dgettext(TEXT_DOMAIN, "%-1d,%-1d "), 417 p->dev_no, p->func_no); 418 log_printf(dgettext(TEXT_DOMAIN, "%-5s "), p->status); 419 log_printf(dgettext(TEXT_DOMAIN, "%-32.32s"), p->name); 420 if (strlen(p->name) > 32) 421 log_printf(dgettext(TEXT_DOMAIN, "+ ")); 422 else 423 log_printf(dgettext(TEXT_DOMAIN, " ")); 424 log_printf(dgettext(TEXT_DOMAIN, "%-22.22s"), p->model); 425 if (strlen(p->model) > 22) 426 log_printf(dgettext(TEXT_DOMAIN, "+")); 427 #ifdef DEBUG 428 log_printf("%s ", p->notes); 429 #endif 430 log_printf("\n"); 431 } 432 } 433 434 /* 435 * display_ffb 436 * 437 * There are no FFB's on a Littleneck, however in the generic library, 438 * the display_ffb() function is implemented so we have to define an 439 * empty function here. 440 */ 441 /*ARGSUSED0*/ 442 void 443 display_ffb(Board_node *board, int table) 444 {} 445 446 447 /* 448 * local functions 449 */ 450 451 /* 452 * disp_fail_parts 453 * 454 * Display the failed parts in the system. This function looks for 455 * the status property in all PROM nodes. On systems where 456 * the PROM does not support passing diagnostic information 457 * through the device tree, this routine will be silent. 458 */ 459 int 460 disp_fail_parts(Sys_tree *tree) 461 { 462 int exit_code = 0; 463 int system_failed = 0; 464 Board_node *bnode = tree->bd_list; 465 Prom_node *pnode; 466 467 /* go through all of the boards looking for failed units. */ 468 while (bnode != NULL) { 469 /* find failed chips */ 470 pnode = find_failed_node(bnode->nodes); 471 if ((pnode != NULL) && !system_failed) { 472 system_failed = 1; 473 exit_code = 1; 474 if (print_flag == 0) { 475 return (exit_code); 476 } 477 log_printf("\n"); 478 log_printf(dgettext(TEXT_DOMAIN, "Failed Field " 479 "Replaceable Units (FRU) in System:\n")); 480 log_printf("==========================" 481 "====================\n"); 482 } 483 while (pnode != NULL) { 484 void *value; 485 char *name; /* node name string */ 486 char *type; /* node type string */ 487 char *board_type = NULL; 488 489 value = get_prop_val(find_prop(pnode, "status")); 490 name = get_node_name(pnode); 491 492 /* sanity check of data retrieved from PROM */ 493 if ((value == NULL) || (name == NULL)) { 494 pnode = next_failed_node(pnode); 495 continue; 496 } 497 498 /* Find the board type of this board */ 499 if (bnode->board_type == CPU_BOARD) { 500 board_type = "CPU"; 501 } else { 502 board_type = "IO"; 503 } 504 505 log_printf(dgettext(TEXT_DOMAIN, "%s unavailable " 506 "on %s Board #%d\n"), name, board_type, 507 bnode->board_num); 508 509 log_printf(dgettext(TEXT_DOMAIN, 510 "\tPROM fault string: %s\n"), value); 511 512 log_printf(dgettext(TEXT_DOMAIN, 513 "\tFailed Field Replaceable Unit is ")); 514 515 /* 516 * Determine whether FRU is CPU module, system 517 * board, or SBus card. 518 */ 519 if ((name != NULL) && (strstr(name, "sbus"))) { 520 521 log_printf(dgettext(TEXT_DOMAIN, 522 "SBus Card %d\n"), 523 get_sbus_slot(pnode)); 524 525 } else if (((name = get_node_name(pnode->parent)) != 526 NULL) && (strstr(name, "pci"))) { 527 528 log_printf(dgettext(TEXT_DOMAIN, 529 "PCI Card %d"), 530 get_pci_device(pnode)); 531 532 } else if (((type = get_node_type(pnode)) != NULL) && 533 (strstr(type, "cpu"))) { 534 535 log_printf(dgettext(TEXT_DOMAIN, "UltraSPARC " 536 "module Board %d Module %d\n"), 0, 537 get_id(pnode)); 538 539 } else { 540 log_printf(dgettext(TEXT_DOMAIN, 541 "%s board %d\n"), board_type, 542 bnode->board_num); 543 } 544 pnode = next_failed_node(pnode); 545 } 546 bnode = bnode->next; 547 } 548 549 if (!system_failed) { 550 log_printf(dgettext(TEXT_DOMAIN, 551 "No failures found in System\n")); 552 log_printf("===========================\n\n"); 553 return (0); 554 } else { 555 return (1); 556 } 557 } 558 559 560 /* 561 * disp_envc_status 562 * 563 * This routine displays the environmental status passed up from 564 * device drivers via the envlibobj.so library. 565 * This is a Littleneck specific environmental information display routine. 566 */ 567 static int 568 disp_envc_status(void) 569 { 570 int err; 571 char *system = "SYSTEM"; 572 picl_nodehdl_t system_node, root; 573 574 log_printf("\n"); 575 log_printf(dgettext(TEXT_DOMAIN, "=========================" 576 " Environmental Status =========================\n\n")); 577 578 err = picl_initialize(); 579 if (err != PICL_SUCCESS) { 580 log_printf(dgettext(TEXT_DOMAIN, 581 "Cannot print environmental information\n" 582 "picl_initialize failed\n" 583 "%s\n"), picl_strerror(err)); 584 } 585 586 if (err == PICL_SUCCESS) { 587 err = picl_get_root(&root); 588 err = find_child_device(root, system, &system_node); 589 if (err != PICL_SUCCESS) { 590 log_printf(dgettext(TEXT_DOMAIN, 591 "Cannot print environmental information\n" 592 "find_child_device for the SYSTEM node " 593 "failed\n" 594 "%s\n"), picl_strerror(err)); 595 } 596 597 if ((err = lneck_env_print_temps(system_node)) != 598 PICL_SUCCESS) { 599 log_printf(dgettext(TEXT_DOMAIN, 600 "Temperature Checking failed: %s\n"), 601 picl_strerror(err)); 602 } 603 if ((err = lneck_env_print_keyswitch(system_node)) != 604 PICL_SUCCESS) { 605 log_printf(dgettext(TEXT_DOMAIN, 606 "Keyswitch information checking failed: %s\n"), 607 picl_strerror(err)); 608 } 609 if ((err = lneck_env_print_FSP_LEDS(system_node)) != 610 PICL_SUCCESS) { 611 log_printf(dgettext(TEXT_DOMAIN, 612 "FSP LED information checking failed: %s\n"), 613 picl_strerror(err)); 614 } 615 if ((err = lneck_env_print_disk(system_node)) != 616 PICL_SUCCESS) { 617 log_printf(dgettext(TEXT_DOMAIN, 618 "Disk information checking failed: %s\n"), 619 picl_strerror(err)); 620 } 621 if ((err = lneck_env_print_fans(system_node)) != 622 PICL_SUCCESS) { 623 log_printf(dgettext(TEXT_DOMAIN, 624 "Fan information checking failed: %s\n"), 625 picl_strerror(err)); 626 } 627 if ((err = lneck_env_print_ps(system_node)) != 628 PICL_SUCCESS) { 629 log_printf(dgettext(TEXT_DOMAIN, 630 "Power Supply information checking failed: " 631 "%s\n"), picl_strerror(err)); 632 } else if (ps_failure != 0) 633 err = PICL_FAILURE; 634 } 635 return (err); 636 } 637 638 int 639 lneck_env_print_ps(picl_nodehdl_t system_node) 640 { 641 int i, err = 0; 642 int32_t number; 643 picl_nodehdl_t *ps; 644 picl_nodehdl_t ps_fail[2], ps_type[2]; 645 char name[PICL_PROPNAMELEN_MAX]; 646 boolean_t type; 647 char fault_state[PICL_PROPNAMELEN_MAX]; 648 649 log_printf(dgettext(TEXT_DOMAIN, 650 "Power Supplies:\n" 651 "---------------\n" 652 "Supply Status PS Type\n" 653 "------ ------ ---------------\n")); 654 err = fill_device_array_from_id(system_node, "PSVC_PS", &number, 655 &ps); 656 if (err != PICL_SUCCESS) { 657 return (err); 658 } 659 660 for (i = 0; i < LNECK_MAX_PS; i++) { 661 err = picl_get_propval_by_name(ps[i], PICL_PROP_NAME, name, 662 PICL_PROPNAMELEN_MAX); 663 if (err == PICL_SUCCESS) { 664 log_printf(dgettext(TEXT_DOMAIN, "%6-s"), name); 665 } else continue; 666 667 err = picl_get_propval_by_name(ps[i], "FaultInformation", 668 fault_state, PICL_PROPNAMELEN_MAX); 669 if (err == PICL_SUCCESS) { 670 if ((strlen(fault_state) == 0) || 671 (strcmp(fault_state, "NO_FAULT") == 0)) { 672 strcpy(fault_state, "OK"); 673 } else 674 /* 675 * Bump up count if fault_state !OK 676 */ 677 ps_failure++; 678 679 log_printf(dgettext(TEXT_DOMAIN, " [%-6s] "), 680 fault_state); 681 } else { 682 return (err); 683 } 684 685 err = fill_device_from_id(ps[i], "PSVC_DEV_FAULT_SENSOR", 686 &ps_fail[i]); 687 if (err != PICL_SUCCESS) { 688 return (err); 689 } 690 691 err = fill_device_from_id(ps[i], "PSVC_DEV_TYPE_SENSOR", 692 &ps_type[i]); 693 if (err != PICL_SUCCESS) { 694 return (err); 695 } 696 err = picl_get_propval_by_name(ps_type[i], "Gpio-value", &type, 697 sizeof (boolean_t)); 698 if (err == PICL_SUCCESS) { 699 log_printf(dgettext(TEXT_DOMAIN, " [%13s]"), 700 type == 0 ? "Quahog/Razor" : "Sun-Fire-280R"); 701 if (type == 0) { 702 log_printf(dgettext(TEXT_DOMAIN, 703 "WARNING: PS is of the wrong type\n")); 704 } else log_printf("\n"); 705 } else { 706 return (err); 707 } 708 709 } 710 711 log_printf(dgettext(TEXT_DOMAIN, 712 "\n" 713 "=================================" 714 "\n" 715 "\n")); 716 717 /* 718 * Do not display an error message just because PS1 is 719 * not present. 720 */ 721 if (err == PICL_INVALIDHANDLE) { 722 err = PICL_SUCCESS; 723 } 724 725 return (err); 726 } 727 728 int 729 lneck_env_print_fans(picl_nodehdl_t system_node) { 730 int i, err = 0; 731 int32_t number; 732 picl_nodehdl_t *fans; 733 picl_nodehdl_t fan_fault[1]; 734 char fault_state[PICL_PROPNAMELEN_MAX]; 735 char name[PICL_PROPNAMELEN_MAX]; 736 737 err = fill_device_array_from_id(system_node, "PSVC_FAN", &number, 738 &fans); 739 if (err != PICL_SUCCESS) { 740 return (err); 741 } 742 743 log_printf(dgettext(TEXT_DOMAIN, 744 "\n" 745 "=================================\n" 746 "\n" 747 "Fan Bank :\n" 748 "----------\n" 749 "\n" 750 "Bank Status\n" 751 "---- -------\n")); 752 753 for (i = 0; i < LNECK_MAX_FANS; i++) { 754 err = picl_get_propval_by_name(fans[i], PICL_PROP_NAME, name, 755 PICL_PROPNAMELEN_MAX); 756 if (err == PICL_SUCCESS) { 757 log_printf(dgettext(TEXT_DOMAIN, "%16-s"), name); 758 } else continue; 759 760 err = fill_device_from_id(fans[i], "PSVC_DEV_FAULT_SENSOR", 761 &fan_fault[i]); 762 if (err != PICL_SUCCESS) { 763 return (err); 764 } 765 766 err = picl_get_propval_by_name(fans[i], "FaultInformation", 767 &fault_state, PICL_PROPNAMELEN_MAX); 768 769 if (err == PICL_SUCCESS) { 770 log_printf(dgettext(TEXT_DOMAIN, " [%3s]\n"), 771 fault_state); 772 } else { 773 return (err); 774 } 775 } 776 log_printf(dgettext(TEXT_DOMAIN, 777 "\n" 778 "=================================" 779 "\n" 780 "\n")); 781 782 return (err); 783 } 784 785 int 786 lneck_env_print_disk(picl_nodehdl_t system_node) { 787 int i, err = 0; 788 int32_t number; 789 picl_nodehdl_t *disks; 790 char fault_state[PICL_PROPNAMELEN_MAX]; 791 char name[PICL_PROPNAMELEN_MAX]; 792 793 err = fill_device_array_from_id(system_node, "PSVC_DISK", &number, 794 &disks); 795 if (err != PICL_SUCCESS) { 796 return (err); 797 } 798 799 log_printf(dgettext(TEXT_DOMAIN, 800 "Disk Status:\n" 801 " Presence Fault Value\n" 802 " -------- -----------\n")); 803 804 for (i = 0; i < LNECK_MAX_DISKS; i++) { 805 err = picl_get_propval_by_name(disks[i], PICL_PROP_NAME, name, 806 PICL_PROPNAMELEN_MAX); 807 switch (err) { 808 case PICL_SUCCESS: 809 log_printf(dgettext(TEXT_DOMAIN, 810 "DISK %2d: [PRESENT]"), i); 811 break; 812 case PICL_INVALIDHANDLE: 813 log_printf(dgettext(TEXT_DOMAIN, 814 "DISK %2d: [EMPTY ]\n"), i); 815 continue; 816 default: 817 return (err); 818 } 819 err = picl_get_propval_by_name(disks[i], "FaultInformation", 820 &fault_state, PICL_PROPNAMELEN_MAX); 821 if (err == PICL_SUCCESS) { 822 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"), 823 fault_state); 824 } else { 825 if (err != PICL_INVALIDHANDLE) 826 return (err); 827 } 828 log_printf("\n"); 829 } 830 831 if (err == PICL_INVALIDHANDLE) { 832 err = PICL_SUCCESS; 833 } 834 835 return (err); 836 } 837 838 int 839 lneck_env_print_FSP_LEDS(picl_nodehdl_t system_node) { 840 int err; 841 int32_t number; 842 picl_nodehdl_t *fsp_led; 843 char fault_state[PICL_PROPNAMELEN_MAX]; 844 845 err = fill_device_array_from_id(system_node, "PSVC_FSP_LED", &number, 846 &fsp_led); 847 if (err != PICL_SUCCESS) { 848 return (err); 849 } 850 851 log_printf(dgettext(TEXT_DOMAIN, 852 "System LED Status: POWER GEN FAULT\n" 853 " [ ON]")); 854 err = picl_get_propval_by_name(fsp_led[0], "State", &fault_state, 855 PICL_PROPNAMELEN_MAX); 856 if (err == PICL_SUCCESS) { 857 log_printf(" [%3s]", fault_state); 858 } else { 859 return (err); 860 } 861 862 log_printf(dgettext(TEXT_DOMAIN, 863 "\n" 864 "\n" 865 "=================================" 866 "\n" 867 "\n")); 868 869 return (err); 870 } 871 872 int 873 lneck_env_print_keyswitch(picl_nodehdl_t system_node) { 874 int err = 0; 875 picl_nodehdl_t *keyswitch; 876 int32_t number; 877 char ks_pos[PICL_PROPNAMELEN_MAX]; 878 879 err = fill_device_array_from_id(system_node, "PSVC_KEYSWITCH", &number, 880 &keyswitch); 881 if (err != PICL_SUCCESS) { 882 return (err); 883 } 884 err = picl_get_propval_by_name(keyswitch[0], "State", ks_pos, 885 PICL_PROPNAMELEN_MAX); 886 if (err != PICL_SUCCESS) { 887 return (err); 888 } 889 890 log_printf(dgettext(TEXT_DOMAIN, 891 "Front Status Panel:\n" 892 "-------------------\n" 893 "Keyswitch position: %s\n"), ks_pos); 894 log_printf("\n"); 895 896 return (err); 897 } 898 899 int 900 lneck_env_print_temps(picl_nodehdl_t system_node) { 901 int i, err = 0; 902 picl_nodehdl_t *system_ts_nodes; 903 int32_t temp, number; 904 905 err = fill_device_array_from_id(system_node, "PSVC_TS", &number, 906 &system_ts_nodes); 907 if (err != PICL_SUCCESS) { 908 return (err); 909 } 910 911 912 log_printf(dgettext(TEXT_DOMAIN, 913 "System Temperatures (Celsius):\n" 914 "------------------------------\n" 915 "cpu0 1 \n" 916 "---------\n")); 917 918 for (i = 0; i < 2; i++) { 919 err = picl_get_propval_by_name(system_ts_nodes[i], 920 "Temperature", &temp, sizeof (temp)); 921 if (err == PICL_SUCCESS) { 922 log_printf(dgettext(TEXT_DOMAIN, " %02d"), temp); 923 } else { 924 if (err == PICL_INVALIDHANDLE) { 925 err = PICL_SUCCESS; 926 log_printf(dgettext(TEXT_DOMAIN, " xx")); 927 } else { 928 return (err); 929 } 930 } 931 } 932 933 log_printf("\n"); 934 log_printf("\n"); 935 log_printf(dgettext(TEXT_DOMAIN, 936 "=================================\n")); 937 log_printf("\n"); 938 939 return (err); 940 } 941 942 static void 943 lneck_display_hw_revisions(Prom_node *root, Board_node *bdlist) 944 { 945 Prom_node *pnode; 946 char *value; 947 948 log_printf(dgettext(TEXT_DOMAIN, "\n" 949 "========================= HW Revisions " 950 "=======================================\n\n")); 951 952 log_printf(dgettext(TEXT_DOMAIN, 953 "System PROM revisions:\n" 954 "----------------------\n")); 955 956 pnode = dev_find_node(root, "openprom"); 957 if (pnode != NULL) { 958 value = (char *)get_prop_val(find_prop(pnode, "version")); 959 log_printf(value); 960 } 961 962 log_printf(dgettext(TEXT_DOMAIN, "\n\n" 963 "IO ASIC revisions:\n" 964 "------------------\n" 965 " Port\n" 966 "Model ID Status Version\n" 967 "-------- ---- ------ -------\n")); 968 969 display_schizo_revisions(bdlist); 970 } 971 972 static void 973 display_schizo_revisions(Board_node *bdlist) 974 { 975 Prom_node *pnode; 976 int *int_val; 977 int portid; 978 int prev_portid = -1; 979 char *status_a = NULL; 980 char *status_b = NULL; 981 int revision; 982 #ifdef DEBUG 983 uint32_t a_notes, b_notes; 984 #endif 985 int pci_bus; 986 Board_node *bnode; 987 bnode = bdlist; 988 989 while (bnode != NULL) { 990 /* 991 * search this board node for all Schizos 992 */ 993 994 for (pnode = dev_find_node_by_compat(bnode->nodes, 995 SCHIZO_COMPAT_PROP); pnode != NULL; 996 pnode = dev_next_node_by_compat(pnode, 997 SCHIZO_COMPAT_PROP)) { 998 999 /* 1000 * get the reg property to determine 1001 * whether we are looking at side A or B 1002 */ 1003 1004 int_val = (int *)get_prop_val 1005 (find_prop(pnode, "reg")); 1006 if (int_val != NULL) { 1007 int_val ++; /* second integer in array */ 1008 pci_bus = ((*int_val) & 0x7f0000); 1009 } 1010 1011 /* get portid */ 1012 int_val = (int *)get_prop_val 1013 (find_prop(pnode, "portid")); 1014 if (int_val == NULL) 1015 continue; 1016 1017 portid = *int_val; 1018 1019 /* 1020 * If this is a new portid and it is PCI bus B, 1021 * we skip onto the PCI bus A. 1022 */ 1023 if ((portid != prev_portid) && (pci_bus == 0x700000)) { 1024 prev_portid = portid; 1025 /* status */ 1026 status_b = (char *)get_prop_val 1027 (find_prop(pnode, "status")); 1028 #ifdef DEBUG 1029 b_notes = pci_bus; 1030 #endif 1031 continue; /* skip to the next schizo */ 1032 } 1033 1034 /* 1035 * This must be side A of the same Schizo. 1036 * Gather all its props and display them. 1037 */ 1038 #ifdef DEBUG 1039 a_notes = pci_bus; 1040 #endif 1041 1042 prev_portid = portid; 1043 1044 int_val = (int *)get_prop_val 1045 (find_prop(pnode, "version#")); 1046 if (int_val != NULL) 1047 revision = *int_val; 1048 else 1049 revision = -1; 1050 1051 status_a = (char *)get_prop_val(find_prop 1052 (pnode, "status")); 1053 1054 log_printf(dgettext(TEXT_DOMAIN, "Schizo ")); 1055 1056 log_printf(dgettext(TEXT_DOMAIN, "%-3d "), portid, 0); 1057 1058 1059 log_printf((status_a == NULL && status_b == NULL) ? 1060 dgettext(TEXT_DOMAIN, " ok ") : 1061 dgettext(TEXT_DOMAIN, " fail ")); 1062 1063 log_printf(dgettext(TEXT_DOMAIN, " %4d "), 1064 revision); 1065 #ifdef DEBUG 1066 log_printf(" 0x%x 0x%x", a_notes, b_notes); 1067 #endif 1068 log_printf("\n"); 1069 } 1070 bnode = bnode->next; 1071 } 1072 } 1073