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