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