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 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <alloca.h> 33 #include <errno.h> 34 #include <libintl.h> 35 #include <sys/utsname.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <sys/openpromio.h> 39 #include <sys/ddi.h> 40 #include <syslog.h> 41 #include <fcntl.h> 42 #include <dirent.h> 43 #include <unistd.h> 44 #include <locale.h> 45 #include <picl.h> 46 #include "pdevinfo.h" 47 #include "display.h" 48 #include "display_sun4u.h" 49 #include "picldefs.h" 50 #include "libprtdiag.h" 51 52 #if !defined(TEXT_DOMAIN) 53 #define TEXT_DOMAIN "SYS_TEST" 54 #endif 55 56 #define EM_INIT_FAIL dgettext(TEXT_DOMAIN,\ 57 "picl_initialize failed: %s\n") 58 #define EM_GET_ROOT_FAIL dgettext(TEXT_DOMAIN,\ 59 "Getting root node failed: %s\n") 60 #define EM_PRTDIAG_FAIL dgettext(TEXT_DOMAIN, "Prtdiag failed!\n") 61 62 #define SIGN_ON_MSG dgettext(TEXT_DOMAIN,\ 63 "System Configuration: Sun Microsystems ") 64 #define SYSCLK_FREQ_MSG dgettext(TEXT_DOMAIN,\ 65 "System clock frequency: %d MHZ\n") 66 #define MEM_SIZE_MSG dgettext(TEXT_DOMAIN, "Memory size: ") 67 #define FFB_DOUBLE_BUF dgettext(TEXT_DOMAIN, "FFB, Double Buffered") 68 #define FFB_SINGLE_BUF dgettext(TEXT_DOMAIN, "FFB, Single Buffered") 69 70 #define DEFAULT_BOARD_NUM 0 71 #define DEFAULT_PORTID 0 72 #define CLK_FREQ_66MHZ 66 73 #define USB -1 74 #define HUB -2 75 76 /* bus id */ 77 #define SBUS_TYPE 0 78 #define PCI_TYPE 1 79 #define UPA_TYPE 2 80 81 #define UPA_NAME "upa" 82 83 /* 84 * PICL classes 85 */ 86 #define PICL_CLASS_OPTIONS "options" 87 88 /* 89 * Property names 90 */ 91 92 #define OBP_PROP_REG "reg" 93 #define OBP_PROP_CLOCK_FREQ "clock-frequency" 94 #define OBP_PROP_BOARD_NUM "board#" 95 #define OBP_PROP_REVISION_ID "revision-id" 96 #define OBP_PROP_VERSION_NUM "version#" 97 #define OBP_PROP_BOARD_TYPE "board_type" 98 #define OBP_PROP_ECACHE_SIZE "ecache-size" 99 #define OBP_PROP_L2_CACHE_SIZE "l2-cache-size" 100 #define OBP_PROP_L3_CACHE_SIZE "l3-cache-size" 101 #define OBP_PROP_IMPLEMENTATION "implementation#" 102 #define OBP_PROP_MASK "mask#" 103 #define OBP_PROP_COMPATIBLE "compatible" 104 #define OBP_PROP_STATUS "status" 105 #define OBP_PROP_BANNER_NAME "banner-name" 106 #define OBP_PROP_MODEL "model" 107 #define OBP_PROP_66MHZ_CAPABLE "66mhz-capable" 108 #define OBP_PROP_FBC_REG_ID "fbc_reg_id" 109 #define OBP_PROP_VERSION "version" 110 111 #define PROP_POWERFAIL_TIME "powerfail-time" 112 #define PICL_PROP_LOW_WARNING_THRESHOLD "LowWarningThreshold" 113 114 #define DEFAULT_LINE_WIDTH 85 115 #define HEADING_SYMBOL "=" 116 117 #define MAX_IWAYS 32 118 119 typedef struct bank_list { 120 picl_nodehdl_t nodeh; 121 uint32_t iway_count; 122 uint32_t iway[MAX_IWAYS]; 123 struct bank_list *next; 124 } bank_list_t; 125 126 typedef struct { 127 uint64_t base; 128 uint64_t size; 129 int ifactor; 130 int bank_count; 131 } seg_info_t; 132 133 static struct io_card *io_card_list = NULL; /* The head of the IO card list */ 134 static bank_list_t *mem_banks = NULL; 135 static int mem_xfersize; 136 static int no_xfer_size = 0; 137 138 static char *io_device_table[] = { 139 "block", 140 "disk", 141 "cdrom", 142 "floppy", 143 "tape", 144 "network", 145 "display", 146 "serial", 147 "parallel", 148 "scsi", 149 "scsi-2", 150 "scsi-3", 151 "ide", 152 "fcal", 153 "keyboard", 154 "mouse", 155 "dma" 156 }; 157 158 #define NIODEVICE sizeof (io_device_table) / sizeof (io_device_table[0]) 159 160 static char *bus_table[] = { 161 "ebus", 162 "isa", 163 "pmu" 164 }; 165 166 #define NBUS sizeof (bus_table) / sizeof (bus_table[0]) 167 168 /* 169 * check if it is an IO deice 170 */ 171 static int 172 is_io_device(char *device_class) 173 { 174 int i; 175 176 for (i = 0; i < NIODEVICE; i++) { 177 if (strcmp(device_class, io_device_table[i]) == 0) 178 return (1); 179 } 180 181 return (0); 182 } 183 184 /* 185 * check if it is a bus 186 */ 187 static int 188 is_bus(char *device_class) 189 { 190 int i; 191 192 for (i = 0; i < NBUS; i++) { 193 if (strcmp(device_class, bus_table[i]) == 0) 194 return (1); 195 } 196 197 return (0); 198 } 199 200 /* 201 * search children to get the node by the nodename 202 */ 203 static int 204 picldiag_get_node_by_name(picl_nodehdl_t rooth, char *name, 205 picl_nodehdl_t *nodeh) 206 { 207 picl_nodehdl_t childh; 208 int err; 209 char *nodename; 210 211 nodename = alloca(strlen(name) + 1); 212 if (nodename == NULL) 213 return (PICL_FAILURE); 214 215 err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh, 216 sizeof (picl_nodehdl_t)); 217 218 while (err == PICL_SUCCESS) { 219 err = picl_get_propval_by_name(childh, PICL_PROP_NAME, 220 nodename, (strlen(name) + 1)); 221 if (err != PICL_SUCCESS) { 222 err = picl_get_propval_by_name(childh, PICL_PROP_PEER, 223 &childh, sizeof (picl_nodehdl_t)); 224 continue; 225 } 226 227 if (strcmp(nodename, name) == 0) { 228 *nodeh = childh; 229 return (PICL_SUCCESS); 230 } 231 232 err = picl_get_propval_by_name(childh, PICL_PROP_PEER, 233 &childh, sizeof (picl_nodehdl_t)); 234 } 235 236 return (err); 237 } 238 239 /* 240 * get the value by the property name of the string prop 241 * Caller must free the outbuf 242 */ 243 static int 244 picldiag_get_string_propval(picl_nodehdl_t modh, char *prop_name, char **outbuf) 245 { 246 int err; 247 picl_prophdl_t proph; 248 picl_propinfo_t pinfo; 249 char *prop_value; 250 251 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); 252 if (err != PICL_SUCCESS) 253 return (err); 254 255 /* 256 * If it is not a string prop, return NULL 257 */ 258 if (pinfo.type != PICL_PTYPE_CHARSTRING) 259 return (PICL_FAILURE); 260 261 prop_value = malloc(pinfo.size); 262 if (prop_value == NULL) 263 return (PICL_FAILURE); 264 265 err = picl_get_propval(proph, prop_value, pinfo.size); 266 if (err != PICL_SUCCESS) { 267 free(prop_value); 268 return (err); 269 } 270 271 *outbuf = prop_value; 272 return (PICL_SUCCESS); 273 } 274 275 276 /* 277 * return the value as a signed integer 278 */ 279 280 static int64_t 281 picldiag_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret) 282 { 283 int err; 284 picl_prophdl_t proph; 285 picl_propinfo_t pinfo; 286 int8_t int8v; 287 int16_t int16v; 288 int32_t int32v; 289 int64_t int64v; 290 291 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); 292 if (err != PICL_SUCCESS) { 293 *ret = err; 294 return (0); 295 } 296 297 /* 298 * If it is not an int or uint prop, return failure 299 */ 300 if ((pinfo.type != PICL_PTYPE_INT) && 301 (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) { 302 *ret = PICL_FAILURE; 303 return (0); 304 } 305 306 switch (pinfo.size) { 307 case sizeof (int8_t): 308 err = picl_get_propval(proph, &int8v, sizeof (int8v)); 309 *ret = err; 310 return (int8v); 311 case sizeof (int16_t): 312 err = picl_get_propval(proph, &int16v, sizeof (int16v)); 313 *ret = err; 314 return (int16v); 315 case sizeof (int32_t): 316 err = picl_get_propval(proph, &int32v, sizeof (int32v)); 317 *ret = err; 318 return (int32v); 319 case sizeof (int64_t): 320 err = picl_get_propval(proph, &int64v, sizeof (int64v)); 321 *ret = err; 322 return (int64v); 323 default: /* not supported size */ 324 *ret = PICL_FAILURE; 325 return (0); 326 } 327 } 328 329 /* 330 * return the value of the uint prop 331 */ 332 static uint64_t 333 picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret) 334 { 335 int err; 336 picl_prophdl_t proph; 337 picl_propinfo_t pinfo; 338 uint8_t uint8v; 339 uint16_t uint16v; 340 uint32_t uint32v; 341 uint64_t uint64v; 342 343 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); 344 if (err != PICL_SUCCESS) { 345 *ret = err; 346 return (0); 347 } 348 349 /* 350 * If it is not an int or uint prop, return failure 351 */ 352 if ((pinfo.type != PICL_PTYPE_INT) && 353 (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) { 354 *ret = PICL_FAILURE; 355 return (0); 356 } 357 358 /* uint prop */ 359 360 switch (pinfo.size) { 361 case sizeof (uint8_t): 362 err = picl_get_propval(proph, &uint8v, sizeof (uint8v)); 363 *ret = err; 364 return (uint8v); 365 case sizeof (uint16_t): 366 err = picl_get_propval(proph, &uint16v, sizeof (uint16v)); 367 *ret = err; 368 return (uint16v); 369 case sizeof (uint32_t): 370 err = picl_get_propval(proph, &uint32v, sizeof (uint32v)); 371 *ret = err; 372 return (uint32v); 373 case sizeof (uint64_t): 374 err = picl_get_propval(proph, &uint64v, sizeof (uint64v)); 375 *ret = err; 376 return (uint64v); 377 default: /* not supported size */ 378 *ret = PICL_FAILURE; 379 return (0); 380 } 381 } 382 383 /* 384 * return the value of the float prop 385 */ 386 static float 387 picldiag_get_float_propval(picl_nodehdl_t modh, char *prop_name, int *ret) 388 { 389 int err; 390 picl_prophdl_t proph; 391 picl_propinfo_t pinfo; 392 float floatv; 393 394 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); 395 if (err != PICL_SUCCESS) { 396 *ret = err; 397 return ((float)0); 398 } 399 400 /* 401 * If it is not a float prop, return failure 402 */ 403 if (pinfo.type != PICL_PTYPE_FLOAT) { 404 *ret = PICL_FAILURE; 405 return ((float)0); 406 } 407 408 *ret = picl_get_propval(proph, &floatv, sizeof (floatv)); 409 return (floatv); 410 } 411 412 /* 413 * get the clock frequency 414 */ 415 static int 416 picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq) 417 { 418 #define ROUND_TO_MHZ(x) (((x) + 500000)/ 1000000) 419 int err; 420 uint64_t clk_freq; 421 422 clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err); 423 if (err != PICL_SUCCESS) 424 return (err); 425 426 *freq = ROUND_TO_MHZ(clk_freq); 427 428 return (PICL_SUCCESS); 429 } 430 431 /* 432 * get the clock frequency from parent 433 */ 434 static int 435 picldiag_get_clock_from_parent(picl_nodehdl_t nodeh, uint32_t *clk) 436 { 437 picl_nodehdl_t parenth; 438 int err; 439 440 441 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, 442 &parenth, sizeof (parenth)); 443 444 while (err == PICL_SUCCESS) { 445 err = picldiag_get_clock_freq(parenth, clk); 446 if (err != PICL_PROPNOTFOUND) 447 return (err); 448 449 err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT, 450 &parenth, sizeof (parenth)); 451 } 452 453 return (err); 454 } 455 456 /* 457 * get _fru_parent prop 458 * If not found, then travese superiors (parent nodes) until 459 * a _fru_parent property is found. 460 * If not found, no fru parent 461 */ 462 static int 463 picldiag_get_fru_parent(picl_nodehdl_t nodeh, picl_nodehdl_t *fruparenth) 464 { 465 picl_nodehdl_t fruh; 466 int err; 467 468 /* find fru parent */ 469 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT, 470 &fruh, sizeof (fruh)); 471 472 if (err != PICL_SUCCESS) 473 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_LOC_PARENT, 474 &fruh, sizeof (fruh)); 475 476 while (err == PICL_PROPNOTFOUND) { 477 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, 478 &nodeh, sizeof (nodeh)); 479 if (err != PICL_SUCCESS) 480 return (err); 481 482 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT, 483 &fruh, sizeof (fruh)); 484 if (err != PICL_SUCCESS) 485 err = picl_get_propval_by_name(nodeh, 486 PICL_REFPROP_LOC_PARENT, &fruh, sizeof (fruh)); 487 } 488 489 if (err == PICL_SUCCESS) 490 *fruparenth = fruh; 491 492 return (err); 493 } 494 495 /* 496 * get label 497 * 498 * To get the label, use the following algorithm: 499 * Lookup "Label" property in the fru node itself. If no 500 * Label found, then traverse superiors (parent nodes) until 501 * a Label property is found. 502 * if not found, then no label 503 */ 504 static int 505 picldiag_get_label(picl_nodehdl_t nodeh, char **label) 506 { 507 int err; 508 509 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, label); 510 511 while (err == PICL_PROPNOTFOUND) { 512 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, 513 &nodeh, sizeof (nodeh)); 514 if (err != PICL_SUCCESS) 515 return (err); 516 517 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, 518 label); 519 } 520 521 return (err); 522 } 523 524 /* 525 * get combined label 526 * 527 * like picldiag_get_label, except concatenates the labels of parent locations 528 * eg SB0/P3 for processor P3 on system board SB0 529 * 530 * if caller specifies non-zero label length, label will be cut to specified 531 * length. 532 * negative length is left justified, non-negative length is right justified 533 */ 534 static int 535 picldiag_get_combined_label(picl_nodehdl_t nodeh, char **label, int lablen) 536 { 537 int err; 538 char *ptr; 539 char *ptr1 = NULL; 540 char *ptr2; 541 int len; 542 543 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr1); 544 if (err != PICL_PROPNOTFOUND && err != PICL_SUCCESS) 545 return (err); 546 547 for (;;) { 548 err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, 549 &nodeh, sizeof (nodeh)); 550 if (err == PICL_PROPNOTFOUND) 551 break; 552 if (err != PICL_SUCCESS) 553 return (err); 554 555 err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr); 556 if (err == PICL_SUCCESS) { 557 if (ptr1 == NULL) { 558 ptr1 = ptr; 559 } else { 560 ptr2 = malloc(strlen(ptr1) + strlen(ptr) + 2); 561 if (ptr2 == NULL) 562 return (PICL_FAILURE); 563 (void) strcpy(ptr2, ptr); 564 (void) strcat(ptr2, "/"); 565 (void) strcat(ptr2, ptr1); 566 (void) free(ptr); 567 (void) free(ptr1); 568 ptr1 = ptr2; 569 } 570 } else if (err != PICL_PROPNOTFOUND) { 571 return (err); 572 } 573 } 574 575 if (ptr1 == NULL) 576 return (PICL_PROPNOTFOUND); 577 578 len = strlen(ptr1); 579 /* if no string truncation is desired or required */ 580 if ((lablen == 0) || (len <= abs(lablen))) { 581 *label = ptr1; 582 return (PICL_SUCCESS); 583 } 584 585 /* string truncation is required; alloc space for (lablen + \0) */ 586 ptr = malloc(abs(lablen) + 1); 587 if (ptr == 0) 588 return (PICL_FAILURE); 589 if (lablen > 0) { 590 /* right justification; label = "+<string>\0" */ 591 strcpy(ptr, "+"); 592 strncat(ptr, ptr1 + len - lablen + 1, lablen + 1); 593 } else { 594 /* left justification; label = "<string>+\0" */ 595 strncpy(ptr, ptr1, abs(lablen) - 1); 596 strcat(ptr, "+"); 597 } 598 599 *label = ptr; 600 return (PICL_SUCCESS); 601 } 602 603 /* 604 * return the first compatible value 605 */ 606 static int 607 picldiag_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf) 608 { 609 int err; 610 picl_prophdl_t proph; 611 picl_propinfo_t pinfo; 612 picl_prophdl_t tblh; 613 picl_prophdl_t rowproph; 614 char *pval; 615 616 err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE, 617 &pinfo, &proph); 618 if (err != PICL_SUCCESS) 619 return (err); 620 621 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 622 pval = malloc(pinfo.size); 623 if (pval == NULL) 624 return (PICL_FAILURE); 625 err = picl_get_propval(proph, pval, pinfo.size); 626 if (err != PICL_SUCCESS) { 627 free(pval); 628 return (err); 629 } 630 *outbuf = pval; 631 return (PICL_SUCCESS); 632 } 633 634 if (pinfo.type != PICL_PTYPE_TABLE) 635 return (PICL_FAILURE); 636 637 /* get first string from table */ 638 err = picl_get_propval(proph, &tblh, pinfo.size); 639 if (err != PICL_SUCCESS) 640 return (err); 641 642 err = picl_get_next_by_row(tblh, &rowproph); 643 if (err != PICL_SUCCESS) 644 return (err); 645 646 err = picl_get_propinfo(rowproph, &pinfo); 647 if (err != PICL_SUCCESS) 648 return (err); 649 650 pval = malloc(pinfo.size); 651 if (pval == NULL) 652 return (PICL_FAILURE); 653 654 err = picl_get_propval(rowproph, pval, pinfo.size); 655 if (err != PICL_SUCCESS) { 656 free(pval); 657 return (err); 658 } 659 660 *outbuf = pval; 661 return (PICL_SUCCESS); 662 } 663 664 /* 665 * print the header in the center 666 */ 667 static void 668 logprintf_header(char *header, size_t line_width) 669 { 670 size_t start_pos; 671 size_t i; 672 673 log_printf("\n"); 674 start_pos = (line_width - strlen(header) - 2) / 2; 675 676 for (i = 0; i < start_pos; i++) 677 log_printf("%s", HEADING_SYMBOL); 678 679 log_printf(" %s ", header); 680 681 for (i = 0; i < start_pos; i++) 682 log_printf("%s", HEADING_SYMBOL); 683 684 log_printf("\n"); 685 } 686 687 /* 688 * print the size 689 */ 690 static void 691 logprintf_size(uint64_t size) 692 { 693 #define SIZE_FIELD 11 694 695 uint64_t kbyte = 1024; 696 uint64_t mbyte = 1024 * 1024; 697 uint64_t gbyte = 1024 * 1024 * 1024; 698 uint64_t residue; 699 char buf[SIZE_FIELD]; 700 701 if (size >= gbyte) { 702 residue = size % gbyte; 703 if (residue == 0) 704 snprintf(buf, sizeof (buf), "%dGB", 705 (int)(size / gbyte)); 706 else 707 snprintf(buf, sizeof (buf), "%.2fGB", 708 (float)size / gbyte); 709 } else if (size >= mbyte) { 710 residue = size % mbyte; 711 if (residue == 0) 712 snprintf(buf, sizeof (buf), "%dMB", 713 (int)(size / mbyte)); 714 else 715 snprintf(buf, sizeof (buf), "%.2fMB", 716 (float)size / mbyte); 717 } else { 718 residue = size % kbyte; 719 if (residue == 0) 720 snprintf(buf, sizeof (buf), "%dKB", 721 (int)(size / kbyte)); 722 else 723 snprintf(buf, sizeof (buf), "%.2fKB", 724 (float)size / kbyte); 725 } 726 727 log_printf("%-10s ", buf); 728 } 729 730 /* 731 * display platform banner 732 */ 733 static int 734 display_platform_banner(picl_nodehdl_t plafh) 735 { 736 char *platform; 737 char *banner_name; 738 int err; 739 740 /* 741 * get PICL_PROP_MACHINE and PICL_PROP_BANNER_NAME 742 */ 743 log_printf(SIGN_ON_MSG); 744 err = picldiag_get_string_propval(plafh, PICL_PROP_MACHINE, 745 &platform); 746 if (err != PICL_SUCCESS) 747 return (err); 748 log_printf(" %s", platform); 749 free(platform); 750 751 err = picldiag_get_string_propval(plafh, OBP_PROP_BANNER_NAME, 752 &banner_name); 753 if (err != PICL_SUCCESS) 754 return (err); 755 log_printf(" %s", banner_name); 756 free(banner_name); 757 758 log_printf("\n"); 759 return (PICL_SUCCESS); 760 } 761 762 /* 763 * display the clock frequency 764 */ 765 static int 766 display_system_clock(picl_nodehdl_t plafh) 767 { 768 uint32_t system_clk; 769 int err; 770 771 err = picldiag_get_clock_freq(plafh, &system_clk); 772 if (err != PICL_SUCCESS) 773 return (err); 774 775 log_printf(SYSCLK_FREQ_MSG, system_clk); 776 777 return (PICL_SUCCESS); 778 } 779 780 /* 781 * callback function to display the memory size 782 */ 783 /*ARGSUSED*/ 784 static int 785 memory_callback(picl_nodehdl_t memh, void *args) 786 { 787 uint64_t mem_size; 788 int err; 789 790 log_printf(MEM_SIZE_MSG); 791 mem_size = picldiag_get_uint_propval(memh, PICL_PROP_SIZE, &err); 792 if (err == PICL_SUCCESS) 793 logprintf_size(mem_size); 794 log_printf("\n"); 795 no_xfer_size = 0; 796 mem_xfersize = picldiag_get_uint_propval(memh, PICL_PROP_TRANSFER_SIZE, 797 &err); 798 if (err == PICL_PROPNOTFOUND) 799 no_xfer_size = 1; 800 return (PICL_WALK_TERMINATE); 801 } 802 803 /* 804 * callback function to print cpu information 805 */ 806 /*ARGSUSED*/ 807 static int 808 cpu_callback(picl_nodehdl_t nodeh, void *args) 809 { 810 int err; 811 int id0, id1; 812 uint64_t uintval; 813 uint64_t decoded_mask; 814 uint32_t freq; 815 char *impl_name; 816 char *status; 817 picl_prophdl_t parenth; 818 picl_prophdl_t peerh; 819 char *label; 820 int is_cmp = 0; 821 int is_cheetah = 0; 822 823 /* 824 * first check the implementation. If it's a CMP 825 * we need to combine info from both cores. 826 */ 827 828 impl_name = NULL; 829 uintval = picldiag_get_uint_propval(nodeh, 830 OBP_PROP_IMPLEMENTATION, &err); 831 if (err == PICL_SUCCESS) { 832 if (CPU_IMPL_IS_CMP(uintval)) { 833 is_cmp = 1; 834 err = picldiag_get_first_compatible_value(nodeh, 835 &impl_name); 836 if (err != PICL_SUCCESS) 837 impl_name = NULL; 838 } else if (IS_CHEETAH(uintval) || IS_CHEETAH_PLUS(uintval)) { 839 is_cheetah = 1; 840 err = picldiag_get_string_propval(nodeh, PICL_PROP_NAME, 841 &impl_name); 842 if (err != PICL_SUCCESS) 843 impl_name = NULL; 844 } 845 } else { 846 err = picldiag_get_string_propval(nodeh, 847 PICL_PROP_NAME, &impl_name); 848 if (err != PICL_SUCCESS) 849 impl_name = NULL; 850 } 851 852 /* 853 * In the CMP case, combine info from both cores. If we 854 * are being called with the first core handle, we display 855 * info on the sibling core handle too. If we are being 856 * called with the second core hanlde as an argument, simply 857 * return. 858 */ 859 860 if (is_cmp) { 861 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, 862 &peerh, sizeof (picl_nodehdl_t)); 863 if (err != PICL_SUCCESS) 864 return (PICL_WALK_CONTINUE); 865 id1 = picldiag_get_uint_propval(peerh, PICL_PROP_ID, &err); 866 if (err == PICL_PROPNOTFOUND) 867 return (PICL_WALK_CONTINUE); 868 else if (err != PICL_SUCCESS) 869 return (err); 870 } 871 872 /* 873 * If no ID is found, return 874 */ 875 id0 = picldiag_get_uint_propval(nodeh, PICL_PROP_ID, &err); 876 if (err == PICL_PROPNOTFOUND) 877 return (PICL_WALK_CONTINUE); 878 else if (err != PICL_SUCCESS) 879 return (err); 880 if (is_cmp) { 881 log_printf("%3d,%3d ", id0, id1); 882 } else { 883 log_printf("%7d ", id0); 884 } 885 886 /* 887 * If no freq is found, return 888 */ 889 err = picldiag_get_clock_freq(nodeh, &freq); 890 if (err == PICL_PROPNOTFOUND) 891 return (PICL_WALK_CONTINUE); 892 else if (err != PICL_SUCCESS) 893 return (err); 894 log_printf("%4d MHz ", freq); 895 896 /* Ecache size */ 897 898 if (is_cmp) { 899 uintval = picldiag_get_uint_propval(nodeh, 900 OBP_PROP_L3_CACHE_SIZE, &err); 901 if (err == PICL_SUCCESS) { 902 /* 903 * Panther L3 is logically shared, so the total E$ 904 * size is equal to the core size. 905 */ 906 logprintf_size(uintval); 907 } else { 908 uintval = picldiag_get_uint_propval(nodeh, 909 OBP_PROP_L2_CACHE_SIZE, &err); 910 if (err == PICL_SUCCESS) { 911 /* 912 * Jaguar has a split E$, so the total size 913 * is the sum of both cores. 914 */ 915 logprintf_size(uintval * 2); 916 } else 917 log_printf(" - "); 918 } 919 } else { 920 uintval = picldiag_get_uint_propval(nodeh, 921 OBP_PROP_ECACHE_SIZE, &err); 922 if (err == PICL_SUCCESS) 923 logprintf_size(uintval); 924 else 925 log_printf(" - "); 926 } 927 928 /* Implementation */ 929 if (impl_name != NULL) 930 log_printf(" %-20s ", impl_name); 931 else 932 log_printf(" <unknown> "); 933 934 /* CPU Mask */ 935 uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_MASK, &err); 936 if (err == PICL_PROPNOTFOUND) 937 log_printf(" - "); 938 else if (err == PICL_SUCCESS) { 939 if (is_cheetah) { 940 decoded_mask = REMAP_CHEETAH_MASK(uintval); 941 } else { 942 decoded_mask = uintval; 943 } 944 log_printf("%2lld.%-2lld ", (decoded_mask >> 4) & 0xf, 945 decoded_mask & 0xf); 946 } else 947 return (err); 948 949 /* 950 * Status - if the node has a status property then display that 951 * otherwise display the State property 952 */ 953 err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, &status); 954 if (err == PICL_SUCCESS) { 955 log_printf("%-12s", status); 956 free(status); 957 } else if (err != PICL_PROPNOTFOUND && err != 958 PICL_PROPVALUNAVAILABLE && err != PICL_ENDOFLIST) { 959 return (err); 960 } else { 961 err = picldiag_get_string_propval(nodeh, 962 PICL_PROP_STATE, &status); 963 if (err == PICL_SUCCESS) { 964 log_printf("%-12s", status); 965 free(status); 966 } else if (err != PICL_PROPNOTFOUND && err != 967 PICL_PROPVALUNAVAILABLE && err != 968 PICL_ENDOFLIST) { 969 return (err); 970 } else { 971 log_printf("unknown "); 972 } 973 } 974 975 /* 976 * Location: use label of fru parent 977 */ 978 err = picldiag_get_fru_parent(nodeh, &parenth); 979 if (err == PICL_PROPNOTFOUND) { 980 log_printf(" - "); 981 } else if (err == PICL_SUCCESS) { 982 err = picldiag_get_combined_label(parenth, &label, 12); 983 if (err == PICL_PROPNOTFOUND) 984 log_printf(" - "); 985 else if (err == PICL_SUCCESS) { 986 log_printf("%s", label); 987 free(label); 988 } else 989 return (err); 990 } else 991 return (err); 992 993 log_printf("\n"); 994 return (PICL_WALK_CONTINUE); 995 } 996 997 /* 998 * display cpu information 999 */ 1000 static int 1001 display_cpu_info(picl_nodehdl_t plafh) 1002 { 1003 int err; 1004 1005 /* 1006 * Display the table header for CPUs . Then display the CPU 1007 * frequency, cache size, and processor revision on all the boards. 1008 */ 1009 logprintf_header(dgettext(TEXT_DOMAIN, "CPUs"), DEFAULT_LINE_WIDTH); 1010 log_printf(" E$ CPU " 1011 "CPU\n"); 1012 log_printf("CPU Freq Size Implementation " 1013 "Mask Status Location\n"); 1014 log_printf("------- -------- ---------- ------------------- " 1015 "----- ------ --------\n"); 1016 1017 err = picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU, 1018 cpu_callback); 1019 return (err); 1020 } 1021 1022 /* 1023 * Inserts an io_card structure into the list. 1024 */ 1025 static void 1026 add_io_card(uint32_t board, uint32_t bus_id, uint32_t slot, char *label, 1027 uint32_t freq, char *name, char *model, char *status, char *devfs_path) 1028 { 1029 struct io_card card; 1030 1031 card.display = 1; 1032 card.board = board; 1033 switch (bus_id) { 1034 case SBUS_TYPE: 1035 strlcpy(card.bus_type, SBUS_NAME, MAXSTRLEN); 1036 break; 1037 case PCI_TYPE: 1038 strlcpy(card.bus_type, PCI_NAME, MAXSTRLEN); 1039 break; 1040 case UPA_TYPE: 1041 strlcpy(card.bus_type, UPA_NAME, MAXSTRLEN); 1042 break; 1043 default: /* won't reach here */ 1044 strlcpy(card.bus_type, "", MAXSTRLEN); 1045 break; 1046 } 1047 if (label == NULL) 1048 card.slot = slot; 1049 else { 1050 card.slot = PCI_SLOT_IS_STRING; 1051 (void) strlcpy(card.slot_str, label, MAXSTRLEN); 1052 } 1053 card.freq = freq; 1054 card.status[0] = '\0'; 1055 card.name[0] = '\0'; 1056 card.model[0] = '\0'; 1057 card.notes[0] = '\0'; 1058 if (status != NULL) 1059 strlcpy(card.status, status, MAXSTRLEN); 1060 if (name != NULL) 1061 strlcpy(card.name, name, MAXSTRLEN); 1062 if (model != NULL) 1063 strlcpy(card.model, model, MAXSTRLEN); 1064 if (status != NULL) 1065 strlcpy(card.status, status, MAXSTRLEN); 1066 if (devfs_path != NULL) 1067 strlcpy(card.notes, devfs_path, MAXSTRLEN); 1068 1069 io_card_list = insert_io_card(io_card_list, &card); 1070 } 1071 1072 static void 1073 append_to_bank_list(bank_list_t *newptr) 1074 { 1075 bank_list_t *ptr; 1076 1077 if (mem_banks == NULL) { 1078 mem_banks = newptr; 1079 return; 1080 } 1081 ptr = mem_banks; 1082 while (ptr->next != NULL) 1083 ptr = ptr->next; 1084 1085 ptr->next = newptr; 1086 } 1087 1088 static void 1089 free_bank_list(void) 1090 { 1091 bank_list_t *ptr; 1092 bank_list_t *tmp; 1093 1094 for (ptr = mem_banks; ptr != NULL; ptr = tmp) { 1095 tmp = ptr->next; 1096 free(ptr); 1097 } 1098 mem_banks = NULL; 1099 } 1100 1101 1102 /* 1103 * print label for memory module 1104 */ 1105 static int 1106 logprintf_memory_module_label(picl_nodehdl_t moduleh) 1107 { 1108 picl_nodehdl_t fruparenth; 1109 int err; 1110 char *label; 1111 1112 err = picldiag_get_fru_parent(moduleh, &fruparenth); 1113 if (err == PICL_PROPNOTFOUND) { 1114 log_printf("-"); 1115 return (PICL_SUCCESS); 1116 } else if (err != PICL_SUCCESS) 1117 return (err); 1118 1119 err = picldiag_get_combined_label(fruparenth, &label, 30); 1120 if (err == PICL_PROPNOTFOUND) 1121 log_printf("-"); 1122 else if (err == PICL_SUCCESS) { 1123 log_printf("%-15s", label); 1124 free(label); 1125 } else 1126 return (err); 1127 1128 return (PICL_SUCCESS); 1129 } 1130 1131 /* 1132 * print the bank id and add the bank handle in the bank list 1133 * return the head of the bank list 1134 */ 1135 static int 1136 membank_callback(picl_nodehdl_t bankh, void *args) 1137 { 1138 int err; 1139 int64_t id; 1140 uint64_t match; 1141 uint64_t mask; 1142 int i; 1143 bank_list_t *newptr; 1144 seg_info_t *segp = args; 1145 1146 /* 1147 * print the bank id in the segment table contains column 1148 */ 1149 id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err); 1150 if (segp->bank_count > 0) 1151 log_printf(","); 1152 if (err == PICL_PROPNOTFOUND) 1153 log_printf("-"); 1154 else if (err == PICL_SUCCESS) 1155 log_printf("%-lld", id); 1156 else 1157 return (err); 1158 segp->bank_count++; 1159 1160 /* 1161 * Save the bank information for later (print_bank_table) 1162 */ 1163 newptr = malloc(sizeof (*newptr)); 1164 if (newptr == NULL) 1165 return (PICL_FAILURE); 1166 1167 newptr->nodeh = bankh; 1168 newptr->iway_count = 0; 1169 newptr->next = NULL; 1170 append_to_bank_list(newptr); 1171 1172 /* 1173 * Compute the way numbers for the bank 1174 */ 1175 if (no_xfer_size) 1176 return (PICL_WALK_CONTINUE); 1177 1178 match = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMATCH, &err); 1179 if (err == PICL_PROPNOTFOUND) 1180 return (PICL_WALK_CONTINUE); 1181 else if (err != PICL_SUCCESS) 1182 return (err); 1183 1184 mask = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMASK, &err); 1185 if (err == PICL_PROPNOTFOUND) 1186 return (PICL_WALK_CONTINUE); 1187 else if (err != PICL_SUCCESS) 1188 return (err); 1189 1190 i = 0; 1191 while ((i < segp->ifactor) && (newptr->iway_count < MAX_IWAYS)) { 1192 if (((segp->base + i * mem_xfersize) & mask) == match) 1193 newptr->iway[newptr->iway_count++] = i; 1194 ++i; 1195 } 1196 return (PICL_WALK_CONTINUE); 1197 } 1198 1199 1200 /* 1201 * find the memory bank and add the bank handle in the bank list 1202 * return the head of the bank list 1203 */ 1204 static int 1205 logprintf_bankinfo(picl_nodehdl_t segh, seg_info_t *segp) 1206 { 1207 int err; 1208 1209 log_printf("BankIDs "); 1210 /* 1211 * find memory-bank 1212 */ 1213 segp->bank_count = 0; 1214 err = picl_walk_tree_by_class(segh, PICL_CLASS_MEMORY_BANK, segp, 1215 membank_callback); 1216 log_printf("\n"); 1217 return (err); 1218 } 1219 1220 /* 1221 * print the label of memory module or the memory module bank ids 1222 */ 1223 static int 1224 logprintf_seg_contains_col(picl_nodehdl_t nodeh, seg_info_t *segp) 1225 { 1226 picl_nodehdl_t moduleh; 1227 int err; 1228 1229 /* 1230 * find memory-module if referenced directly from the memory-segment 1231 * (ie no memory banks) 1232 */ 1233 err = picl_get_propval_by_name(nodeh, PICL_REFPROP_MEMORY_MODULE, 1234 &moduleh, sizeof (moduleh)); 1235 if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND)) 1236 return (err); 1237 if (err == PICL_SUCCESS) { 1238 err = logprintf_memory_module_label(moduleh); 1239 log_printf("\n"); 1240 return (err); 1241 } 1242 1243 /* 1244 * memory-module not referenced directly from the memory segment 1245 * so list memory banks instead 1246 */ 1247 err = logprintf_bankinfo(nodeh, segp); 1248 return (err); 1249 } 1250 1251 /* 1252 * find all memory modules under the given memory module group 1253 * and print its label 1254 */ 1255 static int 1256 logprintf_memory_module_group_info(picl_nodehdl_t memgrph, uint64_t mcid) 1257 { 1258 int err; 1259 int64_t id; 1260 picl_nodehdl_t moduleh; 1261 char piclclass[PICL_CLASSNAMELEN_MAX]; 1262 picl_nodehdl_t fruparenth; 1263 char *status; 1264 1265 id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID, &err); 1266 if (err == PICL_PROPNOTFOUND) 1267 id = -1; 1268 else if (err != PICL_SUCCESS) 1269 return (err); 1270 1271 err = picl_get_propval_by_name(memgrph, PICL_PROP_CHILD, &moduleh, 1272 sizeof (picl_nodehdl_t)); 1273 1274 while (err == PICL_SUCCESS) { 1275 /* controller id */ 1276 log_printf("%-8lld ", mcid); 1277 1278 /* group id */ 1279 if (id == -1) { 1280 log_printf("- "); 1281 } else { 1282 log_printf("%-8lld ", id); 1283 } 1284 1285 err = picl_get_propval_by_name(moduleh, PICL_PROP_CLASSNAME, 1286 piclclass, sizeof (piclclass)); 1287 if (err != PICL_SUCCESS) 1288 return (err); 1289 1290 if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE) == 0) { 1291 err = logprintf_memory_module_label(moduleh); 1292 if (err != PICL_SUCCESS) 1293 return (err); 1294 } 1295 1296 err = picldiag_get_fru_parent(moduleh, &fruparenth); 1297 if (err == PICL_SUCCESS) { 1298 err = picldiag_get_string_propval(fruparenth, 1299 PICL_PROP_OPERATIONAL_STATUS, &status); 1300 if (err == PICL_SUCCESS) { 1301 log_printf("%s", status); 1302 free(status); 1303 } else if (err != PICL_PROPNOTFOUND) 1304 return (err); 1305 } else if (err != PICL_PROPNOTFOUND) 1306 return (err); 1307 1308 err = picl_get_propval_by_name(moduleh, PICL_PROP_PEER, 1309 &moduleh, sizeof (picl_nodehdl_t)); 1310 1311 log_printf("\n"); 1312 } 1313 if (err == PICL_PROPNOTFOUND) 1314 return (PICL_SUCCESS); 1315 return (err); 1316 } 1317 1318 /* 1319 * search children to find memory module group under memory-controller 1320 */ 1321 static int 1322 find_memory_module_group(picl_nodehdl_t mch, int *print_header) 1323 { 1324 picl_nodehdl_t memgrph; 1325 uint64_t mcid; 1326 int err; 1327 char piclclass[PICL_CLASSNAMELEN_MAX]; 1328 1329 mcid = picldiag_get_uint_propval(mch, OBP_PROP_PORTID, &err); 1330 if (err == PICL_PROPNOTFOUND) 1331 mcid = DEFAULT_PORTID; 1332 else if (err != PICL_SUCCESS) 1333 return (err); 1334 1335 err = picl_get_propval_by_name(mch, PICL_PROP_CHILD, 1336 &memgrph, sizeof (picl_nodehdl_t)); 1337 while (err == PICL_SUCCESS) { 1338 err = picl_get_propval_by_name(memgrph, 1339 PICL_PROP_CLASSNAME, piclclass, sizeof (piclclass)); 1340 if (err != PICL_SUCCESS) 1341 return (err); 1342 1343 if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE_GROUP) == 0) { 1344 if (*print_header == 1) { 1345 log_printf( 1346 dgettext(TEXT_DOMAIN, 1347 "\nMemory Module Groups:\n")); 1348 log_printf("--------------------------"); 1349 log_printf("------------------------\n"); 1350 log_printf("ControllerID GroupID Labels"); 1351 log_printf(" Status\n"); 1352 log_printf("--------------------------"); 1353 log_printf("------------------------\n"); 1354 *print_header = 0; 1355 } 1356 err = logprintf_memory_module_group_info(memgrph, mcid); 1357 if (err != PICL_SUCCESS) 1358 return (err); 1359 } 1360 1361 err = picl_get_propval_by_name(memgrph, PICL_PROP_PEER, 1362 &memgrph, sizeof (picl_nodehdl_t)); 1363 } 1364 if (err == PICL_PROPNOTFOUND) 1365 return (PICL_SUCCESS); 1366 return (err); 1367 } 1368 1369 /* 1370 * print memory module group table per memory-controller 1371 */ 1372 static int 1373 print_memory_module_group_table(picl_nodehdl_t plafh) 1374 { 1375 picl_nodehdl_t mch; 1376 int err; 1377 char piclclass[PICL_CLASSNAMELEN_MAX]; 1378 int print_header; 1379 1380 print_header = 1; 1381 1382 /* 1383 * find memory-controller 1384 */ 1385 err = picl_get_propval_by_name(plafh, PICL_PROP_CHILD, &mch, 1386 sizeof (picl_nodehdl_t)); 1387 while (err == PICL_SUCCESS) { 1388 err = picl_get_propval_by_name(mch, PICL_PROP_CLASSNAME, 1389 piclclass, sizeof (piclclass)); 1390 if (err != PICL_SUCCESS) 1391 return (err); 1392 1393 if (strcmp(piclclass, PICL_CLASS_MEMORY_CONTROLLER) != 0) { 1394 err = print_memory_module_group_table(mch); 1395 if (err != PICL_SUCCESS) 1396 return (err); 1397 err = picl_get_propval_by_name(mch, PICL_PROP_PEER, 1398 &mch, sizeof (picl_nodehdl_t)); 1399 continue; 1400 } 1401 1402 err = find_memory_module_group(mch, &print_header); 1403 if (err != PICL_SUCCESS) 1404 return (err); 1405 1406 err = picl_get_propval_by_name(mch, PICL_PROP_PEER, 1407 &mch, sizeof (picl_nodehdl_t)); 1408 } 1409 if (err == PICL_PROPNOTFOUND) 1410 return (PICL_SUCCESS); 1411 1412 return (err); 1413 } 1414 1415 /* 1416 * print bank table 1417 */ 1418 static int 1419 print_bank_table(void) 1420 { 1421 bank_list_t *ptr; 1422 picl_nodehdl_t bankh; 1423 picl_nodehdl_t memgrph; 1424 picl_nodehdl_t mch; 1425 int err; 1426 int32_t i; 1427 uint64_t size; 1428 int id; 1429 1430 log_printf(dgettext(TEXT_DOMAIN, "\nBank Table:\n")); 1431 log_printf("---------------------------------------"); 1432 log_printf("--------------------\n"); 1433 log_printf(dgettext(TEXT_DOMAIN, " Physical Location\n")); 1434 log_printf(dgettext(TEXT_DOMAIN, "ID ControllerID GroupID ")); 1435 log_printf(dgettext(TEXT_DOMAIN, "Size Interleave Way\n")); 1436 log_printf("---------------------------------------"); 1437 log_printf("--------------------\n"); 1438 1439 for (ptr = mem_banks; ptr != NULL; ptr = ptr->next) { 1440 bankh = ptr->nodeh; 1441 id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err); 1442 if (err != PICL_SUCCESS) 1443 log_printf("%-8s ", "-"); 1444 else 1445 log_printf("%-8d ", id); 1446 1447 /* find memory-module-group */ 1448 err = picl_get_propval_by_name(bankh, 1449 PICL_REFPROP_MEMORY_MODULE_GROUP, &memgrph, 1450 sizeof (memgrph)); 1451 if (err == PICL_PROPNOTFOUND) { 1452 log_printf("%-8s ", "-"); 1453 log_printf("%-8s ", "-"); 1454 } else if (err != PICL_SUCCESS) 1455 return (err); 1456 else { 1457 /* 1458 * get controller id 1459 */ 1460 err = picl_get_propval_by_name(memgrph, 1461 PICL_PROP_PARENT, &mch, sizeof (picl_nodehdl_t)); 1462 if (err != PICL_SUCCESS) 1463 return (err); 1464 1465 id = picldiag_get_uint_propval(mch, OBP_PROP_PORTID, 1466 &err); 1467 if (err == PICL_PROPNOTFOUND) 1468 id = DEFAULT_PORTID; /* use default */ 1469 else if (err != PICL_SUCCESS) 1470 return (err); 1471 1472 log_printf("%-8d ", id); 1473 1474 /* get group id */ 1475 id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID, 1476 &err); 1477 if (err == PICL_PROPNOTFOUND) 1478 log_printf("- "); 1479 else if (err == PICL_SUCCESS) 1480 log_printf("%-8d ", id); 1481 else 1482 return (err); 1483 } 1484 1485 size = picldiag_get_uint_propval(bankh, PICL_PROP_SIZE, &err); 1486 if (err == PICL_PROPNOTFOUND) 1487 log_printf("- "); 1488 else if (err == PICL_SUCCESS) 1489 logprintf_size(size); 1490 else 1491 return (err); 1492 1493 log_printf(" "); 1494 for (i = 0; i < ptr->iway_count; i++) { 1495 if (i != 0) 1496 log_printf(","); 1497 log_printf("%d", ptr->iway[i]); 1498 } 1499 1500 log_printf("\n"); 1501 } 1502 return (PICL_SUCCESS); 1503 } 1504 1505 /* 1506 * callback function to print segment, add the bank in the list and 1507 * return the bank list 1508 */ 1509 /* ARGSUSED */ 1510 static int 1511 memseg_callback(picl_nodehdl_t segh, void *args) 1512 { 1513 seg_info_t seginfo; 1514 int err; 1515 1516 /* get base address */ 1517 seginfo.base = picldiag_get_uint_propval(segh, PICL_PROP_BASEADDRESS, 1518 &err); 1519 if (err == PICL_PROPNOTFOUND) { 1520 log_printf("-\n"); 1521 return (PICL_WALK_CONTINUE); 1522 } else if (err == PICL_SUCCESS) 1523 log_printf("0x%-16llx ", seginfo.base); 1524 else 1525 return (err); 1526 1527 /* get size */ 1528 seginfo.size = picldiag_get_uint_propval(segh, PICL_PROP_SIZE, &err); 1529 if (err == PICL_PROPNOTFOUND) { 1530 log_printf("-\n"); 1531 return (PICL_WALK_CONTINUE); 1532 } else if (err == PICL_SUCCESS) 1533 logprintf_size(seginfo.size); 1534 else 1535 return (err); 1536 1537 /* get interleave factor */ 1538 seginfo.ifactor = picldiag_get_uint_propval(segh, 1539 PICL_PROP_INTERLEAVE_FACTOR, &err); 1540 1541 if (err == PICL_PROPNOTFOUND) { 1542 log_printf(" -\n"); 1543 return (PICL_WALK_CONTINUE); 1544 } else if (err == PICL_SUCCESS) 1545 log_printf(" %-2d ", seginfo.ifactor); 1546 else 1547 return (err); 1548 1549 seginfo.bank_count = 0; 1550 err = logprintf_seg_contains_col(segh, &seginfo); 1551 if (err != PICL_SUCCESS) 1552 return (err); 1553 return (PICL_WALK_CONTINUE); 1554 } 1555 1556 /* 1557 * search children to find memory-segment and set up the bank list 1558 */ 1559 static int 1560 find_segments(picl_nodehdl_t plafh) 1561 { 1562 int err; 1563 1564 log_printf(dgettext(TEXT_DOMAIN, "Segment Table:\n")); 1565 log_printf("------------------------------"); 1566 log_printf("-----------------------------------------\n"); 1567 log_printf(dgettext(TEXT_DOMAIN, "Base Address Size ")); 1568 log_printf(dgettext(TEXT_DOMAIN, "Interleave Factor Contains\n")); 1569 log_printf("------------------------------"); 1570 log_printf("-----------------------------------------\n"); 1571 1572 err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT, 1573 NULL, memseg_callback); 1574 return (err); 1575 } 1576 1577 /* 1578 * display memory configuration 1579 */ 1580 static int 1581 display_memory_config(picl_nodehdl_t plafh) 1582 { 1583 int err; 1584 1585 logprintf_header(dgettext(TEXT_DOMAIN, "Memory Configuration"), 1586 DEFAULT_LINE_WIDTH); 1587 1588 mem_banks = NULL; 1589 err = find_segments(plafh); 1590 1591 if ((err == PICL_SUCCESS) && (mem_banks != NULL)) 1592 print_bank_table(); 1593 1594 free_bank_list(); 1595 1596 return (print_memory_module_group_table(plafh)); 1597 } 1598 1599 /* 1600 * print the hub device 1601 */ 1602 static int 1603 logprintf_hub_devices(picl_nodehdl_t hubh) 1604 { 1605 char *name; 1606 int portnum; 1607 int err; 1608 1609 err = picldiag_get_string_propval(hubh, PICL_PROP_NAME, &name); 1610 if (err != PICL_SUCCESS) 1611 return (err); 1612 log_printf("%-12.12s ", name); 1613 free(name); 1614 1615 err = picl_get_propval_by_name(hubh, OBP_PROP_REG, 1616 &portnum, sizeof (portnum)); 1617 if (err == PICL_PROPNOTFOUND) 1618 log_printf("-\n"); 1619 else if (err == PICL_SUCCESS) 1620 log_printf("%3d\n", portnum); 1621 else 1622 return (err); 1623 1624 return (PICL_SUCCESS); 1625 } 1626 1627 /* 1628 * callback functions to display hub devices 1629 */ 1630 /* ARGSUSED */ 1631 static int 1632 print_usb_devices(picl_nodehdl_t hubh, void *arg) 1633 { 1634 picl_nodehdl_t chdh; 1635 char *rootname; 1636 int type = *(int *)arg; 1637 int hubnum; 1638 int err; 1639 1640 err = picl_get_propval_by_name(hubh, PICL_PROP_CHILD, &chdh, 1641 sizeof (picl_nodehdl_t)); 1642 1643 /* print header */ 1644 if (err == PICL_SUCCESS) { 1645 err = picldiag_get_string_propval(hubh, PICL_PROP_NAME, 1646 &rootname); 1647 if (err != PICL_SUCCESS) 1648 return (err); 1649 1650 if (type == USB) { 1651 log_printf("\n==============================="); 1652 log_printf(dgettext(TEXT_DOMAIN, 1653 " %s Devices "), rootname); 1654 } else { 1655 /* Get its hub number */ 1656 err = picl_get_propval_by_name(hubh, 1657 OBP_PROP_REG, &hubnum, sizeof (hubnum)); 1658 if ((err != PICL_SUCCESS) && 1659 (err != PICL_PROPNOTFOUND)) { 1660 free(rootname); 1661 return (err); 1662 } 1663 1664 log_printf("\n==============================="); 1665 if (err == PICL_SUCCESS) 1666 log_printf(dgettext(TEXT_DOMAIN, 1667 " %s#%d Devices "), 1668 rootname, hubnum); 1669 else 1670 log_printf(dgettext(TEXT_DOMAIN, 1671 " %s Devices "), rootname); 1672 } 1673 1674 log_printf("===============================\n\n"); 1675 log_printf("Name Port#\n"); 1676 log_printf("------------ -----\n"); 1677 free(rootname); 1678 1679 do { 1680 logprintf_hub_devices(chdh); 1681 1682 err = picl_get_propval_by_name(chdh, PICL_PROP_PEER, 1683 &chdh, sizeof (picl_nodehdl_t)); 1684 } while (err == PICL_SUCCESS); 1685 } 1686 1687 1688 if (err == PICL_PROPNOTFOUND) 1689 return (PICL_WALK_CONTINUE); 1690 return (err); 1691 } 1692 1693 /* 1694 * callback functions to display usb devices 1695 */ 1696 /* ARGSUSED */ 1697 static int 1698 usb_callback(picl_nodehdl_t usbh, void *args) 1699 { 1700 int err; 1701 int type; 1702 1703 type = USB; 1704 err = print_usb_devices(usbh, &type); 1705 if (err != PICL_WALK_CONTINUE) 1706 return (err); 1707 type = HUB; 1708 err = picl_walk_tree_by_class(usbh, NULL, &type, print_usb_devices); 1709 if (err == PICL_SUCCESS) 1710 err = PICL_WALK_CONTINUE; 1711 return (err); 1712 } 1713 1714 1715 /* 1716 * find usb devices and print its information 1717 */ 1718 static int 1719 display_usb_devices(picl_nodehdl_t plafh) 1720 { 1721 int err; 1722 1723 /* 1724 * get the usb node 1725 */ 1726 err = picl_walk_tree_by_class(plafh, PICL_CLASS_USB, NULL, 1727 usb_callback); 1728 return (err); 1729 } 1730 1731 1732 1733 /* 1734 * If nodeh is the io device, add it into the io list and return 1735 * If it is not an io device and it has the subtree, traverse the subtree 1736 * and add all leaf io devices 1737 */ 1738 static int 1739 add_io_leaves(picl_nodehdl_t nodeh, char *parentname, uint32_t board, 1740 uint32_t bus_id, uint64_t slot, uint32_t freq, char *model, char *status) 1741 { 1742 picl_nodehdl_t childh; 1743 picl_prophdl_t proph; 1744 picl_propinfo_t pinfo; 1745 int err; 1746 char *nameval; 1747 char piclclass[PICL_CLASSNAMELEN_MAX]; 1748 char nodename[MAXSTRLEN]; 1749 char name[MAXSTRLEN]; 1750 char *devfs_path; 1751 char *compatible; 1752 picl_nodehdl_t fruparenth; 1753 char *label; 1754 char binding_name[MAXSTRLEN]; 1755 1756 err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME, &pinfo, 1757 &proph); 1758 if (err != PICL_SUCCESS) 1759 return (err); 1760 1761 nameval = alloca(pinfo.size); 1762 if (nameval == NULL) 1763 return (PICL_FAILURE); 1764 1765 err = picl_get_propval(proph, nameval, pinfo.size); 1766 if (err != PICL_SUCCESS) 1767 return (err); 1768 1769 (void) strlcpy(nodename, nameval, MAXSTRLEN); 1770 1771 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 1772 piclclass, sizeof (piclclass)); 1773 if (err != PICL_SUCCESS) 1774 return (err); 1775 1776 /* if binding_name is found, name will be <nodename>-<binding_name> */ 1777 err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, 1778 binding_name, sizeof (binding_name)); 1779 if (err == PICL_PROPNOTFOUND) { 1780 /* 1781 * if compatible prop is found, name will be 1782 * <nodename>-<compatible> 1783 */ 1784 err = picldiag_get_first_compatible_value(nodeh, &compatible); 1785 if (err == PICL_SUCCESS) { 1786 strlcat(nodename, "-", MAXSTRLEN); 1787 strlcat(nodename, compatible, MAXSTRLEN); 1788 free(compatible); 1789 } else if (err != PICL_PROPNOTFOUND) { 1790 return (err); 1791 } 1792 } else if (err != PICL_SUCCESS) { 1793 return (err); 1794 } else if (strcmp(nodename, binding_name) != 0) { 1795 if (strcmp(nodename, piclclass) == 0) { 1796 /* 1797 * nodename same as binding name - 1798 * no need to display twice 1799 */ 1800 strlcpy(nodename, binding_name, MAXSTRLEN); 1801 } else { 1802 strlcat(nodename, "-", MAXSTRLEN); 1803 strlcat(nodename, binding_name, MAXSTRLEN); 1804 } 1805 } 1806 1807 /* 1808 * If it is an immediate child under pci/sbus/upa and not 1809 * a bus node, add it to the io list. 1810 * If it is a child under sub-bus and it is in an io 1811 * device, add it to the io list. 1812 */ 1813 if (((parentname == NULL) && (!is_bus(piclclass))) || 1814 ((parentname != NULL) && (is_io_device(piclclass)))) { 1815 if (parentname == NULL) 1816 (void) snprintf(name, MAXSTRLEN, "%s", nodename); 1817 else 1818 (void) snprintf(name, MAXSTRLEN, "%s/%s", parentname, 1819 nodename); 1820 1821 /* 1822 * append the class if its class is not a generic 1823 * obp-device class 1824 */ 1825 if (strcmp(piclclass, PICL_CLASS_OBP_DEVICE)) 1826 (void) snprintf(name, MAXSTRLEN, "%s (%s)", name, 1827 piclclass); 1828 1829 err = picldiag_get_fru_parent(nodeh, &fruparenth); 1830 if (err == PICL_PROPNOTFOUND) { 1831 label = NULL; 1832 } else if (err != PICL_SUCCESS) { 1833 return (err); 1834 } else { 1835 err = picldiag_get_combined_label(fruparenth, &label, 1836 15); 1837 if (err == PICL_PROPNOTFOUND) 1838 label = NULL; 1839 else if (err != PICL_SUCCESS) 1840 return (err); 1841 } 1842 /* devfs-path */ 1843 err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, 1844 &devfs_path); 1845 if (err == PICL_PROPNOTFOUND) 1846 devfs_path = NULL; 1847 else if (err != PICL_SUCCESS) 1848 return (err); 1849 1850 add_io_card(board, bus_id, slot, label, freq, name, 1851 model, status, devfs_path); 1852 if (label != NULL) 1853 free(label); 1854 if (devfs_path != NULL) 1855 free(devfs_path); 1856 return (PICL_SUCCESS); 1857 } 1858 1859 /* 1860 * If there is any child, Go through each child. 1861 */ 1862 1863 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, 1864 &childh, sizeof (picl_nodehdl_t)); 1865 1866 /* there is a child */ 1867 while (err == PICL_SUCCESS) { 1868 if (parentname == NULL) 1869 (void) strlcpy(name, nodename, MAXSTRLEN); 1870 else 1871 (void) snprintf(name, MAXSTRLEN, "%s/%s", parentname, 1872 nodename); 1873 1874 err = add_io_leaves(childh, name, board, bus_id, slot, freq, 1875 model, status); 1876 if (err != PICL_SUCCESS) 1877 return (err); 1878 /* 1879 * get next child 1880 */ 1881 err = picl_get_propval_by_name(childh, PICL_PROP_PEER, 1882 &childh, sizeof (picl_nodehdl_t)); 1883 } 1884 1885 if (err == PICL_PROPNOTFOUND) 1886 return (PICL_SUCCESS); 1887 return (err); 1888 } 1889 1890 /* 1891 * callback function to add all io devices under sbus in io list 1892 */ 1893 /*ARGSUSED*/ 1894 static int 1895 sbus_callback(picl_nodehdl_t sbush, void *args) 1896 { 1897 picl_nodehdl_t nodeh; 1898 int err; 1899 uint32_t boardnum; 1900 uint32_t bus_id; 1901 uint32_t slot; 1902 uint32_t freq; 1903 char *model; 1904 char *status; 1905 1906 /* Fill in common infomation */ 1907 bus_id = SBUS_TYPE; 1908 1909 err = picldiag_get_clock_freq(sbush, &freq); 1910 if (err == PICL_PROPNOTFOUND) 1911 return (PICL_WALK_CONTINUE); 1912 else if (err != PICL_SUCCESS) 1913 return (err); 1914 /* 1915 * If no board# is found, set boardnum to 0 1916 */ 1917 boardnum = picldiag_get_uint_propval(sbush, OBP_PROP_BOARD_NUM, &err); 1918 if (err == PICL_PROPNOTFOUND) 1919 boardnum = DEFAULT_BOARD_NUM; 1920 else if (err != PICL_SUCCESS) 1921 return (err); 1922 1923 err = picl_get_propval_by_name(sbush, PICL_PROP_CHILD, &nodeh, 1924 sizeof (picl_nodehdl_t)); 1925 1926 while (err == PICL_SUCCESS) { 1927 slot = picldiag_get_uint_propval(nodeh, 1928 PICL_PROP_SLOT, &err); 1929 if (err == PICL_PROPNOTFOUND) { 1930 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, 1931 &nodeh, sizeof (picl_nodehdl_t)); 1932 continue; 1933 } else if (err != PICL_SUCCESS) 1934 return (err); 1935 1936 err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL, 1937 &model); 1938 if (err == PICL_PROPNOTFOUND) 1939 model = NULL; 1940 else if (err != PICL_SUCCESS) 1941 return (err); 1942 1943 err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, 1944 &status); 1945 if (err == PICL_PROPNOTFOUND) { 1946 status = malloc(5); 1947 strncpy(status, "okay", 5); 1948 } else if (err != PICL_SUCCESS) 1949 return (err); 1950 1951 err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot, freq, 1952 model, status); 1953 if (model != NULL) 1954 free(model); 1955 if (status != NULL) 1956 free(status); 1957 if (err != PICL_SUCCESS) 1958 return (err); 1959 1960 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 1961 sizeof (picl_nodehdl_t)); 1962 } 1963 if (err == PICL_PROPNOTFOUND) 1964 return (PICL_WALK_CONTINUE); 1965 return (err); 1966 } 1967 1968 /* 1969 * add all io devices under pci in io list 1970 */ 1971 /* ARGSUSED */ 1972 static int 1973 pci_callback(picl_nodehdl_t pcih, void *args) 1974 { 1975 picl_nodehdl_t nodeh; 1976 int err; 1977 char piclclass[PICL_CLASSNAMELEN_MAX]; 1978 uint32_t boardnum; 1979 uint32_t bus_id; 1980 uint32_t slot; 1981 uint32_t freq; 1982 char *model; 1983 char *status; 1984 1985 /* Fill in common infomation */ 1986 bus_id = PCI_TYPE; 1987 1988 /* 1989 * Check if it has the freq, if not, 1990 * If not, use its parent's freq 1991 * if its parent's freq is not found, return 1992 */ 1993 err = picldiag_get_clock_freq(pcih, &freq); 1994 if (err == PICL_PROPNOTFOUND) { 1995 err = picldiag_get_clock_from_parent(pcih, &freq); 1996 if (err == PICL_PROPNOTFOUND) 1997 return (PICL_WALK_CONTINUE); 1998 else if (err != PICL_SUCCESS) 1999 return (err); 2000 } else if (err != PICL_SUCCESS) 2001 return (err); 2002 2003 /* 2004 * If no board# is found, set boardnum to 0 2005 */ 2006 boardnum = picldiag_get_uint_propval(pcih, OBP_PROP_BOARD_NUM, &err); 2007 if (err == PICL_PROPNOTFOUND) 2008 boardnum = DEFAULT_BOARD_NUM; 2009 else if (err != PICL_SUCCESS) 2010 return (err); 2011 2012 /* Walk through the children */ 2013 2014 err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 2015 sizeof (picl_nodehdl_t)); 2016 while (err == PICL_SUCCESS) { 2017 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 2018 piclclass, sizeof (piclclass)); 2019 if (err != PICL_SUCCESS) 2020 return (err); 2021 2022 /* 2023 * Skip PCI bridge and USB devices because they will be 2024 * processed later 2025 */ 2026 if ((strcmp(piclclass, PICL_CLASS_PCI) == 0) || 2027 (strcmp(piclclass, PICL_CLASS_USB) == 0)) { 2028 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, 2029 &nodeh, sizeof (picl_nodehdl_t)); 2030 continue; 2031 } 2032 2033 /* Get the device id for pci card */ 2034 slot = picldiag_get_uint_propval(nodeh, 2035 PICL_PROP_DEVICE_ID, &err); 2036 if (err == PICL_PROPNOTFOUND) { 2037 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, 2038 &nodeh, sizeof (picl_nodehdl_t)); 2039 continue; 2040 } else if (err != PICL_SUCCESS) 2041 return (err); 2042 2043 /* Get the model of this card */ 2044 err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL, 2045 &model); 2046 if (err == PICL_PROPNOTFOUND) 2047 model = NULL; 2048 else if (err != PICL_SUCCESS) 2049 return (err); 2050 2051 err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, 2052 &status); 2053 if (err == PICL_PROPNOTFOUND) { 2054 status = malloc(5); 2055 strncpy(status, "okay", 5); 2056 } else if (err != PICL_SUCCESS) 2057 return (err); 2058 2059 err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot, 2060 freq, model, status); 2061 2062 if (model != NULL) 2063 free(model); 2064 2065 if (status != NULL) 2066 free(status); 2067 2068 if (err != PICL_SUCCESS) 2069 return (err); 2070 2071 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 2072 sizeof (picl_nodehdl_t)); 2073 2074 } 2075 2076 if (err == PICL_PROPNOTFOUND) 2077 return (PICL_WALK_CONTINUE); 2078 2079 return (err); 2080 } 2081 2082 /* 2083 * add io devices in io list 2084 * Its slot number is drived from upa-portid 2085 */ 2086 static int 2087 add_io_devices(picl_nodehdl_t nodeh) 2088 { 2089 int err; 2090 uint64_t board_type; 2091 char piclclass[PICL_CLASSNAMELEN_MAX]; 2092 char name[MAXSTRLEN]; 2093 char *devfs_path; 2094 char *nameval; 2095 uint32_t boardnum; 2096 uint32_t bus_id; 2097 uint32_t slot; 2098 uint32_t freq; 2099 char *model; 2100 char *status; 2101 picl_prophdl_t proph; 2102 picl_propinfo_t pinfo; 2103 picl_nodehdl_t fruparenth; 2104 char *label; 2105 2106 2107 bus_id = UPA_TYPE; 2108 2109 /* 2110 * If clock frequency can't be found from its parent, don't add 2111 */ 2112 err = picldiag_get_clock_from_parent(nodeh, &freq); 2113 if (err == PICL_PROPNOTFOUND) 2114 return (PICL_SUCCESS); 2115 else if (err != PICL_SUCCESS) 2116 return (err); 2117 2118 /* 2119 * If no board# is found, set boardnum to 0 2120 */ 2121 boardnum = picldiag_get_uint_propval(nodeh, OBP_PROP_BOARD_NUM, &err); 2122 if (err == PICL_PROPNOTFOUND) 2123 boardnum = DEFAULT_BOARD_NUM; 2124 else if (err != PICL_SUCCESS) 2125 return (err); 2126 2127 /* 2128 * get upa portid as slot number 2129 * If upa portid is not found, don't add the card. 2130 */ 2131 slot = picldiag_get_uint_propval(nodeh, OBP_PROP_UPA_PORTID, 2132 &err); 2133 if (err == PICL_PROPNOTFOUND) 2134 return (PICL_SUCCESS); 2135 else if (err != PICL_SUCCESS) 2136 return (err); 2137 2138 /* Get the model of this card */ 2139 err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL, &model); 2140 if (err == PICL_PROPNOTFOUND) 2141 model = NULL; 2142 else if (err != PICL_SUCCESS) 2143 return (err); 2144 2145 /* 2146 * check if it is a ffb device 2147 * If it's a ffb device, append its board type to name 2148 * otherwise, use its nodename 2149 */ 2150 err = picl_get_prop_by_name(nodeh, PICL_PROP_FFB_BOARD_REV, &proph); 2151 if (err == PICL_PROPNOTFOUND) { 2152 err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME, 2153 &pinfo, &proph); 2154 if (err != PICL_SUCCESS) 2155 return (err); 2156 2157 nameval = alloca(pinfo.size); 2158 if (nameval == NULL) 2159 return (PICL_FAILURE); 2160 2161 err = picl_get_propval(proph, nameval, pinfo.size); 2162 if (err != PICL_SUCCESS) 2163 return (err); 2164 2165 (void) strlcpy(name, nameval, MAXSTRLEN); 2166 } else if (err == PICL_SUCCESS) { 2167 /* Find out if it's single or double buffered */ 2168 board_type = picldiag_get_uint_propval(nodeh, 2169 OBP_PROP_BOARD_TYPE, &err); 2170 if (err == PICL_PROPNOTFOUND) 2171 (void) strlcpy(name, FFB_NAME, sizeof (name)); 2172 if (err == PICL_SUCCESS) { 2173 if (board_type & FFB_B_BUFF) 2174 (void) strlcpy(name, FFB_DOUBLE_BUF, 2175 sizeof (name)); 2176 else 2177 (void) strlcpy(name, FFB_SINGLE_BUF, 2178 sizeof (name)); 2179 } else 2180 return (err); 2181 } else 2182 return (err); 2183 2184 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 2185 piclclass, sizeof (piclclass)); 2186 if (err != PICL_SUCCESS) 2187 return (err); 2188 2189 (void) snprintf(name, sizeof (name), "%s (%s)", name, piclclass); 2190 2191 err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, &status); 2192 if (err == PICL_PROPNOTFOUND) { 2193 status = malloc(5); 2194 strncpy(status, "okay", 5); 2195 } else if (err != PICL_SUCCESS) 2196 return (err); 2197 2198 err = picldiag_get_fru_parent(nodeh, &fruparenth); 2199 if (err == PICL_PROPNOTFOUND) { 2200 label = NULL; 2201 } else if (err != PICL_SUCCESS) { 2202 return (err); 2203 } else { 2204 err = picldiag_get_combined_label(fruparenth, &label, 15); 2205 if (err == PICL_PROPNOTFOUND) 2206 label = NULL; 2207 else if (err != PICL_SUCCESS) 2208 return (err); 2209 } 2210 /* devfs-path */ 2211 err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, 2212 &devfs_path); 2213 if (err == PICL_PROPNOTFOUND) 2214 devfs_path = NULL; 2215 else if (err != PICL_SUCCESS) 2216 return (err); 2217 2218 add_io_card(boardnum, bus_id, slot, label, freq, name, model, status, 2219 devfs_path); 2220 if (label != NULL) 2221 free(label); 2222 if (model != NULL) 2223 free(model); 2224 if (status != NULL) 2225 free(status); 2226 if (devfs_path != NULL) 2227 free(devfs_path); 2228 2229 return (PICL_SUCCESS); 2230 } 2231 2232 /* 2233 * loop through all children and add io devices in io list 2234 */ 2235 static int 2236 process_io_leaves(picl_nodehdl_t rooth) 2237 { 2238 picl_nodehdl_t nodeh; 2239 char classval[PICL_CLASSNAMELEN_MAX]; 2240 int err; 2241 2242 err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh, 2243 sizeof (picl_nodehdl_t)); 2244 while (err == PICL_SUCCESS) { 2245 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 2246 classval, sizeof (classval)); 2247 if (err != PICL_SUCCESS) 2248 return (err); 2249 2250 if (is_io_device(classval)) 2251 err = add_io_devices(nodeh); 2252 2253 if (err != PICL_SUCCESS) 2254 return (err); 2255 2256 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 2257 sizeof (picl_nodehdl_t)); 2258 } 2259 2260 if (err == PICL_PROPNOTFOUND) 2261 return (PICL_SUCCESS); 2262 2263 return (err); 2264 } 2265 2266 /* 2267 * callback function to add all io devices under upa in io list 2268 */ 2269 /*ARGSUSED*/ 2270 static int 2271 upa_callback(picl_nodehdl_t upah, void *args) 2272 { 2273 int err; 2274 2275 err = process_io_leaves(upah); 2276 2277 if (err == PICL_SUCCESS) 2278 return (PICL_WALK_CONTINUE); 2279 return (err); 2280 } 2281 2282 /* 2283 * display ffb hardware configuration 2284 */ 2285 /* ARGSUSED */ 2286 static int 2287 ffbconfig_callback(picl_nodehdl_t ffbh, void *arg) 2288 { 2289 int err; 2290 uint64_t board_rev; 2291 uint64_t fbc_ver; 2292 char *dac_ver; 2293 char *fbram_ver; 2294 2295 /* 2296 * If it has PICL_PROP_FFB_BOARD_REV, it is a ffb device 2297 * Otherwise, return. 2298 */ 2299 board_rev = picldiag_get_uint_propval(ffbh, PICL_PROP_FFB_BOARD_REV, 2300 &err); 2301 if (err == PICL_PROPNOTFOUND) 2302 return (PICL_WALK_CONTINUE); 2303 else if (err != PICL_SUCCESS) 2304 return (err); 2305 2306 log_printf("FFB Hardware Configuration:\n"); 2307 log_printf("-----------------------------------\n"); 2308 log_printf("Board rev: %lld\n", board_rev); 2309 2310 fbc_ver = picldiag_get_uint_propval(ffbh, OBP_PROP_FBC_REG_ID, 2311 &err); 2312 if (err == PICL_SUCCESS) 2313 log_printf("FBC version: 0x%llx\n", fbc_ver); 2314 else if (err != PICL_PROPNOTFOUND) 2315 return (err); 2316 2317 err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_DAC_VER, 2318 &dac_ver); 2319 if (err == PICL_SUCCESS) { 2320 log_printf("DAC: %s\n", dac_ver); 2321 free(dac_ver); 2322 } else if (err != PICL_PROPNOTFOUND) 2323 return (err); 2324 2325 err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_FBRAM_VER, 2326 &fbram_ver); 2327 if (err == PICL_SUCCESS) { 2328 log_printf("3DRAM: %s\n", fbram_ver); 2329 free(fbram_ver); 2330 } else if (err != PICL_PROPNOTFOUND) 2331 return (err); 2332 2333 log_printf("\n"); 2334 return (PICL_WALK_CONTINUE); 2335 } 2336 2337 /* 2338 * find all io devices and add them in the io list 2339 */ 2340 static int 2341 gather_io_cards(picl_nodehdl_t plafh) 2342 { 2343 int err; 2344 2345 /* 2346 * look for io devices under the immediate children of platform 2347 */ 2348 err = process_io_leaves(plafh); 2349 2350 if (err != PICL_SUCCESS) 2351 return (err); 2352 2353 err = picl_walk_tree_by_class(plafh, PICL_CLASS_SBUS, 2354 PICL_CLASS_SBUS, sbus_callback); 2355 if (err != PICL_SUCCESS) 2356 return (err); 2357 err = picl_walk_tree_by_class(plafh, PICL_CLASS_PCI, 2358 PICL_CLASS_PCI, pci_callback); 2359 if (err != PICL_SUCCESS) 2360 return (err); 2361 err = picl_walk_tree_by_class(plafh, PICL_CLASS_UPA, 2362 PICL_CLASS_UPA, upa_callback); 2363 return (err); 2364 } 2365 2366 static void 2367 picldiag_display_io_cards(struct io_card *list) 2368 { 2369 static int banner = 0; /* Have we printed the column headings? */ 2370 struct io_card *p; 2371 2372 if (list == NULL) 2373 return; 2374 2375 if (banner == 0) { 2376 log_printf("Bus Freq Slot + Name +\n", 0); 2377 log_printf("Type MHz Status " 2378 "Path " 2379 "Model", 0); 2380 log_printf("\n", 0); 2381 log_printf("---- ---- ---------- " 2382 "---------------------------- " 2383 "--------------------", 0); 2384 log_printf("\n", 0); 2385 banner = 1; 2386 } 2387 2388 for (p = list; p != NULL; p = p -> next) { 2389 log_printf("%-4s ", p->bus_type, 0); 2390 log_printf("%3d ", p->freq, 0); 2391 /* 2392 * We check to see if it's an int or 2393 * a char string to display for slot. 2394 */ 2395 if (p->slot == PCI_SLOT_IS_STRING) 2396 log_printf("%10s ", p->slot_str, 0); 2397 else 2398 log_printf("%10d ", p->slot, 0); 2399 2400 log_printf("%-28.28s", p->name, 0); 2401 if (strlen(p->name) > 28) 2402 log_printf("+ ", 0); 2403 else 2404 log_printf(" ", 0); 2405 log_printf("%-19.19s", p->model, 0); 2406 if (strlen(p->model) > 19) 2407 log_printf("+", 0); 2408 log_printf("\n", 0); 2409 log_printf(" %10s ", p->status, 0); 2410 if (strlen(p->notes) > 0) 2411 log_printf("%s", p->notes, 0); 2412 log_printf("\n\n", 0); 2413 } 2414 } 2415 2416 /* 2417 * display all io devices 2418 */ 2419 static int 2420 display_io_device_info(picl_nodehdl_t plafh) 2421 { 2422 int err; 2423 2424 err = gather_io_cards(plafh); 2425 if (err != PICL_SUCCESS) 2426 return (err); 2427 2428 logprintf_header(dgettext(TEXT_DOMAIN, "IO Devices"), 2429 DEFAULT_LINE_WIDTH); 2430 2431 picldiag_display_io_cards(io_card_list); 2432 2433 free_io_cards(io_card_list); 2434 2435 return (PICL_SUCCESS); 2436 } 2437 2438 /* 2439 * print fan device information 2440 */ 2441 static int 2442 logprintf_fan_info(picl_nodehdl_t fanh) 2443 { 2444 int err; 2445 char *label; 2446 char *unit; 2447 int64_t speed; 2448 int64_t min_speed; 2449 picl_nodehdl_t fruph; 2450 2451 err = picldiag_get_fru_parent(fanh, &fruph); 2452 if (err != PICL_SUCCESS) 2453 return (err); 2454 2455 err = picldiag_get_combined_label(fruph, &label, 14); 2456 if (err != PICL_SUCCESS) 2457 return (err); 2458 2459 log_printf("%-14s ", label); 2460 free(label); 2461 2462 err = picldiag_get_label(fanh, &label); 2463 if (err == PICL_SUCCESS) { 2464 log_printf("%-14s ", label); 2465 free(label); 2466 } else if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) { 2467 log_printf(" - "); 2468 } else 2469 return (err); 2470 2471 speed = picldiag_get_uint_propval(fanh, PICL_PROP_FAN_SPEED, &err); 2472 if (err == PICL_SUCCESS) { 2473 min_speed = picldiag_get_uint_propval(fanh, 2474 PICL_PROP_LOW_WARNING_THRESHOLD, &err); 2475 if (err != PICL_SUCCESS) 2476 min_speed = 1; 2477 if (speed < min_speed) { 2478 log_printf("failed (%lld", speed); 2479 err = picldiag_get_string_propval(fanh, 2480 PICL_PROP_FAN_SPEED_UNIT, &unit); 2481 if (err == PICL_SUCCESS) { 2482 log_printf("%s", unit); 2483 free(unit); 2484 } 2485 log_printf(")"); 2486 } else { 2487 log_printf("okay"); 2488 } 2489 } else { 2490 err = picldiag_get_string_propval(fanh, 2491 PICL_PROP_FAN_SPEED_UNIT, &unit); 2492 if (err == PICL_SUCCESS) { 2493 log_printf("%-12s ", unit); 2494 free(unit); 2495 } 2496 } 2497 2498 log_printf("\n"); 2499 return (PICL_SUCCESS); 2500 } 2501 2502 static int 2503 fan_callback(picl_nodehdl_t fanh, void *arg) 2504 { 2505 int *countp = arg; 2506 int err; 2507 2508 if (*countp == 0) { 2509 log_printf(dgettext(TEXT_DOMAIN, "Fan Status:\n")); 2510 log_printf("---------------------------------------\n"); 2511 log_printf("Location Sensor Status \n"); 2512 log_printf("---------------------------------------\n"); 2513 } 2514 *countp += 1; 2515 err = logprintf_fan_info(fanh); 2516 if (err == PICL_SUCCESS) 2517 return (PICL_WALK_CONTINUE); 2518 return (err); 2519 } 2520 2521 /* 2522 * callback function search children to find fan device and print its speed 2523 */ 2524 static int 2525 display_fan_speed(picl_nodehdl_t plafh) 2526 { 2527 int err; 2528 int print_header; 2529 2530 print_header = 0; 2531 err = picl_walk_tree_by_class(plafh, PICL_CLASS_FAN, 2532 &print_header, fan_callback); 2533 return (err); 2534 } 2535 2536 /* 2537 * print temperature sensor information 2538 */ 2539 static int 2540 logprintf_temp_info(picl_nodehdl_t temph) 2541 { 2542 int err; 2543 char *label; 2544 int64_t temperature; 2545 int64_t threshold; 2546 picl_nodehdl_t fruph; 2547 char *status = "unknown"; 2548 int got_temp = 0; 2549 2550 err = picldiag_get_fru_parent(temph, &fruph); 2551 if (err != PICL_SUCCESS) 2552 return (err); 2553 2554 err = picldiag_get_combined_label(fruph, &label, 14); 2555 if (err != PICL_SUCCESS) 2556 return (err); 2557 2558 log_printf("%-14s ", label); 2559 free(label); 2560 2561 err = picldiag_get_label(temph, &label); 2562 if (err != PICL_SUCCESS) 2563 return (err); 2564 log_printf("%-14s ", label); 2565 free(label); 2566 2567 temperature = picldiag_get_int_propval(temph, PICL_PROP_TEMPERATURE, 2568 &err); 2569 if (err == PICL_SUCCESS) { 2570 got_temp = 1; 2571 status = "okay"; 2572 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2573 return (err); 2574 } 2575 2576 threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_WARNING, 2577 &err); 2578 if (err == PICL_SUCCESS) { 2579 if (got_temp && temperature < threshold) 2580 status = "warning"; 2581 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2582 return (err); 2583 } 2584 2585 threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_SHUTDOWN, 2586 &err); 2587 if (err == PICL_SUCCESS) { 2588 if (got_temp && temperature < threshold) 2589 status = "failed"; 2590 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2591 return (err); 2592 } 2593 2594 threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_WARNING, 2595 &err); 2596 if (err == PICL_SUCCESS) { 2597 if (got_temp && temperature > threshold) 2598 status = "warning"; 2599 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2600 return (err); 2601 } 2602 2603 threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_SHUTDOWN, 2604 &err); 2605 if (err == PICL_SUCCESS) { 2606 if (got_temp && temperature > threshold) 2607 status = "failed"; 2608 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2609 return (err); 2610 } 2611 2612 err = picldiag_get_string_propval(temph, PICL_PROP_CONDITION, &status); 2613 if (err == PICL_SUCCESS) { 2614 log_printf("%s", status); 2615 free(status); 2616 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2617 return (err); 2618 } else { 2619 log_printf("%s ", status); 2620 if (strcmp(status, "failed") == 0 || 2621 strcmp(status, "warning") == 0) 2622 log_printf("(%.2lldC)", temperature); 2623 } 2624 2625 log_printf("\n"); 2626 return (PICL_SUCCESS); 2627 } 2628 2629 static int 2630 temp_callback(picl_nodehdl_t temph, void *arg) 2631 { 2632 int err; 2633 int *countp = arg; 2634 2635 if (*countp == 0) { 2636 log_printf("\n"); 2637 log_printf("---------------------------------------\n"); 2638 log_printf(dgettext(TEXT_DOMAIN, "Temperature sensors:\n")); 2639 log_printf("------------------------------------\n"); 2640 log_printf("Location Sensor Status\n"); 2641 log_printf("------------------------------------\n"); 2642 } 2643 *countp += 1; 2644 err = logprintf_temp_info(temph); 2645 if (err == PICL_SUCCESS) 2646 return (PICL_WALK_CONTINUE); 2647 return (err); 2648 } 2649 2650 /* 2651 * callback function search children to find temp sensors and print the temp 2652 */ 2653 /* ARGSUSED */ 2654 static int 2655 display_temp(picl_nodehdl_t plafh) 2656 { 2657 int err; 2658 int print_header; 2659 2660 print_header = 0; 2661 err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_SENSOR, 2662 &print_header, temp_callback); 2663 if (err != PICL_SUCCESS) 2664 return (err); 2665 err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_INDICATOR, 2666 &print_header, temp_callback); 2667 return (err); 2668 } 2669 2670 /* 2671 * print current sensor information 2672 */ 2673 static int 2674 logprintf_current_info(picl_nodehdl_t currenth) 2675 { 2676 int err; 2677 char *label; 2678 float current; 2679 float threshold; 2680 picl_nodehdl_t fruph; 2681 char *status = "unknown"; 2682 int got_current = 0; 2683 2684 err = picldiag_get_fru_parent(currenth, &fruph); 2685 if (err != PICL_SUCCESS) 2686 return (err); 2687 2688 err = picldiag_get_combined_label(fruph, &label, 10); 2689 if (err != PICL_SUCCESS) 2690 return (err); 2691 2692 log_printf("%-10s ", label); 2693 free(label); 2694 2695 err = picldiag_get_label(currenth, &label); 2696 if (err != PICL_SUCCESS) 2697 return (err); 2698 log_printf("%-10s ", label); 2699 free(label); 2700 2701 current = picldiag_get_float_propval(currenth, PICL_PROP_CURRENT, &err); 2702 if (err == PICL_SUCCESS) { 2703 status = "okay"; 2704 got_current = 1; 2705 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2706 return (err); 2707 } 2708 2709 threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_WARNING, 2710 &err); 2711 if (err == PICL_SUCCESS) { 2712 if (got_current && current < threshold) 2713 status = "warning"; 2714 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2715 return (err); 2716 } 2717 2718 threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_SHUTDOWN, 2719 &err); 2720 if (err == PICL_SUCCESS) { 2721 if (got_current && current < threshold) 2722 status = "failed"; 2723 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2724 return (err); 2725 } 2726 2727 threshold = picldiag_get_float_propval(currenth, PICL_PROP_HIGH_WARNING, 2728 &err); 2729 if (err == PICL_SUCCESS) { 2730 if (got_current && current > threshold) 2731 status = "warning"; 2732 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2733 return (err); 2734 } 2735 2736 threshold = picldiag_get_float_propval(currenth, 2737 PICL_PROP_HIGH_SHUTDOWN, &err); 2738 if (err == PICL_SUCCESS) { 2739 if (got_current && current > threshold) 2740 status = "failed"; 2741 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2742 return (err); 2743 } 2744 2745 err = picldiag_get_string_propval(currenth, 2746 PICL_PROP_CONDITION, &status); 2747 if (err == PICL_SUCCESS) { 2748 log_printf(" %s", status); 2749 free(status); 2750 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2751 return (err); 2752 } else { 2753 log_printf("%s ", status); 2754 if (strcmp(status, "failed") == 0 || 2755 strcmp(status, "warning") == 0) 2756 log_printf("(%.2fA)", current); 2757 } 2758 2759 log_printf("\n"); 2760 return (PICL_SUCCESS); 2761 } 2762 2763 static int 2764 current_callback(picl_nodehdl_t currh, void *arg) 2765 { 2766 int err; 2767 int *countp = arg; 2768 2769 if (*countp == 0) { 2770 log_printf("------------------------------------\n"); 2771 log_printf(dgettext(TEXT_DOMAIN, "Current sensors:\n")); 2772 log_printf("------------------------------\n"); 2773 log_printf("Location Sensor Status\n"); 2774 log_printf("------------------------------\n"); 2775 } 2776 *countp += 1; 2777 err = logprintf_current_info(currh); 2778 if (err == PICL_SUCCESS) 2779 return (PICL_WALK_CONTINUE); 2780 return (err); 2781 } 2782 2783 /* 2784 * callback function search children to find curr sensors and print the curr 2785 */ 2786 /* ARGSUSED */ 2787 static int 2788 display_current(picl_nodehdl_t plafh) 2789 { 2790 int err; 2791 int print_header; 2792 2793 print_header = 0; 2794 err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_SENSOR, 2795 &print_header, current_callback); 2796 if (err != PICL_SUCCESS) 2797 return (err); 2798 err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_INDICATOR, 2799 &print_header, current_callback); 2800 return (err); 2801 } 2802 2803 /* 2804 * print voltage sensor information 2805 */ 2806 static int 2807 logprintf_voltage_info(picl_nodehdl_t voltageh) 2808 { 2809 int err; 2810 char *label; 2811 float voltage; 2812 float threshold; 2813 picl_nodehdl_t fruph; 2814 char *status = "unknown"; 2815 int got_voltage = 0; 2816 2817 err = picldiag_get_fru_parent(voltageh, &fruph); 2818 if (err != PICL_SUCCESS) 2819 return (err); 2820 2821 err = picldiag_get_combined_label(fruph, &label, 10); 2822 if (err != PICL_SUCCESS) 2823 return (err); 2824 2825 log_printf("%-10s ", label); 2826 free(label); 2827 2828 err = picldiag_get_label(voltageh, &label); 2829 if (err != PICL_SUCCESS) 2830 return (err); 2831 log_printf("%-12s ", label); 2832 free(label); 2833 2834 voltage = picldiag_get_float_propval(voltageh, PICL_PROP_VOLTAGE, &err); 2835 if (err == PICL_SUCCESS) { 2836 status = "okay"; 2837 got_voltage = 1; 2838 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2839 return (err); 2840 } 2841 2842 threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_WARNING, 2843 &err); 2844 if (err == PICL_SUCCESS) { 2845 if (got_voltage && voltage < threshold) 2846 status = "warning"; 2847 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2848 return (err); 2849 } 2850 2851 threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_SHUTDOWN, 2852 &err); 2853 if (err == PICL_SUCCESS) { 2854 if (got_voltage && voltage < threshold) 2855 status = "failed"; 2856 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2857 return (err); 2858 } 2859 2860 threshold = picldiag_get_float_propval(voltageh, PICL_PROP_HIGH_WARNING, 2861 &err); 2862 if (err == PICL_SUCCESS) { 2863 if (got_voltage && voltage > threshold) 2864 status = "warning"; 2865 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2866 return (err); 2867 } 2868 2869 threshold = picldiag_get_float_propval(voltageh, 2870 PICL_PROP_HIGH_SHUTDOWN, &err); 2871 if (err == PICL_SUCCESS) { 2872 if (got_voltage && voltage > threshold) 2873 status = "failed"; 2874 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2875 return (err); 2876 } 2877 2878 err = picldiag_get_string_propval(voltageh, 2879 PICL_PROP_CONDITION, &status); 2880 if (err == PICL_SUCCESS) { 2881 log_printf("%s", status); 2882 free(status); 2883 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 2884 return (err); 2885 } else { 2886 log_printf("%s ", status); 2887 if (strcmp(status, "warning") == 0 || 2888 strcmp(status, "failed") == 0) 2889 log_printf("(%.2fV)", voltage); 2890 } 2891 2892 log_printf("\n"); 2893 return (PICL_SUCCESS); 2894 } 2895 2896 static int 2897 voltage_callback(picl_nodehdl_t voltageh, void *arg) 2898 { 2899 int *countp = arg; 2900 int err; 2901 2902 if (*countp == 0) { 2903 log_printf("--------------------------------\n"); 2904 log_printf(dgettext(TEXT_DOMAIN, "Voltage sensors:\n")); 2905 log_printf("-------------------------------\n"); 2906 log_printf("Location Sensor Status\n"); 2907 log_printf("-------------------------------\n"); 2908 } 2909 *countp += 1; 2910 err = logprintf_voltage_info(voltageh); 2911 if (err == PICL_SUCCESS) 2912 return (PICL_WALK_CONTINUE); 2913 return (err); 2914 } 2915 2916 /* 2917 * callback function search children to find voltage sensors and print voltage 2918 */ 2919 /* ARGSUSED */ 2920 static int 2921 display_voltage(picl_nodehdl_t plafh) 2922 { 2923 int err; 2924 int print_header; 2925 2926 print_header = 0; 2927 err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_SENSOR, 2928 &print_header, voltage_callback); 2929 if (err != PICL_SUCCESS) 2930 return (err); 2931 err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_INDICATOR, 2932 &print_header, voltage_callback); 2933 return (err); 2934 } 2935 2936 /* 2937 * print led device information 2938 */ 2939 static int 2940 logprintf_led_info(picl_nodehdl_t ledh) 2941 { 2942 int err; 2943 char *label; 2944 char *state; 2945 char *color; 2946 picl_nodehdl_t fruph; 2947 2948 err = picldiag_get_fru_parent(ledh, &fruph); 2949 if (err != PICL_SUCCESS) 2950 return (err); 2951 2952 err = picldiag_get_combined_label(fruph, &label, 10); 2953 if (err != PICL_SUCCESS) { 2954 log_printf(" - ", label); 2955 } else { 2956 log_printf("%-10s ", label); 2957 free(label); 2958 } 2959 2960 err = picldiag_get_label(ledh, &label); 2961 if (err != PICL_SUCCESS) 2962 return (err); 2963 log_printf("%-20s ", label); 2964 free(label); 2965 2966 err = picldiag_get_string_propval(ledh, PICL_PROP_STATE, &state); 2967 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) { 2968 log_printf(" - "); 2969 } else if (err != PICL_SUCCESS) { 2970 return (err); 2971 } else { 2972 log_printf("%-10s ", state); 2973 free(state); 2974 } 2975 2976 err = picldiag_get_string_propval(ledh, PICL_PROP_COLOR, &color); 2977 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) { 2978 log_printf("\n"); 2979 } else if (err != PICL_SUCCESS) { 2980 return (err); 2981 } else { 2982 log_printf("%-16s\n", color); 2983 free(color); 2984 } 2985 2986 return (PICL_SUCCESS); 2987 } 2988 2989 static int 2990 led_callback(picl_nodehdl_t ledh, void *arg) 2991 { 2992 int *countp = arg; 2993 int err; 2994 2995 if (*countp == 0) { 2996 2997 log_printf("--------------------------------------" 2998 "------------\n"); 2999 log_printf(dgettext(TEXT_DOMAIN, "Led State:\n")); 3000 log_printf("--------------------------------------" 3001 "------------\n"); 3002 log_printf("Location Led State" 3003 " Color\n"); 3004 log_printf("--------------------------------------" 3005 "------------\n"); 3006 } 3007 *countp += 1; 3008 err = logprintf_led_info(ledh); 3009 if (err == PICL_SUCCESS) 3010 return (PICL_WALK_CONTINUE); 3011 return (err); 3012 } 3013 3014 /* 3015 * callback function search children to find led devices and print status 3016 */ 3017 /* ARGSUSED */ 3018 static int 3019 display_led_status(picl_nodehdl_t plafh) 3020 { 3021 int print_header; 3022 3023 print_header = 0; 3024 picl_walk_tree_by_class(plafh, PICL_CLASS_LED, 3025 &print_header, led_callback); 3026 return (PICL_SUCCESS); 3027 } 3028 3029 /* 3030 * print keyswitch device information 3031 */ 3032 static int 3033 logprintf_keyswitch_info(picl_nodehdl_t keyswitchh, picl_nodehdl_t fruph) 3034 { 3035 int err; 3036 char *label; 3037 char *state; 3038 3039 err = picldiag_get_combined_label(fruph, &label, 10); 3040 if (err != PICL_SUCCESS) { 3041 log_printf("%-14s", " -"); 3042 } else { 3043 log_printf("%-14s ", label); 3044 free(label); 3045 } 3046 3047 err = picldiag_get_label(keyswitchh, &label); 3048 if (err != PICL_SUCCESS) 3049 return (err); 3050 log_printf("%-11s ", label); 3051 free(label); 3052 3053 err = picldiag_get_string_propval(keyswitchh, PICL_PROP_STATE, &state); 3054 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) { 3055 log_printf(" -\n"); 3056 } else if (err != PICL_SUCCESS) { 3057 return (err); 3058 } else { 3059 log_printf("%s\n", state); 3060 free(state); 3061 } 3062 3063 return (PICL_SUCCESS); 3064 } 3065 3066 static int 3067 keyswitch_callback(picl_nodehdl_t keyswitchh, void *arg) 3068 { 3069 int *countp = arg; 3070 int err; 3071 picl_nodehdl_t fruph; 3072 3073 /* 3074 * Tamale simulates a key-switch on ENxS. So the presence of a 3075 * node of class keyswitch is not sufficient. If it has a fru parent 3076 * or location parent, then believe it. 3077 */ 3078 err = picl_get_propval_by_name(keyswitchh, PICL_REFPROP_FRU_PARENT, 3079 &fruph, sizeof (fruph)); 3080 if (err == PICL_PROPNOTFOUND) { 3081 err = picl_get_propval_by_name(keyswitchh, 3082 PICL_REFPROP_LOC_PARENT, &fruph, sizeof (fruph)); 3083 } 3084 if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) 3085 return (PICL_WALK_CONTINUE); 3086 if (err != PICL_SUCCESS) 3087 return (err); 3088 3089 if (*countp == 0) { 3090 log_printf("-----------------------------------------\n"); 3091 log_printf(dgettext(TEXT_DOMAIN, "Keyswitch:\n")); 3092 log_printf("-----------------------------------------\n"); 3093 log_printf(dgettext(TEXT_DOMAIN, 3094 "Location Keyswitch State\n")); 3095 log_printf("-----------------------------------------\n"); 3096 } 3097 *countp += 1; 3098 err = logprintf_keyswitch_info(keyswitchh, fruph); 3099 if (err == PICL_SUCCESS) 3100 return (PICL_WALK_CONTINUE); 3101 return (err); 3102 } 3103 3104 /* 3105 * search children to find keyswitch device(s) and print status 3106 */ 3107 /* ARGSUSED */ 3108 static int 3109 display_keyswitch(picl_nodehdl_t plafh) 3110 { 3111 int print_header = 0; 3112 3113 picl_walk_tree_by_class(plafh, PICL_CLASS_KEYSWITCH, 3114 &print_header, keyswitch_callback); 3115 return (PICL_SUCCESS); 3116 } 3117 3118 /* 3119 * display environment status 3120 */ 3121 static int 3122 display_envctrl_status(picl_nodehdl_t plafh) 3123 { 3124 logprintf_header(dgettext(TEXT_DOMAIN, "Environmental Status"), 3125 DEFAULT_LINE_WIDTH); 3126 3127 display_fan_speed(plafh); 3128 display_temp(plafh); 3129 display_current(plafh); 3130 display_voltage(plafh); 3131 display_keyswitch(plafh); 3132 display_led_status(plafh); 3133 3134 return (PICL_SUCCESS); 3135 } 3136 3137 /* 3138 * print fru operational status 3139 */ 3140 static int 3141 logprintf_fru_oper_status(picl_nodehdl_t fruh, int *countp) 3142 { 3143 int err; 3144 char *label; 3145 char *status; 3146 3147 err = picldiag_get_combined_label(fruh, &label, 15); 3148 if (err != PICL_SUCCESS) 3149 return (PICL_WALK_CONTINUE); 3150 3151 err = picldiag_get_string_propval(fruh, 3152 PICL_PROP_OPERATIONAL_STATUS, &status); 3153 if (err == PICL_SUCCESS) { 3154 if (*countp == 0) { 3155 logprintf_header(dgettext(TEXT_DOMAIN, 3156 "FRU Operational Status"), 3157 DEFAULT_LINE_WIDTH); 3158 log_printf("-------------------------\n"); 3159 log_printf(dgettext(TEXT_DOMAIN, 3160 "Fru Operational Status:\n")); 3161 log_printf("-------------------------\n"); 3162 log_printf("Location Status \n"); 3163 log_printf("-------------------------\n"); 3164 } 3165 *countp += 1; 3166 log_printf("%-15s ", label); 3167 free(label); 3168 log_printf("%s\n", status); 3169 free(status); 3170 } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) { 3171 free(label); 3172 return (err); 3173 } else { 3174 free(label); 3175 } 3176 return (PICL_WALK_CONTINUE); 3177 } 3178 3179 static int 3180 fru_oper_status_callback(picl_nodehdl_t fruh, void *arg) 3181 { 3182 int err; 3183 3184 err = logprintf_fru_oper_status(fruh, (int *)arg); 3185 return (err); 3186 } 3187 3188 /* 3189 * display fru operational status 3190 */ 3191 static int 3192 display_fru_oper_status(picl_nodehdl_t frutreeh) 3193 { 3194 int print_header; 3195 3196 print_header = 0; 3197 picl_walk_tree_by_class(frutreeh, PICL_CLASS_FRU, 3198 &print_header, fru_oper_status_callback); 3199 return (PICL_SUCCESS); 3200 } 3201 3202 /* 3203 * check if the node having the version prop 3204 * If yes, print its nodename and version 3205 */ 3206 /* ARGSUSED */ 3207 static int 3208 asicrev_callback(picl_nodehdl_t nodeh, void *arg) 3209 { 3210 uint32_t version; 3211 char *name; 3212 char *model; 3213 char *status; 3214 int err; 3215 3216 version = picldiag_get_uint_propval(nodeh, OBP_PROP_VERSION_NUM, 3217 &err); 3218 if (err == PICL_PROPNOTFOUND) 3219 return (PICL_WALK_CONTINUE); 3220 else if (err != PICL_SUCCESS) 3221 return (err); 3222 3223 /* devfs-path */ 3224 err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, &name); 3225 if (err == PICL_PROPNOTFOUND) 3226 name = NULL; 3227 else if (err != PICL_SUCCESS) 3228 return (err); 3229 3230 /* model */ 3231 err = picldiag_get_string_propval(nodeh, PICL_PROP_BINDING_NAME, 3232 &model); 3233 if (err == PICL_PROPNOTFOUND) 3234 model = NULL; 3235 else if (err != PICL_SUCCESS) 3236 return (err); 3237 3238 /* status */ 3239 err = picldiag_get_string_propval(nodeh, OBP_PROP_STATUS, &status); 3240 if (err == PICL_PROPNOTFOUND) 3241 status = NULL; 3242 else if (err != PICL_SUCCESS) 3243 return (err); 3244 3245 /* 3246 * Display the data 3247 */ 3248 3249 /* name */ 3250 if (name != NULL) { 3251 log_printf("%-22s ", name); 3252 free(name); 3253 } else 3254 log_printf("%-22s ", "unknown"); 3255 /* model */ 3256 if (model != NULL) { 3257 log_printf("%-15s ", model); 3258 free(model); 3259 } else 3260 log_printf("%-15s ", "unknown"); 3261 /* status */ 3262 if (status == NULL) 3263 log_printf("%-15s ", "okay"); 3264 else { 3265 log_printf("%-15s ", status); 3266 free(status); 3267 } 3268 /* revision */ 3269 log_printf(" %-4d\n", version); 3270 3271 return (PICL_WALK_CONTINUE); 3272 } 3273 3274 /* 3275 * traverse the tree to display asic revision id for ebus 3276 */ 3277 /* ARGSUSED */ 3278 static int 3279 ebus_callback(picl_nodehdl_t ebush, void *arg) 3280 { 3281 uint32_t id; 3282 char *name; 3283 int err; 3284 char *model; 3285 char *status; 3286 3287 id = picldiag_get_uint_propval(ebush, OBP_PROP_REVISION_ID, &err); 3288 if (err == PICL_PROPNOTFOUND) 3289 return (PICL_WALK_CONTINUE); 3290 else if (err != PICL_SUCCESS) 3291 return (err); 3292 3293 /* devfs-path */ 3294 err = picldiag_get_string_propval(ebush, PICL_PROP_DEVFS_PATH, &name); 3295 if (err == PICL_PROPNOTFOUND) 3296 name = NULL; 3297 else if (err != PICL_SUCCESS) 3298 return (err); 3299 3300 /* model */ 3301 err = picldiag_get_string_propval(ebush, PICL_PROP_BINDING_NAME, 3302 &model); 3303 if (err == PICL_PROPNOTFOUND) 3304 model = NULL; 3305 else if (err != PICL_SUCCESS) 3306 return (err); 3307 3308 /* status */ 3309 err = picldiag_get_string_propval(ebush, OBP_PROP_STATUS, &status); 3310 if (err == PICL_PROPNOTFOUND) 3311 status = NULL; 3312 else if (err != PICL_SUCCESS) 3313 return (err); 3314 3315 /* 3316 * Display the data 3317 */ 3318 3319 /* name */ 3320 if (name != NULL) { 3321 log_printf("%-22s ", name); 3322 free(name); 3323 } else 3324 log_printf("%-22s ", "unknown"); 3325 /* model */ 3326 if (model != NULL) { 3327 log_printf("%-15s ", model); 3328 free(model); 3329 } else 3330 log_printf("%-15s ", "unknown"); 3331 /* status */ 3332 if (status == NULL) 3333 log_printf("%-15s ", "okay"); 3334 else { 3335 log_printf("%-15s ", status); 3336 free(status); 3337 } 3338 /* revision */ 3339 log_printf(" %-4d\n", id); 3340 3341 return (PICL_WALK_CONTINUE); 3342 } 3343 3344 /* 3345 * display asic revision id 3346 */ 3347 static int 3348 display_hw_revisions(picl_nodehdl_t plafh) 3349 { 3350 int err; 3351 3352 /* Print the header */ 3353 logprintf_header(dgettext(TEXT_DOMAIN, "HW Revisions"), 3354 DEFAULT_LINE_WIDTH); 3355 3356 log_printf("ASIC Revisions:\n"); 3357 log_printf("-----------------------------"); 3358 log_printf("--------------------------------------\n"); 3359 log_printf("Path Device"); 3360 log_printf(" Status Revision\n"); 3361 log_printf("-----------------------------"); 3362 log_printf("--------------------------------------\n"); 3363 3364 err = picl_walk_tree_by_class(plafh, NULL, NULL, asicrev_callback); 3365 if (err != PICL_SUCCESS) 3366 return (err); 3367 3368 err = picl_walk_tree_by_class(plafh, PICL_CLASS_EBUS, 3369 NULL, ebus_callback); 3370 if (err != PICL_SUCCESS) 3371 return (err); 3372 3373 log_printf("\n"); 3374 3375 err = picl_walk_tree_by_class(plafh, PICL_CLASS_DISPLAY, 3376 NULL, ffbconfig_callback); 3377 return (err); 3378 } 3379 3380 /* 3381 * find the options node and its powerfail_time prop 3382 * If found, display the list of latest powerfail. 3383 */ 3384 /* ARGSUSED */ 3385 static int 3386 options_callback(picl_nodehdl_t nodeh, void *arg) 3387 { 3388 time_t value; 3389 char *failtime; 3390 int err; 3391 3392 err = picldiag_get_string_propval(nodeh, PROP_POWERFAIL_TIME, 3393 &failtime); 3394 if (err == PICL_PROPNOTFOUND) 3395 return (PICL_WALK_TERMINATE); 3396 else if (err != PICL_SUCCESS) 3397 return (err); 3398 3399 value = (time_t)atoi(failtime); 3400 free(failtime); 3401 if (value == 0) 3402 return (PICL_WALK_TERMINATE); 3403 3404 log_printf(dgettext(TEXT_DOMAIN, "Most recent AC Power Failure:\n")); 3405 log_printf("=============================\n"); 3406 log_printf("%s", ctime(&value)); 3407 log_printf("\n"); 3408 return (PICL_WALK_TERMINATE); 3409 } 3410 3411 /* 3412 * display the OBP and POST prom revisions 3413 */ 3414 /* ARGSUSED */ 3415 static int 3416 flashprom_callback(picl_nodehdl_t flashpromh, void *arg) 3417 { 3418 picl_prophdl_t proph; 3419 picl_prophdl_t tblh; 3420 picl_prophdl_t rowproph; 3421 picl_propinfo_t pinfo; 3422 char *prom_version = NULL; 3423 char *obp_version = NULL; 3424 int err; 3425 3426 err = picl_get_propinfo_by_name(flashpromh, OBP_PROP_VERSION, 3427 &pinfo, &proph); 3428 if (err == PICL_PROPNOTFOUND) 3429 return (PICL_WALK_TERMINATE); 3430 else if (err != PICL_SUCCESS) 3431 return (err); 3432 3433 log_printf(dgettext(TEXT_DOMAIN, "System PROM revisions:\n")); 3434 log_printf("----------------------\n"); 3435 3436 /* 3437 * If it's a table prop, the first element is OBP revision 3438 * The second one is POST revision. 3439 * If it's a charstring prop, the value will be only OBP revision 3440 */ 3441 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 3442 prom_version = alloca(pinfo.size); 3443 if (prom_version == NULL) 3444 return (PICL_FAILURE); 3445 err = picl_get_propval(proph, prom_version, pinfo.size); 3446 if (err != PICL_SUCCESS) 3447 return (err); 3448 log_printf("%s\n", prom_version); 3449 } 3450 3451 if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */ 3452 return (PICL_WALK_TERMINATE); 3453 3454 err = picl_get_propval(proph, &tblh, pinfo.size); 3455 if (err != PICL_SUCCESS) 3456 return (err); 3457 3458 err = picl_get_next_by_row(tblh, &rowproph); 3459 if (err == PICL_SUCCESS) { 3460 /* get first row */ 3461 err = picl_get_propinfo(rowproph, &pinfo); 3462 if (err != PICL_SUCCESS) 3463 return (err); 3464 3465 prom_version = alloca(pinfo.size); 3466 if (prom_version == NULL) 3467 return (PICL_FAILURE); 3468 3469 err = picl_get_propval(rowproph, prom_version, pinfo.size); 3470 if (err != PICL_SUCCESS) 3471 return (err); 3472 log_printf("%s\n", prom_version); 3473 3474 /* get second row */ 3475 err = picl_get_next_by_col(rowproph, &rowproph); 3476 if (err == PICL_SUCCESS) { 3477 err = picl_get_propinfo(rowproph, &pinfo); 3478 if (err != PICL_SUCCESS) 3479 return (err); 3480 3481 obp_version = alloca(pinfo.size); 3482 if (obp_version == NULL) 3483 return (PICL_FAILURE); 3484 err = picl_get_propval(rowproph, obp_version, 3485 pinfo.size); 3486 if (err != PICL_SUCCESS) 3487 return (err); 3488 log_printf("%s\n", obp_version); 3489 } 3490 } 3491 3492 return (PICL_WALK_TERMINATE); 3493 } 3494 3495 static int 3496 display_system_info(int serrlog, int log_flag, picl_nodehdl_t rooth) 3497 { 3498 int err; 3499 picl_nodehdl_t plafh; 3500 picl_nodehdl_t frutreeh; 3501 3502 err = picldiag_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh); 3503 if (err != PICL_SUCCESS) 3504 return (err); 3505 3506 if (!log_flag) { 3507 err = display_platform_banner(plafh); 3508 if (err != PICL_SUCCESS) 3509 return (err); 3510 3511 err = display_system_clock(plafh); 3512 if (err != PICL_SUCCESS) 3513 return (err); 3514 3515 err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY, 3516 PICL_CLASS_MEMORY, memory_callback); 3517 if (err != PICL_SUCCESS) 3518 return (err); 3519 3520 err = display_cpu_info(plafh); 3521 if (err != PICL_SUCCESS) 3522 return (err); 3523 3524 err = display_io_device_info(plafh); 3525 if (err != PICL_SUCCESS) 3526 return (err); 3527 3528 err = display_memory_config(plafh); 3529 if (err != PICL_SUCCESS) 3530 return (err); 3531 3532 err = display_usb_devices(plafh); 3533 if (err != PICL_SUCCESS) 3534 return (err); 3535 } 3536 3537 if (serrlog) { 3538 err = picl_walk_tree_by_class(rooth, PICL_CLASS_OPTIONS, 3539 NULL, options_callback); 3540 if (err != PICL_SUCCESS) 3541 return (err); 3542 3543 err = display_envctrl_status(plafh); 3544 if (err != PICL_SUCCESS) 3545 return (err); 3546 3547 err = picldiag_get_node_by_name(rooth, PICL_NODE_FRUTREE, 3548 &frutreeh); 3549 if (err != PICL_SUCCESS) 3550 return (err); 3551 3552 err = display_fru_oper_status(frutreeh); 3553 if (err != PICL_SUCCESS) 3554 return (err); 3555 3556 err = display_hw_revisions(plafh); 3557 if (err != PICL_SUCCESS) 3558 return (err); 3559 3560 err = picl_walk_tree_by_class(plafh, PICL_CLASS_FLASHPROM, 3561 NULL, flashprom_callback); 3562 if (err != PICL_SUCCESS) 3563 return (err); 3564 } 3565 3566 return (PICL_SUCCESS); 3567 } 3568 3569 /* ARGSUSED */ 3570 int 3571 do_prominfo(int serrlog, char *pgname, int log_flag, int prt_flag) 3572 { 3573 int err; 3574 char *errstr; 3575 int done; 3576 picl_nodehdl_t rooth; 3577 3578 err = picl_initialize(); 3579 if (err != PICL_SUCCESS) { 3580 fprintf(stderr, EM_INIT_FAIL, picl_strerror(err)); 3581 exit(1); 3582 } 3583 3584 do { 3585 done = 1; 3586 err = picl_get_root(&rooth); 3587 if (err != PICL_SUCCESS) { 3588 fprintf(stderr, EM_GET_ROOT_FAIL, picl_strerror(err)); 3589 exit(1); 3590 } 3591 3592 err = display_system_info(serrlog, log_flag, rooth); 3593 3594 if ((err == PICL_STALEHANDLE) || (err == PICL_INVALIDHANDLE)) 3595 done = 0; 3596 } while (!done); 3597 3598 if (err != PICL_SUCCESS) { 3599 errstr = picl_strerror(err); 3600 fprintf(stderr, EM_PRTDIAG_FAIL); 3601 fprintf(stderr, "%s\n", errstr? errstr : " "); 3602 } 3603 3604 (void) picl_shutdown(); 3605 3606 return (0); 3607 } 3608