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