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 }