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