Print this page
    
5832 EOF wireless usb (aka UWB)
Reviewed by: TBD
Reviewed by: TBD
Approved by: TBD
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/usb/usba/usba.c
          +++ new/usr/src/uts/common/io/usb/usba/usba.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
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
  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
  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 + *
       25 + * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  24   26   */
  25   27  
  26   28  
  27   29  /*
  28   30   * USBA: Solaris USB Architecture support
  29   31   */
  30   32  #define USBA_FRAMEWORK
  31   33  #include <sys/usb/usba/usba_impl.h>
  32   34  #include <sys/usb/usba/hcdi_impl.h>
  33   35  #include <sys/usb/hubd/hub.h>
  34   36  #include <sys/fs/dv_node.h>
  35   37  
  36   38  static int usba_str_startcmp(char *, char *);
  37   39  
  38   40  /*
  39   41   * USBA private variables and tunables
  40   42   */
  41   43  static kmutex_t usba_mutex;
  42   44  
  43   45  /* mutex to protect usba_root_hubs */
  44   46  static kmutex_t usba_hub_mutex;
  45   47  
  46   48  typedef struct usba_root_hub_ent {
  47   49          dev_info_t *dip;
  48   50          struct usba_root_hub_ent *next;
  49   51  }usba_root_hub_ent_t;
  50   52  
  51   53  static usba_root_hub_ent_t *usba_root_hubs = NULL;
  52   54  
  53   55  /*
  54   56   * ddivs forced binding:
  55   57   *
  56   58   *    usbc usbc_xhubs usbc_xaddress  node name
  57   59   *
  58   60   *      0       x       x       class name or "device"
  59   61   *
  60   62   *      1       0       0       ddivs_usbc
  61   63   *      1       0       >1      ddivs_usbc except device
  62   64   *                              at usbc_xaddress
  63   65   *      1       1       0       ddivs_usbc except hubs
  64   66   *      1       1       >1      ddivs_usbc except hubs and
  65   67   *                              device at usbc_xaddress
  66   68   */
  67   69  uint_t usba_ddivs_usbc;
  68   70  uint_t usba_ddivs_usbc_xhubs;
  69   71  uint_t usba_ddivs_usbc_xaddress;
  70   72  
  71   73  uint_t usba_ugen_force_binding;
  72   74  
  73   75  /*
  74   76   * compatible name handling
  75   77   */
  76   78  /*
  77   79   * allowing for 15 compat names, plus one force bind name and
  78   80   * one possible specified client driver name
  79   81   */
  80   82  #define USBA_MAX_COMPAT_NAMES           17
  81   83  #define USBA_MAX_COMPAT_NAME_LEN        64
  82   84  
  83   85  /* double linked list for usba_devices */
  84   86  usba_list_entry_t       usba_device_list;
  85   87  
  86   88  _NOTE(MUTEX_PROTECTS_DATA(usba_mutex, usba_device_list))
  87   89  
  88   90  /*
  89   91   * modload support
  90   92   */
  91   93  
  92   94  static struct modlmisc modlmisc = {
  93   95          &mod_miscops,   /* Type of module */
  94   96          "USBA: USB Architecture 2.0 1.66"
  95   97  };
  96   98  
  97   99  static struct modlinkage modlinkage = {
  98  100          MODREV_1, (void *)&modlmisc, NULL
  99  101  };
 100  102  
 101  103  
 102  104  static usb_log_handle_t usba_log_handle;
 103  105  uint_t          usba_errlevel = USB_LOG_L4;
 104  106  uint_t          usba_errmask = (uint_t)-1;
 105  107  
 106  108  extern usb_log_handle_t hubdi_log_handle;
 107  109  
 108  110  int
 109  111  _init(void)
 110  112  {
 111  113          int rval;
  
    | 
      ↓ open down ↓ | 
    78 lines elided | 
    
      ↑ open up ↑ | 
  
 112  114  
 113  115          /*
 114  116           * usbai providing log support needs to be init'ed first
 115  117           * and destroyed last
 116  118           */
 117  119          usba_usbai_initialization();
 118  120          usba_usba_initialization();
 119  121          usba_usbai_register_initialization();
 120  122          usba_hcdi_initialization();
 121  123          usba_hubdi_initialization();
 122      -        usba_whcdi_initialization();
 123  124          usba_devdb_initialization();
 124  125  
 125  126          if ((rval = mod_install(&modlinkage)) != 0) {
 126  127                  usba_devdb_destroy();
 127      -                usba_whcdi_destroy();
 128  128                  usba_hubdi_destroy();
 129  129                  usba_hcdi_destroy();
 130  130                  usba_usbai_register_destroy();
 131  131                  usba_usba_destroy();
 132  132                  usba_usbai_destroy();
 133  133          }
 134  134  
 135  135          return (rval);
 136  136  }
 137  137  
 138  138  int
 139  139  _fini()
 140  140  {
 141  141          int rval;
 142  142  
 143  143          if ((rval = mod_remove(&modlinkage)) == 0) {
 144  144                  usba_devdb_destroy();
 145      -                usba_whcdi_destroy();
 146  145                  usba_hubdi_destroy();
 147  146                  usba_hcdi_destroy();
 148  147                  usba_usbai_register_destroy();
 149  148                  usba_usba_destroy();
 150  149                  usba_usbai_destroy();
 151  150          }
 152  151  
 153  152          return (rval);
 154  153  }
 155  154  
 156  155  int
 157  156  _info(struct modinfo *modinfop)
 158  157  {
 159  158          return (mod_info(&modlinkage, modinfop));
 160  159  }
 161  160  
 162  161  boolean_t
 163  162  usba_owns_ia(dev_info_t *dip)
 164  163  {
 165  164          int if_count = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 166  165              "interface-count", 0);
 167  166  
 168  167          return ((if_count) ? B_TRUE : B_FALSE);
 169  168  }
 170  169  
 171  170  /*
 172  171   * common bus ctl for hcd, usb_mid, and hubd
 173  172   */
 174  173  int
 175  174  usba_bus_ctl(dev_info_t *dip,
 176  175          dev_info_t              *rdip,
 177  176          ddi_ctl_enum_t          op,
 178  177          void                    *arg,
 179  178          void                    *result)
 180  179  {
 181  180          dev_info_t              *child_dip = (dev_info_t *)arg;
 182  181          usba_device_t           *usba_device;
 183  182          usba_hcdi_t             *usba_hcdi;
 184  183          usba_hcdi_ops_t         *usba_hcdi_ops;
 185  184  
 186  185          USB_DPRINTF_L4(DPRINT_MASK_USBA, hubdi_log_handle,
 187  186              "usba_bus_ctl: %s%d %s%d op=%d", ddi_node_name(rdip),
 188  187              ddi_get_instance(rdip), ddi_node_name(dip),
 189  188              ddi_get_instance(dip), op);
 190  189  
 191  190          switch (op) {
 192  191  
 193  192          case DDI_CTLOPS_REPORTDEV:
 194  193          {
 195  194                  char *name, compat_name[64], *speed;
 196  195                  usba_device_t   *hub_usba_device;
 197  196                  dev_info_t      *hubdip;
 198  197  
 199  198                  usba_device = usba_get_usba_device(rdip);
 200  199  
 201  200                  /* find the parent hub */
 202  201                  hubdip = ddi_get_parent(rdip);
 203  202                  while ((strcmp(ddi_driver_name(hubdip), "hubd") != 0) &&
 204  203                      !(usba_is_root_hub(hubdip))) {
 205  204                          hubdip = ddi_get_parent(hubdip);
 206  205                  }
 207  206  
 208  207                  hub_usba_device = usba_get_usba_device(hubdip);
 209  208  
 210  209                  if (usba_device) {
 211  210                          if (usb_owns_device(rdip)) {
 212  211                                  (void) snprintf(compat_name,
 213  212                                      sizeof (compat_name),
 214  213                                      "usb%x,%x",
 215  214                                      usba_device->usb_dev_descr->idVendor,
 216  215                                      usba_device->usb_dev_descr->idProduct);
 217  216                          } else if (usba_owns_ia(rdip)) {
 218  217                                  (void) snprintf(compat_name,
 219  218                                      sizeof (compat_name),
 220  219                                      "usbia%x,%x.config%x.%x",
 221  220                                      usba_device->usb_dev_descr->idVendor,
 222  221                                      usba_device->usb_dev_descr->idProduct,
 223  222                                      usba_device->usb_cfg_value,
 224  223                                      usb_get_if_number(rdip));
 225  224                          } else {
 226  225                                  (void) snprintf(compat_name,
 227  226                                      sizeof (compat_name),
 228  227                                      "usbif%x,%x.config%x.%x",
 229  228                                      usba_device->usb_dev_descr->idVendor,
 230  229                                      usba_device->usb_dev_descr->idProduct,
 231  230                                      usba_device->usb_cfg_value,
 232  231                                      usb_get_if_number(rdip));
 233  232                          }
 234  233                          switch (usba_device->usb_port_status) {
 235  234                          case USBA_HIGH_SPEED_DEV:
 236  235                                  speed = "hi speed (USB 2.x)";
 237  236  
 238  237                                  break;
 239  238                          case USBA_LOW_SPEED_DEV:
 240  239                                  speed = "low speed (USB 1.x)";
 241  240  
 242  241                                  break;
 243  242                          case USBA_FULL_SPEED_DEV:
 244  243                          default:
 245  244                                  speed = "full speed (USB 1.x)";
 246  245  
 247  246                                  break;
 248  247                          }
 249  248  
 250  249                          cmn_err(CE_CONT,
 251  250                              "?USB %x.%x %s (%s) operating at %s on "
 252  251                              "USB %x.%x %s hub: "
 253  252                              "%s@%s, %s%d at bus address %d\n",
 254  253                              (usba_device->usb_dev_descr->bcdUSB & 0xff00) >> 8,
 255  254                              usba_device->usb_dev_descr->bcdUSB & 0xff,
 256  255                              (usb_owns_device(rdip) ? "device" :
 257  256                              ((usba_owns_ia(rdip) ? "interface-association" :
 258  257                              "interface"))),
 259  258                              compat_name, speed,
 260  259                              (hub_usba_device->usb_dev_descr->bcdUSB &
 261  260                              0xff00) >> 8,
 262  261                              hub_usba_device->usb_dev_descr->bcdUSB & 0xff,
 263  262                              usba_is_root_hub(hubdip) ? "root" : "external",
 264  263                              ddi_node_name(rdip), ddi_get_name_addr(rdip),
 265  264                              ddi_driver_name(rdip),
 266  265                              ddi_get_instance(rdip), usba_device->usb_addr);
 267  266  
 268  267                          name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 269  268                          (void) usba_get_mfg_prod_sn_str(rdip, name, MAXNAMELEN);
 270  269                          if (name[0] != '\0') {
 271  270                                  cmn_err(CE_CONT, "?\t%s\n", name);
 272  271                          }
 273  272                          kmem_free(name, MAXNAMELEN);
 274  273  
 275  274                  } else { /* harden USBA against this case; if it happens */
 276  275  
 277  276                          cmn_err(CE_CONT,
 278  277                              "?USB-device: %s@%s, %s%d\n",
 279  278                              ddi_node_name(rdip), ddi_get_name_addr(rdip),
 280  279                              ddi_driver_name(rdip), ddi_get_instance(rdip));
 281  280                  }
 282  281  
 283  282                  return (DDI_SUCCESS);
 284  283          }
 285  284  
 286  285          case DDI_CTLOPS_INITCHILD:
 287  286          {
 288  287                  int                     usb_addr;
 289  288                  uint_t                  n;
 290  289                  char                    name[32];
 291  290                  int                     *data;
 292  291                  int                     rval;
 293  292                  int                     len = sizeof (usb_addr);
 294  293  
 295  294                  usba_hcdi       = usba_hcdi_get_hcdi(dip);
 296  295                  usba_hcdi_ops   = usba_hcdi->hcdi_ops;
 297  296                  ASSERT(usba_hcdi_ops != NULL);
 298  297  
 299  298                  /*
 300  299                   * as long as the dip exists, it should have
 301  300                   * usba_device structure associated with it
 302  301                   */
 303  302                  usba_device = usba_get_usba_device(child_dip);
 304  303                  if (usba_device == NULL) {
 305  304  
 306  305                          USB_DPRINTF_L2(DPRINT_MASK_USBA, hubdi_log_handle,
 307  306                              "usba_bus_ctl: DDI_NOT_WELL_FORMED (%s (0x%p))",
 308  307                              ddi_node_name(child_dip), (void *)child_dip);
 309  308  
 310  309                          return (DDI_NOT_WELL_FORMED);
 311  310                  }
 312  311  
 313  312                  /* the dip should have an address and reg property */
 314  313                  if (ddi_prop_op(DDI_DEV_T_NONE, child_dip, PROP_LEN_AND_VAL_BUF,
 315  314                      DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "assigned-address",
 316  315                      (caddr_t)&usb_addr, &len) != DDI_SUCCESS) {
 317  316  
 318  317                          USB_DPRINTF_L2(DPRINT_MASK_USBA, hubdi_log_handle,
 319  318                              "usba_bus_ctl:\n\t"
 320  319                              "%s%d %s%d op=%d rdip = 0x%p dip = 0x%p",
 321  320                              ddi_node_name(rdip), ddi_get_instance(rdip),
 322  321                              ddi_node_name(dip), ddi_get_instance(dip), op,
 323  322                              (void *)rdip, (void *)dip);
 324  323  
 325  324                          USB_DPRINTF_L2(DPRINT_MASK_USBA, hubdi_log_handle,
 326  325                              "usba_bus_ctl: DDI_NOT_WELL_FORMED (%s (0x%p))",
 327  326                              ddi_node_name(child_dip), (void *)child_dip);
 328  327  
 329  328                          return (DDI_NOT_WELL_FORMED);
 330  329                  }
 331  330  
 332  331                  if ((rval = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child_dip,
 333  332                      DDI_PROP_DONTPASS, "reg",
 334  333                      &data, &n)) != DDI_SUCCESS) {
 335  334  
 336  335                          USB_DPRINTF_L2(DPRINT_MASK_USBA, hubdi_log_handle,
 337  336                              "usba_bus_ctl: %d, DDI_NOT_WELL_FORMED", rval);
 338  337  
 339  338                          return (DDI_NOT_WELL_FORMED);
 340  339                  }
 341  340  
 342  341  
 343  342                  /*
 344  343                   * if the configuration is 1, the unit address is
 345  344                   * just the interface number
 346  345                   */
 347  346                  if ((n == 1) || ((n > 1) && (data[1] == 1))) {
 348  347                          (void) sprintf(name, "%x", data[0]);
 349  348                  } else {
 350  349                          (void) sprintf(name, "%x,%x", data[0], data[1]);
 351  350                  }
 352  351  
 353  352                  USB_DPRINTF_L3(DPRINT_MASK_USBA,
 354  353                      hubdi_log_handle, "usba_bus_ctl: name = %s", name);
 355  354  
 356  355                  ddi_prop_free(data);
 357  356                  ddi_set_name_addr(child_dip, name);
 358  357  
 359  358                  /*
 360  359                   * increment the reference count for each child using this
 361  360                   * usba_device structure
 362  361                   */
 363  362                  mutex_enter(&usba_device->usb_mutex);
 364  363                  usba_device->usb_ref_count++;
 365  364  
 366  365                  USB_DPRINTF_L3(DPRINT_MASK_USBA, hubdi_log_handle,
 367  366                      "usba_bus_ctl: init usba_device = 0x%p ref_count = %d",
 368  367                      (void *)usba_device, usba_device->usb_ref_count);
 369  368  
 370  369                  mutex_exit(&usba_device->usb_mutex);
 371  370  
 372  371                  return (DDI_SUCCESS);
 373  372          }
 374  373  
 375  374          case DDI_CTLOPS_UNINITCHILD:
 376  375          {
 377  376                  usba_device = usba_get_usba_device(child_dip);
 378  377  
 379  378                  if (usba_device != NULL) {
 380  379                          /*
 381  380                           * decrement the reference count for each child
 382  381                           * using this  usba_device structure
 383  382                           */
 384  383                          mutex_enter(&usba_device->usb_mutex);
 385  384                          usba_device->usb_ref_count--;
 386  385  
 387  386                          USB_DPRINTF_L3(DPRINT_MASK_USBA, hubdi_log_handle,
 388  387                              "usba_hcdi_bus_ctl: uninit usba_device=0x%p "
 389  388                              "ref_count=%d",
 390  389                              (void *)usba_device, usba_device->usb_ref_count);
 391  390  
 392  391                          mutex_exit(&usba_device->usb_mutex);
 393  392                  }
 394  393                  ddi_set_name_addr(child_dip, NULL);
 395  394  
 396  395                  return (DDI_SUCCESS);
 397  396          }
 398  397  
 399  398          case DDI_CTLOPS_IOMIN:
 400  399                  /* Do nothing */
 401  400                  return (DDI_SUCCESS);
 402  401  
 403  402          /*
 404  403           * These ops correspond to functions that "shouldn't" be called
 405  404           * by a USB client driver.  So  we whine when we're called.
 406  405           */
 407  406          case DDI_CTLOPS_DMAPMAPC:
 408  407          case DDI_CTLOPS_REPORTINT:
 409  408          case DDI_CTLOPS_REGSIZE:
 410  409          case DDI_CTLOPS_NREGS:
 411  410          case DDI_CTLOPS_SIDDEV:
 412  411          case DDI_CTLOPS_SLAVEONLY:
 413  412          case DDI_CTLOPS_AFFINITY:
 414  413          case DDI_CTLOPS_POKE:
 415  414          case DDI_CTLOPS_PEEK:
 416  415                  cmn_err(CE_CONT, "%s%d: invalid op (%d) from %s%d",
 417  416                      ddi_node_name(dip), ddi_get_instance(dip),
 418  417                      op, ddi_node_name(rdip), ddi_get_instance(rdip));
 419  418                  return (DDI_FAILURE);
 420  419  
 421  420          /*
 422  421           * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up
 423  422           */
 424  423          default:
 425  424                  return (ddi_ctlops(dip, rdip, op, arg, result));
 426  425          }
 427  426  }
 428  427  
 429  428  
 430  429  /*
 431  430   * initialize and destroy USBA module
 432  431   */
 433  432  void
 434  433  usba_usba_initialization()
 435  434  {
 436  435          usba_log_handle = usb_alloc_log_hdl(NULL, "usba", &usba_errlevel,
 437  436              &usba_errmask, NULL, 0);
 438  437  
 439  438          USB_DPRINTF_L4(DPRINT_MASK_USBA,
 440  439              usba_log_handle, "usba_usba_initialization");
 441  440  
 442  441          mutex_init(&usba_mutex, NULL, MUTEX_DRIVER, NULL);
 443  442          mutex_init(&usba_hub_mutex, NULL, MUTEX_DRIVER, NULL);
 444  443          usba_init_list(&usba_device_list, NULL, NULL);
 445  444  }
 446  445  
 447  446  
 448  447  void
 449  448  usba_usba_destroy()
 450  449  {
 451  450          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle, "usba_usba_destroy");
 452  451  
 453  452          mutex_destroy(&usba_hub_mutex);
 454  453          mutex_destroy(&usba_mutex);
 455  454          usba_destroy_list(&usba_device_list);
 456  455  
 457  456          usb_free_log_hdl(usba_log_handle);
 458  457  }
 459  458  
 460  459  
 461  460  /*
 462  461   * usba_set_usb_address:
 463  462   *      set usb address in usba_device structure
 464  463   */
 465  464  int
 466  465  usba_set_usb_address(usba_device_t *usba_device)
 467  466  {
 468  467          usb_addr_t address;
 469  468          uchar_t s = 8;
 470  469          usba_hcdi_t *hcdi;
 471  470          char *usb_address_in_use;
 472  471  
 473  472          mutex_enter(&usba_device->usb_mutex);
 474  473  
 475  474          hcdi = usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
 476  475  
 477  476          mutex_enter(&hcdi->hcdi_mutex);
 478  477          usb_address_in_use = hcdi->hcdi_usb_address_in_use;
 479  478  
 480  479          for (address = ROOT_HUB_ADDR + 1;
 481  480              address <= USBA_MAX_ADDRESS; address++) {
 482  481                  if (usb_address_in_use[address/s] & (1 << (address % s))) {
 483  482                          continue;
 484  483                  }
 485  484                  usb_address_in_use[address/s] |= (1 << (address % s));
 486  485                  hcdi->hcdi_device_count++;
 487  486                  HCDI_HOTPLUG_STATS_DATA(hcdi)->hcdi_device_count.value.ui64++;
 488  487                  mutex_exit(&hcdi->hcdi_mutex);
 489  488  
 490  489                  USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
 491  490                      "usba_set_usb_address: %d", address);
 492  491  
 493  492                  usba_device->usb_addr = address;
 494  493  
 495  494                  mutex_exit(&usba_device->usb_mutex);
 496  495  
 497  496                  return (USB_SUCCESS);
 498  497          }
 499  498  
 500  499          usba_device->usb_addr = 0;
 501  500  
 502  501          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
 503  502              "no usb address available");
 504  503  
 505  504          mutex_exit(&hcdi->hcdi_mutex);
 506  505          mutex_exit(&usba_device->usb_mutex);
 507  506  
 508  507          return (USB_FAILURE);
 509  508  }
 510  509  
 511  510  
 512  511  /*
 513  512   * usba_unset_usb_address:
 514  513   *      unset usb_address in usba_device structure
 515  514   */
 516  515  void
 517  516  usba_unset_usb_address(usba_device_t *usba_device)
 518  517  {
 519  518          usb_addr_t address;
 520  519          usba_hcdi_t *hcdi;
 521  520          uchar_t s = 8;
 522  521          char *usb_address_in_use;
 523  522  
 524  523          mutex_enter(&usba_device->usb_mutex);
 525  524          address = usba_device->usb_addr;
 526  525          hcdi = usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
 527  526  
 528  527          if (address > ROOT_HUB_ADDR) {
 529  528                  USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
 530  529                      "usba_unset_usb_address: address=%d", address);
 531  530  
 532  531                  mutex_enter(&hcdi->hcdi_mutex);
 533  532                  usb_address_in_use = hcdi->hcdi_usb_address_in_use;
 534  533  
 535  534                  ASSERT(usb_address_in_use[address/s] & (1 << (address % s)));
 536  535  
 537  536                  usb_address_in_use[address/s] &= ~(1 << (address % s));
 538  537  
 539  538                  hcdi->hcdi_device_count--;
 540  539                  HCDI_HOTPLUG_STATS_DATA(hcdi)->hcdi_device_count.value.ui64--;
 541  540  
 542  541                  mutex_exit(&hcdi->hcdi_mutex);
 543  542  
 544  543                  usba_device->usb_addr = 0;
 545  544          }
 546  545          mutex_exit(&usba_device->usb_mutex);
 547  546  }
 548  547  
 549  548  
 550  549  struct usba_evdata *
 551  550  usba_get_evdata(dev_info_t *dip)
 552  551  {
 553  552          usba_evdata_t *evdata;
 554  553          usba_device_t *usba_device = usba_get_usba_device(dip);
 555  554  
 556  555          /* called when dip attaches */
 557  556          ASSERT(usba_device != NULL);
 558  557  
 559  558          mutex_enter(&usba_device->usb_mutex);
 560  559          evdata = usba_device->usb_evdata;
 561  560          while (evdata) {
 562  561                  if (evdata->ev_dip == dip) {
 563  562                          mutex_exit(&usba_device->usb_mutex);
 564  563  
 565  564                          return (evdata);
 566  565                  }
 567  566                  evdata = evdata->ev_next;
 568  567          }
 569  568  
 570  569          evdata = kmem_zalloc(sizeof (usba_evdata_t), KM_SLEEP);
 571  570          evdata->ev_dip = dip;
 572  571          evdata->ev_next = usba_device->usb_evdata;
 573  572          usba_device->usb_evdata = evdata;
 574  573          mutex_exit(&usba_device->usb_mutex);
 575  574  
 576  575          return (evdata);
 577  576  }
 578  577  
 579  578  
 580  579  /*
 581  580   * allocate a usb device structure and link it in the list
 582  581   */
 583  582  usba_device_t *
 584  583  usba_alloc_usba_device(dev_info_t *root_hub_dip)
 585  584  {
 586  585          usba_device_t   *usba_device;
 587  586          int             ep_idx;
 588  587          ddi_iblock_cookie_t iblock_cookie =
 589  588              usba_hcdi_get_hcdi(root_hub_dip)->hcdi_iblock_cookie;
 590  589  
 591  590          /*
 592  591           * create a new usba_device structure
 593  592           */
 594  593          usba_device = kmem_zalloc(sizeof (usba_device_t), KM_SLEEP);
 595  594  
 596  595          /*
 597  596           * initialize usba_device
 598  597           */
 599  598          mutex_init(&usba_device->usb_mutex, NULL, MUTEX_DRIVER,
 600  599              iblock_cookie);
 601  600  
 602  601          usba_init_list(&usba_device->usb_device_list, (usb_opaque_t)usba_device,
 603  602              iblock_cookie);
 604  603          usba_init_list(&usba_device->usb_allocated, (usb_opaque_t)usba_device,
 605  604              iblock_cookie);
 606  605          mutex_enter(&usba_device->usb_mutex);
 607  606          usba_device->usb_root_hub_dip = root_hub_dip;
 608  607  
 609  608          /*
 610  609           * add to list of usba_devices
 611  610           */
 612  611          usba_add_to_list(&usba_device_list, &usba_device->usb_device_list);
 613  612  
 614  613          /* init mutex in each usba_ph_impl structure */
 615  614          for (ep_idx = 0; ep_idx < USBA_N_ENDPOINTS; ep_idx++) {
 616  615                  mutex_init(&usba_device->usb_ph_list[ep_idx].usba_ph_mutex,
 617  616                      NULL, MUTEX_DRIVER, iblock_cookie);
 618  617          }
 619  618  
 620  619          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
 621  620              "allocated usba_device 0x%p", (void *)usba_device);
 622  621  
 623  622          mutex_exit(&usba_device->usb_mutex);
 624  623  
 625  624          return (usba_device);
 626  625  }
 627  626  
 628  627  
 629  628  /* free NDI event data associated with usba_device */
 630  629  void
 631  630  usba_free_evdata(usba_evdata_t *evdata)
 632  631  {
 633  632          usba_evdata_t *next;
  
    | 
      ↓ open down ↓ | 
    478 lines elided | 
    
      ↑ open up ↑ | 
  
 634  633  
 635  634          while (evdata) {
 636  635                  next = evdata->ev_next;
 637  636                  kmem_free(evdata, sizeof (usba_evdata_t));
 638  637                  evdata = next;
 639  638          }
 640  639  }
 641  640  
 642  641  
 643  642  /*
 644      - * free wireless usb specific structure
 645      - */
 646      -void
 647      -usba_free_wireless_data(usba_wireless_data_t *wireless_data)
 648      -{
 649      -        if (wireless_data == NULL) {
 650      -
 651      -                return;
 652      -        }
 653      -
 654      -        if (wireless_data->wusb_bos) {
 655      -                kmem_free(wireless_data->wusb_bos,
 656      -                    wireless_data->wusb_bos_length);
 657      -        }
 658      -
 659      -        kmem_free(wireless_data, sizeof (usba_wireless_data_t));
 660      -}
 661      -
 662      -
 663      -/*
 664  643   * free usb device structure
 665  644   */
 666  645  void
 667  646  usba_free_usba_device(usba_device_t *usba_device)
 668  647  {
 669  648          int                     i, ep_idx;
 670  649          usb_pipe_handle_t       def_ph;
 671  650  
 672  651          if (usba_device == NULL) {
 673  652  
 674  653                  return;
 675  654          }
 676  655  
 677  656          mutex_enter(&usba_device->usb_mutex);
 678  657          if (usba_device->usb_ref_count) {
 679  658                  mutex_exit(&usba_device->usb_mutex);
 680  659  
 681  660                  return;
 682  661          }
 683  662  
 684  663          USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
 685  664              "usba_free_usba_device 0x%p, address=0x%x, ref cnt=%d",
 686  665              (void *)usba_device, usba_device->usb_addr,
 687  666              usba_device->usb_ref_count);
 688  667  
 689  668          usba_free_evdata(usba_device->usb_evdata);
 690  669          mutex_exit(&usba_device->usb_mutex);
 691  670  
 692  671          def_ph = usba_usbdev_to_dflt_pipe_handle(usba_device);
 693  672          if (def_ph != NULL) {
 694  673                  usba_pipe_handle_data_t *ph_data = usba_get_ph_data(def_ph);
 695  674  
 696  675                  if (ph_data) {
 697  676                          usb_pipe_close(ph_data->p_dip, def_ph,
 698  677                              USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED,
 699  678                              NULL, NULL);
 700  679                  }
 701  680          }
 702  681  
 703  682          mutex_enter(&usba_mutex);
 704  683  
 705  684          /* destroy mutex in each usba_ph_impl structure */
 706  685          for (ep_idx = 0; ep_idx < USBA_N_ENDPOINTS; ep_idx++) {
 707  686                  mutex_destroy(&usba_device->usb_ph_list[ep_idx].usba_ph_mutex);
 708  687          }
 709  688  
 710  689          (void) usba_rm_from_list(&usba_device_list,
 711  690              &usba_device->usb_device_list);
 712  691  
 713  692          mutex_exit(&usba_mutex);
 714  693  
 715  694          usba_destroy_list(&usba_device->usb_device_list);
 716  695          usba_destroy_list(&usba_device->usb_allocated);
 717  696  
 718  697          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
 719  698              "deallocating usba_device = 0x%p, address = 0x%x",
 720  699              (void *)usba_device, usba_device->usb_addr);
 721  700  
 722  701          /*
 723  702           * ohci allocates descriptors for root hub so we can't
 724  703           * deallocate these here
 725  704           */
 726  705  
 727  706          if (usba_device->usb_addr != ROOT_HUB_ADDR) {
 728  707                  if (usba_device->usb_cfg_array) {
 729  708                          USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
 730  709                              "deallocating usb_config_array: 0x%p",
 731  710                              (void *)usba_device->usb_cfg_array);
 732  711                          mutex_enter(&usba_device->usb_mutex);
 733  712                          for (i = 0;
 734  713                              i < usba_device->usb_dev_descr->bNumConfigurations;
 735  714                              i++) {
 736  715                                  if (usba_device->usb_cfg_array[i]) {
 737  716                                          kmem_free(
 738  717                                              usba_device->usb_cfg_array[i],
 739  718                                              usba_device->usb_cfg_array_len[i]);
 740  719                                  }
 741  720                          }
 742  721  
 743  722                          /* free the array pointers */
 744  723                          kmem_free(usba_device->usb_cfg_array,
 745  724                              usba_device->usb_cfg_array_length);
 746  725                          kmem_free(usba_device->usb_cfg_array_len,
 747  726                              usba_device->usb_cfg_array_len_length);
 748  727  
 749  728                          mutex_exit(&usba_device->usb_mutex);
 750  729                  }
 751  730  
 752  731                  if (usba_device->usb_cfg_str_descr) {
 753  732                          USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
 754  733                              "deallocating usb_cfg_str_descr: 0x%p",
 755  734                              (void *)usba_device->usb_cfg_str_descr);
 756  735                          for (i = 0;
 757  736                              i < usba_device->usb_dev_descr->bNumConfigurations;
 758  737                              i++) {
 759  738                                  if (usba_device->usb_cfg_str_descr[i]) {
 760  739                                          kmem_free(
 761  740                                              usba_device->usb_cfg_str_descr[i],
 762  741                                              strlen(usba_device->
 763  742                                              usb_cfg_str_descr[i]) + 1);
 764  743                                  }
 765  744                          }
 766  745                          /* free the array pointers */
 767  746                          kmem_free(usba_device->usb_cfg_str_descr,
 768  747                              sizeof (uchar_t *) * usba_device->usb_n_cfgs);
 769  748                  }
 770  749  
 771  750                  if (usba_device->usb_dev_descr) {
 772  751                          kmem_free(usba_device->usb_dev_descr,
 773  752                              sizeof (usb_dev_descr_t));
 774  753                  }
 775  754  
 776  755                  if (usba_device->usb_mfg_str) {
 777  756                          kmem_free(usba_device->usb_mfg_str,
 778  757                              strlen(usba_device->usb_mfg_str) + 1);
 779  758                  }
 780  759  
  
    | 
      ↓ open down ↓ | 
    107 lines elided | 
    
      ↑ open up ↑ | 
  
 781  760                  if (usba_device->usb_product_str) {
 782  761                          kmem_free(usba_device->usb_product_str,
 783  762                              strlen(usba_device->usb_product_str) + 1);
 784  763                  }
 785  764  
 786  765                  if (usba_device->usb_serialno_str) {
 787  766                          kmem_free(usba_device->usb_serialno_str,
 788  767                              strlen(usba_device->usb_serialno_str) + 1);
 789  768                  }
 790  769  
 791      -                if (usba_device->usb_wireless_data) {
 792      -                        mutex_enter(&usba_device->usb_mutex);
 793      -                        usba_free_wireless_data(
 794      -                            usba_device->usb_wireless_data);
 795      -                        mutex_exit(&usba_device->usb_mutex);
 796      -                }
 797      -
 798      -                /*
 799      -                 * The device address on the wireless bus is assigned
 800      -                 * by the wireless host controller driver(whci or hwahc),
 801      -                 * not by USBA framework, so skip this for wireless
 802      -                 * USB devices.
 803      -                 */
 804      -                if (!usba_device->usb_is_wireless) {
 805      -                        usba_unset_usb_address(usba_device);
 806      -                }
      770 +                usba_unset_usb_address(usba_device);
 807  771          }
 808  772  
 809  773  #ifndef __lock_lint
 810  774          ASSERT(usba_device->usb_client_dev_data_list.cddl_next == NULL);
 811  775  #endif
 812  776  
 813  777          if (usba_device->usb_client_flags) {
 814  778  #ifndef __lock_lint
 815  779                  int i;
 816  780  
 817  781                  for (i = 0; i < usba_device->usb_n_ifs; i++) {
 818  782                          ASSERT(usba_device->usb_client_flags[i] == 0);
 819  783                  }
 820  784  #endif
 821  785                  kmem_free(usba_device->usb_client_flags,
 822  786                      usba_device->usb_n_ifs * USBA_CLIENT_FLAG_SIZE);
 823  787          }
 824  788  
 825  789  
 826  790          if (usba_device->usb_client_attach_list) {
 827  791                  kmem_free(usba_device->usb_client_attach_list,
 828  792                      usba_device->usb_n_ifs *
 829  793                      sizeof (*usba_device->usb_client_attach_list));
 830  794          }
 831  795          if (usba_device->usb_client_ev_cb_list) {
 832  796                  kmem_free(usba_device->usb_client_ev_cb_list,
 833  797                      usba_device->usb_n_ifs *
 834  798                      sizeof (*usba_device->usb_client_ev_cb_list));
 835  799          }
 836  800  
 837  801          /*
 838  802           * finally ready to destroy the structure
 839  803           */
 840  804          mutex_destroy(&usba_device->usb_mutex);
 841  805  
 842  806          kmem_free((caddr_t)usba_device, sizeof (usba_device_t));
 843  807  }
 844  808  
 845  809  
 846  810  /* clear the data toggle for all endpoints on this device */
 847  811  void
 848  812  usba_clear_data_toggle(usba_device_t *usba_device)
 849  813  {
 850  814          int     i;
 851  815  
 852  816          if (usba_device != NULL) {
 853  817                  mutex_enter(&usba_device->usb_mutex);
 854  818                  for (i = 0; i < USBA_N_ENDPOINTS; i++) {
 855  819                          usba_device->usb_ph_list[i].usba_ph_flags &=
 856  820                              ~USBA_PH_DATA_TOGGLE;
 857  821                  }
 858  822                  mutex_exit(&usba_device->usb_mutex);
 859  823          }
 860  824  }
 861  825  
 862  826  
 863  827  /*
 864  828   * usba_create_child_devi():
 865  829   *      create a child devinfo node, usba_device, attach properties.
 866  830   *      the usba_device structure is shared between all interfaces
 867  831   */
 868  832  int
 869  833  usba_create_child_devi(dev_info_t       *dip,
 870  834                  char                    *node_name,
 871  835                  usba_hcdi_ops_t         *usba_hcdi_ops,
 872  836                  dev_info_t              *usb_root_hub_dip,
 873  837                  usb_port_status_t       port_status,
 874  838                  usba_device_t           *usba_device,
 875  839                  dev_info_t              **child_dip)
 876  840  {
 877  841          int rval = USB_FAILURE;
 878  842          int usba_device_allocated = 0;
 879  843          usb_addr_t      address;
 880  844  
 881  845          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
 882  846              "usba_create_child_devi: %s usba_device=0x%p "
 883  847              "port status=0x%x", node_name,
 884  848              (void *)usba_device, port_status);
 885  849  
 886  850          ndi_devi_alloc_sleep(dip, node_name, (pnode_t)DEVI_SID_NODEID,
 887  851              child_dip);
 888  852  
 889  853          USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
 890  854              "child dip=0x%p", (void *)*child_dip);
 891  855  
 892  856          if (usba_device == NULL) {
 893  857  
 894  858                  usba_device = usba_alloc_usba_device(usb_root_hub_dip);
 895  859  
 896  860                  /* grab the mutex to keep warlock happy */
 897  861                  mutex_enter(&usba_device->usb_mutex);
 898  862                  usba_device->usb_hcdi_ops       = usba_hcdi_ops;
 899  863                  usba_device->usb_port_status    = port_status;
 900  864                  mutex_exit(&usba_device->usb_mutex);
 901  865  
 902  866                  usba_device_allocated++;
 903  867          } else {
 904  868                  mutex_enter(&usba_device->usb_mutex);
 905  869                  if (usba_hcdi_ops) {
 906  870                          ASSERT(usba_device->usb_hcdi_ops == usba_hcdi_ops);
 907  871                  }
 908  872                  if (usb_root_hub_dip) {
 909  873                          ASSERT(usba_device->usb_root_hub_dip ==
 910  874                              usb_root_hub_dip);
 911  875                  }
 912  876  
 913  877                  usba_device->usb_port_status    = port_status;
 914  878  
 915  879                  mutex_exit(&usba_device->usb_mutex);
 916  880          }
 917  881  
 918  882          if (usba_device->usb_addr == 0) {
 919  883                  if (usba_set_usb_address(usba_device) == USB_FAILURE) {
 920  884                          address = 0;
 921  885  
 922  886                          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
 923  887                              "cannot set usb address for dip=0x%p",
 924  888                              (void *)*child_dip);
 925  889  
 926  890                          goto fail;
 927  891                  }
 928  892          }
 929  893          address = usba_device->usb_addr;
 930  894  
 931  895          /* attach properties */
 932  896          rval = ndi_prop_update_int(DDI_DEV_T_NONE, *child_dip,
 933  897              "assigned-address", address);
 934  898          if (rval != DDI_PROP_SUCCESS) {
 935  899                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
 936  900                      "cannot set usb address property for dip=0x%p",
 937  901                      (void *)*child_dip);
 938  902                  rval = USB_FAILURE;
 939  903  
 940  904                  goto fail;
 941  905          }
 942  906  
 943  907          /*
 944  908           * store the usba_device point in the dip
 945  909           */
 946  910          usba_set_usba_device(*child_dip, usba_device);
 947  911  
 948  912          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
 949  913              "usba_create_child_devi: devi=0x%p (%s) ud=0x%p",
 950  914              (void *)*child_dip, ddi_driver_name(*child_dip),
 951  915              (void *)usba_device);
 952  916  
 953  917          return (USB_SUCCESS);
 954  918  
 955  919  fail:
 956  920          if (*child_dip) {
 957  921                  int rval = usba_destroy_child_devi(*child_dip, NDI_DEVI_REMOVE);
 958  922                  ASSERT(rval == USB_SUCCESS);
 959  923                  *child_dip = NULL;
 960  924          }
 961  925  
 962  926          if (usba_device_allocated) {
 963  927                  usba_free_usba_device(usba_device);
 964  928          } else if (address && usba_device) {
 965  929                  usba_unset_usb_address(usba_device);
 966  930          }
 967  931  
 968  932          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
 969  933              "usba_create_child_devi failed: rval=%d", rval);
 970  934  
 971  935          return (rval);
 972  936  }
 973  937  
 974  938  
 975  939  int
 976  940  usba_destroy_child_devi(dev_info_t *dip, uint_t flag)
 977  941  {
 978  942          usba_device_t   *usba_device;
 979  943          int             rval = NDI_SUCCESS;
 980  944  
 981  945          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
 982  946              "usba_destroy_child_devi: %s%d (0x%p)",
 983  947              ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip);
 984  948  
 985  949          usba_device = usba_get_usba_device(dip);
 986  950  
 987  951          /*
 988  952           * if the child hasn't been bound yet, we can just
 989  953           * free the dip
 990  954           */
 991  955          if (i_ddi_node_state(dip) < DS_INITIALIZED) {
 992  956                  /*
 993  957                   * do not call ndi_devi_free() since it might
 994  958                   * deadlock
 995  959                   */
 996  960                  rval = ddi_remove_child(dip, 0);
 997  961  
 998  962          } else {
 999  963                  char *devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
1000  964                  dev_info_t *pdip = ddi_get_parent(dip);
1001  965  
1002  966                  (void) ddi_deviname(dip, devnm);
1003  967  
1004  968                  USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
1005  969                      "usba_destroy_child_devi:\n\t"
1006  970                      "offlining dip 0x%p usba_device=0x%p (%s)", (void *)dip,
1007  971                      (void *)usba_device, devnm);
1008  972  
1009  973                  (void) devfs_clean(pdip, NULL, DV_CLEAN_FORCE);
1010  974                  rval =  ndi_devi_unconfig_one(pdip, devnm + 1, NULL,
1011  975                      flag | NDI_UNCONFIG | NDI_DEVI_OFFLINE);
1012  976                  if (rval != NDI_SUCCESS) {
1013  977                          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
1014  978                              " ndi_devi_unconfig_one %s%d failed (%d)",
1015  979                              ddi_driver_name(dip), ddi_get_instance(dip),
1016  980                              rval);
1017  981                  }
1018  982                  kmem_free(devnm, MAXNAMELEN + 1);
1019  983          }
1020  984  
1021  985          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1022  986              "usba_destroy_child_devi: rval=%d", rval);
1023  987  
1024  988          return (rval == NDI_SUCCESS ? USB_SUCCESS : USB_FAILURE);
1025  989  }
1026  990  
1027  991  
1028  992  /*
1029  993   * list management
1030  994   */
1031  995  void
1032  996  usba_init_list(usba_list_entry_t *element, usb_opaque_t private,
1033  997          ddi_iblock_cookie_t     iblock_cookie)
1034  998  {
1035  999          mutex_init(&element->list_mutex, NULL, MUTEX_DRIVER,
1036 1000              iblock_cookie);
1037 1001          mutex_enter(&element->list_mutex);
1038 1002          element->private = private;
1039 1003          mutex_exit(&element->list_mutex);
1040 1004  }
1041 1005  
1042 1006  
1043 1007  void
1044 1008  usba_destroy_list(usba_list_entry_t *head)
1045 1009  {
1046 1010          mutex_enter(&head->list_mutex);
1047 1011          ASSERT(head->next == NULL);
1048 1012          ASSERT(head->prev == NULL);
1049 1013          mutex_exit(&head->list_mutex);
1050 1014  
1051 1015          mutex_destroy(&head->list_mutex);
1052 1016  }
1053 1017  
1054 1018  
1055 1019  void
1056 1020  usba_add_to_list(usba_list_entry_t *head, usba_list_entry_t *element)
1057 1021  {
1058 1022          usba_list_entry_t *next;
1059 1023          int             remaining;
1060 1024  
1061 1025          mutex_enter(&head->list_mutex);
1062 1026          mutex_enter(&element->list_mutex);
1063 1027  
1064 1028          remaining = head->count;
1065 1029  
1066 1030          /* check if it is not in another list */
1067 1031          ASSERT(element->next == NULL);
1068 1032          ASSERT(element->prev == NULL);
1069 1033  
1070 1034  #ifdef DEBUG
1071 1035          /*
1072 1036           * only verify the list when not in interrupt context, we
1073 1037           * have to trust the HCD
1074 1038           */
1075 1039          if (!servicing_interrupt()) {
1076 1040  
1077 1041                  /* check if not already in this list */
1078 1042                  for (next = head->next; (next != NULL);
1079 1043                      next = next->next) {
1080 1044                          if (next == element) {
1081 1045                                  USB_DPRINTF_L0(DPRINT_MASK_USBA,
1082 1046                                      usba_log_handle,
1083 1047                                      "Attempt to corrupt USB list at 0x%p",
1084 1048                                      (void *)head);
1085 1049                                  ASSERT(next == element);
1086 1050  
1087 1051                                  goto done;
1088 1052                          }
1089 1053                          remaining--;
1090 1054  
1091 1055                          /*
1092 1056                           * Detect incorrect circ links or found
1093 1057                           * unexpected elements.
1094 1058                           */
1095 1059                          if ((next->next && (remaining == 0)) ||
1096 1060                              ((next->next == NULL) && remaining)) {
1097 1061                                  panic("Corrupted USB list at 0x%p",
1098 1062                                      (void *)head);
1099 1063                                  /*NOTREACHED*/
1100 1064                          }
1101 1065                  }
1102 1066          }
1103 1067  #endif
1104 1068  
1105 1069          if (head->next == NULL) {
1106 1070                  head->prev = head->next = element;
1107 1071          } else {
1108 1072                  /* add to tail */
1109 1073                  head->prev->next = element;
1110 1074                  element->prev = head->prev;
1111 1075                  head->prev = element;
1112 1076          }
1113 1077  
1114 1078          head->count++;
1115 1079  
1116 1080          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1117 1081              "usba_add_to_list: head=0x%p element=0x%p count=%d",
1118 1082              (void *)head, (void *)element, head->count);
1119 1083  
1120 1084  done:
1121 1085          mutex_exit(&head->list_mutex);
1122 1086          mutex_exit(&element->list_mutex);
1123 1087  }
1124 1088  
1125 1089  
1126 1090  int
1127 1091  usba_rm_from_list(usba_list_entry_t *head, usba_list_entry_t *element)
1128 1092  {
1129 1093          usba_list_entry_t *e;
1130 1094          int             found = 0;
1131 1095          int             remaining;
1132 1096  
1133 1097          /* find the element in the list first */
1134 1098          mutex_enter(&head->list_mutex);
1135 1099  
1136 1100          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1137 1101              "usba_rm_from_list: head=0x%p element=0x%p count=%d",
1138 1102              (void *)head, (void *)element, head->count);
1139 1103  
1140 1104          remaining = head->count;
1141 1105          e = head->next;
1142 1106  
1143 1107          while (e) {
1144 1108                  if (e == element) {
1145 1109                          found++;
1146 1110                          break;
1147 1111                  }
1148 1112                  e = e->next;
1149 1113  
1150 1114                  remaining--;
1151 1115  
1152 1116                  /* Detect incorrect circ links or found unexpected elements. */
1153 1117                  if ((e && (remaining == 0)) ||
1154 1118                      ((e == NULL) && (remaining))) {
1155 1119                          panic("Corrupted USB list at 0x%p", (void *)head);
1156 1120                          /*NOTREACHED*/
1157 1121                  }
1158 1122          }
1159 1123  
1160 1124          if (!found) {
1161 1125                  mutex_exit(&head->list_mutex);
1162 1126  
1163 1127                  return (USB_FAILURE);
1164 1128          }
1165 1129  
1166 1130          /* now remove the element */
1167 1131          mutex_enter(&element->list_mutex);
1168 1132  
1169 1133          if (element->next) {
1170 1134                  element->next->prev = element->prev;
1171 1135          }
1172 1136          if (element->prev) {
1173 1137                  element->prev->next = element->next;
1174 1138          }
1175 1139          if (head->next == element) {
1176 1140                  head->next = element->next;
1177 1141          }
1178 1142          if (head->prev == element) {
1179 1143                  head->prev = element->prev;
1180 1144          }
1181 1145  
1182 1146          element->prev = element->next = NULL;
1183 1147          if (head->next == NULL) {
1184 1148                  ASSERT(head->prev == NULL);
1185 1149          } else {
1186 1150                  ASSERT(head->next->prev == NULL);
1187 1151          }
1188 1152          if (head->prev == NULL) {
1189 1153                  ASSERT(head->next == NULL);
1190 1154          } else {
1191 1155                  ASSERT(head->prev->next == NULL);
1192 1156          }
1193 1157  
1194 1158          head->count--;
1195 1159  
1196 1160          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1197 1161              "usba_rm_from_list success: head=0x%p element=0x%p cnt=%d",
1198 1162              (void *)head, (void *)element, head->count);
1199 1163  
1200 1164          mutex_exit(&element->list_mutex);
1201 1165          mutex_exit(&head->list_mutex);
1202 1166  
1203 1167          return (USB_SUCCESS);
1204 1168  }
1205 1169  
1206 1170  
1207 1171  usba_list_entry_t *
1208 1172  usba_rm_first_from_list(usba_list_entry_t *head)
1209 1173  {
1210 1174          usba_list_entry_t *element = NULL;
1211 1175  
1212 1176          if (head) {
1213 1177                  mutex_enter(&head->list_mutex);
1214 1178                  element = head->next;
1215 1179                  if (element) {
1216 1180                          /* now remove the element */
1217 1181                          mutex_enter(&element->list_mutex);
1218 1182                          head->next = element->next;
1219 1183                          if (head->next) {
1220 1184                                  head->next->prev = NULL;
1221 1185                          }
1222 1186                          if (head->prev == element) {
1223 1187                                  head->prev = element->next;
1224 1188                          }
1225 1189                          element->prev = element->next = NULL;
1226 1190                          mutex_exit(&element->list_mutex);
1227 1191                          head->count--;
1228 1192                  }
1229 1193                  if (head->next == NULL) {
1230 1194                          ASSERT(head->prev == NULL);
1231 1195                  } else {
1232 1196                          ASSERT(head->next->prev == NULL);
1233 1197                  }
1234 1198                  if (head->prev == NULL) {
1235 1199                          ASSERT(head->next == NULL);
1236 1200                  } else {
1237 1201                          ASSERT(head->prev->next == NULL);
1238 1202                  }
1239 1203                  USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1240 1204                      "usba_rm_first_from_list: head=0x%p el=0x%p cnt=%d",
1241 1205                      (void *)head, (void *)element, head->count);
1242 1206  
1243 1207                  mutex_exit(&head->list_mutex);
1244 1208          }
1245 1209  
1246 1210          return (element);
1247 1211  }
1248 1212  
1249 1213  
1250 1214  usb_opaque_t
1251 1215  usba_rm_first_pvt_from_list(usba_list_entry_t *head)
1252 1216  {
1253 1217          usba_list_entry_t *element = usba_rm_first_from_list(head);
1254 1218          usb_opaque_t private = NULL;
1255 1219  
1256 1220          if (element) {
1257 1221                  mutex_enter(&element->list_mutex);
1258 1222                  private = element->private;
1259 1223                  mutex_exit(&element->list_mutex);
1260 1224          }
1261 1225  
1262 1226          return (private);
1263 1227  }
1264 1228  
1265 1229  
1266 1230  /*
1267 1231   * move list to new list and zero original list
1268 1232   */
1269 1233  void
1270 1234  usba_move_list(usba_list_entry_t *head, usba_list_entry_t *new,
1271 1235          ddi_iblock_cookie_t iblock_cookie)
1272 1236  {
1273 1237          usba_init_list(new, NULL, iblock_cookie);
1274 1238          mutex_enter(&head->list_mutex);
1275 1239          mutex_enter(&new->list_mutex);
1276 1240  
1277 1241          new->next = head->next;
1278 1242          new->prev = head->prev;
1279 1243          new->count = head->count;
1280 1244          new->private = head->private;
1281 1245  
1282 1246          head->next = NULL;
1283 1247          head->prev = NULL;
1284 1248          head->count = 0;
1285 1249          head->private = NULL;
1286 1250          mutex_exit(&head->list_mutex);
1287 1251          mutex_exit(&new->list_mutex);
1288 1252  }
1289 1253  
1290 1254  
1291 1255  int
1292 1256  usba_check_in_list(usba_list_entry_t *head, usba_list_entry_t *element)
1293 1257  {
1294 1258          int             rval = USB_FAILURE;
1295 1259          int             remaining;
1296 1260          usba_list_entry_t *next;
1297 1261  
1298 1262          mutex_enter(&head->list_mutex);
1299 1263          remaining = head->count;
1300 1264  
1301 1265          mutex_enter(&element->list_mutex);
1302 1266          for (next = head->next; next != NULL; next = next->next) {
1303 1267                  if (next == element) {
1304 1268                          rval = USB_SUCCESS;
1305 1269                          break;
1306 1270                  }
1307 1271                  remaining--;
1308 1272  
1309 1273                  /* Detect incorrect circ links or found unexpected elements. */
1310 1274                  if ((next->next && (remaining == 0)) ||
1311 1275                      ((next->next == NULL) && remaining)) {
1312 1276                          panic("Corrupted USB list at 0x%p", (void *)head);
1313 1277                          /*NOTREACHED*/
1314 1278                  }
1315 1279          }
1316 1280          mutex_exit(&element->list_mutex);
1317 1281          mutex_exit(&head->list_mutex);
1318 1282  
1319 1283          return (rval);
1320 1284  }
1321 1285  
1322 1286  
1323 1287  int
1324 1288  usba_list_entry_leaks(usba_list_entry_t *head, char *what)
1325 1289  {
1326 1290          int             count = 0;
1327 1291          int             remaining;
1328 1292          usba_list_entry_t *next;
1329 1293  
1330 1294          mutex_enter(&head->list_mutex);
1331 1295          remaining = head->count;
1332 1296          for (next = head->next; next != NULL; next = next->next) {
1333 1297                  USB_DPRINTF_L2(DPRINT_MASK_HCDI, usba_log_handle,
1334 1298                      "leaking %s 0x%p", what, (void *)next->private);
1335 1299                  count++;
1336 1300  
1337 1301                  remaining--;
1338 1302  
1339 1303                  /* Detect incorrect circ links or found unexpected elements. */
1340 1304                  if ((next->next && (remaining == 0)) ||
1341 1305                      ((next->next == NULL) && remaining)) {
1342 1306                          panic("Corrupted USB list at 0x%p", (void *)head);
1343 1307                          /*NOTREACHED*/
1344 1308                  }
1345 1309          }
1346 1310          ASSERT(count == head->count);
1347 1311          mutex_exit(&head->list_mutex);
1348 1312  
1349 1313          if (count) {
1350 1314                  USB_DPRINTF_L2(DPRINT_MASK_HCDI, usba_log_handle,
1351 1315                      "usba_list_entry_count: leaking %d", count);
1352 1316          }
1353 1317  
1354 1318          return (count);
1355 1319  }
1356 1320  
1357 1321  
1358 1322  int
1359 1323  usba_list_entry_count(usba_list_entry_t *head)
1360 1324  {
1361 1325          int count;
1362 1326  
1363 1327          mutex_enter(&head->list_mutex);
1364 1328          count = head->count;
1365 1329          mutex_exit(&head->list_mutex);
1366 1330  
1367 1331          return (count);
1368 1332  }
1369 1333  
1370 1334  /* add a new root hub to the usba_root_hubs list */
1371 1335  
1372 1336  void
1373 1337  usba_add_root_hub(dev_info_t *dip)
1374 1338  {
1375 1339          usba_root_hub_ent_t *hub;
1376 1340  
1377 1341          hub = (usba_root_hub_ent_t *)
1378 1342              kmem_zalloc(sizeof (usba_root_hub_ent_t), KM_SLEEP);
1379 1343  
1380 1344          mutex_enter(&usba_hub_mutex);
1381 1345          hub->dip = dip;
1382 1346          hub->next = usba_root_hubs;
1383 1347          usba_root_hubs = hub;
1384 1348          mutex_exit(&usba_hub_mutex);
1385 1349  }
1386 1350  
1387 1351  /* remove a root hub from the usba_root_hubs list */
1388 1352  
1389 1353  void
1390 1354  usba_rem_root_hub(dev_info_t *dip)
1391 1355  {
1392 1356          usba_root_hub_ent_t **hubp, *hub;
1393 1357  
1394 1358          mutex_enter(&usba_hub_mutex);
1395 1359          hubp = &usba_root_hubs;
1396 1360          while (*hubp) {
1397 1361                  if ((*hubp)->dip == dip) {
1398 1362                          hub = *hubp;
1399 1363                          *hubp = hub->next;
1400 1364                          kmem_free(hub, sizeof (struct usba_root_hub_ent));
1401 1365                          mutex_exit(&usba_hub_mutex);
1402 1366  
1403 1367                          return;
1404 1368                  }
1405 1369                  hubp = &(*hubp)->next;
1406 1370          }
1407 1371          mutex_exit(&usba_hub_mutex);
1408 1372  }
1409 1373  
1410 1374  /*
1411 1375   * check whether this dip is the root hub. Any root hub known by
1412 1376   * usba is recorded in the linked list pointed to by usba_root_hubs
1413 1377   */
1414 1378  int
1415 1379  usba_is_root_hub(dev_info_t *dip)
1416 1380  {
1417 1381          usba_root_hub_ent_t *hub;
1418 1382  
1419 1383          mutex_enter(&usba_hub_mutex);
1420 1384          hub = usba_root_hubs;
1421 1385          while (hub) {
  
    | 
      ↓ open down ↓ | 
    605 lines elided | 
    
      ↑ open up ↑ | 
  
1422 1386                  if (hub->dip == dip) {
1423 1387                          mutex_exit(&usba_hub_mutex);
1424 1388  
1425 1389                          return (1);
1426 1390                  }
1427 1391                  hub = hub->next;
1428 1392          }
1429 1393          mutex_exit(&usba_hub_mutex);
1430 1394  
1431 1395          return (0);
1432      -}
1433      -
1434      -/*
1435      - * check whether this dip is a wire adapter device
1436      - */
1437      -int
1438      -usba_is_wa(dev_info_t *dip)
1439      -{
1440      -        if (dip) {
1441      -                usba_device_t *usba_device;
1442      -
1443      -                usba_device = usba_get_usba_device(dip);
1444      -
1445      -                return (usba_device->usb_is_wa? 1:0);
1446      -        }
1447      -
1448      -        return (0);
1449      -}
1450      -
1451      -/*
1452      - * check whether this dip is a host wire adapter device node
1453      - */
1454      -int
1455      -usba_is_hwa(dev_info_t *dip)
1456      -{
1457      -        dev_info_t      *cdip;
1458      -
1459      -        if (dip == NULL) {
1460      -
1461      -                return (0);
1462      -        }
1463      -
1464      -        if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) {
1465      -
1466      -                return (0);
1467      -        }
1468      -
1469      -        for (cdip = ddi_get_child(dip); cdip;
1470      -            cdip = ddi_get_next_sibling(cdip)) {
1471      -                if (strcmp(ddi_driver_name(cdip), "hwarc") == 0) {
1472      -
1473      -                        return (1);
1474      -                }
1475      -        }
1476      -
1477      -        return (0);
1478 1396  }
1479 1397  
1480 1398  /*
1481 1399   * get and store usba_device pointer in the devi
1482 1400   */
1483 1401  usba_device_t *
1484 1402  usba_get_usba_device(dev_info_t *dip)
1485 1403  {
1486 1404          /*
1487 1405           * we cannot use parent_data in the usb node because its
1488 1406           * bus parent (eg. PCI nexus driver) uses this data
1489 1407           *
1490 1408           * we cannot use driver data in the other usb nodes since
1491 1409           * usb drivers may need to use this
1492 1410           */
1493 1411          if (usba_is_root_hub(dip)) {
1494 1412                  usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(dip);
1495 1413  
1496 1414                  return (hcdi->hcdi_usba_device);
1497 1415          } else {
1498 1416  
1499 1417                  return (ddi_get_parent_data(dip));
1500 1418          }
1501 1419  }
1502 1420  
1503 1421  
1504 1422  /*
1505 1423   * Retrieve the usba_device pointer from the dev without checking for
1506 1424   * the root hub first.  This function is only used in polled mode.
1507 1425   */
1508 1426  usba_device_t *
1509 1427  usba_polled_get_usba_device(dev_info_t *dip)
1510 1428  {
1511 1429          /*
1512 1430           * Don't call usba_is_root_hub() to find out if this is
1513 1431           * the root hub  usba_is_root_hub() calls into the DDI
1514 1432           * where there are locking issues. The dip sent in during
1515 1433           * polled mode will never be the root hub, so just get
1516 1434           * the usba_device pointer from the dip.
1517 1435           */
1518 1436          return (ddi_get_parent_data(dip));
1519 1437  }
1520 1438  
1521 1439  
1522 1440  void
1523 1441  usba_set_usba_device(dev_info_t *dip, usba_device_t *usba_device)
1524 1442  {
1525 1443          if (usba_is_root_hub(dip)) {
1526 1444                  usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(dip);
1527 1445                  /* no locking is needed here */
1528 1446                  _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(hcdi->hcdi_usba_device))
1529 1447                  hcdi->hcdi_usba_device = usba_device;
1530 1448                  _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(hcdi->hcdi_usba_device))
1531 1449          } else {
1532 1450                  ddi_set_parent_data(dip, usba_device);
1533 1451          }
1534 1452  }
1535 1453  
1536 1454  
1537 1455  /*
1538 1456   * usba_set_node_name() according to class, subclass, and protocol
1539 1457   * following the 1275 USB binding tables.
1540 1458   */
1541 1459  
1542 1460  /* device node table, refer to section 3.2.2.1 of 1275 binding */
1543 1461  static node_name_entry_t device_node_name_table[] = {
1544 1462  { USB_CLASS_COMM,       DONTCARE,       DONTCARE,       "communications" },
1545 1463  { USB_CLASS_HUB,        DONTCARE,       DONTCARE,       "hub" },
1546 1464  { USB_CLASS_DIAG,       DONTCARE,       DONTCARE,       "diagnostics" },
1547 1465  { USB_CLASS_MISC,       DONTCARE,       DONTCARE,       "miscellaneous" },
1548 1466  { DONTCARE,             DONTCARE,       DONTCARE,       "device" }
1549 1467  };
1550 1468  
1551 1469  /* interface-association node table */
1552 1470  static node_name_entry_t ia_node_name_table[] = {
1553 1471  { USB_CLASS_AUDIO,      DONTCARE,       DONTCARE, "audio" },
1554 1472  { USB_CLASS_VIDEO,      DONTCARE,       DONTCARE, "video" },
1555 1473  { USB_CLASS_WIRELESS,   USB_SUBCLS_WUSB_2, USB_PROTO_WUSB_DWA,
1556 1474                                                  "device-wire-adaptor" },
1557 1475  { USB_CLASS_WIRELESS,   DONTCARE,       DONTCARE, "wireless-controller" },
1558 1476  { DONTCARE,             DONTCARE,       DONTCARE, "interface-association" }
1559 1477  };
1560 1478  
1561 1479  /* interface node table, refer to section 3.3.2.1 */
1562 1480  static node_name_entry_t if_node_name_table[] = {
1563 1481  { USB_CLASS_AUDIO, USB_SUBCLS_AUD_CONTROL, DONTCARE,    "sound-control" },
1564 1482  { USB_CLASS_AUDIO, USB_SUBCLS_AUD_STREAMING, DONTCARE, "sound" },
1565 1483  { USB_CLASS_AUDIO, USB_SUBCLS_AUD_MIDI_STREAMING, DONTCARE, "midi" },
1566 1484  { USB_CLASS_AUDIO, DONTCARE,            DONTCARE,       "sound" },
1567 1485  
1568 1486  { USB_CLASS_COMM, USB_SUBCLS_CDCC_DIRECT_LINE,  DONTCARE, "line" },
1569 1487  { USB_CLASS_COMM, USB_SUBCLS_CDCC_ABSTRCT_CTRL, DONTCARE, "modem" },
1570 1488  { USB_CLASS_COMM, USB_SUBCLS_CDCC_PHONE_CTRL, DONTCARE, "telephone" },
1571 1489  { USB_CLASS_COMM, USB_SUBCLS_CDCC_MULTCNL_ISDN, DONTCARE, "isdn" },
1572 1490  { USB_CLASS_COMM, USB_SUBCLS_CDCC_ISDN,         DONTCARE, "isdn" },
1573 1491  { USB_CLASS_COMM, USB_SUBCLS_CDCC_ETHERNET,     DONTCARE, "ethernet" },
1574 1492  { USB_CLASS_COMM, USB_SUBCLS_CDCC_ATM_NETWORK, DONTCARE, "atm-network" },
1575 1493  { USB_CLASS_COMM, DONTCARE,             DONTCARE,       "communications" },
1576 1494  
1577 1495  { USB_CLASS_HID, USB_SUBCLS_HID_1, USB_PROTO_HID_KEYBOARD,      "keyboard" },
1578 1496  { USB_CLASS_HID, USB_SUBCLS_HID_1, USB_PROTO_HID_MOUSE, "mouse" },
1579 1497  { USB_CLASS_HID,        DONTCARE,       DONTCARE,       "input" },
1580 1498  
1581 1499  { USB_CLASS_HUB,        DONTCARE,       DONTCARE,       "hub" },
1582 1500  
1583 1501  { USB_CLASS_PHYSICAL,   DONTCARE,       DONTCARE,       "physical" },
1584 1502  
1585 1503  { USB_CLASS_IMAGE,      DONTCARE,       DONTCARE,       "image" },
1586 1504  
1587 1505  { USB_CLASS_PRINTER,    DONTCARE,       DONTCARE,       "printer" },
1588 1506  
1589 1507  { USB_CLASS_MASS_STORAGE, DONTCARE,     DONTCARE,       "storage" },
1590 1508  
1591 1509  { USB_CLASS_CDC_DATA,   DONTCARE,       DONTCARE,       "data" },
1592 1510  
1593 1511  { USB_CLASS_SECURITY,   DONTCARE,       DONTCARE,       "security" },
1594 1512  
1595 1513  { USB_CLASS_VIDEO, USB_SUBCLS_VIDEO_CONTROL, DONTCARE,  "video-control" },
1596 1514  { USB_CLASS_VIDEO, USB_SUBCLS_VIDEO_STREAM,  DONTCARE,  "video-stream" },
1597 1515  { USB_CLASS_VIDEO,      DONTCARE,       DONTCARE,       "video" },
1598 1516  
1599 1517  { USB_CLASS_APP,        USB_SUBCLS_APP_FIRMWARE, DONTCARE, "firmware" },
1600 1518  { USB_CLASS_APP,        USB_SUBCLS_APP_IRDA,    DONTCARE, "IrDa" },
1601 1519  { USB_CLASS_APP,        USB_SUBCLS_APP_TEST,    DONTCARE, "test" },
1602 1520  
1603 1521  { USB_CLASS_MISC,       USB_SUBCLS_CBAF, USB_PROTO_CBAF,  "wusb_ca"},
1604 1522  { USB_CLASS_WIRELESS, USB_SUBCLS_WUSB_1, USB_PROTO_WUSB_RC, "hwa-radio" },
1605 1523  { USB_CLASS_WIRELESS, USB_SUBCLS_WUSB_2, USB_PROTO_WUSB_HWA, "hwa-host" },
1606 1524  { USB_CLASS_WIRELESS, USB_SUBCLS_WUSB_2, USB_PROTO_WUSB_DWA, "dwa-control" },
1607 1525  { USB_CLASS_WIRELESS, USB_SUBCLS_WUSB_2, USB_PROTO_WUSB_DWA_ISO, "dwa-isoc" },
1608 1526  { USB_CLASS_WIRELESS, DONTCARE, DONTCARE, "wireless" },
1609 1527  
1610 1528  { DONTCARE,             DONTCARE,       DONTCARE,       "interface" },
1611 1529  
1612 1530  };
1613 1531  
1614 1532  /* combined node table, refer to section 3.4.2.1 */
1615 1533  static node_name_entry_t combined_node_name_table[] = {
1616 1534  { USB_CLASS_AUDIO, USB_SUBCLS_AUD_CONTROL, DONTCARE,    "sound-control" },
1617 1535  { USB_CLASS_AUDIO, USB_SUBCLS_AUD_STREAMING, DONTCARE, "sound" },
1618 1536  { USB_CLASS_AUDIO, USB_SUBCLS_AUD_MIDI_STREAMING, DONTCARE, "midi" },
1619 1537  { USB_CLASS_AUDIO, DONTCARE,            DONTCARE,       "sound" },
1620 1538  
1621 1539  { USB_CLASS_COMM, USB_SUBCLS_CDCC_DIRECT_LINE,  DONTCARE, "line" },
1622 1540  { USB_CLASS_COMM, USB_SUBCLS_CDCC_ABSTRCT_CTRL, DONTCARE, "modem" },
1623 1541  { USB_CLASS_COMM, USB_SUBCLS_CDCC_PHONE_CTRL, DONTCARE, "telephone" },
1624 1542  { USB_CLASS_COMM, USB_SUBCLS_CDCC_MULTCNL_ISDN, DONTCARE, "isdn" },
1625 1543  { USB_CLASS_COMM, USB_SUBCLS_CDCC_ISDN,         DONTCARE, "isdn" },
1626 1544  { USB_CLASS_COMM, USB_SUBCLS_CDCC_ETHERNET,     DONTCARE, "ethernet" },
1627 1545  { USB_CLASS_COMM, USB_SUBCLS_CDCC_ATM_NETWORK, DONTCARE, "atm-network" },
1628 1546  { USB_CLASS_COMM, DONTCARE,             DONTCARE,       "communications" },
1629 1547  
1630 1548  { USB_CLASS_HID, USB_SUBCLS_HID_1, USB_PROTO_HID_KEYBOARD, "keyboard" },
1631 1549  { USB_CLASS_HID, USB_SUBCLS_HID_1, USB_PROTO_HID_MOUSE, "mouse" },
1632 1550  { USB_CLASS_HID,        DONTCARE,       DONTCARE,       "input" },
1633 1551  
1634 1552  { USB_CLASS_PHYSICAL,   DONTCARE,       DONTCARE,       "physical" },
1635 1553  
1636 1554  { USB_CLASS_IMAGE,      DONTCARE,       DONTCARE,       "image" },
1637 1555  
1638 1556  { USB_CLASS_PRINTER,    DONTCARE,       DONTCARE,       "printer" },
1639 1557  
1640 1558  { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_RBC_T10,        DONTCARE, "storage" },
1641 1559  { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_SFF8020I,       DONTCARE, "cdrom" },
1642 1560  { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_QIC_157,        DONTCARE, "tape" },
1643 1561  { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_UFI,            DONTCARE, "floppy" },
1644 1562  { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_SFF8070I,       DONTCARE, "storage" },
1645 1563  { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_SCSI,           DONTCARE, "storage" },
1646 1564  { USB_CLASS_MASS_STORAGE, DONTCARE,     DONTCARE,       "storage" },
1647 1565  
1648 1566  { USB_CLASS_CDC_DATA,   DONTCARE,       DONTCARE,       "data" },
1649 1567  
1650 1568  { USB_CLASS_SECURITY,   DONTCARE,       DONTCARE,       "security" },
1651 1569  
1652 1570  { USB_CLASS_VIDEO, USB_SUBCLS_VIDEO_CONTROL, DONTCARE,  "video-control" },
1653 1571  { USB_CLASS_VIDEO, USB_SUBCLS_VIDEO_STREAM,  DONTCARE,  "video-stream" },
1654 1572  { USB_CLASS_VIDEO,      DONTCARE,       DONTCARE,       "video" },
1655 1573  
1656 1574  { USB_CLASS_APP,        USB_SUBCLS_APP_FIRMWARE, DONTCARE, "firmware" },
1657 1575  { USB_CLASS_APP,        USB_SUBCLS_APP_IRDA,    DONTCARE, "IrDa" },
1658 1576  { USB_CLASS_APP,        USB_SUBCLS_APP_TEST,    DONTCARE, "test" },
1659 1577  
1660 1578  { USB_CLASS_COMM,       DONTCARE,       DONTCARE,       "communications" },
1661 1579  { USB_CLASS_HUB,        DONTCARE,       DONTCARE,       "hub" },
1662 1580  { USB_CLASS_DIAG,       DONTCARE,       DONTCARE,       "diagnostics" },
1663 1581  { USB_CLASS_MISC,       DONTCARE,       DONTCARE,       "miscellaneous" },
1664 1582  { DONTCARE,             DONTCARE,       DONTCARE,       "device" }
1665 1583  };
1666 1584  
1667 1585  static size_t device_node_name_table_size =
1668 1586          sizeof (device_node_name_table)/sizeof (struct node_name_entry);
1669 1587  static size_t ia_node_name_table_size =
1670 1588          sizeof (ia_node_name_table)/sizeof (struct node_name_entry);
1671 1589  static size_t if_node_name_table_size =
1672 1590          sizeof (if_node_name_table)/sizeof (struct node_name_entry);
1673 1591  static size_t combined_node_name_table_size =
1674 1592          sizeof (combined_node_name_table)/sizeof (struct node_name_entry);
1675 1593  
1676 1594  
1677 1595  static void
1678 1596  usba_set_node_name(dev_info_t *dip, uint8_t class, uint8_t subclass,
1679 1597      uint8_t protocol, uint_t flag)
1680 1598  {
1681 1599          int i;
1682 1600          size_t size;
1683 1601          node_name_entry_t *node_name_table;
1684 1602  
1685 1603          switch (flag) {
1686 1604          /* interface share node names with interface-association */
1687 1605          case FLAG_INTERFACE_ASSOCIATION_NODE:
1688 1606                  node_name_table = ia_node_name_table;
1689 1607                  size = ia_node_name_table_size;
1690 1608                  break;
1691 1609          case FLAG_INTERFACE_NODE:
1692 1610                  node_name_table = if_node_name_table;
1693 1611                  size = if_node_name_table_size;
1694 1612                  break;
1695 1613          case FLAG_DEVICE_NODE:
1696 1614                  node_name_table = device_node_name_table;
1697 1615                  size = device_node_name_table_size;
1698 1616                  break;
1699 1617          case FLAG_COMBINED_NODE:
1700 1618                  node_name_table = combined_node_name_table;
1701 1619                  size = combined_node_name_table_size;
1702 1620                  break;
1703 1621          default:
1704 1622  
1705 1623                  return;
1706 1624          }
1707 1625  
1708 1626          for (i = 0; i < size; i++) {
1709 1627                  int16_t c = node_name_table[i].class;
1710 1628                  int16_t s = node_name_table[i].subclass;
1711 1629                  int16_t p = node_name_table[i].protocol;
1712 1630  
1713 1631                  if (((c == DONTCARE) || (c == class)) &&
1714 1632                      ((s == DONTCARE) || (s == subclass)) &&
1715 1633                      ((p == DONTCARE) || (p == protocol))) {
1716 1634                          char *name = node_name_table[i].name;
1717 1635  
1718 1636                          (void) ndi_devi_set_nodename(dip, name, 0);
1719 1637                          break;
1720 1638                  }
1721 1639          }
1722 1640  }
1723 1641  
1724 1642  
1725 1643  #ifdef DEBUG
1726 1644  /*
1727 1645   * walk the children of the parent of this devi and compare the
1728 1646   * name and  reg property of each child. If there is a match
1729 1647   * return this node
1730 1648   */
1731 1649  static dev_info_t *
1732 1650  usba_find_existing_node(dev_info_t *odip)
1733 1651  {
1734 1652          dev_info_t *ndip, *child, *pdip;
1735 1653          int     *odata, *ndata;
1736 1654          uint_t  n_odata, n_ndata;
1737 1655          int     circular;
1738 1656  
1739 1657          pdip = ddi_get_parent(odip);
1740 1658          if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
1741 1659              odip, DDI_PROP_DONTPASS, "reg",
1742 1660              &odata, &n_odata) != DDI_SUCCESS) {
1743 1661                  USB_DPRINTF_L2(DPRINT_MASK_HCDI, usba_log_handle,
1744 1662                      "usba_find_existing_node: "
1745 1663                      "%s: DDI_NOT_WELL_FORMED", ddi_driver_name(odip));
1746 1664  
1747 1665                  return (NULL);
1748 1666          }
1749 1667  
1750 1668          ndi_devi_enter(pdip, &circular);
1751 1669          ndip = (dev_info_t *)(DEVI(pdip)->devi_child);
1752 1670          while ((child = ndip) != NULL) {
1753 1671  
1754 1672                  ndip = (dev_info_t *)(DEVI(child)->devi_sibling);
1755 1673  
1756 1674                  if (child == odip) {
1757 1675                          continue;
1758 1676                  }
1759 1677  
1760 1678                  if (strcmp(DEVI(child)->devi_node_name,
1761 1679                      DEVI(odip)->devi_node_name)) {
1762 1680                          continue;
1763 1681                  }
1764 1682  
1765 1683                  if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
1766 1684                      child, DDI_PROP_DONTPASS, "reg",
1767 1685                      &ndata, &n_ndata) != DDI_SUCCESS) {
1768 1686  
1769 1687                          USB_DPRINTF_L2(DPRINT_MASK_HCDI, usba_log_handle,
1770 1688                              "usba_find_existing_node: "
1771 1689                              "%s DDI_NOT_WELL_FORMED", ddi_driver_name(child));
1772 1690  
1773 1691                  } else if (n_ndata && n_odata && (bcmp(odata, ndata,
1774 1692                      max(n_odata, n_ndata) * sizeof (int)) == 0)) {
1775 1693  
1776 1694                          USB_DPRINTF_L3(DPRINT_MASK_HCDI, usba_log_handle,
1777 1695                              "usba_find_existing_node: found %s%d (%p)",
1778 1696                              ddi_driver_name(child),
1779 1697                              ddi_get_instance(child), (void *)child);
1780 1698  
1781 1699                          USB_DPRINTF_L3(DPRINT_MASK_HCDI, usba_log_handle,
1782 1700                              "usba_find_existing_node: "
1783 1701                              "reg: %x %x %x - %x %x %x",
1784 1702                              n_odata, odata[0], odata[1],
1785 1703                              n_ndata, ndata[0], ndata[1]);
1786 1704  
1787 1705                          ddi_prop_free(ndata);
1788 1706                          break;
1789 1707  
1790 1708                  } else {
1791 1709                          ddi_prop_free(ndata);
1792 1710                  }
1793 1711          }
1794 1712  
1795 1713          ndi_devi_exit(pdip, circular);
1796 1714  
1797 1715          ddi_prop_free(odata);
1798 1716  
1799 1717          return (child);
1800 1718  }
1801 1719  #endif
1802 1720  
1803 1721  /* change all unprintable characters to spaces */
1804 1722  static void
1805 1723  usba_filter_string(char *instr, char *outstr)
1806 1724  {
1807 1725          while (*instr) {
1808 1726                  if ((*instr >= ' ') && (*instr <= '~')) {
1809 1727                          *outstr = *instr;
1810 1728                  } else {
1811 1729                          *outstr = ' ';
1812 1730                  }
1813 1731                  outstr++;
1814 1732                  instr++;
1815 1733          }
1816 1734          *outstr = '\0';
1817 1735  }
1818 1736  
1819 1737  
1820 1738  /*
1821 1739   * lookup ugen binding specified in property in
1822 1740   * hcd.conf files
1823 1741   */
1824 1742  int
1825 1743  usba_get_ugen_binding(dev_info_t *dip)
1826 1744  {
1827 1745          usba_device_t   *usba_device = usba_get_usba_device(dip);
1828 1746          usba_hcdi_t     *hcdi =
1829 1747              usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
1830 1748  
1831 1749          return (hcdi->hcdi_ugen_default_binding);
1832 1750  }
1833 1751  
1834 1752  
1835 1753  /*
1836 1754   * driver binding support at device level
1837 1755   */
1838 1756  dev_info_t *
1839 1757  usba_ready_device_node(dev_info_t *child_dip)
1840 1758  {
1841 1759          int             rval, i;
1842 1760          int             n = 0;
1843 1761          usba_device_t   *usba_device = usba_get_usba_device(child_dip);
1844 1762          usb_dev_descr_t *usb_dev_descr;
1845 1763          uint_t          n_cfgs; /* number of configs */
1846 1764          uint_t          n_ifs;  /* number of interfaces */
1847 1765          uint_t          port, bus_num;
1848 1766          size_t          usb_config_length;
1849 1767          uchar_t         *usb_config;
1850 1768          int             reg[1];
1851 1769          usb_addr_t      address = usb_get_addr(child_dip);
1852 1770          usb_if_descr_t  if_descr;
1853 1771          size_t          size;
1854 1772          int             combined_node = 0;
1855 1773          int             is_hub;
1856 1774          char            *devprop_str;
1857 1775          char            *force_bind = NULL;
1858 1776          char            *usba_name_buf = NULL;
1859 1777          char            *usba_name[USBA_MAX_COMPAT_NAMES];
1860 1778  
1861 1779          usb_config = usb_get_raw_cfg_data(child_dip, &usb_config_length);
1862 1780  
1863 1781          mutex_enter(&usba_device->usb_mutex);
1864 1782          mutex_enter(&usba_mutex);
1865 1783  
1866 1784          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1867 1785              "usba_ready_device_node: child=0x%p", (void *)child_dip);
1868 1786  
1869 1787          port = usba_device->usb_port;
1870 1788          usb_dev_descr = usba_device->usb_dev_descr;
1871 1789          n_cfgs = usba_device->usb_n_cfgs;
1872 1790          n_ifs = usba_device->usb_n_ifs;
1873 1791          bus_num = usba_device->usb_addr;
1874 1792  
1875 1793          if (address != ROOT_HUB_ADDR) {
1876 1794                  size = usb_parse_if_descr(
1877 1795                      usb_config,
1878 1796                      usb_config_length,
1879 1797                      0,          /* interface index */
1880 1798                      0,          /* alt interface index */
1881 1799                      &if_descr,
1882 1800                      USB_IF_DESCR_SIZE);
1883 1801  
1884 1802                  if (size != USB_IF_DESCR_SIZE) {
1885 1803                          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
1886 1804                              "parsing interface: "
1887 1805                              "size (%lu) != USB_IF_DESCR_SIZE (%d)",
1888 1806                              size, USB_IF_DESCR_SIZE);
1889 1807  
1890 1808                          mutex_exit(&usba_mutex);
1891 1809                          mutex_exit(&usba_device->usb_mutex);
1892 1810  
1893 1811                          return (child_dip);
1894 1812                  }
1895 1813          } else {
1896 1814                  /* fake an interface descriptor for the root hub */
1897 1815                  bzero(&if_descr, sizeof (if_descr));
1898 1816  
1899 1817                  if_descr.bInterfaceClass = USB_CLASS_HUB;
1900 1818          }
1901 1819  
1902 1820          reg[0] = port;
1903 1821  
1904 1822          mutex_exit(&usba_mutex);
1905 1823          mutex_exit(&usba_device->usb_mutex);
1906 1824  
1907 1825          rval = ndi_prop_update_int_array(
1908 1826              DDI_DEV_T_NONE, child_dip, "reg", reg, 1);
1909 1827  
1910 1828          if (rval != DDI_PROP_SUCCESS) {
1911 1829                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
1912 1830                      "usba_ready_device_node: property update failed");
1913 1831  
1914 1832                  return (child_dip);
1915 1833          }
1916 1834  
1917 1835          combined_node = ((n_cfgs == 1) && (n_ifs == 1) &&
1918 1836              ((usb_dev_descr->bDeviceClass == USB_CLASS_HUB) ||
1919 1837              (usb_dev_descr->bDeviceClass == 0)));
1920 1838  
1921 1839          is_hub = (if_descr.bInterfaceClass == USB_CLASS_HUB) ||
1922 1840              (usb_dev_descr->bDeviceClass == USB_CLASS_HUB);
1923 1841  
1924 1842          /* set node name */
1925 1843          if (combined_node) {
1926 1844                  usba_set_node_name(child_dip,
1927 1845                      if_descr.bInterfaceClass,
1928 1846                      if_descr.bInterfaceSubClass,
1929 1847                      if_descr.bInterfaceProtocol,
1930 1848                      FLAG_COMBINED_NODE);
1931 1849          } else {
1932 1850                  usba_set_node_name(child_dip,
1933 1851                      usb_dev_descr->bDeviceClass,
1934 1852                      usb_dev_descr->bDeviceSubClass,
1935 1853                      usb_dev_descr->bDeviceProtocol,
1936 1854                      FLAG_DEVICE_NODE);
1937 1855          }
1938 1856  
1939 1857          /*
1940 1858           * check force binding rules
1941 1859           */
1942 1860          if ((address != ROOT_HUB_ADDR) && usba_ddivs_usbc &&
1943 1861              (address != usba_ddivs_usbc_xaddress) &&
1944 1862              (!(usba_ddivs_usbc_xhubs && is_hub))) {
1945 1863                  force_bind = "ddivs_usbc";
1946 1864                  (void) ndi_devi_set_nodename(child_dip, "ddivs_usbc", 0);
1947 1865  
1948 1866          } else if (usba_device->usb_preferred_driver) {
1949 1867                  force_bind = usba_device->usb_preferred_driver;
1950 1868  
1951 1869          } else if ((address != ROOT_HUB_ADDR) &&
1952 1870              ((usba_ugen_force_binding == USBA_UGEN_DEVICE_BINDING) ||
1953 1871              ((usba_ugen_force_binding == USBA_UGEN_INTERFACE_BINDING) &&
1954 1872              combined_node)) && (!is_hub)) {
1955 1873                  force_bind = "ugen";
1956 1874          }
1957 1875  
1958 1876  #ifdef DEBUG
1959 1877          /*
1960 1878           * check whether there is another dip with this name and address
1961 1879           * If the dip contains usba_device, it is held by the previous
1962 1880           * round of configuration.
1963 1881           */
1964 1882          ASSERT(usba_find_existing_node(child_dip) == NULL);
1965 1883  #endif
1966 1884  
1967 1885          usba_name_buf = kmem_zalloc(USBA_MAX_COMPAT_NAMES *
1968 1886              USBA_MAX_COMPAT_NAME_LEN, KM_SLEEP);
1969 1887  
1970 1888          for (i = 0; i < USBA_MAX_COMPAT_NAMES; i++) {
1971 1889                  usba_name[i] = usba_name_buf + (i * USBA_MAX_COMPAT_NAME_LEN);
1972 1890          }
1973 1891  
1974 1892          if (force_bind) {
1975 1893                  (void) ndi_devi_set_nodename(child_dip, force_bind, 0);
1976 1894                  (void) strncpy(usba_name[n++], force_bind,
1977 1895                      USBA_MAX_COMPAT_NAME_LEN);
1978 1896          }
1979 1897  
1980 1898          /*
1981 1899           * If the callback function of specified driver is registered,
1982 1900           * it will be called here to check whether to take over the device.
1983 1901           */
1984 1902          if (usb_cap.usba_dev_driver_cb != NULL) {
1985 1903                  char            *dev_drv = NULL;
1986 1904                  usb_dev_str_t   dev_str;
1987 1905                  char            *pathname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1988 1906  
1989 1907                  dev_str.usb_mfg = usba_device->usb_mfg_str;
1990 1908                  dev_str.usb_product = usba_device->usb_product_str;
1991 1909                  dev_str.usb_serialno = usba_device->usb_serialno_str;
1992 1910  
1993 1911                  (void) ddi_pathname(child_dip, pathname);
1994 1912  
1995 1913                  if ((usb_cap.usba_dev_driver_cb(usb_dev_descr, &dev_str,
1996 1914                      pathname, bus_num, port, &dev_drv, NULL) == USB_SUCCESS) &&
1997 1915                      (dev_drv != NULL)) {
1998 1916                          USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
1999 1917                              "usba_ready_device_node: dev_driver=%s, port =%d,"
2000 1918                              "bus =%d, path=%s\n\t",
2001 1919                              dev_drv, port, bus_num, pathname);
2002 1920  
2003 1921                          (void) strncpy(usba_name[n++], dev_drv,
2004 1922                              USBA_MAX_COMPAT_NAME_LEN);
2005 1923                  }
2006 1924                  kmem_free(pathname, MAXPATHLEN);
2007 1925          }
2008 1926  
2009 1927          /* create compatible names */
2010 1928          if (combined_node) {
2011 1929  
2012 1930                  /* 1. usbVID,PID.REV */
2013 1931                  (void) sprintf(usba_name[n++],
2014 1932                      "usb%x,%x.%x",
2015 1933                      usb_dev_descr->idVendor,
2016 1934                      usb_dev_descr->idProduct,
2017 1935                      usb_dev_descr->bcdDevice);
2018 1936  
2019 1937                  /* 2. usbVID,PID */
2020 1938                  (void) sprintf(usba_name[n++],
2021 1939                      "usb%x,%x",
2022 1940                      usb_dev_descr->idVendor,
2023 1941                      usb_dev_descr->idProduct);
2024 1942  
2025 1943                  if (usb_dev_descr->bDeviceClass != 0) {
2026 1944                          /* 3. usbVID,classDC.DSC.DPROTO */
2027 1945                          (void) sprintf(usba_name[n++],
2028 1946                              "usb%x,class%x.%x.%x",
2029 1947                              usb_dev_descr->idVendor,
2030 1948                              usb_dev_descr->bDeviceClass,
2031 1949                              usb_dev_descr->bDeviceSubClass,
2032 1950                              usb_dev_descr->bDeviceProtocol);
2033 1951  
2034 1952                          /* 4. usbVID,classDC.DSC */
2035 1953                          (void) sprintf(usba_name[n++],
2036 1954                              "usb%x,class%x.%x",
2037 1955                              usb_dev_descr->idVendor,
2038 1956                              usb_dev_descr->bDeviceClass,
2039 1957                              usb_dev_descr->bDeviceSubClass);
2040 1958  
2041 1959                          /* 5. usbVID,classDC */
2042 1960                          (void) sprintf(usba_name[n++],
2043 1961                              "usb%x,class%x",
2044 1962                              usb_dev_descr->idVendor,
2045 1963                              usb_dev_descr->bDeviceClass);
2046 1964  
2047 1965                          /* 6. usb,classDC.DSC.DPROTO */
2048 1966                          (void) sprintf(usba_name[n++],
2049 1967                              "usb,class%x.%x.%x",
2050 1968                              usb_dev_descr->bDeviceClass,
2051 1969                              usb_dev_descr->bDeviceSubClass,
2052 1970                              usb_dev_descr->bDeviceProtocol);
2053 1971  
2054 1972                          /* 7. usb,classDC.DSC */
2055 1973                          (void) sprintf(usba_name[n++],
2056 1974                              "usb,class%x.%x",
2057 1975                              usb_dev_descr->bDeviceClass,
2058 1976                              usb_dev_descr->bDeviceSubClass);
2059 1977  
2060 1978                          /* 8. usb,classDC */
2061 1979                          (void) sprintf(usba_name[n++],
2062 1980                              "usb,class%x",
2063 1981                              usb_dev_descr->bDeviceClass);
2064 1982                  }
2065 1983  
2066 1984                  if (if_descr.bInterfaceClass != 0) {
2067 1985                          /* 9. usbifVID,classIC.ISC.IPROTO */
2068 1986                          (void) sprintf(usba_name[n++],
2069 1987                              "usbif%x,class%x.%x.%x",
2070 1988                              usb_dev_descr->idVendor,
2071 1989                              if_descr.bInterfaceClass,
2072 1990                              if_descr.bInterfaceSubClass,
2073 1991                              if_descr.bInterfaceProtocol);
2074 1992  
2075 1993                          /* 10. usbifVID,classIC.ISC */
2076 1994                          (void) sprintf(usba_name[n++],
2077 1995                              "usbif%x,class%x.%x",
2078 1996                              usb_dev_descr->idVendor,
2079 1997                              if_descr.bInterfaceClass,
2080 1998                              if_descr.bInterfaceSubClass);
2081 1999  
2082 2000                          /* 11. usbifVID,classIC */
2083 2001                          (void) sprintf(usba_name[n++],
2084 2002                              "usbif%x,class%x",
2085 2003                              usb_dev_descr->idVendor,
2086 2004                              if_descr.bInterfaceClass);
2087 2005  
2088 2006                          /* 12. usbif,classIC.ISC.IPROTO */
2089 2007                          (void) sprintf(usba_name[n++],
2090 2008                              "usbif,class%x.%x.%x",
2091 2009                              if_descr.bInterfaceClass,
2092 2010                              if_descr.bInterfaceSubClass,
2093 2011                              if_descr.bInterfaceProtocol);
2094 2012  
2095 2013                          /* 13. usbif,classIC.ISC */
2096 2014                          (void) sprintf(usba_name[n++],
2097 2015                              "usbif,class%x.%x",
2098 2016                              if_descr.bInterfaceClass,
2099 2017                              if_descr.bInterfaceSubClass);
2100 2018  
2101 2019                          /* 14. usbif,classIC */
2102 2020                          (void) sprintf(usba_name[n++],
2103 2021                              "usbif,class%x",
2104 2022                              if_descr.bInterfaceClass);
2105 2023                  }
2106 2024  
2107 2025                  /* 15. ugen or usb_mid */
2108 2026                  if (usba_get_ugen_binding(child_dip) ==
2109 2027                      USBA_UGEN_DEVICE_BINDING) {
2110 2028                          (void) sprintf(usba_name[n++], "ugen");
2111 2029                  } else {
2112 2030                          (void) sprintf(usba_name[n++], "usb,device");
2113 2031                  }
2114 2032  
2115 2033          } else {
2116 2034                  if (n_cfgs > 1) {
2117 2035                          /* 1. usbVID,PID.REV.configCN */
2118 2036                          (void) sprintf(usba_name[n++],
2119 2037                              "usb%x,%x.%x.config%x",
2120 2038                              usb_dev_descr->idVendor,
2121 2039                              usb_dev_descr->idProduct,
2122 2040                              usb_dev_descr->bcdDevice,
2123 2041                              usba_device->usb_cfg_value);
2124 2042                  }
2125 2043  
2126 2044                  /* 2. usbVID,PID.REV */
2127 2045                  (void) sprintf(usba_name[n++],
2128 2046                      "usb%x,%x.%x",
2129 2047                      usb_dev_descr->idVendor,
2130 2048                      usb_dev_descr->idProduct,
2131 2049                      usb_dev_descr->bcdDevice);
2132 2050  
2133 2051                  /* 3. usbVID,PID.configCN */
2134 2052                  if (n_cfgs > 1) {
2135 2053                          (void) sprintf(usba_name[n++],
2136 2054                              "usb%x,%x.%x",
2137 2055                              usb_dev_descr->idVendor,
2138 2056                              usb_dev_descr->idProduct,
2139 2057                              usba_device->usb_cfg_value);
2140 2058                  }
2141 2059  
2142 2060                  /* 4. usbVID,PID */
2143 2061                  (void) sprintf(usba_name[n++],
2144 2062                      "usb%x,%x",
2145 2063                      usb_dev_descr->idVendor,
2146 2064                      usb_dev_descr->idProduct);
2147 2065  
2148 2066                  if (usb_dev_descr->bDeviceClass != 0) {
2149 2067                          /* 5. usbVID,classDC.DSC.DPROTO */
2150 2068                          (void) sprintf(usba_name[n++],
2151 2069                              "usb%x,class%x.%x.%x",
2152 2070                              usb_dev_descr->idVendor,
2153 2071                              usb_dev_descr->bDeviceClass,
2154 2072                              usb_dev_descr->bDeviceSubClass,
2155 2073                              usb_dev_descr->bDeviceProtocol);
2156 2074  
2157 2075                          /* 6. usbVID,classDC.DSC */
2158 2076                          (void) sprintf(usba_name[n++],
2159 2077                              "usb%x.class%x.%x",
2160 2078                              usb_dev_descr->idVendor,
2161 2079                              usb_dev_descr->bDeviceClass,
2162 2080                              usb_dev_descr->bDeviceSubClass);
2163 2081  
2164 2082                          /* 7. usbVID,classDC */
2165 2083                          (void) sprintf(usba_name[n++],
2166 2084                              "usb%x.class%x",
2167 2085                              usb_dev_descr->idVendor,
2168 2086                              usb_dev_descr->bDeviceClass);
2169 2087  
2170 2088                          /* 8. usb,classDC.DSC.DPROTO */
2171 2089                          (void) sprintf(usba_name[n++],
2172 2090                              "usb,class%x.%x.%x",
2173 2091                              usb_dev_descr->bDeviceClass,
2174 2092                              usb_dev_descr->bDeviceSubClass,
2175 2093                              usb_dev_descr->bDeviceProtocol);
2176 2094  
2177 2095                          /* 9. usb,classDC.DSC */
2178 2096                          (void) sprintf(usba_name[n++],
2179 2097                              "usb,class%x.%x",
2180 2098                              usb_dev_descr->bDeviceClass,
2181 2099                              usb_dev_descr->bDeviceSubClass);
2182 2100  
2183 2101                          /* 10. usb,classDC */
2184 2102                          (void) sprintf(usba_name[n++],
2185 2103                              "usb,class%x",
2186 2104                              usb_dev_descr->bDeviceClass);
2187 2105                  }
2188 2106  
2189 2107                  if (usba_get_ugen_binding(child_dip) ==
2190 2108                      USBA_UGEN_DEVICE_BINDING) {
2191 2109                          /* 11. ugen */
2192 2110                          (void) sprintf(usba_name[n++], "ugen");
2193 2111                  } else {
2194 2112                          /* 11. usb,device */
2195 2113                          (void) sprintf(usba_name[n++], "usb,device");
2196 2114                  }
2197 2115          }
2198 2116  
2199 2117          for (i = 0; i < n; i += 2) {
2200 2118                  USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
2201 2119                      "compatible name:\t%s\t%s", usba_name[i],
2202 2120                      (((i+1) < n)? usba_name[i+1] : ""));
2203 2121          }
2204 2122  
2205 2123          rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, child_dip,
2206 2124              "compatible", (char **)usba_name, n);
2207 2125  
2208 2126          kmem_free(usba_name_buf, USBA_MAX_COMPAT_NAMES *
2209 2127              USBA_MAX_COMPAT_NAME_LEN);
2210 2128  
2211 2129          if (rval != DDI_PROP_SUCCESS) {
2212 2130  
2213 2131                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2214 2132                      "usba_ready_device_node: property update failed");
2215 2133  
2216 2134                  return (child_dip);
2217 2135          }
2218 2136  
2219 2137          /* update the address property */
2220 2138          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2221 2139              "assigned-address", usba_device->usb_addr);
2222 2140          if (rval != DDI_PROP_SUCCESS) {
2223 2141                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2224 2142                      "usba_ready_device_node: address update failed");
2225 2143          }
2226 2144  
2227 2145          /* update the usb device properties (PSARC/2000/454) */
2228 2146          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2229 2147              "usb-vendor-id", usb_dev_descr->idVendor);
2230 2148          if (rval != DDI_PROP_SUCCESS) {
2231 2149                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2232 2150                      "usba_ready_device_node: usb-vendor-id update failed");
2233 2151          }
2234 2152  
2235 2153          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2236 2154              "usb-product-id", usb_dev_descr->idProduct);
2237 2155          if (rval != DDI_PROP_SUCCESS) {
2238 2156                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2239 2157                      "usba_ready_device_node: usb-product-id update failed");
2240 2158          }
2241 2159  
2242 2160          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2243 2161              "usb-revision-id", usb_dev_descr->bcdDevice);
2244 2162          if (rval != DDI_PROP_SUCCESS) {
2245 2163                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2246 2164                      "usba_ready_device_node: usb-revision-id update failed");
2247 2165          }
2248 2166  
2249 2167          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2250 2168              "usb-num-configs", usb_dev_descr->bNumConfigurations);
2251 2169          if (rval != DDI_PROP_SUCCESS) {
2252 2170                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2253 2171                      "usba_ready_device_node: usb-num-configs update failed");
2254 2172          }
2255 2173  
2256 2174          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2257 2175              "usb-release", usb_dev_descr->bcdUSB);
2258 2176          if (rval != DDI_PROP_SUCCESS) {
2259 2177                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2260 2178                      "usba_ready_device_node: usb-release update failed");
2261 2179          }
2262 2180  
2263 2181          rval = ndi_prop_update_byte_array(DDI_DEV_T_NONE, child_dip,
2264 2182              "usb-dev-descriptor", (uchar_t *)usb_dev_descr,
2265 2183              sizeof (usb_dev_descr_t));
2266 2184          if (rval != DDI_PROP_SUCCESS) {
2267 2185                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2268 2186                      "usba_ready_device_node: usb-descriptor update failed");
2269 2187          }
2270 2188  
2271 2189          rval = ndi_prop_update_byte_array(DDI_DEV_T_NONE, child_dip,
2272 2190              "usb-raw-cfg-descriptors", usb_config, usb_config_length);
2273 2191          if (rval != DDI_PROP_SUCCESS) {
2274 2192                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2275 2193                      "usba_ready_device_node: usb-raw-cfg-descriptors update "
2276 2194                      "failed");
2277 2195          }
2278 2196  
2279 2197          devprop_str = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
2280 2198  
2281 2199          if (usba_device->usb_serialno_str) {
2282 2200                  usba_filter_string(usba_device->usb_serialno_str, devprop_str);
2283 2201                  rval = ndi_prop_update_string(DDI_DEV_T_NONE, child_dip,
2284 2202                      "usb-serialno", devprop_str);
2285 2203                  if (rval != DDI_PROP_SUCCESS) {
2286 2204                          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2287 2205                              "usba_ready_device_node: "
2288 2206                              "usb-serialno update failed");
2289 2207                  }
2290 2208          }
2291 2209  
2292 2210          if (usba_device->usb_mfg_str) {
2293 2211                  usba_filter_string(usba_device->usb_mfg_str, devprop_str);
2294 2212                  rval = ndi_prop_update_string(DDI_DEV_T_NONE, child_dip,
2295 2213                      "usb-vendor-name", devprop_str);
2296 2214                  if (rval != DDI_PROP_SUCCESS) {
2297 2215                          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2298 2216                              "usba_ready_device_node: "
2299 2217                              "usb-vendor-name update failed");
2300 2218                  }
2301 2219          }
2302 2220  
2303 2221          if (usba_device->usb_product_str) {
2304 2222                  usba_filter_string(usba_device->usb_product_str, devprop_str);
2305 2223                  rval = ndi_prop_update_string(DDI_DEV_T_NONE, child_dip,
2306 2224                      "usb-product-name", devprop_str);
2307 2225                  if (rval != DDI_PROP_SUCCESS) {
2308 2226                          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2309 2227                              "usba_ready_device_node: "
2310 2228                              "usb-product-name update failed");
2311 2229                  }
2312 2230          }
2313 2231  
2314 2232          kmem_free(devprop_str, USB_MAXSTRINGLEN);
2315 2233  
2316 2234          if (!combined_node) {
2317 2235                  /* update the configuration property */
2318 2236                  rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2319 2237                      "configuration#", usba_device->usb_cfg_value);
2320 2238                  if (rval != DDI_PROP_SUCCESS) {
2321 2239                          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2322 2240                              "usba_ready_device_node: "
2323 2241                              "config prop update failed");
2324 2242                  }
2325 2243          }
2326 2244  
2327 2245          if (usba_device->usb_port_status == USBA_LOW_SPEED_DEV) {
2328 2246                  /* create boolean property */
2329 2247                  rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, child_dip,
2330 2248                      "low-speed");
2331 2249                  if (rval != DDI_PROP_SUCCESS) {
2332 2250                          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2333 2251                              "usba_ready_device_node: "
2334 2252                              "low speed prop update failed");
2335 2253                  }
2336 2254          }
2337 2255  
2338 2256          if (usba_device->usb_port_status == USBA_HIGH_SPEED_DEV) {
2339 2257                  /* create boolean property */
2340 2258                  rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, child_dip,
2341 2259                      "high-speed");
2342 2260                  if (rval != DDI_PROP_SUCCESS) {
2343 2261                          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2344 2262                              "usba_ready_device_node: "
2345 2263                              "high speed prop update failed");
2346 2264                  }
2347 2265          }
2348 2266  
2349 2267          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
2350 2268              "%s%d at port %d: %s, dip=0x%p",
2351 2269              ddi_node_name(ddi_get_parent(child_dip)),
2352 2270              ddi_get_instance(ddi_get_parent(child_dip)),
2353 2271              port, ddi_node_name(child_dip), (void *)child_dip);
2354 2272  
2355 2273          usba_set_usba_device(child_dip, usba_device);
2356 2274  
2357 2275          ASSERT(!mutex_owned(&(usba_get_usba_device(child_dip)->usb_mutex)));
2358 2276  
2359 2277          return (child_dip);
2360 2278  }
2361 2279  
2362 2280  
2363 2281  /*
2364 2282   * driver binding at interface association level. the first arg is the parent
2365 2283   * dip. if_count returns amount of interfaces which are associated within
2366 2284   * this interface-association that starts from first_if.
2367 2285   */
2368 2286  /*ARGSUSED*/
2369 2287  dev_info_t *
2370 2288  usba_ready_interface_association_node(dev_info_t        *dip,
2371 2289                                          uint_t          first_if,
2372 2290                                          uint_t          *if_count)
2373 2291  {
2374 2292          dev_info_t              *child_dip = NULL;
2375 2293          usba_device_t           *child_ud = usba_get_usba_device(dip);
2376 2294          usb_dev_descr_t         *usb_dev_descr;
2377 2295          size_t                  usb_cfg_length;
2378 2296          uchar_t                 *usb_cfg;
2379 2297          usb_ia_descr_t          ia_descr;
2380 2298          int                     i, n, rval;
2381 2299          int                     reg[2];
2382 2300          size_t                  size;
2383 2301          usb_port_status_t       port_status;
2384 2302          char                    *force_bind = NULL;
2385 2303          char                    *usba_name_buf = NULL;
2386 2304          char                    *usba_name[USBA_MAX_COMPAT_NAMES];
2387 2305  
2388 2306          usb_cfg = usb_get_raw_cfg_data(dip, &usb_cfg_length);
2389 2307  
2390 2308          mutex_enter(&child_ud->usb_mutex);
2391 2309  
2392 2310          usb_dev_descr = child_ud->usb_dev_descr;
2393 2311  
2394 2312          /*
2395 2313           * for each interface association, determine all compatible names
2396 2314           */
2397 2315          USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
2398 2316              "usba_ready_ia_node: "
2399 2317              "port %d, interface = %d, port_status = %x",
2400 2318              child_ud->usb_port, first_if, child_ud->usb_port_status);
2401 2319  
2402 2320          /* Parse the interface descriptor */
2403 2321          size = usb_parse_ia_descr(
2404 2322              usb_cfg,
2405 2323              usb_cfg_length,
2406 2324              first_if,   /* interface index */
2407 2325              &ia_descr,
2408 2326              USB_IA_DESCR_SIZE);
2409 2327  
2410 2328          *if_count = 1;
2411 2329          if (size != USB_IA_DESCR_SIZE) {
2412 2330                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2413 2331                      "parsing ia: size (%lu) != USB_IA_DESCR_SIZE (%d)",
2414 2332                      size, USB_IA_DESCR_SIZE);
2415 2333                  mutex_exit(&child_ud->usb_mutex);
2416 2334  
2417 2335                  return (NULL);
2418 2336          }
2419 2337  
2420 2338          port_status = child_ud->usb_port_status;
2421 2339  
2422 2340          /* create reg property */
2423 2341          reg[0] = first_if;
2424 2342          reg[1] = child_ud->usb_cfg_value;
2425 2343  
2426 2344          mutex_exit(&child_ud->usb_mutex);
2427 2345  
2428 2346          /* clone this dip */
2429 2347          rval =  usba_create_child_devi(dip,
2430 2348              "interface-association",
2431 2349              NULL,               /* usba_hcdi ops */
2432 2350              NULL,               /* root hub dip */
2433 2351              port_status,        /* port status */
2434 2352              child_ud,   /* share this usba_device */
2435 2353              &child_dip);
2436 2354  
2437 2355          if (rval != USB_SUCCESS) {
2438 2356  
2439 2357                  goto fail;
2440 2358          }
2441 2359  
2442 2360          rval = ndi_prop_update_int_array(
2443 2361              DDI_DEV_T_NONE, child_dip, "reg", reg, 2);
2444 2362  
2445 2363          if (rval != DDI_PROP_SUCCESS) {
2446 2364  
2447 2365                  goto fail;
2448 2366          }
2449 2367  
2450 2368          usba_set_node_name(child_dip, ia_descr.bFunctionClass,
2451 2369              ia_descr.bFunctionSubClass, ia_descr.bFunctionProtocol,
2452 2370              FLAG_INTERFACE_ASSOCIATION_NODE);
2453 2371  
2454 2372          /* check force binding */
2455 2373          if (usba_ugen_force_binding ==
2456 2374              USBA_UGEN_INTERFACE_ASSOCIATION_BINDING) {
2457 2375                  force_bind = "ugen";
2458 2376          }
2459 2377  
2460 2378          /*
2461 2379           * check whether there is another dip with this name and address
2462 2380           */
2463 2381          ASSERT(usba_find_existing_node(child_dip) == NULL);
2464 2382  
2465 2383          usba_name_buf = kmem_zalloc(USBA_MAX_COMPAT_NAMES *
2466 2384              USBA_MAX_COMPAT_NAME_LEN, KM_SLEEP);
2467 2385  
2468 2386          for (i = 0; i < USBA_MAX_COMPAT_NAMES; i++) {
2469 2387                  usba_name[i] = usba_name_buf + (i * USBA_MAX_COMPAT_NAME_LEN);
2470 2388          }
2471 2389  
2472 2390          n = 0;
2473 2391  
2474 2392          if (force_bind) {
2475 2393                  (void) ndi_devi_set_nodename(child_dip, force_bind, 0);
2476 2394                  (void) strncpy(usba_name[n++], force_bind,
2477 2395                      USBA_MAX_COMPAT_NAME_LEN);
2478 2396          }
2479 2397  
2480 2398          /* 1) usbiaVID,PID.REV.configCN.FN */
2481 2399          (void) sprintf(usba_name[n++],
2482 2400              "usbia%x,%x.%x.config%x.%x",
2483 2401              usb_dev_descr->idVendor,
2484 2402              usb_dev_descr->idProduct,
2485 2403              usb_dev_descr->bcdDevice,
2486 2404              child_ud->usb_cfg_value,
2487 2405              first_if);
2488 2406  
2489 2407          /* 2) usbiaVID,PID.configCN.FN */
2490 2408          (void) sprintf(usba_name[n++],
2491 2409              "usbia%x,%x.config%x.%x",
2492 2410              usb_dev_descr->idVendor,
2493 2411              usb_dev_descr->idProduct,
2494 2412              child_ud->usb_cfg_value,
2495 2413              first_if);
2496 2414  
2497 2415  
2498 2416          if (ia_descr.bFunctionClass) {
2499 2417                  /* 3) usbiaVID,classFC.FSC.FPROTO */
2500 2418                  (void) sprintf(usba_name[n++],
2501 2419                      "usbia%x,class%x.%x.%x",
2502 2420                      usb_dev_descr->idVendor,
2503 2421                      ia_descr.bFunctionClass,
2504 2422                      ia_descr.bFunctionSubClass,
2505 2423                      ia_descr.bFunctionProtocol);
2506 2424  
2507 2425                  /* 4) usbiaVID,classFC.FSC */
2508 2426                  (void) sprintf(usba_name[n++],
2509 2427                      "usbia%x,class%x.%x",
2510 2428                      usb_dev_descr->idVendor,
2511 2429                      ia_descr.bFunctionClass,
2512 2430                      ia_descr.bFunctionSubClass);
2513 2431  
2514 2432                  /* 5) usbiaVID,classFC */
2515 2433                  (void) sprintf(usba_name[n++],
2516 2434                      "usbia%x,class%x",
2517 2435                      usb_dev_descr->idVendor,
2518 2436                      ia_descr.bFunctionClass);
2519 2437  
2520 2438                  /* 6) usbia,classFC.FSC.FPROTO */
2521 2439                  (void) sprintf(usba_name[n++],
2522 2440                      "usbia,class%x.%x.%x",
2523 2441                      ia_descr.bFunctionClass,
2524 2442                      ia_descr.bFunctionSubClass,
2525 2443                      ia_descr.bFunctionProtocol);
2526 2444  
2527 2445                  /* 7) usbia,classFC.FSC */
2528 2446                  (void) sprintf(usba_name[n++],
2529 2447                      "usbia,class%x.%x",
2530 2448                      ia_descr.bFunctionClass,
2531 2449                      ia_descr.bFunctionSubClass);
2532 2450  
2533 2451                  /* 8) usbia,classFC */
2534 2452                  (void) sprintf(usba_name[n++],
2535 2453                      "usbia,class%x",
2536 2454                      ia_descr.bFunctionClass);
2537 2455          }
2538 2456  
2539 2457          if (usba_get_ugen_binding(child_dip) ==
2540 2458              USBA_UGEN_INTERFACE_ASSOCIATION_BINDING) {
2541 2459                  /* 9) ugen */
2542 2460                  (void) sprintf(usba_name[n++], "ugen");
2543 2461          } else {
2544 2462  
2545 2463                  (void) sprintf(usba_name[n++], "usb,ia");
2546 2464          }
2547 2465  
2548 2466          for (i = 0; i < n; i += 2) {
2549 2467                  USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
2550 2468                      "compatible name:\t%s\t%s", usba_name[i],
2551 2469                      (((i+1) < n)? usba_name[i+1] : ""));
2552 2470          }
2553 2471  
2554 2472          /* create compatible property */
2555 2473          rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, child_dip,
2556 2474              "compatible", (char **)usba_name, n);
2557 2475  
2558 2476          kmem_free(usba_name_buf, USBA_MAX_COMPAT_NAMES *
2559 2477              USBA_MAX_COMPAT_NAME_LEN);
2560 2478  
2561 2479          if (rval != DDI_PROP_SUCCESS) {
2562 2480  
2563 2481                  goto fail;
2564 2482          }
2565 2483  
2566 2484          /* update the address property */
2567 2485          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2568 2486              "assigned-address", child_ud->usb_addr);
2569 2487          if (rval != DDI_PROP_SUCCESS) {
2570 2488                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2571 2489                      "usba_ready_interface_node: address update failed");
2572 2490          }
2573 2491  
2574 2492          /* create property with first interface number */
2575 2493          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2576 2494              "interface", ia_descr.bFirstInterface);
2577 2495  
2578 2496          if (rval != DDI_PROP_SUCCESS) {
2579 2497  
2580 2498                  goto fail;
2581 2499          }
2582 2500  
2583 2501          /* create property with the count of interfaces in this ia */
2584 2502          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2585 2503              "interface-count", ia_descr.bInterfaceCount);
2586 2504  
2587 2505          if (rval != DDI_PROP_SUCCESS) {
2588 2506  
2589 2507                  goto fail;
2590 2508          }
2591 2509  
2592 2510          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2593 2511              "%s%d port %d: %s, dip = 0x%p",
2594 2512              ddi_node_name(ddi_get_parent(dip)),
2595 2513              ddi_get_instance(ddi_get_parent(dip)),
2596 2514              child_ud->usb_port, ddi_node_name(child_dip), (void *)child_dip);
2597 2515  
2598 2516          *if_count = ia_descr.bInterfaceCount;
2599 2517          usba_set_usba_device(child_dip, child_ud);
2600 2518          ASSERT(!mutex_owned(&(usba_get_usba_device(child_dip)->usb_mutex)));
2601 2519  
2602 2520          return (child_dip);
2603 2521  
2604 2522  fail:
2605 2523          (void) usba_destroy_child_devi(child_dip, NDI_DEVI_REMOVE);
2606 2524  
2607 2525          return (NULL);
2608 2526  }
2609 2527  
2610 2528  
2611 2529  /*
2612 2530   * driver binding at interface level, the first arg will be the
2613 2531   * the parent dip
2614 2532   */
2615 2533  /*ARGSUSED*/
2616 2534  dev_info_t *
2617 2535  usba_ready_interface_node(dev_info_t *dip, uint_t intf)
2618 2536  {
2619 2537          dev_info_t              *child_dip = NULL;
2620 2538          usba_device_t           *child_ud = usba_get_usba_device(dip);
2621 2539          usb_dev_descr_t *usb_dev_descr;
2622 2540          size_t                  usb_cfg_length;
2623 2541          uchar_t                 *usb_cfg;
2624 2542          usb_if_descr_t  if_descr;
2625 2543          int                     i, n, rval;
2626 2544          int                     reg[2];
2627 2545          size_t                  size;
2628 2546          usb_port_status_t       port_status;
2629 2547          char                    *force_bind = NULL;
2630 2548          char                    *usba_name_buf = NULL;
2631 2549          char                    *usba_name[USBA_MAX_COMPAT_NAMES];
2632 2550  
2633 2551          usb_cfg = usb_get_raw_cfg_data(dip, &usb_cfg_length);
2634 2552  
2635 2553          mutex_enter(&child_ud->usb_mutex);
2636 2554  
2637 2555          usb_dev_descr = child_ud->usb_dev_descr;
2638 2556  
2639 2557          /*
2640 2558           * for each interface, determine all compatible names
2641 2559           */
2642 2560          USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
2643 2561              "usba_ready_interface_node: "
2644 2562              "port %d, interface = %d port status = %x",
2645 2563              child_ud->usb_port, intf, child_ud->usb_port_status);
2646 2564  
2647 2565          /* Parse the interface descriptor */
2648 2566          size = usb_parse_if_descr(
2649 2567              usb_cfg,
2650 2568              usb_cfg_length,
2651 2569              intf,               /* interface index */
2652 2570              0,          /* alt interface index */
2653 2571              &if_descr,
2654 2572              USB_IF_DESCR_SIZE);
2655 2573  
2656 2574          if (size != USB_IF_DESCR_SIZE) {
2657 2575                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2658 2576                      "parsing interface: size (%lu) != USB_IF_DESCR_SIZE (%d)",
2659 2577                      size, USB_IF_DESCR_SIZE);
2660 2578                  mutex_exit(&child_ud->usb_mutex);
2661 2579  
2662 2580                  return (NULL);
2663 2581          }
2664 2582  
2665 2583          port_status = child_ud->usb_port_status;
2666 2584  
2667 2585          /* create reg property */
2668 2586          reg[0] = intf;
2669 2587          reg[1] = child_ud->usb_cfg_value;
2670 2588  
2671 2589          mutex_exit(&child_ud->usb_mutex);
2672 2590  
2673 2591          /* clone this dip */
2674 2592          rval =  usba_create_child_devi(dip,
2675 2593              "interface",
2676 2594              NULL,               /* usba_hcdi ops */
2677 2595              NULL,               /* root hub dip */
2678 2596              port_status,        /* port status */
2679 2597              child_ud,   /* share this usba_device */
2680 2598              &child_dip);
2681 2599  
2682 2600          if (rval != USB_SUCCESS) {
2683 2601  
2684 2602                  goto fail;
2685 2603          }
2686 2604  
2687 2605          rval = ndi_prop_update_int_array(
2688 2606              DDI_DEV_T_NONE, child_dip, "reg", reg, 2);
2689 2607  
2690 2608          if (rval != DDI_PROP_SUCCESS) {
2691 2609  
2692 2610                  goto fail;
2693 2611          }
2694 2612  
2695 2613          usba_set_node_name(child_dip, if_descr.bInterfaceClass,
2696 2614              if_descr.bInterfaceSubClass, if_descr.bInterfaceProtocol,
2697 2615              FLAG_INTERFACE_NODE);
2698 2616  
2699 2617          /* check force binding */
2700 2618          if (usba_ugen_force_binding == USBA_UGEN_INTERFACE_BINDING) {
2701 2619                  force_bind = "ugen";
2702 2620          }
2703 2621  
2704 2622          /*
2705 2623           * check whether there is another dip with this name and address
2706 2624           */
2707 2625          ASSERT(usba_find_existing_node(child_dip) == NULL);
2708 2626  
2709 2627          usba_name_buf = kmem_zalloc(USBA_MAX_COMPAT_NAMES *
2710 2628              USBA_MAX_COMPAT_NAME_LEN, KM_SLEEP);
2711 2629  
2712 2630          for (i = 0; i < USBA_MAX_COMPAT_NAMES; i++) {
2713 2631                  usba_name[i] = usba_name_buf + (i * USBA_MAX_COMPAT_NAME_LEN);
2714 2632          }
2715 2633  
2716 2634          n = 0;
2717 2635  
2718 2636          if (force_bind) {
2719 2637                  (void) ndi_devi_set_nodename(child_dip, force_bind, 0);
2720 2638                  (void) strncpy(usba_name[n++], force_bind,
2721 2639                      USBA_MAX_COMPAT_NAME_LEN);
2722 2640          }
2723 2641  
2724 2642          /* 1) usbifVID,PID.REV.configCN.IN */
2725 2643          (void) sprintf(usba_name[n++],
2726 2644              "usbif%x,%x.%x.config%x.%x",
2727 2645              usb_dev_descr->idVendor,
2728 2646              usb_dev_descr->idProduct,
2729 2647              usb_dev_descr->bcdDevice,
2730 2648              child_ud->usb_cfg_value,
2731 2649              intf);
2732 2650  
2733 2651          /* 2) usbifVID,PID.configCN.IN */
2734 2652          (void) sprintf(usba_name[n++],
2735 2653              "usbif%x,%x.config%x.%x",
2736 2654              usb_dev_descr->idVendor,
2737 2655              usb_dev_descr->idProduct,
2738 2656              child_ud->usb_cfg_value,
2739 2657              intf);
2740 2658  
2741 2659  
2742 2660          if (if_descr.bInterfaceClass) {
2743 2661                  /* 3) usbifVID,classIC.ISC.IPROTO */
2744 2662                  (void) sprintf(usba_name[n++],
2745 2663                      "usbif%x,class%x.%x.%x",
2746 2664                      usb_dev_descr->idVendor,
2747 2665                      if_descr.bInterfaceClass,
2748 2666                      if_descr.bInterfaceSubClass,
2749 2667                      if_descr.bInterfaceProtocol);
2750 2668  
2751 2669                  /* 4) usbifVID,classIC.ISC */
2752 2670                  (void) sprintf(usba_name[n++],
2753 2671                      "usbif%x,class%x.%x",
2754 2672                      usb_dev_descr->idVendor,
2755 2673                      if_descr.bInterfaceClass,
2756 2674                      if_descr.bInterfaceSubClass);
2757 2675  
2758 2676                  /* 5) usbifVID,classIC */
2759 2677                  (void) sprintf(usba_name[n++],
2760 2678                      "usbif%x,class%x",
2761 2679                      usb_dev_descr->idVendor,
2762 2680                      if_descr.bInterfaceClass);
2763 2681  
2764 2682                  /* 6) usbif,classIC.ISC.IPROTO */
2765 2683                  (void) sprintf(usba_name[n++],
2766 2684                      "usbif,class%x.%x.%x",
2767 2685                      if_descr.bInterfaceClass,
2768 2686                      if_descr.bInterfaceSubClass,
2769 2687                      if_descr.bInterfaceProtocol);
2770 2688  
2771 2689                  /* 7) usbif,classIC.ISC */
2772 2690                  (void) sprintf(usba_name[n++],
2773 2691                      "usbif,class%x.%x",
2774 2692                      if_descr.bInterfaceClass,
2775 2693                      if_descr.bInterfaceSubClass);
2776 2694  
2777 2695                  /* 8) usbif,classIC */
2778 2696                  (void) sprintf(usba_name[n++],
2779 2697                      "usbif,class%x",
2780 2698                      if_descr.bInterfaceClass);
2781 2699          }
2782 2700  
2783 2701          if (usba_get_ugen_binding(child_dip) ==
2784 2702              USBA_UGEN_INTERFACE_BINDING) {
2785 2703                  /* 9) ugen */
2786 2704                  (void) sprintf(usba_name[n++], "ugen");
2787 2705          }
2788 2706  
2789 2707          for (i = 0; i < n; i += 2) {
2790 2708                  USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
2791 2709                      "compatible name:\t%s\t%s", usba_name[i],
2792 2710                      (((i+1) < n)? usba_name[i+1] : ""));
2793 2711          }
2794 2712  
2795 2713          /* create compatible property */
2796 2714          rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, child_dip,
2797 2715              "compatible", (char **)usba_name, n);
2798 2716  
2799 2717          kmem_free(usba_name_buf, USBA_MAX_COMPAT_NAMES *
2800 2718              USBA_MAX_COMPAT_NAME_LEN);
2801 2719  
2802 2720          if (rval != DDI_PROP_SUCCESS) {
2803 2721  
2804 2722                  goto fail;
2805 2723          }
2806 2724  
2807 2725          /* update the address property */
2808 2726          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2809 2727              "assigned-address", child_ud->usb_addr);
2810 2728          if (rval != DDI_PROP_SUCCESS) {
2811 2729                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2812 2730                      "usba_ready_interface_node: address update failed");
2813 2731          }
2814 2732  
2815 2733          /* create property with if number */
2816 2734          rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2817 2735              "interface", intf);
2818 2736  
2819 2737          if (rval != DDI_PROP_SUCCESS) {
2820 2738  
2821 2739                  goto fail;
2822 2740          }
2823 2741  
2824 2742          USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2825 2743              "%s%d port %d: %s, dip = 0x%p",
2826 2744              ddi_node_name(ddi_get_parent(dip)),
2827 2745              ddi_get_instance(ddi_get_parent(dip)),
2828 2746              child_ud->usb_port, ddi_node_name(child_dip), (void *)child_dip);
2829 2747  
2830 2748          usba_set_usba_device(child_dip, child_ud);
2831 2749          ASSERT(!mutex_owned(&(usba_get_usba_device(child_dip)->usb_mutex)));
2832 2750  
2833 2751          return (child_dip);
2834 2752  
2835 2753  fail:
2836 2754          (void) usba_destroy_child_devi(child_dip, NDI_DEVI_REMOVE);
2837 2755  
2838 2756          return (NULL);
2839 2757  }
2840 2758  
2841 2759  
2842 2760  /*
2843 2761   * retrieve string descriptors for manufacturer, vendor and serial
2844 2762   * number
2845 2763   */
2846 2764  void
2847 2765  usba_get_dev_string_descrs(dev_info_t *dip, usba_device_t *ud)
2848 2766  {
2849 2767          char    *tmpbuf, *str;
2850 2768          int     l;
2851 2769          usb_dev_descr_t *usb_dev_descr = ud->usb_dev_descr;
2852 2770  
2853 2771  
2854 2772          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
2855 2773              "usba_get_usb_string_descr: m=%d, p=%d, s=%d",
2856 2774              usb_dev_descr->iManufacturer,
2857 2775              usb_dev_descr->iProduct,
2858 2776              usb_dev_descr->iSerialNumber);
2859 2777  
2860 2778          tmpbuf = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
2861 2779  
2862 2780          /* fetch manufacturer string */
2863 2781          if ((ud->usb_mfg_str == NULL) && usb_dev_descr->iManufacturer &&
2864 2782              (usb_get_string_descr(dip, USB_LANG_ID,
2865 2783              usb_dev_descr->iManufacturer, tmpbuf, USB_MAXSTRINGLEN) ==
2866 2784              USB_SUCCESS)) {
2867 2785  
2868 2786                  l = strlen(tmpbuf);
2869 2787                  if (l > 0) {
2870 2788                          str = kmem_zalloc(l + 1, KM_SLEEP);
2871 2789                          mutex_enter(&ud->usb_mutex);
2872 2790                          ud->usb_mfg_str = str;
2873 2791                          (void) strcpy(ud->usb_mfg_str, tmpbuf);
2874 2792                          mutex_exit(&ud->usb_mutex);
2875 2793                  }
2876 2794          }
2877 2795  
2878 2796          /* fetch product string */
2879 2797          if ((ud->usb_product_str == NULL) && usb_dev_descr->iProduct &&
2880 2798              (usb_get_string_descr(dip, USB_LANG_ID, usb_dev_descr->iProduct,
2881 2799              tmpbuf, USB_MAXSTRINGLEN) ==
2882 2800              USB_SUCCESS)) {
2883 2801  
2884 2802                  l = strlen(tmpbuf);
2885 2803                  if (l > 0) {
2886 2804                          str = kmem_zalloc(l + 1, KM_SLEEP);
2887 2805                          mutex_enter(&ud->usb_mutex);
2888 2806                          ud->usb_product_str = str;
2889 2807                          (void) strcpy(ud->usb_product_str, tmpbuf);
2890 2808                          mutex_exit(&ud->usb_mutex);
2891 2809                  }
2892 2810          }
2893 2811  
2894 2812          /* fetch device serial number string */
2895 2813          if ((ud->usb_serialno_str == NULL) && usb_dev_descr->iSerialNumber &&
2896 2814              (usb_get_string_descr(dip, USB_LANG_ID,
2897 2815              usb_dev_descr->iSerialNumber, tmpbuf, USB_MAXSTRINGLEN) ==
2898 2816              USB_SUCCESS)) {
2899 2817  
2900 2818                  l = strlen(tmpbuf);
2901 2819                  if (l > 0) {
2902 2820                          str = kmem_zalloc(l + 1, KM_SLEEP);
2903 2821                          mutex_enter(&ud->usb_mutex);
2904 2822                          ud->usb_serialno_str = str;
2905 2823                          (void) strcpy(ud->usb_serialno_str, tmpbuf);
2906 2824                          mutex_exit(&ud->usb_mutex);
2907 2825                  }
2908 2826          }
2909 2827  
2910 2828          kmem_free(tmpbuf, USB_MAXSTRINGLEN);
2911 2829  }
2912 2830  
2913 2831  
2914 2832  /*
2915 2833   * usba_str_startcmp:
2916 2834   *      Return the number of characters duplicated from the beginning of the
2917 2835   *      string.  Return -1 if a complete duplicate.
2918 2836   *
2919 2837   * Arguments:
2920 2838   *      Two strings to compare.
2921 2839   */
2922 2840  static int usba_str_startcmp(char *first, char *second)
2923 2841  {
2924 2842          int num_same_chars = 0;
2925 2843          while (*first == *second++) {
2926 2844                  if (*first++ == '\0') {
2927 2845                          return (-1);
2928 2846                  }
2929 2847                  num_same_chars++;
2930 2848          }
2931 2849  
2932 2850          return (num_same_chars);
2933 2851  }
2934 2852  
2935 2853  
2936 2854  /*
2937 2855   * usba_get_mfg_prod_sn_str:
2938 2856   *      Return a string containing mfg, product, serial number strings.
2939 2857   *      Remove duplicates if some strings are the same.
2940 2858   *
2941 2859   * Arguments:
2942 2860   *      dip     - pointer to dev info
2943 2861   *      buffer  - Where string is returned
2944 2862   *      buflen  - Length of buffer
2945 2863   *
2946 2864   * Returns:
2947 2865   *      Same as second arg.
2948 2866   */
2949 2867  char *
2950 2868  usba_get_mfg_prod_sn_str(
2951 2869      dev_info_t  *dip,
2952 2870      char        *buffer,
2953 2871      int         buflen)
2954 2872  {
2955 2873          usba_device_t *usba_device = usba_get_usba_device(dip);
2956 2874          int return_len = 0;
2957 2875          int len = 0;
2958 2876          int duplen;
2959 2877  
2960 2878          buffer[0] = '\0';
2961 2879          buffer[buflen-1] = '\0';
2962 2880  
2963 2881          if ((usba_device->usb_mfg_str) &&
2964 2882              ((len = strlen(usba_device->usb_mfg_str)) != 0)) {
2965 2883                  (void) strncpy(buffer, usba_device->usb_mfg_str, buflen - 1);
2966 2884                  return_len = min(buflen - 1, len);
2967 2885          }
2968 2886  
2969 2887          /* Product string exists to append. */
2970 2888          if ((usba_device->usb_product_str) &&
2971 2889              ((len = strlen(usba_device->usb_product_str)) != 0)) {
2972 2890  
2973 2891                  /* Append only parts of string that don't match mfg string. */
2974 2892                  duplen = usba_str_startcmp(buffer,
2975 2893                      usba_device->usb_product_str);
2976 2894  
2977 2895                  if (duplen != -1) {             /* Not a complete match. */
2978 2896                          if (return_len > 0) {
2979 2897                                  buffer[return_len++] = ' ';
2980 2898                          }
2981 2899  
2982 2900                          /* Skip over the dup part of the concat'ed string. */
2983 2901                          len -= duplen;
2984 2902                          (void) strncpy(&buffer[return_len],
2985 2903                              &usba_device->usb_product_str[duplen],
2986 2904                              buflen - return_len - 1);
2987 2905                          return_len = min(buflen - 1, return_len + len);
2988 2906                  }
2989 2907          }
2990 2908  
2991 2909          if ((usba_device->usb_serialno_str) &&
2992 2910              ((len = strlen(usba_device->usb_serialno_str)) != 0)) {
2993 2911                  if (return_len > 0) {
2994 2912                          buffer[return_len++] = ' ';
2995 2913                  }
2996 2914                  (void) strncpy(&buffer[return_len],
2997 2915                      usba_device->usb_serialno_str,
2998 2916                      buflen - return_len - 1);
2999 2917          }
3000 2918  
3001 2919          return (buffer);
3002 2920  }
3003 2921  
3004 2922  
3005 2923  /*
3006 2924   * USB enumeration statistic functions
3007 2925   */
3008 2926  
3009 2927  /*
3010 2928   * Increments the hotplug statistics based on flags.
3011 2929   */
3012 2930  void
3013 2931  usba_update_hotplug_stats(dev_info_t *dip, usb_flags_t flags)
3014 2932  {
3015 2933          usba_device_t   *usba_device = usba_get_usba_device(dip);
3016 2934          usba_hcdi_t     *hcdi =
3017 2935              usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
3018 2936  
3019 2937          mutex_enter(&hcdi->hcdi_mutex);
3020 2938          if (flags & USBA_TOTAL_HOTPLUG_SUCCESS) {
3021 2939                  hcdi->hcdi_total_hotplug_success++;
3022 2940                  HCDI_HOTPLUG_STATS_DATA(hcdi)->
3023 2941                      hcdi_hotplug_total_success.value.ui64++;
3024 2942          }
3025 2943          if (flags & USBA_HOTPLUG_SUCCESS) {
3026 2944                  hcdi->hcdi_hotplug_success++;
3027 2945                  HCDI_HOTPLUG_STATS_DATA(hcdi)->
3028 2946                      hcdi_hotplug_success.value.ui64++;
3029 2947          }
3030 2948          if (flags & USBA_TOTAL_HOTPLUG_FAILURE) {
3031 2949                  hcdi->hcdi_total_hotplug_failure++;
3032 2950                  HCDI_HOTPLUG_STATS_DATA(hcdi)->
3033 2951                      hcdi_hotplug_total_failure.value.ui64++;
3034 2952          }
3035 2953          if (flags & USBA_HOTPLUG_FAILURE) {
3036 2954                  hcdi->hcdi_hotplug_failure++;
3037 2955                  HCDI_HOTPLUG_STATS_DATA(hcdi)->
3038 2956                      hcdi_hotplug_failure.value.ui64++;
3039 2957          }
3040 2958          mutex_exit(&hcdi->hcdi_mutex);
3041 2959  }
3042 2960  
3043 2961  
3044 2962  /*
3045 2963   * Retrieve the current enumeration statistics
3046 2964   */
3047 2965  void
3048 2966  usba_get_hotplug_stats(dev_info_t *dip, ulong_t *total_success,
3049 2967      ulong_t *success, ulong_t *total_failure, ulong_t *failure,
3050 2968      uchar_t *device_count)
3051 2969  {
3052 2970          usba_device_t   *usba_device = usba_get_usba_device(dip);
3053 2971          usba_hcdi_t     *hcdi =
3054 2972              usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
3055 2973  
3056 2974          mutex_enter(&hcdi->hcdi_mutex);
3057 2975          *total_success = hcdi->hcdi_total_hotplug_success;
3058 2976          *success = hcdi->hcdi_hotplug_success;
3059 2977          *total_failure = hcdi->hcdi_total_hotplug_failure;
3060 2978          *failure = hcdi->hcdi_hotplug_failure;
3061 2979          *device_count = hcdi->hcdi_device_count;
3062 2980          mutex_exit(&hcdi->hcdi_mutex);
3063 2981  }
3064 2982  
3065 2983  
3066 2984  /*
3067 2985   * Reset the resetable hotplug stats
3068 2986   */
3069 2987  void
3070 2988  usba_reset_hotplug_stats(dev_info_t *dip)
3071 2989  {
3072 2990          usba_device_t   *usba_device = usba_get_usba_device(dip);
3073 2991          usba_hcdi_t     *hcdi =
3074 2992              usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
3075 2993          hcdi_hotplug_stats_t *hsp;
3076 2994  
3077 2995          mutex_enter(&hcdi->hcdi_mutex);
3078 2996          hcdi->hcdi_hotplug_success = 0;
3079 2997          hcdi->hcdi_hotplug_failure = 0;
3080 2998  
3081 2999          hsp = HCDI_HOTPLUG_STATS_DATA(hcdi);
3082 3000          hsp->hcdi_hotplug_success.value.ui64 = 0;
3083 3001          hsp->hcdi_hotplug_failure.value.ui64 = 0;
3084 3002          mutex_exit(&hcdi->hcdi_mutex);
3085 3003  }
3086 3004  
3087 3005  
3088 3006  /*
3089 3007   * usba_bind_driver():
3090 3008   *      This function calls ndi_devi_bind_driver() which tries to
3091 3009   *      bind a driver to the device.  If the driver binding fails
3092 3010   *      we get an rval of NDI_UNBOUD and report an error to the
3093 3011   *      syslog that the driver failed binding.
3094 3012   *      If rval is something other than NDI_UNBOUND we report an
3095 3013   *      error to the console.
3096 3014   *
3097 3015   *      This function returns USB_SUCCESS if no errors were
3098 3016   *      encountered while binding.
3099 3017   */
3100 3018  int
3101 3019  usba_bind_driver(dev_info_t *dip)
3102 3020  {
3103 3021          int     rval;
3104 3022          char    *name;
3105 3023          uint8_t if_num = usba_get_ifno(dip);
3106 3024  
3107 3025          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
3108 3026              "usba_bind_driver: dip = 0x%p, if_num = 0x%x", (void *)dip, if_num);
3109 3027  
3110 3028          name = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
3111 3029  
3112 3030          /* bind device to the driver */
3113 3031          if ((rval = ndi_devi_bind_driver(dip, 0)) != NDI_SUCCESS) {
3114 3032                  /* if we fail to bind report an error */
3115 3033                  (void) usba_get_mfg_prod_sn_str(dip, name, MAXNAMELEN);
3116 3034                  if (name[0] != '\0') {
3117 3035                          if (!usb_owns_device(dip)) {
3118 3036                                  USB_DPRINTF_L1(DPRINT_MASK_USBA,
3119 3037                                      usba_log_handle,
3120 3038                                      "no driver found for "
3121 3039                                      "interface %d (nodename: '%s') of %s",
3122 3040                                      if_num, ddi_node_name(dip), name);
3123 3041                          } else {
3124 3042                                  USB_DPRINTF_L1(DPRINT_MASK_USBA,
3125 3043                                      usba_log_handle,
3126 3044                                      "no driver found for device %s", name);
3127 3045                          }
3128 3046                  } else {
3129 3047                          (void) ddi_pathname(dip, name);
3130 3048                          USB_DPRINTF_L1(DPRINT_MASK_USBA,
3131 3049                              usba_log_handle,
3132 3050                              "no driver found for device %s", name);
3133 3051                  }
3134 3052  
3135 3053                  kmem_free(name, MAXNAMELEN);
3136 3054  
3137 3055                  return (USB_FAILURE);
3138 3056          }
3139 3057          kmem_free(name, MAXNAMELEN);
3140 3058  
3141 3059          return ((rval == NDI_SUCCESS) ? USB_SUCCESS : USB_FAILURE);
3142 3060  }
3143 3061  
3144 3062  
3145 3063  /*
3146 3064   * usba_get_hc_dma_attr:
3147 3065   *      function returning dma attributes of the HCD
3148 3066   *
3149 3067   * Arguments:
3150 3068   *      dip     - pointer to devinfo of the client
3151 3069   *
3152 3070   * Return Values:
3153 3071   *      hcdi_dma_attr
3154 3072   */
3155 3073  ddi_dma_attr_t *
3156 3074  usba_get_hc_dma_attr(dev_info_t *dip)
3157 3075  {
3158 3076          usba_device_t *usba_device = usba_get_usba_device(dip);
3159 3077          usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
3160 3078  
3161 3079          return (hcdi->hcdi_dma_attr);
3162 3080  }
3163 3081  
3164 3082  
3165 3083  /*
3166 3084   * usba_check_for_leaks:
3167 3085   *      check usba_device structure for leaks
3168 3086   *
3169 3087   * Arguments:
3170 3088   *      usba_device     - usba_device structure pointer
3171 3089   */
3172 3090  void
3173 3091  usba_check_for_leaks(usba_device_t *usba_device)
3174 3092  {
3175 3093          int i, ph_open_cnt, req_wrp_leaks, iface;
3176 3094          int leaks = 0;
3177 3095  
3178 3096          USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
3179 3097              "usba_check_for_leaks: %s%d usba_device=0x%p",
3180 3098              ddi_driver_name(usba_device->usb_dip),
3181 3099              ddi_get_instance(usba_device->usb_dip), (void *)usba_device);
3182 3100  
3183 3101          /*
3184 3102           * default pipe is still open
3185 3103           * all other pipes should be closed
3186 3104           */
3187 3105          for (ph_open_cnt = 0, i = 1; i < USBA_N_ENDPOINTS; i++) {
3188 3106                  usba_ph_impl_t *ph_impl =
3189 3107                      &usba_device->usb_ph_list[i];
3190 3108                  if (ph_impl->usba_ph_data) {
3191 3109                          USB_DPRINTF_L2(DPRINT_MASK_USBA,
3192 3110                              usba_log_handle,
3193 3111                              "%s%d: leaking pipehandle=0x%p (0x%p) ep_addr=0x%x",
3194 3112                              ddi_driver_name(ph_impl->usba_ph_data->p_dip),
3195 3113                              ddi_get_instance(ph_impl->usba_ph_data->p_dip),
3196 3114                              (void *)ph_impl,
3197 3115                              (void *)ph_impl->usba_ph_data,
3198 3116                              ph_impl->usba_ph_ep.bEndpointAddress);
3199 3117                          ph_open_cnt++;
3200 3118                          leaks++;
3201 3119  #ifndef DEBUG
3202 3120                          usb_pipe_close(ph_impl->usba_ph_data->p_dip,
3203 3121                              (usb_pipe_handle_t)ph_impl, USB_FLAGS_SLEEP,
3204 3122                              NULL, NULL);
3205 3123  #endif
3206 3124                  }
3207 3125          }
3208 3126          req_wrp_leaks =  usba_list_entry_leaks(&usba_device->
3209 3127              usb_allocated, "request wrappers");
3210 3128  
3211 3129          ASSERT(ph_open_cnt == 0);
3212 3130          ASSERT(req_wrp_leaks == 0);
3213 3131  
3214 3132          if (req_wrp_leaks) {
3215 3133                  usba_list_entry_t *entry;
3216 3134  
3217 3135                  while ((entry = usba_rm_first_from_list(
3218 3136                      &usba_device->usb_allocated)) != NULL) {
3219 3137                          usba_req_wrapper_t *wrp;
3220 3138  
3221 3139                          mutex_enter(&entry->list_mutex);
3222 3140                          wrp = (usba_req_wrapper_t *)entry->private;
3223 3141                          mutex_exit(&entry->list_mutex);
3224 3142                          leaks++;
3225 3143  
3226 3144                          USB_DPRINTF_L2(DPRINT_MASK_USBA,
3227 3145                              usba_log_handle,
3228 3146                              "%s%d: leaking request 0x%p",
3229 3147                              ddi_driver_name(wrp->wr_dip),
3230 3148                              ddi_get_instance(wrp->wr_dip),
3231 3149                              (void *)wrp->wr_req);
3232 3150  
3233 3151                          /*
3234 3152                           * put it back, usba_req_wrapper_free
3235 3153                           * expects it on the list
3236 3154                           */
3237 3155                          usba_add_to_list(&usba_device->usb_allocated,
3238 3156                              &wrp->wr_allocated_list);
3239 3157  
3240 3158                          usba_req_wrapper_free(wrp);
3241 3159                  }
3242 3160          }
3243 3161  
3244 3162          mutex_enter(&usba_device->usb_mutex);
3245 3163          for (iface = 0; iface < usba_device->usb_n_ifs; iface++) {
3246 3164                  USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
3247 3165                      "usba_check_for_leaks: if=%d client_flags=0x%x",
3248 3166                      iface, usba_device->usb_client_flags[iface]);
3249 3167  
3250 3168                  if (usba_device->usb_client_flags[iface] &
3251 3169                      USBA_CLIENT_FLAG_DEV_DATA) {
3252 3170                          usb_client_dev_data_list_t *entry =
3253 3171                              usba_device->usb_client_dev_data_list.cddl_next;
3254 3172                          usb_client_dev_data_list_t *next;
3255 3173                          usb_client_dev_data_t *dev_data;
3256 3174  
3257 3175                          while (entry) {
3258 3176                                  dev_info_t *dip = entry->cddl_dip;
3259 3177                                  next = entry->cddl_next;
3260 3178                                  dev_data = entry->cddl_dev_data;
3261 3179  
3262 3180  
3263 3181                                  if (!i_ddi_devi_attached(dip)) {
3264 3182                                          USB_DPRINTF_L2(DPRINT_MASK_USBA,
3265 3183                                              usba_log_handle,
3266 3184                                              "%s%d: leaking dev_data 0x%p",
3267 3185                                              ddi_driver_name(dip),
3268 3186                                              ddi_get_instance(dip),
3269 3187                                              (void *)dev_data);
3270 3188  
3271 3189                                          leaks++;
3272 3190  
3273 3191                                          mutex_exit(&usba_device->usb_mutex);
3274 3192                                          usb_free_dev_data(dip, dev_data);
3275 3193                                          mutex_enter(&usba_device->usb_mutex);
3276 3194                                  }
3277 3195  
3278 3196                                  entry = next;
3279 3197                          }
3280 3198                  }
3281 3199                  if (usba_device->usb_client_flags[iface] &
3282 3200                      USBA_CLIENT_FLAG_ATTACH) {
3283 3201                          dev_info_t *dip = usba_device->
3284 3202                              usb_client_attach_list[iface].dip;
3285 3203  
3286 3204                          USB_DPRINTF_L2(DPRINT_MASK_USBA,
3287 3205                              usba_log_handle,
3288 3206                              "%s%d: did no usb_client_detach",
3289 3207                              ddi_driver_name(dip), ddi_get_instance(dip));
3290 3208                          leaks++;
3291 3209  
3292 3210                          mutex_exit(&usba_device->usb_mutex);
3293 3211                          usb_client_detach(dip, NULL);
3294 3212                          mutex_enter(&usba_device->usb_mutex);
3295 3213  
3296 3214                          usba_device->
3297 3215                              usb_client_attach_list[iface].dip = NULL;
3298 3216  
3299 3217                          usba_device->usb_client_flags[iface] &=
3300 3218                              ~USBA_CLIENT_FLAG_ATTACH;
3301 3219  
3302 3220                  }
3303 3221                  if (usba_device->usb_client_flags[iface] &
3304 3222                      USBA_CLIENT_FLAG_EV_CBS) {
3305 3223                          dev_info_t *dip =
3306 3224                              usba_device->usb_client_ev_cb_list[iface].
3307 3225                              dip;
3308 3226                          usb_event_t *ev_data =
3309 3227                              usba_device->usb_client_ev_cb_list[iface].
3310 3228                              ev_data;
3311 3229  
3312 3230                          USB_DPRINTF_L2(DPRINT_MASK_USBA,
3313 3231                              usba_log_handle,
3314 3232                              "%s%d: did no usb_unregister_event_cbs",
3315 3233                              ddi_driver_name(dip), ddi_get_instance(dip));
3316 3234                          leaks++;
3317 3235  
3318 3236                          mutex_exit(&usba_device->usb_mutex);
3319 3237                          usb_unregister_event_cbs(dip, ev_data);
3320 3238                          mutex_enter(&usba_device->usb_mutex);
3321 3239  
3322 3240                          usba_device->usb_client_ev_cb_list[iface].
3323 3241                              dip = NULL;
3324 3242                          usba_device->usb_client_ev_cb_list[iface].
3325 3243                              ev_data = NULL;
3326 3244                          usba_device->usb_client_flags[iface] &=
3327 3245                              ~USBA_CLIENT_FLAG_EV_CBS;
3328 3246                  }
3329 3247          }
3330 3248          mutex_exit(&usba_device->usb_mutex);
3331 3249  
3332 3250          if (leaks) {
3333 3251                  USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
3334 3252                      "all %d leaks fixed", leaks);
3335 3253          }
3336 3254  }
  
    | 
      ↓ open down ↓ | 
    1849 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX