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