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