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