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