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