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