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