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