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