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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 /* 28 * USBA: Solaris USB Architecture support 29 * 30 * Utility functions 31 */ 32 #define USBA_FRAMEWORK 33 #include <sys/usb/usba/usba_impl.h> 34 #include <sys/usb/usba/hcdi_impl.h> 35 36 extern void usba_free_evdata(usba_evdata_t *); 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", (void *)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 (void *)&altif_data->altif_ep[i]); 230 231 return (&altif_data->altif_ep[i]); 232 } 233 } 234 } 235 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 236 "usb_get_ep_data: returning NULL"); 237 238 return (NULL); 239 } 240 241 242 /*ARGSUSED*/ 243 usb_ep_data_t * 244 usb_get_ep_data(dev_info_t *dip, 245 usb_client_dev_data_t *dev_datap, 246 uint_t interface, 247 uint_t alternate, 248 uint_t type, 249 uint_t dir) 250 { 251 return (usb_lookup_ep_data(dip, dev_datap, interface, 252 alternate, 0, type, dir)); 253 } 254 255 256 /* 257 * usb_get_string_descr: 258 * Function to read the string descriptor 259 * This function will access the device and block. 260 * 261 * Arguments: 262 * dip - pointer to devinfo of the client 263 * langid - LANGID to read different LOCALEs 264 * index - index to the string 265 * buf - user provided buffer for string descriptor 266 * buflen - user provided length of the buffer 267 * 268 * Return Values: 269 * USB_SUCCESS - descriptor is valid 270 * USB_FAILURE - full descriptor could not be retrieved 271 * USB_* - refer to usbai.h 272 */ 273 int 274 usb_get_string_descr(dev_info_t *dip, 275 uint16_t langid, 276 uint8_t index, 277 char *buf, 278 size_t buflen) 279 { 280 mblk_t *data = NULL; 281 uint16_t length; 282 int rval; 283 usb_cr_t completion_reason; 284 size_t len; 285 usb_cb_flags_t cb_flags; 286 287 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 288 "usb_get_string_descr: %s, langid=0x%x index=0x%x", 289 ddi_node_name(dip), langid, index); 290 291 if ((dip == NULL) || (buf == NULL) || (buflen == 0) || (index == 0)) { 292 293 return (USB_INVALID_ARGS); 294 } 295 296 /* 297 * determine the length of the descriptor 298 */ 299 rval = usb_pipe_sync_ctrl_xfer(dip, 300 usba_get_dflt_pipe_handle(dip), 301 USB_DEV_REQ_DEV_TO_HOST, 302 USB_REQ_GET_DESCR, 303 USB_DESCR_TYPE_STRING << 8 | index & 0xff, 304 langid, 305 4, 306 &data, USB_ATTRS_SHORT_XFER_OK, 307 &completion_reason, 308 &cb_flags, USB_FLAGS_SLEEP); 309 310 if (rval != USB_SUCCESS) { 311 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 312 "rval=%d cr=%d", rval, completion_reason); 313 314 goto done; 315 } 316 if (data->b_wptr - data->b_rptr == 0) { 317 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 318 "0 bytes received"); 319 320 goto done; 321 } 322 323 ASSERT(data); 324 length = *(data->b_rptr); 325 freemsg(data); 326 data = NULL; 327 328 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 329 "rval=%d, cr=%d, length=%d", rval, completion_reason, length); 330 331 /* 332 * if length is zero the next control request may fail. 333 * the HCD may not support a zero length control request 334 * and return an mblk_t which is NULL along with rval 335 * being USB_SUCCESS and "cr" being USB_CR_OK 336 */ 337 if (length < 2) { 338 rval = USB_FAILURE; 339 340 goto done; 341 } 342 343 rval = usb_pipe_sync_ctrl_xfer(dip, 344 usba_get_dflt_pipe_handle(dip), 345 USB_DEV_REQ_DEV_TO_HOST, 346 USB_REQ_GET_DESCR, 347 USB_DESCR_TYPE_STRING << 8 | index & 0xff, 348 langid, 349 length, 350 &data, USB_ATTRS_SHORT_XFER_OK, 351 &completion_reason, 352 &cb_flags, USB_FLAGS_SLEEP); 353 354 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 355 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 356 357 if ((data == NULL) || (rval != USB_SUCCESS)) { 358 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 359 "failed to get string descriptor (rval=%d cr=%d)", 360 rval, completion_reason); 361 362 goto done; 363 } 364 365 if ((length = data->b_wptr - data->b_rptr) != 0) { 366 len = usba_ascii_string_descr(data->b_rptr, length, buf, 367 buflen); 368 USB_DPRINTF_L4(DPRINT_MASK_USBA, 369 usbai_log_handle, "buf=%s buflen=%lu", buf, len); 370 371 ASSERT(len <= buflen); 372 } else { 373 rval = USB_FAILURE; 374 } 375 done: 376 freemsg(data); 377 378 return (rval); 379 } 380 381 382 /* 383 * usb_get_dev_descr: 384 * utility function to get device descriptor from usba_device 385 * 386 * Arguments: 387 * dip - pointer to devinfo of the client 388 * 389 * Return Values: 390 * usb_dev_descr - device descriptor or NULL 391 */ 392 usb_dev_descr_t * 393 usb_get_dev_descr(dev_info_t *dip) 394 { 395 usba_device_t *usba_device; 396 usb_dev_descr_t *usb_dev_descr = NULL; 397 398 if (dip) { 399 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 400 "usb_get_dev_descr: %s", ddi_node_name(dip)); 401 402 usba_device = usba_get_usba_device(dip); 403 mutex_enter(&usba_device->usb_mutex); 404 usb_dev_descr = usba_device->usb_dev_descr; 405 mutex_exit(&usba_device->usb_mutex); 406 } 407 408 return (usb_dev_descr); 409 } 410 411 412 /* 413 * usb_get_raw_cfg_data: 414 * utility function to get raw config descriptor from usba_device 415 * 416 * Arguments: 417 * dip - pointer to devinfo of the client 418 * length - pointer to copy the cfg length 419 * 420 * Return Values: 421 * usb_cfg - raw config descriptor 422 */ 423 uchar_t * 424 usb_get_raw_cfg_data(dev_info_t *dip, size_t *length) 425 { 426 usba_device_t *usba_device; 427 uchar_t *usb_cfg; 428 429 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 430 "usb_get_raw_cfg_data: %s", ddi_node_name(dip)); 431 432 if ((dip == NULL) || (length == NULL)) { 433 434 return (NULL); 435 } 436 437 usba_device = usba_get_usba_device(dip); 438 439 mutex_enter(&usba_device->usb_mutex); 440 usb_cfg = usba_device->usb_cfg; 441 *length = usba_device->usb_cfg_length; 442 mutex_exit(&usba_device->usb_mutex); 443 444 return (usb_cfg); 445 } 446 447 448 /* 449 * usb_get_addr: 450 * utility function to return current usb address, mostly 451 * for debugging purposes 452 * 453 * Arguments: 454 * dip - pointer to devinfo of the client 455 * 456 * Return Values: 457 * address - USB Device Address 458 */ 459 int 460 usb_get_addr(dev_info_t *dip) 461 { 462 int address = 0; 463 464 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 465 "usb_get_addr: %s", ddi_node_name(dip)); 466 467 if (dip) { 468 usba_device_t *usba_device = usba_get_usba_device(dip); 469 470 mutex_enter(&usba_device->usb_mutex); 471 address = usba_device->usb_addr; 472 mutex_exit(&usba_device->usb_mutex); 473 } 474 475 return (address); 476 } 477 478 479 /* 480 * usb_set_cfg(): 481 * set configuration, use with caution (issues USB_REQ_SET_CONFIG) 482 * Changing configuration will fail if pipes are still open or when 483 * invoked from a driver bound to an interface on a composite device. 484 * 485 * This function will access the device and block 486 * 487 * Arguments: 488 * dip - pointer to devinfo of the client 489 * cfg_index - config index 490 * cfg_value - config value to be set 491 * flags - USB_FLAGS_SLEEP: 492 * wait for completion 493 * cb - if USB_FLAGS_SLEEP has not been specified 494 * this callback function will be called on 495 * completion. This callback may be NULL 496 * and no notification of completion will then 497 * be provided. 498 * cb_arg - 2nd argument to callback function. 499 * 500 * Return Values: 501 * USB_SUCCESS: - new configuration was set 502 * USB_FAILURE: - new configuration could not be set 503 * USB_BUSY: - some pipes were open or there were children 504 * USB_* - refer to usbai.h 505 */ 506 int 507 usb_set_cfg(dev_info_t *dip, 508 uint_t cfg_index, 509 usb_flags_t usb_flags, 510 void (*cb)( 511 usb_pipe_handle_t ph, 512 usb_opaque_t arg, 513 int rval, 514 usb_cb_flags_t flags), 515 usb_opaque_t cb_arg) 516 { 517 usb_pipe_handle_t ph; 518 519 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 520 "usb_set_cfg: %s%d, cfg_index = 0x%x, uf = 0x%x", 521 ddi_driver_name(dip), ddi_get_instance(dip), cfg_index, 522 usb_flags); 523 524 if (dip == NULL) { 525 526 return (USB_INVALID_ARGS); 527 } 528 529 if ((usb_flags & USB_FLAGS_SLEEP) && servicing_interrupt()) { 530 531 return (USB_INVALID_CONTEXT); 532 } 533 534 if (!usb_owns_device(dip)) { 535 536 return (USB_INVALID_PERM); 537 } 538 539 ph = usba_get_dflt_pipe_handle(dip); 540 if (usba_hold_ph_data(ph) == NULL) { 541 542 return (USB_INVALID_PIPE); 543 } 544 545 return (usba_pipe_setup_func_call(dip, 546 usba_sync_set_cfg, (usba_ph_impl_t *)ph, 547 (usb_opaque_t)((uintptr_t)cfg_index), usb_flags, cb, cb_arg)); 548 } 549 550 551 static int 552 usba_sync_set_cfg(dev_info_t *dip, 553 usba_ph_impl_t *ph_impl, 554 usba_pipe_async_req_t *request, 555 usb_flags_t flags) 556 { 557 int rval; 558 usb_cr_t completion_reason; 559 usb_cb_flags_t cb_flags; 560 usba_device_t *usba_device; 561 int i, ph_open_cnt; 562 uint_t cfg_index = (uint_t)((uintptr_t)(request->arg)); 563 size_t size; 564 usb_cfg_descr_t confdescr; 565 dev_info_t *pdip; 566 567 usba_device = usba_get_usba_device(dip); 568 569 /* 570 * default pipe is still open 571 * all other pipes should be closed 572 */ 573 for (ph_open_cnt = 0, i = 1; i < USBA_N_ENDPOINTS; i++) { 574 if (usba_device->usb_ph_list[i].usba_ph_data) { 575 ph_open_cnt++; 576 break; 577 } 578 } 579 580 if (ph_open_cnt || ddi_get_child(dip)) { 581 usba_release_ph_data(ph_impl); 582 583 return (USB_BUSY); 584 } 585 586 /* 587 * check if the configuration meets the 588 * power budget requirement 589 */ 590 if (usba_is_root_hub(dip)) { 591 /* 592 * root hub should never be multi-configured. 593 * the code is here just to ensure 594 */ 595 usba_release_ph_data(ph_impl); 596 597 return (USB_FAILURE); 598 } 599 pdip = ddi_get_parent(dip); 600 601 /* 602 * increase the power budget value back to the unconfigured 603 * state to eliminate the influence of the old configuration 604 * before checking the new configuration; but remember to 605 * make a decrement before leaving this routine to restore 606 * the power consumption state of the device no matter it 607 * is in the new or old configuration 608 */ 609 usba_hubdi_incr_power_budget(pdip, usba_device); 610 611 if ((usba_hubdi_check_power_budget(pdip, usba_device, 612 cfg_index)) != USB_SUCCESS) { 613 usba_hubdi_decr_power_budget(pdip, usba_device); 614 615 usba_release_ph_data(ph_impl); 616 617 return (USB_FAILURE); 618 } 619 620 size = usb_parse_cfg_descr(usba_device->usb_cfg_array[cfg_index], 621 USB_CFG_DESCR_SIZE, &confdescr, USB_CFG_DESCR_SIZE); 622 623 /* hubdi should ensure that this descriptor is correct */ 624 ASSERT(size == USB_CFG_DESCR_SIZE); 625 626 /* set the configuration */ 627 rval = usb_pipe_sync_ctrl_xfer(dip, (usb_pipe_handle_t)ph_impl, 628 USB_DEV_REQ_HOST_TO_DEV, 629 USB_REQ_SET_CFG, 630 confdescr.bConfigurationValue, 631 0, 632 0, 633 NULL, 0, 634 &completion_reason, 635 &cb_flags, flags | USBA_FLAGS_PRIVILEGED | USB_FLAGS_SLEEP); 636 637 if (rval == USB_SUCCESS) { 638 mutex_enter(&usba_device->usb_mutex); 639 usba_device->usb_cfg_value = confdescr.bConfigurationValue; 640 usba_device->usb_active_cfg_ndx = cfg_index; 641 usba_device->usb_cfg = usba_device->usb_cfg_array[cfg_index]; 642 usba_device->usb_cfg_length = confdescr.wTotalLength; 643 mutex_exit(&usba_device->usb_mutex); 644 645 /* update the configuration property */ 646 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 647 "configuration#", usba_device->usb_cfg_value); 648 } 649 650 /* 651 * usba_device->usb_cfg always stores current configuration 652 * descriptor no matter SET_CFG request succeeded or not, 653 * so usba_hubdi_decr_power_budget can be done regardless 654 * of rval above 655 */ 656 usba_hubdi_decr_power_budget(pdip, usba_device); 657 658 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 659 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 660 661 usba_release_ph_data(ph_impl); 662 663 return (rval); 664 } 665 666 667 668 /* 669 * usb_get_cfg(): 670 * get configuration value 671 * 672 * Arguments: 673 * dip - pointer to devinfo of the client 674 * cfg_value - current config value 675 * flags - none, always blocks 676 * 677 * Return Values: 678 * USB_SUCCESS: - config value was retrieved 679 * USB_FAILURE: - config value could not be retrieved 680 * USB_* - refer to usbai.h 681 */ 682 int 683 usb_get_cfg(dev_info_t *dip, 684 uint_t *cfgval, 685 usb_flags_t flags) 686 { 687 int rval; 688 usb_cr_t completion_reason; 689 mblk_t *data = NULL; 690 usb_cb_flags_t cb_flags; 691 usb_pipe_handle_t ph; 692 693 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 694 "usb_get_cfg: %s uf = 0x%x", ddi_node_name(dip), flags); 695 696 if ((cfgval == NULL) || (dip == NULL)) { 697 698 return (USB_INVALID_ARGS); 699 } 700 701 ph = usba_get_dflt_pipe_handle(dip); 702 703 /* 704 * get the cfg value 705 */ 706 rval = usb_pipe_sync_ctrl_xfer(dip, ph, 707 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_DEV, 708 USB_REQ_GET_CFG, 709 0, 710 0, 711 1, /* returns one byte of data */ 712 &data, 0, 713 &completion_reason, 714 &cb_flags, flags); 715 716 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 717 "rval=%d cb_flags=%d cr=%d", rval, cb_flags, completion_reason); 718 719 if ((rval == USB_SUCCESS) && data && 720 ((data->b_wptr - data->b_rptr) == 1)) { 721 *cfgval = *(data->b_rptr); 722 } else { 723 *cfgval = 1; 724 if (rval == USB_SUCCESS) { 725 rval = USB_FAILURE; 726 } 727 } 728 729 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 730 "usb_get_cfg: %s cfgval=%d", ddi_node_name(dip), *cfgval); 731 732 freemsg(data); 733 734 return (rval); 735 } 736 737 738 /* 739 * usb_get_current_cfgidx: 740 * get current current config index 741 */ 742 uint_t 743 usb_get_current_cfgidx(dev_info_t *dip) 744 { 745 usba_device_t *usba_device = usba_get_usba_device(dip); 746 uint_t ndx; 747 748 mutex_enter(&usba_device->usb_mutex); 749 ndx = usba_device->usb_active_cfg_ndx; 750 mutex_exit(&usba_device->usb_mutex); 751 752 return (ndx); 753 } 754 755 756 /* 757 * usb_get_if_number: 758 * get usb interface number of current OS device node. 759 * 760 * Arguments: 761 * dip - pointer to devinfo of the client 762 * 763 * Return Values: 764 * USB_COMBINED_NODE if the driver is responsible for the entire 765 * device and this dip doesn't correspond to a device node. 766 * USB_DEVICE_NODE if the driver is responsible for the entire device 767 * and this dip corresponds to a device node. 768 * interface number: otherwise. 769 */ 770 int 771 usb_get_if_number(dev_info_t *dip) 772 { 773 int interface_num; 774 usba_device_t *usba_device = usba_get_usba_device(dip); 775 usb_dev_descr_t *usb_dev_descr; 776 777 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 778 "usb_get_if_number: dip = 0x%p", (void *)dip); 779 780 /* not quite right but we can't return a negative return value */ 781 if (dip == NULL) { 782 783 return (0); 784 } 785 786 if (usba_device) { 787 usb_dev_descr = usba_device->usb_dev_descr; 788 } else { 789 790 return (0); 791 } 792 793 interface_num = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 794 DDI_PROP_DONTPASS, "interface", USB_COMBINED_NODE); 795 796 if (interface_num == USB_COMBINED_NODE) { 797 if (!(((usb_dev_descr->bDeviceClass == USB_CLASS_HUB) || 798 (usb_dev_descr->bDeviceClass == 0)) && 799 (usba_device->usb_n_cfgs == 1) && 800 (usba_device->usb_n_ifs == 1))) { 801 interface_num = USB_DEVICE_NODE; 802 } 803 } 804 805 return (interface_num); 806 } 807 808 809 boolean_t 810 usb_owns_device(dev_info_t *dip) 811 { 812 int interface_num = usb_get_if_number(dip); 813 814 return (interface_num < 0 ? B_TRUE : B_FALSE); 815 } 816 817 818 /* check whether the interface is in this interface association */ 819 boolean_t 820 usba_check_if_in_ia(dev_info_t *dip, int n_if) 821 { 822 int first_if, if_count; 823 824 first_if = usb_get_if_number(dip); 825 if_count = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 826 DDI_PROP_DONTPASS, "interface-count", -1); 827 if_count += first_if; 828 829 return ((n_if >= first_if && n_if < if_count) ? B_TRUE : B_FALSE); 830 } 831 832 833 uint8_t 834 usba_get_ifno(dev_info_t *dip) 835 { 836 int interface_num = usb_get_if_number(dip); 837 838 return (interface_num < 0 ? 0 : interface_num); 839 } 840 841 842 /* 843 * usb_set_alt_if: 844 * set the alternate interface number. Issues USB_REQ_SET_IF 845 * This function will access the device 846 * 847 * Arguments: 848 * dip - pointer to devinfo of the client 849 * if_number - interface number 850 * alt_number - alternate interface number 851 * flags - USB_FLAGS_SLEEP: 852 * wait for completion 853 * cb - if USB_FLAGS_SLEEP has not been specified 854 * this callback function will be called on 855 * completion. This callback may be NULL 856 * and no notification of completion will then 857 * be provided. 858 * cb_arg - 2nd argument to callback function. 859 * 860 * 861 * return values: 862 * USB_SUCCESS - alternate was set 863 * USB_FAILURE - alternate could not be set because pipes 864 * were still open or some access error occurred 865 * USB_* - refer to usbai.h 866 * 867 * Note: 868 * we can't easily check if all pipes to endpoints for this interface 869 * are closed since we don't have a map of which endpoints belong 870 * to which interface. If we had this map, we would need to update 871 * this on each alternative or configuration switch 872 */ 873 int 874 usb_set_alt_if(dev_info_t *dip, 875 uint_t interface, 876 uint_t alt_number, 877 usb_flags_t usb_flags, 878 void (*cb)( 879 usb_pipe_handle_t ph, 880 usb_opaque_t arg, 881 int rval, 882 usb_cb_flags_t flags), 883 usb_opaque_t cb_arg) 884 { 885 usb_pipe_handle_t ph; 886 887 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 888 "usb_set_alt_if: %s%d, if = %d alt = %d, uf = 0x%x", 889 ddi_driver_name(dip), ddi_get_instance(dip), 890 interface, alt_number, usb_flags); 891 892 if (dip == NULL) { 893 894 return (USB_INVALID_ARGS); 895 } 896 897 if ((usb_flags & USB_FLAGS_SLEEP) && servicing_interrupt()) { 898 899 return (USB_INVALID_CONTEXT); 900 } 901 902 ph = usba_get_dflt_pipe_handle(dip); 903 if (usba_hold_ph_data(ph) == NULL) { 904 905 return (USB_INVALID_PIPE); 906 } 907 908 return (usba_pipe_setup_func_call(dip, 909 usba_sync_set_alt_if, (usba_ph_impl_t *)ph, 910 (usb_opaque_t)((uintptr_t)((interface << 8) | alt_number)), 911 usb_flags, cb, cb_arg)); 912 } 913 914 915 static int 916 usba_sync_set_alt_if(dev_info_t *dip, 917 usba_ph_impl_t *ph_impl, 918 usba_pipe_async_req_t *request, 919 usb_flags_t flags) 920 { 921 int rval; 922 usb_cr_t completion_reason; 923 usb_cb_flags_t cb_flags; 924 usb_opaque_t arg = request->arg; 925 int interface = ((uintptr_t)arg >> 8) & 0xff; 926 int alt_number = (uintptr_t)arg & 0xff; 927 usba_pipe_handle_data_t *ph_data = usba_get_ph_data( 928 (usb_pipe_handle_t)ph_impl); 929 930 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 931 "usb_set_alt_if: %s, interface#=0x%x, alt#=0x%x, " 932 "uf=0x%x", ddi_node_name(dip), interface, 933 alt_number, flags); 934 935 /* if we don't own the device, we must own the interface or ia */ 936 if (!usb_owns_device(dip) && !usba_check_if_in_ia(dip, interface) && 937 (interface != usb_get_if_number(dip))) { 938 usba_release_ph_data(ph_data->p_ph_impl); 939 940 return (USB_INVALID_PERM); 941 } 942 943 /* set the alternate setting */ 944 rval = usb_pipe_sync_ctrl_xfer(dip, usba_get_dflt_pipe_handle(dip), 945 USB_DEV_REQ_HOST_TO_DEV | USB_DEV_REQ_RCPT_IF, 946 USB_REQ_SET_IF, 947 alt_number, 948 interface, 949 0, 950 NULL, 0, 951 &completion_reason, 952 &cb_flags, flags | USB_FLAGS_SLEEP); 953 954 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 955 "rval=%d, cb_flags=%d, cr=%d", rval, cb_flags, completion_reason); 956 957 usba_release_ph_data(ph_data->p_ph_impl); 958 959 return (rval); 960 } 961 962 963 /* 964 * usb_get_alt_if: 965 * get the alternate interface number. Issues USB_REQ_GET_IF 966 * This function will access the device and block 967 * 968 * Arguments: 969 * dip - pointer to devinfo of the client 970 * if_number - interface number 971 * alt_number - alternate interface number 972 * flags - none but USB_FLAGS_SLEEP may be passed 973 * 974 * return values: 975 * USB_SUCCESS: alternate was set 976 * USB_FAILURE: alternate could not be set because pipes 977 * were still open or some access error occurred 978 */ 979 int 980 usb_get_alt_if(dev_info_t *dip, 981 uint_t if_number, 982 uint_t *alt_number, 983 usb_flags_t flags) 984 { 985 int rval; 986 usb_cr_t completion_reason; 987 mblk_t *data = NULL; 988 usb_cb_flags_t cb_flags; 989 usb_pipe_handle_t ph; 990 991 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 992 "usb_get_alt_if: %s, interface# = 0x%x, altp = 0x%p, " 993 "uf = 0x%x", ddi_node_name(dip), if_number, 994 (void *)alt_number, flags); 995 996 if ((alt_number == NULL) || (dip == NULL)) { 997 998 return (USB_INVALID_ARGS); 999 } 1000 1001 ph = usba_get_dflt_pipe_handle(dip); 1002 1003 /* 1004 * get the alternate setting 1005 */ 1006 rval = usb_pipe_sync_ctrl_xfer(dip, ph, 1007 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_IF, 1008 USB_REQ_GET_IF, 1009 0, 1010 if_number, 1011 1, /* returns one byte of data */ 1012 &data, 0, 1013 &completion_reason, 1014 &cb_flags, flags); 1015 1016 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 1017 "rval=%d cb_flags=%d cr=%d", rval, cb_flags, completion_reason); 1018 1019 if ((rval == USB_SUCCESS) && data && 1020 ((data->b_wptr - data->b_rptr) == 1)) { 1021 *alt_number = *(data->b_rptr); 1022 } else { 1023 *alt_number = 0; 1024 if (rval == USB_SUCCESS) { 1025 rval = USB_FAILURE; 1026 } 1027 } 1028 1029 freemsg(data); 1030 1031 return (rval); 1032 } 1033 1034 1035 /* 1036 * usba_get_cfg_cloud: 1037 * Get descriptor cloud for a given configuration. 1038 * 1039 * Arguments: 1040 * dip - pointer to devinfo of the client 1041 * default_ph - default pipe handle 1042 * cfg - which configuration to retrieve raw cloud of 1043 * 1044 * Returns: 1045 * on success: mblock containing the raw data. Caller must free. 1046 * on failure: NULL 1047 */ 1048 static mblk_t * 1049 usba_get_cfg_cloud(dev_info_t *dip, usb_pipe_handle_t default_ph, int cfg) 1050 { 1051 usb_cr_t completion_reason; 1052 usb_cb_flags_t cb_flags; 1053 usb_cfg_descr_t cfg_descr; 1054 mblk_t *pdata = NULL; 1055 1056 if (usb_pipe_sync_ctrl_xfer(dip, default_ph, 1057 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_TYPE_STANDARD, 1058 USB_REQ_GET_DESCR, 1059 USB_DESCR_TYPE_SETUP_CFG | cfg, 1060 0, 1061 USB_CFG_DESCR_SIZE, 1062 &pdata, 1063 0, 1064 &completion_reason, 1065 &cb_flags, 1066 0) != USB_SUCCESS) { 1067 1068 freemsg(pdata); 1069 1070 return (NULL); 1071 } 1072 1073 (void) usb_parse_cfg_descr(pdata->b_rptr, 1074 pdata->b_wptr - pdata->b_rptr, &cfg_descr, USB_CFG_DESCR_SIZE); 1075 freemsg(pdata); 1076 pdata = NULL; 1077 1078 if (usb_pipe_sync_ctrl_xfer(dip, default_ph, 1079 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_TYPE_STANDARD, 1080 USB_REQ_GET_DESCR, 1081 USB_DESCR_TYPE_SETUP_CFG | cfg, 1082 0, 1083 cfg_descr.wTotalLength, 1084 &pdata, 1085 0, 1086 &completion_reason, 1087 &cb_flags, 1088 0) != USB_SUCCESS) { 1089 1090 freemsg(pdata); 1091 1092 return (NULL); 1093 } 1094 1095 return (pdata); 1096 } 1097 1098 /* 1099 * usb_check_same_device: 1100 * Check if the device connected to the port is the same as 1101 * the previous device that was in the port. The previous device is 1102 * represented by the dip on record for the port. Print a message 1103 * if the device is different. If device_string arg is not NULL, it is 1104 * included in the message. Can block. 1105 * 1106 * Arguments: 1107 * dip - pointer to devinfo of the client 1108 * log_handle - handle to which messages are logged 1109 * log_level - one of USB_LOG_* 1110 * log_mask - logging mask 1111 * check_mask - one mask containing things to check: 1112 * USB_CHK_BASIC: empty mask; 1113 * these checks are always done. 1114 * USB_CHK_VIDPID: 1115 * check vid, pid only. 1116 * USB_CHK_SERIAL: check match on device 1117 * serial number. 1118 * USB_CHK_CFG: check all raw config 1119 * clouds for a match. 1120 * NOTE: descr length and content always checked 1121 * device_string - Device string to appear in error message 1122 * 1123 * return values: 1124 * USB_SUCCESS: same device 1125 * USB_INVALID_VERSION not same device 1126 * USB_FAILURE: Failure processing request 1127 * USB_INVALID_ARG: dip is invalid 1128 */ 1129 int 1130 usb_check_same_device(dev_info_t *dip, usb_log_handle_t log_handle, 1131 int log_level, int log_mask, uint_t check_mask, char *device_string) 1132 { 1133 usb_dev_descr_t usb_dev_descr; 1134 usba_device_t *usba_device; 1135 mblk_t *pdata = NULL; 1136 uint16_t length; 1137 int rval; 1138 char *buf; 1139 usb_cr_t completion_reason; 1140 usb_cb_flags_t cb_flags; 1141 boolean_t match = B_TRUE; 1142 usb_pipe_handle_t def_ph; 1143 1144 if (dip == NULL) { 1145 1146 return (USB_INVALID_ARGS); 1147 } 1148 1149 usba_device = usba_get_usba_device(dip); 1150 length = usba_device->usb_dev_descr->bLength; 1151 def_ph = usba_get_dflt_pipe_handle(dip); 1152 ASSERT(def_ph); 1153 1154 /* get the "new" device descriptor */ 1155 rval = usb_pipe_sync_ctrl_xfer(dip, def_ph, 1156 USB_DEV_REQ_DEV_TO_HOST | 1157 USB_DEV_REQ_TYPE_STANDARD, 1158 USB_REQ_GET_DESCR, /* bRequest */ 1159 USB_DESCR_TYPE_SETUP_DEV, /* wValue */ 1160 0, /* wIndex */ 1161 length, /* wLength */ 1162 &pdata, 0, 1163 &completion_reason, 1164 &cb_flags, USB_FLAGS_SLEEP); 1165 1166 if (rval != USB_SUCCESS) { 1167 if (!((completion_reason == USB_CR_DATA_OVERRUN) && (pdata))) { 1168 USB_DPRINTF_L3(DPRINT_MASK_USBA, usbai_log_handle, 1169 "getting device descriptor failed (%d)", rval); 1170 freemsg(pdata); 1171 1172 return (USB_FAILURE); 1173 } 1174 } 1175 1176 ASSERT(pdata != NULL); 1177 1178 (void) usb_parse_dev_descr(pdata->b_rptr, 1179 pdata->b_wptr - pdata->b_rptr, &usb_dev_descr, 1180 sizeof (usb_dev_descr_t)); 1181 1182 freemsg(pdata); 1183 pdata = NULL; 1184 1185 /* Always check the device descriptor length. */ 1186 if (usb_dev_descr.bLength != length) { 1187 match = B_FALSE; 1188 } 1189 1190 if ((match == B_TRUE) && (check_mask & USB_CHK_VIDPID)) { 1191 match = (usba_device->usb_dev_descr->idVendor == 1192 usb_dev_descr.idVendor) && 1193 (usba_device->usb_dev_descr->idProduct == 1194 usb_dev_descr.idProduct); 1195 } else if (bcmp((char *)usba_device->usb_dev_descr, 1196 (char *)&usb_dev_descr, length) != 0) { 1197 match = B_FALSE; 1198 } 1199 1200 /* if requested & this device has a serial number check and compare */ 1201 if ((match == B_TRUE) && ((check_mask & USB_CHK_SERIAL) != 0) && 1202 (usba_device->usb_serialno_str != NULL)) { 1203 buf = kmem_alloc(USB_MAXSTRINGLEN, KM_SLEEP); 1204 if (usb_get_string_descr(dip, USB_LANG_ID, 1205 usb_dev_descr.iSerialNumber, buf, 1206 USB_MAXSTRINGLEN) == USB_SUCCESS) { 1207 match = 1208 (strcmp(buf, usba_device->usb_serialno_str) == 0); 1209 } 1210 kmem_free(buf, USB_MAXSTRINGLEN); 1211 } 1212 1213 if ((match == B_TRUE) && (check_mask & USB_CHK_CFG)) { 1214 1215 uint8_t num_cfgs = usb_dev_descr.bNumConfigurations; 1216 uint8_t cfg; 1217 mblk_t *cloud; 1218 1219 for (cfg = 0; cfg < num_cfgs; cfg++) { 1220 cloud = usba_get_cfg_cloud(dip, def_ph, cfg); 1221 if (cloud == NULL) { 1222 USB_DPRINTF_L3(DPRINT_MASK_USBA, 1223 usbai_log_handle, 1224 "Could not retrieve config cloud for " 1225 "comparison"); 1226 break; 1227 } 1228 1229 if (bcmp((char *)cloud->b_rptr, 1230 usba_device->usb_cfg_array[cfg], 1231 cloud->b_wptr - cloud->b_rptr) != 0) { 1232 freemsg(cloud); 1233 break; 1234 } 1235 1236 freemsg(cloud); 1237 } 1238 if (cfg != num_cfgs) { 1239 match = B_FALSE; 1240 } 1241 } 1242 1243 if (match == B_FALSE) { 1244 boolean_t allocated_here = (device_string == NULL); 1245 if (allocated_here) { 1246 device_string = 1247 kmem_zalloc(USB_MAXSTRINGLEN, USB_FLAGS_SLEEP); 1248 (void) usba_get_mfg_prod_sn_str(dip, device_string, 1249 USB_MAXSTRINGLEN); 1250 } 1251 if (device_string[0] != '\0') { 1252 (void) usb_log(log_handle, log_level, log_mask, 1253 "Cannot access %s. Please reconnect.", 1254 device_string); 1255 } else { 1256 (void) usb_log(log_handle, log_level, log_mask, 1257 "Device is not identical to the " 1258 "previous one this port.\n" 1259 "Please disconnect and reconnect"); 1260 } 1261 if (allocated_here) { 1262 kmem_free(device_string, USB_MAXSTRINGLEN); 1263 } 1264 1265 return (USB_INVALID_VERSION); 1266 } 1267 1268 return (USB_SUCCESS); 1269 } 1270 1271 1272 /* 1273 * usb_pipe_get_state: 1274 * Return the state of the pipe 1275 * 1276 * Arguments: 1277 * pipe_handle - pipe_handle pointer 1278 * pipe_state - pointer to copy pipe state to 1279 * flags: 1280 * not used other than to check context 1281 * 1282 * Return Values: 1283 * USB_SUCCESS - port state returned 1284 * USB_* - refer to usbai.h 1285 */ 1286 int 1287 usb_pipe_get_state(usb_pipe_handle_t pipe_handle, 1288 usb_pipe_state_t *pipe_state, 1289 usb_flags_t usb_flags) 1290 { 1291 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1292 1293 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1294 "usb_pipe_get_state: ph_data=0x%p uf=0x%x", (void *)ph_data, 1295 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 (void *)dip, (void *)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 (void *)dip, (void *)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 (void *)ph_data, (void *)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 (void *)impl_tokenp, (void *)impl_tokenp->s_dip, 1989 impl_tokenp->s_count, (void *)impl_tokenp->s_thread, 1990 how_to_wait, abs_timeout); 1991 1992 if ((impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD) == 0 || 1993 impl_tokenp->s_thread != curthread) { 1994 1995 /* 1996 * There are three ways to break out of the loop: 1997 * 1) Condition met (s_count == 0) - higher prio test 1998 * 2) kill(2) signal received (rval == 0) 1999 * 3) timeout occurred (rval == -1) 2000 * If condition met, whether or not signal or timeout occurred 2001 * take access. If condition not met, check other exit means. 2002 */ 2003 while (impl_tokenp->s_count != 0) { 2004 2005 /* cv_timedwait* returns -1 on timeout. */ 2006 /* cv_wait*_sig returns 0 on (kill(2)) signal. */ 2007 if (rval <= 0) { 2008 mutex_exit(&impl_tokenp->s_mutex); 2009 USB_DPRINTF_L4(DPRINT_MASK_USBA, 2010 usbai_log_handle, 2011 "usb_serialize_access: " 2012 "tok=0x%p exit due to %s", 2013 (void *)impl_tokenp, 2014 ((rval == 0) ? "signal" : "timeout")); 2015 2016 return (rval); 2017 } 2018 2019 switch (how_to_wait) { 2020 default: 2021 how_to_wait = USB_WAIT; 2022 /* FALLTHROUGH */ 2023 case USB_WAIT: 2024 cv_wait(&impl_tokenp->s_cv, 2025 &impl_tokenp->s_mutex); 2026 break; 2027 case USB_WAIT_SIG: 2028 rval = cv_wait_sig(&impl_tokenp->s_cv, 2029 &impl_tokenp->s_mutex); 2030 break; 2031 case USB_TIMEDWAIT: 2032 rval = cv_timedwait(&impl_tokenp->s_cv, 2033 &impl_tokenp->s_mutex, abs_timeout); 2034 break; 2035 case USB_TIMEDWAIT_SIG: 2036 rval = cv_timedwait_sig(&impl_tokenp->s_cv, 2037 &impl_tokenp->s_mutex, abs_timeout); 2038 break; 2039 } 2040 } 2041 2042 impl_tokenp->s_thread = curthread; 2043 } 2044 impl_tokenp->s_count++; 2045 2046 ASSERT(!(impl_tokenp->s_count > 1 && 2047 (impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD) == 0)); 2048 2049 mutex_exit(&impl_tokenp->s_mutex); 2050 2051 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2052 "usb_serialize_access exit: tok=0x%p thr=0x%p", (void *)impl_tokenp, 2053 (void *)curthread); 2054 2055 return (1); 2056 } 2057 2058 2059 /*ARGSUSED*/ 2060 int 2061 usb_try_serialize_access( 2062 usb_serialization_t tokenp, uint_t flag) 2063 { 2064 usba_serialization_impl_t *impl_tokenp = 2065 (usba_serialization_impl_t *)tokenp; 2066 mutex_enter(&impl_tokenp->s_mutex); 2067 2068 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2069 "usb_try_serialize_access: tok=0x%p dip=0x%p cnt=%d thr=0x%p", 2070 (void *)impl_tokenp, (void *)impl_tokenp->s_dip, 2071 impl_tokenp->s_count, (void *)curthread); 2072 2073 /* 2074 * If lock is not taken (s_count is 0), take it. 2075 * If lock is already taken, the thread is owner and lock 2076 * is reentrant, take it. 2077 * Otherwise, fail the access. 2078 */ 2079 if (!impl_tokenp->s_count || ((impl_tokenp->s_thread == curthread) && 2080 (impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD))) { 2081 impl_tokenp->s_thread = curthread; 2082 impl_tokenp->s_count++; 2083 2084 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2085 "usb_try_serialize_access success: tok=0x%p", 2086 (void *)impl_tokenp); 2087 mutex_exit(&impl_tokenp->s_mutex); 2088 2089 return (USB_SUCCESS); 2090 } 2091 2092 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2093 "usb_try_serialize_access failed: " 2094 "tok=0x%p dip=0x%p cnt=%d thr=0x%p", 2095 (void *)impl_tokenp, (void *)impl_tokenp->s_dip, 2096 impl_tokenp->s_count, (void *)impl_tokenp->s_thread); 2097 2098 mutex_exit(&impl_tokenp->s_mutex); 2099 2100 return (USB_FAILURE); 2101 } 2102 2103 2104 void 2105 usb_release_access( 2106 usb_serialization_t tokenp) 2107 { 2108 usba_serialization_impl_t *impl_tokenp = 2109 (usba_serialization_impl_t *)tokenp; 2110 mutex_enter(&impl_tokenp->s_mutex); 2111 2112 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2113 "usb_release_access: tok=0x%p dip=0x%p count=%d thr=0x%p", 2114 (void *)impl_tokenp, (void *)impl_tokenp->s_dip, 2115 impl_tokenp->s_count, (void *)curthread); 2116 2117 ASSERT(impl_tokenp->s_count > 0); 2118 2119 if (impl_tokenp->s_flag & USB_INIT_SER_CHECK_SAME_THREAD) { 2120 if (impl_tokenp->s_thread != curthread) { 2121 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 2122 "usb_release_access: release from wrong thread"); 2123 } 2124 ASSERT(impl_tokenp->s_thread == curthread); 2125 } 2126 2127 if (--impl_tokenp->s_count == 0) { 2128 impl_tokenp->s_thread = NULL; 2129 cv_broadcast(&impl_tokenp->s_cv); 2130 } 2131 mutex_exit(&impl_tokenp->s_mutex); 2132 } 2133 2134 2135 /* 2136 * usb_fail_checkpoint: 2137 * fail checkpoint as driver/device could not be quiesced 2138 */ 2139 /*ARGSUSED*/ 2140 void 2141 usb_fail_checkpoint(dev_info_t *dip, usb_flags_t flags) 2142 { 2143 usba_device_t *usba_device = usba_get_usba_device(dip); 2144 2145 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 2146 "usb_fail_checkpoint: %s%d", ddi_driver_name(dip), 2147 ddi_get_instance(dip)); 2148 2149 mutex_enter(&usba_device->usb_mutex); 2150 usba_device->usb_no_cpr++; 2151 mutex_exit(&usba_device->usb_mutex); 2152 } 2153 2154 2155 _NOTE(SCHEME_PROTECTS_DATA("unique per call", iocblk)) 2156 _NOTE(SCHEME_PROTECTS_DATA("unique per call", datab)) 2157 /* 2158 * usba_mk_mctl: 2159 * create a USB style M_CTL message, given an iocblk and a buffer 2160 * returns mblk_t * on success, NULL on failure 2161 */ 2162 mblk_t * 2163 usba_mk_mctl(struct iocblk mctlmsg, void *buf, size_t len) 2164 { 2165 mblk_t *bp1, *bp2; 2166 2167 if ((bp1 = allocb(sizeof (struct iocblk), BPRI_HI)) != NULL) { 2168 *((struct iocblk *)bp1->b_datap->db_base) = mctlmsg; 2169 bp1->b_datap->db_type = M_CTL; 2170 bp1->b_wptr += sizeof (struct iocblk); 2171 if (buf != NULL) { 2172 if ((bp2 = allocb(len, BPRI_HI)) != NULL) { 2173 bp1->b_cont = bp2; 2174 bcopy(buf, bp2->b_datap->db_base, len); 2175 bp2->b_wptr += len; 2176 } else { 2177 freemsg(bp1); 2178 bp1 = NULL; 2179 } 2180 } 2181 } 2182 2183 return (bp1); 2184 } 2185 2186 2187 #ifdef ALLOCB_TEST 2188 #undef allocb 2189 mblk_t * 2190 usba_test_allocb(size_t size, uint_t pri) 2191 { 2192 if (ddi_get_lbolt() & 0x1) { 2193 2194 return (NULL); 2195 } else { 2196 2197 return (allocb(size, pri)); 2198 } 2199 } 2200 #endif 2201 2202 2203 /* 2204 * usb common power management for usb_mid, usb_ia and maybe other simple 2205 * drivers. 2206 */ 2207 2208 /* 2209 * functions to handle power transition for OS levels 0 -> 3 2210 */ 2211 static int 2212 usb_common_pwrlvl0(dev_info_t *dip, uint8_t *pm, int *dev_state) 2213 { 2214 int rval; 2215 2216 switch (*dev_state) { 2217 case USB_DEV_ONLINE: 2218 /* Issue USB D3 command to the device here */ 2219 rval = usb_set_device_pwrlvl3(dip); 2220 ASSERT(rval == USB_SUCCESS); 2221 2222 *dev_state = USB_DEV_PWRED_DOWN; 2223 *pm = USB_DEV_OS_PWR_OFF; 2224 /* FALLTHRU */ 2225 case USB_DEV_DISCONNECTED: 2226 case USB_DEV_SUSPENDED: 2227 /* allow a disconnected/cpr'ed device to go to low pwr */ 2228 2229 return (USB_SUCCESS); 2230 case USB_DEV_PWRED_DOWN: 2231 default: 2232 return (USB_FAILURE); 2233 } 2234 } 2235 2236 2237 /* ARGSUSED */ 2238 static int 2239 usb_common_pwrlvl1(dev_info_t *dip, uint8_t *pm, int *dev_state) 2240 { 2241 int rval; 2242 2243 /* Issue USB D2 command to the device here */ 2244 rval = usb_set_device_pwrlvl2(dip); 2245 ASSERT(rval == USB_SUCCESS); 2246 2247 return (USB_FAILURE); 2248 } 2249 2250 2251 /* ARGSUSED */ 2252 static int 2253 usb_common_pwrlvl2(dev_info_t *dip, uint8_t *pm, int *dev_state) 2254 { 2255 int rval; 2256 2257 /* Issue USB D1 command to the device here */ 2258 rval = usb_set_device_pwrlvl1(dip); 2259 ASSERT(rval == USB_SUCCESS); 2260 2261 return (USB_FAILURE); 2262 } 2263 2264 2265 static int 2266 usb_common_pwrlvl3(dev_info_t *dip, uint8_t *pm, int *dev_state) 2267 { 2268 int rval; 2269 2270 switch (*dev_state) { 2271 case USB_DEV_PWRED_DOWN: 2272 /* Issue USB D0 command to the device here */ 2273 rval = usb_set_device_pwrlvl0(dip); 2274 ASSERT(rval == USB_SUCCESS); 2275 2276 *dev_state = USB_DEV_ONLINE; 2277 *pm = USB_DEV_OS_FULL_PWR; 2278 2279 /* FALLTHRU */ 2280 case USB_DEV_ONLINE: 2281 /* we are already in full power */ 2282 2283 /* FALLTHRU */ 2284 case USB_DEV_DISCONNECTED: 2285 case USB_DEV_SUSPENDED: 2286 /* allow a disconnected/cpr'ed device to go to low power */ 2287 2288 return (USB_SUCCESS); 2289 default: 2290 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle, 2291 "usb_common_pwrlvl3: Illegal state (%s)", 2292 usb_str_dev_state(*dev_state)); 2293 2294 return (USB_FAILURE); 2295 } 2296 } 2297 2298 /* power management */ 2299 int 2300 usba_common_power(dev_info_t *dip, uint8_t *pm, int *dev_state, int level) 2301 { 2302 int rval = DDI_FAILURE; 2303 2304 switch (level) { 2305 case USB_DEV_OS_PWR_OFF: 2306 rval = usb_common_pwrlvl0(dip, pm, dev_state); 2307 break; 2308 case USB_DEV_OS_PWR_1: 2309 rval = usb_common_pwrlvl1(dip, pm, dev_state); 2310 break; 2311 case USB_DEV_OS_PWR_2: 2312 rval = usb_common_pwrlvl2(dip, pm, dev_state); 2313 break; 2314 case USB_DEV_OS_FULL_PWR: 2315 rval = usb_common_pwrlvl3(dip, pm, dev_state); 2316 break; 2317 } 2318 2319 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 2320 } 2321 2322 /* 2323 * register and unregister for events from our parent for usb_mid and usb_ia 2324 * and maybe other nexus driver. 2325 * 2326 * Note: The cookie fields in usba_device structure is not used. They are 2327 * used/shared by children. 2328 */ 2329 void 2330 usba_common_register_events(dev_info_t *dip, uint_t if_num, 2331 void (*event_cb)(dev_info_t *, ddi_eventcookie_t, void *, void *)) 2332 { 2333 int rval; 2334 usba_evdata_t *evdata; 2335 ddi_eventcookie_t cookie; 2336 2337 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle, 2338 "usb_common_register_events:"); 2339 2340 evdata = usba_get_evdata(dip); 2341 2342 /* get event cookie, discard level and icookie for now */ 2343 rval = ddi_get_eventcookie(dip, DDI_DEVI_REMOVE_EVENT, 2344 &cookie); 2345 2346 if (rval == DDI_SUCCESS) { 2347 rval = ddi_add_event_handler(dip, 2348 cookie, event_cb, NULL, &evdata->ev_rm_cb_id); 2349 2350 if (rval != DDI_SUCCESS) { 2351 2352 goto fail; 2353 } 2354 } 2355 rval = ddi_get_eventcookie(dip, DDI_DEVI_INSERT_EVENT, 2356 &cookie); 2357 if (rval == DDI_SUCCESS) { 2358 rval = ddi_add_event_handler(dip, cookie, event_cb, 2359 NULL, &evdata->ev_ins_cb_id); 2360 2361 if (rval != DDI_SUCCESS) { 2362 2363 goto fail; 2364 } 2365 } 2366 rval = ddi_get_eventcookie(dip, USBA_PRE_SUSPEND_EVENT, &cookie); 2367 if (rval == DDI_SUCCESS) { 2368 rval = ddi_add_event_handler(dip, 2369 cookie, event_cb, NULL, &evdata->ev_suspend_cb_id); 2370 2371 if (rval != DDI_SUCCESS) { 2372 2373 goto fail; 2374 } 2375 } 2376 rval = ddi_get_eventcookie(dip, USBA_POST_RESUME_EVENT, &cookie); 2377 if (rval == DDI_SUCCESS) { 2378 rval = ddi_add_event_handler(dip, cookie, event_cb, NULL, 2379 &evdata->ev_resume_cb_id); 2380 2381 if (rval != DDI_SUCCESS) { 2382 2383 goto fail; 2384 } 2385 } 2386 2387 return; 2388 2389 2390 fail: 2391 usba_common_unregister_events(dip, if_num); 2392 2393 } 2394 2395 void 2396 usba_common_unregister_events(dev_info_t *dip, uint_t if_num) 2397 { 2398 usba_evdata_t *evdata; 2399 usba_device_t *usba_device = usba_get_usba_device(dip); 2400 int i; 2401 2402 evdata = usba_get_evdata(dip); 2403 2404 if (evdata->ev_rm_cb_id != NULL) { 2405 (void) ddi_remove_event_handler(evdata->ev_rm_cb_id); 2406 evdata->ev_rm_cb_id = NULL; 2407 } 2408 2409 if (evdata->ev_ins_cb_id != NULL) { 2410 (void) ddi_remove_event_handler(evdata->ev_ins_cb_id); 2411 evdata->ev_ins_cb_id = NULL; 2412 } 2413 2414 if (evdata->ev_suspend_cb_id != NULL) { 2415 (void) ddi_remove_event_handler(evdata->ev_suspend_cb_id); 2416 evdata->ev_suspend_cb_id = NULL; 2417 } 2418 2419 if (evdata->ev_resume_cb_id != NULL) { 2420 (void) ddi_remove_event_handler(evdata->ev_resume_cb_id); 2421 evdata->ev_resume_cb_id = NULL; 2422 } 2423 2424 /* clear event data for children, required for cfgmadm unconfigure */ 2425 mutex_enter(&usba_device->usb_mutex); 2426 if (usb_owns_device(dip)) { 2427 usba_free_evdata(usba_device->usb_evdata); 2428 usba_device->usb_evdata = NULL; 2429 usba_device->rm_cookie = NULL; 2430 usba_device->ins_cookie = NULL; 2431 usba_device->suspend_cookie = NULL; 2432 usba_device->resume_cookie = NULL; 2433 } else { 2434 for (i = 0; i < if_num; i++) { 2435 usba_device->usb_client_flags[usba_get_ifno(dip) + i] 2436 &= ~USBA_CLIENT_FLAG_EV_CBS; 2437 } 2438 } 2439 mutex_exit(&usba_device->usb_mutex); 2440 } 2441