1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * USBA: Solaris USB Architecture support 30 * 31 * 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 : 1338 ((data) ? *data : NULL); 1339 ctrl_req->ctrl_timeout = USB_PIPE_TIMEOUT; 1340 ctrl_req->ctrl_attributes = attributes | USB_ATTRS_AUTOCLEARING; 1341 1342 /* Issue control xfer to the HCD */ 1343 rval = usb_pipe_ctrl_xfer(pipe_handle, ctrl_req, 1344 flags | USB_FLAGS_SLEEP); 1345 1346 #ifdef DEBUG 1347 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1348 "req=0x%p, cr=%s cb_flags=%s data=0x%p rval=%s", 1349 ctrl_req, usb_str_cr(ctrl_req->ctrl_completion_reason), 1350 usb_str_cb_flags(ctrl_req->ctrl_cb_flags, buf, BUFSIZE), 1351 ctrl_req->ctrl_data, usb_str_rval(rval)); 1352 #endif 1353 1354 /* copy back ctrl_req values */ 1355 if (data) { 1356 *data = ctrl_req->ctrl_data; 1357 } 1358 if (completion_reason) { 1359 *completion_reason = ctrl_req->ctrl_completion_reason; 1360 } 1361 if (cb_flags) { 1362 *cb_flags = ctrl_req->ctrl_cb_flags; 1363 } 1364 1365 /* Free up the control request now */ 1366 ctrl_req->ctrl_data = NULL; /* leave to client to free */ 1367 usb_free_ctrl_req(ctrl_req); 1368 1369 done: 1370 #ifdef DEBUG 1371 kmem_free(buf, BUFSIZE); 1372 #endif 1373 if (ph_data) { 1374 usba_release_ph_data(ph_data->p_ph_impl); 1375 } 1376 1377 return (rval); 1378 } 1379 1380 1381 /* 1382 * usb_pipe_ctrl_xfer_wait(): 1383 * Easy-to-use wrapper around usb_pipe_sync_ctrl_xfer. 1384 * 1385 * ARGUMENTS: 1386 * pipe_handle - control pipe pipehandle (obtained via usb_pipe_open()) 1387 * setup - setup descriptor params, attributes 1388 * data - pointer to pointer to data and may be NULL when 1389 * wLength is 0 1390 * completion_reason - completion status. 1391 * cb_flags - request completions flags. 1392 * flags - none. 1393 * 1394 * RETURN VALUES: 1395 * USB_SUCCESS - request successfully executed. 1396 * USB_* - failure 1397 */ 1398 int 1399 usb_pipe_ctrl_xfer_wait( 1400 usb_pipe_handle_t pipe_handle, 1401 usb_ctrl_setup_t *setup, 1402 mblk_t **data, 1403 usb_cr_t *completion_reason, 1404 usb_cb_flags_t *cb_flags, 1405 usb_flags_t flags) 1406 { 1407 return (usb_pipe_sync_ctrl_xfer( 1408 usba_get_dip(pipe_handle), 1409 pipe_handle, 1410 setup->bmRequestType, 1411 setup->bRequest, 1412 setup->wValue, 1413 setup->wIndex, 1414 setup->wLength, 1415 data, 1416 setup->attrs, 1417 completion_reason, 1418 cb_flags, 1419 flags)); 1420 } 1421 1422 1423 /* 1424 * usb_alloc_bulk_req: 1425 * Allocate a usb bulk request + usba_req_wrapper_t 1426 * 1427 * Arguments: 1428 * dip - dev_info_t of the client driver 1429 * len - length of "data" for this bulk request 1430 * flags: 1431 * USB_FLAGS_SLEEP - Sleep if resources are not available 1432 * 1433 * Return Values: 1434 * usb_bulk_req_t on success, NULL on failure 1435 */ 1436 usb_bulk_req_t * 1437 usb_alloc_bulk_req(dev_info_t *dip, 1438 size_t len, 1439 usb_flags_t flags) 1440 { 1441 usb_bulk_req_t *bulk_req = NULL; 1442 usba_req_wrapper_t *wrp; 1443 1444 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1445 "usb_alloc_bulk_req: dip=0x%p wlen=0x%lx flags=0x%x", 1446 dip, len, flags); 1447 1448 /* Allocate + Initialize the usba_req_wrapper_t structure */ 1449 if (dip && 1450 ((wrp = usba_req_wrapper_alloc(dip, sizeof (*bulk_req), flags)) != 1451 NULL)) { 1452 bulk_req = USBA_WRP2BULK_REQ(wrp); 1453 1454 /* Allocate the usb_bulk_req data mblk */ 1455 if (len) { 1456 if (flags & USB_FLAGS_SLEEP) { 1457 bulk_req->bulk_data = allocb_wait(len, 1458 BPRI_LO, STR_NOSIG, NULL); 1459 } else if ((bulk_req->bulk_data = 1460 allocb(len, BPRI_HI)) == NULL) { 1461 usba_req_wrapper_free(wrp); 1462 bulk_req = NULL; 1463 } 1464 } 1465 1466 } 1467 1468 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1469 "usb_alloc_bulk_req: bulk_req = 0x%p", bulk_req); 1470 1471 return (bulk_req); 1472 } 1473 1474 1475 /* 1476 * usb_free_bulk_req: 1477 * free USB bulk request + wrapper 1478 * 1479 * Arguments: 1480 * req - pointer to usb_bulk_req_t 1481 */ 1482 void 1483 usb_free_bulk_req(usb_bulk_req_t *req) 1484 { 1485 if (req) { 1486 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1487 "usb_free_bulk_req: req=0x%p", req); 1488 1489 if (req->bulk_data) { 1490 freemsg(req->bulk_data); 1491 } 1492 usba_req_wrapper_free(USBA_REQ2WRP(req)); 1493 } 1494 } 1495 1496 1497 /* 1498 * Client driver calls this function to issue the bulk xfer to the USBA 1499 * 1500 * Arguments:- 1501 * pipe_handle - bulk pipe handle (obtained via usb_pipe_open() 1502 * req - bulk data xfer request (IN or OUT) 1503 * usb_flags - USB_FLAGS_SLEEP - wait for the request to complete 1504 * 1505 * Return Values: 1506 * USB_SUCCESS - success 1507 * USB_FAILURE - unspecified failure 1508 */ 1509 int 1510 usb_pipe_bulk_xfer(usb_pipe_handle_t pipe_handle, 1511 usb_bulk_req_t *req, 1512 usb_flags_t usb_flags) 1513 { 1514 int rval; 1515 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 1516 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1517 usba_device_t *usba_device; 1518 usb_flags_t wrp_usb_flags; 1519 usb_pipe_state_t pipe_state; 1520 1521 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1522 "usb_pipe_bulk_xfer: req=0x%p uf=0x%x", req, usb_flags); 1523 1524 if (ph_data == NULL) { 1525 1526 return (USB_INVALID_PIPE); 1527 } 1528 1529 mutex_enter(&ph_data->p_mutex); 1530 usba_device = ph_data->p_usba_device; 1531 1532 if ((rval = usba_check_req(ph_data, (usb_opaque_t)req, usb_flags, 1533 USB_EP_ATTR_BULK)) != USB_SUCCESS) { 1534 mutex_exit(&ph_data->p_mutex); 1535 1536 usba_release_ph_data(ph_data->p_ph_impl); 1537 1538 return (rval); 1539 } 1540 1541 /* we accepted the request */ 1542 ph_data->p_req_count++; 1543 wrp_usb_flags = wrp->wr_usb_flags; 1544 1545 /* Get the current bulk pipe state */ 1546 pipe_state = usba_get_ph_state(ph_data); 1547 1548 /* 1549 * if there is already an active request in the queue 1550 * then just add this request to the queue. 1551 */ 1552 switch (pipe_state) { 1553 case USB_PIPE_STATE_IDLE: 1554 if (ph_data->p_queue.next) { 1555 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1556 "usb_pipe_bulk_xfer: queue request 0x%p", req); 1557 1558 usba_add_to_list(&ph_data->p_queue, &wrp->wr_queue); 1559 rval = USB_SUCCESS; 1560 mutex_exit(&ph_data->p_mutex); 1561 } else { 1562 usba_pipe_new_state(ph_data, USB_PIPE_STATE_ACTIVE); 1563 mutex_exit(&ph_data->p_mutex); 1564 1565 /* issue the request to HCD */ 1566 rval = usba_device->usb_hcdi_ops-> 1567 usba_hcdi_pipe_bulk_xfer(ph_data, req, usb_flags); 1568 } 1569 break; 1570 case USB_PIPE_STATE_ACTIVE: 1571 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1572 "usb_pipe_bulk_xfer: queue request 0x%p", req); 1573 1574 usba_add_to_list(&ph_data->p_queue, &wrp->wr_queue); 1575 rval = USB_SUCCESS; 1576 mutex_exit(&ph_data->p_mutex); 1577 break; 1578 default: 1579 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1580 "usb_pipe_bulk_xfer: pipe state %d", pipe_state); 1581 1582 rval = USB_PIPE_ERROR; 1583 mutex_exit(&ph_data->p_mutex); 1584 break; 1585 } 1586 1587 if (rval != USB_SUCCESS) { 1588 if (req->bulk_completion_reason == USB_CR_OK) { 1589 req->bulk_completion_reason = usba_rval2cr(rval); 1590 } 1591 mutex_enter(&ph_data->p_mutex); 1592 ASSERT(wrp->wr_done == B_FALSE); 1593 ph_data->p_req_count--; 1594 ASSERT(ph_data->p_req_count >= 0); 1595 if ((ph_data->p_req_count == 0) && 1596 (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ACTIVE)) { 1597 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 1598 } 1599 mutex_exit(&ph_data->p_mutex); 1600 } else if (wrp_usb_flags & USBA_WRP_FLAGS_WAIT) { 1601 rval = usba_pipe_sync_wait(ph_data, wrp); 1602 } 1603 1604 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1605 "usb_pipe_bulk_xfer: rval=%d", rval); 1606 1607 usba_release_ph_data(ph_data->p_ph_impl); 1608 1609 return (rval); 1610 } 1611 1612 1613 /* 1614 * usb_pipe_bulk_transfer_size: 1615 * - request HCD to return bulk max transfer data size 1616 * 1617 * Arguments: 1618 * dip - pointer to dev_info_t 1619 * size - pointer to bulk_transfer_size 1620 * 1621 * Return Values: 1622 * USB_SUCCESS - request successfully executed 1623 * USB_FAILURE - request failed 1624 */ 1625 int 1626 usb_pipe_bulk_transfer_size(dev_info_t *dip, 1627 size_t *size) 1628 { 1629 return (usb_pipe_get_max_bulk_transfer_size(dip, size)); 1630 } 1631 1632 1633 int 1634 usb_pipe_get_max_bulk_transfer_size(dev_info_t *dip, 1635 size_t *size) 1636 { 1637 usba_device_t *usba_device; 1638 1639 if ((dip == NULL) || (size == NULL)) { 1640 1641 return (USB_INVALID_ARGS); 1642 } 1643 usba_device = usba_get_usba_device(dip); 1644 1645 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1646 "usb_pipe_bulk_transfer_size: usba_device=0x%p", usba_device); 1647 1648 if ((usba_device) && 1649 (usba_device->usb_hcdi_ops->usba_hcdi_bulk_transfer_size)) { 1650 1651 return (usba_device->usb_hcdi_ops-> 1652 usba_hcdi_bulk_transfer_size(usba_device, size)); 1653 } else { 1654 *size = 0; 1655 1656 return (USB_FAILURE); 1657 } 1658 } 1659 1660 1661 /* 1662 * usb_alloc_intr_req: 1663 * Allocate usb interrupt request 1664 * 1665 * Arguments: 1666 * dip - dev_info_t of the client driver 1667 * len - length of "data" for this interrupt request 1668 * flags - 1669 * USB_FLAGS_SLEEP - Sleep if resources are not available 1670 * 1671 * Return Values: 1672 * usb_intr_req_t on success, NULL on failure 1673 */ 1674 usb_intr_req_t * 1675 usb_alloc_intr_req(dev_info_t *dip, 1676 size_t len, 1677 usb_flags_t flags) 1678 { 1679 usb_intr_req_t *intr_req = NULL; 1680 usba_req_wrapper_t *wrp; 1681 1682 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1683 "usb_alloc_intr_req: dip=0x%p, len=0x%lx, flags=0x%x", 1684 dip, len, flags); 1685 1686 /* Allocate + Initialize the usba_req_wrapper_t structure */ 1687 if ((dip && 1688 (wrp = usba_req_wrapper_alloc(dip, sizeof (*intr_req), flags)) != 1689 NULL)) { 1690 intr_req = (usb_intr_req_t *)USBA_WRP2INTR_REQ(wrp); 1691 1692 /* Allocate the usb_intr_req data mblk */ 1693 if (len) { 1694 if (flags & USB_FLAGS_SLEEP) { 1695 intr_req->intr_data = allocb_wait(len, BPRI_LO, 1696 STR_NOSIG, NULL); 1697 } else if ((intr_req->intr_data = 1698 allocb(len, BPRI_HI)) == NULL) { 1699 usba_req_wrapper_free(wrp); 1700 intr_req = NULL; 1701 } 1702 } 1703 } 1704 1705 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1706 "usb_alloc_intr_req: intr_req=0x%p", intr_req); 1707 1708 return (intr_req); 1709 } 1710 1711 1712 /* 1713 * usba_hcdi_dup_intr_req: 1714 * create duplicate of interrupt request 1715 * 1716 * Arguments: 1717 * dip - devinfo pointer 1718 * reqp - original requestp pointer 1719 * len - length of "data" for this interrupt request 1720 * flags - 1721 * USB_FLAGS_SLEEP - Sleep if resources are not available 1722 * 1723 * Return Values: 1724 * usb_intr_req_t on success, NULL on failure 1725 */ 1726 usb_intr_req_t * 1727 usba_hcdi_dup_intr_req( 1728 dev_info_t *dip, 1729 usb_intr_req_t *reqp, 1730 size_t len, 1731 usb_flags_t flags) 1732 { 1733 usb_intr_req_t *intr_reqp = NULL; 1734 usba_req_wrapper_t *intr_wrp, *req_wrp; 1735 1736 if (reqp == NULL) { 1737 1738 return (NULL); 1739 } 1740 1741 req_wrp = USBA_REQ2WRP(reqp); 1742 1743 if (((intr_reqp = usb_alloc_intr_req(dip, len, flags)) != NULL)) { 1744 intr_reqp->intr_client_private = reqp->intr_client_private; 1745 intr_reqp->intr_timeout = reqp->intr_timeout; 1746 intr_reqp->intr_attributes = reqp->intr_attributes; 1747 intr_reqp->intr_len = reqp->intr_len; 1748 intr_reqp->intr_cb = reqp->intr_cb; 1749 intr_reqp->intr_exc_cb = reqp->intr_exc_cb; 1750 1751 intr_wrp = USBA_REQ2WRP(intr_reqp); 1752 intr_wrp->wr_dip = req_wrp->wr_dip; 1753 intr_wrp->wr_ph_data = req_wrp->wr_ph_data; 1754 intr_wrp->wr_attrs = req_wrp->wr_attrs; 1755 intr_wrp->wr_usb_flags = req_wrp->wr_usb_flags; 1756 } 1757 1758 return (intr_reqp); 1759 } 1760 1761 1762 /* 1763 * usb_free_intr_req: 1764 * free USB intr request + wrapper 1765 * 1766 * Arguments: 1767 * req - pointer to usb_intr_req_t 1768 */ 1769 void 1770 usb_free_intr_req(usb_intr_req_t *req) 1771 { 1772 if (req) { 1773 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1774 "usb_free_intr_req: req = 0x%p", req); 1775 1776 if (req->intr_data) { 1777 freemsg(req->intr_data); 1778 } 1779 1780 usba_req_wrapper_free(USBA_REQ2WRP(req)); 1781 } 1782 } 1783 1784 1785 /* 1786 * Client driver calls this function to issue the intr xfer to the USBA 1787 * 1788 * Arguments:- 1789 * pipe_handle - intr pipe handle (obtained via usb_pipe_open() 1790 * req - intr data xfer request (IN or OUT) 1791 * flags - 1792 * USB_FLAGS_SLEEP - wait for the request to complete 1793 * Return Values 1794 * USB_SUCCESS - success 1795 * USB_FAILURE - unspecified failure 1796 */ 1797 int 1798 usb_pipe_intr_xfer(usb_pipe_handle_t pipe_handle, 1799 usb_intr_req_t *req, 1800 usb_flags_t usb_flags) 1801 { 1802 int rval; 1803 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 1804 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle; 1805 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1806 usba_device_t *usba_device; 1807 uchar_t direction; 1808 usb_flags_t wrp_usb_flags; 1809 usb_pipe_state_t pipe_state; 1810 1811 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1812 "usb_pipe_intr_req: req=0x%p uf=0x%x", 1813 req, usb_flags); 1814 1815 if (ph_data == NULL) { 1816 1817 return (USB_INVALID_PIPE); 1818 } 1819 usba_device = ph_data->p_usba_device; 1820 direction = ph_data->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1821 1822 mutex_enter(&ph_data->p_mutex); 1823 if ((rval = usba_check_req(ph_data, (usb_opaque_t)req, usb_flags, 1824 USB_EP_ATTR_INTR)) != USB_SUCCESS) { 1825 mutex_exit(&ph_data->p_mutex); 1826 1827 usba_release_ph_data(ph_data->p_ph_impl); 1828 1829 return (rval); 1830 } 1831 1832 /* Get the current interrupt pipe state */ 1833 pipe_state = usba_get_ph_state(ph_data); 1834 1835 switch (pipe_state) { 1836 case USB_PIPE_STATE_IDLE: 1837 /* 1838 * if the pipe state is in middle of transition, 1839 * i.e. stop polling is in progress, fail any 1840 * attempt to do a start polling 1841 */ 1842 mutex_enter(&ph_impl->usba_ph_mutex); 1843 if (ph_impl->usba_ph_state_changing > 0) { 1844 mutex_exit(&ph_impl->usba_ph_mutex); 1845 1846 mutex_exit(&ph_data->p_mutex); 1847 usba_release_ph_data(ph_data->p_ph_impl); 1848 1849 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1850 "usb_pipe_intr_req: fail request - " 1851 "stop polling in progress"); 1852 1853 return (USB_FAILURE); 1854 } else { 1855 mutex_exit(&ph_impl->usba_ph_mutex); 1856 usba_pipe_new_state(ph_data, USB_PIPE_STATE_ACTIVE); 1857 } 1858 1859 break; 1860 case USB_PIPE_STATE_ACTIVE: 1861 /* 1862 * If this is interrupt IN pipe and if we are 1863 * already polling, return failure. 1864 */ 1865 if (direction == USB_EP_DIR_IN) { 1866 USB_DPRINTF_L4(DPRINT_MASK_USBAI, 1867 usbai_log_handle, 1868 "usb_pipe_intr_req: already polling"); 1869 1870 mutex_exit(&ph_data->p_mutex); 1871 usba_release_ph_data(ph_data->p_ph_impl); 1872 1873 return (USB_FAILURE); 1874 } 1875 1876 break; 1877 default: 1878 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1879 "usb_pipe_intr_req: pipe state %d", pipe_state); 1880 1881 mutex_exit(&ph_data->p_mutex); 1882 usba_release_ph_data(ph_data->p_ph_impl); 1883 1884 return (USB_PIPE_ERROR); 1885 } 1886 1887 /* we accept the request */ 1888 wrp_usb_flags = wrp->wr_usb_flags; 1889 ph_data->p_req_count++; 1890 1891 mutex_exit(&ph_data->p_mutex); 1892 1893 /* issue the request out */ 1894 if ((rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_intr_xfer(ph_data, 1895 req, usb_flags)) != USB_SUCCESS) { 1896 1897 /* the request failed, decrement the ref_count */ 1898 if (req->intr_completion_reason == USB_CR_OK) { 1899 req->intr_completion_reason = usba_rval2cr(rval); 1900 } 1901 mutex_enter(&ph_data->p_mutex); 1902 ASSERT(wrp->wr_done == B_FALSE); 1903 ph_data->p_req_count--; 1904 ASSERT(ph_data->p_req_count >= 0); 1905 if ((ph_data->p_req_count == 0) && 1906 (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ACTIVE)) { 1907 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 1908 } 1909 mutex_exit(&ph_data->p_mutex); 1910 1911 /* if sleep specified, wait for completion */ 1912 } else if (wrp_usb_flags & USBA_WRP_FLAGS_WAIT) { 1913 rval = usba_pipe_sync_wait(ph_data, wrp); 1914 } 1915 1916 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1917 "usb_pipe_intr_req: rval=0x%x", rval); 1918 1919 usba_release_ph_data(ph_data->p_ph_impl); 1920 1921 return (rval); 1922 } 1923 1924 1925 /* 1926 * usba_pipe_sync_stop_intr_polling: 1927 * - set up for sync transport, if necessary 1928 * - request HCD to stop polling 1929 * - wait for draining of all callbacks 1930 */ 1931 /*ARGSUSED*/ 1932 static int 1933 usba_pipe_sync_stop_intr_polling(dev_info_t *dip, 1934 usba_ph_impl_t *ph_impl, 1935 usba_pipe_async_req_t *request, 1936 usb_flags_t flags) 1937 { 1938 int rval; 1939 usba_pipe_handle_data_t *ph_data; 1940 usba_device_t *usba_device; 1941 1942 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1943 "usba_pipe_sync_stop_intr_polling: flags=0x%x", flags); 1944 1945 ph_data = usba_get_ph_data((usb_pipe_handle_t)ph_impl); 1946 if (ph_data == NULL) { 1947 usba_release_ph_data(ph_impl); 1948 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1949 "usba_pipe_sync_stop_intr_polling: pipe closed"); 1950 1951 return (USB_INVALID_PIPE); 1952 } 1953 1954 usba_device = ph_data->p_usba_device; 1955 1956 mutex_enter(&ph_data->p_mutex); 1957 1958 if (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ERROR) { 1959 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1960 "usba_pipe_sync_stop_intr_polling: pipe error"); 1961 mutex_exit(&ph_data->p_mutex); 1962 1963 usba_release_ph_data(ph_impl); 1964 1965 return (USB_PIPE_ERROR); 1966 } 1967 1968 if (usba_get_ph_state(ph_data) == USB_PIPE_STATE_IDLE) { 1969 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1970 "usba_pipe_sync_stop_intr_polling: already idle"); 1971 mutex_exit(&ph_data->p_mutex); 1972 1973 usba_release_ph_data(ph_impl); 1974 1975 return (USB_SUCCESS); 1976 } 1977 mutex_exit(&ph_data->p_mutex); 1978 1979 mutex_enter(&ph_impl->usba_ph_mutex); 1980 ph_impl->usba_ph_state_changing++; 1981 mutex_exit(&ph_impl->usba_ph_mutex); 1982 1983 flags |= USB_FLAGS_SLEEP; 1984 1985 for (;;) { 1986 rval = usba_device->usb_hcdi_ops-> 1987 usba_hcdi_pipe_stop_intr_polling(ph_data, flags); 1988 1989 /* 1990 * The host controller has stopped polling of the endpoint. 1991 * Now, drain the callbacks if there are any on the callback 1992 * queue. 1993 */ 1994 if (rval == USB_SUCCESS) { 1995 mutex_enter(&ph_data->p_mutex); 1996 1997 /* 1998 * there is a tiny window that the client driver 1999 * may still have restarted the polling and we 2000 * have to let the stop polling win) 2001 */ 2002 rval = usba_drain_cbs(ph_data, 0, 2003 USB_CR_STOPPED_POLLING); 2004 mutex_exit(&ph_data->p_mutex); 2005 if (rval != USB_SUCCESS) { 2006 2007 continue; 2008 } 2009 } 2010 2011 break; 2012 } 2013 2014 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2015 "usba_pipe_sync_stop_intr_polling: rval=0x%x", rval); 2016 2017 mutex_enter(&ph_impl->usba_ph_mutex); 2018 ph_impl->usba_ph_state_changing--; 2019 mutex_exit(&ph_impl->usba_ph_mutex); 2020 2021 usba_release_ph_data(ph_impl); 2022 2023 return (rval); 2024 } 2025 2026 2027 /* 2028 * dummy callback function for stop polling 2029 */ 2030 static void 2031 usba_dummy_callback( 2032 usb_pipe_handle_t ph, 2033 usb_opaque_t arg, 2034 int rval, 2035 usb_cb_flags_t flags) 2036 { 2037 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2038 "usba_dummy_callback: " 2039 "ph=0x%p rval=0x%x flags=0x%x cb_arg=0x%p", 2040 ph, rval, flags, arg); 2041 } 2042 2043 2044 /* 2045 * usb_pipe_stop_intr_polling: 2046 * stop polling for interrupt pipe IN data 2047 * The HCD doesn't do a usba_hcdi_cb(). 2048 * It just returns success/failure 2049 * Arguments: 2050 * pipe_handle - pipe handle 2051 * flags - 2052 * USB_FLAGS_SLEEP: wait for completion 2053 */ 2054 void 2055 usb_pipe_stop_intr_polling(usb_pipe_handle_t pipe_handle, 2056 usb_flags_t flags) 2057 { 2058 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 2059 2060 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2061 "usba_pipe_stop_intr_polling: flags=0x%x", flags); 2062 2063 if (ph_data == NULL) { 2064 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2065 "usba_pipe_stop_intr_polling: pipe closed"); 2066 2067 return; 2068 } 2069 2070 if ((ph_data->p_ep.bmAttributes & 2071 USB_EP_ATTR_MASK) != USB_EP_ATTR_INTR) { 2072 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2073 "usba_pipe_stop_intr_polling: wrong pipe type"); 2074 2075 usba_release_ph_data(ph_data->p_ph_impl); 2076 2077 return; 2078 } 2079 2080 if ((ph_data->p_ep.bEndpointAddress & USB_EP_DIR_IN) == 0) { 2081 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2082 "usba_pipe_stop_intr_polling: wrong pipe direction"); 2083 2084 usba_release_ph_data(ph_data->p_ph_impl); 2085 2086 return; 2087 } 2088 2089 if (servicing_interrupt() && (flags & USB_FLAGS_SLEEP)) { 2090 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2091 "usba_pipe_stop_intr_polling: invalid context"); 2092 2093 usba_release_ph_data(ph_data->p_ph_impl); 2094 2095 return; 2096 } 2097 2098 (void) usba_pipe_setup_func_call(ph_data->p_dip, 2099 usba_pipe_sync_stop_intr_polling, 2100 (usba_ph_impl_t *)pipe_handle, (usb_opaque_t)flags, 2101 flags, usba_dummy_callback, NULL); 2102 } 2103 2104 2105 /* 2106 * usb_alloc_isoc_req: 2107 * - Allocate usb isochronous resources that includes usb isochronous 2108 * request and array of packet descriptor structures and wrapper. 2109 * 2110 * Arguments: 2111 * dip - dev_info_t of the client driver 2112 * isoc_pkts_count - number of isoc_pkt_descr_t's 2113 * len - length of "data" for this isochronous request 2114 * flags - 2115 * USB_FLAGS_SLEEP - Sleep if resources are not available 2116 * no USB_FLAGS_SLEEP - Don't Sleep if resources are not available 2117 * 2118 * Return Values: 2119 * usb_isoc_req_t on success, NULL on failure 2120 */ 2121 /*ARGSUSED*/ 2122 usb_isoc_req_t * 2123 usb_alloc_isoc_req(dev_info_t *dip, 2124 uint_t isoc_pkts_count, 2125 size_t len, 2126 usb_flags_t flags) 2127 { 2128 usb_isoc_req_t *isoc_req = NULL; 2129 usba_req_wrapper_t *wrp; 2130 size_t length = sizeof (*isoc_req) + 2131 (sizeof (usb_isoc_pkt_descr_t) * isoc_pkts_count); 2132 2133 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2134 "usb_alloc_isoc_req: dip=0x%p pkt_cnt=%d len=%lu flags=0x%x", 2135 dip, isoc_pkts_count, len, flags); 2136 2137 /* client needs to set isoc_pks_count */ 2138 if (dip && isoc_pkts_count) { 2139 /* Allocate + Initialize the usba_req_wrapper_t structure */ 2140 if ((wrp = usba_req_wrapper_alloc(dip, length, flags)) != 2141 NULL) { 2142 isoc_req = (usb_isoc_req_t *)USBA_WRP2ISOC_REQ(wrp); 2143 2144 /* Allocate the usb_isoc_req data mblk */ 2145 if (len) { 2146 if ((isoc_req->isoc_data = 2147 allocb(len, BPRI_HI)) == NULL) { 2148 usba_req_wrapper_free(wrp); 2149 isoc_req = NULL; 2150 } 2151 } 2152 } 2153 } 2154 2155 if (isoc_req) { 2156 isoc_req->isoc_pkt_descr = (usb_isoc_pkt_descr_t *) 2157 (((intptr_t)isoc_req) + (sizeof (usb_isoc_req_t))); 2158 2159 /* Initialize all the fields of usb isochronous request */ 2160 isoc_req->isoc_pkts_count = isoc_pkts_count; 2161 } 2162 2163 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2164 "usb_alloc_isoc_req: isoc_req = 0x%p", isoc_req); 2165 2166 return (isoc_req); 2167 } 2168 2169 2170 /* 2171 * usba_hcdi_dup_isoc_req: 2172 * create duplicate of isoc request 2173 * 2174 * Arguments: 2175 * dip - devinfo pointer 2176 * reqp - original request pointer 2177 * len - length of "data" for this isoc request 2178 * flags - 2179 * USB_FLAGS_SLEEP - Sleep if resources are not available 2180 * 2181 * Return Values: 2182 * usb_isoc_req_t on success, NULL on failure 2183 */ 2184 usb_isoc_req_t * 2185 usba_hcdi_dup_isoc_req( 2186 dev_info_t *dip, 2187 usb_isoc_req_t *reqp, 2188 usb_flags_t flags) 2189 { 2190 usb_isoc_req_t *isoc_reqp = NULL; 2191 usba_req_wrapper_t *isoc_wrp, *req_wrp; 2192 ushort_t count; 2193 ushort_t isoc_pkts_count; 2194 size_t length; 2195 2196 if (reqp == NULL) { 2197 2198 return (isoc_reqp); 2199 } 2200 2201 isoc_pkts_count = reqp->isoc_pkts_count; 2202 2203 /* calculate total data length required in original request */ 2204 for (count = length = 0; count < isoc_pkts_count; count++) { 2205 length += reqp->isoc_pkt_descr[count].isoc_pkt_length; 2206 } 2207 2208 req_wrp = USBA_REQ2WRP(reqp); 2209 2210 if (((isoc_reqp = usb_alloc_isoc_req(dip, 2211 isoc_pkts_count, length, flags)) != NULL)) { 2212 isoc_reqp->isoc_frame_no = reqp->isoc_frame_no; 2213 isoc_reqp->isoc_pkts_count = reqp->isoc_pkts_count; 2214 isoc_reqp->isoc_pkts_length = reqp->isoc_pkts_length; 2215 isoc_reqp->isoc_attributes = reqp->isoc_attributes; 2216 isoc_reqp->isoc_client_private = reqp->isoc_client_private; 2217 isoc_reqp->isoc_cb = reqp->isoc_cb; 2218 isoc_reqp->isoc_exc_cb = reqp->isoc_exc_cb; 2219 2220 isoc_wrp = USBA_REQ2WRP(isoc_reqp); 2221 isoc_wrp->wr_dip = req_wrp->wr_dip; 2222 isoc_wrp->wr_ph_data = req_wrp->wr_ph_data; 2223 isoc_wrp->wr_attrs = req_wrp->wr_attrs; 2224 isoc_wrp->wr_usb_flags = req_wrp->wr_usb_flags; 2225 2226 for (count = 0; count < isoc_pkts_count; count++) { 2227 isoc_reqp->isoc_pkt_descr[count].isoc_pkt_length = 2228 reqp->isoc_pkt_descr[count].isoc_pkt_length; 2229 } 2230 } 2231 2232 return (isoc_reqp); 2233 } 2234 2235 2236 /* 2237 * usb_free_isoc_req: 2238 * - Deallocate usb isochronous resources that includes usb isochronous 2239 * request and array of packet descriptor strcutures. 2240 * 2241 * Arguments: 2242 * req - pointer to usb_isoc_req_t 2243 */ 2244 void 2245 usb_free_isoc_req(usb_isoc_req_t *req) 2246 { 2247 if (req) { 2248 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2249 "usb_free_isoc_req: req=0x%p", req); 2250 2251 if (req->isoc_data) { 2252 freemsg(req->isoc_data); 2253 } 2254 2255 usba_req_wrapper_free(USBA_REQ2WRP(req)); 2256 } 2257 } 2258 2259 2260 /* 2261 * usb_get_current_frame_number: 2262 * - request HCD to return current usb frame number 2263 * 2264 * Arguments: 2265 * dip - pointer to dev_info_t 2266 * 2267 * Return Values: 2268 * current_frame_number - request successfully executed 2269 * 0 - request failed 2270 */ 2271 usb_frame_number_t 2272 usb_get_current_frame_number(dev_info_t *dip) 2273 { 2274 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2275 "usb_get_current_frame_number: dip=0x%p", dip); 2276 2277 if (dip) { 2278 usba_device_t *usba_device = usba_get_usba_device(dip); 2279 2280 if (usba_device->usb_hcdi_ops-> 2281 usba_hcdi_get_current_frame_number) { 2282 2283 return (usba_device->usb_hcdi_ops-> 2284 usba_hcdi_get_current_frame_number(usba_device)); 2285 } 2286 } 2287 2288 return (0); 2289 } 2290 2291 2292 /* 2293 * usb_get_max_isoc_pkts: 2294 * - request HCD to return maximum isochronous packets per request 2295 * 2296 * Arguments: 2297 * dip - pointer to dev_info_t 2298 * 2299 * Return Values: 2300 * isoc_pkt - request successfully executed 2301 * 0 - request failed 2302 */ 2303 uint_t 2304 usb_get_max_isoc_pkts(dev_info_t *dip) 2305 { 2306 return (usb_get_max_pkts_per_isoc_request(dip)); 2307 } 2308 2309 2310 uint_t 2311 usb_get_max_pkts_per_isoc_request(dev_info_t *dip) 2312 { 2313 if (dip) { 2314 usba_device_t *usba_device = usba_get_usba_device(dip); 2315 2316 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2317 "usb_get_max_isoc_pkts: usba_device=0x%p", usba_device); 2318 2319 if (usba_device->usb_hcdi_ops->usba_hcdi_get_max_isoc_pkts) { 2320 2321 return (usba_device->usb_hcdi_ops-> 2322 usba_hcdi_get_max_isoc_pkts(usba_device)); 2323 } 2324 } 2325 2326 return (0); 2327 } 2328 2329 2330 /* 2331 * usb_pipe_isoc_xfer: 2332 * - check for pipe stalled 2333 * - request HCD to transport isoc data asynchronously 2334 * 2335 * Arguments: 2336 * pipe_handle - isoc pipe pipehandle (obtained via usb_pipe_open()) 2337 * req - isochronous request 2338 * 2339 * Return Values: 2340 * USB_SUCCESS - request successfully executed 2341 * USB_FAILURE - request failed 2342 */ 2343 int 2344 usb_pipe_isoc_xfer(usb_pipe_handle_t pipe_handle, 2345 usb_isoc_req_t *req, 2346 usb_flags_t flags) 2347 { 2348 int rval; 2349 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 2350 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 2351 usba_device_t *usba_device; 2352 uchar_t direction; 2353 usb_pipe_state_t pipe_state; 2354 2355 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2356 "usb_pipe_isoc_xfer: flags=0x%x", flags); 2357 2358 if (ph_data == NULL) { 2359 2360 return (USB_INVALID_PIPE); 2361 } 2362 2363 usba_device = ph_data->p_usba_device; 2364 direction = ph_data->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 2365 2366 mutex_enter(&ph_data->p_mutex); 2367 if ((rval = usba_check_req(ph_data, (usb_opaque_t)req, flags, 2368 USB_EP_ATTR_ISOCH)) != USB_SUCCESS) { 2369 mutex_exit(&ph_data->p_mutex); 2370 2371 usba_release_ph_data(ph_data->p_ph_impl); 2372 2373 return (rval); 2374 } 2375 2376 req->isoc_error_count = 0; 2377 2378 /* Get the current isoch pipe state */ 2379 pipe_state = usba_get_ph_state(ph_data); 2380 2381 switch (pipe_state) { 2382 case USB_PIPE_STATE_IDLE: 2383 usba_pipe_new_state(ph_data, USB_PIPE_STATE_ACTIVE); 2384 break; 2385 case USB_PIPE_STATE_ACTIVE: 2386 if (direction == USB_EP_DIR_IN) { 2387 USB_DPRINTF_L4(DPRINT_MASK_USBAI, 2388 usbai_log_handle, 2389 "usb_pipe_isoc_req: already polling"); 2390 2391 mutex_exit(&ph_data->p_mutex); 2392 usba_release_ph_data(ph_data->p_ph_impl); 2393 2394 return (USB_FAILURE); 2395 } 2396 break; 2397 default: 2398 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2399 "usb_pipe_isoc_req: pipe state %d", pipe_state); 2400 2401 mutex_exit(&ph_data->p_mutex); 2402 usba_release_ph_data(ph_data->p_ph_impl); 2403 2404 return (USB_PIPE_ERROR); 2405 } 2406 2407 /* we accept the request */ 2408 ph_data->p_req_count++; 2409 mutex_exit(&ph_data->p_mutex); 2410 2411 if ((rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_isoc_xfer( 2412 ph_data, req, flags)) != USB_SUCCESS) { 2413 if (req->isoc_completion_reason == USB_CR_OK) { 2414 req->isoc_completion_reason = usba_rval2cr(rval); 2415 } 2416 mutex_enter(&ph_data->p_mutex); 2417 ASSERT(wrp->wr_done == B_FALSE); 2418 ph_data->p_req_count--; 2419 if ((ph_data->p_req_count == 0) && 2420 (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ACTIVE)) { 2421 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 2422 } 2423 mutex_exit(&ph_data->p_mutex); 2424 } 2425 2426 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2427 "usb_pipe_isoc_req: rval=%x", rval); 2428 2429 usba_release_ph_data(ph_data->p_ph_impl); 2430 2431 return (rval); 2432 } 2433 2434 2435 /* 2436 * usba_pipe_sync_stop_isoc_polling: 2437 * - set up for sync transport, if necessary 2438 * - request HCD to stop polling 2439 * - wait for draining of all callbacks 2440 * 2441 * Arguments: 2442 * dip - dev_info pointer 2443 * pipe_handle - pointer to pipe handle 2444 * flags - USB_FLAGS_SLEEP: wait for completion 2445 */ 2446 /*ARGSUSED*/ 2447 static int 2448 usba_pipe_sync_stop_isoc_polling(dev_info_t *dip, 2449 usba_ph_impl_t *ph_impl, 2450 usba_pipe_async_req_t *request, 2451 usb_flags_t flags) 2452 { 2453 int rval; 2454 usba_pipe_handle_data_t *ph_data = usba_get_ph_data( 2455 (usb_pipe_handle_t)ph_impl); 2456 usba_device_t *usba_device; 2457 2458 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2459 "usba_pipe_sync_stop_isoc_polling: uf=0x%x", flags); 2460 2461 if (ph_data == NULL) { 2462 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2463 "usba_pipe_stop_isoc_polling: pipe closed"); 2464 2465 return (USB_INVALID_PIPE); 2466 } 2467 2468 usba_device = ph_data->p_usba_device; 2469 2470 mutex_enter(&ph_data->p_mutex); 2471 2472 if (usba_get_ph_state(ph_data) == USB_PIPE_STATE_ERROR) { 2473 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2474 "usba_pipe_sync_stop_isoc_polling: pipe error"); 2475 mutex_exit(&ph_data->p_mutex); 2476 2477 usba_release_ph_data(ph_impl); 2478 2479 return (USB_PIPE_ERROR); 2480 } 2481 2482 if (usba_get_ph_state(ph_data) == USB_PIPE_STATE_IDLE) { 2483 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2484 "usba_pipe_sync_stop_isoc_polling: already stopped"); 2485 mutex_exit(&ph_data->p_mutex); 2486 2487 usba_release_ph_data(ph_impl); 2488 2489 return (USB_SUCCESS); 2490 } 2491 2492 2493 mutex_exit(&ph_data->p_mutex); 2494 2495 flags |= USB_FLAGS_SLEEP; 2496 2497 for (;;) { 2498 rval = usba_device->usb_hcdi_ops-> 2499 usba_hcdi_pipe_stop_isoc_polling(ph_data, flags); 2500 2501 /* 2502 * The host controller has stopped polling of the endpoint. 2503 * Now, drain the callbacks if there are any on the callback 2504 * queue. 2505 */ 2506 if (rval == USB_SUCCESS) { 2507 mutex_enter(&ph_data->p_mutex); 2508 2509 /* 2510 * there is a tiny window that the client driver 2511 * may still have restarted the polling and we 2512 * let the stop polling win 2513 */ 2514 rval = usba_drain_cbs(ph_data, 0, 2515 USB_CR_STOPPED_POLLING); 2516 mutex_exit(&ph_data->p_mutex); 2517 if (rval != USB_SUCCESS) { 2518 2519 continue; 2520 } 2521 } 2522 2523 break; 2524 } 2525 2526 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2527 "usba_pipe_sync_stop_isoc_polling: rval=0x%x", rval); 2528 2529 usba_release_ph_data(ph_impl); 2530 2531 return (rval); 2532 } 2533 2534 2535 /* 2536 * usb_pipe_stop_isoc_polling: 2537 * stop polling for isoc IN data 2538 * 2539 * Arguments: 2540 * pipe_handle - pipe handle 2541 * flags - 2542 * USB_FLAGS_SLEEP: wait for completion 2543 */ 2544 void 2545 usb_pipe_stop_isoc_polling(usb_pipe_handle_t pipe_handle, 2546 usb_flags_t flags) 2547 { 2548 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 2549 2550 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 2551 "usba_pipe_stop_isoc_polling: uf=0x%x", flags); 2552 2553 if (ph_data == NULL) { 2554 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2555 "usba_pipe_stop_isoc_polling: pipe closed"); 2556 2557 return; 2558 } 2559 2560 if ((ph_data->p_ep.bmAttributes & USB_EP_ATTR_MASK) != 2561 USB_EP_ATTR_ISOCH) { 2562 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2563 "usba_pipe_stop_isoc_polling: wrong pipe type"); 2564 2565 usba_release_ph_data(ph_data->p_ph_impl); 2566 2567 return; 2568 } 2569 if ((ph_data->p_ep.bEndpointAddress & USB_EP_DIR_IN) == 0) { 2570 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2571 "usba_pipe_stop_isoc_polling: wrong pipe direction"); 2572 2573 usba_release_ph_data(ph_data->p_ph_impl); 2574 2575 return; 2576 } 2577 2578 if (servicing_interrupt() && (flags & USB_FLAGS_SLEEP)) { 2579 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 2580 "usba_pipe_stop_intr_polling: invalid context"); 2581 2582 usba_release_ph_data(ph_data->p_ph_impl); 2583 2584 return; 2585 } 2586 2587 (void) usba_pipe_setup_func_call(ph_data->p_dip, 2588 usba_pipe_sync_stop_isoc_polling, 2589 (usba_ph_impl_t *)pipe_handle, (usb_opaque_t)flags, 2590 flags, usba_dummy_callback, NULL); 2591 } 2592