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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright 2019 Joyent, Inc. 25 */ 26 27 28 /* 29 * USBA: Solaris USB Architecture support 30 * 31 * Utility functions 32 */ 33 #define USBA_FRAMEWORK 34 #include <sys/usb/usba/usba_impl.h> 35 #include <sys/usb/usba/hcdi_impl.h> 36 #include <sys/strsun.h> 37 38 extern void usba_free_evdata(usba_evdata_t *); 39 40 static mblk_t *usba_get_cfg_cloud(dev_info_t *, usb_pipe_handle_t, int); 41 42 /* local functions */ 43 static int usba_sync_set_cfg(dev_info_t *, usba_ph_impl_t *, 44 usba_pipe_async_req_t *, usb_flags_t); 45 static int usba_sync_set_alt_if(dev_info_t *, usba_ph_impl_t *, 46 usba_pipe_async_req_t *, usb_flags_t); 47 static int usba_sync_clear_feature(dev_info_t *, usba_ph_impl_t *, 48 usba_pipe_async_req_t *, usb_flags_t); 49 50 /* 51 * Wrapper functions returning parsed standard descriptors without 52 * getting the config cloud first but by just providing the dip. 53 * 54 * The client can easily retrieve the device and config descriptor from 55 * the usb registration and no separate functions are provided 56 * 57 * These functions return failure if the full descriptor can not be 58 * retrieved. These functions will not access the device. 59 * The caller must allocate the buffer. 60 */ 61 62 /* 63 * usb_get_if_descr: 64 * Function to get the cooked interface descriptor 65 * This function will not access the device. 66 * 67 * Arguments: 68 * dip - pointer to devinfo of the client 69 * if_index - interface index 70 * alt_setting - alt interface setting 71 * descr - pointer to user allocated interface descr 72 * 73 * Return Values: 74 * USB_SUCCESS - descriptor is valid 75 * USB_FAILURE - full descriptor could not be retrieved 76 * USB_* - refer to usbai.h 77 */ 78 int 79 usb_get_if_descr(dev_info_t *dip, 80 uint_t if_index, 81 uint_t alt_setting, 82 usb_if_descr_t *descr) 83 { 84 uchar_t *usb_cfg; /* buf for config descriptor */ 85 size_t size, cfg_length; 86 87 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 88 "usb_get_if_descr: %s, index=0x%x, alt#=0x%x", 89 ddi_node_name(dip), if_index, alt_setting); 90 91 if ((dip == NULL) || (descr == NULL)) { 92 93 return (USB_INVALID_ARGS); 94 } 95 96 usb_cfg = usb_get_raw_cfg_data(dip, &cfg_length); 97 size = usb_parse_if_descr(usb_cfg, cfg_length, 98 if_index, /* interface index */ 99 alt_setting, /* alt interface index */ 100 descr, 101 USB_IF_DESCR_SIZE); 102 103 if (size != USB_IF_DESCR_SIZE) { 104 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 105 "parsing interface: size (%lu) != USB_IF_DESCR_SIZE (%d)", 106 size, USB_IF_DESCR_SIZE); 107 108 return (USB_FAILURE); 109 } 110 111 return (USB_SUCCESS); 112 } 113 114 115 /* 116 * usb_get_ep_descr: 117 * Function to get the cooked endpoint descriptor 118 * This function will not access the device. 119 * 120 * Arguments: 121 * dip - pointer to devinfo of the client 122 * if_index - interface index 123 * alt_setting - alternate interface setting 124 * endpoint_index - endpoint index 125 * descr - pointer to user allocated interface descr 126 * 127 * Return Values: 128 * USB_SUCCESS - descriptor is valid 129 * USB_FAILURE - full descriptor could not be retrieved 130 * USB_* - refer to usbai.h 131 */ 132 int 133 usb_get_ep_descr(dev_info_t *dip, 134 uint_t if_index, 135 uint_t alt_setting, 136 uint_t endpoint_index, 137 usb_ep_descr_t *descr) 138 { 139 uchar_t *usb_cfg; /* buf for config descriptor */ 140 size_t size, cfg_length; 141 142 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 143 "usb_get_ep_descr: %s, index=0x%x, alt#=0x%x", 144 ddi_node_name(dip), if_index, alt_setting); 145 146 if ((dip == NULL) || (descr == NULL)) { 147 148 return (USB_INVALID_ARGS); 149 } 150 151 usb_cfg = usb_get_raw_cfg_data(dip, &cfg_length); 152 size = usb_parse_ep_descr(usb_cfg, cfg_length, 153 if_index, /* interface index */ 154 alt_setting, /* alt interface index */ 155 endpoint_index, /* ep index */ 156 descr, USB_EP_DESCR_SIZE); 157 158 if (size != USB_EP_DESCR_SIZE) { 159 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 160 "parsing endpoint: size (%lu) != USB_EP_DESCR_SIZE (%d)", 161 size, USB_EP_DESCR_SIZE); 162 163 return (USB_FAILURE); 164 } 165 166 return (USB_SUCCESS); 167 } 168 169 170 /* 171 * usb_lookup_ep_data: 172 * usb_get_ep_data (deprecated): 173 * Function to get specific endpoint descriptor data 174 * This function will not access the device. 175 * 176 * Arguments: 177 * dip - pointer to dev info 178 * usb_client_dev_data_t - pointer to registration data 179 * interface - requested interface 180 * alternate - requested alternate 181 * skip - how many to skip 182 * type - endpoint type 183 * direction - endpoint direction or USB_DIR_DONT_CARE 184 * 185 * Return Values: 186 * NULL or an endpoint descriptor pointer 187 */ 188 usb_ep_data_t * 189 usb_lookup_ep_data(dev_info_t *dip, 190 usb_client_dev_data_t *dev_datap, 191 uint_t interface, 192 uint_t alternate, 193 uint_t skip, 194 uint_t type, 195 uint_t dir) 196 { 197 usb_alt_if_data_t *altif_data; 198 int i; 199 200 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 201 "usb_lookup_ep_data: " 202 "if=%d alt=%d skip=%d type=%d dir=%d", 203 interface, alternate, skip, type, dir); 204 205 if ((dip == NULL) || (dev_datap == NULL)) { 206 207 return (NULL); 208 } 209 210 altif_data = &dev_datap->dev_curr_cfg-> 211 cfg_if[interface].if_alt[alternate]; 212 213 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 214 "altif=0x%p n_ep=%d", (void *)altif_data, altif_data->altif_n_ep); 215 216 for (i = 0; i < altif_data->altif_n_ep; i++) { 217 usb_ep_descr_t *ept = &altif_data->altif_ep[i].ep_descr; 218 uint8_t ept_type = ept->bmAttributes & USB_EP_ATTR_MASK; 219 uint8_t ept_dir = ept->bEndpointAddress & USB_EP_DIR_MASK; 220 221 if (ept->bLength == 0) { 222 continue; 223 } 224 if ((ept_type == type) && 225 ((type == USB_EP_ATTR_CONTROL) || (dir == ept_dir))) { 226 227 if (skip-- == 0) { 228 USB_DPRINTF_L4(DPRINT_MASK_USBA, 229 usbai_log_handle, 230 "usb_get_ep_data: data=0x%p", 231 (void *)&altif_data->altif_ep[i]); 232 233 return (&altif_data->altif_ep[i]); 234 } 235 } 236 } 237 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 238 "usb_get_ep_data: returning NULL"); 239 240 return (NULL); 241 } 242 243 244 /*ARGSUSED*/ 245 usb_ep_data_t * 246 usb_get_ep_data(dev_info_t *dip, 247 usb_client_dev_data_t *dev_datap, 248 uint_t interface, 249 uint_t alternate, 250 uint_t type, 251 uint_t dir) 252 { 253 return (usb_lookup_ep_data(dip, dev_datap, interface, 254 alternate, 0, type, dir)); 255 } 256 257 258 /* 259 * usb_get_string_descr: 260 * Function to read the string descriptor 261 * This function will access the device and block. 262 * 263 * Arguments: 264 * dip - pointer to devinfo of the client 265 * langid - LANGID to read different LOCALEs 266 * index - index to the string 267 * buf - user provided buffer for string descriptor 268 * buflen - user provided length of the buffer 269 * 270 * Return Values: 271 * USB_SUCCESS - descriptor is valid 272 * USB_FAILURE - full descriptor could not be retrieved 273 * USB_* - refer to usbai.h 274 */ 275 int 276 usb_get_string_descr(dev_info_t *dip, 277 uint16_t langid, 278 uint8_t index, 279 char *buf, 280 size_t buflen) 281 { 282 mblk_t *data = NULL; 283 uint16_t length; 284 int rval; 285 usb_cr_t completion_reason; 286 size_t len; 287 usb_cb_flags_t cb_flags; 288 289 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 290 "usb_get_string_descr: %s, langid=0x%x index=0x%x", 291 ddi_node_name(dip), langid, index); 292 293 if ((dip == NULL) || (buf == NULL) || (buflen == 0) || (index == 0)) { 294 295 return (USB_INVALID_ARGS); 296 } 297 298 /* 299 * determine the length of the descriptor 300 */ 301 rval = usb_pipe_sync_ctrl_xfer(dip, 302 usba_get_dflt_pipe_handle(dip), 303 USB_DEV_REQ_DEV_TO_HOST, 304 USB_REQ_GET_DESCR, 305 (USB_DESCR_TYPE_STRING << 8) | (index & 0xff), 306 langid, 307 4, 308 &data, USB_ATTRS_SHORT_XFER_OK, 309 &completion_reason, 310 &cb_flags, USB_FLAGS_SLEEP); 311 312 if (rval != USB_SUCCESS) { 313 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 314 "rval=%d cr=%d", rval, completion_reason); 315 316 goto done; 317 } 318 if (MBLKL(data) == 0) { 319 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 320 "0 bytes received"); 321 322 goto done; 323 } 324 325 ASSERT(data); 326 length = *(data->b_rptr); 327 freemsg(data); 328 data = NULL; 329 330 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 331 "rval=%d, cr=%d, length=%d", rval, completion_reason, length); 332 333 /* 334 * if length is zero the next control request may fail. 335 * the HCD may not support a zero length control request 336 * and return an mblk_t which is NULL along with rval 337 * being USB_SUCCESS and "cr" being USB_CR_OK 338 */ 339 if (length < 2) { 340 rval = USB_FAILURE; 341 342 goto done; 343 } 344 345 rval = usb_pipe_sync_ctrl_xfer(dip, 346 usba_get_dflt_pipe_handle(dip), 347 USB_DEV_REQ_DEV_TO_HOST, 348 USB_REQ_GET_DESCR, 349 (USB_DESCR_TYPE_STRING << 8) | (index & 0xff), 350 langid, 351 length, 352 &data, USB_ATTRS_SHORT_XFER_OK, 353 &completion_reason, 354 &cb_flags, USB_FLAGS_SLEEP); 355 356 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 357 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 358 359 if ((data == NULL) || (rval != USB_SUCCESS)) { 360 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 361 "failed to get string descriptor (rval=%d cr=%d)", 362 rval, completion_reason); 363 364 goto done; 365 } 366 367 if ((length = MBLKL(data)) != 0) { 368 len = usba_ascii_string_descr(data->b_rptr, length, buf, 369 buflen); 370 USB_DPRINTF_L4(DPRINT_MASK_USBA, 371 usbai_log_handle, "buf=%s buflen=%lu", buf, len); 372 373 ASSERT(len <= buflen); 374 } else { 375 rval = USB_FAILURE; 376 } 377 done: 378 freemsg(data); 379 380 return (rval); 381 } 382 383 384 /* 385 * usb_get_dev_descr: 386 * utility function to get device descriptor from usba_device 387 * 388 * Arguments: 389 * dip - pointer to devinfo of the client 390 * 391 * Return Values: 392 * usb_dev_descr - device descriptor or NULL 393 */ 394 usb_dev_descr_t * 395 usb_get_dev_descr(dev_info_t *dip) 396 { 397 usba_device_t *usba_device; 398 usb_dev_descr_t *usb_dev_descr = NULL; 399 400 if (dip) { 401 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 402 "usb_get_dev_descr: %s", ddi_node_name(dip)); 403 404 usba_device = usba_get_usba_device(dip); 405 mutex_enter(&usba_device->usb_mutex); 406 usb_dev_descr = usba_device->usb_dev_descr; 407 mutex_exit(&usba_device->usb_mutex); 408 } 409 410 return (usb_dev_descr); 411 } 412 413 414 /* 415 * usb_get_raw_cfg_data: 416 * utility function to get raw config descriptor from usba_device 417 * 418 * Arguments: 419 * dip - pointer to devinfo of the client 420 * length - pointer to copy the cfg length 421 * 422 * Return Values: 423 * usb_cfg - raw config descriptor 424 */ 425 uchar_t * 426 usb_get_raw_cfg_data(dev_info_t *dip, size_t *length) 427 { 428 usba_device_t *usba_device; 429 uchar_t *usb_cfg; 430 431 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 432 "usb_get_raw_cfg_data: %s", ddi_node_name(dip)); 433 434 if ((dip == NULL) || (length == NULL)) { 435 436 return (NULL); 437 } 438 439 usba_device = usba_get_usba_device(dip); 440 441 mutex_enter(&usba_device->usb_mutex); 442 usb_cfg = usba_device->usb_cfg; 443 *length = usba_device->usb_cfg_length; 444 mutex_exit(&usba_device->usb_mutex); 445 446 return (usb_cfg); 447 } 448 449 450 /* 451 * usb_get_addr: 452 * utility function to return current usb address, mostly 453 * for debugging purposes 454 * 455 * Arguments: 456 * dip - pointer to devinfo of the client 457 * 458 * Return Values: 459 * address - USB Device Address 460 */ 461 int 462 usb_get_addr(dev_info_t *dip) 463 { 464 int address = 0; 465 466 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 467 "usb_get_addr: %s", ddi_node_name(dip)); 468 469 if (dip) { 470 usba_device_t *usba_device = usba_get_usba_device(dip); 471 472 mutex_enter(&usba_device->usb_mutex); 473 address = usba_device->usb_addr; 474 mutex_exit(&usba_device->usb_mutex); 475 } 476 477 return (address); 478 } 479 480 481 /* 482 * usb_set_cfg(): 483 * set configuration, use with caution (issues USB_REQ_SET_CONFIG) 484 * Changing configuration will fail if pipes are still open or when 485 * invoked from a driver bound to an interface on a composite device. 486 * 487 * This function will access the device and block 488 * 489 * Arguments: 490 * dip - pointer to devinfo of the client 491 * cfg_index - config index 492 * cfg_value - config value to be set 493 * flags - USB_FLAGS_SLEEP: 494 * wait for completion 495 * cb - if USB_FLAGS_SLEEP has not been specified 496 * this callback function will be called on 497 * completion. This callback may be NULL 498 * and no notification of completion will then 499 * be provided. 500 * cb_arg - 2nd argument to callback function. 501 * 502 * Return Values: 503 * USB_SUCCESS: - new configuration was set 504 * USB_FAILURE: - new configuration could not be set 505 * USB_BUSY: - some pipes were open or there were children 506 * USB_* - refer to usbai.h 507 */ 508 int 509 usb_set_cfg(dev_info_t *dip, 510 uint_t cfg_index, 511 usb_flags_t usb_flags, 512 void (*cb)( 513 usb_pipe_handle_t ph, 514 usb_opaque_t arg, 515 int rval, 516 usb_cb_flags_t flags), 517 usb_opaque_t cb_arg) 518 { 519 usb_pipe_handle_t ph; 520 521 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 522 "usb_set_cfg: %s%d, cfg_index = 0x%x, uf = 0x%x", 523 ddi_driver_name(dip), ddi_get_instance(dip), cfg_index, 524 usb_flags); 525 526 if (dip == NULL) { 527 528 return (USB_INVALID_ARGS); 529 } 530 531 if ((usb_flags & USB_FLAGS_SLEEP) && servicing_interrupt()) { 532 533 return (USB_INVALID_CONTEXT); 534 } 535 536 if (!usb_owns_device(dip)) { 537 538 return (USB_INVALID_PERM); 539 } 540 541 ph = usba_get_dflt_pipe_handle(dip); 542 if (usba_hold_ph_data(ph) == NULL) { 543 544 return (USB_INVALID_PIPE); 545 } 546 547 return (usba_pipe_setup_func_call(dip, 548 usba_sync_set_cfg, (usba_ph_impl_t *)ph, 549 (usb_opaque_t)((uintptr_t)cfg_index), usb_flags, cb, cb_arg)); 550 } 551 552 553 static int 554 usba_sync_set_cfg(dev_info_t *dip, 555 usba_ph_impl_t *ph_impl, 556 usba_pipe_async_req_t *request, 557 usb_flags_t flags) 558 { 559 int rval; 560 usb_cr_t completion_reason; 561 usb_cb_flags_t cb_flags; 562 usba_device_t *usba_device; 563 int i, ph_open_cnt; 564 uint_t cfg_index = (uint_t)((uintptr_t)(request->arg)); 565 size_t size; 566 usb_cfg_descr_t confdescr; 567 dev_info_t *pdip; 568 569 usba_device = usba_get_usba_device(dip); 570 571 /* 572 * default pipe is still open 573 * all other pipes should be closed 574 */ 575 for (ph_open_cnt = 0, i = 1; i < USBA_N_ENDPOINTS; i++) { 576 if (usba_device->usb_ph_list[i].usba_ph_data) { 577 ph_open_cnt++; 578 break; 579 } 580 } 581 582 if (ph_open_cnt || ddi_get_child(dip)) { 583 usba_release_ph_data(ph_impl); 584 585 return (USB_BUSY); 586 } 587 588 /* 589 * check if the configuration meets the 590 * power budget requirement 591 */ 592 if (usba_is_root_hub(dip)) { 593 /* 594 * root hub should never be multi-configured. 595 * the code is here just to ensure 596 */ 597 usba_release_ph_data(ph_impl); 598 599 return (USB_FAILURE); 600 } 601 pdip = ddi_get_parent(dip); 602 603 /* 604 * increase the power budget value back to the unconfigured 605 * state to eliminate the influence of the old configuration 606 * before checking the new configuration; but remember to 607 * make a decrement before leaving this routine to restore 608 * the power consumption state of the device no matter it 609 * is in the new or old configuration 610 */ 611 usba_hubdi_incr_power_budget(pdip, usba_device); 612 613 if ((usba_hubdi_check_power_budget(pdip, usba_device, 614 cfg_index)) != USB_SUCCESS) { 615 usba_hubdi_decr_power_budget(pdip, usba_device); 616 617 usba_release_ph_data(ph_impl); 618 619 return (USB_FAILURE); 620 } 621 622 size = usb_parse_cfg_descr(usba_device->usb_cfg_array[cfg_index], 623 USB_CFG_DESCR_SIZE, &confdescr, USB_CFG_DESCR_SIZE); 624 625 /* hubdi should ensure that this descriptor is correct */ 626 ASSERT(size == USB_CFG_DESCR_SIZE); 627 628 /* set the configuration */ 629 rval = usb_pipe_sync_ctrl_xfer(dip, (usb_pipe_handle_t)ph_impl, 630 USB_DEV_REQ_HOST_TO_DEV, 631 USB_REQ_SET_CFG, 632 confdescr.bConfigurationValue, 633 0, 634 0, 635 NULL, 0, 636 &completion_reason, 637 &cb_flags, flags | USBA_FLAGS_PRIVILEGED | USB_FLAGS_SLEEP); 638 639 if (rval == USB_SUCCESS) { 640 mutex_enter(&usba_device->usb_mutex); 641 usba_device->usb_cfg_value = confdescr.bConfigurationValue; 642 usba_device->usb_active_cfg_ndx = cfg_index; 643 usba_device->usb_cfg = usba_device->usb_cfg_array[cfg_index]; 644 usba_device->usb_cfg_length = confdescr.wTotalLength; 645 mutex_exit(&usba_device->usb_mutex); 646 647 /* update the configuration property */ 648 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 649 "configuration#", usba_device->usb_cfg_value); 650 } 651 652 /* 653 * usba_device->usb_cfg always stores current configuration 654 * descriptor no matter SET_CFG request succeeded or not, 655 * so usba_hubdi_decr_power_budget can be done regardless 656 * of rval above 657 */ 658 usba_hubdi_decr_power_budget(pdip, usba_device); 659 660 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 661 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 662 663 usba_release_ph_data(ph_impl); 664 665 return (rval); 666 } 667 668 669 670 /* 671 * usb_get_cfg(): 672 * get configuration value 673 * 674 * Arguments: 675 * dip - pointer to devinfo of the client 676 * cfg_value - current config value 677 * flags - none, always blocks 678 * 679 * Return Values: 680 * USB_SUCCESS: - config value was retrieved 681 * USB_FAILURE: - config value could not be retrieved 682 * USB_* - refer to usbai.h 683 */ 684 int 685 usb_get_cfg(dev_info_t *dip, 686 uint_t *cfgval, 687 usb_flags_t flags) 688 { 689 int rval; 690 usb_cr_t completion_reason; 691 mblk_t *data = NULL; 692 usb_cb_flags_t cb_flags; 693 usb_pipe_handle_t ph; 694 695 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 696 "usb_get_cfg: %s uf = 0x%x", ddi_node_name(dip), flags); 697 698 if ((cfgval == NULL) || (dip == NULL)) { 699 700 return (USB_INVALID_ARGS); 701 } 702 703 ph = usba_get_dflt_pipe_handle(dip); 704 705 /* 706 * get the cfg value 707 */ 708 rval = usb_pipe_sync_ctrl_xfer(dip, ph, 709 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_DEV, 710 USB_REQ_GET_CFG, 711 0, 712 0, 713 1, /* returns one byte of data */ 714 &data, 0, 715 &completion_reason, 716 &cb_flags, flags); 717 718 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 719 "rval=%d cb_flags=%d cr=%d", rval, cb_flags, completion_reason); 720 721 if ((rval == USB_SUCCESS) && data && 722 (MBLKL(data) == 1)) { 723 *cfgval = *(data->b_rptr); 724 } else { 725 *cfgval = 1; 726 if (rval == USB_SUCCESS) { 727 rval = USB_FAILURE; 728 } 729 } 730 731 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 732 "usb_get_cfg: %s cfgval=%d", ddi_node_name(dip), *cfgval); 733 734 freemsg(data); 735 736 return (rval); 737 } 738 739 740 /* 741 * usb_get_current_cfgidx: 742 * get current current config index 743 */ 744 uint_t 745 usb_get_current_cfgidx(dev_info_t *dip) 746 { 747 usba_device_t *usba_device = usba_get_usba_device(dip); 748 uint_t ndx; 749 750 mutex_enter(&usba_device->usb_mutex); 751 ndx = usba_device->usb_active_cfg_ndx; 752 mutex_exit(&usba_device->usb_mutex); 753 754 return (ndx); 755 } 756 757 758 /* 759 * usb_get_if_number: 760 * get usb interface number of current OS device node. 761 * 762 * Arguments: 763 * dip - pointer to devinfo of the client 764 * 765 * Return Values: 766 * USB_COMBINED_NODE if the driver is responsible for the entire 767 * device and this dip doesn't correspond to a device node. 768 * USB_DEVICE_NODE if the driver is responsible for the entire device 769 * and this dip corresponds to a device node. 770 * interface number: otherwise. 771 */ 772 int 773 usb_get_if_number(dev_info_t *dip) 774 { 775 int interface_num; 776 usba_device_t *usba_device = usba_get_usba_device(dip); 777 usb_dev_descr_t *usb_dev_descr; 778 779 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 780 "usb_get_if_number: dip = 0x%p", (void *)dip); 781 782 /* not quite right but we can't return a negative return value */ 783 if (dip == NULL) { 784 785 return (0); 786 } 787 788 if (usba_device) { 789 usb_dev_descr = usba_device->usb_dev_descr; 790 } else { 791 792 return (0); 793 } 794 795 interface_num = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 796 DDI_PROP_DONTPASS, "interface", USB_COMBINED_NODE); 797 798 if (interface_num == USB_COMBINED_NODE) { 799 if (!(((usb_dev_descr->bDeviceClass == USB_CLASS_HUB) || 800 (usb_dev_descr->bDeviceClass == 0)) && 801 (usba_device->usb_n_cfgs == 1) && 802 (usba_device->usb_n_ifs == 1))) { 803 interface_num = USB_DEVICE_NODE; 804 } 805 } 806 807 return (interface_num); 808 } 809 810 811 boolean_t 812 usb_owns_device(dev_info_t *dip) 813 { 814 int interface_num = usb_get_if_number(dip); 815 816 return (interface_num < 0 ? B_TRUE : B_FALSE); 817 } 818 819 820 /* check whether the interface is in this interface association */ 821 boolean_t 822 usba_check_if_in_ia(dev_info_t *dip, int n_if) 823 { 824 int first_if, if_count; 825 826 first_if = usb_get_if_number(dip); 827 if_count = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 828 DDI_PROP_DONTPASS, "interface-count", -1); 829 if_count += first_if; 830 831 return ((n_if >= first_if && n_if < if_count) ? B_TRUE : B_FALSE); 832 } 833 834 835 uint8_t 836 usba_get_ifno(dev_info_t *dip) 837 { 838 int interface_num = usb_get_if_number(dip); 839 840 return (uint8_t)(interface_num < 0 ? 0 : interface_num); 841 } 842 843 844 /* 845 * usb_set_alt_if: 846 * set the alternate interface number. Issues USB_REQ_SET_IF 847 * This function will access the device 848 * 849 * Arguments: 850 * dip - pointer to devinfo of the client 851 * if_number - interface number 852 * alt_number - alternate interface number 853 * flags - USB_FLAGS_SLEEP: 854 * wait for completion 855 * cb - if USB_FLAGS_SLEEP has not been specified 856 * this callback function will be called on 857 * completion. This callback may be NULL 858 * and no notification of completion will then 859 * be provided. 860 * cb_arg - 2nd argument to callback function. 861 * 862 * 863 * return values: 864 * USB_SUCCESS - alternate was set 865 * USB_FAILURE - alternate could not be set because pipes 866 * were still open or some access error occurred 867 * USB_* - refer to usbai.h 868 * 869 * Note: 870 * we can't easily check if all pipes to endpoints for this interface 871 * are closed since we don't have a map of which endpoints belong 872 * to which interface. If we had this map, we would need to update 873 * this on each alternative or configuration switch 874 */ 875 int 876 usb_set_alt_if(dev_info_t *dip, 877 uint_t interface, 878 uint_t alt_number, 879 usb_flags_t usb_flags, 880 void (*cb)( 881 usb_pipe_handle_t ph, 882 usb_opaque_t arg, 883 int rval, 884 usb_cb_flags_t flags), 885 usb_opaque_t cb_arg) 886 { 887 usb_pipe_handle_t ph; 888 889 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 890 "usb_set_alt_if: %s%d, if = %d alt = %d, uf = 0x%x", 891 ddi_driver_name(dip), ddi_get_instance(dip), 892 interface, alt_number, usb_flags); 893 894 if (dip == NULL) { 895 896 return (USB_INVALID_ARGS); 897 } 898 899 if ((usb_flags & USB_FLAGS_SLEEP) && servicing_interrupt()) { 900 901 return (USB_INVALID_CONTEXT); 902 } 903 904 ph = usba_get_dflt_pipe_handle(dip); 905 if (usba_hold_ph_data(ph) == NULL) { 906 907 return (USB_INVALID_PIPE); 908 } 909 910 return (usba_pipe_setup_func_call(dip, 911 usba_sync_set_alt_if, (usba_ph_impl_t *)ph, 912 (usb_opaque_t)((uintptr_t)((interface << 8) | alt_number)), 913 usb_flags, cb, cb_arg)); 914 } 915 916 917 static int 918 usba_sync_set_alt_if(dev_info_t *dip, 919 usba_ph_impl_t *ph_impl, 920 usba_pipe_async_req_t *request, 921 usb_flags_t flags) 922 { 923 int rval; 924 usb_cr_t completion_reason; 925 usb_cb_flags_t cb_flags; 926 usb_opaque_t arg = request->arg; 927 int interface = ((uintptr_t)arg >> 8) & 0xff; 928 int alt_number = (uintptr_t)arg & 0xff; 929 usba_pipe_handle_data_t *ph_data = usba_get_ph_data( 930 (usb_pipe_handle_t)ph_impl); 931 932 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 933 "usb_set_alt_if: %s, interface#=0x%x, alt#=0x%x, " 934 "uf=0x%x", ddi_node_name(dip), interface, 935 alt_number, flags); 936 937 /* if we don't own the device, we must own the interface or ia */ 938 if (!usb_owns_device(dip) && !usba_check_if_in_ia(dip, interface) && 939 (interface != usb_get_if_number(dip))) { 940 usba_release_ph_data(ph_data->p_ph_impl); 941 942 return (USB_INVALID_PERM); 943 } 944 945 /* set the alternate setting */ 946 rval = usb_pipe_sync_ctrl_xfer(dip, usba_get_dflt_pipe_handle(dip), 947 USB_DEV_REQ_HOST_TO_DEV | USB_DEV_REQ_RCPT_IF, 948 USB_REQ_SET_IF, 949 alt_number, 950 interface, 951 0, 952 NULL, 0, 953 &completion_reason, 954 &cb_flags, flags | USB_FLAGS_SLEEP); 955 956 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 957 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 958 959 usba_release_ph_data(ph_data->p_ph_impl); 960 961 return (rval); 962 } 963 964 965 /* 966 * usb_get_alt_if: 967 * get the alternate interface number. Issues USB_REQ_GET_IF 968 * This function will access the device and block 969 * 970 * Arguments: 971 * dip - pointer to devinfo of the client 972 * if_number - interface number 973 * alt_number - alternate interface number 974 * flags - none but USB_FLAGS_SLEEP may be passed 975 * 976 * return values: 977 * USB_SUCCESS: alternate was set 978 * USB_FAILURE: alternate could not be set because pipes 979 * were still open or some access error occurred 980 */ 981 int 982 usb_get_alt_if(dev_info_t *dip, 983 uint_t if_number, 984 uint_t *alt_number, 985 usb_flags_t flags) 986 { 987 int rval; 988 usb_cr_t completion_reason; 989 mblk_t *data = NULL; 990 usb_cb_flags_t cb_flags; 991 usb_pipe_handle_t ph; 992 993 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 994 "usb_get_alt_if: %s, interface# = 0x%x, altp = 0x%p, " 995 "uf = 0x%x", ddi_node_name(dip), if_number, 996 (void *)alt_number, flags); 997 998 if ((alt_number == NULL) || (dip == NULL)) { 999 1000 return (USB_INVALID_ARGS); 1001 } 1002 1003 ph = usba_get_dflt_pipe_handle(dip); 1004 1005 /* 1006 * get the alternate setting 1007 */ 1008 rval = usb_pipe_sync_ctrl_xfer(dip, ph, 1009 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_IF, 1010 USB_REQ_GET_IF, 1011 0, 1012 if_number, 1013 1, /* returns one byte of data */ 1014 &data, 0, 1015 &completion_reason, 1016 &cb_flags, flags); 1017 1018 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1019 "rval=%d cb_flags=%d cr=%d", rval, cb_flags, completion_reason); 1020 1021 if ((rval == USB_SUCCESS) && data && 1022 (MBLKL(data) == 1)) { 1023 *alt_number = *(data->b_rptr); 1024 } else { 1025 *alt_number = 0; 1026 if (rval == USB_SUCCESS) { 1027 rval = USB_FAILURE; 1028 } 1029 } 1030 1031 freemsg(data); 1032 1033 return (rval); 1034 } 1035 1036 1037 /* 1038 * usba_get_cfg_cloud: 1039 * Get descriptor cloud for a given configuration. 1040 * 1041 * Arguments: 1042 * dip - pointer to devinfo of the client 1043 * default_ph - default pipe handle 1044 * cfg - which configuration to retrieve raw cloud of 1045 * 1046 * Returns: 1047 * on success: mblock containing the raw data. Caller must free. 1048 * on failure: NULL 1049 */ 1050 static mblk_t * 1051 usba_get_cfg_cloud(dev_info_t *dip, usb_pipe_handle_t default_ph, int cfg) 1052 { 1053 usb_cr_t completion_reason; 1054 usb_cb_flags_t cb_flags; 1055 usb_cfg_descr_t cfg_descr; 1056 mblk_t *pdata = NULL; 1057 1058 if (usb_pipe_sync_ctrl_xfer(dip, default_ph, 1059 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_TYPE_STANDARD, 1060 USB_REQ_GET_DESCR, 1061 USB_DESCR_TYPE_SETUP_CFG | cfg, 1062 0, 1063 USB_CFG_DESCR_SIZE, 1064 &pdata, 1065 0, 1066 &completion_reason, 1067 &cb_flags, 1068 0) != USB_SUCCESS) { 1069 1070 freemsg(pdata); 1071 1072 return (NULL); 1073 } 1074 1075 (void) usb_parse_cfg_descr(pdata->b_rptr, 1076 MBLKL(pdata), &cfg_descr, USB_CFG_DESCR_SIZE); 1077 freemsg(pdata); 1078 pdata = NULL; 1079 1080 if (usb_pipe_sync_ctrl_xfer(dip, default_ph, 1081 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_TYPE_STANDARD, 1082 USB_REQ_GET_DESCR, 1083 USB_DESCR_TYPE_SETUP_CFG | cfg, 1084 0, 1085 cfg_descr.wTotalLength, 1086 &pdata, 1087 0, 1088 &completion_reason, 1089 &cb_flags, 1090 0) != USB_SUCCESS) { 1091 1092 freemsg(pdata); 1093 1094 return (NULL); 1095 } 1096 1097 return (pdata); 1098 } 1099 1100 /* 1101 * usb_check_same_device: 1102 * Check if the device connected to the port is the same as 1103 * the previous device that was in the port. The previous device is 1104 * represented by the dip on record for the port. Print a message 1105 * if the device is different. If device_string arg is not NULL, it is 1106 * included in the message. Can block. 1107 * 1108 * Arguments: 1109 * dip - pointer to devinfo of the client 1110 * log_handle - handle to which messages are logged 1111 * log_level - one of USB_LOG_* 1112 * log_mask - logging mask 1113 * check_mask - one mask containing things to check: 1114 * USB_CHK_BASIC: empty mask; 1115 * these checks are always done. 1116 * USB_CHK_VIDPID: 1117 * check vid, pid only. 1118 * USB_CHK_SERIAL: check match on device 1119 * serial number. 1120 * USB_CHK_CFG: check all raw config 1121 * clouds for a match. 1122 * NOTE: descr length and content always checked 1123 * device_string - Device string to appear in error message 1124 * 1125 * return values: 1126 * USB_SUCCESS: same device 1127 * USB_INVALID_VERSION not same device 1128 * USB_FAILURE: Failure processing request 1129 * USB_INVALID_ARG: dip is invalid 1130 */ 1131 int 1132 usb_check_same_device(dev_info_t *dip, usb_log_handle_t log_handle, 1133 int log_level, int log_mask, uint_t check_mask, char *device_string) 1134 { 1135 usb_dev_descr_t usb_dev_descr; 1136 usba_device_t *usba_device; 1137 mblk_t *pdata = NULL; 1138 uint16_t length; 1139 int rval; 1140 char *buf; 1141 usb_cr_t completion_reason; 1142 usb_cb_flags_t cb_flags; 1143 boolean_t match = B_TRUE; 1144 usb_pipe_handle_t def_ph; 1145 1146 if (dip == NULL) { 1147 1148 return (USB_INVALID_ARGS); 1149 } 1150 1151 usba_device = usba_get_usba_device(dip); 1152 length = usba_device->usb_dev_descr->bLength; 1153 def_ph = usba_get_dflt_pipe_handle(dip); 1154 ASSERT(def_ph); 1155 1156 /* get the "new" device descriptor */ 1157 rval = usb_pipe_sync_ctrl_xfer(dip, def_ph, 1158 USB_DEV_REQ_DEV_TO_HOST | 1159 USB_DEV_REQ_TYPE_STANDARD, 1160 USB_REQ_GET_DESCR, /* bRequest */ 1161 USB_DESCR_TYPE_SETUP_DEV, /* wValue */ 1162 0, /* wIndex */ 1163 length, /* wLength */ 1164 &pdata, 0, 1165 &completion_reason, 1166 &cb_flags, USB_FLAGS_SLEEP); 1167 1168 if (rval != USB_SUCCESS) { 1169 if (!((completion_reason == USB_CR_DATA_OVERRUN) && (pdata))) { 1170 USB_DPRINTF_L3(DPRINT_MASK_USBA, usbai_log_handle, 1171 "getting device descriptor failed (%d)", rval); 1172 freemsg(pdata); 1173 1174 return (USB_FAILURE); 1175 } 1176 } 1177 1178 ASSERT(pdata != NULL); 1179 1180 (void) usb_parse_dev_descr(pdata->b_rptr, 1181 MBLKL(pdata), &usb_dev_descr, 1182 sizeof (usb_dev_descr_t)); 1183 1184 freemsg(pdata); 1185 pdata = NULL; 1186 1187 /* Always check the device descriptor length. */ 1188 if (usb_dev_descr.bLength != length) { 1189 match = B_FALSE; 1190 } 1191 1192 if ((match == B_TRUE) && (check_mask & USB_CHK_VIDPID)) { 1193 match = (usba_device->usb_dev_descr->idVendor == 1194 usb_dev_descr.idVendor) && 1195 (usba_device->usb_dev_descr->idProduct == 1196 usb_dev_descr.idProduct); 1197 } else if (bcmp((char *)usba_device->usb_dev_descr, 1198 (char *)&usb_dev_descr, length) != 0) { 1199 match = B_FALSE; 1200 } 1201 1202 /* if requested & this device has a serial number check and compare */ 1203 if ((match == B_TRUE) && ((check_mask & USB_CHK_SERIAL) != 0) && 1204 (usba_device->usb_serialno_str != NULL)) { 1205 buf = kmem_alloc(USB_MAXSTRINGLEN, KM_SLEEP); 1206 if (usb_get_string_descr(dip, USB_LANG_ID, 1207 usb_dev_descr.iSerialNumber, buf, 1208 USB_MAXSTRINGLEN) == USB_SUCCESS) { 1209 match = 1210 (strcmp(buf, usba_device->usb_serialno_str) == 0); 1211 } 1212 kmem_free(buf, USB_MAXSTRINGLEN); 1213 } 1214 1215 if ((match == B_TRUE) && (check_mask & USB_CHK_CFG)) { 1216 1217 uint8_t num_cfgs = usb_dev_descr.bNumConfigurations; 1218 uint8_t cfg; 1219 mblk_t *cloud; 1220 1221 for (cfg = 0; cfg < num_cfgs; cfg++) { 1222 cloud = usba_get_cfg_cloud(dip, def_ph, cfg); 1223 if (cloud == NULL) { 1224 USB_DPRINTF_L3(DPRINT_MASK_USBA, 1225 usbai_log_handle, 1226 "Could not retrieve config cloud for " 1227 "comparison"); 1228 break; 1229 } 1230 1231 if (bcmp((char *)cloud->b_rptr, 1232 usba_device->usb_cfg_array[cfg], 1233 MBLKL(cloud)) != 0) { 1234 freemsg(cloud); 1235 break; 1236 } 1237 1238 freemsg(cloud); 1239 } 1240 if (cfg != num_cfgs) { 1241 match = B_FALSE; 1242 } 1243 } 1244 1245 if (match == B_FALSE) { 1246 boolean_t allocated_here = (device_string == NULL); 1247 if (allocated_here) { 1248 device_string = 1249 kmem_zalloc(USB_MAXSTRINGLEN, USB_FLAGS_SLEEP); 1250 (void) usba_get_mfg_prod_sn_str(dip, device_string, 1251 USB_MAXSTRINGLEN); 1252 } 1253 if (device_string[0] != '\0') { 1254 (void) usb_log(log_handle, log_level, log_mask, 1255 "Cannot access %s. Please reconnect.", 1256 device_string); 1257 } else { 1258 (void) usb_log(log_handle, log_level, log_mask, 1259 "Device is not identical to the " 1260 "previous one this port.\n" 1261 "Please disconnect and reconnect"); 1262 } 1263 if (allocated_here) { 1264 kmem_free(device_string, USB_MAXSTRINGLEN); 1265 } 1266 1267 return (USB_INVALID_VERSION); 1268 } 1269 1270 return (USB_SUCCESS); 1271 } 1272 1273 1274 /* 1275 * usb_pipe_get_state: 1276 * Return the state of the pipe 1277 * 1278 * Arguments: 1279 * pipe_handle - pipe_handle pointer 1280 * pipe_state - pointer to copy pipe state to 1281 * flags: 1282 * not used other than to check context 1283 * 1284 * Return Values: 1285 * USB_SUCCESS - port state returned 1286 * USB_* - refer to usbai.h 1287 */ 1288 int 1289 usb_pipe_get_state(usb_pipe_handle_t pipe_handle, 1290 usb_pipe_state_t *pipe_state, 1291 usb_flags_t usb_flags) 1292 { 1293 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1294 1295 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1296 "usb_pipe_get_state: ph_data=0x%p uf=0x%x", (void *)ph_data, 1297 usb_flags); 1298 1299 if (pipe_state == NULL) { 1300 if (ph_data) { 1301 usba_release_ph_data(ph_data->p_ph_impl); 1302 } 1303 1304 return (USB_INVALID_ARGS); 1305 } 1306 1307 if (ph_data == NULL) { 1308 *pipe_state = USB_PIPE_STATE_CLOSED; 1309 1310 return (USB_SUCCESS); 1311 } 1312 1313 mutex_enter(&ph_data->p_mutex); 1314 *pipe_state = usba_get_ph_state(ph_data); 1315 mutex_exit(&ph_data->p_mutex); 1316 1317 usba_release_ph_data(ph_data->p_ph_impl); 1318 1319 return (USB_SUCCESS); 1320 } 1321 1322 1323 /* 1324 * usba_pipe_get_policy: 1325 * Return a pipe's policy 1326 * 1327 * Arguments: 1328 * pipe_handle - pipe_handle pointer 1329 * 1330 * Return Values: 1331 * On success: the pipe's policy 1332 * On failure: NULL 1333 */ 1334 usb_pipe_policy_t 1335 *usba_pipe_get_policy(usb_pipe_handle_t pipe_handle) 1336 { 1337 usb_pipe_policy_t *pp = NULL; 1338 1339 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1340 1341 if (ph_data) { 1342 pp = &ph_data->p_policy; 1343 1344 usba_release_ph_data(ph_data->p_ph_impl); 1345 } 1346 1347 return (pp); 1348 } 1349 1350 1351 /* 1352 * usb_ep_num: 1353 * Return the endpoint number for a given pipe handle 1354 * 1355 * Arguments: 1356 * pipe_handle - pipe_handle pointer 1357 * 1358 * Return Values: 1359 * endpoint number 1360 */ 1361 int 1362 usb_ep_num(usb_pipe_handle_t pipe_handle) 1363 { 1364 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1365 int ep_num; 1366 1367 if (ph_data == NULL) { 1368 1369 return (USB_INVALID_PIPE); 1370 } 1371 1372 mutex_enter(&ph_data->p_mutex); 1373 ep_num = ph_data->p_ep.bEndpointAddress & USB_EP_NUM_MASK; 1374 mutex_exit(&ph_data->p_mutex); 1375 1376 usba_release_ph_data(ph_data->p_ph_impl); 1377 1378 return (ep_num); 1379 } 1380 1381 1382 /* 1383 * usb_get_status 1384 * Issues USB_REQ_GET_STATUS to device/endpoint/interface 1385 * and report in "status" arg. 1386 * 1387 * status reported for a "device" is 1388 * RemoteWakeup enabled 1389 * SelfPowered device? 1390 * 1391 * status reported for an "interface" is NONE. 1392 * status reported for an "endpoint" is 1393 * HALT set (device STALLED?) 1394 * 1395 * Arguments: 1396 * dip - pointer to devinfo of the client 1397 * ph - pipe handle 1398 * type - bmRequestType to be used 1399 * what - 0 for device, otherwise interface or ep number 1400 * status - user supplied pointer for storing the status 1401 * flags - USB_FLAGS_SLEEP (mandatory) 1402 * 1403 * Return Values: 1404 * valid usb_status_t or USB_FAILURE 1405 */ 1406 int 1407 usb_get_status(dev_info_t *dip, 1408 usb_pipe_handle_t ph, 1409 uint_t type, /* bmRequestType */ 1410 uint_t what, /* 0, interface, ept number */ 1411 uint16_t *status, 1412 usb_flags_t flags) 1413 { 1414 int rval; 1415 usb_cr_t completion_reason; 1416 mblk_t *data = NULL; 1417 usb_cb_flags_t cb_flags; 1418 1419 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1420 "usb_get_status: type = 0x%x, what = 0x%x, uf = 0x%x", 1421 type, what, flags); 1422 1423 if ((status == NULL) || (dip == NULL)) { 1424 1425 return (USB_INVALID_ARGS); 1426 } 1427 if (ph == NULL) { 1428 1429 return (USB_INVALID_PIPE); 1430 } 1431 1432 type |= USB_DEV_REQ_DEV_TO_HOST; 1433 1434 /* get the status */ 1435 rval = usb_pipe_sync_ctrl_xfer(dip, ph, 1436 type, 1437 USB_REQ_GET_STATUS, 1438 0, 1439 what, 1440 USB_GET_STATUS_LEN, /* status is fixed 2 bytes long */ 1441 &data, 0, 1442 &completion_reason, &cb_flags, flags); 1443 1444 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1445 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 1446 1447 if ((rval == USB_SUCCESS) && data && 1448 (MBLKL(data) == USB_GET_STATUS_LEN)) { 1449 *status = (*(data->b_rptr + 1) << 8) | *(data->b_rptr); 1450 } else { 1451 *status = 0; 1452 if (rval == USB_SUCCESS) { 1453 rval = USB_FAILURE; 1454 } 1455 } 1456 1457 freemsg(data); 1458 1459 return (rval); 1460 } 1461 1462 1463 /* 1464 * usb_clear_feature: 1465 * Issue USB_REQ_CLEAR_FEATURE to endpoint/device/interface 1466 * 1467 * Arguments: 1468 * dip - pointer to devinfo of the client 1469 * ph - pipe handle pointer 1470 * type - bmRequestType to be used 1471 * feature - feature to be cleared 1472 * what - 0 for device, otherwise interface or ep number 1473 * flags - none (but will sleep) 1474 * 1475 * Return Values: 1476 * USB_SUCCESS - on doing a successful clear feature 1477 * USB_FAILURE - on failure 1478 * USB_* - refer to usbai.h 1479 */ 1480 int 1481 usb_clear_feature(dev_info_t *dip, 1482 usb_pipe_handle_t ph, 1483 uint_t type, /* bmRequestType */ 1484 uint_t feature, 1485 uint_t what, /* 0, interface, ept number */ 1486 usb_flags_t flags) 1487 { 1488 int rval; 1489 usb_cr_t completion_reason; 1490 usb_cb_flags_t cb_flags; 1491 1492 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1493 "usb_clear_feature: type = 0x%x, feature = 0x%x, what = 0x%x " 1494 "uf = 0x%x", type, feature, what, flags); 1495 1496 if (dip == NULL) { 1497 1498 return (USB_INVALID_ARGS); 1499 } 1500 if (ph == NULL) { 1501 1502 return (USB_INVALID_PIPE); 1503 } 1504 1505 /* issue Clear feature */ 1506 rval = usb_pipe_sync_ctrl_xfer(dip, ph, 1507 type, 1508 USB_REQ_CLEAR_FEATURE, 1509 feature, 1510 what, 1511 0, 1512 NULL, 0, 1513 &completion_reason, 1514 &cb_flags, flags | USB_FLAGS_SLEEP); 1515 1516 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1517 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 1518 1519 return (rval); 1520 } 1521 1522 1523 /* 1524 * usb_clr_feature: 1525 * Issue USB_REQ_CLEAR_FEATURE to endpoint/device/interface 1526 * 1527 * Arguments: 1528 * dip - pointer to devinfo of the client 1529 * type - bmRequestType to be used 1530 * feature - feature to be cleared 1531 * what - 0 for device, otherwise interface or ep number 1532 * flags - USB_FLAGS_SLEEP: 1533 * wait for completion 1534 * cb - if USB_FLAGS_SLEEP has not been specified 1535 * this callback function will be called on 1536 * completion. This callback may be NULL 1537 * and no notification of completion will then 1538 * be provided. 1539 * cb_arg - 2nd argument to callback function. 1540 * 1541 * 1542 * Return Values: 1543 * USB_SUCCESS - on doing a successful clear feature 1544 * USB_FAILURE - on failure 1545 * USB_* - refer to usbai.h 1546 */ 1547 int 1548 usb_clr_feature( 1549 dev_info_t *dip, 1550 uint_t type, /* bmRequestType */ 1551 uint_t feature, 1552 uint_t what, /* 0, interface, ept number */ 1553 usb_flags_t flags, 1554 void (*cb)( 1555 usb_pipe_handle_t ph, 1556 usb_opaque_t arg, 1557 int rval, 1558 usb_cb_flags_t flags), 1559 usb_opaque_t cb_arg) 1560 { 1561 usb_pipe_handle_t ph; 1562 1563 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1564 "usb_clr_feature: type = 0x%x, feature = 0x%x, what = 0x%x " 1565 "uf = 0x%x", type, feature, what, flags); 1566 1567 if (dip == NULL) { 1568 1569 return (USB_INVALID_ARGS); 1570 } 1571 1572 if ((flags & USB_FLAGS_SLEEP) && servicing_interrupt()) { 1573 1574 return (USB_INVALID_CONTEXT); 1575 } 1576 1577 ph = usba_get_dflt_pipe_handle(dip); 1578 if (usba_hold_ph_data(ph) == NULL) { 1579 1580 return (USB_INVALID_PIPE); 1581 } 1582 1583 return (usba_pipe_setup_func_call(dip, 1584 usba_sync_clear_feature, (usba_ph_impl_t *)ph, 1585 (usb_opaque_t)((uintptr_t)((type << 16 | feature << 8 | what))), 1586 flags, cb, cb_arg)); 1587 } 1588 1589 1590 static int 1591 usba_sync_clear_feature(dev_info_t *dip, 1592 usba_ph_impl_t *ph_impl, 1593 usba_pipe_async_req_t *req, 1594 usb_flags_t usb_flags) 1595 { 1596 uint_t n = (uint_t)((uintptr_t)(req->arg)); 1597 uint_t type = ((uint_t)n >> 16) & 0xff; 1598 uint_t feature = ((uint_t)n >> 8) & 0xff; 1599 uint_t what = (uint_t)n & 0xff; 1600 int rval; 1601 usba_device_t *usba_device; 1602 usba_pipe_handle_data_t *ph_data; 1603 usba_ph_impl_t *ph_im; 1604 uchar_t ep_index; 1605 usb_ep_descr_t *eptd; 1606 1607 1608 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1609 "usb_sync_clear_feature: " 1610 "dip=0x%p ph=0x%p type=0x%x feature=0x%x what=0x%x fl=0x%x", 1611 (void *)dip, (void *)ph_impl, type, feature, what, usb_flags); 1612 1613 rval = usb_clear_feature(dip, (usb_pipe_handle_t)ph_impl, type, 1614 feature, what, usb_flags); 1615 1616 /* 1617 * Reset data toggle to DATA0 for bulk and interrupt endpoint. 1618 * Data toggle synchronization is not supported for isochronous 1619 * transfer.Halt feature is not supported by control endpoint. 1620 * 1621 * From USB2.0 specification: 1622 * 1.Section 5.8.5 Bulk Transfer Data Sequences 1623 * Removal of the halt condition is achieved via software intervention 1624 * through a separate control pipe. This recovery will reset the data 1625 * toggle bit to DATA0 for the endpoint on both the host and the device. 1626 * 1627 * 2.Section 5.7.5 Interrupt Transfer Data Sequences 1628 * Removal of the halt condition is achieved via software intervention 1629 * through a separate control pipe. This recovery will reset the data 1630 * toggle bit to DATA0 for the endpoint on both the host and the device. 1631 * 1632 * 3.Section 9.4.5 1633 * If the condition causing a halt has been removed, clearing the Halt 1634 * feature via a ClearFeature(ENDPOINT_HALT) request results in the 1635 * endpoint no longer returning a STALL. For endpoints using data 1636 * toggle, regardless of whether an endpoint has the Halt feature set, a 1637 * ClearFeature(ENDPOINT_HALT) request always results in the data toggle 1638 * being reinitialized to DATA0. 1639 * 1640 */ 1641 if (rval == USB_SUCCESS && feature == 0) { 1642 usba_device = usba_get_usba_device(dip); 1643 ep_index = usb_get_ep_index((uint8_t)what); 1644 ph_im = &usba_device->usb_ph_list[ep_index]; 1645 ph_data = usba_get_ph_data((usb_pipe_handle_t)ph_im); 1646 eptd = &ph_data->p_ep; 1647 if ((eptd->bmAttributes & USB_EP_ATTR_MASK) == 1648 USB_EP_ATTR_BULK || (eptd->bmAttributes & 1649 USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR) 1650 usba_device->usb_hcdi_ops-> 1651 usba_hcdi_pipe_reset_data_toggle(ph_data); 1652 } 1653 1654 usba_release_ph_data(ph_impl); 1655 1656 return (rval); 1657 } 1658 1659 1660 /* 1661 * usb_async_req: 1662 * function used to dispatch a request to the taskq 1663 * 1664 * Arguments: 1665 * dip - pointer to devinfo node 1666 * func - pointer to function issued by taskq 1667 * flag - USB_FLAGS_SLEEP mostly 1668 * 1669 * Return Values: 1670 * USB_SUCCESS - on doing a successful taskq invocation 1671 * USB_FAILURE - on failure 1672 * USB_* - refer to usbai.h 1673 */ 1674 int 1675 usb_async_req(dev_info_t *dip, 1676 void (*func)(void *), 1677 void *arg, 1678 usb_flags_t flag) 1679 { 1680 int tq_flag; 1681 1682 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1683 "usb_async_req: dip=0x%p func=0x%p, arg=0x%p flag=0x%x", 1684 (void *)dip, (void *)func, arg, flag); 1685 1686 if ((dip == NULL) || (func == NULL)) { 1687 1688 return (USB_INVALID_ARGS); 1689 } 1690 tq_flag = (flag & USB_FLAGS_SLEEP) ? TQ_SLEEP : TQ_NOSLEEP; 1691 if (flag & USB_FLAGS_NOQUEUE) { 1692 tq_flag |= TQ_NOQUEUE; 1693 } 1694 1695 if (taskq_dispatch(system_taskq, func, arg, 1696 tq_flag) == TASKQID_INVALID) { 1697 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 1698 "usb_async_req: failure"); 1699 1700 return (USB_FAILURE); 1701 } 1702 1703 return (USB_SUCCESS); 1704 } 1705 1706 /* 1707 * usba_async_ph_req: 1708 * function used to dispatch a request to the ph taskq 1709 * 1710 * Arguments: 1711 * ph_data - pointer to pipe handle data 1712 * func - pointer to function issued by taskq 1713 * flag - USB_FLAGS_SLEEP or USB_FLAGS_NOSLEEP 1714 * 1715 * Return Values: 1716 * USB_SUCCESS - on doing a successful taskq invocation 1717 * USB_FAILURE - on failure 1718 * USB_* - refer to usbai.h 1719 * 1720 * Note: 1721 * If the caller specified USB_FLAGS_NOSLEEP, it must be 1722 * capable of reliably recovering from a failure return 1723 */ 1724 int 1725 usba_async_ph_req(usba_pipe_handle_data_t *ph_data, 1726 void (*func)(void *), 1727 void *arg, 1728 usb_flags_t flag) 1729 { 1730 int tq_flag; 1731 taskq_t *taskq; 1732 1733 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1734 "usba_async_ph_req: ph_data=0x%p func=0x%p, arg=0x%p flag=0x%x", 1735 (void *)ph_data, (void *)func, arg, flag); 1736 1737 if (func == NULL) { 1738 1739 return (USB_INVALID_ARGS); 1740 } 1741 1742 tq_flag = (flag & USB_FLAGS_SLEEP) ? TQ_SLEEP : TQ_NOSLEEP; 1743 1744 if (ph_data && ph_data->p_taskq) { 1745 taskq = ph_data->p_taskq; 1746 } else { 1747 taskq = system_taskq; 1748 tq_flag |= TQ_NOQUEUE; 1749 } 1750 1751 if (taskq_dispatch(taskq, func, arg, tq_flag) == TASKQID_INVALID) { 1752 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 1753 "usba_async_ph_req: failure"); 1754 1755 return (USB_FAILURE); 1756 } 1757 1758 return (USB_SUCCESS); 1759 } 1760 1761 1762 /* 1763 * utility functions to display CR, CB, return values 1764 */ 1765 typedef struct conv_table { 1766 int what; 1767 const char *name; 1768 } conv_table_t; 1769 1770 static const char * 1771 usba_get_name(conv_table_t *conv_table, int value) 1772 { 1773 int i; 1774 for (i = 0; conv_table[i].name != NULL; i++) { 1775 if (conv_table[i].what == value) { 1776 1777 return (conv_table[i].name); 1778 } 1779 } 1780 1781 return ("unknown"); 1782 } 1783 1784 1785 static conv_table_t cr_table[] = { 1786 { USB_CR_OK, "<no errors detected>" }, 1787 { USB_CR_CRC, "<crc error detected>" }, 1788 { USB_CR_BITSTUFFING, "<Bit stuffing violation>" }, 1789 { USB_CR_DATA_TOGGLE_MM, "<Data toggle PID did not match>" }, 1790 { USB_CR_STALL, "<Endpoint returned stall PID>" }, 1791 { USB_CR_DEV_NOT_RESP, "<Device not responding>" }, 1792 { USB_CR_PID_CHECKFAILURE, "<Check bits on PID failed>" }, 1793 { USB_CR_UNEXP_PID, "<Receive PID was not valid>" }, 1794 { USB_CR_DATA_OVERRUN, "<Data size exceeded>" }, 1795 { USB_CR_DATA_UNDERRUN, "<Less data recieved than requested>" }, 1796 { USB_CR_BUFFER_OVERRUN, "<Memory write can't keep up>" }, 1797 { USB_CR_BUFFER_UNDERRUN, "<Buffer underrun>" }, 1798 { USB_CR_TIMEOUT, "<Command timed out>" }, 1799 { USB_CR_NOT_ACCESSED, "<Not accessed by hardware>" }, 1800 { USB_CR_NO_RESOURCES, "<No resources>" }, 1801 { USB_CR_UNSPECIFIED_ERR, "<Unspecified usba or hcd error>" }, 1802 { USB_CR_STOPPED_POLLING, "<Intr/ISOC IN polling stopped>" }, 1803 { USB_CR_PIPE_CLOSING, "<Intr/ISOC IN pipe being closed>" }, 1804 { USB_CR_PIPE_RESET, "<Intr/ISOC IN pipe reset>" }, 1805 { USB_CR_NOT_SUPPORTED, "<Command not supported>" }, 1806 { USB_CR_FLUSHED, "<Req was flushed>" }, 1807 { USB_CR_HC_HARDWARE_ERR, "<USB host controller error>" }, 1808 { 0, NULL } 1809 }; 1810 1811 const char * 1812 usb_str_cr(usb_cr_t cr) 1813 { 1814 return (usba_get_name(cr_table, cr)); 1815 } 1816 1817 1818 static conv_table_t cb_flags_table[] = { 1819 { USB_CB_NO_INFO, "<callback processed>" }, 1820 { USB_CB_STALL_CLEARED, "<stall cleared>" }, 1821 { USB_CB_FUNCTIONAL_STALL, "<functional stall>" }, 1822 { USB_CB_PROTOCOL_STALL, "<protocol stall>" }, 1823 { USB_CB_RESET_PIPE, "<pipe reset>" }, 1824 { USB_CB_ASYNC_REQ_FAILED, "<thread could not be started>" }, 1825 { USB_CB_NO_RESOURCES, "<no resources>" }, 1826 { USB_CB_SUBMIT_FAILED, "<submit failed>" }, 1827 { USB_CB_INTR_CONTEXT, "<Callback executing in interrupt context>" }, 1828 { 0, NULL } 1829 }; 1830 1831 /*ARGSUSED*/ 1832 char * 1833 usb_str_cb_flags(usb_cb_flags_t cb_flags, char *buffer, size_t length) 1834 { 1835 int i; 1836 buffer[0] = '\0'; 1837 if (cb_flags == USB_CB_NO_INFO) { 1838 (void) strncpy(buffer, cb_flags_table[0].name, length); 1839 } else { 1840 for (i = 0; cb_flags_table[i].name != NULL; i++) { 1841 if (cb_flags & cb_flags_table[i].what) { 1842 (void) strncpy(&buffer[strlen(buffer)], 1843 cb_flags_table[0].name, 1844 length - strlen(buffer) - 1); 1845 } 1846 } 1847 } 1848 1849 return (buffer); 1850 } 1851 1852 1853 static conv_table_t pipe_state_table[] = { 1854 { USB_PIPE_STATE_CLOSED, "<closed>" }, 1855 { USB_PIPE_STATE_IDLE, "<idle>" }, 1856 { USB_PIPE_STATE_ACTIVE, "<active>" }, 1857 { USB_PIPE_STATE_ERROR, "<error>" }, 1858 { USB_PIPE_STATE_CLOSING, "<closing>" }, 1859 { 0, NULL } 1860 }; 1861 1862 const char * 1863 usb_str_pipe_state(usb_pipe_state_t state) 1864 { 1865 return (usba_get_name(pipe_state_table, state)); 1866 } 1867 1868 1869 static conv_table_t dev_state[] = { 1870 { USB_DEV_ONLINE, "<online>" }, 1871 { USB_DEV_DISCONNECTED, "<disconnected>" }, 1872 { USB_DEV_SUSPENDED, "<suspended>" }, 1873 { USB_DEV_PWRED_DOWN, "<powered down>" }, 1874 { 0, NULL } 1875 }; 1876 1877 const char * 1878 usb_str_dev_state(int state) 1879 { 1880 return (usba_get_name(dev_state, state)); 1881 } 1882 1883 1884 static conv_table_t rval_table[] = { 1885 { USB_SUCCESS, "<success>" }, 1886 { USB_FAILURE, "<failure>" }, 1887 { USB_NO_RESOURCES, "<no resources>" }, 1888 { USB_NO_BANDWIDTH, "<no bandwidth>" }, 1889 { USB_NOT_SUPPORTED, "<not supported>" }, 1890 { USB_PIPE_ERROR, "<pipe error>" }, 1891 { USB_INVALID_PIPE, "<invalid pipe>" }, 1892 { USB_NO_FRAME_NUMBER, "<no frame number>" }, 1893 { USB_INVALID_START_FRAME, "<invalid frame>" }, 1894 { USB_HC_HARDWARE_ERROR, "<hw error>" }, 1895 { USB_INVALID_REQUEST, "<invalid request>" }, 1896 { USB_INVALID_CONTEXT, "<invalid context>" }, 1897 { USB_INVALID_VERSION, "<invalid version>" }, 1898 { USB_INVALID_ARGS, "<invalid args>" }, 1899 { USB_INVALID_PERM, "<invalid perms>" }, 1900 { USB_BUSY, "<busy>" }, 1901 { 0, NULL } 1902 }; 1903 1904 const char * 1905 usb_str_rval(int rval) 1906 { 1907 return (usba_get_name(rval_table, rval)); 1908 } 1909 1910 1911 /* 1912 * function to convert USB return values to close errno 1913 */ 1914 static struct usb_rval2errno_entry { 1915 int rval; 1916 int Errno; 1917 } usb_rval2errno_table[] = { 1918 { USB_SUCCESS, 0 }, 1919 { USB_FAILURE, EIO }, 1920 { USB_NO_RESOURCES, ENOMEM }, 1921 { USB_NO_BANDWIDTH, EAGAIN }, 1922 { USB_NOT_SUPPORTED, ENOTSUP }, 1923 { USB_PIPE_ERROR, EIO }, 1924 { USB_INVALID_PIPE, EINVAL }, 1925 { USB_NO_FRAME_NUMBER, EINVAL }, 1926 { USB_INVALID_START_FRAME, EINVAL }, 1927 { USB_HC_HARDWARE_ERROR, EIO }, 1928 { USB_INVALID_REQUEST, EINVAL }, 1929 { USB_INVALID_CONTEXT, EINVAL }, 1930 { USB_INVALID_VERSION, EINVAL }, 1931 { USB_INVALID_ARGS, EINVAL }, 1932 { USB_INVALID_PERM, EACCES }, 1933 { USB_BUSY, EBUSY }, 1934 }; 1935 1936 #define USB_RVAL2ERRNO_TABLE_SIZE (sizeof (usb_rval2errno_table) / \ 1937 sizeof (struct usb_rval2errno_entry)) 1938 int 1939 usb_rval2errno(int rval) 1940 { 1941 int i; 1942 1943 for (i = 0; i < USB_RVAL2ERRNO_TABLE_SIZE; i++) { 1944 if (usb_rval2errno_table[i].rval == rval) { 1945 1946 return (usb_rval2errno_table[i].Errno); 1947 } 1948 } 1949 1950 return (EIO); 1951 } 1952 1953 1954 /* 1955 * serialization 1956 */ 1957 usb_serialization_t 1958 usb_init_serialization( 1959 dev_info_t *dip, 1960 uint_t flag) 1961 { 1962 usba_serialization_impl_t *impl_tokenp = kmem_zalloc( 1963 sizeof (usba_serialization_impl_t), KM_SLEEP); 1964 usba_device_t *usba_device; 1965 ddi_iblock_cookie_t cookie = NULL; 1966 1967 if (dip) { 1968 usba_device = usba_get_usba_device(dip); 1969 cookie = usba_hcdi_get_hcdi( 1970 usba_device->usb_root_hub_dip)->hcdi_iblock_cookie; 1971 } 1972 impl_tokenp->s_dip = dip; 1973 impl_tokenp->s_flag = flag; 1974 mutex_init(&impl_tokenp->s_mutex, NULL, MUTEX_DRIVER, cookie); 1975 cv_init(&impl_tokenp->s_cv, NULL, CV_DRIVER, NULL); 1976 1977 return ((usb_serialization_t)impl_tokenp); 1978 } 1979 1980 1981 void 1982 usb_fini_serialization( 1983 usb_serialization_t tokenp) 1984 { 1985 usba_serialization_impl_t *impl_tokenp; 1986 1987 if (tokenp) { 1988 impl_tokenp = (usba_serialization_impl_t *)tokenp; 1989 ASSERT(impl_tokenp->s_count == 0); 1990 cv_destroy(&impl_tokenp->s_cv); 1991 mutex_destroy(&impl_tokenp->s_mutex); 1992 kmem_free(impl_tokenp, sizeof (usba_serialization_impl_t)); 1993 } 1994 } 1995 1996 1997 /* 1998 * usb_serialize_access() permits single threaded access. 1999 * 2000 * If tokenp is initialized with USB_INIT_SER_CHECK_SAME_THREAD, 2001 * it is reentrant with respect to thread. The thread must 2002 * hold and release the same number of times. 2003 * 2004 * If tokenp is initialized without USB_INIT_SER_CHECK_SAME_THREAD, 2005 * it is not reentrant by the same thread. It is something like 2006 * a semaphore. 2007 */ 2008 int 2009 usb_serialize_access( 2010 usb_serialization_t tokenp, uint_t how_to_wait, uint_t delta_timeout) 2011 { 2012 int rval = 1; /* Must be initialized > 0 */ 2013 clock_t abs_timeout = 0; 2014 usba_serialization_impl_t *impl_tokenp; 2015 2016 impl_tokenp = (usba_serialization_impl_t *)tokenp; 2017 2018 /* 2019 * Convert delta timeout in ms to absolute timeout in ticks, if used. 2020 */ 2021 if ((how_to_wait == USB_TIMEDWAIT) || 2022 (how_to_wait == USB_TIMEDWAIT_SIG)) { 2023 /* Convert timeout arg (in ms) to hz */ 2024 abs_timeout = ddi_get_lbolt() + 2025 drv_usectohz(delta_timeout * 1000); 2026 } 2027 2028 /* Get mutex after calc abs time, to count time waiting for mutex. */ 2029 mutex_enter(&impl_tokenp->s_mutex); 2030 2031 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2032 "usb_serialize_access: tok=0x%p dip=0x%p cnt=%d thr=0x%p, " 2033 "flg=0x%x, abs_tmo=0x%lx", 2034 (void *)impl_tokenp, (void *)impl_tokenp->s_dip, 2035 impl_tokenp->s_count, (void *)impl_tokenp->s_thread, 2036 how_to_wait, abs_timeout); 2037 2038 if ((impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD) == 0 || 2039 impl_tokenp->s_thread != curthread) { 2040 2041 /* 2042 * There are three ways to break out of the loop: 2043 * 1) Condition met (s_count == 0) - higher prio test 2044 * 2) kill(2) signal received (rval == 0) 2045 * 3) timeout occurred (rval == -1) 2046 * If condition met, whether or not signal or timeout occurred 2047 * take access. If condition not met, check other exit means. 2048 */ 2049 while (impl_tokenp->s_count != 0) { 2050 2051 /* cv_timedwait* returns -1 on timeout. */ 2052 /* cv_wait*_sig returns 0 on (kill(2)) signal. */ 2053 if (rval <= 0) { 2054 mutex_exit(&impl_tokenp->s_mutex); 2055 USB_DPRINTF_L4(DPRINT_MASK_USBA, 2056 usbai_log_handle, 2057 "usb_serialize_access: " 2058 "tok=0x%p exit due to %s", 2059 (void *)impl_tokenp, 2060 ((rval == 0) ? "signal" : "timeout")); 2061 2062 return (rval); 2063 } 2064 2065 switch (how_to_wait) { 2066 default: 2067 how_to_wait = USB_WAIT; 2068 /* FALLTHROUGH */ 2069 case USB_WAIT: 2070 cv_wait(&impl_tokenp->s_cv, 2071 &impl_tokenp->s_mutex); 2072 break; 2073 case USB_WAIT_SIG: 2074 rval = cv_wait_sig(&impl_tokenp->s_cv, 2075 &impl_tokenp->s_mutex); 2076 break; 2077 case USB_TIMEDWAIT: 2078 rval = cv_timedwait(&impl_tokenp->s_cv, 2079 &impl_tokenp->s_mutex, abs_timeout); 2080 break; 2081 case USB_TIMEDWAIT_SIG: 2082 rval = cv_timedwait_sig(&impl_tokenp->s_cv, 2083 &impl_tokenp->s_mutex, abs_timeout); 2084 break; 2085 } 2086 } 2087 2088 impl_tokenp->s_thread = curthread; 2089 } 2090 impl_tokenp->s_count++; 2091 2092 ASSERT(!(impl_tokenp->s_count > 1 && 2093 (impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD) == 0)); 2094 2095 mutex_exit(&impl_tokenp->s_mutex); 2096 2097 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2098 "usb_serialize_access exit: tok=0x%p thr=0x%p", (void *)impl_tokenp, 2099 (void *)curthread); 2100 2101 return (1); 2102 } 2103 2104 2105 /*ARGSUSED*/ 2106 int 2107 usb_try_serialize_access( 2108 usb_serialization_t tokenp, uint_t flag) 2109 { 2110 usba_serialization_impl_t *impl_tokenp = 2111 (usba_serialization_impl_t *)tokenp; 2112 mutex_enter(&impl_tokenp->s_mutex); 2113 2114 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2115 "usb_try_serialize_access: tok=0x%p dip=0x%p cnt=%d thr=0x%p", 2116 (void *)impl_tokenp, (void *)impl_tokenp->s_dip, 2117 impl_tokenp->s_count, (void *)curthread); 2118 2119 /* 2120 * If lock is not taken (s_count is 0), take it. 2121 * If lock is already taken, the thread is owner and lock 2122 * is reentrant, take it. 2123 * Otherwise, fail the access. 2124 */ 2125 if (!impl_tokenp->s_count || ((impl_tokenp->s_thread == curthread) && 2126 (impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD))) { 2127 impl_tokenp->s_thread = curthread; 2128 impl_tokenp->s_count++; 2129 2130 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2131 "usb_try_serialize_access success: tok=0x%p", 2132 (void *)impl_tokenp); 2133 mutex_exit(&impl_tokenp->s_mutex); 2134 2135 return (USB_SUCCESS); 2136 } 2137 2138 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2139 "usb_try_serialize_access failed: " 2140 "tok=0x%p dip=0x%p cnt=%d thr=0x%p", 2141 (void *)impl_tokenp, (void *)impl_tokenp->s_dip, 2142 impl_tokenp->s_count, (void *)impl_tokenp->s_thread); 2143 2144 mutex_exit(&impl_tokenp->s_mutex); 2145 2146 return (USB_FAILURE); 2147 } 2148 2149 2150 void 2151 usb_release_access( 2152 usb_serialization_t tokenp) 2153 { 2154 usba_serialization_impl_t *impl_tokenp = 2155 (usba_serialization_impl_t *)tokenp; 2156 mutex_enter(&impl_tokenp->s_mutex); 2157 2158 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2159 "usb_release_access: tok=0x%p dip=0x%p count=%d thr=0x%p", 2160 (void *)impl_tokenp, (void *)impl_tokenp->s_dip, 2161 impl_tokenp->s_count, (void *)curthread); 2162 2163 ASSERT(impl_tokenp->s_count > 0); 2164 2165 if (impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD) { 2166 if (impl_tokenp->s_thread != curthread) { 2167 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 2168 "usb_release_access: release from wrong thread"); 2169 } 2170 ASSERT(impl_tokenp->s_thread == curthread); 2171 } 2172 2173 if (--impl_tokenp->s_count == 0) { 2174 impl_tokenp->s_thread = NULL; 2175 cv_broadcast(&impl_tokenp->s_cv); 2176 } 2177 mutex_exit(&impl_tokenp->s_mutex); 2178 } 2179 2180 2181 /* 2182 * usb_fail_checkpoint: 2183 * fail checkpoint as driver/device could not be quiesced 2184 */ 2185 /*ARGSUSED*/ 2186 void 2187 usb_fail_checkpoint(dev_info_t *dip, usb_flags_t flags) 2188 { 2189 usba_device_t *usba_device = usba_get_usba_device(dip); 2190 2191 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 2192 "usb_fail_checkpoint: %s%d", ddi_driver_name(dip), 2193 ddi_get_instance(dip)); 2194 2195 mutex_enter(&usba_device->usb_mutex); 2196 usba_device->usb_no_cpr++; 2197 mutex_exit(&usba_device->usb_mutex); 2198 } 2199 2200 2201 _NOTE(SCHEME_PROTECTS_DATA("unique per call", iocblk)) 2202 _NOTE(SCHEME_PROTECTS_DATA("unique per call", datab)) 2203 /* 2204 * usba_mk_mctl: 2205 * create a USB style M_CTL message, given an iocblk and a buffer 2206 * returns mblk_t * on success, NULL on failure 2207 */ 2208 mblk_t * 2209 usba_mk_mctl(struct iocblk mctlmsg, void *buf, size_t len) 2210 { 2211 mblk_t *bp1, *bp2; 2212 2213 if ((bp1 = allocb(sizeof (struct iocblk), BPRI_HI)) != NULL) { 2214 /* LINTED E_BAD_PTR_CAST_ALIGN */ 2215 *((struct iocblk *)bp1->b_datap->db_base) = mctlmsg; 2216 bp1->b_datap->db_type = M_CTL; 2217 bp1->b_wptr += sizeof (struct iocblk); 2218 if (buf != NULL) { 2219 if ((bp2 = allocb(len, BPRI_HI)) != NULL) { 2220 bp1->b_cont = bp2; 2221 bcopy(buf, bp2->b_datap->db_base, len); 2222 bp2->b_wptr += len; 2223 } else { 2224 freemsg(bp1); 2225 bp1 = NULL; 2226 } 2227 } 2228 } 2229 2230 return (bp1); 2231 } 2232 2233 2234 #ifdef ALLOCB_TEST 2235 #undef allocb 2236 mblk_t * 2237 usba_test_allocb(size_t size, uint_t pri) 2238 { 2239 if (ddi_get_lbolt() & 0x1) { 2240 2241 return (NULL); 2242 } else { 2243 2244 return (allocb(size, pri)); 2245 } 2246 } 2247 #endif 2248 2249 2250 /* 2251 * usb common power management for usb_mid, usb_ia and maybe other simple 2252 * drivers. 2253 */ 2254 2255 /* 2256 * functions to handle power transition for OS levels 0 -> 3 2257 */ 2258 static int 2259 usb_common_pwrlvl0(dev_info_t *dip, uint8_t *pm, int *dev_state) 2260 { 2261 int rval; 2262 2263 switch (*dev_state) { 2264 case USB_DEV_ONLINE: 2265 /* Issue USB D3 command to the device here */ 2266 rval = usb_set_device_pwrlvl3(dip); 2267 ASSERT(rval == USB_SUCCESS); 2268 2269 *dev_state = USB_DEV_PWRED_DOWN; 2270 *pm = USB_DEV_OS_PWR_OFF; 2271 /* FALLTHRU */ 2272 case USB_DEV_DISCONNECTED: 2273 case USB_DEV_SUSPENDED: 2274 /* allow a disconnected/cpr'ed device to go to low pwr */ 2275 2276 return (USB_SUCCESS); 2277 case USB_DEV_PWRED_DOWN: 2278 default: 2279 return (USB_FAILURE); 2280 } 2281 } 2282 2283 2284 /* ARGSUSED */ 2285 static int 2286 usb_common_pwrlvl1(dev_info_t *dip, uint8_t *pm, int *dev_state) 2287 { 2288 int rval; 2289 2290 /* Issue USB D2 command to the device here */ 2291 rval = usb_set_device_pwrlvl2(dip); 2292 ASSERT(rval == USB_SUCCESS); 2293 2294 return (USB_FAILURE); 2295 } 2296 2297 2298 /* ARGSUSED */ 2299 static int 2300 usb_common_pwrlvl2(dev_info_t *dip, uint8_t *pm, int *dev_state) 2301 { 2302 int rval; 2303 2304 /* Issue USB D1 command to the device here */ 2305 rval = usb_set_device_pwrlvl1(dip); 2306 ASSERT(rval == USB_SUCCESS); 2307 2308 return (USB_FAILURE); 2309 } 2310 2311 2312 static int 2313 usb_common_pwrlvl3(dev_info_t *dip, uint8_t *pm, int *dev_state) 2314 { 2315 int rval; 2316 2317 switch (*dev_state) { 2318 case USB_DEV_PWRED_DOWN: 2319 /* Issue USB D0 command to the device here */ 2320 rval = usb_set_device_pwrlvl0(dip); 2321 ASSERT(rval == USB_SUCCESS); 2322 2323 *dev_state = USB_DEV_ONLINE; 2324 *pm = USB_DEV_OS_FULL_PWR; 2325 2326 /* FALLTHRU */ 2327 case USB_DEV_ONLINE: 2328 /* we are already in full power */ 2329 2330 /* FALLTHRU */ 2331 case USB_DEV_DISCONNECTED: 2332 case USB_DEV_SUSPENDED: 2333 /* allow a disconnected/cpr'ed device to go to low power */ 2334 2335 return (USB_SUCCESS); 2336 default: 2337 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 2338 "usb_common_pwrlvl3: Illegal state (%s)", 2339 usb_str_dev_state(*dev_state)); 2340 2341 return (USB_FAILURE); 2342 } 2343 } 2344 2345 /* power management */ 2346 int 2347 usba_common_power(dev_info_t *dip, uint8_t *pm, int *dev_state, int level) 2348 { 2349 int rval = DDI_FAILURE; 2350 2351 switch (level) { 2352 case USB_DEV_OS_PWR_OFF: 2353 rval = usb_common_pwrlvl0(dip, pm, dev_state); 2354 break; 2355 case USB_DEV_OS_PWR_1: 2356 rval = usb_common_pwrlvl1(dip, pm, dev_state); 2357 break; 2358 case USB_DEV_OS_PWR_2: 2359 rval = usb_common_pwrlvl2(dip, pm, dev_state); 2360 break; 2361 case USB_DEV_OS_FULL_PWR: 2362 rval = usb_common_pwrlvl3(dip, pm, dev_state); 2363 break; 2364 } 2365 2366 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 2367 } 2368 2369 /* 2370 * register and unregister for events from our parent for usb_mid and usb_ia 2371 * and maybe other nexus driver. 2372 * 2373 * Note: The cookie fields in usba_device structure is not used. They are 2374 * used/shared by children. 2375 */ 2376 void 2377 usba_common_register_events(dev_info_t *dip, uint_t if_num, 2378 void (*event_cb)(dev_info_t *, ddi_eventcookie_t, void *, void *)) 2379 { 2380 int rval; 2381 usba_evdata_t *evdata; 2382 ddi_eventcookie_t cookie; 2383 2384 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2385 "usb_common_register_events:"); 2386 2387 evdata = usba_get_evdata(dip); 2388 2389 /* get event cookie, discard level and icookie for now */ 2390 rval = ddi_get_eventcookie(dip, DDI_DEVI_REMOVE_EVENT, 2391 &cookie); 2392 2393 if (rval == DDI_SUCCESS) { 2394 rval = ddi_add_event_handler(dip, 2395 cookie, event_cb, NULL, &evdata->ev_rm_cb_id); 2396 2397 if (rval != DDI_SUCCESS) { 2398 2399 goto fail; 2400 } 2401 } 2402 rval = ddi_get_eventcookie(dip, DDI_DEVI_INSERT_EVENT, 2403 &cookie); 2404 if (rval == DDI_SUCCESS) { 2405 rval = ddi_add_event_handler(dip, cookie, event_cb, 2406 NULL, &evdata->ev_ins_cb_id); 2407 2408 if (rval != DDI_SUCCESS) { 2409 2410 goto fail; 2411 } 2412 } 2413 rval = ddi_get_eventcookie(dip, USBA_PRE_SUSPEND_EVENT, &cookie); 2414 if (rval == DDI_SUCCESS) { 2415 rval = ddi_add_event_handler(dip, 2416 cookie, event_cb, NULL, &evdata->ev_suspend_cb_id); 2417 2418 if (rval != DDI_SUCCESS) { 2419 2420 goto fail; 2421 } 2422 } 2423 rval = ddi_get_eventcookie(dip, USBA_POST_RESUME_EVENT, &cookie); 2424 if (rval == DDI_SUCCESS) { 2425 rval = ddi_add_event_handler(dip, cookie, event_cb, NULL, 2426 &evdata->ev_resume_cb_id); 2427 2428 if (rval != DDI_SUCCESS) { 2429 2430 goto fail; 2431 } 2432 } 2433 2434 return; 2435 2436 2437 fail: 2438 usba_common_unregister_events(dip, if_num); 2439 2440 } 2441 2442 void 2443 usba_common_unregister_events(dev_info_t *dip, uint_t if_num) 2444 { 2445 usba_evdata_t *evdata; 2446 usba_device_t *usba_device = usba_get_usba_device(dip); 2447 int i; 2448 2449 evdata = usba_get_evdata(dip); 2450 2451 if (evdata->ev_rm_cb_id != NULL) { 2452 (void) ddi_remove_event_handler(evdata->ev_rm_cb_id); 2453 evdata->ev_rm_cb_id = NULL; 2454 } 2455 2456 if (evdata->ev_ins_cb_id != NULL) { 2457 (void) ddi_remove_event_handler(evdata->ev_ins_cb_id); 2458 evdata->ev_ins_cb_id = NULL; 2459 } 2460 2461 if (evdata->ev_suspend_cb_id != NULL) { 2462 (void) ddi_remove_event_handler(evdata->ev_suspend_cb_id); 2463 evdata->ev_suspend_cb_id = NULL; 2464 } 2465 2466 if (evdata->ev_resume_cb_id != NULL) { 2467 (void) ddi_remove_event_handler(evdata->ev_resume_cb_id); 2468 evdata->ev_resume_cb_id = NULL; 2469 } 2470 2471 /* clear event data for children, required for cfgmadm unconfigure */ 2472 mutex_enter(&usba_device->usb_mutex); 2473 if (usb_owns_device(dip)) { 2474 usba_free_evdata(usba_device->usb_evdata); 2475 usba_device->usb_evdata = NULL; 2476 usba_device->rm_cookie = NULL; 2477 usba_device->ins_cookie = NULL; 2478 usba_device->suspend_cookie = NULL; 2479 usba_device->resume_cookie = NULL; 2480 } else { 2481 for (i = 0; i < if_num; i++) { 2482 usba_device->usb_client_flags[usba_get_ifno(dip) + i] 2483 &= ~USBA_CLIENT_FLAG_EV_CBS; 2484 } 2485 } 2486 mutex_exit(&usba_device->usb_mutex); 2487 } 2488