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