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 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * Littleneck Platform specific functions. 27 * 28 * called when : 29 * machine_type == MTYPE_LITTLENECK 30 * 31 */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" 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 #include <syslog.h> 44 45 #include <sys/openpromio.h> 46 #include <sys/sysmacros.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 #define LNECK_MAX_PS 2 58 #define LNECK_MAX_DISKS 2 59 #define LNECK_MAX_FANS 1 60 61 #ifndef SCHIZO_COMPAT_PROP 62 #define SCHIZO_COMPAT_PROP "pci108e,8001" 63 #endif 64 65 /* Count of failed PSU's found */ 66 int ps_failure = 0; 67 68 /* 69 * Ignore first entry into disp_envc_status() 70 * from libprtdiag/common/display_sun4u.c 71 */ 72 int print_flag = 0; 73 74 /* 75 * these functions will overlay the symbol table of libprtdiag 76 * at runtime (workgroup server systems only) 77 */ 78 int error_check(Sys_tree *tree, struct system_kstat_data *kstats); 79 void display_cpu_devices(Sys_tree *tree); 80 void display_pci(Board_node *board); 81 void display_io_cards(struct io_card *list); 82 void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 83 struct system_kstat_data *kstats); 84 void display_ffb(Board_node *board, int table); 85 void display_memoryconf(Sys_tree *tree, struct grp_info *grps); 86 87 /* local functions */ 88 static int disp_envc_status(void); 89 static int lneck_env_print_temps(picl_nodehdl_t); 90 static int lneck_env_print_keyswitch(picl_nodehdl_t); 91 static int lneck_env_print_FSP_LEDS(picl_nodehdl_t); 92 static int lneck_env_print_disk(picl_nodehdl_t); 93 static int lneck_env_print_fans(picl_nodehdl_t); 94 static int lneck_env_print_ps(picl_nodehdl_t); 95 96 static void lneck_display_hw_revisions(Prom_node *root, 97 Board_node *bnode); 98 static void display_schizo_revisions(Board_node *bdlist); 99 100 /* 101 * Defining the error_check function in order to return the 102 * appropriate error code. 103 */ 104 /*ARGSUSED0*/ 105 int 106 error_check(Sys_tree *tree, struct system_kstat_data *kstats) 107 { 108 int exit_code = 0; /* init to all OK */ 109 /* silently check for any types of machine errors */ 110 print_flag = 0; 111 if (disp_fail_parts(tree) || disp_envc_status()) 112 /* set exit_code to show failures */ 113 exit_code = 1; 114 115 print_flag = 1; 116 117 return (exit_code); 118 } 119 120 void 121 display_cpu_devices(Sys_tree *tree) 122 { 123 Board_node *bnode; 124 125 /* 126 * Display the table header for CPUs . Then display the CPU 127 * frequency, cache size, and processor revision of all cpus. 128 */ 129 log_printf(dgettext(TEXT_DOMAIN, 130 "\n" 131 "========================= CPUs " 132 "===============================================" 133 "\n" 134 "\n" 135 " Run E$ CPU CPU \n" 136 "Brd CPU MHz MB Impl. Mask \n" 137 "--- --- ---- ---- ------- ---- \n")); 138 139 /* Now display all of the cpus on each board */ 140 bnode = tree->bd_list; 141 while (bnode != NULL) { 142 display_cpus(bnode); 143 bnode = bnode->next; 144 } 145 146 log_printf("\n"); 147 } 148 149 150 /* 151 * Display the CPUs present on this board. 152 */ 153 void 154 display_cpus(Board_node *board) 155 { 156 Prom_node *cpu; 157 char cpu_name[] = "cpu"; 158 159 /* 160 * display the CPUs' operating frequency, cache size, impl. field 161 * and mask revision. 162 */ 163 164 for (cpu = dev_find_type(board->nodes, cpu_name); cpu != NULL; 165 cpu = dev_next_type(cpu, cpu_name)) { 166 int freq; /* CPU clock frequency */ 167 int ecache_size; /* External cache size */ 168 int *mid; 169 int *impl; 170 int *mask; 171 172 mid = (int *)get_prop_val(find_prop(cpu, "portid")); 173 freq = LNECK_CLK_FREQ_TO_MHZ(get_cpu_freq(cpu)); 174 ecache_size = get_ecache_size(cpu); 175 impl = (int *)get_prop_val(find_prop(cpu, "implementation#")); 176 mask = (int *)get_prop_val(find_prop(cpu, "mask#")); 177 178 /* Do not display a failed CPU node */ 179 if ((freq != 0) && (node_failed(cpu) == 0)) { 180 /* Board number */ 181 switch (*mid) { 182 case 1: 183 log_printf(dgettext(TEXT_DOMAIN, 184 " B ")); 185 break; 186 case 0: 187 log_printf(dgettext(TEXT_DOMAIN, 188 " A ")); 189 break; 190 default: 191 log_printf(dgettext(TEXT_DOMAIN, "X ")); 192 } 193 194 /* CPU MID */ 195 log_printf("%2d ", *mid); 196 197 /* Module number */ 198 199 /* Running frequency */ 200 log_printf("%4d ", freq); 201 202 /* Ecache size */ 203 if (ecache_size == 0) 204 log_printf("N/A "); 205 else 206 log_printf("%4.1f ", 207 (float)ecache_size / (float)(1<<20)); 208 209 /* Implementation */ 210 if (impl == NULL) { 211 log_printf(dgettext(TEXT_DOMAIN, "%6s "), 212 " N/A"); 213 } else { 214 if (IS_CHEETAH(*impl)) 215 log_printf("%-7s ", "US-III", 0); 216 else if (IS_CHEETAH_PLUS(*impl)) 217 log_printf("%-7s ", "US-III+", 0); 218 else 219 log_printf("%-7x ", *impl, 0); 220 } 221 222 /* CPU Mask */ 223 if (mask == NULL) { 224 log_printf(dgettext(TEXT_DOMAIN, " N/A ")); 225 } else { 226 log_printf(dgettext(TEXT_DOMAIN, " %d.%d "), 227 (*mask >> 4) & 0xf, *mask & 0xf); 228 } 229 230 log_printf("\n"); 231 } 232 } 233 } 234 235 /*ARGSUSED0*/ 236 void 237 display_memoryconf(Sys_tree *tree, struct grp_info *grps) 238 { 239 Board_node *bnode = tree->bd_list; 240 241 log_printf(dgettext(TEXT_DOMAIN, 242 "========================= Memory Configuration" 243 " ===============================\n" 244 "\n Logical Logical Logical " 245 "\n MC Bank Bank Bank DIMM " 246 "Interleave Interleaved" 247 "\n Brd ID num size Status Size " 248 "Factor with" 249 "\n---- --- ---- ------ ----------- ------ " 250 "---------- -----------")); 251 252 while (bnode != NULL) { 253 if (get_us3_mem_regs(bnode)) { 254 log_printf(dgettext(TEXT_DOMAIN, 255 "\nFailed to get memory information.\n")); 256 return; 257 } 258 bnode = bnode->next; 259 } 260 261 /* Display what we have found */ 262 display_us3_banks(); 263 } 264 265 /*ARGSUSED2*/ 266 void 267 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 268 struct system_kstat_data *kstats) 269 { 270 /* 271 * Now display the last powerfail time and the fatal hardware 272 * reset information. We do this under a couple of conditions. 273 * First if the user asks for it. The second is iof the user 274 * told us to do logging, and we found a system failure. 275 */ 276 277 if (flag) { 278 /* 279 * display time of latest powerfail. Not all systems 280 * have this capability. For those that do not, this 281 * is just a no-op. 282 */ 283 disp_powerfail(root); 284 285 (void) disp_envc_status(); 286 287 /* Hardware revision function calls */ 288 lneck_display_hw_revisions(root, tree->bd_list); 289 log_printf("\n"); 290 } 291 return; 292 293 } 294 295 /* 296 * display_pci 297 * Display all the PCI IO cards on this board. 298 */ 299 void 300 display_pci(Board_node *board) 301 { 302 struct io_card *card_list = NULL; 303 struct io_card card; 304 void *value; 305 Prom_node *pci; 306 Prom_node *card_node; 307 308 char *slot_name_arr[LNECK_MAX_SLOTS_PER_IO_BD] = {NULL}; 309 int i; 310 311 if (board == NULL) 312 return; 313 314 memset(&card, 0, sizeof (struct io_card)); 315 /* Initialize all the common information */ 316 card.display = TRUE; 317 card.board = board->board_num; 318 319 /* 320 * Search for each pci instance, then find/display all nodes under 321 * each instance node found. 322 */ 323 for (pci = dev_find_node_by_compat(board->nodes, SCHIZO_COMPAT_PROP); 324 pci != NULL; 325 pci = dev_next_node_by_compat(pci, SCHIZO_COMPAT_PROP)) { 326 (void) snprintf(card.bus_type, MAXSTRLEN, 327 dgettext(TEXT_DOMAIN, "PCI")); 328 /* 329 * Get slot-name properties from parent node and 330 * store them in an array. 331 */ 332 value = (char *)get_prop_val( 333 find_prop(pci, "slot-names")); 334 335 if (value != NULL) { 336 /* array starts after first int */ 337 slot_name_arr[0] = (char *)value + sizeof (int); 338 for (i = 1; i < LNECK_MAX_SLOTS_PER_IO_BD; i++) { 339 slot_name_arr[i] = (char *)slot_name_arr[i - 1] 340 + strlen(slot_name_arr[i - 1]) +1; 341 } 342 } 343 /* 344 * Search for Children of this node ie. Cards. 345 * Note: any of these cards can be a pci-bridge 346 * that itself has children. If we find a 347 * pci-bridge we need to handle it specially. 348 */ 349 card_node = pci->child; 350 /* Generate the list of pci cards on pci instance: pci */ 351 fill_pci_card_list(pci, card_node, &card, &card_list, 352 slot_name_arr); 353 } /* end-for */ 354 355 display_io_cards(card_list); 356 free_io_cards(card_list); 357 log_printf("\n"); 358 } 359 360 /* 361 * Print out all the io cards in the list. Also print the column 362 * headers if told to do so. 363 */ 364 void 365 display_io_cards(struct io_card *list) 366 { 367 static int banner = 0; /* Have we printed the column headings? */ 368 struct io_card *p; 369 370 if (list == NULL) { 371 return; 372 } 373 374 if (banner == FALSE) { 375 log_printf(dgettext(TEXT_DOMAIN, 376 " Bus Max\n" 377 " IO Port Bus Freq Bus Dev,\n" 378 "Brd Type ID Side Slot MHz Freq Func State " 379 "Name " 380 #ifdef DEBUG 381 "Model Notes\n")); 382 #else 383 "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