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