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 * functions that deal with allocation/free/data_xfers 31 * for the control/bulk/interrupt/isoch pipes: 32 * usb_alloc_ctrl_req() 33 * usb_free_ctrl_req() 34 * usb_pipe_ctrl_xfer() 35 * usb_pipe_sync_ctrl_xfer() 36 * usb_pipe_ctrl_xfer_wait() 37 * 38 * usb_alloc_bulk_req() 39 * usb_free_bulk_req() 40 * usb_pipe_bulk_xfer() 41 * usb_pipe_bulk_transfer_size() 42 * 43 * usb_alloc_intr_req() 44 * usb_free_intr_req() 45 * usb_pipe_intr_xfer() 46 * usb_pipe_stop_intr_polling() 47 * 48 * usb_alloc_isoc_req() 49 * usb_free_isoc_req() 50 * usb_get_current_frame_number() 51 * usb_get_max_isoc_pkts() 52 * usb_pipe_isoc_xfer() 53 * usb_pipe_stop_isoc_polling() 54 * 55 * XXX to do: 56 * update return values where needed 57 * keep track of requests not freed 58 * 59 */ 60 #define USBA_FRAMEWORK 61 #include <sys/usb/usba/usba_impl.h> 62 #include <sys/usb/usba/hcdi_impl.h> 63 #include <sys/strsubr.h> 64 #include <sys/strsun.h> 65 66 /* prototypes */ 67 static int usba_flags_attr_check(usba_pipe_handle_data_t *, 68 usb_req_attrs_t attrs, usb_flags_t); 69 static int _usba_check_req(usba_pipe_handle_data_t *, usb_opaque_t, 70 usb_flags_t, uchar_t); 71 72 /* 73 * usba_check_req: 74 * check pipe, request structure for validity 75 * 76 * Arguments: 77 * ph - pipe handle pointer 78 * req - opaque request pointer 79 * flags - usb flags 80 * 81 * Returns: 82 * USB_SUCCESS - valid request 83 * USB_INVALID_REQUEST - request contains some invalid values 84 * USB_PIPE_ERROR - pipe is in error state 85 * USB_INVALID_CONTEXT - sleep in interrupt context 86 * USB_INVALID_PIPE - zero pipe or wrong pipe 87 */ 88 static int 89 usba_check_req(usba_pipe_handle_data_t *ph_data, usb_opaque_t req, 90 usb_flags_t flags, uchar_t pipe_type) 91 { 92 int rval = _usba_check_req(ph_data, req, flags, pipe_type); 93 94 if (rval != USB_SUCCESS) { 95 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 96 "usba_check_req: ph_data=0x%p req=0x%p flags=0%x rval=%d", 97 (void *)ph_data, (void *)req, flags, rval); 98 } 99 100 return (rval); 101 } 102 103 104 static int 105 _usba_check_req(usba_pipe_handle_data_t *ph_data, usb_opaque_t req, 106 usb_flags_t flags, uchar_t pipe_type) 107 { 108 usb_ctrl_req_t *ctrl_req = (usb_ctrl_req_t *)req; 109 usb_bulk_req_t *bulk_req = (usb_bulk_req_t *)req; 110 usb_intr_req_t *intr_req = (usb_intr_req_t *)req; 111 usb_isoc_req_t *isoc_req = (usb_isoc_req_t *)req; 112 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 113 mblk_t *data; 114 usb_cr_t *cr; 115 usb_req_attrs_t attrs; 116 usb_opaque_t cb, exc_cb; 117 uint_t timeout = 0; 118 uchar_t direction = ph_data->p_ep.bEndpointAddress & 119 USB_EP_DIR_MASK; 120 uchar_t ep_attrs = ph_data->p_ep.bmAttributes & 121 USB_EP_ATTR_MASK; 122 int n; 123 124 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 125 "usba_check_req: ph_data=0x%p req=0x%p flags=0x%x", 126 (void *)ph_data, (void *)req, flags); 127 128 if (req == NULL) { 129 130 return (USB_INVALID_ARGS); 131 } 132 133 /* set completion reason first so it specifies an error */ 134 switch (ep_attrs) { 135 case USB_EP_ATTR_CONTROL: 136 cr = &ctrl_req->ctrl_completion_reason; 137 break; 138 case USB_EP_ATTR_BULK: 139 cr = &bulk_req->bulk_completion_reason; 140 break; 141 case USB_EP_ATTR_INTR: 142 cr = &intr_req->intr_completion_reason; 143 break; 144 case USB_EP_ATTR_ISOCH: 145 cr = &isoc_req->isoc_completion_reason; 146 break; 147 } 148 149 *cr = USB_CR_UNSPECIFIED_ERR; 150 151 if (servicing_interrupt() && (flags & USB_FLAGS_SLEEP)) { 152 153 return (USB_INVALID_CONTEXT); 154 } 155 156 if (pipe_type != ep_attrs) { 157 158 return (USB_INVALID_PIPE); 159 } 160 161 /* we must have usba_device and default ph to do autoclearing */ 162 ASSERT(ph_data->p_usba_device); 163 164 if (ph_data->p_usba_device->usb_ph_list[0].usba_ph_data == NULL) { 165 166 return (USB_INVALID_PIPE); 167 } 168 169 /* check if this is a valid request packet, ie. not freed */ 170 if (usba_check_in_list(&(ph_data->p_usba_device->usb_allocated), 171 &wrp->wr_allocated_list) != USB_SUCCESS) { 172 173 return (USB_INVALID_REQUEST); 174 } 175 176 /* copy over some members for easy checking later */ 177 switch (ep_attrs) { 178 case USB_EP_ATTR_CONTROL: 179 ctrl_req->ctrl_cb_flags = USB_CB_NO_INFO; 180 data = ctrl_req->ctrl_data; 181 attrs = ctrl_req->ctrl_attributes; 182 timeout = ctrl_req->ctrl_timeout; 183 cb = (usb_opaque_t)ctrl_req->ctrl_cb; 184 exc_cb = (usb_opaque_t)ctrl_req->ctrl_exc_cb; 185 if (flags & USB_FLAGS_SLEEP) { 186 flags |= USBA_WRP_FLAGS_WAIT; 187 } 188 /* force auto clearing on the default pipe */ 189 if (USBA_IS_DEFAULT_PIPE(ph_data)) { 190 attrs |= USB_ATTRS_AUTOCLEARING; 191 } 192 break; 193 case USB_EP_ATTR_BULK: 194 bulk_req->bulk_cb_flags = USB_CB_NO_INFO; 195 data = bulk_req->bulk_data; 196 attrs = bulk_req->bulk_attributes; 197 timeout = bulk_req->bulk_timeout; 198 cb = (usb_opaque_t)bulk_req->bulk_cb; 199 exc_cb = (usb_opaque_t)bulk_req->bulk_exc_cb; 200 if (flags & USB_FLAGS_SLEEP) { 201 flags |= USBA_WRP_FLAGS_WAIT; 202 } 203 break; 204 case USB_EP_ATTR_INTR: 205 intr_req->intr_cb_flags = USB_CB_NO_INFO; 206 data = intr_req->intr_data; 207 attrs = intr_req->intr_attributes; 208 timeout = intr_req->intr_timeout; 209 cb = (usb_opaque_t)intr_req->intr_cb; 210 exc_cb = (usb_opaque_t)intr_req->intr_exc_cb; 211 if ((flags & USB_FLAGS_SLEEP) && 212 (attrs & USB_ATTRS_ONE_XFER)) { 213 flags |= USBA_WRP_FLAGS_WAIT; 214 } 215 break; 216 case USB_EP_ATTR_ISOCH: 217 isoc_req->isoc_cb_flags = USB_CB_NO_INFO; 218 data = isoc_req->isoc_data; 219 attrs = isoc_req->isoc_attributes; 220 cb = (usb_opaque_t)isoc_req->isoc_cb; 221 exc_cb = (usb_opaque_t)isoc_req->isoc_exc_cb; 222 break; 223 } 224 225 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 226 "usba_check_req: attrs = 0x%x flags=0x%x", attrs, flags); 227 228 /* check flags and attr combinations */ 229 if (usba_flags_attr_check(ph_data, attrs, flags) != 230 USB_SUCCESS) { 231 232 return (USB_INVALID_REQUEST); 233 } 234 235 /* if no sleep, there must be callback ptrs */ 236 if ((flags & USB_FLAGS_SLEEP) == 0) { 237 if (cb == NULL || exc_cb == NULL) { 238 239 return (USB_INVALID_REQUEST); 240 } 241 } 242 243 switch (ep_attrs) { 244 case USB_EP_ATTR_CONTROL: 245 if (ctrl_req->ctrl_wLength && (data == NULL)) { 246 247 return (USB_INVALID_REQUEST); 248 } 249 break; 250 case USB_EP_ATTR_BULK: 251 if ((bulk_req->bulk_len) && (data == NULL)) { 252 253 return (USB_INVALID_REQUEST); 254 } 255 break; 256 case USB_EP_ATTR_INTR: 257 if (direction == USB_EP_DIR_OUT) { 258 if (intr_req->intr_len && data == NULL) { 259 260 return (USB_INVALID_REQUEST); 261 } 262 } 263 264 if (direction == USB_EP_DIR_IN) { 265 if (!(intr_req->intr_attributes & USB_ATTRS_ONE_XFER)) { 266 if (cb == NULL || exc_cb == NULL) { 267 268 return (USB_INVALID_REQUEST); 269 } 270 } 271 if (data != NULL) { 272 273 return (USB_INVALID_REQUEST); 274 } 275 if (!(intr_req->intr_attributes & USB_ATTRS_ONE_XFER) && 276 (timeout > 0)) { 277 278 return (USB_INVALID_REQUEST); 279 } 280 } 281 break; 282 case USB_EP_ATTR_ISOCH: 283 if (direction == USB_EP_DIR_IN) { 284 if (cb == NULL || exc_cb == NULL) { 285 286 return (USB_INVALID_REQUEST); 287 } 288 } 289 290 if (data == NULL) { 291 292 return (USB_INVALID_REQUEST); 293 } 294 295 /* 296 * Since ehci/ohci/uhci use (data->b_wptr - data->b_rptr) as 297 * real isoc_pkts_length, it should be checked. 298 */ 299 if (direction == USB_EP_DIR_OUT) { 300 if (MBLKL(data) <= 0) { 301 302 return (USB_INVALID_REQUEST); 303 } 304 } 305 306 /* special isoc checks */ 307 if ((isoc_req->isoc_pkts_count == 0) || 308 (isoc_req->isoc_pkt_descr == NULL)) { 309 310 return (USB_INVALID_REQUEST); 311 } 312 313 /* check attributes for conflicts, one must be specified */ 314 if (!((isoc_req->isoc_attributes & 315 USB_ATTRS_ISOC_START_FRAME) || 316 (isoc_req->isoc_attributes & USB_ATTRS_ISOC_XFER_ASAP))) { 317 318 return (USB_NO_FRAME_NUMBER); 319 } 320 321 /* both may not be specified */ 322 if ((isoc_req->isoc_attributes & 323 (USB_ATTRS_ISOC_START_FRAME | USB_ATTRS_ISOC_XFER_ASAP)) == 324 (USB_ATTRS_ISOC_START_FRAME | USB_ATTRS_ISOC_XFER_ASAP)) { 325 326 return (USB_NO_FRAME_NUMBER); 327 } 328 329 /* no start frame may be specified for ASAP attribute */ 330 if (((isoc_req->isoc_attributes & USB_ATTRS_ISOC_XFER_ASAP)) && 331 isoc_req->isoc_frame_no) { 332 333 return (USB_INVALID_REQUEST); 334 } 335 336 /* start frame must be specified for START FRAME attribute */ 337 if (((isoc_req->isoc_attributes & 338 USB_ATTRS_ISOC_START_FRAME)) && 339 (isoc_req->isoc_frame_no == 0)) { 340 341 return (USB_NO_FRAME_NUMBER); 342 } 343 344 /* each packet must have initialized pkt length */ 345 for (n = 0; n < isoc_req->isoc_pkts_count; n++) { 346 if (isoc_req->isoc_pkt_descr[n].isoc_pkt_length == 0) { 347 348 return (USB_INVALID_REQUEST); 349 } 350 } 351 break; 352 } 353 354 /* save pipe_handle/attrs/timeout/usb_flags */ 355 wrp->wr_ph_data = ph_data; 356 wrp->wr_usb_flags = flags; 357 wrp->wr_attrs = attrs; 358 359 /* zero some fields in case the request is reused */ 360 wrp->wr_done = B_FALSE; 361 wrp->wr_cr = USB_CR_OK; 362 363 /* this request looks good */ 364 *cr = USB_CR_OK; 365 366 return (USB_SUCCESS); 367 } 368 369 370 /* 371 * Table of invalid flags and attributes values. See "usbai.h" 372 * for a complete table on valid usb_req_attrs_t 373 */ 374 #define X ((uint_t)(-1)) 375 #define OUT USB_EP_DIR_OUT 376 #define IN USB_EP_DIR_IN 377 378 struct flags_attr { 379 uint_t ep_dir; 380 uint_t ep_attr; 381 uint_t usb_flags; /* usb_flags SLEEP or none */ 382 uint_t attrs; 383 } usb_invalid_flags_attrs[] = { 384 { OUT, USB_EP_ATTR_BULK, X, USB_ATTRS_SHORT_XFER_OK }, 385 { OUT, USB_EP_ATTR_INTR, X, USB_ATTRS_SHORT_XFER_OK }, 386 { OUT, USB_EP_ATTR_ISOCH, X, USB_ATTRS_SHORT_XFER_OK }, 387 388 { X, USB_EP_ATTR_CONTROL, X, USB_ATTRS_ISOC_START_FRAME }, 389 { X, USB_EP_ATTR_BULK, X, USB_ATTRS_ISOC_START_FRAME }, 390 { X, USB_EP_ATTR_INTR, X, USB_ATTRS_ISOC_START_FRAME }, 391 392 { X, USB_EP_ATTR_CONTROL, X, USB_ATTRS_ISOC_XFER_ASAP }, 393 { X, USB_EP_ATTR_INTR, X, USB_ATTRS_ISOC_XFER_ASAP }, 394 { OUT, USB_EP_ATTR_INTR, X, USB_ATTRS_ONE_XFER }, 395 { X, USB_EP_ATTR_BULK, X, USB_ATTRS_ISOC_XFER_ASAP }, 396 397 { X, USB_EP_ATTR_CONTROL, X, USB_ATTRS_ONE_XFER }, 398 { X, USB_EP_ATTR_BULK, X, USB_ATTRS_ONE_XFER }, 399 { X, USB_EP_ATTR_ISOCH, X, USB_ATTRS_ONE_XFER }, 400 }; 401 402 #define N_INVALID_FLAGS_ATTRS (sizeof (usb_invalid_flags_attrs))/ \ 403 sizeof (struct flags_attr) 404 405 /* 406 * function to check flags and attribute combinations for a particular pipe 407 * Arguments: 408 * ph - pipe handle pointer 409 * attrs - attributes of the request 410 * flags - usb_flags 411 */ 412 static int 413 usba_flags_attr_check(usba_pipe_handle_data_t *ph_data, 414 usb_req_attrs_t attrs, 415 usb_flags_t flags) 416 { 417 uchar_t i; 418 uchar_t ep_dir = ph_data->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 419 uchar_t ep_attr = ph_data->p_ep.bmAttributes & USB_EP_ATTR_MASK; 420 421 flags &= USB_FLAGS_SLEEP; /* ignore other flags */ 422 423 /* 424 * Do some attributes validation checks here. 425 */ 426 for (i = 0; i < N_INVALID_FLAGS_ATTRS; i++) { 427 if (((ep_dir == usb_invalid_flags_attrs[i].ep_dir) || 428 (usb_invalid_flags_attrs[i].ep_dir == X)) && 429 ((ep_attr == usb_invalid_flags_attrs[i].ep_attr) || 430 (usb_invalid_flags_attrs[i].ep_attr == X)) && 431 ((flags & usb_invalid_flags_attrs[i].usb_flags) || 432 (usb_invalid_flags_attrs[i].usb_flags == X)) && 433 ((attrs & usb_invalid_flags_attrs[i].attrs) || 434 (usb_invalid_flags_attrs[i].attrs == X))) { 435 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 436 "invalid (%d) : flags = 0x%x, attrs = 0x%x", 437 i, flags, attrs); 438 439 return (USB_INVALID_REQUEST); 440 } 441 } 442 443 return (USB_SUCCESS); 444 } 445 446 447 /* 448 * usba_rval2cr: 449 * convert rval to meaningful completion reason 450 * XXX extend completion reasons to get better mapping 451 */ 452 static struct { 453 int rval; 454 usb_cr_t cr; 455 } rval2cr[] = { 456 {USB_SUCCESS, USB_CR_OK}, 457 {USB_FAILURE, USB_CR_UNSPECIFIED_ERR}, 458 {USB_NO_RESOURCES, USB_CR_NO_RESOURCES}, 459 {USB_NO_BANDWIDTH, USB_CR_NO_RESOURCES}, 460 {USB_NOT_SUPPORTED, USB_CR_UNSPECIFIED_ERR}, 461 {USB_PIPE_ERROR, USB_CR_UNSPECIFIED_ERR}, 462 {USB_INVALID_PIPE, USB_CR_UNSPECIFIED_ERR}, 463 {USB_NO_FRAME_NUMBER, USB_CR_UNSPECIFIED_ERR}, 464 {USB_INVALID_START_FRAME, USB_CR_UNSPECIFIED_ERR}, 465 {USB_HC_HARDWARE_ERROR, USB_CR_UNSPECIFIED_ERR}, 466 {USB_INVALID_REQUEST, USB_CR_UNSPECIFIED_ERR}, 467 {USB_INVALID_CONTEXT, USB_CR_UNSPECIFIED_ERR}, 468 {USB_INVALID_VERSION, USB_CR_UNSPECIFIED_ERR}, 469 {USB_INVALID_ARGS, USB_CR_UNSPECIFIED_ERR}, 470 {USB_INVALID_PERM, USB_CR_UNSPECIFIED_ERR}, 471 {USB_BUSY, USB_CR_UNSPECIFIED_ERR}, 472 {0xffff, 0} 473 }; 474 475 usb_cr_t 476 usba_rval2cr(int rval) 477 { 478 int i; 479 480 for (i = 0; rval2cr[i].rval != 0xffff; i++) { 481 if (rval2cr[i].rval == rval) { 482 483 return (rval2cr[i].cr); 484 } 485 } 486 487 return (USB_CR_UNSPECIFIED_ERR); 488 } 489 490 491 /* 492 * usba_start_next_req: 493 * Arguments: 494 * ph_data - pointer to pipe handle 495 * 496 * Currently, only ctrl/bulk requests can be queued 497 */ 498 void 499 usba_start_next_req(usba_pipe_handle_data_t *ph_data) 500 { 501 usb_ctrl_req_t *ctrl_req; 502 usb_bulk_req_t *bulk_req; 503 usba_req_wrapper_t *wrp; 504 uchar_t ep_attrs = ph_data->p_ep.bmAttributes & 505 USB_EP_ATTR_MASK; 506 int rval; 507 usb_pipe_state_t state; 508 509 mutex_enter(&ph_data->p_mutex); 510 switch (ep_attrs) { 511 case USB_EP_ATTR_CONTROL: 512 case USB_EP_ATTR_BULK: 513 switch (usba_get_ph_state(ph_data)) { 514 case USB_PIPE_STATE_IDLE: 515 case USB_PIPE_STATE_CLOSING: 516 517 break; 518 519 default: 520 mutex_exit(&ph_data->p_mutex); 521 522 return; 523 } 524 525 break; 526 case USB_EP_ATTR_ISOCH: 527 case USB_EP_ATTR_INTR: 528 default: 529 mutex_exit(&ph_data->p_mutex); 530 531 return; 532 } 533 534 while ((wrp = (usba_req_wrapper_t *) 535 usba_rm_first_pvt_from_list(&ph_data->p_queue)) != NULL) { 536 537 /* only submit to HCD when idle/active */ 538 539 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 540 "usba_start_next_req: ph_data=0x%p state=%d", 541 (void *)ph_data, usba_get_ph_state(ph_data)); 542 543 if (ep_attrs == USB_EP_ATTR_CONTROL) { 544 ph_data->p_active_cntrl_req_wrp = (usb_opaque_t)wrp; 545 } 546 547 if ((state = usba_get_ph_state(ph_data)) == 548 USB_PIPE_STATE_IDLE) { 549 usba_pipe_new_state(ph_data, USB_PIPE_STATE_ACTIVE); 550 551 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 552 "starting req = 0x%p", 553 (void *)USBA_WRP2CTRL_REQ(wrp)); 554 555 switch (ep_attrs) { 556 case USB_EP_ATTR_CONTROL: 557 mutex_exit(&ph_data->p_mutex); 558 ctrl_req = USBA_WRP2CTRL_REQ(wrp); 559 /* submit to hcd */ 560 rval = ph_data->p_usba_device->usb_hcdi_ops-> 561 usba_hcdi_pipe_ctrl_xfer(ph_data, 562 ctrl_req, wrp->wr_usb_flags); 563 mutex_enter(&ph_data->p_mutex); 564 break; 565 case USB_EP_ATTR_BULK: 566 mutex_exit(&ph_data->p_mutex); 567 bulk_req = USBA_WRP2BULK_REQ(wrp); 568 /* submit to hcd */ 569 rval = ph_data->p_usba_device->usb_hcdi_ops-> 570 usba_hcdi_pipe_bulk_xfer(ph_data, 571 bulk_req, wrp->wr_usb_flags); 572 mutex_enter(&ph_data->p_mutex); 573 break; 574 default: 575 /* there shouldn't be any requests */ 576 rval = USB_FAILURE; 577 break; 578 } 579 580 if (rval != USB_SUCCESS) { 581 mutex_exit(&ph_data->p_mutex); 582 usba_do_req_exc_cb(wrp, 583 usba_rval2cr(rval), 584 USB_CB_SUBMIT_FAILED); 585 mutex_enter(&ph_data->p_mutex); 586 } 587 /* we are done */ 588 break; 589 590 } else { 591 mutex_exit(&ph_data->p_mutex); 592 switch (state) { 593 case USB_PIPE_STATE_CLOSING: 594 usba_do_req_exc_cb(wrp, USB_CR_PIPE_CLOSING, 0); 595 break; 596 case USB_PIPE_STATE_ERROR: 597 default: 598 usba_do_req_exc_cb(wrp, USB_CR_FLUSHED, 0); 599 break; 600 } 601 mutex_enter(&ph_data->p_mutex); 602 } 603 } 604 605 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 606 "usba_start_next_req done: ph_data=0x%p state=%d", (void *)ph_data, 607 usba_get_ph_state(ph_data)); 608 609 mutex_exit(&ph_data->p_mutex); 610 } 611 612 613 /* 614 * usba_req_wrapper_alloc: 615 * Allocate + Initialize a usba_req_wrapper_t 616 * 617 * Arguments: 618 * dip - dev_info_t of the client driver 619 * req_len - sizeof request 620 * flags - 621 * USB_FLAGS_SLEEP - Sleep if resources are not available 622 * no USB_FLAGS_SLEEP - Don't Sleep if resources are not available 623 * 624 * Return Values: 625 * pointer to usba_req_wrapper_t on success; NULL on failure. 626 * 627 */ 628 static usba_req_wrapper_t * 629 usba_req_wrapper_alloc(dev_info_t *dip, 630 size_t req_len, 631 usb_flags_t flags) 632 { 633 int kmflag; 634 usba_device_t *usba_device = usba_get_usba_device(dip); 635 usba_req_wrapper_t *wrp; 636 size_t wr_length = sizeof (usba_req_wrapper_t) + req_len; 637 ddi_iblock_cookie_t iblock_cookie = 638 usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip)-> 639 hcdi_iblock_cookie; 640 641 if (servicing_interrupt() && (flags & USB_FLAGS_SLEEP)) { 642 643 return (NULL); 644 } 645 646 kmflag = (flags & USB_FLAGS_SLEEP) ? KM_SLEEP : KM_NOSLEEP; 647 648 /* Allocate the usb_{c/b/i/i}_req + usba_req_wrapper_t structure */ 649 if ((wrp = kmem_zalloc(wr_length, kmflag)) != NULL) { 650 wrp->wr_length = wr_length; 651 wrp->wr_dip = dip; 652 wrp->wr_req = (usb_opaque_t)USBA_SETREQ_ADDR(wrp); 653 cv_init(&wrp->wr_cv, NULL, CV_DRIVER, NULL); 654 655 /* initialize mutex for the queue */ 656 usba_init_list(&wrp->wr_queue, (usb_opaque_t)wrp, 657 iblock_cookie); 658 usba_init_list(&wrp->wr_allocated_list, (usb_opaque_t)wrp, 659 iblock_cookie); 660 661 usba_add_to_list(&usba_device->usb_allocated, 662 &wrp->wr_allocated_list); 663 664 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 665 "usba_req_wrapper_alloc: wrp = 0x%p", (void *)wrp); 666 } 667 668 return (wrp); 669 } 670 671 672 /* 673 * usba_req_wrapper_free: 674 * Frees a usba_req_wrapper_t. Get rid of lists if any. 675 * 676 * Arguments: 677 * wrp: request wrapper structure 678 */ 679 void 680 usba_req_wrapper_free(usba_req_wrapper_t *wrp) 681 { 682 usba_device_t *usba_device; 683 usba_pipe_handle_data_t *ph_data; 684 685 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 686 "usba_req_wrapper_free: wrp=0x%p", (void *)wrp); 687 688 if (wrp) { 689 /* remove from queues */ 690 ph_data = USBA_WRP2PH_DATA(wrp); 691 if (ph_data) { 692 (void) usba_rm_from_list(&ph_data->p_queue, 693 &wrp->wr_queue); 694 } 695 usba_device = usba_get_usba_device(wrp->wr_dip); 696 if (usba_rm_from_list(&usba_device->usb_allocated, 697 &wrp->wr_allocated_list) != USB_SUCCESS) { 698 cmn_err(CE_PANIC, 699 "usba_req_wrapper_free: data corruption"); 700 } 701 usba_destroy_list(&wrp->wr_queue); 702 usba_destroy_list(&wrp->wr_allocated_list); 703 cv_destroy(&wrp->wr_cv); 704 kmem_free(wrp, wrp->wr_length); 705 } 706 } 707 708 709 /* 710 * usba_check_intr_context 711 * Set USB_CB_INTR_CONTEXT callback flag if executing in interrupt context 712 */ 713 usb_cb_flags_t 714 usba_check_intr_context(usb_cb_flags_t cb_flags) 715 { 716 if (servicing_interrupt() != 0) { 717 cb_flags |= USB_CB_INTR_CONTEXT; 718 } 719 720 return (cb_flags); 721 } 722 723 724 /* 725 * usba_req_normal_cb: 726 * perform normal callback depending on request type 727 */ 728 void 729 usba_req_normal_cb(usba_req_wrapper_t *req_wrp) 730 { 731 usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data; 732 usb_pipe_handle_t pipe_handle; 733 uint_t direction = ph_data->p_ep.bEndpointAddress & 734 USB_EP_DIR_MASK; 735 usb_pipe_state_t pipe_state; 736 737 pipe_handle = usba_get_pipe_handle(ph_data); 738 739 mutex_enter(&ph_data->p_mutex); 740 ASSERT(ph_data->p_req_count >= 0); 741 pipe_state = usba_get_ph_state(ph_data); 742 743 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 744 "usba_req_normal_cb: " 745 "ph_data=0x%p state=%d wrp=0x%p ref=%d req=%d", 746 (void *)ph_data, pipe_state, (void *)req_wrp, 747 usba_get_ph_ref_count(ph_data), ph_data->p_req_count); 748 749 ASSERT((pipe_state == USB_PIPE_STATE_ACTIVE) || 750 (pipe_state == USB_PIPE_STATE_CLOSING)); 751 752 /* set done to indicate that we will do callback or cv_signal */ 753 ASSERT(req_wrp->wr_done == B_FALSE); 754 req_wrp->wr_done = B_TRUE; 755 756 /* update the pipe state */ 757 switch (req_wrp->wr_ph_data->p_ep.bmAttributes & 758 USB_EP_ATTR_MASK) { 759 case USB_EP_ATTR_CONTROL: 760 case USB_EP_ATTR_BULK: 761 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 762 break; 763 case USB_EP_ATTR_INTR: 764 if ((direction == USB_EP_DIR_IN) && 765 (USBA_WRP2INTR_REQ(req_wrp)->intr_attributes & 766 USB_ATTRS_ONE_XFER)) { 767 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 768 } else if ((direction == USB_EP_DIR_OUT) && 769 (ph_data->p_req_count == 0)) { 770 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 771 } 772 break; 773 case USB_EP_ATTR_ISOCH: 774 if ((ph_data->p_req_count == 0) && 775 (direction == USB_EP_DIR_OUT)) { 776 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 777 } 778 break; 779 } 780 781 782 /* now complete the request */ 783 if (req_wrp->wr_usb_flags & USBA_WRP_FLAGS_WAIT) { 784 ph_data->p_active_cntrl_req_wrp = NULL; 785 cv_signal(&req_wrp->wr_cv); 786 mutex_exit(&ph_data->p_mutex); 787 } else { 788 mutex_exit(&ph_data->p_mutex); 789 790 /* This sets USB_CB_INTR_CONTEXT as needed. */ 791 usba_req_set_cb_flags(req_wrp, USB_CB_NO_INFO); 792 793 switch (req_wrp->wr_ph_data->p_ep.bmAttributes & 794 USB_EP_ATTR_MASK) { 795 case USB_EP_ATTR_CONTROL: 796 USBA_WRP2CTRL_REQ(req_wrp)->ctrl_cb(pipe_handle, 797 USBA_WRP2CTRL_REQ(req_wrp)); 798 mutex_enter(&ph_data->p_mutex); 799 ph_data->p_active_cntrl_req_wrp = NULL; 800 mutex_exit(&ph_data->p_mutex); 801 break; 802 case USB_EP_ATTR_INTR: 803 USBA_WRP2INTR_REQ(req_wrp)->intr_cb(pipe_handle, 804 USBA_WRP2INTR_REQ(req_wrp)); 805 break; 806 case USB_EP_ATTR_BULK: 807 USBA_WRP2BULK_REQ(req_wrp)->bulk_cb(pipe_handle, 808 USBA_WRP2BULK_REQ(req_wrp)); 809 break; 810 case USB_EP_ATTR_ISOCH: 811 USBA_WRP2ISOC_REQ(req_wrp)->isoc_cb(pipe_handle, 812 USBA_WRP2ISOC_REQ(req_wrp)); 813 break; 814 } 815 } 816 817 /* we are done with this request */ 818 mutex_enter(&ph_data->p_mutex); 819 ph_data->p_req_count--; 820 ASSERT(ph_data->p_req_count >= 0); 821 mutex_exit(&ph_data->p_mutex); 822 } 823 824 825 /* 826 * usba_req_exc_cb: 827 * perform exception cb depending on request type. 828 * ensure the completion reason is non zero 829 */ 830 void 831 usba_req_exc_cb(usba_req_wrapper_t *req_wrp, usb_cr_t cr, 832 usb_cb_flags_t cb_flags) 833 { 834 usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data; 835 usb_pipe_handle_t pipe_handle = usba_get_pipe_handle(ph_data); 836 837 mutex_enter(&req_wrp->wr_ph_data->p_mutex); 838 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 839 "usba_req_exc_cb: %s%d: ph_data=0x%p (ep%x) state=%d wrp=0x%p " 840 "ref=%d reqcnt=%d cr=%d", 841 ddi_driver_name(req_wrp->wr_dip), 842 ddi_get_instance(req_wrp->wr_dip), 843 (void *)ph_data, ph_data->p_ep.bEndpointAddress, 844 usba_get_ph_state(ph_data), (void *)req_wrp, 845 usba_get_ph_ref_count(ph_data), ph_data->p_req_count, 846 req_wrp->wr_cr); 847 848 ASSERT(req_wrp->wr_ph_data->p_req_count >= 0); 849 850 usba_req_set_cb_flags(req_wrp, cb_flags); 851 852 /* if there was no CR set already, set it now */ 853 if (req_wrp->wr_cr == USB_CR_OK) { 854 req_wrp->wr_cr = (cr != USB_CR_OK) ? 855 cr : USB_CR_UNSPECIFIED_ERR; 856 } 857 858 ASSERT(req_wrp->wr_done == B_FALSE); 859 req_wrp->wr_done = B_TRUE; 860 861 switch (req_wrp->wr_ph_data->p_ep.bmAttributes & 862 USB_EP_ATTR_MASK) { 863 case USB_EP_ATTR_CONTROL: 864 if (USBA_WRP2CTRL_REQ(req_wrp)-> 865 ctrl_completion_reason == USB_CR_OK) { 866 USBA_WRP2CTRL_REQ(req_wrp)-> 867 ctrl_completion_reason = req_wrp->wr_cr; 868 } 869 break; 870 case USB_EP_ATTR_INTR: 871 if (USBA_WRP2INTR_REQ(req_wrp)-> 872 intr_completion_reason == USB_CR_OK) { 873 USBA_WRP2INTR_REQ(req_wrp)-> 874 intr_completion_reason = req_wrp->wr_cr; 875 } 876 break; 877 case USB_EP_ATTR_BULK: 878 if (USBA_WRP2BULK_REQ(req_wrp)-> 879 bulk_completion_reason == USB_CR_OK) { 880 USBA_WRP2BULK_REQ(req_wrp)-> 881 bulk_completion_reason = req_wrp->wr_cr; 882 } 883 break; 884 case USB_EP_ATTR_ISOCH: 885 if (USBA_WRP2ISOC_REQ(req_wrp)-> 886 isoc_completion_reason == USB_CR_OK) { 887 USBA_WRP2ISOC_REQ(req_wrp)-> 888 isoc_completion_reason = req_wrp->wr_cr; 889 } 890 break; 891 } 892 893 if (req_wrp->wr_usb_flags & USBA_WRP_FLAGS_WAIT) { 894 cv_signal(&req_wrp->wr_cv); 895 if (ph_data->p_active_cntrl_req_wrp == (usb_opaque_t)req_wrp) { 896 ph_data->p_active_cntrl_req_wrp = NULL; 897 } 898 mutex_exit(&ph_data->p_mutex); 899 } else { 900 mutex_exit(&ph_data->p_mutex); 901 switch (req_wrp->wr_ph_data->p_ep.bmAttributes & 902 USB_EP_ATTR_MASK) { 903 case USB_EP_ATTR_CONTROL: 904 USBA_WRP2CTRL_REQ(req_wrp)->ctrl_exc_cb(pipe_handle, 905 USBA_WRP2CTRL_REQ(req_wrp)); 906 mutex_enter(&ph_data->p_mutex); 907 if (ph_data->p_active_cntrl_req_wrp == 908 (usb_opaque_t)req_wrp) { 909 ph_data->p_active_cntrl_req_wrp = NULL; 910 } 911 mutex_exit(&ph_data->p_mutex); 912 break; 913 case USB_EP_ATTR_INTR: 914 USBA_WRP2INTR_REQ(req_wrp)->intr_exc_cb(pipe_handle, 915 USBA_WRP2INTR_REQ(req_wrp)); 916 break; 917 case USB_EP_ATTR_BULK: 918 USBA_WRP2BULK_REQ(req_wrp)->bulk_exc_cb(pipe_handle, 919 USBA_WRP2BULK_REQ(req_wrp)); 920 break; 921 case USB_EP_ATTR_ISOCH: 922 USBA_WRP2ISOC_REQ(req_wrp)->isoc_exc_cb(pipe_handle, 923 USBA_WRP2ISOC_REQ(req_wrp)); 924 break; 925 } 926 } 927 928 /* we are done with this request */ 929 mutex_enter(&ph_data->p_mutex); 930 ph_data->p_req_count--; 931 ASSERT(ph_data->p_req_count >= 0); 932 mutex_exit(&ph_data->p_mutex); 933 } 934 935 936 /* 937 * usba_do_req_exc_cb: 938 * called when flushing requests. rather than calling usba_req_exc_cb() 939 * directly, this function uses usba_hcdi_cb() which ensures callback 940 * order is preserved 941 */ 942 void 943 usba_do_req_exc_cb(usba_req_wrapper_t *req_wrp, usb_cr_t cr, 944 usb_cb_flags_t cb_flags) 945 { 946 req_wrp->wr_cb_flags |= cb_flags; 947 usba_hcdi_cb(req_wrp->wr_ph_data, req_wrp->wr_req, cr); 948 } 949 950 951 /* 952 * usba_req_set_cb_flags: 953 * This function sets the request's callback flags to those stored in the 954 * request wrapper ORed with those received as an argument. Additionally 955 * USB_CB_INTR_CONTEXT is set if called from interrupt context. 956 * 957 * NOTE: The xfer may have succeeded, which client driver can determine 958 * by looking at usb_cr_t 959 */ 960 void 961 usba_req_set_cb_flags(usba_req_wrapper_t *req_wrp, 962 usb_cb_flags_t cb_flags) 963 { 964 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 965 "usba_req_set_cb_flags: wrp=0x%p cb-flags=0x%x", 966 (void *)req_wrp, cb_flags); 967 968 cb_flags |= req_wrp->wr_cb_flags; 969 cb_flags = usba_check_intr_context(cb_flags); 970 971 /* do the callback under taskq context */ 972 switch (req_wrp->wr_ph_data->p_ep.bmAttributes & 973 USB_EP_ATTR_MASK) { 974 case USB_EP_ATTR_CONTROL: 975 USBA_WRP2CTRL_REQ(req_wrp)->ctrl_cb_flags |= cb_flags; 976 break; 977 case USB_EP_ATTR_INTR: 978 USBA_WRP2INTR_REQ(req_wrp)->intr_cb_flags |= cb_flags; 979 break; 980 case USB_EP_ATTR_BULK: 981 USBA_WRP2BULK_REQ(req_wrp)->bulk_cb_flags |= cb_flags; 982 break; 983 case USB_EP_ATTR_ISOCH: 984 USBA_WRP2ISOC_REQ(req_wrp)->isoc_cb_flags |= cb_flags; 985 break; 986 } 987 } 988 989 990 /* 991 * usba_pipe_sync_wait: 992 * wait for the request to finish. 993 * usba_hcdi_cb() does a cv_signal thru a soft intr 994 * 995 * Arguments: 996 * ph_data - pointer to pipe handle data 997 * wrp - pointer to usba_req_wrapper_structure. 998 * 999 * Return Values: 1000 * USB_SUCCESS - request successfully executed 1001 * USB_FAILURE - request failed 1002 */ 1003 static int 1004 usba_pipe_sync_wait(usba_pipe_handle_data_t *ph_data, 1005 usba_req_wrapper_t *wrp) 1006 { 1007 ASSERT(wrp->wr_usb_flags & USB_FLAGS_SLEEP); 1008 ASSERT(ph_data == wrp->wr_ph_data); 1009 1010 mutex_enter(&ph_data->p_mutex); 1011 while (wrp->wr_done != B_TRUE) { 1012 cv_wait(&wrp->wr_cv, &ph_data->p_mutex); 1013 } 1014 1015 mutex_exit(&ph_data->p_mutex); 1016 1017 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1018 "usba_pipe_sync_wait: ph_data=0x%p cr=0x%x", (void *)ph_data, 1019 wrp->wr_cr); 1020 1021 /* XXX return something better than USB_FAILURE?? */ 1022 1023 return (wrp->wr_cr == USB_CR_OK ? USB_SUCCESS : USB_FAILURE); 1024 } 1025 1026 1027 /* 1028 * Allocate usb control request and a USB request wrapper 1029 * 1030 * Arguments: 1031 * dip - dev_info_t of the client driver 1032 * len - length of "data" for this control request 1033 * flags: 1034 * USB_FLAGS_SLEEP - Sleep if resources are not available 1035 * no USB_FLAGS_SLEEP - Don't Sleep if resources are not available 1036 * 1037 * Return Values: usb_ctrl_req_t on success, NULL on failure 1038 */ 1039 usb_ctrl_req_t * 1040 usb_alloc_ctrl_req(dev_info_t *dip, 1041 size_t len, 1042 usb_flags_t flags) 1043 { 1044 usb_ctrl_req_t *ctrl_req = NULL; 1045 usba_req_wrapper_t *wrp; 1046 1047 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1048 "usb_alloc_ctrl_req: dip=0x%p, wlen=0x%lx, flags=0x%x", 1049 (void *)dip, len, flags); 1050 1051 /* Allocate + Initialize the usba_req_wrapper_t structure */ 1052 if (dip && 1053 ((wrp = usba_req_wrapper_alloc(dip, sizeof (*ctrl_req), flags)) != 1054 NULL)) { 1055 ctrl_req = USBA_WRP2CTRL_REQ(wrp); 1056 1057 /* Allocate the usb_ctrl_req data mblk */ 1058 if (len) { 1059 if (flags & USB_FLAGS_SLEEP) { 1060 ctrl_req->ctrl_data = allocb_wait(len, BPRI_LO, 1061 STR_NOSIG, NULL); 1062 } else if ((ctrl_req->ctrl_data = 1063 allocb(len, BPRI_HI)) == NULL) { 1064 usba_req_wrapper_free(wrp); 1065 ctrl_req = NULL; 1066 } 1067 } 1068 } 1069 1070 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1071 "usb_alloc_ctrl_req: ctrl_req = 0x%p", (void *)ctrl_req); 1072 1073 return (ctrl_req); 1074 } 1075 1076 1077 /* 1078 * usb_free_ctrl_req: 1079 * free USB control request + wrapper 1080 * 1081 * Arguments: 1082 * req - pointer to usb_ctrl_req_t 1083 */ 1084 void 1085 usb_free_ctrl_req(usb_ctrl_req_t *req) 1086 { 1087 if (req) { 1088 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1089 "usb_free_ctrl_req: req = 0x%p", (void *)req); 1090 1091 if (req->ctrl_data) { 1092 freemsg(req->ctrl_data); 1093 } 1094 usba_req_wrapper_free(USBA_REQ2WRP(req)); 1095 } 1096 } 1097 1098 1099 /* 1100 * Client driver calls this function to issue the control 1101 * request to the USBA 1102 * 1103 * Arguments: 1104 * pipe_handle: control pipe pipehandle (obtained via usb_pipe_open() 1105 * req: control request 1106 * usb_flags: 1107 * USB_FLAGS_SLEEP - wait for the request to complete 1108 * 1109 * Return Values: 1110 * USB_SUCCESS - request successfully executed 1111 * USB_FAILURE - request failed 1112 */ 1113 int 1114 usb_pipe_ctrl_xfer(usb_pipe_handle_t pipe_handle, 1115 usb_ctrl_req_t *req, 1116 usb_flags_t usb_flags) 1117 { 1118 int rval; 1119 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 1120 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1121 usba_device_t *usba_device; 1122 usb_flags_t wrp_usb_flags; 1123 usb_pipe_state_t pipe_state; 1124 1125 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1126 "usb_pipe_ctrl_xfer: req=0x%p, wrp=0x%p\n\t" 1127 "setup = 0x%x 0x%x 0x%x 0x%x 0x%x uf=0x%x", 1128 (void *)req, (void *)wrp, req->ctrl_bmRequestType, 1129 req->ctrl_bRequest, req->ctrl_wValue, req->ctrl_wIndex, 1130 req->ctrl_wLength, usb_flags); 1131 1132 if (ph_data == NULL) { 1133 1134 return (USB_INVALID_PIPE); 1135 } 1136 1137 mutex_enter(&ph_data->p_mutex); 1138 usba_device = ph_data->p_usba_device; 1139 1140 if ((rval = usba_check_req(ph_data, (usb_opaque_t)req, usb_flags, 1141 USB_EP_ATTR_CONTROL)) != USB_SUCCESS) { 1142 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1143 "request rejected: rval=%d", rval); 1144 mutex_exit(&ph_data->p_mutex); 1145 1146 usba_release_ph_data(ph_data->p_ph_impl); 1147 1148 return (rval); 1149 } 1150 1151 ASSERT(ph_data == wrp->wr_ph_data); 1152 1153 /* we accepted the request, so increment the req count */ 1154 ph_data->p_req_count++; 1155 1156 wrp_usb_flags = wrp->wr_usb_flags; 1157 1158 /* Get the current bulk pipe state */ 1159 pipe_state = usba_get_ph_state(ph_data); 1160 1161 /* 1162 * if this is for the default pipe, and the pipe is in error, 1163 * just queue the request. autoclearing will start this request 1164 * 1165 * if there is already an active request in the queue 1166 * then just add this request to the queue. 1167 */ 1168 switch (pipe_state) { 1169 case USB_PIPE_STATE_IDLE: 1170 if (ph_data->p_queue.next || 1171 ph_data->p_active_cntrl_req_wrp) { 1172 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1173 "usb_pipe_ctrl_xfer: queue request 0x%p", 1174 (void *)req); 1175 1176 usba_add_to_list(&ph_data->p_queue, &wrp->wr_queue); 1177 rval = USB_SUCCESS; 1178 mutex_exit(&ph_data->p_mutex); 1179 } else { 1180 usba_pipe_new_state(ph_data, USB_PIPE_STATE_ACTIVE); 1181 ph_data->p_active_cntrl_req_wrp = (usb_opaque_t)wrp; 1182 mutex_exit(&ph_data->p_mutex); 1183 1184 /* issue the request to HCD */ 1185 rval = usba_device->usb_hcdi_ops-> 1186 usba_hcdi_pipe_ctrl_xfer(ph_data, req, usb_flags); 1187 } 1188 break; 1189 case USB_PIPE_STATE_ACTIVE: 1190 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1191 "usb_pipe_ctrl_xfer: queue request 0x%p", (void *)req); 1192 1193 usba_add_to_list(&ph_data->p_queue, &wrp->wr_queue); 1194 rval = USB_SUCCESS; 1195 mutex_exit(&ph_data->p_mutex); 1196 break; 1197 case USB_PIPE_STATE_ERROR: 1198 if (USBA_IS_DEFAULT_PIPE(ph_data)) { 1199 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1200 "usb_pipe_ctrl_xfer: queue request 0x%p on " 1201 "pending def pipe error", (void *)req); 1202 1203 usba_add_to_list(&ph_data->p_queue, &wrp->wr_queue); 1204 rval = USB_SUCCESS; 1205 } else { 1206 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1207 "usb_pipe_ctrl_xfer: pipe is in error state "); 1208 1209 rval = USB_PIPE_ERROR; 1210 } 1211 mutex_exit(&ph_data->p_mutex); 1212 break; 1213 default: 1214 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1215 "usb_pipe_ctrl_xfer: pipe state %d", pipe_state); 1216 1217 rval = USB_PIPE_ERROR; 1218 mutex_exit(&ph_data->p_mutex); 1219 break; 1220 } 1221 1222 /* if there has been a failure, decrement req count */ 1223 if (rval != USB_SUCCESS) { 1224 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1225 "usb_pipe_ctrl_xfer: hcd failed req 0x%p", (void *)req); 1226 1227 if (req->ctrl_completion_reason == USB_CR_OK) { 1228 req->ctrl_completion_reason = usba_rval2cr(rval); 1229 } 1230 mutex_enter(&ph_data->p_mutex); 1231 ASSERT(wrp->wr_done == B_FALSE); 1232 ph_data->p_req_count--; 1233 ASSERT(ph_data->p_req_count >= 0); 1234 ph_data->p_active_cntrl_req_wrp = NULL; 1235 if ((ph_data->p_req_count == 0) && 1236 (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ACTIVE)) { 1237 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 1238 } 1239 mutex_exit(&ph_data->p_mutex); 1240 1241 /* if success and sleep specified, wait for completion */ 1242 } else if (wrp_usb_flags & USBA_WRP_FLAGS_WAIT) { 1243 rval = usba_pipe_sync_wait(ph_data, wrp); 1244 } 1245 1246 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1247 "usb_pipe_ctrl_xfer: rval=0x%x", rval); 1248 1249 usba_release_ph_data(ph_data->p_ph_impl); 1250 1251 return (rval); 1252 } 1253 1254 1255 /* 1256 * usb_pipe_sync_ctrl_xfer(): 1257 * for simple synchronous control transactions this wrapper function 1258 * will perform the allocation, xfer, and deallocation 1259 * USB_ATTRS_AUTOCLEARING will be enabled 1260 * 1261 * Arguments: 1262 * dip - pointer to clients devinfo 1263 * pipe_handle - control pipe pipehandle (obtained via usb_pipe_open() 1264 * bmRequestType - characteristics of request 1265 * bRequest - specific request 1266 * wValue - varies according to request 1267 * wIndex - index or offset 1268 * wLength - number of bytes to xfer 1269 * data - pointer to pointer to data and may be NULL if 1270 * wLength is 0 1271 * attrs - required request attributes 1272 * completion_reason - completion status 1273 * cb_flags - request completions flags 1274 * flags - none 1275 * 1276 * Return Values: 1277 * USB_SUCCESS - request successfully executed 1278 * USB_* - request failed 1279 * 1280 * Notes: 1281 * - in the case of failure, the client should check completion_reason and 1282 * and cb_flags and determine further recovery action 1283 * - the client should check data and if non-zero, free the data on 1284 * completion 1285 */ 1286 int 1287 usb_pipe_sync_ctrl_xfer(dev_info_t *dip, 1288 usb_pipe_handle_t pipe_handle, 1289 uchar_t bmRequestType, 1290 uchar_t bRequest, 1291 uint16_t wValue, 1292 uint16_t wIndex, 1293 uint16_t wLength, 1294 mblk_t **data, 1295 usb_req_attrs_t attributes, 1296 usb_cr_t *completion_reason, 1297 usb_cb_flags_t *cb_flags, 1298 usb_flags_t flags) 1299 { 1300 usba_pipe_handle_data_t *ph_data; 1301 int rval; 1302 usb_ctrl_req_t *ctrl_req; 1303 size_t length; 1304 #ifdef DEBUG 1305 #define BUFSIZE 256 1306 char *buf = kmem_alloc(BUFSIZE, KM_SLEEP); 1307 #endif 1308 1309 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1310 "usb_pipe_sync_ctrl_xfer: ph=0x%p\n\t" 1311 "setup = 0x%x 0x%x 0x%x 0x%x 0x%x uf = 0x%x", (void *)pipe_handle, 1312 bmRequestType, bRequest, wValue, wIndex, wLength, flags); 1313 1314 if ((ph_data = usba_hold_ph_data(pipe_handle)) == NULL) { 1315 rval = USB_INVALID_PIPE; 1316 1317 goto done; 1318 } 1319 if (servicing_interrupt()) { 1320 rval = USB_INVALID_CONTEXT; 1321 1322 goto done; 1323 } 1324 if (dip == NULL) { 1325 rval = USB_INVALID_ARGS; 1326 1327 goto done; 1328 } 1329 1330 length = ((data) && (*data)) ? 0: wLength; 1331 1332 ctrl_req = usb_alloc_ctrl_req(dip, 1333 length, flags | USB_FLAGS_SLEEP); 1334 1335 /* Initialize the ctrl_req structure */ 1336 ctrl_req->ctrl_bmRequestType = bmRequestType; 1337 ctrl_req->ctrl_bRequest = bRequest; 1338 ctrl_req->ctrl_wValue = wValue; 1339 ctrl_req->ctrl_wIndex = wIndex; 1340 ctrl_req->ctrl_wLength = wLength; 1341 ctrl_req->ctrl_data = ctrl_req->ctrl_data ? 1342 ctrl_req->ctrl_data : ((data) ? *data : NULL); 1343 ctrl_req->ctrl_timeout = USB_PIPE_TIMEOUT; 1344 ctrl_req->ctrl_attributes = attributes | USB_ATTRS_AUTOCLEARING; 1345 1346 /* Issue control xfer to the HCD */ 1347 rval = usb_pipe_ctrl_xfer(pipe_handle, ctrl_req, 1348 flags | USB_FLAGS_SLEEP); 1349 1350 #ifdef DEBUG 1351 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1352 "req=0x%p, cr=%s cb_flags=%s data=0x%p rval=%s", 1353 (void *)ctrl_req, usb_str_cr(ctrl_req->ctrl_completion_reason), 1354 usb_str_cb_flags(ctrl_req->ctrl_cb_flags, buf, BUFSIZE), 1355 (void *)ctrl_req->ctrl_data, usb_str_rval(rval)); 1356 #endif 1357 1358 /* copy back ctrl_req values */ 1359 if (data) { 1360 *data = ctrl_req->ctrl_data; 1361 } 1362 if (completion_reason) { 1363 *completion_reason = ctrl_req->ctrl_completion_reason; 1364 } 1365 if (cb_flags) { 1366 *cb_flags = ctrl_req->ctrl_cb_flags; 1367 } 1368 1369 /* Free up the control request now */ 1370 ctrl_req->ctrl_data = NULL; /* leave to client to free */ 1371 usb_free_ctrl_req(ctrl_req); 1372 1373 done: 1374 #ifdef DEBUG 1375 kmem_free(buf, BUFSIZE); 1376 #endif 1377 if (ph_data) { 1378 usba_release_ph_data(ph_data->p_ph_impl); 1379 } 1380 1381 return (rval); 1382 } 1383 1384 1385 /* 1386 * usb_pipe_ctrl_xfer_wait(): 1387 * Easy-to-use wrapper around usb_pipe_sync_ctrl_xfer. 1388 * 1389 * ARGUMENTS: 1390 * pipe_handle - control pipe pipehandle (obtained via usb_pipe_open()) 1391 * setup - setup descriptor params, attributes 1392 * data - pointer to pointer to data and may be NULL when 1393 * wLength is 0 1394 * completion_reason - completion status. 1395 * cb_flags - request completions flags. 1396 * flags - none. 1397 * 1398 * RETURN VALUES: 1399 * USB_SUCCESS - request successfully executed. 1400 * USB_* - failure 1401 */ 1402 int 1403 usb_pipe_ctrl_xfer_wait( 1404 usb_pipe_handle_t pipe_handle, 1405 usb_ctrl_setup_t *setup, 1406 mblk_t **data, 1407 usb_cr_t *completion_reason, 1408 usb_cb_flags_t *cb_flags, 1409 usb_flags_t flags) 1410 { 1411 return (usb_pipe_sync_ctrl_xfer( 1412 usba_get_dip(pipe_handle), 1413 pipe_handle, 1414 setup->bmRequestType, 1415 setup->bRequest, 1416 setup->wValue, 1417 setup->wIndex, 1418 setup->wLength, 1419 data, 1420 setup->attrs, 1421 completion_reason, 1422 cb_flags, 1423 flags)); 1424 } 1425 1426 1427 /* 1428 * usb_alloc_bulk_req: 1429 * Allocate a usb bulk request + usba_req_wrapper_t 1430 * 1431 * Arguments: 1432 * dip - dev_info_t of the client driver 1433 * len - length of "data" for this bulk request 1434 * flags: 1435 * USB_FLAGS_SLEEP - Sleep if resources are not available 1436 * 1437 * Return Values: 1438 * usb_bulk_req_t on success, NULL on failure 1439 */ 1440 usb_bulk_req_t * 1441 usb_alloc_bulk_req(dev_info_t *dip, 1442 size_t len, 1443 usb_flags_t flags) 1444 { 1445 usb_bulk_req_t *bulk_req = NULL; 1446 usba_req_wrapper_t *wrp; 1447 1448 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1449 "usb_alloc_bulk_req: dip=0x%p wlen=0x%lx flags=0x%x", 1450 (void *)dip, len, flags); 1451 1452 /* Allocate + Initialize the usba_req_wrapper_t structure */ 1453 if (dip && 1454 ((wrp = usba_req_wrapper_alloc(dip, sizeof (*bulk_req), flags)) != 1455 NULL)) { 1456 bulk_req = USBA_WRP2BULK_REQ(wrp); 1457 1458 /* Allocate the usb_bulk_req data mblk */ 1459 if (len) { 1460 if (flags & USB_FLAGS_SLEEP) { 1461 bulk_req->bulk_data = allocb_wait(len, 1462 BPRI_LO, STR_NOSIG, NULL); 1463 } else if ((bulk_req->bulk_data = 1464 allocb(len, BPRI_HI)) == NULL) { 1465 usba_req_wrapper_free(wrp); 1466 bulk_req = NULL; 1467 } 1468 } 1469 1470 } 1471 1472 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1473 "usb_alloc_bulk_req: bulk_req = 0x%p", (void *)bulk_req); 1474 1475 return (bulk_req); 1476 } 1477 1478 1479 /* 1480 * usb_free_bulk_req: 1481 * free USB bulk request + wrapper 1482 * 1483 * Arguments: 1484 * req - pointer to usb_bulk_req_t 1485 */ 1486 void 1487 usb_free_bulk_req(usb_bulk_req_t *req) 1488 { 1489 if (req) { 1490 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1491 "usb_free_bulk_req: req=0x%p", (void *)req); 1492 1493 if (req->bulk_data) { 1494 freemsg(req->bulk_data); 1495 } 1496 usba_req_wrapper_free(USBA_REQ2WRP(req)); 1497 } 1498 } 1499 1500 1501 /* 1502 * Client driver calls this function to issue the bulk xfer to the USBA 1503 * 1504 * Arguments:- 1505 * pipe_handle - bulk pipe handle (obtained via usb_pipe_open() 1506 * req - bulk data xfer request (IN or OUT) 1507 * usb_flags - USB_FLAGS_SLEEP - wait for the request to complete 1508 * 1509 * Return Values: 1510 * USB_SUCCESS - success 1511 * USB_FAILURE - unspecified failure 1512 */ 1513 int 1514 usb_pipe_bulk_xfer(usb_pipe_handle_t pipe_handle, 1515 usb_bulk_req_t *req, 1516 usb_flags_t usb_flags) 1517 { 1518 int rval; 1519 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 1520 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1521 usba_device_t *usba_device; 1522 usb_flags_t wrp_usb_flags; 1523 usb_pipe_state_t pipe_state; 1524 1525 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1526 "usb_pipe_bulk_xfer: req=0x%p uf=0x%x", (void *)req, usb_flags); 1527 1528 if (ph_data == NULL) { 1529 1530 return (USB_INVALID_PIPE); 1531 } 1532 1533 mutex_enter(&ph_data->p_mutex); 1534 usba_device = ph_data->p_usba_device; 1535 1536 if ((rval = usba_check_req(ph_data, (usb_opaque_t)req, usb_flags, 1537 USB_EP_ATTR_BULK)) != USB_SUCCESS) { 1538 mutex_exit(&ph_data->p_mutex); 1539 1540 usba_release_ph_data(ph_data->p_ph_impl); 1541 1542 return (rval); 1543 } 1544 1545 /* we accepted the request */ 1546 ph_data->p_req_count++; 1547 wrp_usb_flags = wrp->wr_usb_flags; 1548 1549 /* Get the current bulk pipe state */ 1550 pipe_state = usba_get_ph_state(ph_data); 1551 1552 /* 1553 * if there is already an active request in the queue 1554 * then just add this request to the queue. 1555 */ 1556 switch (pipe_state) { 1557 case USB_PIPE_STATE_IDLE: 1558 if (ph_data->p_queue.next) { 1559 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1560 "usb_pipe_bulk_xfer: queue request 0x%p", 1561 (void *)req); 1562 1563 usba_add_to_list(&ph_data->p_queue, &wrp->wr_queue); 1564 rval = USB_SUCCESS; 1565 mutex_exit(&ph_data->p_mutex); 1566 } else { 1567 usba_pipe_new_state(ph_data, USB_PIPE_STATE_ACTIVE); 1568 mutex_exit(&ph_data->p_mutex); 1569 1570 /* issue the request to HCD */ 1571 rval = usba_device->usb_hcdi_ops-> 1572 usba_hcdi_pipe_bulk_xfer(ph_data, req, usb_flags); 1573 } 1574 break; 1575 case USB_PIPE_STATE_ACTIVE: 1576 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1577 "usb_pipe_bulk_xfer: queue request 0x%p", (void *)req); 1578 1579 usba_add_to_list(&ph_data->p_queue, &wrp->wr_queue); 1580 rval = USB_SUCCESS; 1581 mutex_exit(&ph_data->p_mutex); 1582 break; 1583 default: 1584 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1585 "usb_pipe_bulk_xfer: pipe state %d", pipe_state); 1586 1587 rval = USB_PIPE_ERROR; 1588 mutex_exit(&ph_data->p_mutex); 1589 break; 1590 } 1591 1592 if (rval != USB_SUCCESS) { 1593 if (req->bulk_completion_reason == USB_CR_OK) { 1594 req->bulk_completion_reason = usba_rval2cr(rval); 1595 } 1596 mutex_enter(&ph_data->p_mutex); 1597 ASSERT(wrp->wr_done == B_FALSE); 1598 ph_data->p_req_count--; 1599 ASSERT(ph_data->p_req_count >= 0); 1600 if ((ph_data->p_req_count == 0) && 1601 (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ACTIVE)) { 1602 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 1603 } 1604 mutex_exit(&ph_data->p_mutex); 1605 } else if (wrp_usb_flags & USBA_WRP_FLAGS_WAIT) { 1606 rval = usba_pipe_sync_wait(ph_data, wrp); 1607 } 1608 1609 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1610 "usb_pipe_bulk_xfer: rval=%d", rval); 1611 1612 usba_release_ph_data(ph_data->p_ph_impl); 1613 1614 return (rval); 1615 } 1616 1617 1618 /* 1619 * usb_pipe_bulk_transfer_size: 1620 * - request HCD to return bulk max transfer data size 1621 * 1622 * Arguments: 1623 * dip - pointer to dev_info_t 1624 * size - pointer to bulk_transfer_size 1625 * 1626 * Return Values: 1627 * USB_SUCCESS - request successfully executed 1628 * USB_FAILURE - request failed 1629 */ 1630 int 1631 usb_pipe_bulk_transfer_size(dev_info_t *dip, 1632 size_t *size) 1633 { 1634 return (usb_pipe_get_max_bulk_transfer_size(dip, size)); 1635 } 1636 1637 1638 int 1639 usb_pipe_get_max_bulk_transfer_size(dev_info_t *dip, 1640 size_t *size) 1641 { 1642 usba_device_t *usba_device; 1643 1644 if ((dip == NULL) || (size == NULL)) { 1645 1646 return (USB_INVALID_ARGS); 1647 } 1648 usba_device = usba_get_usba_device(dip); 1649 1650 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1651 "usb_pipe_bulk_transfer_size: usba_device=0x%p", 1652 (void *)usba_device); 1653 1654 if ((usba_device) && 1655 (usba_device->usb_hcdi_ops->usba_hcdi_bulk_transfer_size)) { 1656 1657 return (usba_device->usb_hcdi_ops-> 1658 usba_hcdi_bulk_transfer_size(usba_device, size)); 1659 } else { 1660 *size = 0; 1661 1662 return (USB_FAILURE); 1663 } 1664 } 1665 1666 1667 /* 1668 * usb_alloc_intr_req: 1669 * Allocate usb interrupt request 1670 * 1671 * Arguments: 1672 * dip - dev_info_t of the client driver 1673 * len - length of "data" for this interrupt request 1674 * flags - 1675 * USB_FLAGS_SLEEP - Sleep if resources are not available 1676 * 1677 * Return Values: 1678 * usb_intr_req_t on success, NULL on failure 1679 */ 1680 usb_intr_req_t * 1681 usb_alloc_intr_req(dev_info_t *dip, 1682 size_t len, 1683 usb_flags_t flags) 1684 { 1685 usb_intr_req_t *intr_req = NULL; 1686 usba_req_wrapper_t *wrp; 1687 1688 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1689 "usb_alloc_intr_req: dip=0x%p, len=0x%lx, flags=0x%x", 1690 (void *)dip, len, flags); 1691 1692 /* Allocate + Initialize the usba_req_wrapper_t structure */ 1693 if ((dip && 1694 (wrp = usba_req_wrapper_alloc(dip, sizeof (*intr_req), flags)) != 1695 NULL)) { 1696 intr_req = (usb_intr_req_t *)USBA_WRP2INTR_REQ(wrp); 1697 1698 /* Allocate the usb_intr_req data mblk */ 1699 if (len) { 1700 if (flags & USB_FLAGS_SLEEP) { 1701 intr_req->intr_data = allocb_wait(len, BPRI_LO, 1702 STR_NOSIG, NULL); 1703 } else if ((intr_req->intr_data = 1704 allocb(len, BPRI_HI)) == NULL) { 1705 usba_req_wrapper_free(wrp); 1706 intr_req = NULL; 1707 } 1708 } 1709 } 1710 1711 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1712 "usb_alloc_intr_req: intr_req=0x%p", (void *)intr_req); 1713 1714 return (intr_req); 1715 } 1716 1717 1718 /* 1719 * usba_hcdi_dup_intr_req: 1720 * create duplicate of interrupt request 1721 * 1722 * Arguments: 1723 * dip - devinfo pointer 1724 * reqp - original requestp pointer 1725 * len - length of "data" for this interrupt request 1726 * flags - 1727 * USB_FLAGS_SLEEP - Sleep if resources are not available 1728 * 1729 * Return Values: 1730 * usb_intr_req_t on success, NULL on failure 1731 */ 1732 usb_intr_req_t * 1733 usba_hcdi_dup_intr_req( 1734 dev_info_t *dip, 1735 usb_intr_req_t *reqp, 1736 size_t len, 1737 usb_flags_t flags) 1738 { 1739 usb_intr_req_t *intr_reqp = NULL; 1740 usba_req_wrapper_t *intr_wrp, *req_wrp; 1741 1742 if (reqp == NULL) { 1743 1744 return (NULL); 1745 } 1746 1747 req_wrp = USBA_REQ2WRP(reqp); 1748 1749 if (((intr_reqp = usb_alloc_intr_req(dip, len, flags)) != NULL)) { 1750 intr_reqp->intr_client_private = reqp->intr_client_private; 1751 intr_reqp->intr_timeout = reqp->intr_timeout; 1752 intr_reqp->intr_attributes = reqp->intr_attributes; 1753 intr_reqp->intr_len = reqp->intr_len; 1754 intr_reqp->intr_cb = reqp->intr_cb; 1755 intr_reqp->intr_exc_cb = reqp->intr_exc_cb; 1756 1757 intr_wrp = USBA_REQ2WRP(intr_reqp); 1758 intr_wrp->wr_dip = req_wrp->wr_dip; 1759 intr_wrp->wr_ph_data = req_wrp->wr_ph_data; 1760 intr_wrp->wr_attrs = req_wrp->wr_attrs; 1761 intr_wrp->wr_usb_flags = req_wrp->wr_usb_flags; 1762 } 1763 1764 return (intr_reqp); 1765 } 1766 1767 1768 /* 1769 * usb_free_intr_req: 1770 * free USB intr request + wrapper 1771 * 1772 * Arguments: 1773 * req - pointer to usb_intr_req_t 1774 */ 1775 void 1776 usb_free_intr_req(usb_intr_req_t *req) 1777 { 1778 if (req) { 1779 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1780 "usb_free_intr_req: req = 0x%p", (void *)req); 1781 1782 if (req->intr_data) { 1783 freemsg(req->intr_data); 1784 } 1785 1786 usba_req_wrapper_free(USBA_REQ2WRP(req)); 1787 } 1788 } 1789 1790 1791 /* 1792 * Client driver calls this function to issue the intr xfer to the USBA 1793 * 1794 * Arguments:- 1795 * pipe_handle - intr pipe handle (obtained via usb_pipe_open() 1796 * req - intr data xfer request (IN or OUT) 1797 * flags - 1798 * USB_FLAGS_SLEEP - wait for the request to complete 1799 * Return Values 1800 * USB_SUCCESS - success 1801 * USB_FAILURE - unspecified failure 1802 */ 1803 int 1804 usb_pipe_intr_xfer(usb_pipe_handle_t pipe_handle, 1805 usb_intr_req_t *req, 1806 usb_flags_t usb_flags) 1807 { 1808 int rval; 1809 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 1810 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle; 1811 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1812 usba_device_t *usba_device; 1813 uchar_t direction; 1814 usb_flags_t wrp_usb_flags; 1815 usb_pipe_state_t pipe_state; 1816 1817 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1818 "usb_pipe_intr_req: req=0x%p uf=0x%x", 1819 (void *)req, usb_flags); 1820 1821 if (ph_data == NULL) { 1822 1823 return (USB_INVALID_PIPE); 1824 } 1825 usba_device = ph_data->p_usba_device; 1826 direction = ph_data->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1827 1828 mutex_enter(&ph_data->p_mutex); 1829 if ((rval = usba_check_req(ph_data, (usb_opaque_t)req, usb_flags, 1830 USB_EP_ATTR_INTR)) != USB_SUCCESS) { 1831 mutex_exit(&ph_data->p_mutex); 1832 1833 usba_release_ph_data(ph_data->p_ph_impl); 1834 1835 return (rval); 1836 } 1837 1838 /* Get the current interrupt pipe state */ 1839 pipe_state = usba_get_ph_state(ph_data); 1840 1841 switch (pipe_state) { 1842 case USB_PIPE_STATE_IDLE: 1843 /* 1844 * if the pipe state is in middle of transition, 1845 * i.e. stop polling is in progress, fail any 1846 * attempt to do a start polling 1847 */ 1848 mutex_enter(&ph_impl->usba_ph_mutex); 1849 if (ph_impl->usba_ph_state_changing > 0) { 1850 mutex_exit(&ph_impl->usba_ph_mutex); 1851 1852 mutex_exit(&ph_data->p_mutex); 1853 usba_release_ph_data(ph_data->p_ph_impl); 1854 1855 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1856 "usb_pipe_intr_req: fail request - " 1857 "stop polling in progress"); 1858 1859 return (USB_FAILURE); 1860 } else { 1861 mutex_exit(&ph_impl->usba_ph_mutex); 1862 usba_pipe_new_state(ph_data, USB_PIPE_STATE_ACTIVE); 1863 } 1864 1865 break; 1866 case USB_PIPE_STATE_ACTIVE: 1867 /* 1868 * If this is interrupt IN pipe and if we are 1869 * already polling, return failure. 1870 */ 1871 if (direction == USB_EP_DIR_IN) { 1872 USB_DPRINTF_L4(DPRINT_MASK_USBAI, 1873 usbai_log_handle, 1874 "usb_pipe_intr_req: already polling"); 1875 1876 mutex_exit(&ph_data->p_mutex); 1877 usba_release_ph_data(ph_data->p_ph_impl); 1878 1879 return (USB_FAILURE); 1880 } 1881 1882 break; 1883 default: 1884 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1885 "usb_pipe_intr_req: pipe state %d", pipe_state); 1886 1887 mutex_exit(&ph_data->p_mutex); 1888 usba_release_ph_data(ph_data->p_ph_impl); 1889 1890 return (USB_PIPE_ERROR); 1891 } 1892 1893 /* we accept the request */ 1894 wrp_usb_flags = wrp->wr_usb_flags; 1895 ph_data->p_req_count++; 1896 1897 mutex_exit(&ph_data->p_mutex); 1898 1899 /* issue the request out */ 1900 if ((rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_intr_xfer(ph_data, 1901 req, usb_flags)) != USB_SUCCESS) { 1902 1903 /* the request failed, decrement the ref_count */ 1904 if (req->intr_completion_reason == USB_CR_OK) { 1905 req->intr_completion_reason = usba_rval2cr(rval); 1906 } 1907 mutex_enter(&ph_data->p_mutex); 1908 ASSERT(wrp->wr_done == B_FALSE); 1909 ph_data->p_req_count--; 1910 ASSERT(ph_data->p_req_count >= 0); 1911 if ((ph_data->p_req_count == 0) && 1912 (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ACTIVE)) { 1913 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 1914 } 1915 mutex_exit(&ph_data->p_mutex); 1916 1917 /* if sleep specified, wait for completion */ 1918 } else if (wrp_usb_flags & USBA_WRP_FLAGS_WAIT) { 1919 rval = usba_pipe_sync_wait(ph_data, wrp); 1920 } 1921 1922 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1923 "usb_pipe_intr_req: rval=0x%x", rval); 1924 1925 usba_release_ph_data(ph_data->p_ph_impl); 1926 1927 return (rval); 1928 } 1929 1930 1931 /* 1932 * usba_pipe_sync_stop_intr_polling: 1933 * - set up for sync transport, if necessary 1934 * - request HCD to stop polling 1935 * - wait for draining of all callbacks 1936 */ 1937 /*ARGSUSED*/ 1938 static int 1939 usba_pipe_sync_stop_intr_polling(dev_info_t *dip, 1940 usba_ph_impl_t *ph_impl, 1941 usba_pipe_async_req_t *request, 1942 usb_flags_t flags) 1943 { 1944 int rval; 1945 usba_pipe_handle_data_t *ph_data; 1946 usba_device_t *usba_device; 1947 1948 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1949 "usba_pipe_sync_stop_intr_polling: flags=0x%x", flags); 1950 1951 ph_data = usba_get_ph_data((usb_pipe_handle_t)ph_impl); 1952 if (ph_data == NULL) { 1953 usba_release_ph_data(ph_impl); 1954 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1955 "usba_pipe_sync_stop_intr_polling: pipe closed"); 1956 1957 return (USB_INVALID_PIPE); 1958 } 1959 1960 usba_device = ph_data->p_usba_device; 1961 1962 mutex_enter(&ph_data->p_mutex); 1963 1964 if (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ERROR) { 1965 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1966 "usba_pipe_sync_stop_intr_polling: pipe error"); 1967 mutex_exit(&ph_data->p_mutex); 1968 1969 usba_release_ph_data(ph_impl); 1970 1971 return (USB_PIPE_ERROR); 1972 } 1973 1974 if (usba_get_ph_state(ph_data) == USB_PIPE_STATE_IDLE) { 1975 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1976 "usba_pipe_sync_stop_intr_polling: already idle"); 1977 mutex_exit(&ph_data->p_mutex); 1978 1979 usba_release_ph_data(ph_impl); 1980 1981 return (USB_SUCCESS); 1982 } 1983 mutex_exit(&ph_data->p_mutex); 1984 1985 mutex_enter(&ph_impl->usba_ph_mutex); 1986 ph_impl->usba_ph_state_changing++; 1987 mutex_exit(&ph_impl->usba_ph_mutex); 1988 1989 flags |= USB_FLAGS_SLEEP; 1990 1991 for (;;) { 1992 rval = usba_device->usb_hcdi_ops-> 1993 usba_hcdi_pipe_stop_intr_polling(ph_data, flags); 1994 1995 /* 1996 * The host controller has stopped polling of the endpoint. 1997 * Now, drain the callbacks if there are any on the callback 1998 * queue. 1999 */ 2000 if (rval == USB_SUCCESS) { 2001 mutex_enter(&ph_data->p_mutex); 2002 2003 /* 2004 * there is a tiny window that the client driver 2005 * may still have restarted the polling and we 2006 * have to let the stop polling win) 2007 */ 2008 rval = usba_drain_cbs(ph_data, 0, 2009 USB_CR_STOPPED_POLLING); 2010 mutex_exit(&ph_data->p_mutex); 2011 if (rval != USB_SUCCESS) { 2012 2013 continue; 2014 } 2015 } 2016 2017 break; 2018 } 2019 2020 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2021 "usba_pipe_sync_stop_intr_polling: rval=0x%x", rval); 2022 2023 mutex_enter(&ph_impl->usba_ph_mutex); 2024 ph_impl->usba_ph_state_changing--; 2025 mutex_exit(&ph_impl->usba_ph_mutex); 2026 2027 usba_release_ph_data(ph_impl); 2028 2029 return (rval); 2030 } 2031 2032 2033 /* 2034 * dummy callback function for stop polling 2035 */ 2036 static void 2037 usba_dummy_callback( 2038 usb_pipe_handle_t ph, 2039 usb_opaque_t arg, 2040 int rval, 2041 usb_cb_flags_t flags) 2042 { 2043 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2044 "usba_dummy_callback: " 2045 "ph=0x%p rval=0x%x flags=0x%x cb_arg=0x%p", 2046 (void *)ph, rval, flags, (void *)arg); 2047 } 2048 2049 2050 /* 2051 * usb_pipe_stop_intr_polling: 2052 * stop polling for interrupt pipe IN data 2053 * The HCD doesn't do a usba_hcdi_cb(). 2054 * It just returns success/failure 2055 * Arguments: 2056 * pipe_handle - pipe handle 2057 * flags - 2058 * USB_FLAGS_SLEEP: wait for completion 2059 */ 2060 void 2061 usb_pipe_stop_intr_polling(usb_pipe_handle_t pipe_handle, 2062 usb_flags_t flags) 2063 { 2064 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 2065 2066 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2067 "usba_pipe_stop_intr_polling: flags=0x%x", flags); 2068 2069 if (ph_data == NULL) { 2070 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2071 "usba_pipe_stop_intr_polling: pipe closed"); 2072 2073 return; 2074 } 2075 2076 if ((ph_data->p_ep.bmAttributes & 2077 USB_EP_ATTR_MASK) != USB_EP_ATTR_INTR) { 2078 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2079 "usba_pipe_stop_intr_polling: wrong pipe type"); 2080 2081 usba_release_ph_data(ph_data->p_ph_impl); 2082 2083 return; 2084 } 2085 2086 if ((ph_data->p_ep.bEndpointAddress & USB_EP_DIR_IN) == 0) { 2087 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2088 "usba_pipe_stop_intr_polling: wrong pipe direction"); 2089 2090 usba_release_ph_data(ph_data->p_ph_impl); 2091 2092 return; 2093 } 2094 2095 if (servicing_interrupt() && (flags & USB_FLAGS_SLEEP)) { 2096 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2097 "usba_pipe_stop_intr_polling: invalid context"); 2098 2099 usba_release_ph_data(ph_data->p_ph_impl); 2100 2101 return; 2102 } 2103 2104 (void) usba_pipe_setup_func_call(ph_data->p_dip, 2105 usba_pipe_sync_stop_intr_polling, 2106 (usba_ph_impl_t *)pipe_handle, (usb_opaque_t)flags, 2107 flags, usba_dummy_callback, NULL); 2108 } 2109 2110 2111 /* 2112 * usb_alloc_isoc_req: 2113 * - Allocate usb isochronous resources that includes usb isochronous 2114 * request and array of packet descriptor structures and wrapper. 2115 * 2116 * Arguments: 2117 * dip - dev_info_t of the client driver 2118 * isoc_pkts_count - number of isoc_pkt_descr_t's 2119 * len - length of "data" for this isochronous request 2120 * flags - 2121 * USB_FLAGS_SLEEP - Sleep if resources are not available 2122 * no USB_FLAGS_SLEEP - Don't Sleep if resources are not available 2123 * 2124 * Return Values: 2125 * usb_isoc_req_t on success, NULL on failure 2126 */ 2127 /*ARGSUSED*/ 2128 usb_isoc_req_t * 2129 usb_alloc_isoc_req(dev_info_t *dip, 2130 uint_t isoc_pkts_count, 2131 size_t len, 2132 usb_flags_t flags) 2133 { 2134 usb_isoc_req_t *isoc_req = NULL; 2135 usba_req_wrapper_t *wrp; 2136 size_t length = sizeof (*isoc_req) + 2137 (sizeof (usb_isoc_pkt_descr_t) * isoc_pkts_count); 2138 2139 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2140 "usb_alloc_isoc_req: dip=0x%p pkt_cnt=%d len=%lu flags=0x%x", 2141 (void *)dip, isoc_pkts_count, len, flags); 2142 2143 /* client needs to set isoc_pks_count */ 2144 if (dip && isoc_pkts_count) { 2145 /* Allocate + Initialize the usba_req_wrapper_t structure */ 2146 if ((wrp = usba_req_wrapper_alloc(dip, length, flags)) != 2147 NULL) { 2148 isoc_req = (usb_isoc_req_t *)USBA_WRP2ISOC_REQ(wrp); 2149 2150 /* Allocate the usb_isoc_req data mblk */ 2151 if (len) { 2152 if ((isoc_req->isoc_data = 2153 allocb(len, BPRI_HI)) == NULL) { 2154 usba_req_wrapper_free(wrp); 2155 isoc_req = NULL; 2156 } 2157 } 2158 } 2159 } 2160 2161 if (isoc_req) { 2162 isoc_req->isoc_pkt_descr = (usb_isoc_pkt_descr_t *) 2163 (((intptr_t)isoc_req) + (sizeof (usb_isoc_req_t))); 2164 2165 /* Initialize all the fields of usb isochronous request */ 2166 isoc_req->isoc_pkts_count = (ushort_t)isoc_pkts_count; 2167 } 2168 2169 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2170 "usb_alloc_isoc_req: isoc_req = 0x%p", (void *)isoc_req); 2171 2172 return (isoc_req); 2173 } 2174 2175 2176 /* 2177 * usba_hcdi_dup_isoc_req: 2178 * create duplicate of isoc request 2179 * 2180 * Arguments: 2181 * dip - devinfo pointer 2182 * reqp - original request pointer 2183 * len - length of "data" for this isoc request 2184 * flags - 2185 * USB_FLAGS_SLEEP - Sleep if resources are not available 2186 * 2187 * Return Values: 2188 * usb_isoc_req_t on success, NULL on failure 2189 */ 2190 usb_isoc_req_t * 2191 usba_hcdi_dup_isoc_req( 2192 dev_info_t *dip, 2193 usb_isoc_req_t *reqp, 2194 usb_flags_t flags) 2195 { 2196 usb_isoc_req_t *isoc_reqp = NULL; 2197 usba_req_wrapper_t *isoc_wrp, *req_wrp; 2198 ushort_t count; 2199 ushort_t isoc_pkts_count; 2200 size_t length; 2201 2202 if (reqp == NULL) { 2203 2204 return (isoc_reqp); 2205 } 2206 2207 isoc_pkts_count = reqp->isoc_pkts_count; 2208 2209 /* calculate total data length required in original request */ 2210 for (count = length = 0; count < isoc_pkts_count; count++) { 2211 length += reqp->isoc_pkt_descr[count].isoc_pkt_length; 2212 } 2213 2214 req_wrp = USBA_REQ2WRP(reqp); 2215 2216 if (((isoc_reqp = usb_alloc_isoc_req(dip, 2217 isoc_pkts_count, length, flags)) != NULL)) { 2218 isoc_reqp->isoc_frame_no = reqp->isoc_frame_no; 2219 isoc_reqp->isoc_pkts_count = reqp->isoc_pkts_count; 2220 isoc_reqp->isoc_pkts_length = reqp->isoc_pkts_length; 2221 isoc_reqp->isoc_attributes = reqp->isoc_attributes; 2222 isoc_reqp->isoc_client_private = reqp->isoc_client_private; 2223 isoc_reqp->isoc_cb = reqp->isoc_cb; 2224 isoc_reqp->isoc_exc_cb = reqp->isoc_exc_cb; 2225 2226 isoc_wrp = USBA_REQ2WRP(isoc_reqp); 2227 isoc_wrp->wr_dip = req_wrp->wr_dip; 2228 isoc_wrp->wr_ph_data = req_wrp->wr_ph_data; 2229 isoc_wrp->wr_attrs = req_wrp->wr_attrs; 2230 isoc_wrp->wr_usb_flags = req_wrp->wr_usb_flags; 2231 2232 for (count = 0; count < isoc_pkts_count; count++) { 2233 isoc_reqp->isoc_pkt_descr[count].isoc_pkt_length = 2234 reqp->isoc_pkt_descr[count].isoc_pkt_length; 2235 } 2236 } 2237 2238 return (isoc_reqp); 2239 } 2240 2241 2242 /* 2243 * usb_free_isoc_req: 2244 * - Deallocate usb isochronous resources that includes usb isochronous 2245 * request and array of packet descriptor strcutures. 2246 * 2247 * Arguments: 2248 * req - pointer to usb_isoc_req_t 2249 */ 2250 void 2251 usb_free_isoc_req(usb_isoc_req_t *req) 2252 { 2253 if (req) { 2254 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2255 "usb_free_isoc_req: req=0x%p", (void *)req); 2256 2257 if (req->isoc_data) { 2258 freemsg(req->isoc_data); 2259 } 2260 2261 usba_req_wrapper_free(USBA_REQ2WRP(req)); 2262 } 2263 } 2264 2265 2266 /* 2267 * usb_get_current_frame_number: 2268 * - request HCD to return current usb frame number 2269 * 2270 * Arguments: 2271 * dip - pointer to dev_info_t 2272 * 2273 * Return Values: 2274 * current_frame_number - request successfully executed 2275 * 0 - request failed 2276 */ 2277 usb_frame_number_t 2278 usb_get_current_frame_number(dev_info_t *dip) 2279 { 2280 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2281 "usb_get_current_frame_number: dip=0x%p", (void *)dip); 2282 2283 if (dip) { 2284 usba_device_t *usba_device = usba_get_usba_device(dip); 2285 usb_frame_number_t frame_number; 2286 2287 if (usba_device->usb_hcdi_ops-> 2288 usba_hcdi_get_current_frame_number) { 2289 2290 if (usba_device->usb_hcdi_ops-> 2291 usba_hcdi_get_current_frame_number(usba_device, 2292 &frame_number) == USB_SUCCESS) { 2293 2294 return (frame_number); 2295 } 2296 } 2297 } 2298 2299 return (0); 2300 } 2301 2302 2303 /* 2304 * usb_get_max_isoc_pkts: 2305 * - request HCD to return maximum isochronous packets per request 2306 * 2307 * Arguments: 2308 * dip - pointer to dev_info_t 2309 * 2310 * Return Values: 2311 * isoc_pkt - request successfully executed 2312 * 0 - request failed 2313 */ 2314 uint_t 2315 usb_get_max_isoc_pkts(dev_info_t *dip) 2316 { 2317 return (usb_get_max_pkts_per_isoc_request(dip)); 2318 } 2319 2320 2321 uint_t 2322 usb_get_max_pkts_per_isoc_request(dev_info_t *dip) 2323 { 2324 if (dip) { 2325 usba_device_t *usba_device = usba_get_usba_device(dip); 2326 uint_t max_isoc_pkts_per_request; 2327 2328 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2329 "usb_get_max_isoc_pkts: usba_device=0x%p", 2330 (void *)usba_device); 2331 2332 if (usba_device->usb_hcdi_ops->usba_hcdi_get_max_isoc_pkts) { 2333 2334 if (usba_device->usb_hcdi_ops-> 2335 usba_hcdi_get_max_isoc_pkts(usba_device, 2336 &max_isoc_pkts_per_request) == USB_SUCCESS) { 2337 2338 return (max_isoc_pkts_per_request); 2339 } 2340 } 2341 } 2342 2343 return (0); 2344 } 2345 2346 2347 /* 2348 * usb_pipe_isoc_xfer: 2349 * - check for pipe stalled 2350 * - request HCD to transport isoc data asynchronously 2351 * 2352 * Arguments: 2353 * pipe_handle - isoc pipe pipehandle (obtained via usb_pipe_open()) 2354 * req - isochronous request 2355 * 2356 * Return Values: 2357 * USB_SUCCESS - request successfully executed 2358 * USB_FAILURE - request failed 2359 */ 2360 int 2361 usb_pipe_isoc_xfer(usb_pipe_handle_t pipe_handle, 2362 usb_isoc_req_t *req, 2363 usb_flags_t flags) 2364 { 2365 int rval; 2366 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 2367 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 2368 usba_device_t *usba_device; 2369 uchar_t direction; 2370 usb_pipe_state_t pipe_state; 2371 2372 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2373 "usb_pipe_isoc_xfer: flags=0x%x", flags); 2374 2375 if (ph_data == NULL) { 2376 2377 return (USB_INVALID_PIPE); 2378 } 2379 2380 usba_device = ph_data->p_usba_device; 2381 direction = ph_data->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 2382 2383 mutex_enter(&ph_data->p_mutex); 2384 if ((rval = usba_check_req(ph_data, (usb_opaque_t)req, flags, 2385 USB_EP_ATTR_ISOCH)) != USB_SUCCESS) { 2386 mutex_exit(&ph_data->p_mutex); 2387 2388 usba_release_ph_data(ph_data->p_ph_impl); 2389 2390 return (rval); 2391 } 2392 2393 req->isoc_error_count = 0; 2394 2395 /* Get the current isoch pipe state */ 2396 pipe_state = usba_get_ph_state(ph_data); 2397 2398 switch (pipe_state) { 2399 case USB_PIPE_STATE_IDLE: 2400 usba_pipe_new_state(ph_data, USB_PIPE_STATE_ACTIVE); 2401 break; 2402 case USB_PIPE_STATE_ACTIVE: 2403 if (direction == USB_EP_DIR_IN) { 2404 USB_DPRINTF_L4(DPRINT_MASK_USBAI, 2405 usbai_log_handle, 2406 "usb_pipe_isoc_req: already polling"); 2407 2408 mutex_exit(&ph_data->p_mutex); 2409 usba_release_ph_data(ph_data->p_ph_impl); 2410 2411 return (USB_FAILURE); 2412 } 2413 break; 2414 default: 2415 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2416 "usb_pipe_isoc_req: pipe state %d", pipe_state); 2417 2418 mutex_exit(&ph_data->p_mutex); 2419 usba_release_ph_data(ph_data->p_ph_impl); 2420 2421 return (USB_PIPE_ERROR); 2422 } 2423 2424 /* we accept the request */ 2425 ph_data->p_req_count++; 2426 mutex_exit(&ph_data->p_mutex); 2427 2428 if ((rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_isoc_xfer( 2429 ph_data, req, flags)) != USB_SUCCESS) { 2430 if (req->isoc_completion_reason == USB_CR_OK) { 2431 req->isoc_completion_reason = usba_rval2cr(rval); 2432 } 2433 mutex_enter(&ph_data->p_mutex); 2434 ASSERT(wrp->wr_done == B_FALSE); 2435 ph_data->p_req_count--; 2436 if ((ph_data->p_req_count == 0) && 2437 (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ACTIVE)) { 2438 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 2439 } 2440 mutex_exit(&ph_data->p_mutex); 2441 } 2442 2443 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2444 "usb_pipe_isoc_req: rval=%x", rval); 2445 2446 usba_release_ph_data(ph_data->p_ph_impl); 2447 2448 return (rval); 2449 } 2450 2451 2452 /* 2453 * usba_pipe_sync_stop_isoc_polling: 2454 * - set up for sync transport, if necessary 2455 * - request HCD to stop polling 2456 * - wait for draining of all callbacks 2457 * 2458 * Arguments: 2459 * dip - dev_info pointer 2460 * pipe_handle - pointer to pipe handle 2461 * flags - USB_FLAGS_SLEEP: wait for completion 2462 */ 2463 /*ARGSUSED*/ 2464 static int 2465 usba_pipe_sync_stop_isoc_polling(dev_info_t *dip, 2466 usba_ph_impl_t *ph_impl, 2467 usba_pipe_async_req_t *request, 2468 usb_flags_t flags) 2469 { 2470 int rval; 2471 usba_pipe_handle_data_t *ph_data = usba_get_ph_data( 2472 (usb_pipe_handle_t)ph_impl); 2473 usba_device_t *usba_device; 2474 2475 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2476 "usba_pipe_sync_stop_isoc_polling: uf=0x%x", flags); 2477 2478 if (ph_data == NULL) { 2479 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2480 "usba_pipe_stop_isoc_polling: pipe closed"); 2481 2482 return (USB_INVALID_PIPE); 2483 } 2484 2485 usba_device = ph_data->p_usba_device; 2486 2487 mutex_enter(&ph_data->p_mutex); 2488 2489 if (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ERROR) { 2490 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2491 "usba_pipe_sync_stop_isoc_polling: pipe error"); 2492 mutex_exit(&ph_data->p_mutex); 2493 2494 usba_release_ph_data(ph_impl); 2495 2496 return (USB_PIPE_ERROR); 2497 } 2498 2499 if (usba_get_ph_state(ph_data) == USB_PIPE_STATE_IDLE) { 2500 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2501 "usba_pipe_sync_stop_isoc_polling: already stopped"); 2502 mutex_exit(&ph_data->p_mutex); 2503 2504 usba_release_ph_data(ph_impl); 2505 2506 return (USB_SUCCESS); 2507 } 2508 2509 2510 mutex_exit(&ph_data->p_mutex); 2511 2512 flags |= USB_FLAGS_SLEEP; 2513 2514 for (;;) { 2515 rval = usba_device->usb_hcdi_ops-> 2516 usba_hcdi_pipe_stop_isoc_polling(ph_data, flags); 2517 2518 /* 2519 * The host controller has stopped polling of the endpoint. 2520 * Now, drain the callbacks if there are any on the callback 2521 * queue. 2522 */ 2523 if (rval == USB_SUCCESS) { 2524 mutex_enter(&ph_data->p_mutex); 2525 2526 /* 2527 * there is a tiny window that the client driver 2528 * may still have restarted the polling and we 2529 * let the stop polling win 2530 */ 2531 rval = usba_drain_cbs(ph_data, 0, 2532 USB_CR_STOPPED_POLLING); 2533 mutex_exit(&ph_data->p_mutex); 2534 if (rval != USB_SUCCESS) { 2535 2536 continue; 2537 } 2538 } 2539 2540 break; 2541 } 2542 2543 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2544 "usba_pipe_sync_stop_isoc_polling: rval=0x%x", rval); 2545 2546 usba_release_ph_data(ph_impl); 2547 2548 return (rval); 2549 } 2550 2551 2552 /* 2553 * usb_pipe_stop_isoc_polling: 2554 * stop polling for isoc IN data 2555 * 2556 * Arguments: 2557 * pipe_handle - pipe handle 2558 * flags - 2559 * USB_FLAGS_SLEEP: wait for completion 2560 */ 2561 void 2562 usb_pipe_stop_isoc_polling(usb_pipe_handle_t pipe_handle, 2563 usb_flags_t flags) 2564 { 2565 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 2566 2567 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2568 "usba_pipe_stop_isoc_polling: uf=0x%x", flags); 2569 2570 if (ph_data == NULL) { 2571 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2572 "usba_pipe_stop_isoc_polling: pipe closed"); 2573 2574 return; 2575 } 2576 2577 if ((ph_data->p_ep.bmAttributes & USB_EP_ATTR_MASK) != 2578 USB_EP_ATTR_ISOCH) { 2579 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2580 "usba_pipe_stop_isoc_polling: wrong pipe type"); 2581 2582 usba_release_ph_data(ph_data->p_ph_impl); 2583 2584 return; 2585 } 2586 if ((ph_data->p_ep.bEndpointAddress & USB_EP_DIR_IN) == 0) { 2587 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2588 "usba_pipe_stop_isoc_polling: wrong pipe direction"); 2589 2590 usba_release_ph_data(ph_data->p_ph_impl); 2591 2592 return; 2593 } 2594 2595 if (servicing_interrupt() && (flags & USB_FLAGS_SLEEP)) { 2596 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2597 "usba_pipe_stop_intr_polling: invalid context"); 2598 2599 usba_release_ph_data(ph_data->p_ph_impl); 2600 2601 return; 2602 } 2603 2604 (void) usba_pipe_setup_func_call(ph_data->p_dip, 2605 usba_pipe_sync_stop_isoc_polling, 2606 (usba_ph_impl_t *)pipe_handle, (usb_opaque_t)flags, 2607 flags, usba_dummy_callback, NULL); 2608 } 2609