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