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