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