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) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
  23  *
  24  * Netract Platform specific functions.
  25  *
  26  *      called when :
  27  *      machine_type == MTYPE_MONTECARLO
  28  */
  29 
  30 /* includes */
  31 #include <assert.h>
  32 #include <stdio.h>
  33 #include <stdlib.h>
  34 #include <stddef.h>
  35 #include <unistd.h>
  36 #include <ctype.h>
  37 #include <string.h>
  38 #include <strings.h>
  39 #include <stropts.h>
  40 #include <fcntl.h>
  41 #include <kvm.h>
  42 #include <kstat.h>
  43 #include <sys/types.h>
  44 #include <sys/utsname.h>
  45 #include <sys/openpromio.h>
  46 #include <sys/sunddi.h>
  47 #include <sys/ddi_impldefs.h>
  48 #include <sys/devinfo_impl.h>
  49 #include <sys/ioccom.h>
  50 #include <sys/systeminfo.h>
  51 #include <libintl.h>
  52 #include <config_admin.h>
  53 #include "pdevinfo.h"
  54 #include "display.h"
  55 #include "pdevinfo_sun4u.h"
  56 #include "display_sun4u.h"
  57 #include "libprtdiag.h"
  58 #include "libdevinfo.h"
  59 
  60 /* MC specific header, might just include from MC space */
  61 #include "mct_topology.h"
  62 #include "envctrl_gen.h"
  63 #include "pcf8574_nct.h"
  64 #include "netract_gen.h"
  65 #include "hscimpl.h"
  66 #include "scsbioctl.h"
  67 
  68 #if !defined(TEXT_DOMAIN)
  69 #define TEXT_DOMAIN                     "SYS_TEST"
  70 #endif
  71 
  72 /* globals */
  73 #define MAXNAMESZ                       128
  74 #define MAX_NODE_NAME_SZ                32
  75 
  76 /* this values equates to Max Tree depth for now */
  77 #define MAXIMUM_DEVS                    64
  78 
  79 typedef char device_info_t[MAX_NODE_NAME_SZ];
  80 
  81 typedef struct {
  82         cfga_list_data_t *ldatap;
  83         int req; /* If set, this list_data was requested by user */
  84 } ap_out_t;
  85 
  86 
  87 typedef struct {
  88         uint_t slot_addr;
  89         uint_t slot_stat;
  90         uint_t slot_cond;
  91         device_info_t devs_info[MAXIMUM_DEVS];
  92         uint_t number_devs;
  93 } mc_slot_info_t;
  94 
  95 typedef struct {
  96         mc_slot_info_t mc_slot_info[MC_MAX_SLOTS];
  97 } slot_data_t;
  98 
  99 
 100 extern char *progname;
 101 extern int print_flag;
 102 
 103 /* These are used to store all force loads of the drivers */
 104 static int ps_fd[MC_MAX_PS];
 105 static int oprom_fd;
 106 static int slot_index                   = 0;
 107 static int idx_minuscpu                 = 0;
 108 static int num_devs                     = 0;
 109 static int sd_instances[MC_MAX_SLOTS*15];
 110 static int gpio_instances[MC_MAX_PS+MC_MAX_FAN];
 111 static int sd_count                     = 0;
 112 static int st_instance;
 113 static int gpio_count                   = 0;
 114 static int slot_table_not_found         = 0;
 115 
 116 /* default not present */
 117 static int alarm_card_present           = 0;
 118 static int cpu_ftm_present              = 0;
 119 
 120 /*
 121  * We will store all kstat in globals so that
 122  * we can browse thru them later
 123  */
 124 static  int fail_syssoft_prop           = 0;
 125 static  int fail_drv_prop               = 0;
 126 di_node_t rootnode;     /* root nexus */
 127 slot_data_t mc_slots_data;
 128 
 129 /* scsb driver kstats */
 130 scsb_ks_leddata_t scsb_ks_leddata;
 131 scsb_ks_state_t scsb_ks_state;
 132 mct_topology_t scsb_ks_topo;
 133 
 134 /* pcf8574(gpio) driver kstats */
 135 envctrl_cpuvoltage_t pcf8574_ks_cpuv;
 136 envctrl_pwrsupp_t pcf8574_ks_ps1;
 137 envctrl_fantray_t pcf8574_ks_fant1;
 138 envctrl_pwrsupp_t pcf8574_ks_ps2;
 139 envctrl_fantray_t pcf8574_ks_fant2;
 140 
 141 /* pcf8591(adc-dac) driver kstats */
 142 envctrl_temp_t pcf8591_ks_temp;
 143 
 144 hsc_slot_table_t hotswap_slot_table[MC_MAX_SLOTS];
 145 hsc_prom_slot_table_t prom_slot_table[MC_MAX_SLOTS];
 146 
 147 static char *hotswap_mode               = NULL;
 148 static char *slot_auto_config[MC_MAX_SLOTS];
 149 static  int slot_table_size;
 150 
 151 /*
 152  * use this to ascertain what's the system,
 153  * default is tonga, we can add more for future variations
 154  * 0=tonga, 1=montecarlo
 155  * we need also to figure out what the system version is
 156  * 0 = 1.5, 1 = 1.0, 0.6 etc.
 157  */
 158 int montecarlo                          = 0;
 159 int version_p15_and_p20                 = 0;
 160 
 161 #define MAX_PRTDIAG_INFO_LENGTH         1024
 162 #define MAX_PRTDIAG_FRUS                22
 163 #define BIT_TEST(X, N)                  ((X) & (1 << (N)))
 164 #define SLOT1_OK_BIT                    0
 165 #define SLOT2_OK_BIT                    1
 166 #define SLOT3_OK_BIT                    2
 167 #define SLOT4_OK_BIT                    3
 168 #define SLOT5_OK_BIT                    4
 169 #define SLOT6_OK_BIT                    5
 170 #define SLOT7_OK_BIT                    6
 171 #define SLOT8_OK_BIT                    7
 172 #define PDU1_OK_BIT                     SLOT2_OK_BIT
 173 #define PDU2_OK_BIT                     SLOT4_OK_BIT
 174 #define FTM_OK_BIT                      SLOT5_OK_BIT
 175 #define SCB_OK_BIT                      SLOT6_OK_BIT
 176 #define FAN1_OK_BIT                     SLOT1_OK_BIT
 177 #define FAN2_OK_BIT                     SLOT2_OK_BIT
 178 #define DISK1_OK_BIT                    SLOT4_OK_BIT
 179 #define DISK2_OK_BIT                    SLOT5_OK_BIT
 180 #define DISK3_OK_BIT                    SLOT6_OK_BIT
 181 #define PS1_OK_BIT                      SLOT7_OK_BIT
 182 #define PS2_OK_BIT                      SLOT8_OK_BIT
 183 #define S_FREE(x)       (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
 184 #define ENVC_DEBUG_MODE                 0x03
 185 #define OPENPROMDEV                     "/dev/openprom"
 186 #define I2C_PCF8591_NAME                "adc-dac"
 187 #define I2C_KSTAT_CPUTEMP               "adc_temp"
 188 #define SCSB_DEV                        "scsb"
 189 #define SDERR                           "sderr"
 190 #define STERR                           "sterr"
 191 #define OK                              "ok"
 192 #define NOK                             "Not ok"
 193 #define ON                              "on"
 194 #define OFF                             "off"
 195 #define BLINK                           "blink"
 196 #define NA                              "Not Available"
 197 #define UK                              "Unknown "
 198 #define YES                             "Yes"
 199 #define NO                              "No "
 200 #define LO                              "low"
 201 #define HI                              "high"
 202 #define BLANK                           " "
 203 #define SYSSOFT_PROP                    "System software"
 204 #define DRV_PROP                        "Driver"
 205 #define HSC_PROP_NAME                   "hsc-slot-map"
 206 #define HSC_MODE                        "hotswap-mode"
 207 #define PCI_ROOT_AP                     "pci"
 208 #define PROPS                           "Properties:"
 209 #define BOARDTYPE                       "Board Type:"
 210 #define DEVS                            "Devices:"
 211 #define CPCI_IO                         "CompactPCI IO Slot"
 212 #define AC_CARD                         "Alarm Card"
 213 #define CPU_FTM                         "Front Transition Module"
 214 #define SCTRL_PROM_P06                  0x00
 215 #define SCTRL_PROM_P10                  0x01
 216 #define SCTRL_PROM_P15                  0x02
 217 #define SCTRL_PROM_P20                  0x03
 218 
 219 #define RMM_NUMBER                      3
 220 
 221 #define MONTECARLO_PLATFORM             "SUNW,UltraSPARC-IIi-Netract"
 222 #define MAKAHA_PLATFORM                 "SUNW,UltraSPARC-IIe-NetraCT-40"
 223 
 224 /*
 225  * The follow table is indexed with the enum's defined by mct_slot_occupant_t
 226  * OC_UNKN OC_CPU  OC_AC    OC_BHS OC_FHS OC_HAHS
 227  * OC_QFE  OC_FRCH OC_COMBO OC_PMC OC_ATM
 228  *
 229  * But "scsb" can currently identify only CPU and Alarm Cards by known
 230  * slot numbers.
 231  */
 232 char    *slot_occupants[] = {
 233                 CPCI_IO,
 234                 "CPU board ",
 235                 CPCI_IO,
 236                 "Basic HotSwap Board",
 237                 "Full HotSwap Board",
 238                 "HA Board",
 239                 "QFE Board",
 240                 "Fresh Choice Board",
 241                 "SUN Combo Board",
 242                 "PMC Board",
 243                 "ATM Board"
 244         };
 245 
 246 static char     *prtdiag_fru_types[] = {
 247                 "I/O        ",  /* 0 */
 248                 "CPU        ",
 249                 "PSU        ",
 250                 "HDD        ",
 251                 "FAN        ",
 252                 "Alarm Card ",
 253                 "SCB        ",
 254                 "SSB        ",
 255                 "CFTM       ",
 256                 "CRTM       ",
 257                 "PRTM       ",
 258                 "Midplane   "   /* 11 */
 259         };
 260 
 261 char prtdiag_fru_info[MAX_PRTDIAG_FRUS][MAX_PRTDIAG_INFO_LENGTH];
 262 
 263 #define SCB_REG_READ                    1
 264 #define SCB_REG_WRITE                   2
 265 
 266 /* Standard Device nodes - hardwired for now */
 267 /* will include fan tray later, cpu voltage not impl */
 268 static char     *scsb_node = NULL;
 269 static char     **ps_node = NULL;
 270 static char     *temp_node = NULL;
 271 
 272 static char     *mc_scsb_node =
 273 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/sysctrl@0,80:scsb";
 274 
 275 static char     *ot_scsb_node =
 276 "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/sysctrl@0,80:scsb";
 277 
 278 static char     *mc_ps_node[] = {
 279 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7c:pwrsuppply",
 280 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7e:pwrsuppply"
 281 };
 282 
 283 static char     *ot_ps_node[] = {
 284 "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7c:pwrsuppply",
 285 "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7e:pwrsuppply"
 286 };
 287 
 288 static char     *mc_temp_node =
 289 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/adc-dac@0,9e:cputemp";
 290 
 291 /*
 292  * these functions will overlay the symbol table of libprtdiag
 293  * at runtime (netract systems only)
 294  * display functions
 295  */
 296 int     display(Sys_tree *, Prom_node *, struct system_kstat_data *, int);
 297 /* local functions */
 298 /*
 299  * prom function
 300  */
 301 static void     gather_diaginfo(int flag);
 302 static int      extract_slot_table_from_obp();
 303 static int      mc_next(int id);
 304 static void     mc_walk(int id);
 305 static int      mc_child(int id);
 306 static void     mc_dump_node(int id);
 307 static int      mc_getpropval(struct openpromio *opp);
 308 
 309 #ifdef  REDUNDANT_INFO
 310 static int      mc_get_cpu_freq(Prom_node *node);
 311 static int      mc_get_ecache_size(Prom_node *node);
 312 static void     mc_display_cpus(Board_node *board);
 313 static void     mc_display_cpu_devices(Sys_tree *tree);
 314 #endif  /* REDUNDANT_INFO */
 315 
 316 static void     netract_disp_prom_version();
 317 
 318 /*
 319  * Since we do not have a system wide kstat for MC/Tg
 320  * here we have to do specific kstats to drivers that
 321  * post this information - MC/Tg specific drivers
 322  * that post kstat here are : scsb, pcf8574(gpio) and pcf8591
 323  */
 324 static int      analyze_nodes(di_node_t, void*);
 325 static void     analyze_pcipci_siblings(di_node_t);
 326 static void     display_mc_prtdiag_info();
 327 static int      dump_devs(di_node_t, void *);
 328 static void     prtdiag_devinfo(void);
 329 static void     force_load_drivers();
 330 static int      dump_prop_list(char *name,
 331                     di_node_t node, di_prop_t (*nxtprop)());
 332 static void     *config_calloc_check(size_t nelem, size_t elsize);
 333 static void     explore_slot_occupants();
 334 static void     do_scsb_kstat();
 335 static void     do_pcf8574_kstat();
 336 static void     do_pcf8591_kstat();
 337 static void     do_promversion();
 338 static int      mc_promopen(int oflag);
 339 static int      scsi_disk_status(int disk_number);
 340 static void     alarm_card_occupant();
 341 static int      scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode);
 342 static int      scsb_ioc_reg_read(int fd, uchar_t index,
 343                     scsb_ioc_rdwr_t *ioc_rd, int num);
 344 
 345 static int      check_platform();
 346 
 347 int
 348 display(Sys_tree *tree,
 349             Prom_node *root,
 350             struct system_kstat_data *kstats,
 351             int syserrlog)
 352 {
 353         int exit_code = 0;   /* init to all OK */
 354         void *value;  /* used for opaque PROM data */
 355         struct mem_total memory_total;  /* Total memory in system */
 356         struct grp_info grps;   /* Info on all groups in system */
 357 #ifdef  lint
 358         syserrlog = syserrlog;
 359 #endif
 360         sys_clk = -1;  /* System clock freq. (in MHz) */
 361         /*
 362          * Now display the machine's configuration. We do this if we
 363          * are not logging or exit_code is set (machine is broke).
 364          */
 365         if (!logging || exit_code) {
 366                 struct utsname uts_buf;
 367 
 368                 /*
 369                  * Display system banner
 370                  */
 371                 (void) uname(&uts_buf);
 372 
 373                 log_printf(dgettext(TEXT_DOMAIN,
 374                     "System Configuration:  Oracle Corporation"
 375                     "  %s %s\n"), uts_buf.machine,
 376                     get_prop_val(find_prop(root, "banner-name")), 0);
 377 
 378                 /* display system clock frequency */
 379                 value = get_prop_val(find_prop(root, "clock-frequency"));
 380                 if (value != NULL) {
 381                         sys_clk = ((*((int *)value)) + 500000) / 1000000;
 382                         log_printf(dgettext(TEXT_DOMAIN,
 383                             "System clock frequency: "
 384                             "%d MHz\n"), sys_clk, 0);
 385                 }
 386 
 387                 /* Display the Memory Size */
 388                 display_memorysize(tree, kstats, &grps, &memory_total);
 389                 /* Lets make sure we have all the needed drivers loaded */
 390                 /* display Montecarlo/Tonga FRU information */
 391                 if (!extract_slot_table_from_obp())
 392                         log_printf(dgettext(TEXT_DOMAIN,
 393                             "\r\nslot-table not available\r\n"), 0);
 394                 do_scsb_kstat();
 395                 force_load_drivers();
 396                 gather_diaginfo(print_flag && !logging);
 397                 /* figure out if ac is present */
 398                 alarm_card_occupant();
 399                 /* platform specific display mod */
 400                 display_mc_prtdiag_info();
 401                 di_fini(rootnode);
 402                 netract_disp_prom_version();
 403         }  /* if (!logging || exit_code) */
 404 
 405         return (exit_code);
 406 
 407 }       /* display(....) */
 408 
 409 static int
 410 check_platform()
 411 {
 412         char    si_platform[SYS_NMLN];
 413 
 414         /*
 415          * Check for the platform: Montecarlo or Makaha/CP2040 based
 416          */
 417         if (sysinfo(SI_PLATFORM, si_platform, sizeof (si_platform)) == -1) {
 418                 return (-1);
 419         }
 420 
 421         if ((strncmp(si_platform, MONTECARLO_PLATFORM,
 422             strlen(MONTECARLO_PLATFORM))) == 0) {
 423                 scsb_node = mc_scsb_node;
 424                 ps_node = mc_ps_node;
 425                 temp_node = mc_temp_node;
 426         } else if ((strncmp(si_platform, MAKAHA_PLATFORM,
 427             strlen(MAKAHA_PLATFORM))) == 0) {
 428                 scsb_node = ot_scsb_node;
 429                 ps_node = ot_ps_node;
 430                 temp_node = NULL;
 431         } else {
 432                 return (-1);
 433         }
 434 
 435         return (0);
 436 }
 437 
 438 void
 439 force_load_drivers()
 440 {
 441         int     i;
 442 
 443         if (NULL == scsb_node || NULL == ps_node) {
 444                 if (check_platform() == -1) {
 445                         return;
 446                 }
 447         }
 448 
 449         /* check scb/ssb presence */
 450         if (scsb_ks_state.scb_present || scsb_ks_state.ssb_present) {
 451                 if (open(scsb_node, O_RDONLY) < 0)
 452                         log_printf(dgettext(TEXT_DOMAIN,
 453                             "\nscsb open FAILED!"), 0);
 454         }
 455 
 456         /* check the num of PS we have */
 457         for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
 458                 if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) {
 459                         if ((ps_fd[i] = open(ps_node[i], O_RDONLY)) < 0)
 460                                 log_printf(dgettext(TEXT_DOMAIN,
 461                                     "\npowersupply%d open failed"),
 462                                     i, 0);
 463                 }
 464         } /* for */
 465 
 466         /* open the cpu temp driver */
 467         if (temp_node) {
 468                 if (open(temp_node, O_RDONLY) < 0)
 469                         log_printf(dgettext(TEXT_DOMAIN,
 470                             "\ncputemp open FAILED!"), 0);
 471         }
 472 }
 473 
 474 
 475 void
 476 explore_slot_occupants()
 477 {
 478         char *cp = NULL;
 479         int index;
 480         int ret = CFGA_ERROR;
 481         char *estrp = NULL;
 482         cfga_list_data_t *list_array = NULL;
 483         ap_out_t *out_array = NULL;
 484         int nlist = 0;
 485         char  *prefilt_optp = NULL;
 486         int dyn_exp = 1;
 487         char *plat_opts = NULL;
 488 
 489         ret = config_list_ext(0, NULL, &list_array,
 490             &nlist, plat_opts, prefilt_optp, &estrp,
 491             dyn_exp ? CFGA_FLAG_LIST_ALL : 0);
 492         if (ret != CFGA_OK) {
 493                 log_printf(dgettext(TEXT_DOMAIN,
 494                     "\ncannot explore configuration"), 0);
 495                 return;
 496         }
 497         assert(nlist != 0);
 498         out_array = config_calloc_check(nlist, sizeof (*out_array));
 499         if (out_array == NULL) {
 500                 ret = CFGA_LIB_ERROR;
 501                 goto bail;
 502         }
 503         /* create a list of output stat data */
 504         for (index = 0; index < nlist; index++) {
 505                 out_array[index].ldatap = &list_array[index];
 506                 out_array[index].req = 0;
 507         }
 508 
 509         for (index = 0; index < nlist; index++) {
 510                 if ((cp = strstr(out_array[index].ldatap->ap_phys_id,
 511                     "cpci_slot")) != NULL) {
 512                         mc_slots_data.mc_slot_info[idx_minuscpu].slot_stat
 513                             = out_array[index].ldatap->ap_o_state;
 514                         mc_slots_data.mc_slot_info[idx_minuscpu].slot_cond
 515                             = out_array[index].ldatap->ap_cond;
 516                         idx_minuscpu++;
 517                 }
 518         }
 519 bail:
 520         S_FREE(list_array);
 521         S_FREE(out_array);
 522 }
 523 
 524 
 525 /*
 526  * config_calloc_check - perform allocation, check result and
 527  * set error indicator
 528  */
 529 void *
 530 config_calloc_check(
 531         size_t nelem,
 532         size_t elsize)
 533 {
 534         void *p;
 535         static char alloc_fail[] =
 536             "%s: memory allocation failed (%d*%d bytes)\n";
 537 
 538         p = calloc(nelem, elsize);
 539         if (p == NULL) {
 540                 log_printf(dgettext(TEXT_DOMAIN, alloc_fail), nelem, elsize, 0);
 541         }
 542         return (p);
 543 }
 544 
 545 
 546 void
 547 do_scsb_kstat()
 548 {
 549         kstat_ctl_t     *kc;
 550         kstat_t         *ksp_leddata;
 551         kstat_t         *ksp_state;
 552         kstat_t          *ksp_topo;
 553         scsb_ks_leddata_t *pks_leddata;
 554         scsb_ks_state_t *pks_state;
 555         mct_topology_t  *pks_topo;
 556         int i;
 557 
 558 #ifdef  DEBUG_TEMP1
 559                 int index;
 560 #endif
 561         if (!(kc = kstat_open())) {
 562 #ifdef  DEBUG_TEMP
 563                 log_printf("\nkstat_open failed", 0);
 564 #endif
 565                 return;
 566         }
 567 #ifdef  lint
 568         kc = kc;
 569 #endif
 570         /* get kstat on scsb led data */
 571         if ((ksp_leddata = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_LEDDATA))
 572             == NULL) {
 573 #ifdef  DEBUG_TEMP
 574                 log_printf("\nkstat_lookup for scsb_leddata failed", 0);
 575 #endif
 576                 return;
 577         }
 578         if (kstat_read(kc, ksp_leddata, NULL) == -1) {
 579 #ifdef  DEBUG_TEMP
 580                 log_printf("\nkstat_read for scsb_leddata failed", 0);
 581 #endif
 582                 return;
 583         }
 584         pks_leddata = (scsb_ks_leddata_t *)ksp_leddata->ks_data;
 585         scsb_ks_leddata = *pks_leddata; /* set the globals for future */
 586 #ifdef  DEBUG_LEDS
 587         /* dump the kstat leddata */
 588         printf("\nDumping LED regs: ");
 589         for (i = 0; i < SCSB_LEDDATA_REGISTERS; ++i) {
 590                 log_printf("0x%x ", pks_leddata->scb_led_regs[i] & 0xff, 0);
 591         }
 592         log_printf("\n", 0);
 593 #endif
 594         /* get kstat on scsb states */
 595         if ((ksp_state = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_STATE))
 596             == NULL) {
 597 #ifdef  DEBUG_TEMP
 598                 log_printf("\nkstat_lookup for scsb_state failed", 0);
 599 #endif
 600                 return;
 601         }
 602         if (kstat_read(kc, ksp_state, NULL) == -1) {
 603 #ifdef  DEBUG_TEMP
 604                 log_printf("\nkstat_read for scsb_state failed", 0);
 605 #endif
 606                 return;
 607         }
 608         pks_state = (scsb_ks_state_t *)ksp_state->ks_data;
 609         scsb_ks_state = *pks_state; /* set the global for future */
 610 #ifdef  DEBUG_TEMP1
 611         /* dump the kstat state */
 612         log_printf("\tSCB                       is%spresent\n",
 613             pks_state->scb_present ? " " : " not ", 0);
 614         log_printf("\tSSB                       is%spresent\n",
 615             pks_state->ssb_present ? " " : " not ", 0);
 616         log_printf("\tscsb                      is%sfrozen\n",
 617             pks_state->scsb_frozen ? " " : " not ", 0);
 618         log_printf("\tscsb mode:                ", 0);
 619         switch (pks_state->scsb_mode) {
 620                 case ENVC_DEBUG_MODE:
 621                         log_printf("DEBUG MODE\n", 0);
 622                         break;
 623                 case ENVCTRL_DIAG_MODE:
 624                         log_printf("DIAGNOSTIC MODE\n", 0);
 625                         break;
 626                 case ENVCTRL_NORMAL_MODE:
 627                         log_printf("NORMAL MODE\n", 0);
 628                         break;
 629         }
 630         log_printf("\tscsb event code:  0x%x\n", pks_state->event_code, 0);
 631 #endif  /* DEBUG_TEMP1 */
 632 
 633         if ((ksp_topo = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_TOPOLOGY))
 634             == NULL) {
 635 #ifdef  DEBUG_TEMP
 636                 log_printf("\nkstat_lookup for scsb_topo failed", 0);
 637 #endif
 638                 return;
 639         }
 640         if (kstat_read(kc, ksp_topo, NULL) == -1) {
 641 #ifdef  DEBUG_TEMP
 642                 log_printf("\nkstat_read for scsb_topo failed", 0);
 643 #endif
 644                 return;
 645         }
 646         pks_topo = (mct_topology_t *)ksp_topo->ks_data;
 647         scsb_ks_topo = *pks_topo; /* set the global for future */
 648         /*
 649          * we need to set this so that we can get status info
 650          * for the 2 powersupplies in MC as we need to get
 651          * kstat from both driver instances for environment
 652          */
 653         if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF)
 654                 montecarlo = 1; /* Monte Carlo */
 655         /*
 656          * HW version 0.6 and 1.0 had different led maps
 657          * its assumed that HW 2.0 would not change this
 658          * need to modify if it does
 659          */
 660         if ((pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P15) ||
 661             (pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P20)) {
 662                 version_p15_and_p20 = 1;
 663         }
 664 
 665         /* set flag to note that CFTM is present */
 666         for (i = 0; i < pks_topo->max_units[CFTM]; ++i) {
 667                 if (pks_topo->mct_cftm[i].fru_status == FRU_PRESENT)
 668                         cpu_ftm_present = 1;
 669         }
 670 
 671 #ifdef  DEBUG_TEMP1
 672         /*
 673          * Midplane
 674          */
 675         log_printf("Midplane type:              ", 0);
 676         if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF)
 677                 log_printf("Netra ct800 server\n", 0);
 678         else
 679                 log_printf("Netra ct400 server%s\n",
 680                     pks_topo->mid_plane.fru_id ==
 681                     SCTRL_MPID_QUARTER_NODSK ? ", no disk" : " with disk", 0);
 682         log_printf("Midplane version:   %d\n",
 683             pks_topo->mid_plane.fru_version, 0);
 684         log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
 685             pks_topo->mct_scb[0].fru_type,
 686             pks_topo->mct_scb[0].fru_unit,
 687             pks_topo->mct_scb[0].fru_id,
 688             pks_topo->mct_scb[0].fru_version, 0);
 689         /*
 690          * Slots
 691          */
 692         log_printf("Slots present out of maximum %d\n",
 693             pks_topo->max_units[SLOT], 0);
 694         for (i = 0; i < pks_topo->max_units[SLOT]; ++i) {
 695                 if (pks_topo->mct_slots[i].fru_status != FRU_PRESENT)
 696                         continue;
 697                 index = (int)pks_topo->mct_slots[i].fru_type;
 698                 log_printf("\tSlot %d occupant: %s;",
 699                     pks_topo->mct_slots[i].fru_unit, slot_occupants[index], 0);
 700                 log_printf(" ID 0x%x; VER 0x%x ; ",
 701                     pks_topo->mct_slots[i].fru_id,
 702                     pks_topo->mct_slots[i].fru_version, 0);
 703                 log_printf(" Slot health %d\n",
 704                     pks_topo->mct_slots[i].fru_health, 0);
 705                 /* pks_topo->mct_slots[i].fru_health */
 706         }
 707 
 708         /*
 709          * PDU
 710          */
 711         log_printf("PDUs present out of maximum %d\n",
 712             pks_topo->max_units[PDU], 0);
 713         for (i = 0; i < pks_topo->max_units[PDU]; ++i) {
 714                 if (pks_topo->mct_pdu[i].fru_status != FRU_PRESENT)
 715                         continue;
 716                 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
 717                     pks_topo->mct_pdu[i].fru_type,
 718                     pks_topo->mct_pdu[i].fru_unit,
 719                     pks_topo->mct_pdu[i].fru_id,
 720                     pks_topo->mct_pdu[i].fru_version, 0);
 721                 /* pks_topo->mct_pdu[i].fru_health */
 722         }
 723 
 724         /*
 725          * Power Supplies
 726          */
 727         log_printf("Power Supplies present out of maximum %d\n",
 728             pks_topo->max_units[PS], 0);
 729         for (i = 0; i < pks_topo->max_units[PS]; ++i) {
 730                 if (pks_topo->mct_ps[i].fru_status != FRU_PRESENT)
 731                         continue;
 732                 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
 733                     pks_topo->mct_ps[i].fru_type,
 734                     pks_topo->mct_ps[i].fru_unit,
 735                     pks_topo->mct_ps[i].fru_id,
 736                     pks_topo->mct_ps[i].fru_version, 0);
 737         }
 738 
 739         /*
 740          * Disks
 741          */
 742         log_printf("Disks present out of maximum %d\n",
 743             pks_topo->max_units[DISK], 0);
 744         for (i = 0; i < pks_topo->max_units[DISK]; ++i) {
 745                 if (pks_topo->mct_disk[i].fru_status != FRU_PRESENT)
 746                         continue;
 747                 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
 748                     pks_topo->mct_disk[i].fru_type,
 749                     pks_topo->mct_disk[i].fru_unit,
 750                     pks_topo->mct_disk[i].fru_id,
 751                     pks_topo->mct_disk[i].fru_version, 0);
 752         }
 753 
 754         /*
 755          * Fans
 756          */
 757         log_printf("Fans present out of maximum %d\n",
 758             pks_topo->max_units[FAN], 0);
 759         for (i = 0; i < pks_topo->max_units[FAN]; ++i) {
 760                 if (pks_topo->mct_fan[i].fru_status != FRU_PRESENT)
 761                         continue;
 762                 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
 763                     pks_topo->mct_fan[i].fru_type,
 764                     pks_topo->mct_fan[i].fru_unit,
 765                     pks_topo->mct_fan[i].fru_id,
 766                     pks_topo->mct_fan[i].fru_version, 0);
 767         }
 768 
 769         /*
 770          * SCBs
 771          */
 772         log_printf("SCBs present out of maximum %d\n",
 773             pks_topo->max_units[SCB], 0);
 774         for (i = 0; i < pks_topo->max_units[SCB]; ++i) {
 775                 if (pks_topo->mct_scb[i].fru_status != FRU_PRESENT)
 776                         continue;
 777                 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
 778                     pks_topo->mct_scb[i].fru_type,
 779                     pks_topo->mct_scb[i].fru_unit,
 780                     pks_topo->mct_scb[i].fru_id,
 781                     pks_topo->mct_scb[i].fru_version, 0);
 782         }
 783 
 784         /*
 785          * SSBs
 786          */
 787         log_printf("SSBs present out of maximum %d\n",
 788             pks_topo->max_units[SSB], 0);
 789         for (i = 0; i < pks_topo->max_units[SSB]; ++i) {
 790                 if (pks_topo->mct_ssb[i].fru_status != FRU_PRESENT)
 791                         continue;
 792                 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
 793                     pks_topo->mct_ssb[i].fru_type,
 794                     pks_topo->mct_ssb[i].fru_unit,
 795                     pks_topo->mct_ssb[i].fru_id,
 796                     pks_topo->mct_ssb[i].fru_version, 0);
 797         }
 798 
 799         /*
 800          * Alarms Cards
 801          */
 802         log_printf("Alarm Cards present out of maximum %d\n",
 803             pks_topo->max_units[ALARM], 0);
 804         for (i = 0; i < pks_topo->max_units[ALARM]; ++i) {
 805                 if (pks_topo->mct_alarm[i].fru_status != FRU_PRESENT)
 806                         continue;
 807                 log_printf("\ttype %d; unit %d; id 0x%x; VER 0x%x\n",
 808                     pks_topo->mct_alarm[i].fru_type,
 809                     pks_topo->mct_alarm[i].fru_unit,
 810                     pks_topo->mct_alarm[i].fru_id,
 811                     pks_topo->mct_alarm[i].fru_version, 0);
 812         }
 813 
 814         /*
 815          * CFTMs
 816          */
 817         log_printf("CFTMs present out of maximum %d\n",
 818             pks_topo->max_units[CFTM], 0);
 819         for (i = 0; i < pks_topo->max_units[CFTM]; ++i) {
 820                 if (pks_topo->mct_cftm[i].fru_status != FRU_PRESENT)
 821                         continue;
 822                 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
 823                     pks_topo->mct_cftm[i].fru_type,
 824                     pks_topo->mct_cftm[i].fru_unit,
 825                     pks_topo->mct_cftm[i].fru_id,
 826                     pks_topo->mct_cftm[i].fru_version, 0);
 827         }
 828 
 829         /*
 830          * CRTMs
 831          */
 832         log_printf("CRTMs present out of maximum %d\n",
 833             pks_topo->max_units[CRTM], 0);
 834         for (i = 0; i < pks_topo->max_units[CRTM]; ++i) {
 835                 if (pks_topo->mct_crtm[i].fru_status != FRU_PRESENT)
 836                         continue;
 837                 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
 838                     pks_topo->mct_crtm[i].fru_type,
 839                     pks_topo->mct_crtm[i].fru_unit,
 840                     pks_topo->mct_crtm[i].fru_id,
 841                     pks_topo->mct_crtm[i].fru_version, 0);
 842         }
 843 
 844         /*
 845          * PRTMs
 846          */
 847         log_printf("PRTMs present out of maximum %d\n",
 848             pks_topo->max_units[PRTM], 0);
 849         for (i = 0; i < pks_topo->max_units[PRTM]; ++i) {
 850                 if (pks_topo->mct_prtm[i].fru_status != FRU_PRESENT)
 851                         continue;
 852                 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
 853                     pks_topo->mct_prtm[i].fru_type,
 854                     pks_topo->mct_prtm[i].fru_unit,
 855                     pks_topo->mct_prtm[i].fru_id,
 856                     pks_topo->mct_prtm[i].fru_version, 0);
 857         }
 858 #endif  /* DEBUG_TEMP1 */
 859 
 860 }       /*  do_scsb_kstat(...) */
 861 
 862 
 863 void
 864 do_pcf8574_kstat()
 865 {
 866         kstat_ctl_t     *kc;
 867         kstat_t         *ksp_ps;
 868         kstat_t         *ksp_fan;
 869         envctrl_pwrsupp_t *pks_ps;
 870         envctrl_fantray_t *pks_fan;
 871         int     i;
 872         char    *kstat_name = NULL;
 873 
 874         if (!(kc = kstat_open())) {
 875 #ifdef  DEBUG_TEMP
 876                 log_printf("\nkstat_open for pcf8574 failed", 0);
 877 #endif
 878                 return;
 879         }
 880 
 881 #ifdef  lint
 882         kc = kc;
 883 #endif
 884         /* get kstat on gpio powersupply and fan states */
 885         for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
 886                 if (i == 1) {
 887                         kstat_name = I2C_KSTAT_PWRSUPPLY;
 888                         strncat(kstat_name, "1", 1);
 889                 } else {
 890                         kstat_name = I2C_KSTAT_PWRSUPPLY;
 891                         strncat(kstat_name, "2", 1);
 892                 }
 893                 if ((ksp_ps = kstat_lookup(kc, I2C_PCF8574_NAME, 0, kstat_name))
 894                     == NULL) {
 895 #ifdef  DEBUG_TEMP
 896                         log_printf("\nks lookup for pwrsupply%d failed",
 897                             i+1, 0);
 898 #endif
 899                         return;
 900                 }
 901                 if (kstat_read(kc, ksp_ps, NULL) == -1) {
 902 #ifdef  DEBUG_TEMP
 903                         log_printf("\nks read for pwrsupply%d failed", i+1, 0);
 904 #endif
 905                         return;
 906                 }
 907                 pks_ps = (envctrl_pwrsupp_t *)ksp_ps->ks_data;
 908                 if (i == 1)
 909                         pcf8574_ks_ps1 = *pks_ps; /* ps 1 */
 910                 else
 911                         pcf8574_ks_ps2 = *pks_ps; /* ps 2 */
 912         } /* for */
 913         for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) {
 914                 if (i == 1) {
 915                         kstat_name = I2C_KSTAT_FANTRAY;
 916                         strncat(kstat_name, "1", 1);
 917                 } else {
 918                         kstat_name = I2C_KSTAT_FANTRAY;
 919                         strncat(kstat_name, "2", 1);
 920                 }
 921                 if ((ksp_fan = kstat_lookup(kc, I2C_PCF8574_NAME,
 922                     0, kstat_name)) == NULL) {
 923 #ifdef  DEBUG_TEMP
 924                         log_printf("\nks lookup for fantray%d failed",
 925                             i+1, 0);
 926 #endif
 927                         return;
 928                 }
 929                 if (kstat_read(kc, ksp_fan, NULL) == -1) {
 930 #ifdef  DEBUG_TEMP
 931                         log_printf("\nks read for fantray%d failed", i+1, 0);
 932 #endif
 933                         return;
 934                 }
 935                 pks_fan = (envctrl_fantray_t *)ksp_fan->ks_data;
 936                 if (i == 1)
 937                         pcf8574_ks_fant1 = *pks_fan; /* fan 1 */
 938                 else
 939                         pcf8574_ks_fant2 = *pks_fan; /* fan 2 */
 940         } /* for */
 941         kstat_close(kc);
 942 
 943 }       /*  do_pcf8574_kstat(...) */
 944 
 945 void
 946 do_pcf8591_kstat()
 947 {
 948         kstat_ctl_t     *kc;
 949         kstat_t         *ksp_temp;
 950 
 951         envctrl_temp_t *pks_temp;
 952 
 953         if (!(kc = kstat_open())) {
 954 #ifdef  DEBUG_TEMP
 955                 log_printf("ks open for pcf8591 failed", 0);
 956 #endif
 957                 return;
 958         }
 959 #ifdef  lint
 960         kc = kc;
 961 #endif
 962         /* get kstat on adc driver's CPU temperature data */
 963         if ((ksp_temp = kstat_lookup(kc, I2C_PCF8591_NAME,
 964             -1, I2C_KSTAT_CPUTEMP))
 965             == NULL) {
 966 #ifdef  DEBUG_TEMP
 967                 log_printf("ks lookup for adc_temp failed", 0);
 968 #endif
 969                 return;
 970         }
 971         if (kstat_read(kc, ksp_temp, NULL) == -1) {
 972 #ifdef  DEBUG_TEMP
 973                 log_printf("ks read for adc_temp failed", 0);
 974 #endif
 975                 return;
 976         }
 977         pks_temp = (envctrl_temp_t *)ksp_temp->ks_data;
 978         pcf8591_ks_temp = *pks_temp;
 979         kstat_close(kc);
 980 }       /*  do_pcf8591_kstat(.) */
 981 
 982 
 983 void
 984 gather_diaginfo(int flag)
 985 {
 986         if (flag) {
 987                 /* gather system environmental conditions. */
 988                 /* obtain kstat info from gpio & temp. driver */
 989                 do_pcf8574_kstat();
 990                 do_pcf8591_kstat();
 991                 explore_slot_occupants();       /* fill in some occupant info */
 992                 prtdiag_devinfo();
 993                 analyze_pcipci_siblings(rootnode);
 994         }
 995 
 996 }       /* display_diaginfo(...) */
 997 
 998 void
 999 netract_disp_prom_version()
1000 {
1001         /* Display Prom revision header */
1002         log_printf(dgettext(TEXT_DOMAIN, "System Board PROM revision:\n"), 0);
1003         log_printf("---------------------------\n", 0);
1004         do_promversion();
1005 
1006 }       /* netract_disp_prom_version(.) */
1007 
1008 
1009 /*
1010  * Get and print the PROM version.
1011  */
1012 void
1013 do_promversion(void)
1014 {
1015         Oppbuf  oppbuf;
1016         struct openpromio *opp = &(oppbuf.opp);
1017 
1018         if (mc_promopen(O_RDONLY))  {
1019                 log_printf(dgettext(TEXT_DOMAIN,
1020                     "\nCannot open openprom device"), 0);
1021                 return;
1022         }
1023 
1024         opp->oprom_size = MAXVALSIZE;
1025         if (ioctl(oprom_fd, OPROMGETVERSION, opp) < 0) {
1026                 perror("\nOPROMGETVERSION ioctl failed");
1027                 return;
1028         }
1029         log_printf("%s\n", opp->oprom_array, 0);
1030 
1031         if (close(oprom_fd) < 0) {
1032                 log_printf(dgettext(TEXT_DOMAIN,
1033                     "\nclose error on %s"), OPENPROMDEV, 0);
1034                 return;
1035         }
1036 }       /* do_promversion() */
1037 
1038 int
1039 mc_promopen(int oflag)
1040 {
1041         for (;;) {
1042                 if ((oprom_fd = open(OPENPROMDEV, oflag)) < 0) {
1043                         if (errno == EAGAIN) {
1044                                 (void) sleep(5);
1045                                 continue;
1046                         }
1047                         if (errno == ENXIO)
1048                                 return (-1);
1049                         log_printf(dgettext(TEXT_DOMAIN,
1050                             "\ncannot open %s"), OPENPROMDEV, 0);
1051                         return (1);
1052                 } else
1053                         return (0);
1054         }
1055 }
1056 
1057 
1058 /*
1059  * This will return -1 for status unknown, 0 for OK, and 1 for failed (scsi
1060  * hard errors)
1061  * swiped from envmon policies
1062  */
1063 int
1064 scsi_disk_status(int disk_number)
1065 {
1066         kstat_ctl_t    *kc;
1067         kstat_t         *ksp_disk;
1068         kstat_named_t  *disk_data;
1069 
1070         int i;
1071         int nlist = 0;
1072         cfga_list_data_t *list_array = NULL;
1073         char *ap_ids[] = {"c0"};
1074 
1075         if ((kc = kstat_open()) == NULL) {
1076                 log_printf(dgettext(TEXT_DOMAIN, "\nks open failed"), 0);
1077                 return (-1);
1078         }
1079 
1080         if (disk_number == RMM_NUMBER) { /* RMM */
1081                 if (config_list_ext(1, ap_ids, &list_array, &nlist,
1082                     NULL, NULL, NULL, CFGA_FLAG_LIST_ALL) != CFGA_OK) {
1083                         kstat_close(kc);
1084                         return (-1);
1085                 }
1086                 for (i = 0; i < nlist; i++) {
1087                         if (strstr(list_array[i].ap_phys_id, "rmt/0") != NULL) {
1088                                 /* Tape drive */
1089                                 if (list_array[i].ap_o_state ==
1090                                     CFGA_STAT_UNCONFIGURED) {
1091                                         kstat_close(kc);
1092                                         return (-1);
1093                                 }
1094                                 if ((ksp_disk = kstat_lookup(kc, STERR,
1095                                     st_instance, NULL)) == NULL) {
1096                                         kstat_close(kc);
1097                                         return (-1);
1098                                 }
1099                                 break;
1100                         } else if (strstr(list_array[i].ap_phys_id,
1101                             "dsk/c0t6d0") != NULL) {
1102                                 /* CD_ROM */
1103                                 if (list_array[i].ap_o_state ==
1104                                     CFGA_STAT_UNCONFIGURED) {
1105                                         kstat_close(kc);
1106                                         return (-1);
1107                                 }
1108                                 if ((ksp_disk = kstat_lookup(kc, SDERR,
1109                                     sd_instances[disk_number-1], NULL)) ==
1110                                     NULL) {
1111                                         kstat_close(kc);
1112                                         return (-1);
1113                                 }
1114                                 break;
1115                         }
1116                 }
1117         } else { /* Hard disk */
1118                 if ((ksp_disk = kstat_lookup(kc, SDERR,
1119                     sd_instances[disk_number-1], NULL)) == NULL) {
1120                         kstat_close(kc);
1121                         return (-1);
1122                 }
1123         }
1124 
1125         if (kstat_read(kc, ksp_disk, NULL) == -1) {
1126                 log_printf(dgettext(TEXT_DOMAIN,
1127                     "\nks read error for disk%d, drv inst%d"),
1128                     disk_number, sd_instances[disk_number-1], 0);
1129                 kstat_close(kc);
1130                 return (-1);
1131         }
1132         disk_data = KSTAT_NAMED_PTR(ksp_disk);
1133         /*
1134          * if disk_data[].value is >0, we have a problem
1135          */
1136         if (disk_data[1].value.ui32 == 0) {
1137                 kstat_close(kc);
1138                 return (0);
1139         } else {
1140                 kstat_close(kc);
1141                 return (1);
1142         }
1143 }
1144 
1145 
1146 void
1147 prtdiag_devinfo(void)
1148 {
1149         uint_t flag;
1150         /* lets get everything we can from kernel */
1151         flag = DINFOSUBTREE|DINFOPROP;
1152         rootnode = di_init("/", flag);
1153         if (rootnode == DI_NODE_NIL) {
1154                 log_printf(dgettext(TEXT_DOMAIN,
1155                     "\nprtdiag_devinfo: di_init() failed"), 0);
1156                 return;
1157         }
1158         (void) di_walk_node(rootnode, DI_WALK_CLDFIRST, NULL,
1159             dump_devs);
1160 }
1161 
1162 
1163 /*
1164  * gather information about this node, returns appropriate code.
1165  * specific information we seek are driver names, instances
1166  * we will initialize some globals depending on what we find
1167  * from the kernel device tree info and may be private data
1168  * if required
1169  */
1170 /*ARGSUSED1*/
1171 int
1172 dump_devs(di_node_t node, void *arg)
1173 {
1174         char *driver_name;
1175 
1176         driver_name = di_driver_name(node);
1177         /* we will initialize our globals here */
1178         if ((di_instance(node) >= 0) &&
1179             (driver_name != NULL) &&
1180             (!(di_state(node) & DI_DRIVER_DETACHED))) {
1181                 if (strcmp(driver_name, "pcf8574") == 0) {
1182                         gpio_instances[gpio_count] = di_instance(node);
1183                         gpio_count++;
1184                 } else if (strcmp(driver_name, "sd") == 0) {
1185                         sd_instances[sd_count] =  di_instance(node);
1186                         sd_count++;
1187                 } else if (strcmp(driver_name, "st") == 0) {
1188                         st_instance = di_instance(node);
1189                 }
1190         }
1191 
1192         if (strcmp(di_node_name(node), "pseudo") == 0)
1193                 return (DI_WALK_PRUNECHILD);
1194         else
1195                 return (DI_WALK_CONTINUE);
1196 }
1197 
1198 
1199 
1200 /*
1201  * Returns 0 if error , 1 otherwise
1202  */
1203 int
1204 dump_prop_list(char *name, di_node_t node, di_prop_t (*nxtprop)())
1205 {
1206         int prop_len, i, k, max_slots_minus_cpu, n;
1207         uchar_t *prop_data;
1208         char    *p;
1209         char   *temp_s;
1210         di_prop_t prop, next;
1211         int ret_value = 0;
1212 
1213         max_slots_minus_cpu = scsb_ks_topo.max_units[SLOT]-1;
1214 
1215         if ((next = nxtprop(node, DI_PROP_NIL)) == DI_PROP_NIL)
1216                 return (0);
1217         while (next != DI_PROP_NIL) {
1218                 int maybe_str = 1, npossible_strs = 0;
1219                 prop = next;
1220                 next = nxtprop(node, prop);
1221                 /*
1222                  * get prop length and value:
1223                  * private interface--always success
1224                  */
1225                 prop_len = di_prop_rawdata(prop, &prop_data);
1226                 if (di_prop_type(prop) == DDI_PROP_UNDEF_IT) {
1227                         continue;
1228                 }
1229 
1230                 if (prop_len == 0)  {
1231                         continue;
1232                 }
1233                 if (prop_data[prop_len - 1] != '\0') {
1234                         maybe_str = 0;
1235                 } else {
1236                         /*
1237                          * Every character must be a string character or a \0,
1238                          * and there must not be two \0's in a row.
1239                          */
1240                         for (i = 0; i < prop_len; i++) {
1241                                 if (prop_data[i] == '\0') {
1242                                         npossible_strs++;
1243                                 } else if (!isascii(prop_data[i]) ||
1244                                     iscntrl(prop_data[i])) {
1245                                         maybe_str = 0;
1246                                         break;
1247                                 }
1248 
1249                                 if ((i > 0) && (prop_data[i] == '\0') &&
1250                                     (prop_data[i - 1] == '\0')) {
1251                                         maybe_str = 0;
1252                                         break;
1253                                 }
1254                         }
1255                 }
1256 
1257                 if (maybe_str) {
1258                         p = (char *)prop_data;
1259                         for (i = 0; i < npossible_strs - 1; i++) {
1260                                 if ((strcmp(name, SYSSOFT_PROP) == 0) &&
1261                                     (strcmp(di_prop_name(prop),
1262                                     HSC_PROP_NAME) == 0)) {
1263                                         temp_s = p;
1264                                         temp_s += strlen(temp_s) + 1;
1265                                 }
1266                                 p += strlen(p) + 1;
1267                         }
1268 
1269                         if ((strcmp(name, SYSSOFT_PROP) == 0) &&
1270                             (strcmp(di_prop_name(prop), HSC_PROP_NAME) == 0)) {
1271                                 temp_s = temp_s - prop_len+2;
1272                                 for (k = 0, n = 0; k < prop_len; k++) {
1273                                         if (temp_s[k] == 0) {
1274                                                 n++;
1275                                         }
1276                                 }
1277                                 if (n % 4) {
1278                                         log_printf(dgettext(TEXT_DOMAIN,
1279                                             "\nbad slot-table(%d)\n"), n);
1280                                         slot_table_not_found = 0;
1281                                         return (ret_value);
1282                                 }
1283                                 slot_table_size = n / 4;
1284                                 /*
1285                                  * NOTE : We save slot table info in order
1286                                  */
1287                                 for (k = 0; k < slot_table_size; k++) {
1288                                         char *nexus, *pcidev, *phys_slotname;
1289                                         char *ga;
1290                                         /*
1291                                          * Pick off pointer to nexus
1292                                          * path or PROM handle
1293                                          */
1294                                         nexus = temp_s;
1295                                         while (*temp_s != NULL)
1296                                                 temp_s++;
1297                                         temp_s++;
1298 
1299                                         /*
1300                                          * Pick off pointer to the
1301                                          * pci device number
1302                                          */
1303                                         pcidev = temp_s;
1304                                         while (*temp_s != NULL)
1305                                                 temp_s++;
1306                                         temp_s++;
1307 
1308                                         /* Pick off physical slot no */
1309                                         phys_slotname = temp_s;
1310                                         while (*temp_s != NULL)
1311                                                 temp_s++;
1312                                         temp_s++;
1313 
1314                                         /*
1315                                          * Pick off GA bits which
1316                                          * we dont use for now.
1317                                          */
1318                                         ga = temp_s;
1319                                         while (*temp_s != NULL)
1320                                                 temp_s++;
1321                                         temp_s++;
1322 
1323                                         hotswap_slot_table[k].pslotnum
1324                                             = atoi(phys_slotname);
1325                                         hotswap_slot_table[k].ga = atoi(ga);
1326                                         hotswap_slot_table[k].pci_devno
1327                                             = atoi(pcidev);
1328                                         strcpy(hotswap_slot_table[k].nexus,
1329                                             nexus);
1330                                 } /* for (k = 0; k < slot_table_size; k++) */
1331 
1332                                 ret_value = 1;
1333                         } else /* (strcmp(name, SYSSOFT_PROP) */
1334                                 slot_table_not_found = 1;
1335 
1336                         /*
1337                          * now we want to save off the info
1338                          * we would use later
1339                          */
1340                         if ((strcmp(name, DRV_PROP) == 0) &&
1341                             (strcmp(di_prop_name(prop), HSC_MODE) == 0)) {
1342                                 hotswap_mode = p;
1343                                 ret_value = 1;
1344                         } else if ((strcmp(name, DRV_PROP) == 0) &&
1345                             (strcmp(di_prop_name(prop), HSC_MODE) != 0)) {
1346                                 /* save it in order in the right index */
1347                                 slot_auto_config[max_slots_minus_cpu] = p;
1348                                 max_slots_minus_cpu--;
1349                                 ret_value = 1;
1350                         }
1351 
1352                 } else {
1353                         for (i = 0; i < prop_len; ++i)  {
1354 #if     0
1355                                 unsigned char byte;
1356                                 byte = (unsigned char)prop_data[i];
1357                                 log_printf("%2.2x", byte, 0);
1358 #endif
1359                         }
1360                 }
1361         }
1362         return (ret_value);
1363 }
1364 
1365 
1366 void
1367 display_mc_prtdiag_info()
1368 {
1369         int i, index;
1370         int s_index, i1;
1371         int tg_cpu_index = 0;
1372         char *mcfru_type, *status, *mc_ok_led, *mc_nok_led;
1373         char *misc_info, *health, *board_type;
1374 
1375         log_printf("===============================", 0);
1376         log_printf(dgettext(TEXT_DOMAIN,
1377             " FRU Information ================================\n"), 0);
1378         log_printf(dgettext(TEXT_DOMAIN,
1379             "FRU         FRU    FRU      Green    Amber"), 0);
1380         log_printf(dgettext(TEXT_DOMAIN, "    Miscellaneous\n"), 0);
1381         log_printf(dgettext(TEXT_DOMAIN,
1382             "Type        Unit#  Present  LED      LED"), 0);
1383         log_printf(dgettext(TEXT_DOMAIN, "      Information\n"), 0);
1384 
1385         log_printf("----------  -----  -------  -----    -----", 0);
1386         log_printf("    ----------------------------------\n", 0);
1387 
1388         if (scsb_ks_topo.mid_plane.fru_id == SCTRL_MPID_HALF)
1389                 misc_info = "Netra ct800";
1390         else {
1391                 misc_info = "Netra ct400";
1392         }
1393         mcfru_type = prtdiag_fru_types[MIDPLANE];
1394         switch (scsb_ks_topo.mid_plane.fru_status) {
1395                 case FRU_PRESENT:
1396                         status = YES;
1397                         break;
1398                 case FRU_NOT_PRESENT:
1399                         status = NO;
1400                         break;
1401                 case FRU_NOT_AVAILABLE:
1402                         status = NA; break;
1403                 default:
1404                         status = NA; break;
1405                 }
1406         mc_ok_led = "   ";
1407         mc_nok_led = "   ";
1408 
1409         log_printf(dgettext(TEXT_DOMAIN,
1410             "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
1411             mcfru_type, scsb_ks_topo.mid_plane.fru_unit,
1412             status, mc_ok_led, mc_nok_led,
1413             misc_info, 0);
1414         log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0);
1415         log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK,
1416             scsb_ks_topo.mid_plane.fru_version, 0);
1417         log_printf(dgettext(TEXT_DOMAIN, "%49sMaximum Slots=%d\n"), BLANK,
1418             scsb_ks_topo.max_units[SLOT], 0);
1419 
1420         /* SCB & SSB */
1421         mcfru_type = prtdiag_fru_types[SCB];
1422         for (i = 0; i < scsb_ks_topo.max_units[SCB]; ++i) {
1423                 misc_info = "System Controller Board";
1424                 if (version_p15_and_p20) {
1425                         mc_ok_led =
1426                             BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1]
1427                             & 0xff), SCB_OK_BIT) ? BLINK :
1428                             (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1]
1429                             & 0xff), SCB_OK_BIT) ? ON:OFF);
1430                         mc_nok_led =
1431                             BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1]
1432                             & 0xff), SCB_OK_BIT) ? ON:OFF;
1433                 } else {
1434                         /*
1435                          * support for 1.0 systems -
1436                          * Hack! - should use tables ?
1437                          */
1438                         mc_ok_led =
1439                             (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
1440                             & 0xff), 0) ? ON:OFF);
1441                         mc_nok_led =
1442                             BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
1443                             & 0xff), 0) ? ON:OFF;
1444                 }
1445                 switch (scsb_ks_topo.mct_scb[i].fru_status) {
1446                         case FRU_PRESENT:
1447                                 status = YES;
1448                                 break;
1449                         case FRU_NOT_PRESENT:
1450                                 status = NO;
1451                                 break;
1452                         case FRU_NOT_AVAILABLE:
1453                                 status = NA;
1454                                 break;
1455                         default:
1456                                 status = NA;
1457                                 break;
1458                 }
1459                 log_printf(dgettext(TEXT_DOMAIN,
1460                     "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
1461                     mcfru_type, scsb_ks_topo.mct_scb[i].fru_unit,
1462                     status, mc_ok_led, mc_nok_led, misc_info, 0);
1463                 log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0);
1464                 log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK,
1465                     scsb_ks_topo.mct_scb[0].fru_version, 0);
1466                 if (fail_drv_prop == 1)
1467                         log_printf(dgettext(TEXT_DOMAIN,
1468                             "%49s%s=%s\n"), BLANK, HSC_MODE,
1469                             hotswap_mode, 0);
1470         } /* for */
1471 
1472         mcfru_type = prtdiag_fru_types[SSB];
1473         for (i = 0; i < scsb_ks_topo.max_units[SSB]; ++i) {
1474                 misc_info = "System Status Panel";
1475                 switch (scsb_ks_topo.mct_ssb[i].fru_status) {
1476                         case FRU_PRESENT:
1477                                 status = YES;
1478                                 break;
1479                         case FRU_NOT_PRESENT:
1480                                 status = NO;
1481                                 break;
1482                         case FRU_NOT_AVAILABLE:
1483                                 status = NA;
1484                                 break;
1485                         default:
1486                                 status = NA;
1487                                 break;
1488                 }
1489                 log_printf(dgettext(TEXT_DOMAIN,
1490                     "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
1491                     mcfru_type, scsb_ks_topo.mct_ssb[i].fru_unit,
1492                     status, BLANK, BLANK, misc_info, 0);
1493         } /* for */
1494 
1495         /* Slots */
1496         for (i = 0; i < scsb_ks_topo.max_units[SLOT]; ++i) {
1497                 if (montecarlo) {
1498                         if (scsb_ks_topo.mct_slots[i].fru_unit == 1)
1499                                 mcfru_type = prtdiag_fru_types[1];
1500                         else
1501                                 mcfru_type = prtdiag_fru_types[SLOT];
1502                         /*
1503                          * Another way this could have been done is,
1504                          * to read the sub system id
1505                          * it is 0x6722 for Alarm Card
1506                          * but this id is only valid for the new ACs
1507                          * older ACs still have the same susbsystem
1508                          * id as most other Sun PCI cards
1509                          * We cannot completely rely on this.
1510                          * Also,it turns out that Sun OpenBoot does not
1511                          * always follow IEEE 1275 std, hence in a few
1512                          * systems, the "subsystem-id" published by the
1513                          * PROM could not be found
1514                          * We know the AC slot# if present on both MC&Tg
1515                          * Hence we check on both - now we are sure
1516                          * that we have found an AC
1517                          */
1518                         if ((scsb_ks_topo.mct_slots[i].fru_unit == 8) &&
1519                             (alarm_card_present == 1))
1520                                 board_type = AC_CARD;
1521                         else
1522                                 board_type = UK;
1523                 } else {
1524                         if (scsb_ks_topo.mct_slots[i].fru_unit == 3)
1525                                 mcfru_type = prtdiag_fru_types[1];
1526                         else
1527                                 mcfru_type = prtdiag_fru_types[SLOT];
1528                         /*
1529                          * Another way this could have been done is,
1530                          * to read the sub system id
1531                          * it is 0x6722 for Alarm Card
1532                          * but this id is only valid for the new ACs
1533                          * older ACs still have the same susbsystem
1534                          * id as most other Sun PCI cards
1535                          * We cannot completely rely on this.
1536                          * Also,it turns out that Sun OpenBoot does not
1537                          * always follow IEEE 1275 std, hence in a few
1538                          * systems, the "subsystem-id" published by the
1539                          * PROM could not be found
1540                          * We know the AC slot# if present on both MC&Tg
1541                          * Hence we check on both - now we are sure
1542                          * that we have found an AC
1543                          */
1544                         if ((scsb_ks_topo.mct_slots[i].fru_unit == 1) &&
1545                             (alarm_card_present == 1))
1546                                 board_type = AC_CARD;
1547                         else
1548                                 board_type = UK;
1549                 }
1550                 if (version_p15_and_p20) {
1551                         mc_ok_led =
1552                             BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[0]
1553                             & 0xff), i) ? BLINK :
1554                             (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[0]
1555                             & 0xff), i) ? ON:OFF);
1556                         mc_nok_led =
1557                             BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[0]
1558                             & 0xff), i) ? ON:OFF;
1559                 } else {
1560                         /*
1561                          * support for 1.0 systems -
1562                          * Hack! - should use tables ?
1563                          */
1564                         if (scsb_ks_topo.mct_slots[i].fru_unit == 7) {
1565                                 mc_ok_led =
1566                                     BIT_TEST(
1567                                     (scsb_ks_leddata.leds.p10.blink_leds[1]
1568                                     & 0xff), 0) ? BLINK :
1569                                     (BIT_TEST(
1570                                     (scsb_ks_leddata.leds.p10.ok_leds[1]
1571                                     & 0xff), 0) ? ON:OFF);
1572                                 mc_nok_led =
1573                                     BIT_TEST(
1574                                     (scsb_ks_leddata.leds.p10.nok_leds[1]
1575                                     & 0xff), 0) ? ON:OFF;
1576                         } else  if (scsb_ks_topo.mct_slots[i].fru_unit == 8) {
1577                                 mc_ok_led =
1578                                     BIT_TEST(
1579                                     (scsb_ks_leddata.leds.p10.blink_leds[1]
1580                                     & 0xff), 1) ? BLINK :
1581                                     (BIT_TEST(
1582                                     (scsb_ks_leddata.leds.p10.ok_leds[1]
1583                                     & 0xff), 1) ? ON:OFF);
1584                                 mc_nok_led =
1585                                     BIT_TEST(
1586                                     (scsb_ks_leddata.leds.p10.nok_leds[1]
1587                                     & 0xff), 1) ? ON:OFF;
1588                         } else {
1589                                 /*
1590                                  * for all other slots offset,
1591                                  * index are the same
1592                                  */
1593                                 mc_ok_led =
1594                                     BIT_TEST(
1595                                     (scsb_ks_leddata.leds.p10.blink_leds[0]
1596                                     & 0xff), i) ? BLINK :
1597                                     (BIT_TEST(
1598                                     (scsb_ks_leddata.leds.p10.ok_leds[0]
1599                                     & 0xff), i) ? ON:OFF);
1600                                 mc_nok_led =
1601                                     BIT_TEST(
1602                                     (scsb_ks_leddata.leds.p10.nok_leds[0]
1603                                     & 0xff), i) ? ON:OFF;
1604                         }
1605 
1606                 } /* else if (!version_p15_and_p20) */
1607 
1608                 switch (scsb_ks_topo.mct_slots[i].fru_status) {
1609                         case FRU_PRESENT:
1610                                 status = YES;
1611                                 break;
1612                         case FRU_NOT_PRESENT:
1613                                 status = NO;
1614                                 break;
1615                         case FRU_NOT_AVAILABLE:
1616                                 status = NA;
1617                                 break;
1618                         default:
1619                                 status = NA;
1620                                 break;
1621                 }
1622 
1623                 index = (int)scsb_ks_topo.mct_slots[i].fru_type;
1624                 if (montecarlo) {
1625                         if (scsb_ks_topo.mct_slots[i].fru_unit == 1) {
1626                                 /* cpu slot */
1627                                 log_printf(dgettext(TEXT_DOMAIN,
1628                                     "%10s   %-5d  %-7s %-5s    "),
1629                                     mcfru_type,
1630                                     scsb_ks_topo.mct_slots[i].fru_unit,
1631                                     status, mc_ok_led, mc_nok_led, 0);
1632                                 log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
1633                                     mc_nok_led,
1634                                     slot_occupants[index], 0);
1635                                 log_printf(dgettext(TEXT_DOMAIN,
1636                                     "%49stemperature(celsius):%d\n"),
1637                                     BLANK,
1638                                     pcf8591_ks_temp.value, 0);
1639 #ifdef  NEVER
1640                                 log_printf(dgettext(TEXT_DOMAIN,
1641                                     "%49sminimum temperature:%d\n"),
1642                                     BLANK,
1643                                     pcf8591_ks_temp.min, 0);
1644                                 log_printf(dgettext(TEXT_DOMAIN,
1645                                     "%49swarning temp. threshold:%d\n"),
1646                                     BLANK,
1647                                     pcf8591_ks_temp.warning_threshold, 0);
1648                                 log_printf(dgettext(TEXT_DOMAIN,
1649                                     "%49sshutdown temp.threshold:%d\n"),
1650                                     BLANK,
1651                                     pcf8591_ks_temp.shutdown_threshold, 0);
1652 #endif  /* NEVER */
1653                         } else if ((scsb_ks_topo.mct_slots[i].fru_unit == 2) &&
1654                             (cpu_ftm_present == 1)) {
1655                                 /* CFTM slot */
1656                                 /*
1657                                  * The CFTM can only be present in Slot 2
1658                                  * for Netract-800, for Netract-400 the FTM
1659                                  * is not sitted in a Slot. Hence, this is
1660                                  * another special case and we need to handle
1661                                  * this differently than other slots
1662                                  */
1663                                 log_printf(dgettext(TEXT_DOMAIN,
1664                                     "%10s   %-5d  %-7s %-5s    "),
1665                                     mcfru_type,
1666                                     scsb_ks_topo.mct_slots[i].fru_unit,
1667                                     status, mc_ok_led, mc_nok_led, 0);
1668                                 log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
1669                                     mc_nok_led,
1670                                     CPU_FTM, 0);
1671                         } else {
1672                                 if (fail_drv_prop == 1) {
1673                                         log_printf(dgettext(TEXT_DOMAIN,
1674                                             "%10s   %-5d  %-7s %-5s    "),
1675                                             mcfru_type,
1676                                             scsb_ks_topo.mct_slots[i].fru_unit,
1677                                             status, mc_ok_led, 0);
1678                                         log_printf(dgettext(TEXT_DOMAIN,
1679                                             "%-5s   %s\n"),
1680                                             mc_nok_led,
1681                                             slot_occupants[index], 0);
1682                                         log_printf(dgettext(TEXT_DOMAIN,
1683                                             "%46s%s\n"), BLANK,
1684                                             PROPS, 0);
1685                                         log_printf(dgettext(TEXT_DOMAIN,
1686                                             "%49sauto-config=%s\n"),
1687                                             BLANK,
1688                                             slot_auto_config[i], 0);
1689                                 } else {
1690                                 log_printf(dgettext(TEXT_DOMAIN,
1691                                     "%10s   %-5d  %-7s %-5s    "),
1692                                     mcfru_type,
1693                                     scsb_ks_topo.mct_slots[i].fru_unit,
1694                                     status, mc_ok_led, 0);
1695                                 log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
1696                                     mc_nok_led,
1697                                     slot_occupants[index], 0);
1698                                 }
1699                         }
1700                 } else { /* tonga */
1701                         if (scsb_ks_topo.mct_slots[i].fru_unit == 3) {
1702                                 /* cpu slot */
1703                                 log_printf(dgettext(TEXT_DOMAIN,
1704                                     "%10s   %-5d  %-7s %-5s    "),
1705                                     mcfru_type,
1706                                     scsb_ks_topo.mct_slots[i].fru_unit,
1707                                     status, mc_ok_led, 0);
1708                                 log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
1709                                     mc_nok_led,
1710                                     slot_occupants[index], 0);
1711                                 log_printf(dgettext(TEXT_DOMAIN,
1712                                     "%49stemperature(celsius):%d\n"),
1713                                     BLANK,
1714                                     pcf8591_ks_temp.value, 0);
1715 #ifdef  NEVER
1716 
1717                                 log_printf(dgettext(TEXT_DOMAIN,
1718                                     "%49sminimum temperature:%d\n"),
1719                                     BLANK,
1720                                     pcf8591_ks_temp.min, 0);
1721                                 log_printf(dgettext(TEXT_DOMAIN,
1722                                     "%49swarning temp. threshold:%d\n"),
1723                                     BLANK,
1724                                     pcf8591_ks_temp.warning_threshold, 0);
1725                                 log_printf(dgettext(TEXT_DOMAIN,
1726                                     "%49sshutdown temp. threshold:%d\n"),
1727                                     BLANK,
1728                                     pcf8591_ks_temp.shutdown_threshold, 0);
1729 #endif  /* NEVER */
1730                         } else {
1731                                 if (fail_drv_prop == 1) {
1732                                         log_printf(dgettext(TEXT_DOMAIN,
1733                                             "%10s   %-5d  %-7s %-5s    "),
1734                                             mcfru_type,
1735                                             scsb_ks_topo.mct_slots[i].fru_unit,
1736                                             status, mc_ok_led, 0);
1737                                         log_printf(dgettext(TEXT_DOMAIN,
1738                                             "%-5s   %s\n"),
1739                                             mc_nok_led,
1740                                             slot_occupants[index], 0);
1741 
1742                                         log_printf(dgettext(TEXT_DOMAIN,
1743                                             "%46s%s\n"), BLANK, PROPS, 0);
1744                                         log_printf(dgettext(TEXT_DOMAIN,
1745                                             "%49sauto-config=%s\n"),
1746                                             BLANK,
1747                                             slot_auto_config[tg_cpu_index+1],
1748                                             0);
1749                                         if (scsb_ks_topo.mct_slots[i].fru_unit
1750                                             != 3)
1751                                                 tg_cpu_index++;
1752                                 } else {
1753                                 log_printf(dgettext(TEXT_DOMAIN,
1754                                     "%10s   %-5d  %-7s %-5s    "),
1755                                     mcfru_type,
1756                                     scsb_ks_topo.mct_slots[i].fru_unit,
1757                                     status, mc_ok_led, 0);
1758                                 log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
1759                                     mc_nok_led,
1760                                     slot_occupants[index], 0);
1761                                 }
1762                         }
1763                 }
1764                 /* we first match the correct slot numbers */
1765                 for (s_index = 0; s_index < slot_table_size; s_index++) {
1766                         if (slot_table_not_found == 1) {
1767                         /* use prom table */
1768                         if (scsb_ks_topo.mct_slots[i].fru_unit ==
1769                             prom_slot_table[s_index].pslotnum) {
1770                                 /*
1771                                  * search for the addr/pci num
1772                                  * in all slot info structs
1773                                  */
1774                                 for (i1 = 0; i1 < slot_index;
1775                                     i1++) {
1776                         if (prom_slot_table[s_index].pci_devno ==
1777                             mc_slots_data.mc_slot_info[i1].slot_addr) {
1778                                         int nd;
1779                                         log_printf(dgettext(TEXT_DOMAIN,
1780                                             "%46s%s%s\n"), BLANK,
1781                                             BOARDTYPE, board_type, 0);
1782                                         log_printf(dgettext(TEXT_DOMAIN,
1783                                             "%46s%s\n"), BLANK, DEVS, 0);
1784                                         log_printf(dgettext(TEXT_DOMAIN,
1785                                             "%49s%s\n"), BLANK,
1786                                             PCI_ROOT_AP, 0);
1787                         for (nd = 0;
1788                             nd < mc_slots_data.mc_slot_info[i1].number_devs;
1789                             nd++) {
1790                         log_printf(dgettext(TEXT_DOMAIN, "%52s%s\n"), BLANK,
1791                             mc_slots_data.mc_slot_info[i1].devs_info[nd],
1792                             0);
1793                                                 } /* for */
1794 
1795                                         } /* if */
1796 
1797                                 } /* for(i1) */
1798 
1799                         } /* if */
1800 
1801                 } else {
1802                         /* use solaris lot table */
1803                         if (fail_syssoft_prop == 1) {
1804                                 if (scsb_ks_topo.mct_slots[i].fru_unit ==
1805                                     hotswap_slot_table[s_index].pslotnum) {
1806                                         /*
1807                                          * search for the addr/pci
1808                                          * num in all slot info structs
1809                                          */
1810                                         for (i1 = 0; i1 < slot_index; i1++) {
1811                                 if (hotswap_slot_table[s_index].pci_devno ==
1812                                     mc_slots_data.mc_slot_info[i1].slot_addr) {
1813                                         int nd;
1814                         for (nd = 0;
1815                             nd < mc_slots_data.mc_slot_info[i1].number_devs;
1816                             nd++) {
1817                         log_printf(dgettext(TEXT_DOMAIN, "%49s%s\n"), BLANK,
1818                             mc_slots_data.mc_slot_info[i1].devs_info[nd],
1819                             0);
1820                                                         }
1821                                                 } /* if */
1822 
1823                                         } /* for(i1) */
1824 
1825                                 } /* if */
1826 
1827                         } /* (fail_syssoft_prop == 1) */
1828 
1829                         }  /* (slot_table_not_found == 1) */
1830 
1831                 } /* for(s_index) */
1832 
1833         }       /* for */
1834         mcfru_type = "PDU";
1835         misc_info = "Power Distribution Unit";
1836         for (i = 0; i < scsb_ks_topo.max_units[PDU]; ++i) {
1837                 if (version_p15_and_p20) {
1838                         mc_ok_led =
1839                             BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1]
1840                             & 0xff), PDU1_OK_BIT+i*2) ? BLINK :
1841                             (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1]
1842                             & 0xff), PDU1_OK_BIT+i*2) ? ON:OFF);
1843                         mc_nok_led =
1844                             BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1]
1845                             & 0xff), PDU1_OK_BIT+i*2) ? ON:OFF;
1846                 }
1847                 switch (scsb_ks_topo.mct_pdu[i].fru_status) {
1848                         case FRU_PRESENT:
1849                                 status = YES;
1850                                 break;
1851                         case FRU_NOT_PRESENT:
1852                                 status = NO;
1853                                 break;
1854                         case FRU_NOT_AVAILABLE:
1855                                 status = NA;
1856                                 break;
1857                         default:
1858                                 status = NA;
1859                                 break;
1860                 }
1861                 if (version_p15_and_p20) {
1862                         log_printf(dgettext(TEXT_DOMAIN,
1863                             "%-10s    %-5d  %-7s %-5s    %-5s   %s\n"),
1864                             mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit,
1865                             status, mc_ok_led, mc_nok_led, misc_info, 0);
1866                 } else {
1867                         log_printf(dgettext(TEXT_DOMAIN,
1868                             "%-10s    %-5d  %-7s%18s%s\n"),
1869                             mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit,
1870                             status, BLANK, misc_info, 0);
1871                 }
1872         } /* for */
1873 
1874         /* PS */
1875         mcfru_type = prtdiag_fru_types[PS];
1876         misc_info = "Power Supply Unit";
1877         for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
1878                 if (version_p15_and_p20) {
1879                         mc_ok_led =
1880                             BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2]
1881                             & 0xff), PS1_OK_BIT+i) ? BLINK :
1882                             (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
1883                             & 0xff), PS1_OK_BIT+i) ? ON:OFF);
1884                         mc_nok_led =
1885                             BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
1886                             & 0xff), PS1_OK_BIT+i) ? ON:OFF;
1887                 } else {
1888                         /*
1889                          * support for 1.0 systems -
1890                          * Hack! - should use tables ?
1891                          */
1892                         mc_ok_led =
1893                             (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
1894                             & 0xff), 1+i) ? ON:OFF);
1895                         mc_nok_led =
1896                             BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
1897                             & 0xff), 1+i) ? ON:OFF;
1898                 }
1899                 switch (scsb_ks_topo.mct_ps[i].fru_status) {
1900                         case FRU_PRESENT:
1901                                 status = YES;
1902                                 break;
1903                         case FRU_NOT_PRESENT:
1904                                 status = NO;
1905                                 break;
1906                         case FRU_NOT_AVAILABLE:
1907                                 status = NA;
1908                                 break;
1909                         default:
1910                                 status = NA;
1911                                 break;
1912                 }
1913                 log_printf(dgettext(TEXT_DOMAIN,
1914                     "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
1915                     mcfru_type, scsb_ks_topo.mct_ps[i].fru_unit,
1916                     status, mc_ok_led, mc_nok_led,
1917                     misc_info, 0);
1918                 if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) {
1919                         if (scsb_ks_topo.mct_ps[i].fru_unit == 1) {
1920                                 log_printf(dgettext(TEXT_DOMAIN,
1921                                     "%49scondition:%s\n"), BLANK,
1922                                     ((pcf8574_ks_ps1.ps_ok)? NOK:OK), 0);
1923                                 log_printf(dgettext(TEXT_DOMAIN,
1924                                     "%49stemperature:%s\n"), BLANK,
1925                                     ((pcf8574_ks_ps1.temp_ok)? NOK:OK), 0);
1926                                 log_printf(dgettext(TEXT_DOMAIN,
1927                                     "%49sps fan:%s\n"), BLANK,
1928                                     ((pcf8574_ks_ps1.psfan_ok)? NOK:OK), 0);
1929                                 log_printf(dgettext(TEXT_DOMAIN,
1930                                     "%49ssupply:%s\n"), BLANK,
1931                                     ((pcf8574_ks_ps1.on_state)? OFF:ON), 0);
1932                         } else {
1933                                 log_printf(dgettext(TEXT_DOMAIN,
1934                                     "%49scondition:%s\n"), BLANK,
1935                                     ((pcf8574_ks_ps2.ps_ok)? NOK:OK), 0);
1936                                 log_printf(dgettext(TEXT_DOMAIN,
1937                                     "%49stemperature:%s\n"), BLANK,
1938                                     ((pcf8574_ks_ps2.temp_ok)? NOK:OK), 0);
1939                                 log_printf(dgettext(TEXT_DOMAIN,
1940                                     "%49sps fan:%s\n"), BLANK,
1941                                     ((pcf8574_ks_ps2.psfan_ok)? NOK:OK), 0);
1942                                 log_printf(dgettext(TEXT_DOMAIN,
1943                                     "%49ssupply:%s\n"), BLANK,
1944                                     ((pcf8574_ks_ps2.on_state)? OFF:ON), 0);
1945                         } /* if */
1946                 }
1947 
1948         } /* for */
1949 
1950         /* Fan tray */
1951         mcfru_type = prtdiag_fru_types[FAN];
1952         misc_info = "Fan Tray";
1953         for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) {
1954                 if (version_p15_and_p20) {
1955                         mc_ok_led =
1956                             BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2]
1957                             & 0xff), FAN1_OK_BIT+i) ? BLINK :
1958                             (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
1959                             & 0xff), FAN1_OK_BIT+i) ? ON:OFF);
1960                         mc_nok_led =
1961                             BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
1962                             & 0xff), FAN1_OK_BIT+i) ? ON:OFF;
1963                 } else {
1964                         /*
1965                          * support for 1.0 systems -
1966                          * Hack! - should use tables ?
1967                          */
1968                         mc_ok_led =
1969                             (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[3]
1970                             & 0xff), 3+i) ? ON:OFF);
1971                         mc_nok_led =
1972                             BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[3]
1973                             & 0xff), 3+i) ? ON:OFF;
1974                 }
1975                 switch (scsb_ks_topo.mct_fan[i].fru_status) {
1976                         case FRU_PRESENT:
1977                                 status = YES;
1978                                 break;
1979                         case FRU_NOT_PRESENT:
1980                                 status = NO;
1981                                 break;
1982                         case FRU_NOT_AVAILABLE:
1983                                 status = NA;
1984                                 break;
1985                         default:
1986                                 status = NA;
1987                                 break;
1988                 }
1989                 log_printf(dgettext(TEXT_DOMAIN,
1990                     "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
1991                     mcfru_type, scsb_ks_topo.mct_fan[i].fru_unit,
1992                     status, mc_ok_led, mc_nok_led,
1993                     misc_info, 0);
1994                 if (scsb_ks_topo.mct_fan[i].fru_status == FRU_PRESENT) {
1995                         if (scsb_ks_topo.mct_fan[i].fru_unit == 1) {
1996                                 log_printf(dgettext(TEXT_DOMAIN,
1997                                     "%49scondition:%s\n"), BLANK,
1998                                     ((pcf8574_ks_fant1.fan_ok)? OK:NOK), 0);
1999                                 log_printf(dgettext(TEXT_DOMAIN,
2000                                     "%49sfan speed:%s\n"), BLANK,
2001                                     ((pcf8574_ks_fant1.fanspeed)? HI:LO), 0);
2002                         } else {
2003                                 log_printf(dgettext(TEXT_DOMAIN,
2004                                     "%49scondition:%s\n"), BLANK,
2005                                     ((pcf8574_ks_fant2.fan_ok)? OK:NOK), 0);
2006                                 log_printf(dgettext(TEXT_DOMAIN,
2007                                     "%49sfan speed:%s\n"), BLANK,
2008                                     ((pcf8574_ks_fant2.fanspeed)? HI:LO), 0);
2009                         }
2010                 }
2011 
2012         } /* for */
2013 
2014         /* DISKS */
2015         for (i = 0; i < scsb_ks_topo.max_units[DISK]; ++i) {
2016                 if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER)
2017                         mcfru_type = prtdiag_fru_types[DISK];
2018                 else
2019                         mcfru_type = "RMM        ";
2020                 switch (scsb_ks_topo.mct_disk[i].fru_status) {
2021                         case FRU_PRESENT:
2022                                 status = YES;
2023                                 break;
2024                         case FRU_NOT_PRESENT:
2025                                 status = NO;
2026                                 break;
2027                         case FRU_NOT_AVAILABLE:
2028                                 status = NA;
2029                                 break;
2030                         default:
2031                                 status = NA;
2032                                 break;
2033                 }
2034                 if (version_p15_and_p20) {
2035                         mc_ok_led =
2036                             BIT_TEST((scsb_ks_leddata.scb_led_regs[8]
2037                             & 0xff), DISK1_OK_BIT+i) ? BLINK :
2038                             (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
2039                             & 0xff), DISK1_OK_BIT+i) ? ON:OFF);
2040                         mc_nok_led =
2041                             BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
2042                             & 0xff), DISK1_OK_BIT+i) ? ON:OFF;
2043                 } else {
2044                         /*
2045                          * support for 1.0 systems -
2046                          * Hack! - should use tables ?
2047                          */
2048                         mc_ok_led =
2049                             (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
2050                             & 0xff), DISK1_OK_BIT+i) ? ON:OFF);
2051                         mc_nok_led =
2052                             BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
2053                             & 0xff), DISK1_OK_BIT+i) ? ON:OFF;
2054                 }
2055                 /* print everything except condition */
2056                 if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER) {
2057                         misc_info = "Hard Disk Drive";
2058                         log_printf(dgettext(TEXT_DOMAIN,
2059                             "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
2060                             mcfru_type, scsb_ks_topo.mct_disk[i].fru_unit-1,
2061                             status, mc_ok_led, mc_nok_led, misc_info, 0);
2062                 } else {
2063                         misc_info = "Removable Media Module";
2064                         log_printf(dgettext(TEXT_DOMAIN,
2065                             "%10s   %5s  %-7s %-5s    %-5s   %s\n"),
2066                             mcfru_type, BLANK,
2067                             status, mc_ok_led, mc_nok_led, misc_info, 0);
2068                 }
2069 
2070                 /* find out fru health from the SCSI drivers */
2071                 if (scsb_ks_topo.mct_disk[i].fru_status == FRU_PRESENT) {
2072                         switch (
2073                             scsi_disk_status(
2074                             scsb_ks_topo.mct_disk[i].fru_unit)) {
2075                                 case 0:
2076                                         health = OK;
2077                                         break;
2078                                 case 1:
2079                                         health = NOK;
2080                                         break;
2081                                 case -1:
2082                                         health = UK;
2083                                         break;
2084                                 default:
2085                                         health = NA;
2086                                         break;
2087                         }
2088                         log_printf(dgettext(TEXT_DOMAIN,
2089                             "%49scondition:%s\n"), BLANK, health, 0);
2090                 }
2091 
2092         }       /* for */
2093 
2094         log_printf(dgettext(TEXT_DOMAIN, "\n"), 0);
2095 
2096 }       /*  display_mc_prtdiag_info() */
2097 
2098 
2099 void
2100 analyze_pcipci_siblings(di_node_t node)
2101 {
2102         di_node_t lc_node;
2103         /* we will find all the dev info for slots first */
2104         lc_node = di_drv_first_node("pci_pci", node);
2105         lc_node = di_child_node(lc_node);
2106         /* we are at "pci" node now */
2107         do  {
2108                 if (di_walk_node(lc_node, DI_WALK_CLDFIRST,
2109                     NULL, analyze_nodes) != 0) {
2110                         return;
2111                 }
2112         } while ((lc_node = di_sibling_node(lc_node)) != DI_NODE_NIL);
2113 
2114         /* now we wll gather info on sysctrl */
2115         lc_node = di_drv_first_node(SCSB_DEV, node);
2116         if (lc_node != DI_NODE_NIL)
2117                 analyze_nodes(lc_node, "sysctrl");
2118 }       /* analyze_pcipci_siblings(.) */
2119 
2120 
2121 int
2122 analyze_nodes(di_node_t l_node, void *arg)
2123 {
2124         char *temp;
2125         char *name, *pname;
2126         di_node_t parent;
2127         /*
2128          *  we will figure out whether the parent node is "pci" type
2129          *  we will save info only in this case as we only want to
2130          * print out the nodes under AP and not others
2131          */
2132         parent = di_parent_node(l_node);
2133         pname =  di_node_name(parent);
2134         name = di_node_name(l_node);
2135         /*
2136          * if this is PCI bridge, we know that this is the AP for slots
2137          * hence, we will save off the address(to convert to slot mapping)
2138          * later, and also we will start saving off slot info struct for
2139          * reporting later
2140          * we will save the immediate childs of this bridge only
2141          */
2142         if (strcmp(name, "pci") == 0) {
2143                 num_devs = 0;
2144                 if ((temp = di_bus_addr(l_node)) != NULL) {
2145                         mc_slots_data.mc_slot_info[slot_index].slot_addr
2146                             = (int)strtol(temp, (char **)NULL, 16);
2147                 }
2148                 slot_index++;
2149         } else {
2150                 if (strcmp(pname, "pci") == 0) {
2151         if ((mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs])
2152             != NULL) {
2153         (void) strcat(
2154             mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs],
2155             name);
2156                         } else {
2157         (void) strcpy(
2158             mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs],
2159             name);
2160                         } /* if ((mc_slots_data.mc_slot_inf */
2161 
2162                         num_devs++;
2163                         mc_slots_data.mc_slot_info[slot_index-1].number_devs
2164                             = num_devs;
2165                 } /* if parent is pci */
2166 
2167         } /* if node is pci */
2168         if (arg != NULL) {
2169                 if (strcmp((char *)arg, "sysctrl") == 0) {
2170                         if (dump_prop_list("System", l_node,
2171                             di_prop_sys_next)) {
2172                                 (void) dump_prop_list(NULL, l_node,
2173                                     di_prop_global_next);
2174                         } else {
2175                                 fail_syssoft_prop =
2176                                     dump_prop_list(SYSSOFT_PROP,
2177                                     l_node, di_prop_global_next);
2178                         }
2179 
2180                         fail_drv_prop =
2181                             dump_prop_list(DRV_PROP, l_node,
2182                             di_prop_drv_next);
2183                         /*
2184                          * (void) dump_prop_list("Hardware",
2185                          *   l_node, di_prop_hw_next);
2186                          */
2187                         /*  dump_priv_data(l_node); */
2188                 }
2189         }
2190 
2191         return  (0);
2192 
2193 }       /* analyze_nodes(..) */
2194 
2195 
2196 
2197 /*
2198  * To get the slot information,
2199  * The OBP defines the 'slot-table' property. But the OS
2200  * can override it with 'hsc-slot-map' property
2201  * through the .conf file.
2202  * Since the formats are different, 2 different property names
2203  * are chosen.
2204  * The OBP property format is
2205  * <phandle>,<pci-devno>,<phys-slotno>,<ga-bits>
2206  * The OS property format is (ga-bits is not used however)
2207  * <busnexus-path>,<pci-devno>,<phys-slotno>,<ga-bits>
2208  * returns 0 on error, 1 otherwise
2209  */
2210 int
2211 extract_slot_table_from_obp()
2212 {
2213         if (mc_promopen(O_RDONLY))  {
2214                 log_printf(dgettext(TEXT_DOMAIN,
2215                     "\ncannot open openprom device"), 0);
2216                 return (0);
2217         }
2218 
2219         if (mc_next(0) == 0)
2220                 return (0);
2221         mc_walk(mc_next(0));
2222 
2223         if (close(oprom_fd) < 0) {
2224                 log_printf(dgettext(TEXT_DOMAIN,
2225                     "\nclose error on %s"), OPENPROMDEV, 0);
2226                 return (0);
2227         }
2228 
2229         return (1);
2230 
2231 }       /* extract_slot_table_from_obp() */
2232 
2233 
2234 int
2235 mc_next(int id)
2236 {
2237         Oppbuf  oppbuf;
2238         struct openpromio *opp = &(oppbuf.opp);
2239 
2240         bzero(oppbuf.buf, BUFSIZE);
2241         opp->oprom_size = MAXVALSIZE;
2242         opp->oprom_node = id;
2243         if (ioctl(oprom_fd, OPROMNEXT, opp) < 0) {
2244                 log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMNEXT"), 0);
2245                 return (0);
2246         }
2247         return (opp->oprom_node);
2248 
2249 }       /* mc_next(.) */
2250 
2251 
2252 void
2253 mc_walk(int id)
2254 {
2255         int curnode;
2256         mc_dump_node(id);
2257         if (curnode = mc_child(id))
2258                 mc_walk(curnode);
2259         if (curnode = mc_next(id))
2260                 mc_walk(curnode);
2261 }       /*  mc_walk(.) */
2262 
2263 int
2264 mc_child(int id)
2265 {
2266         Oppbuf  oppbuf;
2267         struct openpromio *opp = &(oppbuf.opp);
2268 
2269         bzero(oppbuf.buf, BUFSIZE);
2270         opp->oprom_size = MAXVALSIZE;
2271         opp->oprom_node = id;
2272         if (ioctl(oprom_fd, OPROMCHILD, opp) < 0) {
2273                 perror("\nOPROMCHILD");
2274                 exit(0);
2275         }
2276         return (opp->oprom_node);
2277 
2278 }       /* mc_child(.) */
2279 
2280 
2281 /*
2282  * Print all properties and values
2283  */
2284 void
2285 mc_dump_node(int id)
2286 {
2287         int k;
2288         Oppbuf  oppbuf;
2289         hsc_prom_slot_table_t   *hpstp;
2290         struct openpromio *opp = &(oppbuf.opp);
2291 
2292         /* get first prop by asking for null string */
2293         bzero(oppbuf.buf, BUFSIZE);
2294         for (;;) {
2295                 /*
2296                  * get next property name
2297                  */
2298                 opp->oprom_size = MAXNAMESZ;
2299 
2300                 if (ioctl(oprom_fd, OPROMNXTPROP, opp) < 0) {
2301                         perror("\nOPROMNXTPROP");
2302                         return;
2303                 }
2304                 if (opp->oprom_size == 0)
2305                         break;
2306                 if (strcmp(opp->oprom_array, "slot-table") == 0) {
2307                         if (mc_getpropval(opp) || opp->oprom_size
2308                             == (uint_t)-1) {
2309                                 log_printf(dgettext(TEXT_DOMAIN,
2310                                     "\ndata not available"), 0);
2311                                 return;
2312                         } else {
2313                                 slot_table_size =
2314                                     opp->oprom_size /
2315                                     sizeof (hsc_prom_slot_table_t);
2316                                 hpstp =
2317                                     (hsc_prom_slot_table_t *)opp->oprom_array;
2318                                 for (k = 0; k < slot_table_size; k++, hpstp++) {
2319                                         prom_slot_table[k].pslotnum =
2320                                             hpstp->pslotnum;
2321                                         prom_slot_table[k].ga =
2322                                             hpstp->ga;
2323                                         prom_slot_table[k].pci_devno =
2324                                             hpstp->pci_devno;
2325                                         prom_slot_table[k].phandle =
2326                                             hpstp->phandle;
2327                                 } /* for (k = 0; k < slot_table_size; k++) */
2328 
2329                         }
2330                 }
2331         }
2332 
2333 }       /* mc_dump_node(.) */
2334 
2335 
2336 int
2337 mc_getpropval(struct openpromio *opp)
2338 {
2339         opp->oprom_size = MAXVALSIZE;
2340         if (ioctl(oprom_fd, OPROMGETPROP, opp) < 0) {
2341                 log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMGETPROP"), 0);
2342                 return (1);
2343         }
2344         return (0);
2345 
2346 }       /* mc_getpropval(.) */
2347 
2348 
2349 
2350 /*
2351  * This function returns nothing.
2352  */
2353 void
2354 alarm_card_occupant()
2355 {
2356         int             scsb_fd;
2357         scsb_ioc_rdwr_t ioc_read;
2358         uint8_t         new_mode = 0;
2359         uint8_t         old_mode = 0;
2360         uchar_t         reg_index;
2361 
2362         if (NULL == scsb_node) {
2363                 if (check_platform() == -1) {
2364                         return;
2365                 }
2366         }
2367 
2368         if (version_p15_and_p20 == 1)
2369                 reg_index = 0xe9;       /* config status reg offset on SCB */
2370         else
2371                 reg_index = 0xd7;       /* config status reg offset on SCB */
2372 
2373         if ((scsb_fd = open(scsb_node, O_RDONLY)) < 0)  {
2374                 log_printf(dgettext(TEXT_DOMAIN,
2375                     "\n%s open failed"), scsb_node, 0);
2376                 return;
2377         }
2378 
2379         /* save off the old mode */
2380         if (scsb_mode(scsb_fd, GET, &old_mode) == 0)
2381                 return;
2382         /* we put scsb in diag mode to read this specific ioctl */
2383         new_mode = ENVCTRL_DIAG_MODE;
2384         if (scsb_mode(scsb_fd, SET, &new_mode) == 0)
2385                 return;
2386         /* now lets read the config register */
2387         if (scsb_ioc_reg_read(scsb_fd, reg_index, &ioc_read, 1) == 0)
2388                 return;
2389         /* restore the original mode */
2390         if (scsb_mode(scsb_fd, SET, &old_mode) == 0)
2391                 return;
2392         alarm_card_present = (BIT_TEST(ioc_read.ioc_rbuf[0]&0xff, 0) ? 1:0);
2393 
2394 }       /* alarm_card_occupant() */
2395 
2396 
2397 /*
2398  * This function changes the SCSB mode to the desired one
2399  * 1 on sucess, 0 otherwise
2400  */
2401 int
2402 scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode)
2403 {
2404         struct strioctl sioc;
2405 
2406         if (sop == GET)
2407                 sioc.ic_cmd = ENVC_IOC_GETMODE;
2408         else
2409                 sioc.ic_cmd = ENVC_IOC_SETMODE;
2410 
2411         sioc.ic_timout = 0;
2412         sioc.ic_len = sizeof (uint8_t);
2413         sioc.ic_dp = (char *)new_mode;
2414 
2415 
2416         if (ioctl(fd, I_STR, &sioc) == -1) {
2417                 log_printf(dgettext(TEXT_DOMAIN,
2418                     "\nscsb_mode():scsb ioctl() failed"), 0);
2419                 return (0);
2420         }
2421         return (1);
2422 
2423 }       /* scsb_mode(...) */
2424 
2425 
2426 /*
2427  * 1 on success, 0 otherwise
2428  */
2429 int
2430 scsb_ioc_reg_read(int fd, uchar_t index, scsb_ioc_rdwr_t *ioc_rd, int num)
2431 {
2432         struct strioctl         sioc;
2433         scsb_ioc_rdwr_t         *rdwrp;
2434 
2435         rdwrp = ioc_rd;
2436         sioc.ic_timout = 0;
2437         sioc.ic_len = sizeof (scsb_ioc_rdwr_t);
2438         sioc.ic_dp = (char *)rdwrp;
2439         /* setup read command before ioctl */
2440         sioc.ic_cmd = SCSBIOC_REG_READ;
2441         rdwrp->ioc_wlen = 0;
2442         rdwrp->ioc_rlen = num;
2443         rdwrp->ioc_regindex = index;
2444         if (ioctl(fd, I_STR, &sioc) == -1) {
2445                 log_printf(dgettext(TEXT_DOMAIN,
2446                     "scsb_ioc_reg_read(): scsb ioctl() failed\n"), 0);
2447                 return (0);
2448         }
2449         return (1);
2450 
2451 }       /* scsb_ioc_reg_read(....) */