Print this page
    
10135 picl plugins need smatch fixes
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/picl/plugins/common/devtree/picldevtree.c
          +++ new/usr/src/cmd/picl/plugins/common/devtree/picldevtree.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  
    | 
      ↓ open down ↓ | 
    16 lines elided | 
    
      ↑ open up ↑ | 
  
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  /*
       27 + * Copyright (c) 2018, Joyent, Inc.
       28 + */
       29 +
       30 +/*
  27   31   * PICL plug-in that creates device tree nodes for all platforms
  28   32   */
  29   33  
  30   34  #include <stdio.h>
  31   35  #include <string.h>
  32   36  #include <ctype.h>
  33   37  #include <limits.h>
  34   38  #include <stdlib.h>
  35   39  #include <assert.h>
  36   40  #include <alloca.h>
  37   41  #include <unistd.h>
  38   42  #include <stropts.h>
  39   43  #include <syslog.h>
  40   44  #include <libdevinfo.h>
  41   45  #include <sys/dkio.h>
  42   46  #include <sys/vtoc.h>
  43   47  #include <sys/time.h>
  44   48  #include <fcntl.h>
  45   49  #include <picl.h>
  46   50  #include <picltree.h>
  47   51  #include <sys/types.h>
  48   52  #include <sys/processor.h>
  49   53  #include <kstat.h>
  50   54  #include <sys/sysinfo.h>
  51   55  #include <dirent.h>
  52   56  #include <libintl.h>
  53   57  #include <pthread.h>
  54   58  #include <libnvpair.h>
  55   59  #include <sys/utsname.h>
  56   60  #include <sys/systeminfo.h>
  57   61  #include <sys/obpdefs.h>
  58   62  #include <sys/openpromio.h>
  59   63  #include "picldevtree.h"
  60   64  
  61   65  /*
  62   66   * Plugin registration entry points
  63   67   */
  64   68  static void     picldevtree_register(void);
  65   69  static void     picldevtree_init(void);
  66   70  static void     picldevtree_fini(void);
  67   71  
  68   72  static void     picldevtree_evhandler(const char *ename, const void *earg,
  69   73                      size_t size, void *cookie);
  70   74  
  71   75  #pragma init(picldevtree_register)
  72   76  
  73   77  /*
  74   78   * Log message texts
  75   79   */
  76   80  #define DEVINFO_PLUGIN_INIT_FAILED      gettext("SUNW_picldevtree failed!\n")
  77   81  #define PICL_EVENT_DROPPED      \
  78   82          gettext("SUNW_picldevtree '%s' event dropped.\n")
  79   83  
  80   84  /*
  81   85   * Macro to get PCI device id (from IEEE 1275 spec)
  82   86   */
  83   87  #define PCI_DEVICE_ID(x)                        (((x) >> 11) & 0x1f)
  84   88  /*
  85   89   * Local variables
  86   90   */
  87   91  static picld_plugin_reg_t  my_reg_info = {
  88   92          PICLD_PLUGIN_VERSION_1,
  89   93          PICLD_PLUGIN_CRITICAL,
  90   94          "SUNW_picldevtree",
  91   95          picldevtree_init,
  92   96          picldevtree_fini
  93   97  };
  94   98  
  95   99  /*
  96  100   * Debug enabling environment variable
  97  101   */
  98  102  #define SUNW_PICLDEVTREE_PLUGIN_DEBUG   "SUNW_PICLDEVTREE_PLUGIN_DEBUG"
  99  103  static  int             picldevtree_debug = 0;
 100  104  
 101  105  static  conf_entries_t  *conf_name_class_map = NULL;
 102  106  static  builtin_map_t   sun4u_map[] = {
 103  107          /* MAX_NAMEVAL_SIZE */
 104  108          { "SUNW,bpp", PICL_CLASS_PARALLEL},
 105  109          { "parallel", PICL_CLASS_PARALLEL},
 106  110          { "floppy", PICL_CLASS_FLOPPY},
 107  111          { "memory", PICL_CLASS_MEMORY},
 108  112          { "ebus", PICL_CLASS_EBUS},
 109  113          { "i2c", PICL_CLASS_I2C},
 110  114          { "usb", PICL_CLASS_USB},
 111  115          { "isa", PICL_CLASS_ISA},
 112  116          { "dma", PICL_CLASS_DMA},
 113  117          { "keyboard", PICL_CLASS_KEYBOARD},
 114  118          { "mouse", PICL_CLASS_MOUSE},
 115  119          { "fan-control", PICL_CLASS_FAN_CONTROL},
 116  120          { "sc", PICL_CLASS_SYSTEM_CONTROLLER},
 117  121          { "dimm", PICL_CLASS_SEEPROM},
 118  122          { "dimm-fru", PICL_CLASS_SEEPROM},
 119  123          { "cpu", PICL_CLASS_SEEPROM},
 120  124          { "cpu-fru", PICL_CLASS_SEEPROM},
 121  125          { "flashprom", PICL_CLASS_FLASHPROM},
 122  126          { "temperature", PICL_CLASS_TEMPERATURE_DEVICE},
 123  127          { "motherboard", PICL_CLASS_SEEPROM},
 124  128          { "motherboard-fru", PICL_CLASS_SEEPROM},
 125  129          { "motherboard-fru-prom", PICL_CLASS_SEEPROM},
 126  130          { "pmu", PICL_CLASS_PMU},
 127  131          { "sound", PICL_CLASS_SOUND},
 128  132          { "firewire", PICL_CLASS_FIREWIRE},
 129  133          { "i2c-at34c02", PICL_CLASS_SEEPROM},
 130  134          { "hardware-monitor", PICL_CLASS_HARDWARE_MONITOR},
 131  135          { "", ""}
 132  136  };
 133  137  static  builtin_map_t   i86pc_map[] = {
 134  138          /* MAX_NAMEVAL_SIZE */
 135  139          { "cpus", PICL_CLASS_I86CPUS},
 136  140          { "cpu", PICL_CLASS_CPU},
 137  141          { "memory", PICL_CLASS_MEMORY},
 138  142          { "asy", PICL_CLASS_SERIAL},
 139  143          { "", ""}
 140  144  };
 141  145  static  pname_type_map_t        pname_type_map[] = {
 142  146          { "reg", PICL_PTYPE_BYTEARRAY},
 143  147          { "device_type", PICL_PTYPE_CHARSTRING},
 144  148          { "ranges", PICL_PTYPE_BYTEARRAY},
 145  149          { "status", PICL_PTYPE_CHARSTRING},
 146  150          { "compatible", PICL_PTYPE_CHARSTRING},
 147  151          { "interrupts", PICL_PTYPE_BYTEARRAY},
 148  152          { "model", PICL_PTYPE_CHARSTRING},
 149  153          { "address", PICL_PTYPE_BYTEARRAY},
 150  154          { "vendor-id", PICL_PTYPE_UNSIGNED_INT},
 151  155          { "device-id", PICL_PTYPE_UNSIGNED_INT},
 152  156          { "revision-id", PICL_PTYPE_UNSIGNED_INT},
 153  157          { "class-code", PICL_PTYPE_UNSIGNED_INT},
 154  158          { "min-grant", PICL_PTYPE_UNSIGNED_INT},
 155  159          { "max-latency", PICL_PTYPE_UNSIGNED_INT},
 156  160          { "devsel-speed", PICL_PTYPE_UNSIGNED_INT},
 157  161          { "subsystem-id", PICL_PTYPE_UNSIGNED_INT},
 158  162          { "subsystem-vendor-id", PICL_PTYPE_UNSIGNED_INT},
 159  163          { "assigned-addresses", PICL_PTYPE_BYTEARRAY},
 160  164          { "configuration#", PICL_PTYPE_UNSIGNED_INT},
 161  165          { "assigned-address", PICL_PTYPE_UNSIGNED_INT},
 162  166          { "#address-cells", PICL_PTYPE_UNSIGNED_INT},
 163  167          { "#size-cells", PICL_PTYPE_UNSIGNED_INT},
 164  168          { "clock-frequency", PICL_PTYPE_UNSIGNED_INT},
 165  169          { "scsi-initiator-id", PICL_PTYPE_UNSIGNED_INT},
 166  170          { "differential", PICL_PTYPE_UNSIGNED_INT},
 167  171          { "idprom", PICL_PTYPE_BYTEARRAY},
 168  172          { "bus-range", PICL_PTYPE_BYTEARRAY},
 169  173          { "alternate-reg", PICL_PTYPE_BYTEARRAY},
 170  174          { "power-consumption", PICL_PTYPE_BYTEARRAY},
 171  175          { "slot-names", PICL_PTYPE_BYTEARRAY},
 172  176          { "burst-sizes", PICL_PTYPE_UNSIGNED_INT},
 173  177          { "up-burst-sizes", PICL_PTYPE_UNSIGNED_INT},
 174  178          { "slot-address-bits", PICL_PTYPE_UNSIGNED_INT},
 175  179          { "eisa-slots", PICL_PTYPE_BYTEARRAY},
 176  180          { "dma", PICL_PTYPE_BYTEARRAY},
 177  181          { "slot-names-index", PICL_PTYPE_UNSIGNED_INT},
 178  182          { "pnp-csn", PICL_PTYPE_UNSIGNED_INT},
 179  183          { "pnp-data", PICL_PTYPE_BYTEARRAY},
 180  184          { "description", PICL_PTYPE_CHARSTRING},
 181  185          { "pnp-id", PICL_PTYPE_CHARSTRING},
 182  186          { "max-frame-size", PICL_PTYPE_UNSIGNED_INT},
 183  187          { "address-bits", PICL_PTYPE_UNSIGNED_INT},
 184  188          { "local-mac-address", PICL_PTYPE_BYTEARRAY},
 185  189          { "mac-address", PICL_PTYPE_BYTEARRAY},
 186  190          { "character-set", PICL_PTYPE_CHARSTRING},
 187  191          { "available", PICL_PTYPE_BYTEARRAY},
 188  192          { "port-wwn", PICL_PTYPE_BYTEARRAY},
 189  193          { "node-wwn", PICL_PTYPE_BYTEARRAY},
 190  194          { "width", PICL_PTYPE_UNSIGNED_INT},
 191  195          { "linebytes", PICL_PTYPE_UNSIGNED_INT},
 192  196          { "height", PICL_PTYPE_UNSIGNED_INT},
 193  197          { "banner-name", PICL_PTYPE_CHARSTRING},
 194  198          { "reset-reason", PICL_PTYPE_CHARSTRING},
 195  199          { "implementation#", PICL_PTYPE_UNSIGNED_INT},
 196  200          { "version#", PICL_PTYPE_UNSIGNED_INT},
 197  201          { "icache-size", PICL_PTYPE_UNSIGNED_INT},
 198  202          { "icache-line-size", PICL_PTYPE_UNSIGNED_INT},
 199  203          { "icache-associativity", PICL_PTYPE_UNSIGNED_INT},
 200  204          { "l1-icache-size", PICL_PTYPE_UNSIGNED_INT},
 201  205          { "l1-icache-line-size", PICL_PTYPE_UNSIGNED_INT},
 202  206          { "l1-icache-associativity", PICL_PTYPE_UNSIGNED_INT},
 203  207          { "#itlb-entries", PICL_PTYPE_UNSIGNED_INT},
 204  208          { "dcache-size", PICL_PTYPE_UNSIGNED_INT},
 205  209          { "dcache-line-size", PICL_PTYPE_UNSIGNED_INT},
 206  210          { "dcache-associativity", PICL_PTYPE_UNSIGNED_INT},
 207  211          { "l1-dcache-size", PICL_PTYPE_UNSIGNED_INT},
 208  212          { "l1-dcache-line-size", PICL_PTYPE_UNSIGNED_INT},
 209  213          { "l1-dcache-associativity", PICL_PTYPE_UNSIGNED_INT},
 210  214          { "#dtlb-entries", PICL_PTYPE_UNSIGNED_INT},
 211  215          { "ecache-size", PICL_PTYPE_UNSIGNED_INT},
 212  216          { "ecache-line-size", PICL_PTYPE_UNSIGNED_INT},
 213  217          { "ecache-associativity", PICL_PTYPE_UNSIGNED_INT},
 214  218          { "l2-cache-size", PICL_PTYPE_UNSIGNED_INT},
 215  219          { "l2-cache-line-size", PICL_PTYPE_UNSIGNED_INT},
 216  220          { "l2-cache-associativity", PICL_PTYPE_UNSIGNED_INT},
 217  221          { "l2-cache-sharing", PICL_PTYPE_BYTEARRAY},
 218  222          { "mask#", PICL_PTYPE_UNSIGNED_INT},
 219  223          { "manufacturer#", PICL_PTYPE_UNSIGNED_INT},
 220  224          { "sparc-version", PICL_PTYPE_UNSIGNED_INT},
 221  225          { "version", PICL_PTYPE_CHARSTRING},
 222  226          { "cpu-model", PICL_PTYPE_UNSIGNED_INT},
 223  227          { "memory-layout", PICL_PTYPE_BYTEARRAY},
 224  228          { "#interrupt-cells", PICL_PTYPE_UNSIGNED_INT},
 225  229          { "interrupt-map", PICL_PTYPE_BYTEARRAY},
 226  230          { "interrupt-map-mask", PICL_PTYPE_BYTEARRAY}
 227  231  };
 228  232  
 229  233  #define PNAME_MAP_SIZE  sizeof (pname_type_map) / sizeof (pname_type_map_t)
 230  234  
 231  235  static  builtin_map_t   *builtin_map_ptr = NULL;
 232  236  static  int             builtin_map_size = 0;
 233  237  static  char            mach_name[SYS_NMLN];
 234  238  static  di_prom_handle_t        ph = DI_PROM_HANDLE_NIL;
 235  239  static  int             snapshot_stale;
 236  240  
 237  241  /*
 238  242   * UnitAddress mapping table
 239  243   */
 240  244  static  unitaddr_func_t encode_default_unitaddr;
 241  245  static  unitaddr_func_t encode_optional_unitaddr;
 242  246  static  unitaddr_func_t encode_scsi_unitaddr;
 243  247  static  unitaddr_func_t encode_upa_unitaddr;
 244  248  static  unitaddr_func_t encode_gptwo_jbus_unitaddr;
 245  249  static  unitaddr_func_t encode_pci_unitaddr;
 246  250  
 247  251  static  unitaddr_map_t unitaddr_map_table[] = {
 248  252          {PICL_CLASS_JBUS, encode_gptwo_jbus_unitaddr, 0},
 249  253          {PICL_CLASS_GPTWO, encode_gptwo_jbus_unitaddr, 0},
 250  254          {PICL_CLASS_PCI, encode_pci_unitaddr, 0},
 251  255          {PICL_CLASS_PCIEX, encode_pci_unitaddr, 0},
 252  256          {PICL_CLASS_UPA, encode_upa_unitaddr, 0},
 253  257          {PICL_CLASS_SCSI, encode_scsi_unitaddr, 0},
 254  258          {PICL_CLASS_SCSI2, encode_scsi_unitaddr, 0},
 255  259          {PICL_CLASS_EBUS, encode_default_unitaddr, 2},
 256  260          {PICL_CLASS_SBUS, encode_default_unitaddr, 2},
 257  261          {PICL_CLASS_I2C, encode_default_unitaddr, 2},
 258  262          {PICL_CLASS_USB, encode_default_unitaddr, 1},
 259  263          {PICL_CLASS_PMU, encode_optional_unitaddr, 2},
 260  264          {NULL, encode_default_unitaddr, 0}
 261  265  };
 262  266  
 263  267  static int add_unitaddr_prop_to_subtree(picl_nodehdl_t nodeh);
 264  268  static int get_unitaddr(picl_nodehdl_t parh, picl_nodehdl_t nodeh,
 265  269          char *unitaddr, size_t ualen);
 266  270  static void set_pci_pciex_deviceid(picl_nodehdl_t plafh);
 267  271  
 268  272  /*
 269  273   * The mc event completion handler.
 270  274   * The arguments are event name buffer and a packed nvlist buffer
 271  275   * with the size specifying the size of unpacked nvlist. These
 272  276   * buffers are deallcoated here.
 273  277   *
 274  278   * Also, if a memory controller node is being removed then destroy the
 275  279   * PICL subtree associated with that memory controller.
 276  280   */
 277  281  static void
 278  282  mc_completion_handler(char *ename, void *earg, size_t size)
 279  283  {
 280  284          picl_nodehdl_t  mch;
 281  285          nvlist_t        *unpack_nvl;
 282  286  
 283  287          if (strcmp(ename, PICLEVENT_MC_REMOVED) == 0 &&
 284  288              nvlist_unpack(earg, size, &unpack_nvl, NULL) == 0) {
 285  289                  mch = NULL;
 286  290                  (void) nvlist_lookup_uint64(unpack_nvl,
 287  291                      PICLEVENTARG_NODEHANDLE, &mch);
 288  292                  if (mch != NULL) {
 289  293                          if (picldevtree_debug)
 290  294                                  syslog(LOG_INFO,
 291  295                                      "picldevtree: destroying_node:%llx\n",
 292  296                                      mch);
 293  297                          (void) ptree_destroy_node(mch);
 294  298                  }
 295  299                  nvlist_free(unpack_nvl);
 296  300          }
 297  301  
 298  302          free(ename);
 299  303          free(earg);
 300  304  }
 301  305  
 302  306  /*
 303  307   * Functions to post memory controller change event
 304  308   */
 305  309  static int
 306  310  post_mc_event(char *ename, picl_nodehdl_t mch)
 307  311  {
 308  312          nvlist_t        *nvl;
 309  313          size_t          nvl_size;
 310  314          char            *pack_buf;
 311  315          char            *ev_name;
 312  316  
 313  317          ev_name = strdup(ename);
 314  318          if (ev_name == NULL)
 315  319                  return (-1);
 316  320  
 317  321          if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) {
 318  322                  free(ev_name);
 319  323                  return (-1);
 320  324          }
 321  325  
 322  326          pack_buf = NULL;
 323  327          if (nvlist_add_uint64(nvl, PICLEVENTARG_NODEHANDLE, mch) ||
 324  328              nvlist_pack(nvl, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) {
 325  329                  free(ev_name);
 326  330                  nvlist_free(nvl);
 327  331                  return (-1);
 328  332          }
 329  333  
 330  334          if (picldevtree_debug)
 331  335                  syslog(LOG_INFO,
 332  336                      "picldevtree: posting MC event ename:%s nodeh:%llx\n",
 333  337                      ev_name, mch);
 334  338          if (ptree_post_event(ev_name, pack_buf, nvl_size,
 335  339              mc_completion_handler) != PICL_SUCCESS) {
 336  340                  free(ev_name);
 337  341                  nvlist_free(nvl);
 338  342                  return (-1);
 339  343          }
 340  344          nvlist_free(nvl);
 341  345          return (0);
 342  346  }
 343  347  
 344  348  /*
 345  349   * Lookup a name in the name to class map tables
 346  350   */
 347  351  static int
 348  352  lookup_name_class_map(char *classbuf, const char *nm)
 349  353  {
 350  354          conf_entries_t  *ptr;
 351  355          int             i;
 352  356  
 353  357          /*
 354  358           * check name to class mapping in conf file
 355  359           */
 356  360          ptr = conf_name_class_map;
 357  361  
 358  362          while (ptr != NULL) {
 359  363                  if (strcmp(ptr->name, nm) == 0) {
 360  364                          (void) strlcpy(classbuf, ptr->piclclass,
 361  365                              PICL_CLASSNAMELEN_MAX);
 362  366                          return (0);
 363  367                  }
 364  368                  ptr = ptr->next;
 365  369          }
 366  370  
 367  371          /*
 368  372           * check name to class mapping in builtin table
 369  373           */
 370  374          if (builtin_map_ptr == NULL)
 371  375                  return (-1);
 372  376  
 373  377          for (i = 0; i < builtin_map_size; ++i)
 374  378                  if (strcmp(builtin_map_ptr[i].name, nm) == 0) {
 375  379                          (void) strlcpy(classbuf, builtin_map_ptr[i].piclclass,
 376  380                              PICL_CLASSNAMELEN_MAX);
 377  381                          return (0);
 378  382                  }
 379  383          return (-1);
 380  384  }
 381  385  
 382  386  /*
 383  387   * Lookup a prop name in the pname to class map table
 384  388   */
 385  389  static int
 386  390  lookup_pname_type_map(const char *pname, picl_prop_type_t *type)
 387  391  {
 388  392          int             i;
 389  393  
 390  394          for (i = 0; i < PNAME_MAP_SIZE; ++i)
 391  395                  if (strcmp(pname_type_map[i].pname, pname) == 0) {
 392  396                          *type = pname_type_map[i].type;
 393  397                          return (0);
 394  398                  }
 395  399  
 396  400          return (-1);
 397  401  }
 398  402  
 399  403  /*
 400  404   * Return the number of strings in the buffer
 401  405   */
 402  406  static int
 403  407  get_string_count(char *strdat, int length)
 404  408  {
 405  409          int     count;
 406  410          char    *lastnull;
 407  411          char    *nullptr;
 408  412  
 409  413          count = 1;
 410  414          for (lastnull = &strdat[length - 1], nullptr = strchr(strdat, '\0');
 411  415              nullptr != lastnull; nullptr = strchr(nullptr+1, '\0'))
 412  416                  count++;
 413  417  
 414  418          return (count);
 415  419  }
 416  420  
 417  421  /*
 418  422   * Return 1 if the node has a "reg" property
 419  423   */
 420  424  static int
 421  425  has_reg_prop(di_node_t dn)
 422  426  {
 423  427          int                     *pdata;
 424  428          int                     dret;
 425  429  
 426  430          dret = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, OBP_REG, &pdata);
 427  431          if (dret > 0)
 428  432                  return (1);
 429  433  
 430  434          if (!ph)
 431  435                  return (0);
 432  436          dret = di_prom_prop_lookup_ints(ph, dn, OBP_REG, &pdata);
 433  437          return (dret < 0 ? 0 : 1);
 434  438  }
 435  439  
 436  440  /*
 437  441   * This function copies a PROM node's device_type property value into the
 438  442   * buffer given by outbuf. The buffer size is PICL_CLASSNAMELEN_MAX.
 439  443   *
 440  444   * We reclassify device_type 'fru-prom' to PICL class 'seeprom'
 441  445   * for FRUID support.
 442  446   */
 443  447  static int
 444  448  get_device_type(char *outbuf, di_node_t dn)
 445  449  {
 446  450          char                    *pdata;
 447  451          char                    *pdatap;
 448  452          int                     dret;
 449  453          int                     i;
 450  454  
 451  455          dret = di_prop_lookup_strings(DDI_DEV_T_ANY, dn, OBP_DEVICETYPE,
 452  456              &pdata);
 453  457          if (dret <= 0) {
 454  458                  if (!ph)
 455  459                          return (-1);
 456  460  
 457  461                  dret = di_prom_prop_lookup_strings(ph, dn, OBP_DEVICETYPE,
 458  462                      &pdata);
 459  463                  if (dret <= 0) {
 460  464                          return (-1);
 461  465                  }
 462  466          }
 463  467  
 464  468          if (dret != 1) {
 465  469                  /*
 466  470                   * multiple strings
 467  471                   */
 468  472                  pdatap = pdata;
 469  473                  for (i = 0; i < (dret - 1); ++i) {
 470  474                          pdatap += strlen(pdatap);
 471  475                          *pdatap = '-';  /* replace '\0' with '-' */
 472  476                          pdatap++;
 473  477                  }
 474  478          }
 475  479          if (strcasecmp(pdata, "fru-prom") == 0) {
 476  480                  /*
 477  481                   * Use PICL 'seeprom' class for fru-prom device types
 478  482                   */
 479  483                  (void) strlcpy(outbuf, PICL_CLASS_SEEPROM,
 480  484                      PICL_CLASSNAMELEN_MAX);
 481  485          } else {
 482  486                  (void) strlcpy(outbuf, pdata, PICL_CLASSNAMELEN_MAX);
 483  487          }
 484  488          return (0);
 485  489  }
 486  490  
 487  491  /*
 488  492   * Get the minor node name in the class buffer passed
 489  493   */
 490  494  static int
 491  495  get_minor_class(char *classbuf, di_node_t dn)
 492  496  {
 493  497          di_minor_t      mi_node;
 494  498          char            *mi_nodetype;
 495  499          char            *mi_name;
 496  500  
 497  501          /* get minor node type */
 498  502          mi_node = di_minor_next(dn, DI_MINOR_NIL);
 499  503          if (mi_node == DI_MINOR_NIL)
 500  504                  return (-1);
 501  505  
 502  506          mi_nodetype = di_minor_nodetype(mi_node);
 503  507          if (mi_nodetype == NULL) { /* no type info, return name */
 504  508                  mi_name = di_minor_name(mi_node);
 505  509                  if (mi_name == NULL)
 506  510                          return (-1);
 507  511                  (void) strlcpy(classbuf, mi_name, PICL_CLASSNAMELEN_MAX);
 508  512                  return (0);
 509  513          }
 510  514  
 511  515  #define DDI_NODETYPE(x, y) (strncmp(x, y, (sizeof (y) - 1)) == 0)
 512  516  
 513  517          /*
 514  518           * convert the string to the picl class for non-peudo nodes
 515  519           */
 516  520          if (DDI_NODETYPE(mi_nodetype, DDI_PSEUDO))
 517  521                  return (-1);
 518  522          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_WWN))
 519  523                  (void) strcpy(classbuf, PICL_CLASS_BLOCK);
 520  524          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_CHAN))
 521  525                  (void) strcpy(classbuf, PICL_CLASS_BLOCK);
 522  526          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_CD))
 523  527                  (void) strcpy(classbuf, PICL_CLASS_CDROM);
 524  528          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_CD_CHAN))
 525  529                  (void) strcpy(classbuf, PICL_CLASS_CDROM);
 526  530          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_FD))
 527  531                  (void) strcpy(classbuf, PICL_CLASS_FLOPPY);
 528  532          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_FABRIC))
 529  533                  (void) strcpy(classbuf, PICL_CLASS_FABRIC);
 530  534          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_SAS))
 531  535                  (void) strcpy(classbuf, PICL_CLASS_SAS);
 532  536          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK))
 533  537                  (void) strcpy(classbuf, PICL_CLASS_BLOCK);
 534  538          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_MOUSE))
 535  539                  (void) strcpy(classbuf, PICL_CLASS_MOUSE);
 536  540          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_KEYBOARD))
 537  541                  (void) strcpy(classbuf, PICL_CLASS_KEYBOARD);
 538  542          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_ATTACHMENT_POINT))
 539  543                  (void) strcpy(classbuf, PICL_CLASS_ATTACHMENT_POINT);
 540  544          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_TAPE))
 541  545                  (void) strcpy(classbuf, PICL_CLASS_TAPE);
 542  546          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_SCSI_ENCLOSURE))
 543  547                  (void) strcpy(classbuf, PICL_CLASS_SCSI);
 544  548          else if (DDI_NODETYPE(mi_nodetype, DDI_NT_ENCLOSURE)) {
 545  549                  char    *colon;
 546  550  
 547  551                  if ((colon = strchr(mi_nodetype, ':')) == NULL)
 548  552                          return (-1);
 549  553                  ++colon;
 550  554                  (void) strcpy(classbuf, colon);
 551  555          } else {        /* unrecognized type, return name */
 552  556                  mi_name = di_minor_name(mi_node);
 553  557                  if (mi_name == NULL)
 554  558                          return (-1);
 555  559                  (void) strlcpy(classbuf, mi_name, PICL_CLASSNAMELEN_MAX);
 556  560          }
 557  561          return (0);
 558  562  }
 559  563  
 560  564  /*
 561  565   * Derive PICL class using the compatible property of the node
 562  566   * We use the map table to map compatible property value to
 563  567   * class.
 564  568   */
 565  569  static int
 566  570  get_compatible_class(char *outbuf, di_node_t dn)
 567  571  {
 568  572          char                    *pdata;
 569  573          char                    *pdatap;
 570  574          int                     dret;
 571  575          int                     i;
 572  576  
 573  577          dret = di_prop_lookup_strings(DDI_DEV_T_ANY, dn, OBP_COMPATIBLE,
 574  578              &pdata);
 575  579          if (dret <= 0) {
 576  580                  if (!ph)
 577  581                          return (-1);
 578  582  
 579  583                  dret = di_prom_prop_lookup_strings(ph, dn, OBP_COMPATIBLE,
 580  584                      &pdata);
 581  585                  if (dret <= 0) {
 582  586                          return (-1);
 583  587                  }
 584  588          }
 585  589  
 586  590          pdatap = pdata;
 587  591          for (i = 0; i < dret; ++i) {
 588  592                  if (lookup_name_class_map(outbuf, pdatap) == 0)
 589  593                          return (0);
 590  594                  pdatap += strlen(pdatap);
 591  595                  pdatap++;
 592  596          }
 593  597          return (-1);
 594  598  }
 595  599  
 596  600  /*
 597  601   * For a given device node find the PICL class to use. Returns NULL
 598  602   * for non device node
 599  603   */
 600  604  static int
 601  605  get_node_class(char *classbuf, di_node_t dn, const char *nodename)
 602  606  {
 603  607          if (get_device_type(classbuf, dn) == 0) {
 604  608                  if (di_nodeid(dn) == DI_PROM_NODEID) {
 605  609                          /*
 606  610                           * discard place holder nodes
 607  611                           */
 608  612                          if ((strcmp(classbuf, DEVICE_TYPE_BLOCK) == 0) ||
 609  613                              (strcmp(classbuf, DEVICE_TYPE_BYTE) == 0) ||
 610  614                              (strcmp(classbuf, DEVICE_TYPE_SES) == 0) ||
 611  615                              (strcmp(classbuf, DEVICE_TYPE_FP) == 0) ||
 612  616                              (strcmp(classbuf, DEVICE_TYPE_DISK) == 0))
 613  617                                  return (-1);
 614  618  
 615  619                          return (0);
 616  620                  }
 617  621                  return (0);     /* return device_type value */
 618  622          }
 619  623  
 620  624          if (get_compatible_class(classbuf, dn) == 0) {
 621  625                  return (0);     /* derive class using compatible prop */
 622  626          }
 623  627  
 624  628          if (lookup_name_class_map(classbuf, nodename) == 0)
 625  629                  return (0);     /* derive class using name prop */
 626  630  
 627  631          if (has_reg_prop(dn)) { /* use default obp-device */
 628  632                  (void) strcpy(classbuf, PICL_CLASS_OBP_DEVICE);
 629  633                  return (0);
 630  634          }
 631  635  
 632  636          return (get_minor_class(classbuf, dn));
 633  637  }
 634  638  
 635  639  /*
 636  640   * Add a table property containing nrows with one column
 637  641   */
 638  642  static int
 639  643  add_string_list_prop(picl_nodehdl_t nodeh, char *name, char *strlist,
 640  644      unsigned int nrows)
 641  645  {
 642  646          ptree_propinfo_t        propinfo;
 643  647          picl_prophdl_t          proph;
 644  648          picl_prophdl_t          tblh;
 645  649          int                     err;
 646  650          unsigned int            i;
 647  651          unsigned int            j;
 648  652          picl_prophdl_t          *proprow;
 649  653          int                     len;
 650  654  
 651  655  #define NCOLS_IN_STRING_TABLE   1
 652  656  
 653  657          err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
 654  658              PICL_PTYPE_TABLE, PICL_READ, sizeof (picl_prophdl_t), name,
 655  659              NULL, NULL);
 656  660          if (err != PICL_SUCCESS)
 657  661                  return (err);
 658  662  
 659  663          err = ptree_create_table(&tblh);
 660  664          if (err != PICL_SUCCESS)
 661  665                  return (err);
 662  666  
 663  667          err = ptree_create_and_add_prop(nodeh, &propinfo, &tblh, &proph);
 664  668          if (err != PICL_SUCCESS)
 665  669                  return (err);
 666  670  
 667  671          proprow = alloca(sizeof (picl_prophdl_t) * nrows);
 668  672          if (proprow == NULL) {
 669  673                  (void) ptree_destroy_prop(proph);
 670  674                  return (PICL_FAILURE);
 671  675          }
 672  676  
 673  677          for (j = 0; j < nrows; ++j) {
 674  678                  len = strlen(strlist) + 1;
 675  679                  err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
 676  680                      PICL_PTYPE_CHARSTRING, PICL_READ, len, name,
 677  681                      NULL, NULL);
 678  682                  if (err != PICL_SUCCESS)
 679  683                          break;
 680  684                  err = ptree_create_prop(&propinfo, strlist, &proprow[j]);
 681  685                  if (err != PICL_SUCCESS)
 682  686                          break;
 683  687                  strlist += len;
 684  688                  err = ptree_add_row_to_table(tblh, NCOLS_IN_STRING_TABLE,
 685  689                      &proprow[j]);
 686  690                  if (err != PICL_SUCCESS)
 687  691                          break;
 688  692          }
 689  693  
 690  694          if (err != PICL_SUCCESS) {
 691  695                  for (i = 0; i < j; ++i)
 692  696                          (void) ptree_destroy_prop(proprow[i]);
 693  697                  (void) ptree_delete_prop(proph);
 694  698                  (void) ptree_destroy_prop(proph);
 695  699                  return (err);
 696  700          }
 697  701  
 698  702          return (PICL_SUCCESS);
 699  703  }
 700  704  
 701  705  /*
 702  706   * return 1 if this node has this property with the given value
 703  707   */
 704  708  static int
 705  709  compare_string_propval(picl_nodehdl_t nodeh, const char *pname,
 706  710      const char *pval)
 707  711  {
 708  712          char                    *pvalbuf;
 709  713          int                     err;
 710  714          int                     len;
 711  715          ptree_propinfo_t        pinfo;
 712  716          picl_prophdl_t          proph;
 713  717  
 714  718          err = ptree_get_prop_by_name(nodeh, pname, &proph);
 715  719          if (err != PICL_SUCCESS)        /* prop doesn't exist */
 716  720                  return (0);
 717  721  
 718  722          err = ptree_get_propinfo(proph, &pinfo);
 719  723          if (pinfo.piclinfo.type != PICL_PTYPE_CHARSTRING)
 720  724                  return (0);     /* not string prop */
 721  725  
 722  726          len = strlen(pval) + 1;
 723  727  
 724  728          pvalbuf = alloca(len);
 725  729          if (pvalbuf == NULL)
 726  730                  return (0);
 727  731  
 728  732          err = ptree_get_propval(proph, pvalbuf, len);
 729  733          if ((err == PICL_SUCCESS) && (strcmp(pvalbuf, pval) == 0))
 730  734                  return (1);     /* prop match */
 731  735  
 732  736          return (0);
 733  737  }
 734  738  
 735  739  /*
 736  740   * This function recursively searches the tree for a node that has
 737  741   * the specified string property name and value
 738  742   */
 739  743  static int
 740  744  find_node_by_string_prop(picl_nodehdl_t rooth, const char *pname,
 741  745      const char *pval, picl_nodehdl_t *nodeh)
 742  746  {
 743  747          picl_nodehdl_t          childh;
 744  748          int                     err;
 745  749  
 746  750          for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
 747  751              sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
 748  752              err = ptree_get_propval_by_name(childh, PICL_PROP_PEER, &childh,
 749  753              sizeof (picl_nodehdl_t))) {
 750  754                  if (err != PICL_SUCCESS)
 751  755                          return (err);
 752  756  
 753  757                  if (compare_string_propval(childh, pname, pval)) {
 754  758                          *nodeh = childh;
 755  759                          return (PICL_SUCCESS);
 756  760                  }
 757  761  
 758  762                  if (find_node_by_string_prop(childh, pname, pval, nodeh) ==
 759  763                      PICL_SUCCESS)
 760  764                          return (PICL_SUCCESS);
 761  765          }
 762  766  
 763  767          return (PICL_FAILURE);
 764  768  }
 765  769  
 766  770  /*
 767  771   * check if this is a string prop
 768  772   * If the length is less than or equal to 4, assume it's not a string list.
 769  773   * If there is any non-ascii or non-print char, it's not a string prop
 770  774   * If \0 is in the first char or any two consecutive \0's exist,
 771  775   * it's a bytearray prop.
 772  776   * Return value: 0 means it's not a string prop, 1 means it's a string prop
 773  777   */
 774  778  static int
 775  779  is_string_propval(unsigned char *pdata, int len)
 776  780  {
 777  781          int     i;
 778  782          int     lastindex;
 779  783          int     prevnull = -1;
 780  784  
 781  785          switch (len) {
 782  786          case 1:
 783  787                  if (!isascii(pdata[0]) || !isprint(pdata[0]))
 784  788                          return (0);
 785  789                  return (1);
 786  790          case 2:
 787  791          case 3:
 788  792          case 4:
 789  793                  lastindex = len;
 790  794                  if (pdata[len-1] == '\0')
 791  795                          lastindex = len - 1;
 792  796  
 793  797                  for (i = 0; i < lastindex; i++)
 794  798                          if (!isascii(pdata[i]) || !isprint(pdata[i]))
 795  799                                  return (0);
 796  800  
 797  801                  return (1);
 798  802  
 799  803          default:
 800  804                  if (len <= 0)
 801  805                          return (0);
 802  806                  for (i = 0; i < len; i++) {
 803  807                          if (!isascii(pdata[i]) || !isprint(pdata[i])) {
 804  808                                  if (pdata[i] != '\0')
 805  809                                          return (0);
 806  810                                  /*
 807  811                                   * if the null char is in the first char
 808  812                                   * or two consecutive nulls' exist,
 809  813                                   * it's a bytearray prop
 810  814                                   */
 811  815                                  if ((i == 0) || ((i - prevnull) == 1))
 812  816                                          return (0);
 813  817  
 814  818                                  prevnull = i;
 815  819                          }
 816  820                  }
 817  821                  break;
 818  822          }
 819  823  
 820  824          return (1);
 821  825  }
 822  826  
 823  827  /*
 824  828   * This function counts the number of strings in the value buffer pdata
 825  829   * and creates a property.
 826  830   * If there is only one string in the buffer, pdata, a charstring property
 827  831   * type is created and added.
 828  832   * If there are more than one string in the buffer, pdata, then a table
 829  833   * of charstrings is added.
 830  834   */
 831  835  static int
 832  836  process_charstring_data(picl_nodehdl_t nodeh, char *pname, unsigned char *pdata,
 833  837      int retval)
 834  838  {
 835  839          int                     err;
 836  840          int                     strcount;
 837  841          char                    *strdat;
 838  842          ptree_propinfo_t        propinfo;
 839  843  
 840  844          /*
 841  845           * append the null char at the end of string when there is
 842  846           * no null terminator
 843  847           */
 844  848          if (pdata[retval - 1] != '\0') {
 845  849                  strdat = alloca(retval + 1);
 846  850                  (void) memcpy(strdat, pdata, retval);
 847  851                  strdat[retval] = '\0';
 848  852                  retval++;
 849  853          } else {
 850  854                  strdat = alloca(retval);
 851  855                  (void) memcpy(strdat, pdata, retval);
 852  856          }
 853  857  
 854  858          /*
 855  859           * If it's a string list, create a table prop
 856  860           */
 857  861          strcount = get_string_count(strdat, retval);
 858  862          if (strcount > 1) {
 859  863                  err = add_string_list_prop(nodeh, pname,
 860  864                      strdat, strcount);
 861  865                  if (err != PICL_SUCCESS)
 862  866                          return (err);
 863  867          } else {
 864  868                  err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
 865  869                      PICL_PTYPE_CHARSTRING, PICL_READ,
 866  870                      strlen(strdat) + 1, pname, NULL,
 867  871                      NULL);
 868  872                  if (err != PICL_SUCCESS)
 869  873                          return (err);
 870  874                  (void) ptree_create_and_add_prop(nodeh, &propinfo,
 871  875                      strdat, NULL);
 872  876          }
 873  877          return (PICL_SUCCESS);
 874  878  }
 875  879  
 876  880  /*
 877  881   * Add the OBP properties as properties of the PICL node
 878  882   */
 879  883  static int
 880  884  add_openprom_props(picl_nodehdl_t nodeh, di_node_t di_node)
 881  885  {
 882  886          di_prom_prop_t          promp;
 883  887          char                    *pname;
 884  888          unsigned char           *pdata;
 885  889          int                     retval;
 886  890          ptree_propinfo_t        propinfo;
 887  891          int                     err;
 888  892          picl_prop_type_t        type;
 889  893  
 890  894          if (!ph)
 891  895                  return (PICL_FAILURE);
 892  896  
 893  897          for (promp = di_prom_prop_next(ph, di_node, DI_PROM_PROP_NIL);
 894  898              promp != DI_PROM_PROP_NIL;
 895  899              promp = di_prom_prop_next(ph, di_node, promp)) {
 896  900  
 897  901                  pname = di_prom_prop_name(promp);
 898  902  
 899  903                  retval = di_prom_prop_data(promp, &pdata);
 900  904                  if (retval < 0) {
 901  905                          return (PICL_SUCCESS);
 902  906                  }
 903  907                  if (retval == 0) {
 904  908                          err = ptree_init_propinfo(&propinfo,
 905  909                              PTREE_PROPINFO_VERSION, PICL_PTYPE_VOID,
 906  910                              PICL_READ, (size_t)0, pname, NULL, NULL);
 907  911                          if (err != PICL_SUCCESS) {
 908  912                                  return (err);
 909  913                          }
 910  914                          (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL,
 911  915                              NULL);
 912  916                          continue;
 913  917                  }
 914  918  
 915  919                  /*
 916  920                   * Get the prop type from pname map table
 917  921                   */
 918  922                  if (lookup_pname_type_map(pname, &type) == 0) {
 919  923                          if (type == PICL_PTYPE_CHARSTRING) {
 920  924                                  err = process_charstring_data(nodeh, pname,
 921  925                                      pdata, retval);
 922  926                                  if (err != PICL_SUCCESS) {
 923  927                                          return (err);
 924  928                                  }
 925  929                                  continue;
 926  930                          }
 927  931  
 928  932                          err = ptree_init_propinfo(&propinfo,
 929  933                              PTREE_PROPINFO_VERSION, type, PICL_READ,
 930  934                              retval, pname, NULL, NULL);
 931  935                          if (err != PICL_SUCCESS) {
 932  936                                  return (err);
 933  937                          }
 934  938                          (void) ptree_create_and_add_prop(nodeh, &propinfo,
 935  939                              pdata, NULL);
 936  940                  } else if (!is_string_propval(pdata, retval)) {
 937  941                          switch (retval) {
 938  942                          case sizeof (uint8_t):
 939  943                                  /*FALLTHROUGH*/
 940  944                          case sizeof (uint16_t):
 941  945                                  /*FALLTHROUGH*/
 942  946                          case sizeof (uint32_t):
 943  947                                  type = PICL_PTYPE_UNSIGNED_INT;
 944  948                                  break;
 945  949                          default:
 946  950                                  type = PICL_PTYPE_BYTEARRAY;
 947  951                                  break;
 948  952                          }
 949  953                          err = ptree_init_propinfo(&propinfo,
 950  954                              PTREE_PROPINFO_VERSION, type, PICL_READ,
 951  955                              retval, pname, NULL, NULL);
 952  956                          if (err != PICL_SUCCESS) {
 953  957                                  return (err);
 954  958                          }
 955  959                          (void) ptree_create_and_add_prop(nodeh, &propinfo,
 956  960                              pdata, NULL);
 957  961                  } else {
 958  962                          err = process_charstring_data(nodeh, pname, pdata,
 959  963                              retval);
 960  964                          if (err != PICL_SUCCESS) {
 961  965                                  return (err);
 962  966                          }
 963  967                  }
 964  968          }
 965  969  
 966  970          return (PICL_SUCCESS);
 967  971  }
 968  972  
 969  973  static void
 970  974  add_boolean_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val)
 971  975  {
 972  976          (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
 973  977              PICL_PTYPE_VOID, PICL_READ, (size_t)0, di_val, NULL, NULL);
 974  978          (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, NULL);
 975  979  }
 976  980  
 977  981  static void
 978  982  add_uints_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val,
 979  983      int *idata, int len)
 980  984  {
 981  985          if (len == 1)
 982  986                  (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
 983  987                      PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (int), di_val,
 984  988                      NULL, NULL);
 985  989          else
 986  990                  (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
 987  991                      PICL_PTYPE_BYTEARRAY, PICL_READ, len * sizeof (int), di_val,
 988  992                      NULL, NULL);
 989  993  
 990  994          (void) ptree_create_and_add_prop(nodeh, &propinfo, idata, NULL);
 991  995  }
 992  996  
 993  997  static void
 994  998  add_strings_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val,
 995  999      char *sdata, int len)
 996 1000  {
 997 1001          if (len == 1) {
 998 1002                  (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
 999 1003                      PICL_PTYPE_CHARSTRING, PICL_READ, strlen(sdata) + 1, di_val,
1000 1004                      NULL, NULL);
1001 1005                  (void) ptree_create_and_add_prop(nodeh, &propinfo, sdata, NULL);
1002 1006          } else {
1003 1007                  (void) add_string_list_prop(nodeh, di_val, sdata, len);
1004 1008          }
1005 1009  }
1006 1010  
1007 1011  static void
1008 1012  add_bytes_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val,
1009 1013      unsigned char *bdata, int len)
1010 1014  {
1011 1015          (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1012 1016              PICL_PTYPE_BYTEARRAY, PICL_READ, len, di_val, NULL, NULL);
1013 1017          (void) ptree_create_and_add_prop(nodeh, &propinfo, bdata, NULL);
1014 1018  }
1015 1019  
1016 1020  static const char *
1017 1021  path_state_name(di_path_state_t st)
1018 1022  {
1019 1023          switch (st) {
1020 1024                  case DI_PATH_STATE_ONLINE:
1021 1025                          return ("online");
1022 1026                  case DI_PATH_STATE_STANDBY:
1023 1027                          return ("standby");
1024 1028                  case DI_PATH_STATE_OFFLINE:
1025 1029                          return ("offline");
1026 1030                  case DI_PATH_STATE_FAULT:
1027 1031                          return ("faulted");
1028 1032          }
1029 1033          return ("unknown");
1030 1034  }
1031 1035  
1032 1036  /*
1033 1037   * This function is the volatile property handler for the multipath node
1034 1038   * "State" property. It must locate the associated devinfo node in order to
1035 1039   * determine the current state. Since the devinfo node can have multiple
1036 1040   * paths the devfs_path is used to locate the correct path.
1037 1041   */
1038 1042  static int
1039 1043  get_path_state_name(ptree_rarg_t *rarg, void *vbuf)
1040 1044  {
1041 1045          int             err;
1042 1046          picl_nodehdl_t  parh;
1043 1047          char            devfs_path[PATH_MAX];
1044 1048          di_node_t       di_node;
1045 1049          di_node_t       di_root;
1046 1050          di_path_t       pi = DI_PATH_NIL;
1047 1051          picl_nodehdl_t  mpnode;
1048 1052  
1049 1053          (void) strlcpy(vbuf, "unknown", MAX_STATE_SIZE);
1050 1054  
1051 1055          mpnode = rarg->nodeh;
1052 1056  
1053 1057          /*
1054 1058           * The parent node represents the vHCI.
1055 1059           */
1056 1060          err = ptree_get_propval_by_name(mpnode, PICL_PROP_PARENT, &parh,
1057 1061              sizeof (picl_nodehdl_t));
1058 1062          if (err != PICL_SUCCESS) {
1059 1063                  return (PICL_SUCCESS);
1060 1064          }
1061 1065  
1062 1066          /*
1063 1067           * The PICL_PROP_DEVFS_PATH property will be used to locate the
1064 1068           * devinfo node for the vHCI driver.
1065 1069           */
1066 1070          err = ptree_get_propval_by_name(parh, PICL_PROP_DEVFS_PATH, devfs_path,
1067 1071              sizeof (devfs_path));
1068 1072          if (err != PICL_SUCCESS) {
1069 1073                  return (PICL_SUCCESS);
1070 1074          }
1071 1075          /*
1072 1076           * Find the di_node for the vHCI driver. It will be used to scan
1073 1077           * the path information nodes.
1074 1078           */
1075 1079          di_root = di_init("/", DINFOCACHE);
1076 1080          if (di_root == DI_NODE_NIL) {
1077 1081                  return (PICL_SUCCESS);
1078 1082          }
1079 1083          di_node = di_lookup_node(di_root, devfs_path);
1080 1084          if (di_node == DI_NODE_NIL) {
1081 1085                  di_fini(di_root);
1082 1086                  return (PICL_SUCCESS);
1083 1087          }
1084 1088  
1085 1089          /*
1086 1090           * The devfs_path will be used below to match the
1087 1091           * proper path information node.
1088 1092           */
1089 1093          err = ptree_get_propval_by_name(mpnode, PICL_PROP_DEVFS_PATH,
1090 1094              devfs_path, sizeof (devfs_path));
1091 1095          if (err != PICL_SUCCESS) {
1092 1096                  di_fini(di_root);
1093 1097                  return (PICL_SUCCESS);
1094 1098          }
1095 1099  
1096 1100          /*
1097 1101           * Scan the path information nodes looking for the matching devfs
1098 1102           * path. When found obtain the state information.
1099 1103           */
1100 1104          while ((pi = di_path_next_phci(di_node, pi)) != DI_PATH_NIL) {
1101 1105                  char            *di_path;
1102 1106                  di_node_t       phci_node = di_path_phci_node(pi);
1103 1107  
1104 1108                  if (phci_node == DI_PATH_NIL)
1105 1109                          continue;
1106 1110  
1107 1111                  di_path = di_devfs_path(phci_node);
1108 1112                  if (di_path) {
1109 1113                          if (strcmp(di_path, devfs_path) != 0) {
1110 1114                                  di_devfs_path_free(di_path);
1111 1115                                  continue;
1112 1116                          }
1113 1117                          (void) strlcpy(vbuf, path_state_name(di_path_state(pi)),
1114 1118                              MAX_STATE_SIZE);
1115 1119                          di_devfs_path_free(di_path);
1116 1120                          break;
1117 1121                  }
1118 1122          }
1119 1123  
1120 1124          di_fini(di_root);
1121 1125          return (PICL_SUCCESS);
1122 1126  }
1123 1127  
1124 1128  static void
1125 1129  add_di_path_prop(picl_nodehdl_t nodeh, di_path_prop_t di_path_prop)
1126 1130  {
1127 1131          int                     di_ptype;
1128 1132          char                    *di_val;
1129 1133          ptree_propinfo_t        propinfo;
1130 1134          int                     *idata;
1131 1135          char                    *sdata;
1132 1136          unsigned char           *bdata;
1133 1137          int                     len;
1134 1138  
1135 1139          di_ptype = di_path_prop_type(di_path_prop);
1136 1140          di_val = di_path_prop_name(di_path_prop);
1137 1141  
1138 1142          switch (di_ptype) {
1139 1143          case DI_PROP_TYPE_BOOLEAN:
1140 1144                  add_boolean_prop(nodeh, propinfo, di_val);
1141 1145                  break;
1142 1146          case DI_PROP_TYPE_INT:
1143 1147          case DI_PROP_TYPE_INT64:
1144 1148                  len = di_path_prop_ints(di_path_prop, &idata);
1145 1149                  if (len < 0)
1146 1150                          /* Received error, so ignore prop */
1147 1151                          break;
1148 1152                  add_uints_prop(nodeh, propinfo, di_val, idata, len);
1149 1153                  break;
1150 1154          case DI_PROP_TYPE_STRING:
1151 1155                  len = di_path_prop_strings(di_path_prop, &sdata);
1152 1156                  if (len <= 0)
1153 1157                          break;
1154 1158                  add_strings_prop(nodeh, propinfo, di_val, sdata, len);
1155 1159                  break;
1156 1160          case DI_PROP_TYPE_BYTE:
1157 1161                  len = di_path_prop_bytes(di_path_prop, &bdata);
1158 1162                  if (len < 0)
1159 1163                          break;
1160 1164                  add_bytes_prop(nodeh, propinfo, di_val, bdata, len);
1161 1165                  break;
1162 1166          case DI_PROP_TYPE_UNKNOWN:
1163 1167                  /*
1164 1168                   * Unknown type, we'll try and guess what it should be.
1165 1169                   */
1166 1170                  len = di_path_prop_strings(di_path_prop, &sdata);
1167 1171                  if ((len > 0) && (sdata[0] != 0)) {
1168 1172                          add_strings_prop(nodeh, propinfo, di_val, sdata,
1169 1173                              len);
1170 1174                          break;
1171 1175                  }
1172 1176                  len = di_path_prop_ints(di_path_prop, &idata);
1173 1177                  if (len > 0) {
1174 1178                          add_uints_prop(nodeh, propinfo, di_val,
1175 1179                              idata, len);
1176 1180                          break;
1177 1181                  }
1178 1182                  len = di_path_prop_bytes(di_path_prop, &bdata);
1179 1183                  if (len > 0)
1180 1184                          add_bytes_prop(nodeh, propinfo,
1181 1185                              di_val, bdata, len);
1182 1186                  else if (len == 0)
1183 1187                          add_boolean_prop(nodeh, propinfo,
1184 1188                              di_val);
1185 1189                  break;
1186 1190          case DI_PROP_TYPE_UNDEF_IT:
1187 1191                  break;
1188 1192          default:
1189 1193                  break;
1190 1194          }
1191 1195  }
1192 1196  
1193 1197  /*
1194 1198   * Add nodes for path information (PSARC/1999/647, PSARC/2008/437)
1195 1199   */
1196 1200  static void
1197 1201  construct_mpath_node(picl_nodehdl_t parh, di_node_t di_node)
1198 1202  {
1199 1203          di_path_t               pi = DI_PATH_NIL;
1200 1204  
1201 1205          while ((pi = di_path_next_phci(di_node, pi)) != DI_PATH_NIL) {
1202 1206                  di_node_t               phci_node = di_path_phci_node(pi);
1203 1207                  di_path_prop_t          di_path_prop;
1204 1208                  picl_nodehdl_t          nodeh;
1205 1209                  ptree_propinfo_t        propinfo;
1206 1210                  int                     err;
1207 1211                  int                     instance;
1208 1212                  char                    *di_val;
1209 1213  
1210 1214                  if (phci_node == DI_PATH_NIL)
1211 1215                          continue;
1212 1216  
1213 1217                  err = ptree_create_and_add_node(parh, PICL_CLASS_MULTIPATH,
1214 1218                      PICL_CLASS_MULTIPATH, &nodeh);
1215 1219                  if (err != PICL_SUCCESS)
1216 1220                          continue;
1217 1221  
1218 1222                  instance = di_instance(phci_node);
1219 1223                  (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1220 1224                      PICL_PTYPE_INT, PICL_READ, sizeof (instance),
1221 1225                      PICL_PROP_INSTANCE, NULL, NULL);
1222 1226                  (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance,
1223 1227                      NULL);
1224 1228  
1225 1229                  di_val = di_devfs_path(phci_node);
1226 1230                  if (di_val) {
1227 1231                          (void) ptree_init_propinfo(&propinfo,
1228 1232                              PTREE_PROPINFO_VERSION,
1229 1233                              PICL_PTYPE_CHARSTRING, PICL_READ,
1230 1234                              strlen(di_val) + 1, PICL_PROP_DEVFS_PATH,
1231 1235                              NULL, NULL);
1232 1236                          (void) ptree_create_and_add_prop(nodeh,
1233 1237                              &propinfo, di_val, NULL);
1234 1238                          di_devfs_path_free(di_val);
1235 1239                  }
1236 1240  
1237 1241                  (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1238 1242                      PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE),
1239 1243                      MAX_STATE_SIZE, PICL_PROP_STATE, get_path_state_name, NULL);
1240 1244                  (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, NULL);
1241 1245  
1242 1246                  for (di_path_prop = di_path_prop_next(pi, DI_PROP_NIL);
1243 1247                      di_path_prop != DI_PROP_NIL;
1244 1248                      di_path_prop = di_path_prop_next(pi, di_path_prop)) {
1245 1249                          add_di_path_prop(nodeh, di_path_prop);
1246 1250                  }
1247 1251          }
1248 1252  }
1249 1253  
1250 1254  /*
1251 1255   * Add properties provided by libdevinfo
1252 1256   */
1253 1257  static void
1254 1258  add_devinfo_props(picl_nodehdl_t nodeh, di_node_t di_node)
1255 1259  {
1256 1260          int                     instance;
1257 1261          char                    *di_val;
1258 1262          di_prop_t               di_prop;
1259 1263          int                     di_ptype;
1260 1264          ptree_propinfo_t        propinfo;
1261 1265          char                    *sdata;
1262 1266          unsigned char           *bdata;
1263 1267          int                     *idata;
1264 1268          int                     len;
1265 1269  
1266 1270          instance = di_instance(di_node);
1267 1271          (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1268 1272              PICL_PTYPE_INT, PICL_READ, sizeof (instance), PICL_PROP_INSTANCE,
1269 1273              NULL, NULL);
1270 1274          (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, NULL);
1271 1275  
1272 1276          di_val = di_bus_addr(di_node);
1273 1277          if (di_val) {
1274 1278                  (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1275 1279                      PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1276 1280                      PICL_PROP_BUS_ADDR, NULL, NULL);
1277 1281                  (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1278 1282                      NULL);
1279 1283          }
1280 1284  
1281 1285          di_val = di_binding_name(di_node);
1282 1286          if (di_val) {
1283 1287                  (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1284 1288                      PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1285 1289                      PICL_PROP_BINDING_NAME, NULL, NULL);
1286 1290                  (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1287 1291                      NULL);
1288 1292          }
1289 1293  
1290 1294          di_val = di_driver_name(di_node);
1291 1295          if (di_val) {
1292 1296                  (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1293 1297                      PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1294 1298                      PICL_PROP_DRIVER_NAME, NULL, NULL);
1295 1299                  (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1296 1300                      NULL);
1297 1301          }
1298 1302  
1299 1303          di_val = di_devfs_path(di_node);
1300 1304          if (di_val) {
1301 1305                  (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1302 1306                      PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1303 1307                      PICL_PROP_DEVFS_PATH, NULL, NULL);
1304 1308                  (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1305 1309                      NULL);
1306 1310                  di_devfs_path_free(di_val);
1307 1311          }
1308 1312  
1309 1313          for (di_prop = di_prop_next(di_node, DI_PROP_NIL);
1310 1314              di_prop != DI_PROP_NIL;
1311 1315              di_prop = di_prop_next(di_node, di_prop)) {
1312 1316  
1313 1317                  di_val = di_prop_name(di_prop);
1314 1318                  di_ptype = di_prop_type(di_prop);
1315 1319  
1316 1320                  switch (di_ptype) {
1317 1321                  case DI_PROP_TYPE_BOOLEAN:
1318 1322                          add_boolean_prop(nodeh, propinfo, di_val);
1319 1323                          break;
1320 1324                  case DI_PROP_TYPE_INT:
1321 1325                          len = di_prop_ints(di_prop, &idata);
1322 1326                          if (len < 0)
1323 1327                                  /* Received error, so ignore prop */
1324 1328                                  break;
1325 1329                          add_uints_prop(nodeh, propinfo, di_val, idata, len);
1326 1330                          break;
1327 1331                  case DI_PROP_TYPE_STRING:
1328 1332                          len = di_prop_strings(di_prop, &sdata);
1329 1333                          if (len < 0)
1330 1334                                  break;
1331 1335                          add_strings_prop(nodeh, propinfo, di_val, sdata, len);
1332 1336                          break;
1333 1337                  case DI_PROP_TYPE_BYTE:
1334 1338                          len = di_prop_bytes(di_prop, &bdata);
1335 1339                          if (len < 0)
1336 1340                                  break;
1337 1341                          add_bytes_prop(nodeh, propinfo, di_val, bdata, len);
1338 1342                          break;
1339 1343                  case DI_PROP_TYPE_UNKNOWN:
1340 1344                          /*
1341 1345                           * Unknown type, we'll try and guess what it should be.
1342 1346                           */
1343 1347                          len = di_prop_strings(di_prop, &sdata);
1344 1348                          if ((len > 0) && (sdata[0] != 0)) {
1345 1349                                  add_strings_prop(nodeh, propinfo, di_val, sdata,
1346 1350                                      len);
1347 1351                                  break;
1348 1352                          }
1349 1353                          len = di_prop_ints(di_prop, &idata);
1350 1354                          if (len > 0) {
1351 1355                                  add_uints_prop(nodeh, propinfo, di_val,
1352 1356                                      idata, len);
1353 1357                                  break;
1354 1358                          }
1355 1359                          len = di_prop_rawdata(di_prop, &bdata);
1356 1360                          if (len > 0)
1357 1361                                  add_bytes_prop(nodeh, propinfo,
1358 1362                                      di_val, bdata, len);
1359 1363                          else if (len == 0)
1360 1364                                  add_boolean_prop(nodeh, propinfo,
1361 1365                                      di_val);
1362 1366                          break;
1363 1367                  case DI_PROP_TYPE_UNDEF_IT:
1364 1368                          break;
1365 1369                  default:
1366 1370                          break;
1367 1371                  }
1368 1372          }
1369 1373  }
1370 1374  
1371 1375  /*
1372 1376   * This function creates the /obp node in the PICL tree for OBP nodes
1373 1377   * without a device type class.
1374 1378   */
1375 1379  static int
1376 1380  construct_picl_openprom(picl_nodehdl_t rooth, picl_nodehdl_t *obph)
1377 1381  {
1378 1382          picl_nodehdl_t  tmph;
1379 1383          int             err;
1380 1384  
1381 1385          err = ptree_create_and_add_node(rooth, PICL_NODE_OBP,
1382 1386              PICL_CLASS_PICL, &tmph);
1383 1387  
1384 1388          if (err != PICL_SUCCESS)
1385 1389                  return (err);
1386 1390          *obph = tmph;
1387 1391          return (PICL_SUCCESS);
1388 1392  }
1389 1393  
1390 1394  /*
1391 1395   * This function creates the /platform node in the PICL tree and
1392 1396   * its properties. It sets the "platform-name" property to the
1393 1397   * platform name
1394 1398   */
1395 1399  static int
1396 1400  construct_picl_platform(picl_nodehdl_t rooth, di_node_t di_root,
1397 1401      picl_nodehdl_t *piclh)
1398 1402  {
1399 1403          int                     err;
1400 1404          picl_nodehdl_t          plafh;
1401 1405          char                    *nodename;
1402 1406          char                    nodeclass[PICL_CLASSNAMELEN_MAX];
1403 1407          ptree_propinfo_t        propinfo;
1404 1408          picl_prophdl_t          proph;
1405 1409  
1406 1410          nodename = di_node_name(di_root);
1407 1411          if (nodename == NULL)
1408 1412                  return (PICL_FAILURE);
1409 1413  
1410 1414          err = 0;
1411 1415          if (di_nodeid(di_root) == DI_PROM_NODEID ||
1412 1416              di_nodeid(di_root) == DI_SID_NODEID)
1413 1417                  err = get_device_type(nodeclass, di_root);
1414 1418  
1415 1419          if (err < 0)
1416 1420                  (void) strcpy(nodeclass, PICL_CLASS_UPA);       /* default */
1417 1421  
1418 1422          err = ptree_create_and_add_node(rooth, PICL_NODE_PLATFORM,
1419 1423              nodeclass, &plafh);
1420 1424          if (err != PICL_SUCCESS)
1421 1425                  return (err);
1422 1426  
1423 1427          (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1424 1428              PICL_PTYPE_CHARSTRING, PICL_READ, strlen(nodename) + 1,
1425 1429              PICL_PROP_PLATFORM_NAME, NULL, NULL);
1426 1430          err = ptree_create_and_add_prop(plafh, &propinfo, nodename, &proph);
1427 1431          if (err != PICL_SUCCESS)
1428 1432                  return (err);
1429 1433  
1430 1434          (void) add_devinfo_props(plafh, di_root);
1431 1435  
1432 1436          (void) add_openprom_props(plafh, di_root);
1433 1437  
1434 1438          *piclh = plafh;
1435 1439  
1436 1440          return (PICL_SUCCESS);
1437 1441  }
1438 1442  
1439 1443  /*
1440 1444   * This function creates a node in /obp tree for the libdevinfo handle.
1441 1445   */
1442 1446  static int
1443 1447  construct_obp_node(picl_nodehdl_t parh, di_node_t dn, picl_nodehdl_t *chdh)
1444 1448  {
1445 1449          int             err;
1446 1450          char            *nodename;
1447 1451          char            nodeclass[PICL_CLASSNAMELEN_MAX];
1448 1452          picl_nodehdl_t  anodeh;
1449 1453  
1450 1454          nodename = di_node_name(dn);    /* PICL_PROP_NAME */
1451 1455          if (nodename == NULL)
1452 1456                  return (PICL_FAILURE);
1453 1457  
1454 1458          if (strcmp(nodename, "pseudo") == 0)
1455 1459                  return (PICL_FAILURE);
1456 1460  
1457 1461          if ((di_nodeid(dn) == DI_PROM_NODEID) &&
1458 1462              (get_device_type(nodeclass, dn) == 0))
1459 1463                  return (PICL_FAILURE);
1460 1464  
1461 1465          err = ptree_create_and_add_node(parh, nodename, nodename, &anodeh);
1462 1466          if (err != PICL_SUCCESS)
1463 1467                  return (err);
1464 1468  
1465 1469          add_devinfo_props(anodeh, dn);
1466 1470  
1467 1471          (void) add_openprom_props(anodeh, dn);
1468 1472  
1469 1473          *chdh = anodeh;
1470 1474  
1471 1475          return (PICL_SUCCESS);
1472 1476  }
1473 1477  
1474 1478  /*
1475 1479   * This function creates a PICL node in /platform tree for a device
1476 1480   */
1477 1481  static int
1478 1482  construct_devtype_node(picl_nodehdl_t parh, char *nodename,
1479 1483      char *nodeclass, di_node_t dn, picl_nodehdl_t *chdh)
1480 1484  {
1481 1485          int                     err;
1482 1486          picl_nodehdl_t          anodeh;
1483 1487  
1484 1488          err = ptree_create_and_add_node(parh, nodename, nodeclass, &anodeh);
1485 1489          if (err != PICL_SUCCESS)
1486 1490                  return (err);
1487 1491  
1488 1492          (void) add_devinfo_props(anodeh, dn);
1489 1493          (void) add_openprom_props(anodeh, dn);
1490 1494          construct_mpath_node(anodeh, dn);
1491 1495  
1492 1496          *chdh = anodeh;
1493 1497          return (err);
1494 1498  }
1495 1499  
1496 1500  /*
1497 1501   * Create a subtree of "picl" class nodes in /obp for these nodes
1498 1502   */
1499 1503  static int
1500 1504  construct_openprom_tree(picl_nodehdl_t nodeh, di_node_t  dinode)
1501 1505  {
1502 1506          di_node_t       cnode;
1503 1507          picl_nodehdl_t  chdh;
1504 1508          int             err;
1505 1509  
1506 1510          err = construct_obp_node(nodeh, dinode, &chdh);
1507 1511          if (err != PICL_SUCCESS)
1508 1512                  return (err);
1509 1513  
1510 1514          for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL;
1511 1515              cnode = di_sibling_node(cnode))
1512 1516                  (void) construct_openprom_tree(chdh, cnode);
1513 1517  
1514 1518          return (PICL_SUCCESS);
1515 1519  
1516 1520  }
1517 1521  
1518 1522  /*
1519 1523   * Process the libdevinfo device tree and create nodes in /platform or /obp
1520 1524   * PICL tree.
1521 1525   *
1522 1526   * This routine traverses the immediate children of "dinode" device and
1523 1527   * determines the node class for that child. If it finds a valid class
1524 1528   * name, then it builds a PICL node under /platform subtree and calls itself
1525 1529   * recursively to construct the subtree for that child node. Otherwise, if
1526 1530   * the parent_class is NULL, then it constructs a node and subtree under /obp
1527 1531   * subtree.
1528 1532   *
1529 1533   * Note that we skip the children nodes that don't have a valid class name
1530 1534   * and the parent_class is non NULL to prevent creation of any placeholder
1531 1535   * nodes (such as sd,...).
1532 1536   */
1533 1537  static int
1534 1538  construct_devinfo_tree(picl_nodehdl_t plafh, picl_nodehdl_t obph,
1535 1539      di_node_t dinode, char *parent_class)
1536 1540  {
1537 1541          di_node_t       cnode;
1538 1542          picl_nodehdl_t  chdh;
1539 1543          char            nodeclass[PICL_CLASSNAMELEN_MAX];
1540 1544          char            *nodename;
1541 1545          int             err;
1542 1546  
1543 1547          err = PICL_SUCCESS;
1544 1548          for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL;
1545 1549              cnode = di_sibling_node(cnode)) {
1546 1550                  nodename = di_node_name(cnode); /* PICL_PROP_NAME */
1547 1551                  if (nodename == NULL)
1548 1552                          continue;
1549 1553  
1550 1554                  err = get_node_class(nodeclass, cnode, nodename);
1551 1555  
1552 1556                  if (err == 0) {
1553 1557                          err = construct_devtype_node(plafh, nodename,
1554 1558                              nodeclass, cnode, &chdh);
1555 1559                          if (err != PICL_SUCCESS)
1556 1560                                  return (err);
1557 1561                          err = construct_devinfo_tree(chdh, obph, cnode,
1558 1562                              nodeclass);
1559 1563                  } else if (parent_class == NULL)
1560 1564                          err = construct_openprom_tree(obph, cnode);
1561 1565                  else
1562 1566                          continue;
1563 1567                  /*
1564 1568                   * if parent_class is non NULL, skip the children nodes
1565 1569                   * that don't have a valid device class - eliminates
1566 1570                   * placeholder nodes (sd,...) from being created.
1567 1571                   */
1568 1572          }
1569 1573  
1570 1574          return (err);
1571 1575  
1572 1576  }
1573 1577  
1574 1578  /*
1575 1579   * This function is called from the event handler called from the daemon
1576 1580   * on PICL events.
1577 1581   *
1578 1582   * This routine traverses the children of the "dinode" device and
1579 1583   * creates a PICL node for each child not found in the PICL tree and
1580 1584   * invokes itself recursively to create a subtree for the newly created
1581 1585   * child node. It also checks if the node being created is a meory
1582 1586   * controller. If so, it posts PICLEVENT_MC_ADDED PICL event to the PICL
1583 1587   * framework.
1584 1588   */
1585 1589  static int
1586 1590  update_subtree(picl_nodehdl_t nodeh, di_node_t dinode)
1587 1591  {
1588 1592          di_node_t       cnode;
1589 1593          picl_nodehdl_t  chdh;
1590 1594          picl_nodehdl_t  nh;
1591 1595          char            *nodename;
1592 1596          char            nodeclass[PICL_CLASSNAMELEN_MAX];
1593 1597          char            *path_buf;
1594 1598          char            buf[MAX_UNIT_ADDRESS_LEN];
1595 1599          char            unitaddr[MAX_UNIT_ADDRESS_LEN];
1596 1600          char            path_w_ua[MAXPATHLEN];
1597 1601          char            path_wo_ua[MAXPATHLEN];
1598 1602          char            *strp;
1599 1603          int             gotit;
1600 1604          int             err;
1601 1605  
1602 1606          for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL;
1603 1607              cnode = di_sibling_node(cnode)) {
1604 1608                  path_buf = di_devfs_path(cnode);
1605 1609                  if (path_buf == NULL)
1606 1610                          continue;
1607 1611  
1608 1612                  nodename = di_node_name(cnode);
1609 1613                  if (nodename == NULL) {
1610 1614                          di_devfs_path_free(path_buf);
1611 1615                          continue;
1612 1616                  }
1613 1617  
1614 1618                  err = get_node_class(nodeclass, cnode, nodename);
1615 1619  
1616 1620                  if (err < 0) {
1617 1621                          di_devfs_path_free(path_buf);
1618 1622                          continue;
1619 1623                  }
1620 1624  
1621 1625                  /*
1622 1626                   * this is quite complicated - both path_buf and any nodes
1623 1627                   * already in the picl tree may, or may not, have the
1624 1628                   * @<unit_addr> at the end of their names. So we must
1625 1629                   * take path_buf and work out what the device path would
1626 1630                   * be both with and without the unit_address, then search
1627 1631                   * the picl tree for both forms.
1628 1632                   */
1629 1633                  if (((strp = strrchr(path_buf, '/')) != NULL) &&
1630 1634                      strchr(strp, '@') == NULL) {
1631 1635                          /*
1632 1636                           * This is an unattached node - so the path is not
1633 1637                           * unique. Need to find out which node it is.
1634 1638                           * Find the unit_address from the OBP or devinfo
1635 1639                           * properties.
1636 1640                           */
1637 1641                          err = ptree_create_node(nodename, nodeclass, &chdh);
1638 1642                          if (err != PICL_SUCCESS)
1639 1643                                  return (err);
1640 1644  
1641 1645                          (void) add_devinfo_props(chdh, cnode);
1642 1646                          (void) add_openprom_props(chdh, cnode);
1643 1647  
1644 1648                          err = get_unitaddr(nodeh, chdh, unitaddr,
1645 1649                              sizeof (unitaddr));
1646 1650                          if (err != PICL_SUCCESS)
1647 1651                                  return (err);
1648 1652                          (void) ptree_destroy_node(chdh);
1649 1653                          (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s@%s",
1650 1654                              path_buf, unitaddr);
1651 1655                          (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s",
1652 1656                              path_buf);
1653 1657                  } else {
1654 1658                          /*
1655 1659                           * this is an attached node - so the path is unique
1656 1660                           */
1657 1661                          (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s",
1658 1662                              path_buf);
1659 1663                          (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s",
1660 1664                              path_buf);
1661 1665                          strp = strrchr(path_wo_ua, '@');
1662 1666                          *strp++ = '\0';
1663 1667                          (void) snprintf(unitaddr, sizeof (unitaddr), "%s",
1664 1668                              strp);
1665 1669                  }
1666 1670                  /*
1667 1671                   * first look for node with unit address in devfs_path
1668 1672                   */
1669 1673                  if (ptree_find_node(nodeh, PICL_PROP_DEVFS_PATH,
1670 1674                      PICL_PTYPE_CHARSTRING, path_w_ua, strlen(path_w_ua) + 1,
1671 1675                      &nh) == PICL_SUCCESS) {
1672 1676                          /*
1673 1677                           * node already there - there's nothing we need to do
1674 1678                           */
1675 1679                          if (picldevtree_debug > 1)
1676 1680                                  syslog(LOG_INFO,
1677 1681                                      "update_subtree: path:%s node exists\n",
1678 1682                                      path_buf);
1679 1683                          di_devfs_path_free(path_buf);
1680 1684                          continue;
1681 1685                  }
1682 1686                  /*
1683 1687                   * now look for node without unit address in devfs_path.
1684 1688                   * This might be just one out of several
1685 1689                   * nodes - need to check all siblings
1686 1690                   */
1687 1691                  err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD,
1688 1692                      &chdh, sizeof (chdh));
1689 1693                  if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND))
1690 1694                          return (err);
1691 1695                  gotit = 0;
1692 1696                  while (err == PICL_SUCCESS) {
1693 1697                          err = ptree_get_propval_by_name(chdh,
1694 1698                              PICL_PROP_DEVFS_PATH, buf, sizeof (buf));
1695 1699                          if (err != PICL_SUCCESS)
1696 1700                                  return (err);
1697 1701                          if (strcmp(buf, path_wo_ua) == 0) {
1698 1702                                  err = ptree_get_propval_by_name(chdh,
1699 1703                                      PICL_PROP_UNIT_ADDRESS, buf, sizeof (buf));
1700 1704                                  if (err != PICL_SUCCESS)
1701 1705                                          return (err);
1702 1706                                  if (strcmp(buf, unitaddr) == 0) {
1703 1707                                          gotit = 1;
1704 1708                                          break;
1705 1709                                  }
1706 1710                          }
1707 1711                          err = ptree_get_propval_by_name(chdh,
1708 1712                              PICL_PROP_PEER, &chdh, sizeof (chdh));
1709 1713                          if (err != PICL_SUCCESS)
1710 1714                                  break;
1711 1715                  }
1712 1716                  if (gotit) {
1713 1717                          /*
1714 1718                           * node already there - there's nothing we need to do
1715 1719                           */
1716 1720                          if (picldevtree_debug > 1)
1717 1721                                  syslog(LOG_INFO,
1718 1722                                      "update_subtree: path:%s node exists\n",
1719 1723                                      path_buf);
1720 1724                          di_devfs_path_free(path_buf);
1721 1725                          continue;
1722 1726                  }
1723 1727  
1724 1728  #define IS_MC(x)        (strcmp(x, PICL_CLASS_MEMORY_CONTROLLER) == 0 ? 1 : 0)
1725 1729  
1726 1730                  if (construct_devtype_node(nodeh, nodename, nodeclass, cnode,
1727 1731                      &chdh) == PICL_SUCCESS) {
1728 1732                          if (picldevtree_debug)
1729 1733                                  syslog(LOG_INFO,
1730 1734                                      "picldevtree: added node:%s path:%s\n",
1731 1735                                      nodename, path_buf);
1732 1736                          if (IS_MC(nodeclass)) {
1733 1737                                  if (post_mc_event(PICLEVENT_MC_ADDED, chdh) !=
1734 1738                                      PICL_SUCCESS)
1735 1739                                          syslog(LOG_WARNING, PICL_EVENT_DROPPED,
1736 1740                                              PICLEVENT_MC_ADDED);
1737 1741                          }
1738 1742  
1739 1743                          di_devfs_path_free(path_buf);
1740 1744                          (void) update_subtree(chdh, cnode);
1741 1745                  }
1742 1746          }
1743 1747  
1744 1748          return (PICL_SUCCESS);
1745 1749  
1746 1750  }
1747 1751  
1748 1752  /*
1749 1753   * Check for a stale OBP node. EINVAL is returned from the openprom(7D) driver
1750 1754   * if the nodeid stored in the snapshot is not valid.
1751 1755   */
1752 1756  static int
1753 1757  check_stale_node(di_node_t node, void *arg)
1754 1758  {
1755 1759          di_prom_prop_t  promp;
1756 1760  
1757 1761          errno = 0;
1758 1762          promp = di_prom_prop_next(ph, node, DI_PROM_PROP_NIL);
1759 1763          if (promp == DI_PROM_PROP_NIL && errno == EINVAL) {
1760 1764                  snapshot_stale = 1;
1761 1765                  return (DI_WALK_TERMINATE);
1762 1766          }
  
    | 
      ↓ open down ↓ | 
    1726 lines elided | 
    
      ↑ open up ↑ | 
  
1763 1767          return (DI_WALK_CONTINUE);
1764 1768  }
1765 1769  
1766 1770  /*
1767 1771   * Walk the snapshot and check the OBP properties of each node.
1768 1772   */
1769 1773  static int
1770 1774  is_snapshot_stale(di_node_t root)
1771 1775  {
1772 1776          snapshot_stale = 0;
1773      -        di_walk_node(root, DI_WALK_CLDFIRST, NULL, check_stale_node);
     1777 +        (void) di_walk_node(root, DI_WALK_CLDFIRST, NULL, check_stale_node);
1774 1778          return (snapshot_stale);
1775 1779  }
1776 1780  
1777 1781  /*
1778 1782   * This function processes the data from libdevinfo and creates nodes
1779 1783   * in the PICL tree.
1780 1784   */
1781 1785  static int
1782 1786  libdevinfo_init(picl_nodehdl_t rooth)
1783 1787  {
1784 1788          di_node_t       di_root;
1785 1789          picl_nodehdl_t  plafh;
1786 1790          picl_nodehdl_t  obph;
1787 1791          int             err;
1788 1792  
1789 1793          /*
1790 1794           * Use DINFOCACHE so that we obtain all attributes for all
1791 1795           * device instances (without necessarily doing a load/attach
1792 1796           * of all drivers).  Once the (on-disk) cache file is built, it
1793 1797           * exists over a reboot and can be read into memory at a very
1794 1798           * low cost.
1795 1799           */
1796 1800          if ((di_root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
1797 1801                  return (PICL_FAILURE);
1798 1802  
1799 1803          if ((ph = di_prom_init()) == NULL)
1800 1804                  return (PICL_FAILURE);
1801 1805  
1802 1806          /*
1803 1807           * Check if the snapshot cache contains stale OBP nodeid references.
1804 1808           * If it does release the snapshot and obtain a live snapshot from the
1805 1809           * kernel.
1806 1810           */
1807 1811          if (is_snapshot_stale(di_root)) {
1808 1812                  syslog(LOG_INFO, "picld detected stale snapshot cache");
1809 1813                  di_fini(di_root);
1810 1814                  if ((di_root = di_init("/", DINFOCPYALL | DINFOFORCE)) ==
1811 1815                      DI_NODE_NIL) {
1812 1816                          return (PICL_FAILURE);
1813 1817                  }
1814 1818          }
1815 1819  
1816 1820          /*
1817 1821           * create platform PICL node using di_root node
1818 1822           */
1819 1823          err = construct_picl_platform(rooth, di_root, &plafh);
1820 1824          if (err != PICL_SUCCESS) {
1821 1825                  di_fini(di_root);
1822 1826                  return (PICL_FAILURE);
1823 1827          }
1824 1828  
1825 1829          err = construct_picl_openprom(rooth, &obph);
1826 1830          if (err != PICL_SUCCESS) {
1827 1831                  di_fini(di_root);
1828 1832                  return (PICL_FAILURE);
1829 1833          }
1830 1834  
1831 1835          (void) construct_devinfo_tree(plafh, obph, di_root, NULL);
1832 1836          if (ph) {
1833 1837                  di_prom_fini(ph);
1834 1838                  ph = NULL;
1835 1839          }
1836 1840          di_fini(di_root);
1837 1841          return (err);
1838 1842  }
1839 1843  
1840 1844  /*
1841 1845   * This function returns the integer property value
1842 1846   */
1843 1847  static int
1844 1848  get_int_propval_by_name(picl_nodehdl_t  nodeh, char *pname, int *ival)
1845 1849  {
1846 1850          int     err;
1847 1851  
1848 1852          err = ptree_get_propval_by_name(nodeh, pname, ival,
1849 1853              sizeof (int));
1850 1854  
1851 1855          return (err);
1852 1856  }
1853 1857  
1854 1858  /*
1855 1859   * This function returns the port ID (or CPU ID in the case of CMP cores)
1856 1860   * of the specific CPU node handle.  If upa_portid exists, return its value.
1857 1861   * Otherwise, return portid/cpuid.
1858 1862   */
1859 1863  static int
1860 1864  get_cpu_portid(picl_nodehdl_t modh, int *id)
1861 1865  {
1862 1866          int     err;
1863 1867  
1864 1868          if (strcmp(mach_name, "sun4u") == 0 ||
1865 1869              strcmp(mach_name, "sun4v") == 0) {
1866 1870                  err = get_int_propval_by_name(modh, OBP_PROP_UPA_PORTID, id);
1867 1871                  if (err == PICL_SUCCESS)
1868 1872                          return (err);
1869 1873                  err = get_int_propval_by_name(modh, OBP_PROP_PORTID, id);
1870 1874                  if (err == PICL_SUCCESS)
1871 1875                          return (err);
1872 1876                  return (get_int_propval_by_name(modh, OBP_PROP_CPUID, id));
1873 1877          }
1874 1878          if (strcmp(mach_name, "i86pc") == 0)
1875 1879                  return (get_int_propval_by_name(modh, OBP_REG, id));
1876 1880  
1877 1881          return (PICL_FAILURE);
1878 1882  }
1879 1883  
1880 1884  /*
1881 1885   * This function is the volatile read access function of CPU state
1882 1886   * property
1883 1887   */
1884 1888  static int
1885 1889  get_pi_state(ptree_rarg_t *rarg, void *vbuf)
1886 1890  {
1887 1891          int     id;
1888 1892          int     err;
1889 1893  
1890 1894          err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id);
1891 1895          if (err != PICL_SUCCESS)
1892 1896                  return (err);
1893 1897  
1894 1898          switch (p_online(id, P_STATUS)) {
1895 1899          case P_ONLINE:
1896 1900                  (void) strlcpy(vbuf, PS_ONLINE, MAX_STATE_SIZE);
1897 1901                  break;
1898 1902          case P_OFFLINE:
1899 1903                  (void) strlcpy(vbuf, PS_OFFLINE, MAX_STATE_SIZE);
1900 1904                  break;
1901 1905          case P_NOINTR:
1902 1906                  (void) strlcpy(vbuf, PS_NOINTR, MAX_STATE_SIZE);
1903 1907                  break;
1904 1908          case P_SPARE:
1905 1909                  (void) strlcpy(vbuf, PS_SPARE, MAX_STATE_SIZE);
1906 1910                  break;
1907 1911          case P_FAULTED:
1908 1912                  (void) strlcpy(vbuf, PS_FAULTED, MAX_STATE_SIZE);
1909 1913                  break;
1910 1914          case P_POWEROFF:
1911 1915                  (void) strlcpy(vbuf, PS_POWEROFF, MAX_STATE_SIZE);
1912 1916                  break;
1913 1917          default:
1914 1918                  (void) strlcpy(vbuf, "unknown", MAX_STATE_SIZE);
1915 1919                  break;
1916 1920          }
1917 1921          return (PICL_SUCCESS);
1918 1922  }
1919 1923  
1920 1924  /*
1921 1925   * This function is the volatile read access function of CPU processor_type
1922 1926   * property
1923 1927   */
1924 1928  static int
1925 1929  get_processor_type(ptree_rarg_t *rarg, void *vbuf)
1926 1930  {
1927 1931          processor_info_t        cpu_info;
1928 1932          int     id;
1929 1933          int     err;
1930 1934  
1931 1935          err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id);
1932 1936          if (err != PICL_SUCCESS)
1933 1937                  return (err);
1934 1938  
1935 1939          if (processor_info(id, &cpu_info) >= 0) {
1936 1940                  (void) strlcpy(vbuf, cpu_info.pi_processor_type, PI_TYPELEN);
1937 1941          }
1938 1942          return (PICL_SUCCESS);
1939 1943  }
1940 1944  
1941 1945  /*
1942 1946   * This function is the volatile read access function of CPU fputypes
1943 1947   * property
1944 1948   */
1945 1949  static int
1946 1950  get_fputypes(ptree_rarg_t *rarg, void *vbuf)
1947 1951  {
1948 1952          processor_info_t        cpu_info;
1949 1953          int     id;
1950 1954          int     err;
1951 1955  
1952 1956          err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id);
1953 1957          if (err != PICL_SUCCESS)
1954 1958                  return (err);
1955 1959  
1956 1960          if (processor_info(id, &cpu_info) >= 0) {
1957 1961                  (void) strlcpy(vbuf, cpu_info.pi_fputypes, PI_FPUTYPE);
1958 1962          }
1959 1963          return (PICL_SUCCESS);
1960 1964  }
1961 1965  
1962 1966  /*
1963 1967   * This function is the volatile read access function of CPU StateBegin
1964 1968   * property. To minimize overhead, use kstat_chain_update() to refresh
1965 1969   * the kstat header info as opposed to invoking kstat_open() every time.
1966 1970   */
1967 1971  static int
1968 1972  get_pi_state_begin(ptree_rarg_t *rarg, void *vbuf)
1969 1973  {
1970 1974          int                     err;
1971 1975          int                     cpu_id;
1972 1976          static kstat_ctl_t      *kc = NULL;
1973 1977          static pthread_mutex_t  kc_mutex = PTHREAD_MUTEX_INITIALIZER;
1974 1978          kstat_t                 *kp;
1975 1979          kstat_named_t           *kn;
1976 1980  
1977 1981          err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &cpu_id);
1978 1982          if (err != PICL_SUCCESS)
1979 1983                  return (err);
1980 1984  
1981 1985          (void) pthread_mutex_lock(&kc_mutex);
1982 1986          if (kc == NULL)
1983 1987                  kc = kstat_open();
1984 1988          else if (kstat_chain_update(kc) == -1) {
1985 1989                  (void) kstat_close(kc);
1986 1990                  kc = kstat_open();
1987 1991          }
1988 1992  
1989 1993          if (kc == NULL) {
1990 1994                  (void) pthread_mutex_unlock(&kc_mutex);
1991 1995                  return (PICL_FAILURE);
1992 1996          }
1993 1997  
1994 1998          /* Get the state_begin from kstat */
1995 1999          if ((kp = kstat_lookup(kc, KSTAT_CPU_INFO, cpu_id, NULL)) == NULL ||
1996 2000              kp->ks_type != KSTAT_TYPE_NAMED || kstat_read(kc, kp, 0) < 0) {
1997 2001                  (void) pthread_mutex_unlock(&kc_mutex);
1998 2002                  return (PICL_FAILURE);
1999 2003          }
2000 2004  
2001 2005          kn = kstat_data_lookup(kp, KSTAT_STATE_BEGIN);
2002 2006          if (kn) {
2003 2007                  *(uint64_t *)vbuf = (uint64_t)kn->value.l;
2004 2008                  err = PICL_SUCCESS;
2005 2009          } else
2006 2010                  err = PICL_FAILURE;
2007 2011  
2008 2012          (void) pthread_mutex_unlock(&kc_mutex);
2009 2013          return (err);
2010 2014  }
2011 2015  
2012 2016  /*
2013 2017   * This function adds CPU information to the CPU nodes
2014 2018   */
2015 2019  /* ARGSUSED */
2016 2020  static int
2017 2021  add_processor_info(picl_nodehdl_t cpuh, void *args)
2018 2022  {
2019 2023          int                     err;
2020 2024          int                     cpu_id;
2021 2025          ptree_propinfo_t        propinfo;
2022 2026          ptree_propinfo_t        pinfo;
2023 2027  
2024 2028          err = get_cpu_portid(cpuh, &cpu_id);
2025 2029          if (err != PICL_SUCCESS)
2026 2030                  return (PICL_WALK_CONTINUE);
2027 2031  
2028 2032          /*
2029 2033           * Check to make sure that the CPU is still present, i.e. that it
2030 2034           * has not been DR'ed out of the system.
2031 2035           */
2032 2036          if (p_online(cpu_id, P_STATUS) == -1) {
2033 2037                  if (picldevtree_debug)
2034 2038                          syslog(LOG_INFO,
2035 2039                              "picldevtree: cpu %d (%llx) does not exist - "
2036 2040                              "deleting node\n", cpu_id, cpuh);
2037 2041  
2038 2042                  if (ptree_delete_node(cpuh) == PICL_SUCCESS)
2039 2043                          (void) ptree_destroy_node(cpuh);
2040 2044  
2041 2045                  return (PICL_WALK_CONTINUE);
2042 2046          }
2043 2047  
2044 2048          (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2045 2049              PICL_PTYPE_INT, PICL_READ, sizeof (int), PICL_PROP_ID, NULL, NULL);
2046 2050          err = ptree_create_and_add_prop(cpuh, &propinfo, &cpu_id, NULL);
2047 2051          if (err != PICL_SUCCESS)
2048 2052                  return (PICL_WALK_CONTINUE);
2049 2053  
2050 2054          (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
2051 2055              PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), MAX_STATE_SIZE,
2052 2056              PICL_PROP_STATE, get_pi_state, NULL);
2053 2057          (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL);
2054 2058  
2055 2059          (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
2056 2060              PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_TYPELEN,
2057 2061              PICL_PROP_PROCESSOR_TYPE, get_processor_type, NULL);
2058 2062          (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL);
2059 2063  
2060 2064          (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
2061 2065              PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_FPUTYPE,
2062 2066              PICL_PROP_FPUTYPE, get_fputypes, NULL);
2063 2067          (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL);
2064 2068  
2065 2069          (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
2066 2070              PICL_PTYPE_TIMESTAMP, PICL_READ|PICL_VOLATILE, sizeof (uint64_t),
2067 2071              PICL_PROP_STATE_BEGIN, get_pi_state_begin, NULL);
2068 2072          (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL);
2069 2073  
2070 2074          return (PICL_WALK_CONTINUE);
2071 2075  }
2072 2076  
2073 2077  /*
2074 2078   * This function sets up the "ID" property in every CPU nodes
2075 2079   * and adds processor info
2076 2080   */
2077 2081  static int
2078 2082  setup_cpus(picl_nodehdl_t plafh)
2079 2083  {
2080 2084          int                     err;
2081 2085  
2082 2086          err = ptree_walk_tree_by_class(plafh, PICL_CLASS_CPU, NULL,
2083 2087              add_processor_info);
2084 2088  
2085 2089          return (err);
2086 2090  }
2087 2091  
2088 2092  /*
2089 2093   * This function format's the manufacture's information for FFB display
2090 2094   * devices
2091 2095   */
2092 2096  static void
2093 2097  fmt_manf_id(manuf_t manufid, int bufsz, char *outbuf)
2094 2098  {
2095 2099          /*
2096 2100           * Format the manufacturer's info.  Note a small inconsistency we
2097 2101           * have to work around - Brooktree has it's part number in decimal,
2098 2102           * while Mitsubishi has it's part number in hex.
2099 2103           */
2100 2104          switch (manufid.fld.manf) {
2101 2105          case MANF_BROOKTREE:
2102 2106                  (void) snprintf(outbuf, bufsz, "%s %d, version %d",
2103 2107                      "Brooktree", manufid.fld.partno, manufid.fld.version);
2104 2108                  break;
2105 2109  
2106 2110          case MANF_MITSUBISHI:
2107 2111                  (void) snprintf(outbuf, bufsz, "%s %x, version %d",
2108 2112                      "Mitsubishi", manufid.fld.partno, manufid.fld.version);
2109 2113                  break;
2110 2114  
2111 2115          default:
2112 2116                  (void) snprintf(outbuf, bufsz,
2113 2117                      "JED code %d, Part num 0x%x, version %d",
2114 2118                      manufid.fld.manf, manufid.fld.partno, manufid.fld.version);
2115 2119          }
2116 2120  }
2117 2121  
2118 2122  /*
2119 2123   * If it's an ffb device, open ffb devices and return PICL_SUCCESS
2120 2124   */
2121 2125  static int
2122 2126  open_ffb_device(picl_nodehdl_t ffbh, int *fd)
2123 2127  {
2124 2128          DIR                     *dirp;
2125 2129          char                    devfs_path[PATH_MAX];
2126 2130          char                    dev_path[PATH_MAX];
2127 2131          char                    *devp;
2128 2132          struct dirent           *direntp;
2129 2133          int                     err;
2130 2134          int                     tmpfd;
2131 2135  
2132 2136          /* Get the devfs_path of the ffb devices */
2133 2137          err = ptree_get_propval_by_name(ffbh, PICL_PROP_DEVFS_PATH, devfs_path,
2134 2138              sizeof (devfs_path));
2135 2139          if (err != PICL_SUCCESS)
2136 2140                  return (err);
2137 2141  
2138 2142          /* Get the device node name */
2139 2143          devp = strrchr(devfs_path, '/');
2140 2144          if (devp == NULL)
2141 2145                  return (PICL_FAILURE);
2142 2146          *devp = '\0';
2143 2147          ++devp;
2144 2148  
2145 2149          /*
2146 2150           * Check if device node name has the ffb string
2147 2151           * If not, assume it's not a ffb device.
2148 2152           */
2149 2153          if (strstr(devp, FFB_NAME) == NULL)
2150 2154                  return (PICL_FAILURE);
2151 2155  
2152 2156          /*
2153 2157           * Get the parent path of the ffb device node.
2154 2158           */
2155 2159          (void) snprintf(dev_path, sizeof (dev_path), "%s/%s", "/devices",
2156 2160              devfs_path);
2157 2161  
2158 2162          /*
2159 2163           * Since we don't know ffb's minor nodename,
2160 2164           * we need to search all the devices under its
2161 2165           * parent dir by comparing the node name
2162 2166           */
2163 2167          if ((dirp = opendir(dev_path)) == NULL)
2164 2168                  return (PICL_FAILURE);
2165 2169  
2166 2170          while ((direntp = readdir(dirp)) != NULL) {
2167 2171                  if (strstr(direntp->d_name, devp) != NULL) {
2168 2172                          (void) strcat(dev_path, "/");
2169 2173                          (void) strcat(dev_path, direntp->d_name);
2170 2174                          tmpfd = open(dev_path, O_RDWR);
2171 2175                          if (tmpfd < 0)
2172 2176                                  continue;
2173 2177                          *fd = tmpfd;
2174 2178                          (void) closedir(dirp);
2175 2179                          return (PICL_SUCCESS);
2176 2180                  }
2177 2181          }
2178 2182  
2179 2183          (void) closedir(dirp);
2180 2184          return (PICL_FAILURE);
2181 2185  }
2182 2186  
2183 2187  /*
2184 2188   * This function recursively searches the tree for ffb display devices
2185 2189   * and add ffb config information
2186 2190   */
2187 2191  static int
2188 2192  add_ffb_config_info(picl_nodehdl_t rooth)
2189 2193  {
2190 2194          picl_nodehdl_t          nodeh;
2191 2195          int                     err;
2192 2196          char                    piclclass[PICL_CLASSNAMELEN_MAX];
2193 2197          char                    manfidbuf[FFB_MANUF_BUFSIZE];
2194 2198          int                     fd;
2195 2199          int                     board_rev;
2196 2200          ffb_sys_info_t          fsi;
2197 2201          ptree_propinfo_t        pinfo;
2198 2202  
2199 2203          for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh,
2200 2204              sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
2201 2205              err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER,
2202 2206              &nodeh, sizeof (picl_nodehdl_t))) {
2203 2207  
2204 2208                  if (err != PICL_SUCCESS)
2205 2209                          return (err);
2206 2210  
2207 2211                  err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
2208 2212                      piclclass, PICL_CLASSNAMELEN_MAX);
2209 2213  
2210 2214                  if ((err == PICL_SUCCESS) &&
2211 2215                      (strcmp(piclclass, PICL_CLASS_DISPLAY) == 0)) {
2212 2216  
2213 2217                          err = open_ffb_device(nodeh, &fd);
2214 2218                          if ((err == PICL_SUCCESS) &&
2215 2219                              (ioctl(fd, FFB_SYS_INFO, &fsi) >= 0)) {
2216 2220                                  (void) ptree_init_propinfo(&pinfo,
2217 2221                                      PTREE_PROPINFO_VERSION,
2218 2222                                      PICL_PTYPE_UNSIGNED_INT, PICL_READ,
2219 2223                                      sizeof (int), PICL_PROP_FFB_BOARD_REV,
2220 2224                                      NULL, NULL);
2221 2225                                  board_rev = fsi.ffb_strap_bits.fld.board_rev;
2222 2226                                  (void) ptree_create_and_add_prop(nodeh, &pinfo,
2223 2227                                      &board_rev, NULL);
2224 2228  
2225 2229                                  fmt_manf_id(fsi.dac_version,
2226 2230                                      sizeof (manfidbuf), manfidbuf);
2227 2231                                  (void) ptree_init_propinfo(&pinfo,
2228 2232                                      PTREE_PROPINFO_VERSION,
2229 2233                                      PICL_PTYPE_CHARSTRING, PICL_READ,
2230 2234                                      strlen(manfidbuf) + 1,
2231 2235                                      PICL_PROP_FFB_DAC_VER, NULL, NULL);
2232 2236                                  (void) ptree_create_and_add_prop(nodeh, &pinfo,
2233 2237                                      manfidbuf, NULL);
2234 2238  
2235 2239                                  fmt_manf_id(fsi.fbram_version,
2236 2240                                      sizeof (manfidbuf), manfidbuf);
2237 2241                                  (void) ptree_init_propinfo(&pinfo,
2238 2242                                      PTREE_PROPINFO_VERSION,
2239 2243                                      PICL_PTYPE_CHARSTRING, PICL_READ,
2240 2244                                      strlen(manfidbuf) + 1,
2241 2245                                      PICL_PROP_FFB_FBRAM_VER, NULL,
2242 2246                                      NULL);
2243 2247                                  (void) ptree_create_and_add_prop(nodeh, &pinfo,
2244 2248                                      manfidbuf, NULL);
2245 2249                                  (void) close(fd);
2246 2250                          }
2247 2251                  } else if (add_ffb_config_info(nodeh) != PICL_SUCCESS)
2248 2252                          return (PICL_FAILURE);
2249 2253          }
2250 2254          return (PICL_SUCCESS);
2251 2255  }
2252 2256  
2253 2257  static conf_entries_t *
2254 2258  free_conf_entries(conf_entries_t *list)
2255 2259  {
2256 2260          conf_entries_t  *el;
2257 2261          conf_entries_t  *del;
2258 2262  
2259 2263          if (list == NULL)
2260 2264                  return (NULL);
2261 2265          el = list;
2262 2266          while (el != NULL) {
2263 2267                  del = el;
2264 2268                  el = el->next;
2265 2269                  free(del->name);
2266 2270                  free(del->piclclass);
2267 2271                  free(del);
2268 2272          }
2269 2273          return (el);
2270 2274  }
2271 2275  
2272 2276  /*
2273 2277   * Reading config order: platform, common
2274 2278   */
2275 2279  static conf_entries_t *
2276 2280  read_conf_file(char *fname, conf_entries_t *list)
2277 2281  {
2278 2282          FILE            *fp;
2279 2283          char            lbuf[CONFFILE_LINELEN_MAX];
2280 2284          char            *nametok;
2281 2285          char            *classtok;
2282 2286          conf_entries_t  *el;
2283 2287          conf_entries_t  *ptr;
2284 2288  
2285 2289          if (fname == NULL)
2286 2290                  return (list);
2287 2291  
2288 2292          fp = fopen(fname, "r");
2289 2293  
2290 2294          if (fp == NULL)
2291 2295                  return (list);
2292 2296  
2293 2297          while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) {
2294 2298                  if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n'))
2295 2299                          continue;
2296 2300  
2297 2301                  nametok = strtok(lbuf, " \t\n");
2298 2302                  if (nametok == NULL)
2299 2303                          continue;
2300 2304  
2301 2305                  classtok = strtok(NULL, " \t\n");
2302 2306                  if (classtok == NULL)
2303 2307                          continue;
2304 2308  
2305 2309                  el = malloc(sizeof (conf_entries_t));
2306 2310                  if (el == NULL)
2307 2311                          break;
2308 2312                  el->name = strdup(nametok);
2309 2313                  el->piclclass = strdup(classtok);
2310 2314                  if ((el->name == NULL) || (el->piclclass == NULL)) {
2311 2315                          free(el);
2312 2316                          return (list);
2313 2317                  }
2314 2318                  el->next = NULL;
2315 2319  
2316 2320                  /*
2317 2321                   * Add it to the end of list
2318 2322                   */
2319 2323                  if (list == NULL)
2320 2324                          list = el;
2321 2325                  else {
2322 2326                          ptr = list;
2323 2327                          while (ptr->next != NULL)
2324 2328                                  ptr = ptr->next;
2325 2329                          ptr->next = el;
2326 2330                  }
2327 2331  
2328 2332          }
2329 2333          (void) fclose(fp);
2330 2334          return (list);
2331 2335  }
2332 2336  
2333 2337  /*
2334 2338   * Process the devtree conf file and set up the conf_name_class_map list
2335 2339   */
2336 2340  static void
2337 2341  process_devtree_conf_file(void)
2338 2342  {
2339 2343          char    nmbuf[SYS_NMLN];
2340 2344          char    pname[PATH_MAX];
2341 2345  
2342 2346          conf_name_class_map = NULL;
2343 2347  
2344 2348          if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
2345 2349                  (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
2346 2350                  (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX);
2347 2351                  conf_name_class_map = read_conf_file(pname,
2348 2352                      conf_name_class_map);
2349 2353          }
2350 2354  
2351 2355          if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
2352 2356                  (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
2353 2357                  (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX);
2354 2358                  conf_name_class_map = read_conf_file(pname,
2355 2359                      conf_name_class_map);
2356 2360          }
2357 2361  
2358 2362          (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR,
2359 2363              DEVTREE_CONFFILE_NAME);
2360 2364          conf_name_class_map = read_conf_file(pname, conf_name_class_map);
2361 2365  }
2362 2366  
2363 2367  static  asr_conf_entries_t      *conf_name_asr_map = NULL;
2364 2368  
2365 2369  static void
2366 2370  free_asr_conf_entries(asr_conf_entries_t *list) {
2367 2371          asr_conf_entries_t  *el;
2368 2372          asr_conf_entries_t  *del;
2369 2373  
2370 2374          el = list;
2371 2375          while (el != NULL) {
2372 2376                  del = el;
2373 2377                  el = el->next;
2374 2378                  if (del->name)
2375 2379                          free(del->name);
2376 2380                  if (del->address)
2377 2381                          free(del->address);
2378 2382                  if (del->status)
2379 2383                          free(del->status);
2380 2384                  if (del->piclclass)
2381 2385                          free(del->piclclass);
2382 2386                  if (del->props)
2383 2387                          free(del->props);
2384 2388                  free(del);
2385 2389          }
2386 2390  }
2387 2391  
2388 2392  /*
2389 2393   * Reading config order: platform, common
2390 2394   */
2391 2395  static asr_conf_entries_t *
2392 2396  read_asr_conf_file(char *fname, asr_conf_entries_t *list)
2393 2397  {
2394 2398          FILE            *fp;
2395 2399          char            lbuf[CONFFILE_LINELEN_MAX];
2396 2400          char            *nametok;
2397 2401          char            *classtok;
2398 2402          char            *statustok;
2399 2403          char            *addresstok;
2400 2404          char            *propstok;
2401 2405          asr_conf_entries_t      *el;
2402 2406          asr_conf_entries_t      *ptr;
2403 2407  
2404 2408          if (fname == NULL)
2405 2409                  return (list);
2406 2410  
2407 2411          fp = fopen(fname, "r");
2408 2412          if (fp == NULL)
2409 2413                  return (list);
2410 2414  
2411 2415          while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) {
2412 2416                  if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n'))
2413 2417                          continue;
2414 2418  
2415 2419                  nametok = strtok(lbuf, " \t\n");
2416 2420                  if (nametok == NULL)
2417 2421                          continue;
2418 2422  
2419 2423                  classtok = strtok(NULL, " \t\n");
2420 2424                  if (classtok == NULL)
2421 2425                          continue;
2422 2426  
2423 2427                  statustok = strtok(NULL, " \t\n");
2424 2428                  if (statustok == NULL)
2425 2429                          continue;
2426 2430  
2427 2431                  addresstok = strtok(NULL, " \t\n");
2428 2432                  if (addresstok == NULL)
2429 2433                          continue;
2430 2434  
2431 2435                  /*
2432 2436                   * props are optional
2433 2437                   */
2434 2438                  propstok = strtok(NULL, " \t\n");
2435 2439  
2436 2440                  el = malloc(sizeof (asr_conf_entries_t));
2437 2441                  if (el == NULL)
2438 2442                          break;
2439 2443                  el->name = strdup(nametok);
2440 2444                  el->piclclass = strdup(classtok);
2441 2445                  el->status = strdup(statustok);
2442 2446                  el->address = strdup(addresstok);
2443 2447                  if (propstok != NULL)
2444 2448                          el->props = strdup(propstok);
2445 2449                  else
2446 2450                          el->props = NULL;
2447 2451                  if ((el->name == NULL) || (el->piclclass == NULL) ||
2448 2452                      (el->address == NULL) || (el->status == NULL)) {
2449 2453                          if (el->name)
2450 2454                                  free(el->name);
2451 2455                          if (el->address)
2452 2456                                  free(el->address);
2453 2457                          if (el->status)
2454 2458                                  free(el->status);
2455 2459                          if (el->piclclass)
2456 2460                                  free(el->piclclass);
2457 2461                          if (el->props)
2458 2462                                  free(el->props);
2459 2463                          free(el);
2460 2464                          break;
2461 2465                  }
2462 2466                  el->next = NULL;
2463 2467  
2464 2468                  /*
2465 2469                   * Add it to the end of list
2466 2470                   */
2467 2471                  if (list == NULL)
2468 2472                          list = el;
2469 2473                  else {
2470 2474                          ptr = list;
2471 2475                          while (ptr->next != NULL)
2472 2476                                  ptr = ptr->next;
2473 2477                          ptr->next = el;
2474 2478                  }
2475 2479  
2476 2480          }
2477 2481          (void) fclose(fp);
2478 2482          return (list);
2479 2483  }
2480 2484  
2481 2485  /*
2482 2486   * Process the asr conf file
2483 2487   */
2484 2488  static void
2485 2489  process_asrtree_conf_file(void)
2486 2490  {
2487 2491          char    nmbuf[SYS_NMLN];
2488 2492          char    pname[PATH_MAX];
2489 2493  
2490 2494          if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
2491 2495                  (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
2492 2496                  (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX);
2493 2497                  conf_name_asr_map = read_asr_conf_file(pname,
2494 2498                      conf_name_asr_map);
2495 2499          }
2496 2500  
2497 2501          if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
2498 2502                  (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
2499 2503                  (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX);
2500 2504                  conf_name_asr_map = read_asr_conf_file(pname,
2501 2505                      conf_name_asr_map);
2502 2506          }
2503 2507  
2504 2508          (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR,
2505 2509              ASRTREE_CONFFILE_NAME);
2506 2510          conf_name_asr_map = read_asr_conf_file(pname, conf_name_asr_map);
2507 2511  }
2508 2512  
2509 2513  /*
2510 2514   * This function reads the export file list from ASR
2511 2515   */
2512 2516  static int
2513 2517  get_asr_export_list(char **exportlist, int *exportlistlen)
2514 2518  {
2515 2519          struct openpromio oppbuf;
2516 2520          struct openpromio *opp = &oppbuf;
2517 2521          int d;
2518 2522          int listsize;
2519 2523  
2520 2524          d = open("/dev/openprom", O_RDWR);
2521 2525          if (d < 0)
2522 2526                  return (0);
2523 2527  
2524 2528          if (ioctl(d, OPROMEXPORTLEN, opp) == -1) {
2525 2529                  (void) close(d);
2526 2530                  return (0);
2527 2531          }
2528 2532          listsize = opp->oprom_size;
2529 2533          opp = (struct openpromio *)malloc(sizeof (struct openpromio) +
2530 2534              listsize);
2531 2535          if (opp == NULL) {
2532 2536                  (void) close(d);
2533 2537                  return (0);
2534 2538          }
2535 2539          (void) memset(opp, '\0', sizeof (struct openpromio) + listsize);
2536 2540          opp->oprom_size = listsize;
2537 2541          if (ioctl(d, OPROMEXPORT, opp) == -1) {
2538 2542                  free(opp);
  
    | 
      ↓ open down ↓ | 
    755 lines elided | 
    
      ↑ open up ↑ | 
  
2539 2543                  (void) close(d);
2540 2544                  return (0);
2541 2545          }
2542 2546          *exportlist = malloc(listsize);
2543 2547          if (*exportlist == NULL) {
2544 2548                  free(opp);
2545 2549                  (void) close(d);
2546 2550                  return (0);
2547 2551          }
2548 2552          (void) memcpy(*exportlist, opp->oprom_array, opp->oprom_size);
2549      -        free(opp);
2550 2553          *exportlistlen = opp->oprom_size;
     2554 +        free(opp);
2551 2555          (void) close(d);
2552 2556          return (1);
2553 2557  }
2554 2558  
2555 2559  /*
2556 2560   * Parses properties string, fills in triplet structure with first
2557 2561   * type, name, val triplet and returns pointer to next property.
2558 2562   * Returns NULL if no valid triplet found
2559 2563   * CAUTION: drops \0 characters over separator characters: if you
2560 2564   * want to parse the string twice, you'll have to take a copy.
2561 2565   */
2562 2566  static char *
2563 2567  parse_props_string(char *props, asr_prop_triplet_t *triplet)
2564 2568  {
2565 2569          char    *prop_name;
2566 2570          char    *prop_val;
2567 2571          char    *prop_next;
2568 2572  
2569 2573          prop_name = strchr(props, '?');
2570 2574          if (prop_name == NULL)
2571 2575                  return (NULL);
2572 2576          *prop_name++ = '\0';
2573 2577          prop_val = strchr(prop_name, '=');
2574 2578          if (prop_val == NULL)
2575 2579                  return (NULL);
2576 2580          *prop_val++ = '\0';
2577 2581          triplet->proptype = props;
2578 2582          triplet->propname = prop_name;
2579 2583          triplet->propval = prop_val;
2580 2584          prop_next = strchr(prop_val, ':');
2581 2585          if (prop_next == NULL)
2582 2586                  return (prop_val - 1);
2583 2587          *prop_next++ = '\0';
2584 2588          return (prop_next);
2585 2589  }
2586 2590  
2587 2591  static int
2588 2592  add_status_prop(picl_nodehdl_t chdh, char *status)
2589 2593  {
2590 2594          ptree_propinfo_t        propinfo;
2591 2595          picl_prophdl_t          proph;
2592 2596          int                     err;
2593 2597  
2594 2598          err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2595 2599              PICL_PTYPE_CHARSTRING, PICL_READ, strlen(status) + 1,
2596 2600              PICL_PROP_STATUS, NULL, NULL);
2597 2601          if (err != PICL_SUCCESS)
2598 2602                  return (err);
2599 2603          err = ptree_create_and_add_prop(chdh, &propinfo, status, &proph);
2600 2604          return (err);
2601 2605  }
2602 2606  
2603 2607  static void
2604 2608  create_asr_node(char *parent, char *child, char *unitaddr, char *class,
2605 2609          char *status, char *props)
2606 2610  {
2607 2611          char                    ptreepath[PATH_MAX];
2608 2612          char                    nodename[PICL_PROPNAMELEN_MAX];
2609 2613          char                    ua[MAX_UNIT_ADDRESS_LEN];
2610 2614          char                    *props_copy = NULL;
2611 2615          char                    *next;
2612 2616          char                    *prop_string;
2613 2617          boolean_t               found = B_FALSE;
2614 2618          picl_nodehdl_t          nodeh;
2615 2619          picl_nodehdl_t          chdh;
2616 2620          asr_prop_triplet_t      triple;
2617 2621          ptree_propinfo_t        propinfo;
2618 2622          picl_prophdl_t          proph;
2619 2623          int                     val;
2620 2624          int                     err;
2621 2625  
2622 2626          (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX);
2623 2627          (void) strlcat(ptreepath, parent, PATH_MAX);
2624 2628  
2625 2629          if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS)
2626 2630                  return;
2627 2631          /*
2628 2632           * see if the required child node already exists
2629 2633           */
2630 2634          for (err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh,
2631 2635              sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
2632 2636              err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
2633 2637              sizeof (picl_nodehdl_t))) {
2634 2638                  if (err != PICL_SUCCESS)
2635 2639                          break;
2636 2640                  err = ptree_get_propval_by_name(chdh, PICL_PROP_NAME,
2637 2641                      (void *)nodename, PICL_PROPNAMELEN_MAX);
2638 2642                  if (err != PICL_SUCCESS)
2639 2643                          break;
2640 2644                  if (strcmp(nodename, child) != 0)
2641 2645                          continue;
2642 2646                  /*
2643 2647                   * found a candidate child node
2644 2648                   */
2645 2649                  if (unitaddr) {
2646 2650                          /*
2647 2651                           * does it match the required unit address?
2648 2652                           */
2649 2653                          err = ptree_get_propval_by_name(chdh,
2650 2654                              PICL_PROP_UNIT_ADDRESS, ua, sizeof (ua));
2651 2655                          if (err == PICL_PROPNOTFOUND)
2652 2656                                  continue;
2653 2657                          if (err != PICL_SUCCESS)
2654 2658                                  break;
2655 2659                          if (strcmp(unitaddr, ua) != 0)
2656 2660                                  continue;
2657 2661                  }
2658 2662                  if (props == NULL) {
2659 2663                          next = "";
2660 2664                  } else if (props_copy == NULL) {
2661 2665                          props_copy = strdup(props);
2662 2666                          if (props_copy == NULL)
2663 2667                                  return;
2664 2668                          next = props_copy;
2665 2669                  }
2666 2670                  while ((next = parse_props_string(next, &triple)) != NULL) {
2667 2671                          err = ptree_get_prop_by_name(chdh, triple.propname,
2668 2672                              &proph);
2669 2673                          if (err != PICL_SUCCESS)
2670 2674                                  break;
2671 2675                          err = ptree_get_propinfo(proph, &propinfo);
2672 2676                          if (err != PICL_SUCCESS)
2673 2677                                  break;
2674 2678                          err = PICL_FAILURE;
2675 2679                          switch (propinfo.piclinfo.type) {
2676 2680                          case PICL_PTYPE_INT:
2677 2681                          case PICL_PTYPE_UNSIGNED_INT:
2678 2682                                  if (strcmp(triple.proptype, "I") != 0)
2679 2683                                          break;
2680 2684                                  err = ptree_get_propval(proph, (void  *)&val,
2681 2685                                      sizeof (val));
2682 2686                                  if (err != PICL_SUCCESS)
2683 2687                                          break;
2684 2688                                  if (val != atoi(triple.propval))
2685 2689                                          err = PICL_FAILURE;
2686 2690                                  break;
2687 2691                          case PICL_PTYPE_CHARSTRING:
2688 2692                                  if (strcmp(triple.proptype, "S") != 0)
2689 2693                                          break;
2690 2694                                  prop_string = malloc(propinfo.piclinfo.size);
2691 2695                                  if (prop_string == NULL)
2692 2696                                          break;
2693 2697                                  err = ptree_get_propval(proph,
2694 2698                                      (void *)prop_string,
2695 2699                                      propinfo.piclinfo.size);
2696 2700                                  if (err != PICL_SUCCESS) {
2697 2701                                          free(prop_string);
2698 2702                                          break;
2699 2703                                  }
2700 2704                                  if (strcmp(prop_string, triple.propval) != 0)
2701 2705                                          err = PICL_FAILURE;
2702 2706                                  free(prop_string);
2703 2707                                  break;
2704 2708                          default:
2705 2709                                  break;
2706 2710                          }
2707 2711                          if (err != PICL_SUCCESS) {
2708 2712                                  break;
2709 2713                          }
2710 2714                  }
2711 2715                  if (next == NULL) {
2712 2716                          found = B_TRUE;
2713 2717                          break;
2714 2718                  }
2715 2719          }
2716 2720          if (props_copy)
2717 2721                  free(props_copy);
2718 2722          if (found) {
2719 2723                  /*
2720 2724                   * does the pre-existing node have a status property?
2721 2725                   */
2722 2726                  err = ptree_get_propval_by_name(chdh, PICL_PROP_STATUS,
2723 2727                      ua, sizeof (ua));
2724 2728                  if (err == PICL_PROPNOTFOUND)
2725 2729                          (void) add_status_prop(chdh, status);
2726 2730                  if (err != PICL_SUCCESS)
2727 2731                          return;
2728 2732                  if ((strcmp(ua, ASR_DISABLED) == 0) ||
2729 2733                      (strcmp(ua, ASR_FAILED) == 0) ||
2730 2734                      ((strcmp(status, ASR_DISABLED) != 0) &&
2731 2735                      (strcmp(status, ASR_FAILED) != 0))) {
2732 2736                          return;
2733 2737                  }
2734 2738                  /*
2735 2739                   * more urgent status now, so replace existing value
2736 2740                   */
2737 2741                  err = ptree_get_prop_by_name(chdh, PICL_PROP_STATUS, &proph);
2738 2742                  if (err != PICL_SUCCESS)
2739 2743                          return;
2740 2744                  (void) ptree_delete_prop(proph);
2741 2745                  (void) ptree_destroy_prop(proph);
2742 2746                  err = add_status_prop(chdh, status);
2743 2747                  if (err != PICL_SUCCESS)
2744 2748                          return;
2745 2749                  return;
2746 2750          }
2747 2751  
2748 2752          /*
2749 2753           * typical case, node needs adding together with a set of properties
2750 2754           */
2751 2755          if (ptree_create_and_add_node(nodeh, child, class, &chdh) ==
2752 2756              PICL_SUCCESS) {
2753 2757                  (void) add_status_prop(chdh, status);
2754 2758                  if (unitaddr) {
2755 2759                          (void) ptree_init_propinfo(&propinfo,
2756 2760                              PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING,
2757 2761                              PICL_READ, strlen(unitaddr) + 1,
2758 2762                              PICL_PROP_UNIT_ADDRESS, NULL, NULL);
2759 2763                          (void) ptree_create_and_add_prop(chdh, &propinfo,
2760 2764                              unitaddr, &proph);
2761 2765                          (void) strlcpy(ptreepath, parent, PATH_MAX);
2762 2766                          (void) strlcat(ptreepath, "/", PATH_MAX);
2763 2767                          (void) strlcat(ptreepath, child, PATH_MAX);
2764 2768                          (void) strlcat(ptreepath, "@", PATH_MAX);
2765 2769                          (void) strlcat(ptreepath, unitaddr, PATH_MAX);
2766 2770                          (void) ptree_init_propinfo(&propinfo,
2767 2771                              PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING,
2768 2772                              PICL_READ, strlen(ptreepath) + 1,
2769 2773                              PICL_PROP_DEVFS_PATH, NULL, NULL);
2770 2774                          (void) ptree_create_and_add_prop(chdh, &propinfo,
2771 2775                              ptreepath, &proph);
2772 2776                  }
2773 2777                  next = props;
2774 2778                  while ((next = parse_props_string(next, &triple)) != NULL) {
2775 2779                          /*
2776 2780                           * only handle int and string properties for
2777 2781                           * simplicity
2778 2782                           */
2779 2783                          if (strcmp(triple.proptype, "I") == 0) {
2780 2784                                  (void) ptree_init_propinfo(&propinfo,
2781 2785                                      PTREE_PROPINFO_VERSION,
2782 2786                                      PICL_PTYPE_INT, PICL_READ,
2783 2787                                      sizeof (int), triple.propname, NULL, NULL);
2784 2788                                  val = atoi(triple.propval);
2785 2789                                  (void) ptree_create_and_add_prop(chdh,
2786 2790                                      &propinfo, &val, &proph);
2787 2791                          } else {
2788 2792                                  (void) ptree_init_propinfo(&propinfo,
2789 2793                                      PTREE_PROPINFO_VERSION,
2790 2794                                      PICL_PTYPE_CHARSTRING, PICL_READ,
2791 2795                                      strlen(triple.propval) + 1,
2792 2796                                      triple.propname, NULL, NULL);
2793 2797                                  (void) ptree_create_and_add_prop(chdh,
2794 2798                                      &propinfo, triple.propval, &proph);
2795 2799                          }
2796 2800                  }
2797 2801          }
2798 2802  }
2799 2803  
2800 2804  static void
2801 2805  add_asr_nodes()
2802 2806  {
2803 2807          char                    *asrexport;
2804 2808          int                     asrexportlen;
2805 2809          asr_conf_entries_t      *c = NULL;
2806 2810          int                     i;
2807 2811          char                    *key;
2808 2812          char                    *child;
2809 2813          char                    *unitaddr;
2810 2814          uint16_t                count;
2811 2815          int                     disabled;
2812 2816  
2813 2817          if (get_asr_export_list(&asrexport, &asrexportlen) == 0)
2814 2818                  return;
2815 2819          process_asrtree_conf_file();
2816 2820          if (conf_name_asr_map == NULL)
2817 2821                  return;
2818 2822          i = 0;
2819 2823          while (i < asrexportlen) {
2820 2824                  key = &asrexport[i];
2821 2825                  i += strlen(key) + 1;
2822 2826                  if (i >= asrexportlen)
2823 2827                          break;
2824 2828  
2825 2829                  /*
2826 2830                   * next byte tells us whether failed by diags or manually
2827 2831                   * disabled
2828 2832                   */
2829 2833                  disabled = asrexport[i];
2830 2834                  i++;
2831 2835                  if (i >= asrexportlen)
2832 2836                          break;
2833 2837  
2834 2838                  /*
2835 2839                   * only type 1 supported
2836 2840                   */
2837 2841                  if (asrexport[i] != 1)
2838 2842                          break;
2839 2843                  i++;
2840 2844                  if (i >= asrexportlen)
2841 2845                          break;
2842 2846  
2843 2847                  /*
2844 2848                   * next two bytes give size of reason string
2845 2849                   */
2846 2850                  count = (asrexport[i] << 8) | asrexport[i + 1];
2847 2851                  i += count + 2;
2848 2852                  if (i > asrexportlen)
2849 2853                          break;
2850 2854  
2851 2855                  /*
2852 2856                   * now look for key in conf file info
2853 2857                   */
2854 2858                  c = conf_name_asr_map;
2855 2859                  while (c != NULL) {
2856 2860                          if (strcmp(key, c->name) == 0) {
2857 2861                                  child = strrchr(c->address, '/');
2858 2862                                  *child++ = '\0';
2859 2863                                  unitaddr = strchr(child, '@');
2860 2864                                  if (unitaddr)
2861 2865                                          *unitaddr++ = '\0';
2862 2866                                  if (strcmp(c->status, ASR_DISABLED) == 0) {
2863 2867                                          create_asr_node(c->address, child,
2864 2868                                              unitaddr, c->piclclass, disabled ?
2865 2869                                              ASR_DISABLED : ASR_FAILED,
2866 2870                                              c->props);
2867 2871                                  } else {
2868 2872                                          create_asr_node(c->address, child,
2869 2873                                              unitaddr, c->piclclass, c->status,
2870 2874                                              c->props);
2871 2875                                  }
2872 2876                          }
2873 2877                          c = c->next;
2874 2878                  }
2875 2879          }
2876 2880  
2877 2881          free_asr_conf_entries(conf_name_asr_map);
2878 2882          free(asrexport);
2879 2883  }
2880 2884  
2881 2885  /*
2882 2886   * This function adds information to the /platform node
2883 2887   */
2884 2888  static int
2885 2889  add_platform_info(picl_nodehdl_t plafh)
2886 2890  {
2887 2891          struct utsname          uts_info;
2888 2892          int                     err;
2889 2893          ptree_propinfo_t        propinfo;
2890 2894          picl_prophdl_t          proph;
2891 2895  
2892 2896          if (uname(&uts_info) < 0)
2893 2897                  return (PICL_FAILURE);
2894 2898  
2895 2899          (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2896 2900              PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.sysname) + 1,
2897 2901              PICL_PROP_SYSNAME, NULL, NULL);
2898 2902          err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.sysname,
2899 2903              &proph);
2900 2904          if (err != PICL_SUCCESS)
2901 2905                  return (err);
2902 2906  
2903 2907          (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2904 2908              PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.nodename) + 1,
2905 2909              PICL_PROP_NODENAME, NULL, NULL);
2906 2910          err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.nodename,
2907 2911              &proph);
2908 2912          if (err != PICL_SUCCESS)
2909 2913                  return (err);
2910 2914  
2911 2915          (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2912 2916              PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.release) + 1,
2913 2917              PICL_PROP_RELEASE, NULL, NULL);
2914 2918          err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.release,
2915 2919              &proph);
2916 2920          if (err != PICL_SUCCESS)
2917 2921                  return (err);
2918 2922  
2919 2923          (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2920 2924              PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.version) + 1,
2921 2925              PICL_PROP_VERSION, NULL, NULL);
2922 2926          err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.version,
2923 2927              &proph);
2924 2928          if (err != PICL_SUCCESS)
2925 2929                  return (err);
2926 2930  
2927 2931          (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2928 2932              PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.machine) + 1,
2929 2933              PICL_PROP_MACHINE, NULL, NULL);
2930 2934          err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.machine,
2931 2935              &proph);
2932 2936          return (err);
2933 2937  }
2934 2938  
2935 2939  /*
2936 2940   * Get first 32-bit value from the reg property
2937 2941   */
2938 2942  static int
2939 2943  get_first_reg_word(picl_nodehdl_t nodeh, uint32_t *regval)
2940 2944  {
2941 2945          int                     err;
2942 2946          uint32_t                *regbuf;
2943 2947          picl_prophdl_t          regh;
2944 2948          ptree_propinfo_t        pinfo;
2945 2949  
2946 2950          err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h);
2947 2951          if (err != PICL_SUCCESS)        /* no reg property */
2948 2952                  return (err);
2949 2953          err = ptree_get_propinfo(regh, &pinfo);
2950 2954          if (err != PICL_SUCCESS)
2951 2955                  return (err);
2952 2956          if (pinfo.piclinfo.size < sizeof (uint32_t)) /* too small */
2953 2957                  return (PICL_FAILURE);
2954 2958          regbuf = alloca(pinfo.piclinfo.size);
2955 2959          if (regbuf == NULL)
2956 2960                  return (PICL_FAILURE);
2957 2961          err = ptree_get_propval(regh, regbuf, pinfo.piclinfo.size);
2958 2962          if (err != PICL_SUCCESS)
2959 2963                  return (err);
2960 2964          *regval = *regbuf;      /* get first 32-bit value */
2961 2965          return (PICL_SUCCESS);
2962 2966  }
2963 2967  
2964 2968  /*
2965 2969   * Get device ID from the reg property
2966 2970   */
2967 2971  static int
2968 2972  get_device_id(picl_nodehdl_t nodeh, uint32_t *dev_id)
2969 2973  {
2970 2974          int                     err;
2971 2975          uint32_t                regval;
2972 2976  
2973 2977          err = get_first_reg_word(nodeh, ®val);
2974 2978          if (err != PICL_SUCCESS)
2975 2979                  return (err);
2976 2980  
2977 2981          *dev_id = PCI_DEVICE_ID(regval);
2978 2982          return (PICL_SUCCESS);
2979 2983  }
2980 2984  
2981 2985  /*
2982 2986   * add Slot property for children of SBUS node
2983 2987   */
2984 2988  /* ARGSUSED */
2985 2989  static int
2986 2990  add_sbus_slots(picl_nodehdl_t pcih, void *args)
2987 2991  {
2988 2992          picl_nodehdl_t          nodeh;
2989 2993          uint32_t                slot;
2990 2994          int                     err;
2991 2995          ptree_propinfo_t        pinfo;
2992 2996  
2993 2997          for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
2994 2998              sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
2995 2999              err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
2996 3000              sizeof (picl_nodehdl_t))) {
2997 3001                  if (err != PICL_SUCCESS)
2998 3002                          return (err);
2999 3003  
3000 3004                  if (get_first_reg_word(nodeh, &slot) != 0)
3001 3005                          continue;
3002 3006                  (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
3003 3007                      PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t),
3004 3008                      PICL_PROP_SLOT, NULL, NULL);
3005 3009                  (void) ptree_create_and_add_prop(nodeh, &pinfo, &slot, NULL);
3006 3010          }
3007 3011  
3008 3012          return (PICL_WALK_CONTINUE);
3009 3013  }
3010 3014  
3011 3015  /*
3012 3016   * This function creates a Slot property for SBUS child nodes
3013 3017   * which can be correlated with the slot they are plugged into
3014 3018   * on the motherboard.
3015 3019   */
3016 3020  static int
3017 3021  set_sbus_slot(picl_nodehdl_t plafh)
3018 3022  {
3019 3023          int             err;
3020 3024  
3021 3025          err = ptree_walk_tree_by_class(plafh, PICL_CLASS_SBUS, NULL,
3022 3026              add_sbus_slots);
3023 3027  
3024 3028          return (err);
3025 3029  }
3026 3030  
3027 3031  /*
3028 3032   * add DeviceID property for children of PCI/PCIEX node
3029 3033   */
3030 3034  /* ARGSUSED */
3031 3035  static int
3032 3036  add_pci_deviceids(picl_nodehdl_t pcih, void *args)
3033 3037  {
3034 3038          picl_nodehdl_t          nodeh;
3035 3039          uint32_t                dev_id;
3036 3040          int                     err;
3037 3041          ptree_propinfo_t        pinfo;
3038 3042  
3039 3043          for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
3040 3044              sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
3041 3045              err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
3042 3046              sizeof (picl_nodehdl_t))) {
3043 3047                  if (err != PICL_SUCCESS)
3044 3048                          return (err);
3045 3049  
3046 3050                  if (get_device_id(nodeh, &dev_id) != 0)
3047 3051                          continue;
3048 3052                  (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
3049 3053                      PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t),
3050 3054                      PICL_PROP_DEVICE_ID, NULL, NULL);
3051 3055                  (void) ptree_create_and_add_prop(nodeh, &pinfo, &dev_id, NULL);
3052 3056          }
3053 3057  
3054 3058          return (PICL_WALK_CONTINUE);
3055 3059  }
3056 3060  
3057 3061  /*
3058 3062   * This function creates a DeviceID property for PCI/PCIEX child nodes
3059 3063   * which can be correlated with the slot they are plugged into
3060 3064   * on the motherboard.
3061 3065   */
3062 3066  static void
3063 3067  set_pci_pciex_deviceid(picl_nodehdl_t plafh)
3064 3068  {
3065 3069          (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCI, NULL,
3066 3070              add_pci_deviceids);
3067 3071  
3068 3072          (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, NULL,
3069 3073              add_pci_deviceids);
3070 3074  }
3071 3075  
3072 3076  /*
3073 3077   * Default UnitAddress encode function
3074 3078   */
3075 3079  static int
3076 3080  encode_default_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells)
3077 3081  {
3078 3082          int     i, len;
3079 3083  
3080 3084          /*
3081 3085           * Encode UnitAddress as %a,%b,%c,...,%n
3082 3086           */
3083 3087          if (addrcells < 1)
3084 3088                  return (-1);
3085 3089  
3086 3090          len = snprintf(buf, sz, "%x", *regprop);
3087 3091          for (i = 1; i < addrcells && len < sz; i++)
3088 3092                  len += snprintf(&buf[len], sz-len, ",%x", regprop[i]);
3089 3093  
3090 3094          return ((len >= sz) ? -1 : 0);
3091 3095  }
3092 3096  
3093 3097  /*
3094 3098   * UnitAddress encode function where the last component is not printed
3095 3099   * unless non-zero.
3096 3100   */
3097 3101  static int
3098 3102  encode_optional_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells)
3099 3103  {
3100 3104          int     retval;
3101 3105  
3102 3106          /*
3103 3107           * Encode UnitAddress as %a,%b,%c,...,%n where the last component
3104 3108           * is printed only if non-zero.
3105 3109           */
3106 3110          if (addrcells > 1 && regprop[addrcells-1] == 0)
3107 3111                  retval = encode_default_unitaddr(buf, sz, regprop, addrcells-1);
3108 3112          else
3109 3113                  retval = encode_default_unitaddr(buf, sz, regprop, addrcells);
3110 3114  
3111 3115          return (retval);
3112 3116  }
3113 3117  
3114 3118  
3115 3119  /*
3116 3120   * UnitAddress encode function for SCSI class of devices
3117 3121   */
3118 3122  static int
3119 3123  encode_scsi_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells)
3120 3124  {
3121 3125          int     len, retval;
3122 3126  
3123 3127          /*
3124 3128           * #address-cells       Format
3125 3129           *      2               second component printed only if non-zero
3126 3130           *
3127 3131           *      4               regprop:   phys_hi phys_lo lun_hi lun_lo
3128 3132           *                      UnitAddr:  w<phys_hi><phys_lo>,<lun_lo>
3129 3133           */
3130 3134  
3131 3135          if (addrcells == 2) {
3132 3136                  retval = encode_optional_unitaddr(buf, sz, regprop, addrcells);
3133 3137          } else if (addrcells == 4) {
3134 3138                  len = snprintf(buf, sz, "w%08x%08x,%x", regprop[0], regprop[1],
3135 3139                      regprop[3]);
3136 3140                  retval = (len >= sz) ? -1 : 0;
3137 3141          } else
3138 3142                  retval = -1;
3139 3143  
3140 3144          return (retval);
3141 3145  }
3142 3146  
3143 3147  /*
3144 3148   * UnitAddress encode function for UPA devices
3145 3149   */
3146 3150  static int
3147 3151  encode_upa_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells)
3148 3152  {
3149 3153          int     len;
3150 3154  
3151 3155          if (addrcells != 2)
3152 3156                  return (-1);
3153 3157  
3154 3158          len = snprintf(buf, sz, "%x,%x", (regprop[0]/2)&0x1f, regprop[1]);
3155 3159          return ((len >= sz) ? -1 : 0);
3156 3160  }
3157 3161  
3158 3162  /*
3159 3163   * UnitAddress encode function for GPTWO, JBUS devices
3160 3164   */
3161 3165  static int
3162 3166  encode_gptwo_jbus_unitaddr(char *buf, int sz, uint32_t *regprop,
3163 3167      uint_t addrcells)
3164 3168  {
3165 3169          uint32_t        hi, lo;
3166 3170          int             len, id, off;
3167 3171  
3168 3172          if (addrcells != 2)
3169 3173                  return (-1);
3170 3174  
3171 3175          hi = regprop[0];
3172 3176          lo = regprop[1];
3173 3177  
3174 3178          if (hi & 0x400) {
3175 3179                  id = ((hi & 0x1) << 9) | (lo >> 23);    /* agent id */
3176 3180                  off = lo & 0x7fffff;                    /* config offset */
3177 3181                  len = snprintf(buf, sz, "%x,%x", id, off);
3178 3182          } else {
3179 3183                  len = snprintf(buf, sz, "m%x,%x", hi, lo);
3180 3184          }
3181 3185          return ((len >= sz) ? -1 : 0);
3182 3186  }
3183 3187  
3184 3188  /*
3185 3189   * UnitAddress encode function for PCI devices
3186 3190   */
3187 3191  static int
3188 3192  encode_pci_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells)
3189 3193  {
3190 3194          typedef struct {
3191 3195                  uint32_t        n:1,            /* relocatable */
3192 3196                                  p:1,            /* prefetchable */
3193 3197                                  t:1,            /* address region aliases */
3194 3198                                  zero:3,         /* must be zero */
3195 3199                                  ss:2,           /* address space type */
3196 3200                                  bus:8,          /* bus number */
3197 3201                                  dev:5,          /* device number */
3198 3202                                  fn:3,           /* function number */
3199 3203                                  reg:8;          /* register number */
3200 3204                  uint32_t        phys_hi;        /* high physical address */
3201 3205                  uint32_t        phys_lo;        /* low physical address */
3202 3206          } pci_addrcell_t;
3203 3207  
3204 3208          pci_addrcell_t  *p;
3205 3209          int             len;
3206 3210  
3207 3211          if (addrcells != 3)
3208 3212                  return (-1);
3209 3213  
3210 3214          p = (pci_addrcell_t *)regprop;
3211 3215          switch (p->ss) {
3212 3216          case 0:         /* Config */
3213 3217                  if (p->fn)
3214 3218                          len = snprintf(buf, sz, "%x,%x", p->dev, p->fn);
3215 3219                  else
3216 3220                          len = snprintf(buf, sz, "%x", p->dev);
3217 3221                  break;
3218 3222          case 1:         /* IO */
3219 3223                  len = snprintf(buf, sz, "i%x,%x,%x,%x", p->dev, p->fn, p->reg,
3220 3224                      p->phys_lo);
3221 3225                  break;
3222 3226          case 2:         /* Mem32 */
3223 3227                  len = snprintf(buf, sz, "m%x,%x,%x,%x", p->dev, p->fn, p->reg,
3224 3228                      p->phys_lo);
3225 3229                  break;
3226 3230          case 3:         /* Mem64 */
3227 3231                  len = snprintf(buf, sz, "x%x,%x,%x,%x%08x", p->dev, p->fn,
3228 3232                      p->reg, p->phys_hi, p->phys_lo);
3229 3233                  break;
3230 3234          }
3231 3235          return ((len >= sz) ? -1 : 0);
3232 3236  }
3233 3237  
3234 3238  /*
3235 3239   * Get #address-cells property value
3236 3240   */
3237 3241  static uint_t
3238 3242  get_addrcells_prop(picl_nodehdl_t nodeh)
3239 3243  {
3240 3244          int                     len, err;
3241 3245          uint32_t                addrcells;
3242 3246          ptree_propinfo_t        pinfo;
3243 3247          picl_prophdl_t          proph;
3244 3248  
3245 3249          /*
3246 3250           * Get #address-cells property.  If not present, use default value.
3247 3251           */
3248 3252          err = ptree_get_prop_by_name(nodeh, OBP_PROP_ADDRESS_CELLS, &proph);
3249 3253          if (err == PICL_SUCCESS)
3250 3254                  err = ptree_get_propinfo(proph, &pinfo);
3251 3255  
3252 3256          len = pinfo.piclinfo.size;
3253 3257          if (err == PICL_SUCCESS && len >= sizeof (uint8_t) &&
3254 3258              len <= sizeof (addrcells)) {
3255 3259                  err = ptree_get_propval(proph, &addrcells, len);
3256 3260                  if (err == PICL_SUCCESS) {
3257 3261                          if (len == sizeof (uint8_t))
3258 3262                                  addrcells = *(uint8_t *)&addrcells;
3259 3263                          else if (len == sizeof (uint16_t))
3260 3264                                  addrcells = *(uint16_t *)&addrcells;
3261 3265                  } else
3262 3266                          addrcells = DEFAULT_ADDRESS_CELLS;
3263 3267          } else
3264 3268                  addrcells = DEFAULT_ADDRESS_CELLS;
3265 3269  
3266 3270          return (addrcells);
3267 3271  }
3268 3272  
3269 3273  /*
3270 3274   * Get UnitAddress mapping entry for a node
3271 3275   */
3272 3276  static unitaddr_map_t *
3273 3277  get_unitaddr_mapping(picl_nodehdl_t nodeh)
3274 3278  {
3275 3279          int             err;
3276 3280          unitaddr_map_t  *uamap;
3277 3281          char            clname[PICL_CLASSNAMELEN_MAX];
3278 3282  
3279 3283          /*
3280 3284           * Get my classname and locate a function to translate "reg" prop
3281 3285           * into "UnitAddress" prop for my children.
3282 3286           */
3283 3287          err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, clname,
3284 3288              sizeof (clname));
3285 3289          if (err != PICL_SUCCESS)
3286 3290                  (void) strcpy(clname, "");      /* NULL class name */
3287 3291  
3288 3292          for (uamap = &unitaddr_map_table[0]; uamap->class != NULL; uamap++)
3289 3293                  if (strcmp(clname, uamap->class) == 0)
3290 3294                          break;
3291 3295  
3292 3296          return (uamap);
3293 3297  }
3294 3298  
3295 3299  /*
3296 3300   * Add UnitAddress property to the specified node
3297 3301   */
3298 3302  static int
3299 3303  add_unitaddr_prop(picl_nodehdl_t nodeh, unitaddr_map_t *uamap, uint_t addrcells)
3300 3304  {
3301 3305          int                     regproplen, err;
3302 3306          uint32_t                *regbuf;
3303 3307          picl_prophdl_t          regh;
3304 3308          ptree_propinfo_t        pinfo;
3305 3309          char                    unitaddr[MAX_UNIT_ADDRESS_LEN];
3306 3310  
3307 3311          err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h);
3308 3312          if (err != PICL_SUCCESS)
3309 3313                  return (err);
3310 3314  
3311 3315          err = ptree_get_propinfo(regh, &pinfo);
3312 3316          if (err != PICL_SUCCESS)
3313 3317                  return (PICL_FAILURE);
3314 3318  
3315 3319          if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t)))
3316 3320                  return (PICL_FAILURE);
3317 3321  
3318 3322          regproplen = pinfo.piclinfo.size;
3319 3323          regbuf = alloca(regproplen);
3320 3324          if (regbuf == NULL)
3321 3325                  return (PICL_FAILURE);
3322 3326  
3323 3327          err = ptree_get_propval(regh, regbuf, regproplen);
3324 3328          if (err != PICL_SUCCESS || uamap->func == NULL ||
3325 3329              (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) ||
3326 3330              (uamap->func)(unitaddr, sizeof (unitaddr), regbuf,
3327 3331              addrcells) != 0) {
3328 3332                  return (PICL_FAILURE);
3329 3333          }
3330 3334  
3331 3335          err = ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
3332 3336              PICL_PTYPE_CHARSTRING, PICL_READ, strlen(unitaddr)+1,
3333 3337              PICL_PROP_UNIT_ADDRESS, NULL, NULL);
3334 3338          if (err == PICL_SUCCESS)
3335 3339                  err = ptree_create_and_add_prop(nodeh, &pinfo, unitaddr, NULL);
3336 3340  
3337 3341          return (err);
3338 3342  }
3339 3343  
3340 3344  /*
3341 3345   * work out UnitAddress property of the specified node
3342 3346   */
3343 3347  static int
3344 3348  get_unitaddr(picl_nodehdl_t parh, picl_nodehdl_t nodeh, char *unitaddr,
3345 3349      size_t ualen)
3346 3350  {
3347 3351          int                     regproplen, err;
3348 3352          uint32_t                *regbuf;
3349 3353          picl_prophdl_t          regh;
3350 3354          ptree_propinfo_t        pinfo;
3351 3355          unitaddr_map_t          *uamap;
3352 3356          uint32_t                addrcells;
3353 3357  
3354 3358          addrcells = get_addrcells_prop(parh);
3355 3359          uamap = get_unitaddr_mapping(parh);
3356 3360  
3357 3361          err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h);
3358 3362          if (err != PICL_SUCCESS)
3359 3363                  return (err);
3360 3364  
3361 3365          err = ptree_get_propinfo(regh, &pinfo);
3362 3366          if (err != PICL_SUCCESS)
3363 3367                  return (err);
3364 3368  
3365 3369          if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t)))
3366 3370                  return (PICL_FAILURE);
3367 3371  
3368 3372          regproplen = pinfo.piclinfo.size;
3369 3373          regbuf = alloca(regproplen);
3370 3374          if (regbuf == NULL)
3371 3375                  return (PICL_FAILURE);
3372 3376  
3373 3377          err = ptree_get_propval(regh, regbuf, regproplen);
3374 3378          if (err != PICL_SUCCESS || uamap->func == NULL ||
3375 3379              (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) ||
3376 3380              (uamap->func)(unitaddr, ualen, regbuf, addrcells) != 0) {
3377 3381                  return (PICL_FAILURE);
3378 3382          }
3379 3383          return (PICL_SUCCESS);
3380 3384  }
3381 3385  
3382 3386  /*
3383 3387   * Add UnitAddress property to all children of the specified node
3384 3388   */
3385 3389  static int
3386 3390  add_unitaddr_prop_to_subtree(picl_nodehdl_t nodeh)
3387 3391  {
3388 3392          int                     err;
3389 3393          picl_nodehdl_t          chdh;
3390 3394          unitaddr_map_t          *uamap;
3391 3395          uint32_t                addrcells;
3392 3396  
3393 3397          /*
3394 3398           * Get #address-cells and unit address mapping entry for my
3395 3399           * node's class
3396 3400           */
3397 3401          addrcells = get_addrcells_prop(nodeh);
3398 3402          uamap = get_unitaddr_mapping(nodeh);
3399 3403  
3400 3404          /*
3401 3405           * Add UnitAddress property to my children and their subtree
3402 3406           */
3403 3407          err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh,
3404 3408              sizeof (picl_nodehdl_t));
3405 3409  
3406 3410          while (err == PICL_SUCCESS) {
3407 3411                  (void) add_unitaddr_prop(chdh, uamap, addrcells);
3408 3412                  (void) add_unitaddr_prop_to_subtree(chdh);
3409 3413  
3410 3414                  err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
3411 3415                      sizeof (picl_nodehdl_t));
3412 3416          }
3413 3417  
3414 3418          return (PICL_SUCCESS);
3415 3419  }
3416 3420  
3417 3421  static int
3418 3422  update_memory_size_prop(picl_nodehdl_t plafh)
3419 3423  {
3420 3424          picl_nodehdl_t          memh;
3421 3425          picl_prophdl_t          proph;
3422 3426          ptree_propinfo_t        pinfo;
3423 3427          int                     err, nspecs, snum, pval;
3424 3428          char                    *regbuf;
3425 3429          memspecs_t              *mspecs;
3426 3430          uint64_t                memsize;
3427 3431  
3428 3432          /*
3429 3433           * check if the #size-cells of the platform node is 2
3430 3434           */
3431 3435          err = ptree_get_propval_by_name(plafh, OBP_PROP_SIZE_CELLS, &pval,
3432 3436              sizeof (pval));
3433 3437  
3434 3438          if (err == PICL_PROPNOTFOUND)
3435 3439                  pval = SUPPORTED_NUM_CELL_SIZE;
3436 3440          else if (err != PICL_SUCCESS)
3437 3441                  return (err);
3438 3442  
3439 3443          /*
3440 3444           * don't know how to handle other vals
3441 3445           */
3442 3446          if (pval != SUPPORTED_NUM_CELL_SIZE)
3443 3447                  return (PICL_FAILURE);
3444 3448  
3445 3449          err = ptree_get_node_by_path(MEMORY_PATH, &memh);
3446 3450          if (err != PICL_SUCCESS)
3447 3451                  return (err);
3448 3452  
3449 3453          /*
3450 3454           * Get the REG property to calculate the size of memory
3451 3455           */
3452 3456          err = ptree_get_prop_by_name(memh, OBP_REG, &proph);
3453 3457          if (err != PICL_SUCCESS)
3454 3458                  return (err);
3455 3459  
3456 3460          err = ptree_get_propinfo(proph, &pinfo);
3457 3461          if (err != PICL_SUCCESS)
3458 3462                  return (err);
3459 3463  
3460 3464          regbuf = alloca(pinfo.piclinfo.size);
3461 3465          if (regbuf == NULL)
3462 3466                  return (PICL_FAILURE);
3463 3467  
3464 3468          err = ptree_get_propval(proph, regbuf, pinfo.piclinfo.size);
3465 3469          if (err != PICL_SUCCESS)
3466 3470                  return (err);
3467 3471  
3468 3472          mspecs = (memspecs_t *)regbuf;
3469 3473          nspecs = pinfo.piclinfo.size / sizeof (memspecs_t);
3470 3474  
3471 3475          memsize = 0;
3472 3476          for (snum = 0; snum < nspecs; ++snum)
3473 3477                  memsize += mspecs[snum].size;
3474 3478  
3475 3479          err = ptree_get_prop_by_name(memh, PICL_PROP_SIZE, &proph);
3476 3480          if (err == PICL_SUCCESS) {
3477 3481                  err = ptree_update_propval(proph, &memsize, sizeof (memsize));
3478 3482                  return (err);
3479 3483          }
3480 3484  
3481 3485          /*
3482 3486           * Add the size property
3483 3487           */
3484 3488          (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
3485 3489              PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (memsize),
3486 3490              PICL_PROP_SIZE, NULL, NULL);
3487 3491          err = ptree_create_and_add_prop(memh, &pinfo, &memsize, NULL);
3488 3492          return (err);
3489 3493  }
3490 3494  
3491 3495  /*
3492 3496   * This function is executed as part of .init when the plugin is
3493 3497   * dlopen()ed
3494 3498   */
3495 3499  static void
3496 3500  picldevtree_register(void)
3497 3501  {
3498 3502          if (getenv(SUNW_PICLDEVTREE_PLUGIN_DEBUG))
3499 3503                  picldevtree_debug = 1;
3500 3504          (void) picld_plugin_register(&my_reg_info);
3501 3505  }
3502 3506  
3503 3507  /*
3504 3508   * This function is the init entry point of the plugin.
3505 3509   * It initializes the /platform tree based on libdevinfo
3506 3510   */
3507 3511  static void
3508 3512  picldevtree_init(void)
3509 3513  {
3510 3514          picl_nodehdl_t  rhdl;
3511 3515          int             err;
3512 3516          struct utsname  utsname;
3513 3517          picl_nodehdl_t  plafh;
3514 3518  
3515 3519          if (uname(&utsname) < 0)
3516 3520                  return;
3517 3521  
3518 3522          (void) strcpy(mach_name, utsname.machine);
3519 3523  
3520 3524          if (strcmp(mach_name, "sun4u") == 0) {
3521 3525                  builtin_map_ptr = sun4u_map;
3522 3526                  builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t);
3523 3527          } else if (strcmp(mach_name, "sun4v") == 0) {
3524 3528                  builtin_map_ptr = sun4u_map;
3525 3529                  builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t);
3526 3530          } else if (strcmp(mach_name, "i86pc") == 0) {
3527 3531                  builtin_map_ptr = i86pc_map;
3528 3532                  builtin_map_size = sizeof (i86pc_map) / sizeof (builtin_map_t);
3529 3533          } else {
3530 3534                  builtin_map_ptr = NULL;
3531 3535                  builtin_map_size = 0;
3532 3536          }
3533 3537  
3534 3538          err = ptree_get_root(&rhdl);
3535 3539          if (err != PICL_SUCCESS) {
3536 3540                  syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED);
3537 3541                  return;
3538 3542          }
3539 3543  
3540 3544          process_devtree_conf_file();
3541 3545  
3542 3546          if (libdevinfo_init(rhdl) != PICL_SUCCESS) {
3543 3547                  syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED);
3544 3548                  return;
3545 3549          }
3546 3550  
3547 3551          err = ptree_get_node_by_path(PLATFORM_PATH, &plafh);
3548 3552          if (err != PICL_SUCCESS)
3549 3553                  return;
3550 3554  
3551 3555          (void) add_unitaddr_prop_to_subtree(plafh);
3552 3556  
3553 3557          add_asr_nodes();
3554 3558  
3555 3559          (void) update_memory_size_prop(plafh);
3556 3560  
3557 3561          (void) setup_cpus(plafh);
3558 3562  
3559 3563          (void) add_ffb_config_info(plafh);
3560 3564  
3561 3565          (void) add_platform_info(plafh);
3562 3566  
3563 3567          set_pci_pciex_deviceid(plafh);
3564 3568  
3565 3569          (void) set_sbus_slot(plafh);
3566 3570  
3567 3571          (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3568 3572              picldevtree_evhandler, NULL);
3569 3573          (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3570 3574              picldevtree_evhandler, NULL);
3571 3575          (void) ptree_register_handler(PICLEVENT_CPU_STATE_CHANGE,
3572 3576              picldevtree_evhandler, NULL);
3573 3577          (void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3574 3578              picldevtree_evhandler, NULL);
3575 3579  }
3576 3580  
3577 3581  /*
3578 3582   * This function is the fini entry point of the plugin
3579 3583   */
3580 3584  static void
3581 3585  picldevtree_fini(void)
3582 3586  {
3583 3587          /* First unregister the event handlers */
3584 3588          (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3585 3589              picldevtree_evhandler, NULL);
3586 3590          (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3587 3591              picldevtree_evhandler, NULL);
3588 3592          (void) ptree_unregister_handler(PICLEVENT_CPU_STATE_CHANGE,
3589 3593              picldevtree_evhandler, NULL);
3590 3594          (void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3591 3595              picldevtree_evhandler, NULL);
3592 3596  
3593 3597          conf_name_class_map = free_conf_entries(conf_name_class_map);
3594 3598  }
3595 3599  
3596 3600  /*
3597 3601   * This function is the event handler of this plug-in.
3598 3602   *
3599 3603   * It processes the following events:
3600 3604   *
3601 3605   *      PICLEVENT_SYSEVENT_DEVICE_ADDED
3602 3606   *      PICLEVENT_SYSEVENT_DEVICE_REMOVED
3603 3607   *      PICLEVENT_CPU_STATE_CHANGE
3604 3608   *      PICLEVENT_DR_AP_STATE_CHANGE
3605 3609   */
3606 3610  /* ARGSUSED */
3607 3611  static void
3608 3612  picldevtree_evhandler(const char *ename, const void *earg, size_t size,
3609 3613      void *cookie)
3610 3614  {
3611 3615          char                    *devfs_path;
3612 3616          char                    ptreepath[PATH_MAX];
3613 3617          char                    dipath[PATH_MAX];
3614 3618          picl_nodehdl_t          plafh;
3615 3619          picl_nodehdl_t          nodeh;
3616 3620          nvlist_t                *nvlp;
3617 3621  
3618 3622          if ((earg == NULL) ||
3619 3623              (ptree_get_node_by_path(PLATFORM_PATH, &plafh) != PICL_SUCCESS))
3620 3624                  return;
3621 3625  
3622 3626          if (strcmp(ename, PICLEVENT_DR_AP_STATE_CHANGE) == 0) {
3623 3627                  (void) setup_cpus(plafh);
3624 3628                  if (picldevtree_debug > 1)
3625 3629                          syslog(LOG_INFO, "picldevtree: event handler done\n");
3626 3630                  return;
3627 3631          }
3628 3632  
3629 3633          nvlp = NULL;
3630 3634          if (nvlist_unpack((char *)earg, size, &nvlp, NULL) ||
3631 3635              nvlist_lookup_string(nvlp, PICLEVENTARG_DEVFS_PATH, &devfs_path) ||
3632 3636              strlen(devfs_path) > (PATH_MAX - sizeof (PLATFORM_PATH))) {
3633 3637                  syslog(LOG_INFO, PICL_EVENT_DROPPED, ename);
3634 3638                  nvlist_free(nvlp);
3635 3639                  return;
3636 3640          }
3637 3641  
3638 3642          (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX);
3639 3643          (void) strlcat(ptreepath, devfs_path, PATH_MAX);
3640 3644          (void) strlcpy(dipath, devfs_path, PATH_MAX);
3641 3645          nvlist_free(nvlp);
3642 3646  
3643 3647          if (picldevtree_debug)
3644 3648                  syslog(LOG_INFO, "picldevtree: event handler invoked ename:%s "
3645 3649                      "ptreepath:%s\n", ename, ptreepath);
3646 3650  
3647 3651          if (strcmp(ename, PICLEVENT_CPU_STATE_CHANGE) == 0) {
3648 3652                  goto done;
3649 3653          }
3650 3654          if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) {
3651 3655                  di_node_t               devnode;
3652 3656                  char            *strp;
3653 3657                  picl_nodehdl_t  parh;
3654 3658                  char            nodeclass[PICL_CLASSNAMELEN_MAX];
3655 3659                  char            *nodename;
3656 3660                  int             err;
3657 3661  
3658 3662                  /* If the node already exist, then nothing else to do here */
3659 3663                  if (ptree_get_node_by_path(ptreepath, &nodeh) == PICL_SUCCESS)
3660 3664                          return;
3661 3665  
3662 3666                  /* Skip if unable to find parent PICL node handle */
3663 3667                  parh = plafh;
3664 3668                  if (((strp = strrchr(ptreepath, '/')) != NULL) &&
3665 3669                      (strp != strchr(ptreepath, '/'))) {
3666 3670                          *strp = '\0';
3667 3671                          if (ptree_get_node_by_path(ptreepath, &parh) !=
3668 3672                              PICL_SUCCESS)
3669 3673                                  return;
3670 3674                  }
3671 3675  
3672 3676                  /*
3673 3677                   * If parent is the root node
3674 3678                   */
3675 3679                  if (parh == plafh) {
3676 3680                          ph = di_prom_init();
3677 3681                          devnode = di_init(dipath, DINFOCPYALL);
3678 3682                          if (devnode == DI_NODE_NIL) {
3679 3683                                  if (ph != NULL) {
3680 3684                                          di_prom_fini(ph);
3681 3685                                          ph = NULL;
3682 3686                                  }
3683 3687                                  return;
3684 3688                          }
3685 3689                          nodename = di_node_name(devnode);
3686 3690                          if (nodename == NULL) {
3687 3691                                  di_fini(devnode);
3688 3692                                  if (ph != NULL) {
3689 3693                                          di_prom_fini(ph);
3690 3694                                          ph = NULL;
3691 3695                                  }
3692 3696                                  return;
3693 3697                          }
3694 3698  
3695 3699                          err = get_node_class(nodeclass, devnode, nodename);
3696 3700                          if (err < 0) {
3697 3701                                  di_fini(devnode);
3698 3702                                  if (ph != NULL) {
3699 3703                                          di_prom_fini(ph);
3700 3704                                          ph = NULL;
3701 3705                                  }
3702 3706                                  return;
3703 3707                          }
3704 3708                          err = construct_devtype_node(plafh, nodename,
3705 3709                              nodeclass, devnode, &nodeh);
3706 3710                          if (err != PICL_SUCCESS) {
3707 3711                                  di_fini(devnode);
3708 3712                                  if (ph != NULL) {
3709 3713                                          di_prom_fini(ph);
3710 3714                                          ph = NULL;
3711 3715                                  }
3712 3716                                  return;
3713 3717                          }
3714 3718                          (void) update_subtree(nodeh, devnode);
3715 3719                          (void) add_unitaddr_prop_to_subtree(nodeh);
3716 3720                          if (ph != NULL) {
3717 3721                                  di_prom_fini(ph);
3718 3722                                  ph = NULL;
3719 3723                          }
3720 3724                          di_fini(devnode);
3721 3725                          goto done;
3722 3726                  }
3723 3727  
3724 3728                  /* kludge ... try without bus-addr first */
3725 3729                  if ((strp = strrchr(dipath, '@')) != NULL) {
3726 3730                          char *p;
3727 3731  
3728 3732                          p = strrchr(dipath, '/');
3729 3733                          if (p != NULL && strp > p) {
3730 3734                                  *strp = '\0';
3731 3735                                  devnode = di_init(dipath, DINFOCPYALL);
3732 3736                                  if (devnode != DI_NODE_NIL)
3733 3737                                          di_fini(devnode);
3734 3738                                  *strp = '@';
3735 3739                          }
3736 3740                  }
3737 3741                  /* Get parent devnode */
3738 3742                  if ((strp = strrchr(dipath, '/')) != NULL)
3739 3743                          *++strp = '\0';
3740 3744                  devnode = di_init(dipath, DINFOCPYALL);
3741 3745                  if (devnode == DI_NODE_NIL)
3742 3746                          return;
3743 3747                  ph = di_prom_init();
3744 3748                  (void) update_subtree(parh, devnode);
3745 3749                  (void) add_unitaddr_prop_to_subtree(parh);
3746 3750                  if (ph) {
3747 3751                          di_prom_fini(ph);
3748 3752                          ph = NULL;
3749 3753                  }
3750 3754                  di_fini(devnode);
3751 3755          } else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) {
3752 3756                  char                    delclass[PICL_CLASSNAMELEN_MAX];
3753 3757                  char            *strp;
3754 3758  
3755 3759                  /*
3756 3760                   * if final element of path doesn't have a unit address
3757 3761                   * then it is not uniquely identifiable - cannot remove
3758 3762                   */
3759 3763                  if (((strp = strrchr(ptreepath, '/')) != NULL) &&
3760 3764                      strchr(strp, '@') == NULL)
3761 3765                          return;
3762 3766  
3763 3767                  /* skip if can't find the node */
3764 3768                  if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS)
3765 3769                          return;
3766 3770  
3767 3771                  if (ptree_delete_node(nodeh) != PICL_SUCCESS)
3768 3772                          return;
3769 3773  
3770 3774                  if (picldevtree_debug)
3771 3775                          syslog(LOG_INFO,
3772 3776                              "picldevtree: deleted node nodeh:%llx\n", nodeh);
3773 3777                  if ((ptree_get_propval_by_name(nodeh,
3774 3778                      PICL_PROP_CLASSNAME, delclass, PICL_CLASSNAMELEN_MAX) ==
3775 3779                      PICL_SUCCESS) && IS_MC(delclass)) {
3776 3780                          if (post_mc_event(PICLEVENT_MC_REMOVED, nodeh) !=
3777 3781                              PICL_SUCCESS)
3778 3782                                  syslog(LOG_WARNING, PICL_EVENT_DROPPED,
3779 3783                                      PICLEVENT_MC_REMOVED);
3780 3784                  } else
3781 3785                          (void) ptree_destroy_node(nodeh);
3782 3786          }
3783 3787  done:
3784 3788          (void) setup_cpus(plafh);
3785 3789          (void) add_ffb_config_info(plafh);
3786 3790          set_pci_pciex_deviceid(plafh);
3787 3791          (void) set_sbus_slot(plafh);
3788 3792          if (picldevtree_debug > 1)
3789 3793                  syslog(LOG_INFO, "picldevtree: event handler done\n");
3790 3794  }
  
    | 
      ↓ open down ↓ | 
    1230 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX