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