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