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