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 2004 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 566 usba_device = usba_get_usba_device(dip); 567 568 /* 569 * default pipe is still open 570 * all other pipes should be closed 571 */ 572 for (ph_open_cnt = 0, i = 1; i < USBA_N_ENDPOINTS; i++) { 573 if (usba_device->usb_ph_list[i].usba_ph_data) { 574 ph_open_cnt++; 575 break; 576 } 577 } 578 579 if (ph_open_cnt || ddi_get_child(dip)) { 580 usba_release_ph_data(ph_impl); 581 582 return (USB_BUSY); 583 } 584 585 size = usb_parse_cfg_descr(usba_device->usb_cfg_array[cfg_index], 586 USB_CFG_DESCR_SIZE, &confdescr, USB_CFG_DESCR_SIZE); 587 588 /* hubdi should ensure that this descriptor is correct */ 589 ASSERT(size == USB_CFG_DESCR_SIZE); 590 591 /* set the configuration */ 592 rval = usb_pipe_sync_ctrl_xfer(dip, (usb_pipe_handle_t)ph_impl, 593 USB_DEV_REQ_HOST_TO_DEV, 594 USB_REQ_SET_CFG, 595 confdescr.bConfigurationValue, 596 0, 597 0, 598 NULL, 0, 599 &completion_reason, 600 &cb_flags, flags | USBA_FLAGS_PRIVILEGED | USB_FLAGS_SLEEP); 601 602 if (rval == USB_SUCCESS) { 603 mutex_enter(&usba_device->usb_mutex); 604 usba_device->usb_cfg_value = confdescr.bConfigurationValue; 605 usba_device->usb_active_cfg_ndx = cfg_index; 606 usba_device->usb_cfg = usba_device->usb_cfg_array[cfg_index]; 607 usba_device->usb_cfg_length = confdescr.wTotalLength; 608 mutex_exit(&usba_device->usb_mutex); 609 610 /* update the configuration property */ 611 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 612 "configuration#", usba_device->usb_cfg_value); 613 } 614 615 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 616 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 617 618 usba_release_ph_data(ph_impl); 619 620 return (rval); 621 } 622 623 624 625 /* 626 * usb_get_cfg(): 627 * get configuration value 628 * 629 * Arguments: 630 * dip - pointer to devinfo of the client 631 * cfg_value - current config value 632 * flags - none, always blocks 633 * 634 * Return Values: 635 * USB_SUCCESS: - config value was retrieved 636 * USB_FAILURE: - config value could not be retrieved 637 * USB_* - refer to usbai.h 638 */ 639 int 640 usb_get_cfg(dev_info_t *dip, 641 uint_t *cfgval, 642 usb_flags_t flags) 643 { 644 int rval; 645 usb_cr_t completion_reason; 646 mblk_t *data = NULL; 647 usb_cb_flags_t cb_flags; 648 usb_pipe_handle_t ph; 649 650 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 651 "usb_get_cfg: %s uf = 0x%x", ddi_node_name(dip), flags); 652 653 if ((cfgval == NULL) || (dip == NULL)) { 654 655 return (USB_INVALID_ARGS); 656 } 657 658 ph = usba_get_dflt_pipe_handle(dip); 659 660 /* 661 * get the cfg value 662 */ 663 rval = usb_pipe_sync_ctrl_xfer(dip, ph, 664 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_DEV, 665 USB_REQ_GET_CFG, 666 0, 667 0, 668 1, /* returns one byte of data */ 669 &data, 0, 670 &completion_reason, 671 &cb_flags, flags); 672 673 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 674 "rval=%d cb_flags=%d cr=%d", rval, cb_flags, completion_reason); 675 676 if ((rval == USB_SUCCESS) && data && 677 ((data->b_wptr - data->b_rptr) == 1)) { 678 *cfgval = *(data->b_rptr); 679 } else { 680 *cfgval = 1; 681 if (rval == USB_SUCCESS) { 682 rval = USB_FAILURE; 683 } 684 } 685 686 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 687 "usb_get_cfg: %s cfgval=%d", ddi_node_name(dip), *cfgval); 688 689 freemsg(data); 690 691 return (rval); 692 } 693 694 695 /* 696 * usb_get_current_cfgidx: 697 * get current current config index 698 */ 699 uint_t 700 usb_get_current_cfgidx(dev_info_t *dip) 701 { 702 usba_device_t *usba_device = usba_get_usba_device(dip); 703 uint_t ndx; 704 705 mutex_enter(&usba_device->usb_mutex); 706 ndx = usba_device->usb_active_cfg_ndx; 707 mutex_exit(&usba_device->usb_mutex); 708 709 return (ndx); 710 } 711 712 713 /* 714 * usb_get_if_number: 715 * get usb interface number of current OS device node. 716 * 717 * Arguments: 718 * dip - pointer to devinfo of the client 719 * 720 * Return Values: 721 * USB_COMBINED_NODE if the driver is responsible for the entire 722 * device and this dip doesn't correspond to a device node. 723 * USB_DEVICE_NODE if the driver is responsible for the entire device 724 * and this dip corresponds to a device node. 725 * interface number: otherwise. 726 */ 727 int 728 usb_get_if_number(dev_info_t *dip) 729 { 730 int interface_num; 731 usba_device_t *usba_device = usba_get_usba_device(dip); 732 usb_dev_descr_t *usb_dev_descr; 733 734 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 735 "usb_get_if_number: dip = 0x%p", dip); 736 737 /* not quite right but we can't return a negative return value */ 738 if (dip == NULL) { 739 740 return (0); 741 } 742 743 if (usba_device) { 744 usb_dev_descr = usba_device->usb_dev_descr; 745 } else { 746 747 return (0); 748 } 749 750 interface_num = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 751 DDI_PROP_DONTPASS, "interface", USB_COMBINED_NODE); 752 753 if (interface_num == USB_COMBINED_NODE) { 754 if (!(((usb_dev_descr->bDeviceClass == USB_CLASS_HUB) || 755 (usb_dev_descr->bDeviceClass == 0)) && 756 (usba_device->usb_n_cfgs == 1) && 757 (usba_device->usb_n_ifs == 1))) { 758 interface_num = USB_DEVICE_NODE; 759 } 760 } 761 762 return (interface_num); 763 } 764 765 766 boolean_t 767 usb_owns_device(dev_info_t *dip) 768 { 769 int interface_num = usb_get_if_number(dip); 770 771 return (interface_num < 0 ? B_TRUE : B_FALSE); 772 } 773 774 775 uint8_t 776 usba_get_ifno(dev_info_t *dip) 777 { 778 int interface_num = usb_get_if_number(dip); 779 780 return (interface_num < 0 ? 0 : interface_num); 781 } 782 783 784 /* 785 * usb_set_alt_if: 786 * set the alternate interface number. Issues USB_REQ_SET_IF 787 * This function will access the device 788 * 789 * Arguments: 790 * dip - pointer to devinfo of the client 791 * if_number - interface number 792 * alt_number - alternate interface number 793 * flags - USB_FLAGS_SLEEP: 794 * wait for completion 795 * cb - if USB_FLAGS_SLEEP has not been specified 796 * this callback function will be called on 797 * completion. This callback may be NULL 798 * and no notification of completion will then 799 * be provided. 800 * cb_arg - 2nd argument to callback function. 801 * 802 * 803 * return values: 804 * USB_SUCCESS - alternate was set 805 * USB_FAILURE - alternate could not be set because pipes 806 * were still open or some access error occurred 807 * USB_* - refer to usbai.h 808 * 809 * Note: 810 * we can't easily check if all pipes to endpoints for this interface 811 * are closed since we don't have a map of which endpoints belong 812 * to which interface. If we had this map, we would need to update 813 * this on each alternative or configuration switch 814 */ 815 int 816 usb_set_alt_if(dev_info_t *dip, 817 uint_t interface, 818 uint_t alt_number, 819 usb_flags_t usb_flags, 820 void (*cb)( 821 usb_pipe_handle_t ph, 822 usb_opaque_t arg, 823 int rval, 824 usb_cb_flags_t flags), 825 usb_opaque_t cb_arg) 826 { 827 usb_pipe_handle_t ph; 828 829 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 830 "usb_set_alt_if: %s%d, if = %d alt = %d, uf = 0x%x", 831 ddi_driver_name(dip), ddi_get_instance(dip), 832 interface, alt_number, usb_flags); 833 834 if (dip == NULL) { 835 836 return (USB_INVALID_ARGS); 837 } 838 839 if ((usb_flags & USB_FLAGS_SLEEP) && servicing_interrupt()) { 840 841 return (USB_INVALID_CONTEXT); 842 } 843 844 ph = usba_get_dflt_pipe_handle(dip); 845 if (usba_hold_ph_data(ph) == NULL) { 846 847 return (USB_INVALID_PIPE); 848 } 849 850 return (usba_pipe_setup_func_call(dip, 851 usba_sync_set_alt_if, (usba_ph_impl_t *)ph, 852 (usb_opaque_t)((uintptr_t)((interface << 8) | alt_number)), 853 usb_flags, cb, cb_arg)); 854 } 855 856 857 static int 858 usba_sync_set_alt_if(dev_info_t *dip, 859 usba_ph_impl_t *ph_impl, 860 usba_pipe_async_req_t *request, 861 usb_flags_t flags) 862 { 863 int rval; 864 usb_cr_t completion_reason; 865 usb_cb_flags_t cb_flags; 866 usb_opaque_t arg = request->arg; 867 int interface = ((uintptr_t)arg >> 8) & 0xff; 868 int alt_number = (uintptr_t)arg & 0xff; 869 usba_pipe_handle_data_t *ph_data = usba_get_ph_data( 870 (usb_pipe_handle_t)ph_impl); 871 872 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 873 "usb_set_alt_if: %s, interface#=0x%x, alt#=0x%x, " 874 "uf=0x%x", ddi_node_name(dip), interface, 875 alt_number, flags); 876 877 /* if we don't own the device, we must own the interface */ 878 if (!usb_owns_device(dip) && 879 (interface != usb_get_if_number(dip))) { 880 usba_release_ph_data(ph_data->p_ph_impl); 881 882 return (USB_INVALID_PERM); 883 } 884 885 /* set the alternate setting */ 886 rval = usb_pipe_sync_ctrl_xfer(dip, usba_get_dflt_pipe_handle(dip), 887 USB_DEV_REQ_HOST_TO_DEV | USB_DEV_REQ_RCPT_IF, 888 USB_REQ_SET_IF, 889 alt_number, 890 interface, 891 0, 892 NULL, 0, 893 &completion_reason, 894 &cb_flags, flags | USB_FLAGS_SLEEP); 895 896 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 897 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 898 899 usba_release_ph_data(ph_data->p_ph_impl); 900 901 return (rval); 902 } 903 904 905 /* 906 * usb_get_alt_if: 907 * get the alternate interface number. Issues USB_REQ_GET_IF 908 * This function will access the device and block 909 * 910 * Arguments: 911 * dip - pointer to devinfo of the client 912 * if_number - interface number 913 * alt_number - alternate interface number 914 * flags - none but USB_FLAGS_SLEEP may be passed 915 * 916 * return values: 917 * USB_SUCCESS: alternate was set 918 * USB_FAILURE: alternate could not be set because pipes 919 * were still open or some access error occurred 920 */ 921 int 922 usb_get_alt_if(dev_info_t *dip, 923 uint_t if_number, 924 uint_t *alt_number, 925 usb_flags_t flags) 926 { 927 int rval; 928 usb_cr_t completion_reason; 929 mblk_t *data = NULL; 930 usb_cb_flags_t cb_flags; 931 usb_pipe_handle_t ph; 932 933 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 934 "usb_get_alt_if: %s, interface# = 0x%x, altp = 0x%p, " 935 "uf = 0x%x", ddi_node_name(dip), if_number, 936 alt_number, flags); 937 938 if ((alt_number == NULL) || (dip == NULL)) { 939 940 return (USB_INVALID_ARGS); 941 } 942 943 ph = usba_get_dflt_pipe_handle(dip); 944 945 /* 946 * get the alternate setting 947 */ 948 rval = usb_pipe_sync_ctrl_xfer(dip, ph, 949 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_IF, 950 USB_REQ_GET_IF, 951 0, 952 if_number, 953 1, /* returns one byte of data */ 954 &data, 0, 955 &completion_reason, 956 &cb_flags, flags); 957 958 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 959 "rval=%d cb_flags=%d cr=%d", rval, cb_flags, completion_reason); 960 961 if ((rval == USB_SUCCESS) && data && 962 ((data->b_wptr - data->b_rptr) == 1)) { 963 *alt_number = *(data->b_rptr); 964 } else { 965 *alt_number = 0; 966 if (rval == USB_SUCCESS) { 967 rval = USB_FAILURE; 968 } 969 } 970 971 freemsg(data); 972 973 return (rval); 974 } 975 976 977 /* 978 * usba_get_cfg_cloud: 979 * Get descriptor cloud for a given configuration. 980 * 981 * Arguments: 982 * dip - pointer to devinfo of the client 983 * default_ph - default pipe handle 984 * cfg - which configuration to retrieve raw cloud of 985 * 986 * Returns: 987 * on success: mblock containing the raw data. Caller must free. 988 * on failure: NULL 989 */ 990 static mblk_t * 991 usba_get_cfg_cloud(dev_info_t *dip, usb_pipe_handle_t default_ph, int cfg) 992 { 993 usb_cr_t completion_reason; 994 usb_cb_flags_t cb_flags; 995 usb_cfg_descr_t cfg_descr; 996 mblk_t *pdata = NULL; 997 998 if (usb_pipe_sync_ctrl_xfer(dip, default_ph, 999 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_TYPE_STANDARD, 1000 USB_REQ_GET_DESCR, 1001 USB_DESCR_TYPE_SETUP_CFG | cfg, 1002 0, 1003 USB_CFG_DESCR_SIZE, 1004 &pdata, 1005 0, 1006 &completion_reason, 1007 &cb_flags, 1008 0) != USB_SUCCESS) { 1009 1010 freemsg(pdata); 1011 1012 return (NULL); 1013 } 1014 1015 (void) usb_parse_cfg_descr(pdata->b_rptr, 1016 pdata->b_wptr - pdata->b_rptr, &cfg_descr, USB_CFG_DESCR_SIZE); 1017 freemsg(pdata); 1018 pdata = NULL; 1019 1020 if (usb_pipe_sync_ctrl_xfer(dip, default_ph, 1021 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_TYPE_STANDARD, 1022 USB_REQ_GET_DESCR, 1023 USB_DESCR_TYPE_SETUP_CFG | cfg, 1024 0, 1025 cfg_descr.wTotalLength, 1026 &pdata, 1027 0, 1028 &completion_reason, 1029 &cb_flags, 1030 0) != USB_SUCCESS) { 1031 1032 freemsg(pdata); 1033 1034 return (NULL); 1035 } 1036 1037 return (pdata); 1038 } 1039 1040 /* 1041 * usb_check_same_device: 1042 * Check if the device connected to the port is the same as 1043 * the previous device that was in the port. The previous device is 1044 * represented by the dip on record for the port. Print a message 1045 * if the device is different. If device_string arg is not NULL, it is 1046 * included in the message. Can block. 1047 * 1048 * Arguments: 1049 * dip - pointer to devinfo of the client 1050 * log_handle - handle to which messages are logged 1051 * log_level - one of USB_LOG_* 1052 * log_mask - logging mask 1053 * check_mask - one mask containing things to check: 1054 * USB_CHK_BASIC: empty mask; 1055 * these checks are always done. 1056 * USB_CHK_VIDPID: 1057 * check vid, pid only. 1058 * USB_CHK_SERIAL: check match on device 1059 * serial number. 1060 * USB_CHK_CFG: check all raw config 1061 * clouds for a match. 1062 * NOTE: descr length and content always checked 1063 * device_string - Device string to appear in error message 1064 * 1065 * return values: 1066 * USB_SUCCESS: same device 1067 * USB_INVALID_VERSION not same device 1068 * USB_FAILURE: Failure processing request 1069 * USB_INVALID_ARG: dip is invalid 1070 */ 1071 int 1072 usb_check_same_device(dev_info_t *dip, usb_log_handle_t log_handle, 1073 int log_level, int log_mask, uint_t check_mask, char *device_string) 1074 { 1075 usb_dev_descr_t usb_dev_descr; 1076 usba_device_t *usba_device; 1077 mblk_t *pdata = NULL; 1078 uint16_t length; 1079 int rval; 1080 char *buf; 1081 usb_cr_t completion_reason; 1082 usb_cb_flags_t cb_flags; 1083 boolean_t match = B_TRUE; 1084 usb_pipe_handle_t def_ph; 1085 1086 if (dip == NULL) { 1087 1088 return (USB_INVALID_ARGS); 1089 } 1090 1091 usba_device = usba_get_usba_device(dip); 1092 length = usba_device->usb_dev_descr->bLength; 1093 def_ph = usba_get_dflt_pipe_handle(dip); 1094 ASSERT(def_ph); 1095 1096 /* get the "new" device descriptor */ 1097 rval = usb_pipe_sync_ctrl_xfer(dip, def_ph, 1098 USB_DEV_REQ_DEV_TO_HOST | 1099 USB_DEV_REQ_TYPE_STANDARD, 1100 USB_REQ_GET_DESCR, /* bRequest */ 1101 USB_DESCR_TYPE_SETUP_DEV, /* wValue */ 1102 0, /* wIndex */ 1103 length, /* wLength */ 1104 &pdata, 0, 1105 &completion_reason, 1106 &cb_flags, USB_FLAGS_SLEEP); 1107 1108 if (rval != USB_SUCCESS) { 1109 if (!((completion_reason == USB_CR_DATA_OVERRUN) && (pdata))) { 1110 USB_DPRINTF_L3(DPRINT_MASK_USBA, usbai_log_handle, 1111 "getting device descriptor failed (%d)", rval); 1112 freemsg(pdata); 1113 1114 return (USB_FAILURE); 1115 } 1116 } 1117 1118 ASSERT(pdata != NULL); 1119 1120 (void) usb_parse_dev_descr(pdata->b_rptr, 1121 pdata->b_wptr - pdata->b_rptr, &usb_dev_descr, 1122 sizeof (usb_dev_descr_t)); 1123 1124 freemsg(pdata); 1125 pdata = NULL; 1126 1127 /* Always check the device descriptor length. */ 1128 if (usb_dev_descr.bLength != length) { 1129 match = B_FALSE; 1130 } 1131 1132 if ((match == B_TRUE) && (check_mask & USB_CHK_VIDPID)) { 1133 match = (usba_device->usb_dev_descr->idVendor == 1134 usb_dev_descr.idVendor) && 1135 (usba_device->usb_dev_descr->idProduct == 1136 usb_dev_descr.idProduct); 1137 } else if (bcmp((char *)usba_device->usb_dev_descr, 1138 (char *)&usb_dev_descr, length) != 0) { 1139 match = B_FALSE; 1140 } 1141 1142 /* if requested & this device has a serial number check and compare */ 1143 if ((match == B_TRUE) && ((check_mask & USB_CHK_SERIAL) != 0) && 1144 (usba_device->usb_serialno_str != NULL)) { 1145 buf = kmem_alloc(USB_MAXSTRINGLEN, KM_SLEEP); 1146 if (usb_get_string_descr(dip, USB_LANG_ID, 1147 usb_dev_descr.iSerialNumber, buf, 1148 USB_MAXSTRINGLEN) == USB_SUCCESS) { 1149 match = 1150 (strcmp(buf, usba_device->usb_serialno_str) == 0); 1151 } 1152 kmem_free(buf, USB_MAXSTRINGLEN); 1153 } 1154 1155 if ((match == B_TRUE) && (check_mask & USB_CHK_CFG)) { 1156 1157 uint8_t num_cfgs = usb_dev_descr.bNumConfigurations; 1158 uint8_t cfg; 1159 mblk_t *cloud; 1160 1161 for (cfg = 0; cfg < num_cfgs; cfg++) { 1162 cloud = usba_get_cfg_cloud(dip, def_ph, cfg); 1163 if (cloud == NULL) { 1164 USB_DPRINTF_L3(DPRINT_MASK_USBA, 1165 usbai_log_handle, 1166 "Could not retrieve config cloud for " 1167 "comparison"); 1168 break; 1169 } 1170 1171 if (bcmp((char *)cloud->b_rptr, 1172 usba_device->usb_cfg_array[cfg], 1173 cloud->b_wptr - cloud->b_rptr) != 0) { 1174 freemsg(cloud); 1175 break; 1176 } 1177 1178 freemsg(cloud); 1179 } 1180 if (cfg != num_cfgs) { 1181 match = B_FALSE; 1182 } 1183 } 1184 1185 if (match == B_FALSE) { 1186 boolean_t allocated_here = (device_string == NULL); 1187 if (allocated_here) { 1188 device_string = 1189 kmem_zalloc(USB_MAXSTRINGLEN, USB_FLAGS_SLEEP); 1190 (void) usba_get_mfg_prod_sn_str(dip, device_string, 1191 USB_MAXSTRINGLEN); 1192 } 1193 if (device_string[0] != '\0') { 1194 (void) usb_log(log_handle, log_level, log_mask, 1195 "Cannot access %s. Please reconnect.", 1196 device_string); 1197 } else { 1198 (void) usb_log(log_handle, log_level, log_mask, 1199 "Device is not identical to the " 1200 "previous one this port.\n" 1201 "Please disconnect and reconnect"); 1202 } 1203 if (allocated_here) { 1204 kmem_free(device_string, USB_MAXSTRINGLEN); 1205 } 1206 1207 return (USB_INVALID_VERSION); 1208 } 1209 1210 return (USB_SUCCESS); 1211 } 1212 1213 1214 /* 1215 * usb_pipe_get_state: 1216 * Return the state of the pipe 1217 * 1218 * Arguments: 1219 * pipe_handle - pipe_handle pointer 1220 * pipe_state - pointer to copy pipe state to 1221 * flags: 1222 * not used other than to check context 1223 * 1224 * Return Values: 1225 * USB_SUCCESS - port state returned 1226 * USB_* - refer to usbai.h 1227 */ 1228 int 1229 usb_pipe_get_state(usb_pipe_handle_t pipe_handle, 1230 usb_pipe_state_t *pipe_state, 1231 usb_flags_t usb_flags) 1232 { 1233 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1234 1235 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1236 "usb_pipe_get_state: ph_data=0x%p uf=0x%x", ph_data, usb_flags); 1237 1238 if (pipe_state == NULL) { 1239 if (ph_data) { 1240 usba_release_ph_data(ph_data->p_ph_impl); 1241 } 1242 1243 return (USB_INVALID_ARGS); 1244 } 1245 1246 if (ph_data == NULL) { 1247 *pipe_state = USB_PIPE_STATE_CLOSED; 1248 1249 return (USB_SUCCESS); 1250 } 1251 1252 mutex_enter(&ph_data->p_mutex); 1253 *pipe_state = usba_get_ph_state(ph_data); 1254 mutex_exit(&ph_data->p_mutex); 1255 1256 usba_release_ph_data(ph_data->p_ph_impl); 1257 1258 return (USB_SUCCESS); 1259 } 1260 1261 1262 /* 1263 * usba_pipe_get_policy: 1264 * Return a pipe's policy 1265 * 1266 * Arguments: 1267 * pipe_handle - pipe_handle pointer 1268 * 1269 * Return Values: 1270 * On success: the pipe's policy 1271 * On failure: NULL 1272 */ 1273 usb_pipe_policy_t 1274 *usba_pipe_get_policy(usb_pipe_handle_t pipe_handle) 1275 { 1276 usb_pipe_policy_t *pp = NULL; 1277 1278 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1279 1280 if (ph_data) { 1281 pp = &ph_data->p_policy; 1282 1283 usba_release_ph_data(ph_data->p_ph_impl); 1284 } 1285 1286 return (pp); 1287 } 1288 1289 1290 /* 1291 * usb_ep_num: 1292 * Return the endpoint number for a given pipe handle 1293 * 1294 * Arguments: 1295 * pipe_handle - pipe_handle pointer 1296 * 1297 * Return Values: 1298 * endpoint number 1299 */ 1300 int 1301 usb_ep_num(usb_pipe_handle_t pipe_handle) 1302 { 1303 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1304 int ep_num; 1305 1306 if (ph_data == NULL) { 1307 1308 return (USB_INVALID_PIPE); 1309 } 1310 1311 mutex_enter(&ph_data->p_mutex); 1312 ep_num = ph_data->p_ep.bEndpointAddress & USB_EP_NUM_MASK; 1313 mutex_exit(&ph_data->p_mutex); 1314 1315 usba_release_ph_data(ph_data->p_ph_impl); 1316 1317 return (ep_num); 1318 } 1319 1320 1321 /* 1322 * usb_get_status 1323 * Issues USB_REQ_GET_STATUS to device/endpoint/interface 1324 * and report in "status" arg. 1325 * 1326 * status reported for a "device" is 1327 * RemoteWakeup enabled 1328 * SelfPowered device? 1329 * 1330 * status reported for an "interface" is NONE. 1331 * status reported for an "endpoint" is 1332 * HALT set (device STALLED?) 1333 * 1334 * Arguments: 1335 * dip - pointer to devinfo of the client 1336 * ph - pipe handle 1337 * type - bmRequestType to be used 1338 * what - 0 for device, otherwise interface or ep number 1339 * status - user supplied pointer for storing the status 1340 * flags - USB_FLAGS_SLEEP (mandatory) 1341 * 1342 * Return Values: 1343 * valid usb_status_t or USB_FAILURE 1344 */ 1345 int 1346 usb_get_status(dev_info_t *dip, 1347 usb_pipe_handle_t ph, 1348 uint_t type, /* bmRequestType */ 1349 uint_t what, /* 0, interface, ept number */ 1350 uint16_t *status, 1351 usb_flags_t flags) 1352 { 1353 int rval; 1354 usb_cr_t completion_reason; 1355 mblk_t *data = NULL; 1356 usb_cb_flags_t cb_flags; 1357 1358 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1359 "usb_get_status: type = 0x%x, what = 0x%x, uf = 0x%x", 1360 type, what, flags); 1361 1362 if ((status == NULL) || (dip == NULL)) { 1363 1364 return (USB_INVALID_ARGS); 1365 } 1366 if (ph == NULL) { 1367 1368 return (USB_INVALID_PIPE); 1369 } 1370 1371 type |= USB_DEV_REQ_DEV_TO_HOST; 1372 1373 /* get the status */ 1374 rval = usb_pipe_sync_ctrl_xfer(dip, ph, 1375 type, 1376 USB_REQ_GET_STATUS, 1377 0, 1378 what, 1379 USB_GET_STATUS_LEN, /* status is fixed 2 bytes long */ 1380 &data, 0, 1381 &completion_reason, &cb_flags, flags); 1382 1383 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1384 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 1385 1386 if ((rval == USB_SUCCESS) && data && 1387 ((data->b_wptr - data->b_rptr) == USB_GET_STATUS_LEN)) { 1388 *status = (*(data->b_rptr + 1) << 8) | *(data->b_rptr); 1389 } else { 1390 *status = 0; 1391 if (rval == USB_SUCCESS) { 1392 rval = USB_FAILURE; 1393 } 1394 } 1395 1396 freemsg(data); 1397 1398 return (rval); 1399 } 1400 1401 1402 /* 1403 * usb_clear_feature: 1404 * Issue USB_REQ_CLEAR_FEATURE to endpoint/device/interface 1405 * 1406 * Arguments: 1407 * dip - pointer to devinfo of the client 1408 * ph - pipe handle pointer 1409 * type - bmRequestType to be used 1410 * feature - feature to be cleared 1411 * what - 0 for device, otherwise interface or ep number 1412 * flags - none (but will sleep) 1413 * 1414 * Return Values: 1415 * USB_SUCCESS - on doing a successful clear feature 1416 * USB_FAILURE - on failure 1417 * USB_* - refer to usbai.h 1418 */ 1419 int 1420 usb_clear_feature(dev_info_t *dip, 1421 usb_pipe_handle_t ph, 1422 uint_t type, /* bmRequestType */ 1423 uint_t feature, 1424 uint_t what, /* 0, interface, ept number */ 1425 usb_flags_t flags) 1426 { 1427 int rval; 1428 usb_cr_t completion_reason; 1429 usb_cb_flags_t cb_flags; 1430 1431 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1432 "usb_clear_feature: type = 0x%x, feature = 0x%x, what = 0x%x " 1433 "uf = 0x%x", type, feature, what, flags); 1434 1435 if (dip == NULL) { 1436 1437 return (USB_INVALID_ARGS); 1438 } 1439 if (ph == NULL) { 1440 1441 return (USB_INVALID_PIPE); 1442 } 1443 1444 /* issue Clear feature */ 1445 rval = usb_pipe_sync_ctrl_xfer(dip, ph, 1446 type, 1447 USB_REQ_CLEAR_FEATURE, 1448 feature, 1449 what, 1450 0, 1451 NULL, 0, 1452 &completion_reason, 1453 &cb_flags, flags | USB_FLAGS_SLEEP); 1454 1455 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1456 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 1457 1458 return (rval); 1459 } 1460 1461 1462 /* 1463 * usb_clr_feature: 1464 * Issue USB_REQ_CLEAR_FEATURE to endpoint/device/interface 1465 * 1466 * Arguments: 1467 * dip - pointer to devinfo of the client 1468 * type - bmRequestType to be used 1469 * feature - feature to be cleared 1470 * what - 0 for device, otherwise interface or ep number 1471 * flags - USB_FLAGS_SLEEP: 1472 * wait for completion 1473 * cb - if USB_FLAGS_SLEEP has not been specified 1474 * this callback function will be called on 1475 * completion. This callback may be NULL 1476 * and no notification of completion will then 1477 * be provided. 1478 * cb_arg - 2nd argument to callback function. 1479 * 1480 * 1481 * Return Values: 1482 * USB_SUCCESS - on doing a successful clear feature 1483 * USB_FAILURE - on failure 1484 * USB_* - refer to usbai.h 1485 */ 1486 int 1487 usb_clr_feature( 1488 dev_info_t *dip, 1489 uint_t type, /* bmRequestType */ 1490 uint_t feature, 1491 uint_t what, /* 0, interface, ept number */ 1492 usb_flags_t flags, 1493 void (*cb)( 1494 usb_pipe_handle_t ph, 1495 usb_opaque_t arg, 1496 int rval, 1497 usb_cb_flags_t flags), 1498 usb_opaque_t cb_arg) 1499 { 1500 usb_pipe_handle_t ph; 1501 1502 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1503 "usb_clr_feature: type = 0x%x, feature = 0x%x, what = 0x%x " 1504 "uf = 0x%x", type, feature, what, flags); 1505 1506 if (dip == NULL) { 1507 1508 return (USB_INVALID_ARGS); 1509 } 1510 1511 if ((flags & USB_FLAGS_SLEEP) && servicing_interrupt()) { 1512 1513 return (USB_INVALID_CONTEXT); 1514 } 1515 1516 ph = usba_get_dflt_pipe_handle(dip); 1517 if (usba_hold_ph_data(ph) == NULL) { 1518 1519 return (USB_INVALID_PIPE); 1520 } 1521 1522 return (usba_pipe_setup_func_call(dip, 1523 usba_sync_clear_feature, (usba_ph_impl_t *)ph, 1524 (usb_opaque_t)((uintptr_t)((type << 16 | feature << 8 | what))), 1525 flags, cb, cb_arg)); 1526 } 1527 1528 1529 static int 1530 usba_sync_clear_feature(dev_info_t *dip, 1531 usba_ph_impl_t *ph_impl, 1532 usba_pipe_async_req_t *req, 1533 usb_flags_t usb_flags) 1534 { 1535 uint_t n = (uint_t)((uintptr_t)(req->arg)); 1536 uint_t type = ((uint_t)n >> 16) & 0xff; 1537 uint_t feature = ((uint_t)n >> 8) & 0xff; 1538 uint_t what = (uint_t)n & 0xff; 1539 int rval; 1540 1541 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1542 "usb_sync_clear_feature: " 1543 "dip=0x%p ph=0x%p type=0x%x feature=0x%x what=0x%x fl=0x%x", 1544 dip, ph_impl, type, feature, what, usb_flags); 1545 1546 rval = usb_clear_feature(dip, (usb_pipe_handle_t)ph_impl, type, 1547 feature, what, usb_flags); 1548 1549 usba_release_ph_data(ph_impl); 1550 1551 return (rval); 1552 } 1553 1554 1555 /* 1556 * usb_async_req: 1557 * function used to dispatch a request to the taskq 1558 * 1559 * Arguments: 1560 * dip - pointer to devinfo node 1561 * func - pointer to function issued by taskq 1562 * flag - USB_FLAGS_SLEEP mostly 1563 * 1564 * Return Values: 1565 * USB_SUCCESS - on doing a successful taskq invocation 1566 * USB_FAILURE - on failure 1567 * USB_* - refer to usbai.h 1568 */ 1569 int 1570 usb_async_req(dev_info_t *dip, 1571 void (*func)(void *), 1572 void *arg, 1573 usb_flags_t flag) 1574 { 1575 int tq_flag; 1576 1577 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1578 "usb_async_req: dip=0x%p func=0x%p, arg=0x%p flag=0x%x", 1579 dip, func, arg, flag); 1580 1581 if ((dip == NULL) || (func == NULL)) { 1582 1583 return (USB_INVALID_ARGS); 1584 } 1585 tq_flag = (flag & USB_FLAGS_SLEEP) ? TQ_SLEEP : TQ_NOSLEEP; 1586 if (flag & USB_FLAGS_NOQUEUE) { 1587 tq_flag |= TQ_NOQUEUE; 1588 } 1589 1590 if (!taskq_dispatch(system_taskq, func, (void *)arg, 1591 tq_flag)) { 1592 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 1593 "usb_async_req: failure"); 1594 1595 return (USB_FAILURE); 1596 } 1597 1598 return (USB_SUCCESS); 1599 } 1600 1601 /* 1602 * usba_async_ph_req: 1603 * function used to dispatch a request to the ph taskq 1604 * 1605 * Arguments: 1606 * ph_data - pointer to pipe handle data 1607 * func - pointer to function issued by taskq 1608 * flag - USB_FLAGS_SLEEP or USB_FLAGS_NOSLEEP 1609 * 1610 * Return Values: 1611 * USB_SUCCESS - on doing a successful taskq invocation 1612 * USB_FAILURE - on failure 1613 * USB_* - refer to usbai.h 1614 * 1615 * Note: 1616 * If the caller specified USB_FLAGS_NOSLEEP, it must be 1617 * capable of reliably recovering from a failure return 1618 */ 1619 int 1620 usba_async_ph_req(usba_pipe_handle_data_t *ph_data, 1621 void (*func)(void *), 1622 void *arg, 1623 usb_flags_t flag) 1624 { 1625 int tq_flag; 1626 taskq_t *taskq; 1627 1628 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1629 "usba_async_ph_req: ph_data=0x%p func=0x%p, arg=0x%p flag=0x%x", 1630 ph_data, func, arg, flag); 1631 1632 if (func == NULL) { 1633 1634 return (USB_INVALID_ARGS); 1635 } 1636 1637 tq_flag = (flag & USB_FLAGS_SLEEP) ? TQ_SLEEP : TQ_NOSLEEP; 1638 1639 if (ph_data && ph_data->p_taskq) { 1640 taskq = ph_data->p_taskq; 1641 } else { 1642 taskq = system_taskq; 1643 tq_flag |= TQ_NOQUEUE; 1644 } 1645 1646 if (!taskq_dispatch(taskq, func, (void *)arg, tq_flag)) { 1647 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 1648 "usba_async_ph_req: failure"); 1649 1650 return (USB_FAILURE); 1651 } 1652 1653 return (USB_SUCCESS); 1654 } 1655 1656 1657 /* 1658 * utility functions to display CR, CB, return values 1659 */ 1660 typedef struct conv_table { 1661 int what; 1662 const char *name; 1663 } conv_table_t; 1664 1665 static const char * 1666 usba_get_name(conv_table_t *conv_table, int value) 1667 { 1668 int i; 1669 for (i = 0; conv_table[i].name != NULL; i++) { 1670 if (conv_table[i].what == value) { 1671 1672 return (conv_table[i].name); 1673 } 1674 } 1675 1676 return ("unknown"); 1677 } 1678 1679 1680 static conv_table_t cr_table[] = { 1681 { USB_CR_OK, "<no errors detected>" }, 1682 { USB_CR_CRC, "<crc error detected>" }, 1683 { USB_CR_BITSTUFFING, "<Bit stuffing violation>" }, 1684 { USB_CR_DATA_TOGGLE_MM, "<Data toggle PID did not match>" }, 1685 { USB_CR_STALL, "<Endpoint returned stall PID>" }, 1686 { USB_CR_DEV_NOT_RESP, "<Device not responding>" }, 1687 { USB_CR_PID_CHECKFAILURE, "<Check bits on PID failed>" }, 1688 { USB_CR_UNEXP_PID, "<Receive PID was not valid>" }, 1689 { USB_CR_DATA_OVERRUN, "<Data size exceeded>" }, 1690 { USB_CR_DATA_UNDERRUN, "<Less data recieved than requested>" }, 1691 { USB_CR_BUFFER_OVERRUN, "<Memory write can't keep up>" }, 1692 { USB_CR_BUFFER_UNDERRUN, "<Buffer underrun>" }, 1693 { USB_CR_TIMEOUT, "<Command timed out>" }, 1694 { USB_CR_NOT_ACCESSED, "<Not accessed by hardware>" }, 1695 { USB_CR_NO_RESOURCES, "<No resources>" }, 1696 { USB_CR_UNSPECIFIED_ERR, "<Unspecified usba or hcd error>" }, 1697 { USB_CR_STOPPED_POLLING, "<Intr/ISOC IN polling stopped>" }, 1698 { USB_CR_PIPE_CLOSING, "<Intr/ISOC IN pipe being closed>" }, 1699 { USB_CR_PIPE_RESET, "<Intr/ISOC IN pipe reset>" }, 1700 { USB_CR_NOT_SUPPORTED, "<Command not supported>" }, 1701 { USB_CR_FLUSHED, "<Req was flushed>" }, 1702 { USB_CR_HC_HARDWARE_ERR, "<USB host controller error>" }, 1703 { 0, NULL } 1704 }; 1705 1706 const char * 1707 usb_str_cr(usb_cr_t cr) 1708 { 1709 return (usba_get_name(cr_table, cr)); 1710 } 1711 1712 1713 static conv_table_t cb_flags_table[] = { 1714 { USB_CB_NO_INFO, "<callback processed>" }, 1715 { USB_CB_STALL_CLEARED, "<stall cleared>" }, 1716 { USB_CB_FUNCTIONAL_STALL, "<functional stall>" }, 1717 { USB_CB_PROTOCOL_STALL, "<protocol stall>" }, 1718 { USB_CB_RESET_PIPE, "<pipe reset>" }, 1719 { USB_CB_ASYNC_REQ_FAILED, "<thread could not be started>" }, 1720 { USB_CB_NO_RESOURCES, "<no resources>" }, 1721 { USB_CB_SUBMIT_FAILED, "<submit failed>" }, 1722 { USB_CB_INTR_CONTEXT, "<Callback executing in interrupt context>" }, 1723 { 0, NULL } 1724 }; 1725 1726 /*ARGSUSED*/ 1727 char * 1728 usb_str_cb_flags(usb_cb_flags_t cb_flags, char *buffer, size_t length) 1729 { 1730 int i; 1731 buffer[0] = '\0'; 1732 if (cb_flags == USB_CB_NO_INFO) { 1733 (void) strncpy(buffer, cb_flags_table[0].name, length); 1734 } else { 1735 for (i = 0; cb_flags_table[i].name != NULL; i++) { 1736 if (cb_flags & cb_flags_table[i].what) { 1737 (void) strncpy(&buffer[strlen(buffer)], 1738 cb_flags_table[0].name, 1739 length - strlen(buffer) - 1); 1740 } 1741 } 1742 } 1743 1744 return (buffer); 1745 } 1746 1747 1748 static conv_table_t pipe_state_table[] = { 1749 { USB_PIPE_STATE_CLOSED, "<closed>" }, 1750 { USB_PIPE_STATE_IDLE, "<idle>" }, 1751 { USB_PIPE_STATE_ACTIVE, "<active>" }, 1752 { USB_PIPE_STATE_ERROR, "<error>" }, 1753 { USB_PIPE_STATE_CLOSING, "<closing>" }, 1754 { 0, NULL } 1755 }; 1756 1757 const char * 1758 usb_str_pipe_state(usb_pipe_state_t state) 1759 { 1760 return (usba_get_name(pipe_state_table, state)); 1761 } 1762 1763 1764 static conv_table_t dev_state[] = { 1765 { USB_DEV_ONLINE, "<online>" }, 1766 { USB_DEV_DISCONNECTED, "<disconnected>" }, 1767 { USB_DEV_SUSPENDED, "<suspended>" }, 1768 { USB_DEV_PWRED_DOWN, "<powered down>" }, 1769 { 0, NULL } 1770 }; 1771 1772 const char * 1773 usb_str_dev_state(int state) 1774 { 1775 return (usba_get_name(dev_state, state)); 1776 } 1777 1778 1779 static conv_table_t rval_table[] = { 1780 { USB_SUCCESS, "<success>" }, 1781 { USB_FAILURE, "<failure>" }, 1782 { USB_NO_RESOURCES, "<no resources>" }, 1783 { USB_NO_BANDWIDTH, "<no bandwidth>" }, 1784 { USB_NOT_SUPPORTED, "<not supported>" }, 1785 { USB_PIPE_ERROR, "<pipe error>" }, 1786 { USB_INVALID_PIPE, "<invalid pipe>" }, 1787 { USB_NO_FRAME_NUMBER, "<no frame number>" }, 1788 { USB_INVALID_START_FRAME, "<invalid frame>" }, 1789 { USB_HC_HARDWARE_ERROR, "<hw error>" }, 1790 { USB_INVALID_REQUEST, "<invalid request>" }, 1791 { USB_INVALID_CONTEXT, "<invalid context>" }, 1792 { USB_INVALID_VERSION, "<invalid version>" }, 1793 { USB_INVALID_ARGS, "<invalid args>" }, 1794 { USB_INVALID_PERM, "<invalid perms>" }, 1795 { USB_BUSY, "<busy>" }, 1796 { 0, NULL } 1797 }; 1798 1799 const char * 1800 usb_str_rval(int rval) 1801 { 1802 return (usba_get_name(rval_table, rval)); 1803 } 1804 1805 1806 /* 1807 * function to convert USB return values to close errno 1808 */ 1809 static struct usb_rval2errno_entry { 1810 int rval; 1811 int Errno; 1812 } usb_rval2errno_table[] = { 1813 { USB_SUCCESS, 0 }, 1814 { USB_FAILURE, EIO }, 1815 { USB_NO_RESOURCES, ENOMEM }, 1816 { USB_NO_BANDWIDTH, EAGAIN }, 1817 { USB_NOT_SUPPORTED, ENOTSUP }, 1818 { USB_PIPE_ERROR, EIO }, 1819 { USB_INVALID_PIPE, EINVAL }, 1820 { USB_NO_FRAME_NUMBER, EINVAL }, 1821 { USB_INVALID_START_FRAME, EINVAL }, 1822 { USB_HC_HARDWARE_ERROR, EIO }, 1823 { USB_INVALID_REQUEST, EINVAL }, 1824 { USB_INVALID_CONTEXT, EINVAL }, 1825 { USB_INVALID_VERSION, EINVAL }, 1826 { USB_INVALID_ARGS, EINVAL }, 1827 { USB_INVALID_PERM, EACCES }, 1828 { USB_BUSY, EBUSY }, 1829 }; 1830 1831 #define USB_RVAL2ERRNO_TABLE_SIZE (sizeof (usb_rval2errno_table) / \ 1832 sizeof (struct usb_rval2errno_entry)) 1833 int 1834 usb_rval2errno(int rval) 1835 { 1836 int i; 1837 1838 for (i = 0; i < USB_RVAL2ERRNO_TABLE_SIZE; i++) { 1839 if (usb_rval2errno_table[i].rval == rval) { 1840 1841 return (usb_rval2errno_table[i].Errno); 1842 } 1843 } 1844 1845 return (EIO); 1846 } 1847 1848 1849 /* 1850 * serialization 1851 */ 1852 usb_serialization_t 1853 usb_init_serialization( 1854 dev_info_t *dip, 1855 uint_t flag) 1856 { 1857 usba_serialization_impl_t *impl_tokenp = kmem_zalloc( 1858 sizeof (usba_serialization_impl_t), KM_SLEEP); 1859 usba_device_t *usba_device; 1860 ddi_iblock_cookie_t cookie = NULL; 1861 1862 if (dip) { 1863 usba_device = usba_get_usba_device(dip); 1864 cookie = usba_hcdi_get_hcdi( 1865 usba_device->usb_root_hub_dip)->hcdi_iblock_cookie; 1866 } 1867 impl_tokenp->s_dip = dip; 1868 impl_tokenp->s_flag = flag; 1869 mutex_init(&impl_tokenp->s_mutex, NULL, MUTEX_DRIVER, cookie); 1870 cv_init(&impl_tokenp->s_cv, NULL, CV_DRIVER, NULL); 1871 1872 return ((usb_serialization_t)impl_tokenp); 1873 } 1874 1875 1876 void 1877 usb_fini_serialization( 1878 usb_serialization_t tokenp) 1879 { 1880 usba_serialization_impl_t *impl_tokenp; 1881 1882 if (tokenp) { 1883 impl_tokenp = (usba_serialization_impl_t *)tokenp; 1884 ASSERT(impl_tokenp->s_count == 0); 1885 cv_destroy(&impl_tokenp->s_cv); 1886 mutex_destroy(&impl_tokenp->s_mutex); 1887 kmem_free(impl_tokenp, sizeof (usba_serialization_impl_t)); 1888 } 1889 } 1890 1891 1892 /* 1893 * usb_serialize_access() permits single threaded access. 1894 * 1895 * If tokenp is initialized with USB_INIT_SER_CHECK_SAME_THREAD, 1896 * it is reentrant with respect to thread. The thread must 1897 * hold and release the same number of times. 1898 * 1899 * If tokenp is initialized without USB_INIT_SER_CHECK_SAME_THREAD, 1900 * it is not reentrant by the same thread. It is something like 1901 * a semaphore. 1902 */ 1903 int 1904 usb_serialize_access( 1905 usb_serialization_t tokenp, uint_t how_to_wait, uint_t delta_timeout) 1906 { 1907 int rval = 1; /* Must be initialized > 0 */ 1908 clock_t abs_timeout; 1909 usba_serialization_impl_t *impl_tokenp; 1910 1911 impl_tokenp = (usba_serialization_impl_t *)tokenp; 1912 1913 /* 1914 * Convert delta timeout in ms to absolute timeout in ticks, if used. 1915 */ 1916 if ((how_to_wait == USB_TIMEDWAIT) || 1917 (how_to_wait == USB_TIMEDWAIT_SIG)) { 1918 /* Convert timeout arg (in ms) to hz */ 1919 abs_timeout = ddi_get_lbolt() + 1920 drv_usectohz(delta_timeout * 1000); 1921 } 1922 1923 /* Get mutex after calc abs time, to count time waiting for mutex. */ 1924 mutex_enter(&impl_tokenp->s_mutex); 1925 1926 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1927 "usb_serialize_access: tok=0x%p dip=0x%p cnt=%d thr=0x%p, " 1928 "flg=0x%x, abs_tmo=0x%lx", 1929 impl_tokenp, impl_tokenp->s_dip, impl_tokenp->s_count, 1930 impl_tokenp->s_thread, how_to_wait, abs_timeout); 1931 1932 if ((impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD) == 0 || 1933 impl_tokenp->s_thread != curthread) { 1934 1935 /* 1936 * There are three ways to break out of the loop: 1937 * 1) Condition met (s_count == 0) - higher prio test 1938 * 2) kill(2) signal received (rval == 0) 1939 * 3) timeout occurred (rval == -1) 1940 * If condition met, whether or not signal or timeout occurred 1941 * take access. If condition not met, check other exit means. 1942 */ 1943 while (impl_tokenp->s_count != 0) { 1944 1945 /* cv_timedwait* returns -1 on timeout. */ 1946 /* cv_wait*_sig returns 0 on (kill(2)) signal. */ 1947 if (rval <= 0) { 1948 mutex_exit(&impl_tokenp->s_mutex); 1949 USB_DPRINTF_L4(DPRINT_MASK_USBA, 1950 usbai_log_handle, 1951 "usb_serialize_access: " 1952 "tok=0x%p exit due to %s", impl_tokenp, 1953 ((rval == 0) ? "signal" : "timeout")); 1954 1955 return (rval); 1956 } 1957 1958 switch (how_to_wait) { 1959 default: 1960 how_to_wait = USB_WAIT; 1961 /* FALLTHROUGH */ 1962 case USB_WAIT: 1963 cv_wait(&impl_tokenp->s_cv, 1964 &impl_tokenp->s_mutex); 1965 break; 1966 case USB_WAIT_SIG: 1967 rval = cv_wait_sig(&impl_tokenp->s_cv, 1968 &impl_tokenp->s_mutex); 1969 break; 1970 case USB_TIMEDWAIT: 1971 rval = cv_timedwait(&impl_tokenp->s_cv, 1972 &impl_tokenp->s_mutex, abs_timeout); 1973 break; 1974 case USB_TIMEDWAIT_SIG: 1975 rval = cv_timedwait_sig(&impl_tokenp->s_cv, 1976 &impl_tokenp->s_mutex, abs_timeout); 1977 break; 1978 } 1979 } 1980 1981 impl_tokenp->s_thread = curthread; 1982 } 1983 impl_tokenp->s_count++; 1984 1985 ASSERT(!(impl_tokenp->s_count > 1 && 1986 (impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD) == 0)); 1987 1988 mutex_exit(&impl_tokenp->s_mutex); 1989 1990 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1991 "usb_serialize_access exit: tok=0x%p thr=0x%p", impl_tokenp, 1992 curthread); 1993 1994 return (1); 1995 } 1996 1997 1998 /*ARGSUSED*/ 1999 int 2000 usb_try_serialize_access( 2001 usb_serialization_t tokenp, uint_t flag) 2002 { 2003 usba_serialization_impl_t *impl_tokenp = 2004 (usba_serialization_impl_t *)tokenp; 2005 mutex_enter(&impl_tokenp->s_mutex); 2006 2007 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2008 "usb_try_serialize_access: tok=0x%p dip=0x%p cnt=%d thr=0x%p", 2009 impl_tokenp, impl_tokenp->s_dip, impl_tokenp->s_count, curthread); 2010 2011 /* 2012 * If lock is not taken (s_count is 0), take it. 2013 * If lock is already taken, the thread is owner and lock 2014 * is reentrant, take it. 2015 * Otherwise, fail the access. 2016 */ 2017 if (!impl_tokenp->s_count || ((impl_tokenp->s_thread == curthread) && 2018 (impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD))) { 2019 impl_tokenp->s_thread = curthread; 2020 impl_tokenp->s_count++; 2021 2022 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2023 "usb_try_serialize_access success: tok=0x%p", impl_tokenp); 2024 mutex_exit(&impl_tokenp->s_mutex); 2025 2026 return (USB_SUCCESS); 2027 } 2028 2029 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2030 "usb_try_serialize_access failed: " 2031 "tok=0x%p dip=0x%p cnt=%d thr=0x%p", 2032 impl_tokenp, impl_tokenp->s_dip, impl_tokenp->s_count, 2033 impl_tokenp->s_thread); 2034 2035 mutex_exit(&impl_tokenp->s_mutex); 2036 2037 return (USB_FAILURE); 2038 } 2039 2040 2041 void 2042 usb_release_access( 2043 usb_serialization_t tokenp) 2044 { 2045 usba_serialization_impl_t *impl_tokenp = 2046 (usba_serialization_impl_t *)tokenp; 2047 mutex_enter(&impl_tokenp->s_mutex); 2048 2049 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2050 "usb_release_access: tok=0x%p dip=0x%p count=%d thr=0x%p", 2051 impl_tokenp, impl_tokenp->s_dip, impl_tokenp->s_count, curthread); 2052 2053 ASSERT(impl_tokenp->s_count > 0); 2054 2055 if (impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD) { 2056 if (impl_tokenp->s_thread != curthread) { 2057 USB_DPRINTF_L1(DPRINT_MASK_USBA, usbai_log_handle, 2058 "usb_release_access: release from wrong thread"); 2059 } 2060 ASSERT(impl_tokenp->s_thread == curthread); 2061 } 2062 2063 if (--impl_tokenp->s_count == 0) { 2064 impl_tokenp->s_thread = NULL; 2065 cv_broadcast(&impl_tokenp->s_cv); 2066 } 2067 mutex_exit(&impl_tokenp->s_mutex); 2068 } 2069 2070 2071 /* 2072 * usb_fail_checkpoint: 2073 * fail checkpoint as driver/device could not be quiesced 2074 */ 2075 /*ARGSUSED*/ 2076 void 2077 usb_fail_checkpoint(dev_info_t *dip, usb_flags_t flags) 2078 { 2079 usba_device_t *usba_device = usba_get_usba_device(dip); 2080 2081 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 2082 "usb_fail_checkpoint: %s%d", ddi_driver_name(dip), 2083 ddi_get_instance(dip)); 2084 2085 mutex_enter(&usba_device->usb_mutex); 2086 usba_device->usb_no_cpr++; 2087 mutex_exit(&usba_device->usb_mutex); 2088 } 2089 2090 2091 _NOTE(SCHEME_PROTECTS_DATA("unique per call", iocblk)) 2092 _NOTE(SCHEME_PROTECTS_DATA("unique per call", datab)) 2093 /* 2094 * usba_mk_mctl: 2095 * create a USB style M_CTL message, given an iocblk and a buffer 2096 * returns mblk_t * on success, NULL on failure 2097 */ 2098 mblk_t * 2099 usba_mk_mctl(struct iocblk mctlmsg, void *buf, size_t len) 2100 { 2101 mblk_t *bp1, *bp2; 2102 2103 if ((bp1 = allocb(sizeof (struct iocblk), BPRI_HI)) != NULL) { 2104 *((struct iocblk *)bp1->b_datap->db_base) = mctlmsg; 2105 bp1->b_datap->db_type = M_CTL; 2106 bp1->b_wptr += sizeof (struct iocblk); 2107 if (buf != NULL) { 2108 if ((bp2 = allocb(len, BPRI_HI)) != NULL) { 2109 bp1->b_cont = bp2; 2110 bcopy(buf, bp2->b_datap->db_base, len); 2111 bp2->b_wptr += len; 2112 } else { 2113 freemsg(bp1); 2114 bp1 = NULL; 2115 } 2116 } 2117 } 2118 2119 return (bp1); 2120 } 2121 2122 2123 #ifdef ALLOCB_TEST 2124 #undef allocb 2125 mblk_t * 2126 usba_test_allocb(size_t size, uint_t pri) 2127 { 2128 if (ddi_get_lbolt() & 0x1) { 2129 2130 return (NULL); 2131 } else { 2132 2133 return (allocb(size, pri)); 2134 } 2135 } 2136 #endif 2137