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