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