1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 
  26 /*
  27  * This program prints the diagnostics of Sanibel system. It
  28  * also prints other miscellaneous information about watchdog, temperature
  29  * of CPU sensor, firmware versions of SMC and, micro controller role
  30  * etc. The basic sources of output is PICL, and  SMC.
  31  */
  32 
  33 /* includes */
  34 
  35 #include <stdio.h>
  36 #include <strings.h>
  37 #include <ctype.h>
  38 #include <string.h>
  39 #include <time.h>
  40 #include <dirent.h>
  41 #include <sys/param.h>
  42 #include <picl.h>
  43 #include <libintl.h>
  44 #include <sys/types.h>
  45 #include <sys/stat.h>
  46 #include <sys/systeminfo.h>
  47 #include <sys/openpromio.h>
  48 #include <fcntl.h>
  49 #include <smc_if.h>
  50 #include <stropts.h>
  51 #include <alloca.h>
  52 #include <errno.h>
  53 #include <poll.h>
  54 #include <stdlib.h>
  55 #include <unistd.h>
  56 #include <kstat.h>
  57 #include <sys/utsname.h>
  58 #include <stddef.h>
  59 #include <pdevinfo.h>
  60 #include <display_sun4u.h>
  61 #include <libprtdiag.h>
  62 #include <smclib.h>
  63 #include <smc_commands.h>
  64 #include <picldefs.h>
  65 
  66 /* #defines for the PICL library API usage and local static variables */
  67 #define PD_CPCI_SLOT_TYPE       "cpci"
  68 #define PD_PCI_SLOT_TYPE        "pci"
  69 #define PD_PRESENT              1
  70 #define PD_BLANK                " "
  71 #define PD_ENABLED              1
  72 #define PD_DISABLED             0
  73 #define SNOWBIRD                "SUNW,Netra-CP2300"
  74 #define CHASSIS_NODE_NAME       "chassis"
  75 
  76 /* #defines for the SMC and IPMI commands */
  77 #define POLL_TIMEOUT                            10000
  78 #define DEFAULT_SEQN                            0xff
  79 
  80 /* SMC driver */
  81 #define PD_SMC_DRV_PATH                 "/dev/ctsmc"
  82 
  83 /* Constants */
  84 #define OBP_PROP_BANNER_NAME            "banner-name"
  85 #define OBP_PROP_CLOCK_FREQ             "clock-frequency"
  86 
  87 
  88 
  89 /* #defines for local usage */
  90 #define PD_SUCCESS      0
  91 #define PD_FAILURE      1
  92 #define PD_INTERNAL_FAILURE     2
  93 #define PD_ERROR        -1
  94 
  95 /*      static global variables */
  96 static int pd_print_option;
  97 static uint8_t pd_smc_glbl_enabl_rsp[2];
  98 static boolean_t pd_hdr_prt             = B_TRUE;
  99 static int pd_smc_fd                    = 0;
 100 
 101 
 102 /* function declarations used in this program */
 103 static uint32_t pd_check_for_snowbird();
 104 static uint32_t pd_prt_snowbird_diag();
 105 static uint32_t pd_check_cpu_health();
 106 static uint32_t pd_check_tty_debug_mode();
 107 static uint32_t pd_query_SMC_firmware_version();
 108 static uint32_t pd_check_slots();
 109 int32_t pd_prt_slot_info(picl_nodehdl_t, void *);
 110 int do_prominfo(int syserrlog, char *pname, int log_flag, int prt_flag);
 111 static uint32_t pd_query_watchdog_state();
 112 int pd_check_wd_state(picl_nodehdl_t, void *);
 113 static uint32_t pd_print_fruinfo_hdr();
 114 static uint32_t pd_print_device_info(int);
 115 static uint32_t pd_get_role_information();
 116 static uint32_t pd_get_message_flags();
 117 static uint32_t pd_get_reset_mode();
 118 static uint32_t pd_get_sensor_reading();
 119 static uint32_t pd_get_sensor_threshold();
 120 static uint32_t pd_prt_cpci_condition(picl_nodehdl_t nodeh);
 121 static uint32_t pd_check_location_parent(picl_nodehdl_t nodeh);
 122 static uint64_t
 123 picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret);
 124 static int picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq);
 125 static int display_system_clock(picl_nodehdl_t plafh);
 126 
 127 /*
 128  * return the value of the uint prop
 129  */
 130 static uint64_t
 131 picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
 132 {
 133         int             err;
 134         picl_prophdl_t  proph;
 135         picl_propinfo_t pinfo;
 136         uint8_t         uint8v;
 137         uint16_t        uint16v;
 138         uint32_t        uint32v;
 139         uint64_t        uint64v;
 140 
 141         err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
 142         if (err != PICL_SUCCESS) {
 143                 *ret = err;
 144                 return (0);
 145         }
 146 
 147         /*
 148          * If it is not an int or uint prop, return failure
 149          */
 150         if ((pinfo.type != PICL_PTYPE_INT) &&
 151             (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
 152                 *ret = PICL_FAILURE;
 153                 return (0);
 154         }
 155 
 156         /* uint prop */
 157 
 158         switch (pinfo.size) {
 159         case sizeof (uint8_t):
 160                 err = picl_get_propval(proph, &uint8v, sizeof (uint8v));
 161                 *ret = err;
 162                 return (uint8v);
 163         case sizeof (uint16_t):
 164                 err = picl_get_propval(proph, &uint16v, sizeof (uint16v));
 165                 *ret = err;
 166                 return (uint16v);
 167         case sizeof (uint32_t):
 168                 err = picl_get_propval(proph, &uint32v, sizeof (uint32v));
 169                 *ret = err;
 170                 return (uint32v);
 171         case sizeof (uint64_t):
 172                 err = picl_get_propval(proph, &uint64v, sizeof (uint64v));
 173                 *ret = err;
 174                 return (uint64v);
 175         default:        /* not supported size */
 176                 *ret = PICL_FAILURE;
 177                 return (0);
 178         }
 179 }
 180 
 181 
 182 
 183 /*
 184  * get the clock frequency
 185  */
 186 static int
 187 picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq)
 188 {
 189 #define ROUND_TO_MHZ(x) (((x) + 500000)/ 1000000)
 190 
 191         int             err;
 192         uint64_t        clk_freq;
 193 
 194         clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err);
 195         if (err != PICL_SUCCESS)
 196                 return (err);
 197 
 198         *freq = ROUND_TO_MHZ(clk_freq);
 199 
 200         return (PICL_SUCCESS);
 201 }
 202 
 203 
 204 /*
 205  * display the clock frequency
 206  */
 207 static int
 208 display_system_clock(picl_nodehdl_t plafh)
 209 {
 210         uint32_t        system_clk;
 211         int             err;
 212 
 213         err = picldiag_get_clock_freq(plafh, &system_clk);
 214         if (err != PICL_SUCCESS)
 215                 return (err);
 216 
 217         log_printf(dgettext(TEXT_DOMAIN,
 218             "System clock frequency: %d MHZ\n"), system_clk);
 219 
 220         return (PICL_SUCCESS);
 221 }
 222 
 223 
 224 /*
 225  * get the value by the property name of the string prop
 226  * Caller must free the outbuf
 227  */
 228 static int
 229 picldiag_get_string_propval(picl_nodehdl_t modh, char *prop_name, char **outbuf)
 230 {
 231         int             err;
 232         picl_prophdl_t  proph;
 233         picl_propinfo_t pinfo;
 234         char            *prop_value;
 235 
 236         err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
 237         if (err != PICL_SUCCESS)
 238                 return (err);
 239 
 240         /*
 241          * If it is not a string prop, return NULL
 242          */
 243         if (pinfo.type != PICL_PTYPE_CHARSTRING)
 244                 return (PICL_FAILURE);
 245 
 246         prop_value = malloc(pinfo.size);
 247         if (prop_value == NULL)
 248                 return (PICL_FAILURE);
 249 
 250         err = picl_get_propval(proph, prop_value, pinfo.size);
 251         if (err != PICL_SUCCESS) {
 252                 free(prop_value);
 253                 return (err);
 254         }
 255 
 256         *outbuf = prop_value;
 257         return (PICL_SUCCESS);
 258 }
 259 
 260 
 261 
 262 /*
 263  * display platform banner
 264  */
 265 static int
 266 display_platform_banner(picl_nodehdl_t plafh)
 267 {
 268         char    *platform;
 269         char    *banner_name;
 270         int     err;
 271 
 272         /*
 273          * get PICL_PROP_MACHINE and PICL_PROP_BANNER_NAME
 274          */
 275         log_printf(dgettext(TEXT_DOMAIN,
 276             "System Configuration: Oracle Corporation "), 0);
 277         err = picldiag_get_string_propval(plafh, PICL_PROP_MACHINE,
 278             &platform);
 279         if (err != PICL_SUCCESS)
 280                 return (err);
 281         log_printf(" %s", platform, 0);
 282         free(platform);
 283 
 284         err = picldiag_get_string_propval(plafh, OBP_PROP_BANNER_NAME,
 285             &banner_name);
 286         if (err != PICL_SUCCESS)
 287                 return (err);
 288         log_printf(" %s", banner_name, 0);
 289         free(banner_name);
 290 
 291         log_printf("\n", 0);
 292         return (PICL_SUCCESS);
 293 }
 294 
 295 /*
 296  * search children to get the node by the nodename
 297  */
 298 static int
 299 picldiag_get_node_by_name(picl_nodehdl_t rooth, char *name,
 300     picl_nodehdl_t *nodeh)
 301 {
 302         picl_nodehdl_t  childh;
 303         int             err;
 304         char            *nodename;
 305 
 306         nodename = alloca(strlen(name) + 1);
 307         if (nodename == NULL)
 308                 return (PICL_FAILURE);
 309 
 310         err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
 311             sizeof (picl_nodehdl_t));
 312 
 313         while (err == PICL_SUCCESS) {
 314                 err = picl_get_propval_by_name(childh, PICL_PROP_NAME,
 315                     nodename, (strlen(name) + 1));
 316                 if (err != PICL_SUCCESS) {
 317                         err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
 318                             &childh, sizeof (picl_nodehdl_t));
 319                         continue;
 320                 }
 321 
 322                 if (strcmp(nodename, name) == 0) {
 323                         *nodeh = childh;
 324                         return (PICL_SUCCESS);
 325                 }
 326 
 327                 err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
 328                     &childh, sizeof (picl_nodehdl_t));
 329         }
 330 
 331         return (err);
 332 }
 333 
 334 
 335 /*
 336  * This routine is invoked when prtdiag starts execution. It prints
 337  * system configuration, memory size, initializes PICL and acts as
 338  * a driver routine for prtdiag output for Snowbird.
 339  */
 340 /* ARGSUSED */
 341 int
 342 do_prominfo(int syserrlog, char *pname, int log_flag, int prt_flag)
 343 {
 344 
 345         struct mem_total memory_total;  /*      total memory in system  */
 346         struct grp_info grps;
 347         uint8_t status = PD_SUCCESS;
 348         picl_nodehdl_t rooth;
 349         picl_nodehdl_t plafh;
 350         struct system_kstat_data *kstats = NULL;
 351         Sys_tree *tree = NULL;
 352 
 353         sys_clk = -1;
 354         pd_print_option = syserrlog;
 355 
 356         if ((status = picl_initialize()) != PICL_SUCCESS) {
 357                 log_printf("prtdiag: failed to initialize the PICL\n", 0);
 358                 exit(1);
 359         }
 360 
 361         if ((status = picl_get_root(&rooth)) != PICL_SUCCESS) {
 362                 log_printf("prtdiag: failed\n", 0);
 363                 exit(1);
 364         }
 365 
 366         status = picldiag_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh);
 367         if (status != PICL_SUCCESS)
 368                 return (status);
 369 
 370         if (!log_flag) {
 371 
 372                 status = display_platform_banner(plafh);
 373                 if (status != PICL_SUCCESS)
 374                         return (status);
 375 
 376                 status = display_system_clock(plafh);
 377                 if (status != PICL_SUCCESS)
 378                         return (status);
 379 
 380                 /* display the memory Size */
 381                 display_memorysize(tree, kstats, &grps, &memory_total);
 382         }
 383 
 384         if ((pd_smc_fd = open(PD_SMC_DRV_PATH, O_RDWR)) == -1)
 385                 return (PD_FAILURE);
 386 
 387         if ((status = pd_check_for_snowbird()) != PD_SUCCESS)
 388                 return (status);
 389 
 390         if ((status = pd_prt_snowbird_diag()) != PD_SUCCESS)
 391                 return (status);
 392 
 393         (void) close(pd_smc_fd);
 394 
 395         if (picl_shutdown() != PICL_SUCCESS)
 396                 return (PD_INTERNAL_FAILURE);
 397 
 398         return (PD_SUCCESS);
 399 
 400 }
 401 
 402 /*
 403  * This routine prints out the platform name.
 404  */
 405 
 406 static uint32_t
 407 pd_check_for_snowbird()
 408 {
 409 
 410         char si_platform[30];
 411 
 412         if (sysinfo(SI_PLATFORM, si_platform, sizeof (si_platform)) == -1) {
 413                 return (PD_FAILURE);
 414         }
 415         /* is it a Snowbird? */
 416         if (strcmp(si_platform, SNOWBIRD) != 0)
 417                 return (PD_FAILURE);
 418 
 419         log_printf("platform Type : %s\n", si_platform, 0);
 420         return (PD_SUCCESS);
 421 
 422 }
 423 
 424 
 425 /*
 426  * Driver routine for satellite specific output. This is also used by
 427  * host driver routine as all satellite information is printed by host.
 428  * It also prints some host specific information for formatting purposes
 429  */
 430 
 431 static uint32_t
 432 pd_prt_snowbird_diag()
 433 {
 434         uint8_t status = PD_SUCCESS;
 435         if ((status = pd_check_cpu_health()) != PD_SUCCESS) {
 436                 return (status);
 437         }
 438         if (pd_print_option) {
 439 
 440                 log_printf(
 441                     "\n %11s Other Miscellaneous Information \n",
 442                     PD_BLANK, 0);
 443                 log_printf(
 444                     "%12s ------------------------------- \n",
 445                     PD_BLANK, 0);
 446 
 447                 if ((status = pd_get_role_information()) != PD_SUCCESS) {
 448                         return (status);
 449                 }
 450 
 451                 if (pd_smc_glbl_enabl_rsp[1] & 0x10) {
 452                         log_printf(
 453                             "IPMI Response Notification\t\tEnabled\n", 0);
 454                 } else {
 455                         log_printf(
 456                             "IPMI Response Notification\t\tDisabled\n", 0);
 457                 }
 458                 if ((status = pd_query_SMC_firmware_version()) != PD_SUCCESS) {
 459                         return (status);
 460                 }
 461 
 462                 if ((status = pd_check_tty_debug_mode()) != PD_SUCCESS) {
 463                         return (status);
 464                 }
 465 
 466                 if ((status = pd_get_reset_mode()) != PD_SUCCESS) {
 467                         return (status);
 468                 }
 469 
 470                 if ((status = pd_get_message_flags()) != PD_SUCCESS) {
 471                         return (status);
 472                 }
 473 
 474                 if ((status = pd_query_watchdog_state()) != PD_SUCCESS) {
 475                         return (status);
 476                 }
 477 
 478                 if ((status = pd_get_sensor_reading()) != PD_SUCCESS) {
 479                         return (status);
 480                 }
 481 
 482                 if ((status = pd_get_sensor_threshold()) != PD_SUCCESS) {
 483                         return (status);
 484                 }
 485 
 486         }
 487         return (status);
 488 
 489 }
 490 
 491 /*
 492  * This routine prints the mode in which SMC is running. It uses the
 493  * response from SMC global enables to determine the mode
 494  */
 495 static uint32_t
 496 pd_check_tty_debug_mode()
 497 {
 498 
 499         if (pd_smc_glbl_enabl_rsp[1] & 0x20) {
 500                 log_printf("SMC verbose mode\t\t\tON\n", 0);
 501         } else {
 502                 log_printf("SMC verbose mode\t\t\tOFF\n", 0);
 503         }
 504 
 505         return (PD_SUCCESS);
 506 }
 507 
 508 /* This routine prints SMC f/w version */
 509 static uint32_t
 510 pd_query_SMC_firmware_version()
 511 {
 512 
 513         sc_reqmsg_t req_pkt;
 514         sc_rspmsg_t rsp_pkt;
 515         uint8_t ver, rev, bldrev;
 516 
 517 
 518         smc_init_smc_msg(&req_pkt, SMC_QUERY_FIRMWARE_VERSION,
 519             DEFAULT_SEQN, 0);
 520         smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
 521         ver = (rsp_pkt.data[0] & 0xf0) >> 4;
 522         rev = rsp_pkt.data[0] & 0x0f;
 523         bldrev = rsp_pkt.data[2] & 0x3f;
 524 
 525         log_printf("SMC f/w version is\t\t\t%d.%d.%d\n", ver, rev, bldrev, 0);
 526 
 527         return (PD_SUCCESS);
 528 
 529 }
 530 
 531 /*
 532  * This routine checks CPU's health by using SMC self test results command
 533  * It acts as driver routine for printing cPCI slot information
 534  */
 535 static uint32_t
 536 pd_check_cpu_health()
 537 {
 538 
 539         sc_reqmsg_t req_pkt;
 540         sc_rspmsg_t rsp_pkt;
 541         uint8_t dev_id = 0x1f;
 542 #ifdef DEBUG
 543         uint8_t i2c_chk = 0x40;
 544 #endif
 545         uint8_t mem_test = 0x20;
 546 
 547         smc_init_smc_msg(&req_pkt, SMC_GET_SMC_SELF_TEST_RESULT,
 548             DEFAULT_SEQN, 0);
 549         smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
 550 
 551         dev_id = rsp_pkt.data[0] & dev_id;
 552 
 553 #ifdef DEBUG
 554         if (rsp_pkt.data[0] & i2c_chk) {
 555                 pd_print_device_info(dev_id);
 556         }
 557 #endif
 558         if (rsp_pkt.data[0] & mem_test) {
 559                 pd_print_device_info(dev_id);
 560         }
 561         return (pd_check_slots());
 562 
 563 }
 564 
 565 /*
 566  * This routine decodes error message for CPU failures and prints details
 567  * of the failure
 568  */
 569 static uint32_t
 570 pd_print_device_info(int dev_id)
 571 {
 572 
 573         switch (dev_id) {
 574                 case 1:
 575                         log_printf("Mux Philip 9540\n", 0);
 576                         break;
 577                 case 2:
 578                         log_printf("cpu temp max1617\n", 0);
 579                         break;
 580                 case 3:
 581                         log_printf("pmc temp max 1617\n", 0);
 582                         break;
 583                 case 4:
 584                         log_printf("MB HS temp max 1617\n", 0);
 585                         break;
 586                 case 5:
 587                         log_printf("MB mem temp max1617\n", 0);
 588                         break;
 589                 case 6:
 590                         log_printf("MB gpio Philip8574\n", 0);
 591                         break;
 592                 case 7:
 593                         log_printf("MB Fru ID ID i2c eep\n", 0);
 594                         break;
 595                 case 8:
 596                         log_printf("MB enet ID ID i2d eep\n", 0);
 597                         break;
 598                 case 9:
 599                         log_printf("MB gpio Philip8574A\n", 0);
 600                         break;
 601                 case 10:
 602                         log_printf("SDRAM mod1 temp max1617\n", 0);
 603                         break;
 604                 case 11:
 605                         log_printf("SDRAM mod ID  ID i2c eep\n", 0);
 606                         break;
 607                 case 12:
 608                         log_printf("SDRAM mod2 temp max1617\n", 0);
 609                         break;
 610                 case 13:
 611                         log_printf("SDRAM mod ID  ID i2c eep\n", 0);
 612                         break;
 613                 case 14:
 614                         log_printf("Power mod temp ds1721\n", 0);
 615                         break;
 616                 case 15:
 617                         log_printf("Power mod gpio Philip 8574\n", 0);
 618                         break;
 619                 case 16:
 620                         log_printf("Power mod ID eep ST M24C01\n", 0);
 621                         break;
 622                 case 17:
 623                         log_printf("SMC ID i2c eep\n", 0);
 624                         break;
 625 
 626                 default:
 627                         log_printf("device id unknown\n", 0);
 628                         break;
 629 
 630         }
 631 
 632         return (PD_SUCCESS);
 633 
 634 }
 635 
 636 /*
 637  * This routine walks PICL tree by "Location" class and calls prt_slot_info
 638  * routine to print the slot information
 639  */
 640 
 641 /*ARGSUSED*/
 642 static uint32_t
 643 pd_check_slots()
 644 {
 645 
 646         picl_nodehdl_t nodeh;
 647         char *c_args = NULL;
 648 
 649         if (picl_get_root(&nodeh) != PICL_SUCCESS)
 650                 return (PD_INTERNAL_FAILURE);
 651 
 652 
 653         if (picl_walk_tree_by_class(nodeh, PICL_CLASS_LOCATION,
 654             (void *)c_args, pd_prt_slot_info) != PICL_SUCCESS) {
 655                 return (PD_INTERNAL_FAILURE);
 656         }
 657 
 658         return (PD_SUCCESS);
 659 
 660 }
 661 
 662 
 663 /*ARGSUSED*/
 664 int32_t
 665 
 666 pd_prt_slot_info(picl_nodehdl_t nodeh, void *c_args)
 667 {
 668 
 669         char *valbuf;
 670         char label_txt[30];
 671         int unit_no = -1, ctr = 0;
 672         picl_nodehdl_t childh;
 673         picl_propinfo_t propinfo;
 674         picl_prophdl_t proph;
 675 
 676         /* if not immediate child of "chassis" node, ignore it */
 677         if (pd_check_location_parent(nodeh) != PD_SUCCESS)
 678                 return (PD_INTERNAL_FAILURE);
 679 
 680 
 681         /* get the label on the location */
 682         if (picl_get_prop_by_name(nodeh, PICL_PROP_LABEL,
 683             &proph) != PICL_SUCCESS)
 684                 return (PD_INTERNAL_FAILURE);
 685 
 686         if (picl_get_propinfo(proph, &propinfo) != PICL_SUCCESS)
 687                 return (PD_INTERNAL_FAILURE);
 688 
 689         valbuf = (char *) malloc(sizeof (char) * (propinfo.size));
 690         if (valbuf == NULL)
 691                 return (PD_INTERNAL_FAILURE);
 692 
 693         if (picl_get_propval(proph, (void *)valbuf, propinfo.size)
 694             != PICL_SUCCESS) {
 695                 free(valbuf);
 696                 return (PD_INTERNAL_FAILURE);
 697         }
 698 
 699         while (valbuf[ctr] != ' ' && valbuf[ctr] != NULL) {
 700                 label_txt[ctr] = valbuf[ctr];
 701                 ++ctr;
 702         }
 703 
 704         label_txt[ctr++] = '\0';
 705 
 706         if (valbuf[ctr] != NULL) {
 707                 unit_no = atoi(valbuf+ctr);
 708         }
 709 
 710         free(valbuf);
 711 
 712         /* get the slot type for the location */
 713         if (picl_get_prop_by_name(nodeh, PICL_PROP_SLOT_TYPE,
 714             &proph) != PICL_SUCCESS)
 715                 return (PD_INTERNAL_FAILURE);
 716 
 717         if (picl_get_propinfo(proph, & propinfo) != PICL_SUCCESS)
 718                 return (PD_INTERNAL_FAILURE);
 719 
 720         valbuf = (char *) malloc(sizeof (char) * (propinfo.size));
 721         if (valbuf == NULL)
 722                 return (PD_INTERNAL_FAILURE);
 723 
 724         if (picl_get_propval(proph, (void *)valbuf,
 725             propinfo.size) != PICL_SUCCESS) {
 726                 free(valbuf);
 727                 return (PD_INTERNAL_FAILURE);
 728         }
 729 
 730         if ((strcmp(valbuf, PD_CPCI_SLOT_TYPE) == 0) ||
 731             (strcmp(valbuf, PD_PCI_SLOT_TYPE) == 0)) {
 732                 (void) pd_print_fruinfo_hdr();
 733                 log_printf("\n%s         ", label_txt, 0);
 734 
 735         /* For Snowbird no unit number is present on the label */
 736                 unit_no = 1;
 737                 log_printf(" %d       Yes      cPSB IO Slot\n", unit_no, 0);
 738 
 739                 if (picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
 740                     &childh, sizeof (childh)) == PICL_SUCCESS) {
 741                         pd_prt_cpci_condition(childh);
 742                 }
 743                 /* For Snowbird auto configuration is always enabled */
 744                 log_printf("%29s Properties:\n", PD_BLANK, 0);
 745                 log_printf("%31s auto-config = enabled\n", PD_BLANK, 0);
 746         }
 747 
 748 
 749         free(valbuf);
 750         return (PD_SUCCESS);
 751 
 752 }
 753 
 754 
 755 
 756 static uint32_t
 757 pd_print_fruinfo_hdr()
 758 {
 759 
 760         log_printf(
 761             "\n %19s FRU Information \n",
 762             PD_BLANK, 0);
 763         log_printf(
 764             "%11s ------------------------------------------------\n",
 765             PD_BLANK, 0);
 766 
 767         log_printf(dgettext(TEXT_DOMAIN,
 768             "FRU         FRU    FRU      Miscellaneous\n"), 0);
 769         log_printf(dgettext(TEXT_DOMAIN,
 770             "Type        Unit#  Present  Information\n"), 0);
 771         log_printf("----        -----  -------", 0);
 772         log_printf("  --------------------------------\n", 0);
 773         return (PD_SUCCESS);
 774 
 775 }
 776 
 777 static uint32_t
 778 pd_check_location_parent(picl_nodehdl_t nodeh)
 779 {
 780 
 781         picl_nodehdl_t parenth;
 782         char *prop_name;
 783 
 784         if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
 785             &parenth, sizeof (parenth)) != PICL_SUCCESS) {
 786                 return (PD_FAILURE);
 787         }
 788 
 789         prop_name = (char *) malloc(sizeof (char) * PICL_PROPNAMELEN_MAX);
 790         if (prop_name == NULL) {
 791                 return (PD_FAILURE);
 792         }
 793 
 794         if (picl_get_propval_by_name(parenth, PICL_PROP_NAME, (void *)prop_name,
 795             PICL_PROPNAMELEN_MAX) != PICL_SUCCESS) {
 796                 free(prop_name);
 797                 return (PD_FAILURE);
 798         }
 799 
 800         if (strcmp(prop_name, CHASSIS_NODE_NAME) == 0) {
 801                 free(prop_name);
 802                 return (PD_SUCCESS);
 803         } else {
 804                 free(prop_name);
 805                 return (PD_FAILURE);
 806         }
 807 
 808 }
 809 
 810 
 811 /*ARGSUSED*/
 812 static uint32_t
 813 pd_query_watchdog_state()
 814 {
 815 
 816         picl_nodehdl_t nodehandle;
 817         char *c_args = NULL;
 818 
 819         if (picl_get_root(&nodehandle) != PICL_SUCCESS) {
 820                 return (PD_INTERNAL_FAILURE);
 821         }
 822 
 823         if (picl_walk_tree_by_class(nodehandle, PICL_CLASS_WATCHDOG_TIMER,
 824             (void *)c_args, pd_check_wd_state) != PICL_SUCCESS)
 825                 return (PD_INTERNAL_FAILURE);
 826 
 827         return (PD_SUCCESS);
 828 
 829 }
 830 
 831 /*ARGSUSED*/
 832 int
 833 pd_check_wd_state(picl_nodehdl_t nodeh, void *c_args)
 834 {
 835 
 836         char *prop_name, *valbuf;
 837         picl_propinfo_t propinfo;
 838         picl_prophdl_t proph;
 839 
 840         prop_name = (char *) malloc(sizeof (char) * PICL_PROPNAMELEN_MAX);
 841         if (prop_name == NULL) {
 842                 return (PICL_WALK_TERMINATE);
 843         }
 844 
 845         if (picl_get_propval_by_name(nodeh, PICL_PROP_NAME,
 846             (void *)prop_name, PICL_PROPNAMELEN_MAX) != PICL_SUCCESS) {
 847                 free(prop_name);
 848                 return (PICL_WALK_TERMINATE);
 849         }
 850 
 851         if ((picl_get_prop_by_name(nodeh, PICL_PROP_STATE,
 852             &proph)) != PICL_SUCCESS) {
 853                 free(prop_name);
 854                 return (PICL_WALK_TERMINATE);
 855         }
 856 
 857         if ((picl_get_propinfo(proph, &propinfo)) != PICL_SUCCESS) {
 858                 free(prop_name);
 859                 return (PICL_WALK_TERMINATE);
 860         }
 861 
 862         valbuf = (char *) malloc(sizeof (char) * (propinfo.size));
 863         if (valbuf == NULL) {
 864                 free(prop_name);
 865                 return (PICL_WALK_TERMINATE);
 866         }
 867 
 868         if ((picl_get_propval(proph, (void *)valbuf,
 869             propinfo.size)) != PICL_SUCCESS) {
 870                 free(valbuf);
 871                 free(prop_name);
 872                 return (PICL_WALK_TERMINATE);
 873         }
 874 
 875         if (pd_hdr_prt) {
 876                 log_printf("\n       Watch Dog Status \n", 0);
 877                 log_printf("       ---------------- \n", 0);
 878                 log_printf("Node                      Status\n", 0);
 879                 log_printf("----                      ------\n", 0);
 880                 pd_hdr_prt = B_FALSE;
 881         }
 882 
 883         log_printf("%s           ", prop_name, 0);
 884         log_printf("%s\n", valbuf, 0);
 885 
 886         free(prop_name);
 887         free(valbuf);
 888         return (PICL_WALK_CONTINUE);
 889 
 890 }
 891 
 892 
 893 static uint32_t
 894 pd_get_role_information()
 895 {
 896 
 897         sc_reqmsg_t req_pkt;
 898         sc_rspmsg_t rsp_pkt;
 899         uint8_t usparc_role;
 900 
 901         smc_init_smc_msg(&req_pkt, SMC_GET_ROLE_INFO,
 902             DEFAULT_SEQN, 0);
 903         smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
 904         usparc_role = rsp_pkt.data[1];
 905 
 906         log_printf(dgettext(TEXT_DOMAIN,
 907             "UltraSPARC Host Role\t\t\t"), 0);
 908         if (usparc_role & 0x80) {
 909                 log_printf(
 910                     dgettext(TEXT_DOMAIN,
 911                     "System Board Computer (SBC)\n"), 0);
 912         }
 913         if (usparc_role & 0x40) {
 914                 log_printf(dgettext(TEXT_DOMAIN,
 915                     "Standby System Board Computer (Standby SBC)\n"), 0);
 916         }
 917         if (usparc_role & 0x20) {
 918                 log_printf(dgettext(TEXT_DOMAIN,
 919                 "Alternate System Board Computer (Alternate SBC)\n"), 0);
 920         }
 921         if (usparc_role & 0x10) {
 922                 log_printf(dgettext(TEXT_DOMAIN,
 923                     "Satellite Board Computer (SAT)\n"), 0);
 924         }
 925         return (PD_SUCCESS);
 926 
 927 }
 928 
 929 
 930 static uint32_t
 931 pd_get_message_flags()
 932 {
 933 
 934         sc_reqmsg_t req_pkt;
 935         sc_rspmsg_t rsp_pkt;
 936 
 937         smc_init_smc_msg(&req_pkt, SMC_GET_MESSAGE_FLAGS,
 938             DEFAULT_SEQN, 0);
 939         smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
 940 
 941         if (rsp_pkt.data[0] & 0x01) {
 942                 log_printf("Messages Available in queue Recieving\n", 0);
 943         } else {
 944                 log_printf("No messages in queue for Recieving\n", 0);
 945         }
 946 
 947         return (PD_SUCCESS);
 948 
 949 
 950 }
 951 
 952 
 953 
 954 static uint32_t
 955 pd_get_reset_mode()
 956 {
 957 
 958         sc_reqmsg_t req_pkt;
 959         sc_rspmsg_t rsp_pkt;
 960 
 961 
 962         smc_init_smc_msg(&req_pkt, SMC_GET_CONFIG_BLOCK,
 963             DEFAULT_SEQN,  0);
 964         smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
 965 
 966         log_printf("Reset Mode\t\t\t\t%x \n", rsp_pkt.data[2], 0);
 967 
 968         return (PD_SUCCESS);
 969 
 970 }
 971 
 972 
 973 static uint32_t
 974 pd_get_sensor_reading()
 975 {
 976 
 977 
 978         sc_reqmsg_t req_pkt;
 979         sc_rspmsg_t rsp_pkt;
 980 
 981         req_pkt.data[0] = 0x0e;
 982 
 983         smc_init_smc_msg(&req_pkt, SMC_SENSOR_READING_GET,
 984             DEFAULT_SEQN, 1);
 985         smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
 986         log_printf("\nCPU Node Temperature Information\n", PD_BLANK, 0);
 987         log_printf("--------------------------------\n", PD_BLANK, 0);
 988         log_printf("Temperature Reading: %d\n\n", rsp_pkt.data[0], 0);
 989 
 990         return (PD_SUCCESS);
 991 
 992 }
 993 
 994 
 995 static uint32_t
 996 pd_get_sensor_threshold()
 997 {
 998 
 999 
1000         sc_reqmsg_t req_pkt;
1001         sc_rspmsg_t rsp_pkt;
1002         uint8_t thres_mask;
1003         req_pkt.data[0] = 0x0e;
1004 
1005         smc_init_smc_msg(&req_pkt, SMC_SENSOR_THRESHOLD_GET,
1006             DEFAULT_SEQN,  1);
1007         smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
1008         log_printf("Critical Threshold Information\n", 0);
1009         log_printf("------------------------------\n", 0);
1010 
1011         thres_mask = rsp_pkt.data[0];
1012 
1013         if (thres_mask & 0x20) {
1014                 log_printf("High Power-Off Threshold %9s", PD_BLANK, 0);
1015                 if (rsp_pkt.data[6] & 0x80) {
1016                         log_printf("-%d\n",
1017                             (int)((uint8_t)~rsp_pkt.data[6] + 1), 0);
1018                 } else {
1019                         log_printf(" %d\n", rsp_pkt.data[6], 0);
1020                 }
1021         }
1022 
1023         if (thres_mask & 0x10) {
1024                 log_printf("High Shutdown Threshold %10s", PD_BLANK, 0);
1025                 if (rsp_pkt.data[5] & 0x80) {
1026                         log_printf("-%d\n",
1027                             (int)((uint8_t)~rsp_pkt.data[5] + 1), 0);
1028                 } else {
1029                         log_printf(" %d\n", rsp_pkt.data[5], 0);
1030                 }
1031         }
1032 
1033 
1034         if (thres_mask & 0x08) {
1035                 log_printf("High Warning Threshold %11s", PD_BLANK, 0);
1036                 if (rsp_pkt.data[4] & 0x80) {
1037                         log_printf("-%d\n",
1038                             (int)((uint8_t)~rsp_pkt.data[4] + 1), 0);
1039                 } else {
1040                         log_printf(" %d\n", rsp_pkt.data[4], 0);
1041                 }
1042         }
1043 
1044         if (thres_mask & 0x04) {
1045                 log_printf("Low Power Off Threshold %10s", PD_BLANK, 0);
1046                 if (rsp_pkt.data[3] & 0x80) {
1047                         log_printf("-%d\n",
1048                             (int)((uint8_t)~rsp_pkt.data[3] + 1), 0);
1049                 } else {
1050                         log_printf(" %d\n", rsp_pkt.data[3], 0);
1051                 }
1052         }
1053 
1054         if (thres_mask & 0x02) {
1055                 log_printf("Low Shutdown Threshold %11s", PD_BLANK, 0);
1056                 if (rsp_pkt.data[2] & 0x80) {
1057                         log_printf("-%d\n",
1058                             (int)((uint8_t)~rsp_pkt.data[2] + 1), 0);
1059                 } else {
1060                         log_printf(" %d\n", rsp_pkt.data[2], 0);
1061                 }
1062         }
1063 
1064         if (thres_mask & 0x01) {
1065                 log_printf("Low Warning Threshold %12s", PD_BLANK, 0);
1066                 if (rsp_pkt.data[1] & 0x80) {
1067                         log_printf("-%d\n",
1068                             (int)((uint8_t)~rsp_pkt.data[1] + 1), 0);
1069                 } else {
1070                         log_printf(" %d\n", rsp_pkt.data[1], 0);
1071                 }
1072         }
1073 
1074         return (PD_SUCCESS);
1075 
1076 }
1077 
1078 
1079 
1080 static uint32_t
1081 pd_prt_cpci_condition(picl_nodehdl_t nodeh)
1082 {
1083 
1084         picl_propinfo_t propinfo;
1085         picl_prophdl_t proph;
1086         char *valbuf;
1087 
1088 
1089         if (picl_get_prop_by_name(nodeh, PICL_PROP_CONDITION,
1090             &proph) != PICL_SUCCESS) {
1091                 return (PD_FAILURE);
1092         }
1093 
1094         if (picl_get_propinfo(proph, &propinfo) != PICL_SUCCESS) {
1095                 return (PD_FAILURE);
1096         }
1097 
1098         valbuf = (char *) malloc(sizeof (char) * (propinfo.size));
1099         if (valbuf == NULL) {
1100                 return (PD_FAILURE);
1101         }
1102 
1103         if (picl_get_propval(proph, (void *)valbuf,
1104             propinfo.size) != PICL_SUCCESS) {
1105                 free(valbuf);
1106                 return (PD_FAILURE);
1107         }
1108 
1109 
1110         log_printf("%29s Condition : %s\n", PD_BLANK, valbuf, 0);
1111 
1112         free(valbuf);
1113         return (PD_SUCCESS);
1114 
1115 
1116 }