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