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