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