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