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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * USBA: Solaris USB Architecture support
30 * functions that deal with allocation/free/data_xfers
31 * for the control/bulk/interrupt/isoch pipes:
32 * usb_alloc_ctrl_req()
34 * usb_pipe_ctrl_xfer()
35 * usb_pipe_sync_ctrl_xfer()
36 * usb_pipe_ctrl_xfer_wait()
38 * usb_alloc_bulk_req()
40 * usb_pipe_bulk_xfer()
41 * usb_pipe_bulk_transfer_size()
43 * usb_alloc_intr_req()
45 * usb_pipe_intr_xfer()
46 * usb_pipe_stop_intr_polling()
48 * usb_alloc_isoc_req()
50 * usb_get_current_frame_number()
51 * usb_get_max_isoc_pkts()
52 * usb_pipe_isoc_xfer()
53 * usb_pipe_stop_isoc_polling()
56 * update return values where needed
57 * keep track of requests not freed
60 #define USBA_FRAMEWORK
61 #include <sys/usb/usba/usba_impl.h>
62 #include <sys/usb/usba/hcdi_impl.h>
63 #include <sys/strsubr.h>
64 #include <sys/strsun.h>
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
);
74 * check pipe, request structure for validity
77 * ph - pipe handle pointer
78 * req - opaque request pointer
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
89 usba_check_req(usba_pipe_handle_data_t
*ph_data
, usb_opaque_t req
,
90 usb_flags_t flags
, uchar_t pipe_type
)
92 int rval
= _usba_check_req(ph_data
, req
, flags
, pipe_type
);
94 if (rval
!= USB_SUCCESS
) {
95 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
96 "usba_check_req: ph_data=0x%p req=0x%p flags=0%x rval=%d",
97 (void *)ph_data
, (void *)req
, flags
, rval
);
105 _usba_check_req(usba_pipe_handle_data_t
*ph_data
, usb_opaque_t req
,
106 usb_flags_t flags
, uchar_t pipe_type
)
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
);
115 usb_req_attrs_t attrs
;
116 usb_opaque_t cb
, exc_cb
;
118 uchar_t direction
= ph_data
->p_ep
.bEndpointAddress
&
120 uchar_t ep_attrs
= ph_data
->p_ep
.bmAttributes
&
124 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
125 "usba_check_req: ph_data=0x%p req=0x%p flags=0x%x",
126 (void *)ph_data
, (void *)req
, flags
);
130 return (USB_INVALID_ARGS
);
133 /* set completion reason first so it specifies an error */
135 case USB_EP_ATTR_CONTROL
:
136 cr
= &ctrl_req
->ctrl_completion_reason
;
138 case USB_EP_ATTR_BULK
:
139 cr
= &bulk_req
->bulk_completion_reason
;
141 case USB_EP_ATTR_INTR
:
142 cr
= &intr_req
->intr_completion_reason
;
144 case USB_EP_ATTR_ISOCH
:
145 cr
= &isoc_req
->isoc_completion_reason
;
149 *cr
= USB_CR_UNSPECIFIED_ERR
;
151 if (servicing_interrupt() && (flags
& USB_FLAGS_SLEEP
)) {
153 return (USB_INVALID_CONTEXT
);
156 if (pipe_type
!= ep_attrs
) {
158 return (USB_INVALID_PIPE
);
161 /* we must have usba_device and default ph to do autoclearing */
162 ASSERT(ph_data
->p_usba_device
);
164 if (ph_data
->p_usba_device
->usb_ph_list
[0].usba_ph_data
== NULL
) {
166 return (USB_INVALID_PIPE
);
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
) {
173 return (USB_INVALID_REQUEST
);
176 /* copy over some members for easy checking later */
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
;
188 /* force auto clearing on the default pipe */
189 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
190 attrs
|= USB_ATTRS_AUTOCLEARING
;
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
;
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
;
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
;
225 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
226 "usba_check_req: attrs = 0x%x flags=0x%x", attrs
, flags
);
228 /* check flags and attr combinations */
229 if (usba_flags_attr_check(ph_data
, attrs
, flags
) !=
232 return (USB_INVALID_REQUEST
);
235 /* if no sleep, there must be callback ptrs */
236 if ((flags
& USB_FLAGS_SLEEP
) == 0) {
237 if (cb
== NULL
|| exc_cb
== NULL
) {
239 return (USB_INVALID_REQUEST
);
244 case USB_EP_ATTR_CONTROL
:
245 if (ctrl_req
->ctrl_wLength
&& (data
== NULL
)) {
247 return (USB_INVALID_REQUEST
);
250 case USB_EP_ATTR_BULK
:
251 if ((bulk_req
->bulk_len
) && (data
== NULL
)) {
253 return (USB_INVALID_REQUEST
);
256 case USB_EP_ATTR_INTR
:
257 if (direction
== USB_EP_DIR_OUT
) {
258 if (intr_req
->intr_len
&& data
== NULL
) {
260 return (USB_INVALID_REQUEST
);
264 if (direction
== USB_EP_DIR_IN
) {
265 if (!(intr_req
->intr_attributes
& USB_ATTRS_ONE_XFER
)) {
266 if (cb
== NULL
|| exc_cb
== NULL
) {
268 return (USB_INVALID_REQUEST
);
273 return (USB_INVALID_REQUEST
);
275 if (!(intr_req
->intr_attributes
& USB_ATTRS_ONE_XFER
) &&
278 return (USB_INVALID_REQUEST
);
282 case USB_EP_ATTR_ISOCH
:
283 if (direction
== USB_EP_DIR_IN
) {
284 if (cb
== NULL
|| exc_cb
== NULL
) {
286 return (USB_INVALID_REQUEST
);
292 return (USB_INVALID_REQUEST
);
296 * Since ehci/ohci/uhci use (data->b_wptr - data->b_rptr) as
297 * real isoc_pkts_length, it should be checked.
299 if (direction
== USB_EP_DIR_OUT
) {
300 if (MBLKL(data
) <= 0) {
302 return (USB_INVALID_REQUEST
);
306 /* special isoc checks */
307 if ((isoc_req
->isoc_pkts_count
== 0) ||
308 (isoc_req
->isoc_pkt_descr
== NULL
)) {
310 return (USB_INVALID_REQUEST
);
313 /* check attributes for conflicts, one must be specified */
314 if (!((isoc_req
->isoc_attributes
&
315 USB_ATTRS_ISOC_START_FRAME
) ||
316 (isoc_req
->isoc_attributes
& USB_ATTRS_ISOC_XFER_ASAP
))) {
318 return (USB_NO_FRAME_NUMBER
);
321 /* both may not be specified */
322 if ((isoc_req
->isoc_attributes
&
323 (USB_ATTRS_ISOC_START_FRAME
| USB_ATTRS_ISOC_XFER_ASAP
)) ==
324 (USB_ATTRS_ISOC_START_FRAME
| USB_ATTRS_ISOC_XFER_ASAP
)) {
326 return (USB_NO_FRAME_NUMBER
);
329 /* no start frame may be specified for ASAP attribute */
330 if (((isoc_req
->isoc_attributes
& USB_ATTRS_ISOC_XFER_ASAP
)) &&
331 isoc_req
->isoc_frame_no
) {
333 return (USB_INVALID_REQUEST
);
336 /* start frame must be specified for START FRAME attribute */
337 if (((isoc_req
->isoc_attributes
&
338 USB_ATTRS_ISOC_START_FRAME
)) &&
339 (isoc_req
->isoc_frame_no
== 0)) {
341 return (USB_NO_FRAME_NUMBER
);
344 /* each packet must have initialized pkt length */
345 for (n
= 0; n
< isoc_req
->isoc_pkts_count
; n
++) {
346 if (isoc_req
->isoc_pkt_descr
[n
].isoc_pkt_length
== 0) {
348 return (USB_INVALID_REQUEST
);
354 /* save pipe_handle/attrs/timeout/usb_flags */
355 wrp
->wr_ph_data
= ph_data
;
356 wrp
->wr_usb_flags
= flags
;
357 wrp
->wr_attrs
= attrs
;
359 /* zero some fields in case the request is reused */
360 wrp
->wr_done
= B_FALSE
;
361 wrp
->wr_cr
= USB_CR_OK
;
363 /* this request looks good */
366 return (USB_SUCCESS
);
371 * Table of invalid flags and attributes values. See "usbai.h"
372 * for a complete table on valid usb_req_attrs_t
374 #define X ((uint_t)(-1))
375 #define OUT USB_EP_DIR_OUT
376 #define IN USB_EP_DIR_IN
381 uint_t usb_flags
; /* usb_flags SLEEP or none */
383 } usb_invalid_flags_attrs
[] = {
384 { OUT
, USB_EP_ATTR_BULK
, X
, USB_ATTRS_SHORT_XFER_OK
},
385 { OUT
, USB_EP_ATTR_INTR
, X
, USB_ATTRS_SHORT_XFER_OK
},
386 { OUT
, USB_EP_ATTR_ISOCH
, X
, USB_ATTRS_SHORT_XFER_OK
},
388 { X
, USB_EP_ATTR_CONTROL
, X
, USB_ATTRS_ISOC_START_FRAME
},
389 { X
, USB_EP_ATTR_BULK
, X
, USB_ATTRS_ISOC_START_FRAME
},
390 { X
, USB_EP_ATTR_INTR
, X
, USB_ATTRS_ISOC_START_FRAME
},
392 { X
, USB_EP_ATTR_CONTROL
, X
, USB_ATTRS_ISOC_XFER_ASAP
},
393 { X
, USB_EP_ATTR_INTR
, X
, USB_ATTRS_ISOC_XFER_ASAP
},
394 { OUT
, USB_EP_ATTR_INTR
, X
, USB_ATTRS_ONE_XFER
},
395 { X
, USB_EP_ATTR_BULK
, X
, USB_ATTRS_ISOC_XFER_ASAP
},
397 { X
, USB_EP_ATTR_CONTROL
, X
, USB_ATTRS_ONE_XFER
},
398 { X
, USB_EP_ATTR_BULK
, X
, USB_ATTRS_ONE_XFER
},
399 { X
, USB_EP_ATTR_ISOCH
, X
, USB_ATTRS_ONE_XFER
},
402 #define N_INVALID_FLAGS_ATTRS (sizeof (usb_invalid_flags_attrs))/ \
403 sizeof (struct flags_attr)
406 * function to check flags and attribute combinations for a particular pipe
408 * ph - pipe handle pointer
409 * attrs - attributes of the request
413 usba_flags_attr_check(usba_pipe_handle_data_t
*ph_data
,
414 usb_req_attrs_t attrs
,
418 uchar_t ep_dir
= ph_data
->p_ep
.bEndpointAddress
& USB_EP_DIR_MASK
;
419 uchar_t ep_attr
= ph_data
->p_ep
.bmAttributes
& USB_EP_ATTR_MASK
;
421 flags
&= USB_FLAGS_SLEEP
; /* ignore other flags */
424 * Do some attributes validation checks here.
426 for (i
= 0; i
< N_INVALID_FLAGS_ATTRS
; i
++) {
427 if (((ep_dir
== usb_invalid_flags_attrs
[i
].ep_dir
) ||
428 (usb_invalid_flags_attrs
[i
].ep_dir
== X
)) &&
429 ((ep_attr
== usb_invalid_flags_attrs
[i
].ep_attr
) ||
430 (usb_invalid_flags_attrs
[i
].ep_attr
== X
)) &&
431 ((flags
& usb_invalid_flags_attrs
[i
].usb_flags
) ||
432 (usb_invalid_flags_attrs
[i
].usb_flags
== X
)) &&
433 ((attrs
& usb_invalid_flags_attrs
[i
].attrs
) ||
434 (usb_invalid_flags_attrs
[i
].attrs
== X
))) {
435 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
436 "invalid (%d) : flags = 0x%x, attrs = 0x%x",
439 return (USB_INVALID_REQUEST
);
443 return (USB_SUCCESS
);
449 * convert rval to meaningful completion reason
450 * XXX extend completion reasons to get better mapping
456 {USB_SUCCESS
, USB_CR_OK
},
457 {USB_FAILURE
, USB_CR_UNSPECIFIED_ERR
},
458 {USB_NO_RESOURCES
, USB_CR_NO_RESOURCES
},
459 {USB_NO_BANDWIDTH
, USB_CR_NO_RESOURCES
},
460 {USB_NOT_SUPPORTED
, USB_CR_UNSPECIFIED_ERR
},
461 {USB_PIPE_ERROR
, USB_CR_UNSPECIFIED_ERR
},
462 {USB_INVALID_PIPE
, USB_CR_UNSPECIFIED_ERR
},
463 {USB_NO_FRAME_NUMBER
, USB_CR_UNSPECIFIED_ERR
},
464 {USB_INVALID_START_FRAME
, USB_CR_UNSPECIFIED_ERR
},
465 {USB_HC_HARDWARE_ERROR
, USB_CR_UNSPECIFIED_ERR
},
466 {USB_INVALID_REQUEST
, USB_CR_UNSPECIFIED_ERR
},
467 {USB_INVALID_CONTEXT
, USB_CR_UNSPECIFIED_ERR
},
468 {USB_INVALID_VERSION
, USB_CR_UNSPECIFIED_ERR
},
469 {USB_INVALID_ARGS
, USB_CR_UNSPECIFIED_ERR
},
470 {USB_INVALID_PERM
, USB_CR_UNSPECIFIED_ERR
},
471 {USB_BUSY
, USB_CR_UNSPECIFIED_ERR
},
476 usba_rval2cr(int rval
)
480 for (i
= 0; rval2cr
[i
].rval
!= 0xffff; i
++) {
481 if (rval2cr
[i
].rval
== rval
) {
483 return (rval2cr
[i
].cr
);
487 return (USB_CR_UNSPECIFIED_ERR
);
492 * usba_start_next_req:
494 * ph_data - pointer to pipe handle
496 * Currently, only ctrl/bulk requests can be queued
499 usba_start_next_req(usba_pipe_handle_data_t
*ph_data
)
501 usb_ctrl_req_t
*ctrl_req
;
502 usb_bulk_req_t
*bulk_req
;
503 usba_req_wrapper_t
*wrp
;
504 uchar_t ep_attrs
= ph_data
->p_ep
.bmAttributes
&
507 usb_pipe_state_t state
;
509 mutex_enter(&ph_data
->p_mutex
);
511 case USB_EP_ATTR_CONTROL
:
512 case USB_EP_ATTR_BULK
:
513 switch (usba_get_ph_state(ph_data
)) {
514 case USB_PIPE_STATE_IDLE
:
515 case USB_PIPE_STATE_CLOSING
:
520 mutex_exit(&ph_data
->p_mutex
);
526 case USB_EP_ATTR_ISOCH
:
527 case USB_EP_ATTR_INTR
:
529 mutex_exit(&ph_data
->p_mutex
);
534 while ((wrp
= (usba_req_wrapper_t
*)
535 usba_rm_first_pvt_from_list(&ph_data
->p_queue
)) != NULL
) {
537 /* only submit to HCD when idle/active */
539 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
540 "usba_start_next_req: ph_data=0x%p state=%d",
541 (void *)ph_data
, usba_get_ph_state(ph_data
));
543 if (ep_attrs
== USB_EP_ATTR_CONTROL
) {
544 ph_data
->p_active_cntrl_req_wrp
= (usb_opaque_t
)wrp
;
547 if ((state
= usba_get_ph_state(ph_data
)) ==
548 USB_PIPE_STATE_IDLE
) {
549 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_ACTIVE
);
551 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
552 "starting req = 0x%p",
553 (void *)USBA_WRP2CTRL_REQ(wrp
));
556 case USB_EP_ATTR_CONTROL
:
557 mutex_exit(&ph_data
->p_mutex
);
558 ctrl_req
= USBA_WRP2CTRL_REQ(wrp
);
560 rval
= ph_data
->p_usba_device
->usb_hcdi_ops
->
561 usba_hcdi_pipe_ctrl_xfer(ph_data
,
562 ctrl_req
, wrp
->wr_usb_flags
);
563 mutex_enter(&ph_data
->p_mutex
);
565 case USB_EP_ATTR_BULK
:
566 mutex_exit(&ph_data
->p_mutex
);
567 bulk_req
= USBA_WRP2BULK_REQ(wrp
);
569 rval
= ph_data
->p_usba_device
->usb_hcdi_ops
->
570 usba_hcdi_pipe_bulk_xfer(ph_data
,
571 bulk_req
, wrp
->wr_usb_flags
);
572 mutex_enter(&ph_data
->p_mutex
);
575 /* there shouldn't be any requests */
580 if (rval
!= USB_SUCCESS
) {
581 mutex_exit(&ph_data
->p_mutex
);
582 usba_do_req_exc_cb(wrp
,
584 USB_CB_SUBMIT_FAILED
);
585 mutex_enter(&ph_data
->p_mutex
);
591 mutex_exit(&ph_data
->p_mutex
);
593 case USB_PIPE_STATE_CLOSING
:
594 usba_do_req_exc_cb(wrp
, USB_CR_PIPE_CLOSING
, 0);
596 case USB_PIPE_STATE_ERROR
:
598 usba_do_req_exc_cb(wrp
, USB_CR_FLUSHED
, 0);
601 mutex_enter(&ph_data
->p_mutex
);
605 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
606 "usba_start_next_req done: ph_data=0x%p state=%d", (void *)ph_data
,
607 usba_get_ph_state(ph_data
));
609 mutex_exit(&ph_data
->p_mutex
);
614 * usba_req_wrapper_alloc:
615 * Allocate + Initialize a usba_req_wrapper_t
618 * dip - dev_info_t of the client driver
619 * req_len - sizeof request
621 * USB_FLAGS_SLEEP - Sleep if resources are not available
622 * no USB_FLAGS_SLEEP - Don't Sleep if resources are not available
625 * pointer to usba_req_wrapper_t on success; NULL on failure.
628 static usba_req_wrapper_t
*
629 usba_req_wrapper_alloc(dev_info_t
*dip
,
634 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
635 usba_req_wrapper_t
*wrp
;
636 size_t wr_length
= sizeof (usba_req_wrapper_t
) + req_len
;
637 ddi_iblock_cookie_t iblock_cookie
=
638 usba_hcdi_get_hcdi(usba_device
->usb_root_hub_dip
)->
641 if (servicing_interrupt() && (flags
& USB_FLAGS_SLEEP
)) {
646 kmflag
= (flags
& USB_FLAGS_SLEEP
) ? KM_SLEEP
: KM_NOSLEEP
;
648 /* Allocate the usb_{c/b/i/i}_req + usba_req_wrapper_t structure */
649 if ((wrp
= kmem_zalloc(wr_length
, kmflag
)) != NULL
) {
650 wrp
->wr_length
= wr_length
;
652 wrp
->wr_req
= (usb_opaque_t
)USBA_SETREQ_ADDR(wrp
);
653 cv_init(&wrp
->wr_cv
, NULL
, CV_DRIVER
, NULL
);
655 /* initialize mutex for the queue */
656 usba_init_list(&wrp
->wr_queue
, (usb_opaque_t
)wrp
,
658 usba_init_list(&wrp
->wr_allocated_list
, (usb_opaque_t
)wrp
,
661 usba_add_to_list(&usba_device
->usb_allocated
,
662 &wrp
->wr_allocated_list
);
664 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
665 "usba_req_wrapper_alloc: wrp = 0x%p", (void *)wrp
);
673 * usba_req_wrapper_free:
674 * Frees a usba_req_wrapper_t. Get rid of lists if any.
677 * wrp: request wrapper structure
680 usba_req_wrapper_free(usba_req_wrapper_t
*wrp
)
682 usba_device_t
*usba_device
;
683 usba_pipe_handle_data_t
*ph_data
;
685 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
686 "usba_req_wrapper_free: wrp=0x%p", (void *)wrp
);
689 /* remove from queues */
690 ph_data
= USBA_WRP2PH_DATA(wrp
);
692 (void) usba_rm_from_list(&ph_data
->p_queue
,
695 usba_device
= usba_get_usba_device(wrp
->wr_dip
);
696 if (usba_rm_from_list(&usba_device
->usb_allocated
,
697 &wrp
->wr_allocated_list
) != USB_SUCCESS
) {
699 "usba_req_wrapper_free: data corruption");
701 usba_destroy_list(&wrp
->wr_queue
);
702 usba_destroy_list(&wrp
->wr_allocated_list
);
703 cv_destroy(&wrp
->wr_cv
);
704 kmem_free(wrp
, wrp
->wr_length
);
710 * usba_check_intr_context
711 * Set USB_CB_INTR_CONTEXT callback flag if executing in interrupt context
714 usba_check_intr_context(usb_cb_flags_t cb_flags
)
716 if (servicing_interrupt() != 0) {
717 cb_flags
|= USB_CB_INTR_CONTEXT
;
725 * usba_req_normal_cb:
726 * perform normal callback depending on request type
729 usba_req_normal_cb(usba_req_wrapper_t
*req_wrp
)
731 usba_pipe_handle_data_t
*ph_data
= req_wrp
->wr_ph_data
;
732 usb_pipe_handle_t pipe_handle
;
733 uint_t direction
= ph_data
->p_ep
.bEndpointAddress
&
735 usb_pipe_state_t pipe_state
;
737 pipe_handle
= usba_get_pipe_handle(ph_data
);
739 mutex_enter(&ph_data
->p_mutex
);
740 ASSERT(ph_data
->p_req_count
>= 0);
741 pipe_state
= usba_get_ph_state(ph_data
);
743 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
744 "usba_req_normal_cb: "
745 "ph_data=0x%p state=%d wrp=0x%p ref=%d req=%d",
746 (void *)ph_data
, pipe_state
, (void *)req_wrp
,
747 usba_get_ph_ref_count(ph_data
), ph_data
->p_req_count
);
749 ASSERT((pipe_state
== USB_PIPE_STATE_ACTIVE
) ||
750 (pipe_state
== USB_PIPE_STATE_CLOSING
));
752 /* set done to indicate that we will do callback or cv_signal */
753 ASSERT(req_wrp
->wr_done
== B_FALSE
);
754 req_wrp
->wr_done
= B_TRUE
;
756 /* update the pipe state */
757 switch (req_wrp
->wr_ph_data
->p_ep
.bmAttributes
&
759 case USB_EP_ATTR_CONTROL
:
760 case USB_EP_ATTR_BULK
:
761 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
763 case USB_EP_ATTR_INTR
:
764 if ((direction
== USB_EP_DIR_IN
) &&
765 (USBA_WRP2INTR_REQ(req_wrp
)->intr_attributes
&
766 USB_ATTRS_ONE_XFER
)) {
767 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
768 } else if ((direction
== USB_EP_DIR_OUT
) &&
769 (ph_data
->p_req_count
== 0)) {
770 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
773 case USB_EP_ATTR_ISOCH
:
774 if ((ph_data
->p_req_count
== 0) &&
775 (direction
== USB_EP_DIR_OUT
)) {
776 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
782 /* now complete the request */
783 if (req_wrp
->wr_usb_flags
& USBA_WRP_FLAGS_WAIT
) {
784 ph_data
->p_active_cntrl_req_wrp
= NULL
;
785 cv_signal(&req_wrp
->wr_cv
);
786 mutex_exit(&ph_data
->p_mutex
);
788 mutex_exit(&ph_data
->p_mutex
);
790 /* This sets USB_CB_INTR_CONTEXT as needed. */
791 usba_req_set_cb_flags(req_wrp
, USB_CB_NO_INFO
);
793 switch (req_wrp
->wr_ph_data
->p_ep
.bmAttributes
&
795 case USB_EP_ATTR_CONTROL
:
796 USBA_WRP2CTRL_REQ(req_wrp
)->ctrl_cb(pipe_handle
,
797 USBA_WRP2CTRL_REQ(req_wrp
));
798 mutex_enter(&ph_data
->p_mutex
);
799 ph_data
->p_active_cntrl_req_wrp
= NULL
;
800 mutex_exit(&ph_data
->p_mutex
);
802 case USB_EP_ATTR_INTR
:
803 USBA_WRP2INTR_REQ(req_wrp
)->intr_cb(pipe_handle
,
804 USBA_WRP2INTR_REQ(req_wrp
));
806 case USB_EP_ATTR_BULK
:
807 USBA_WRP2BULK_REQ(req_wrp
)->bulk_cb(pipe_handle
,
808 USBA_WRP2BULK_REQ(req_wrp
));
810 case USB_EP_ATTR_ISOCH
:
811 USBA_WRP2ISOC_REQ(req_wrp
)->isoc_cb(pipe_handle
,
812 USBA_WRP2ISOC_REQ(req_wrp
));
817 /* we are done with this request */
818 mutex_enter(&ph_data
->p_mutex
);
819 ph_data
->p_req_count
--;
820 ASSERT(ph_data
->p_req_count
>= 0);
821 mutex_exit(&ph_data
->p_mutex
);
827 * perform exception cb depending on request type.
828 * ensure the completion reason is non zero
831 usba_req_exc_cb(usba_req_wrapper_t
*req_wrp
, usb_cr_t cr
,
832 usb_cb_flags_t cb_flags
)
834 usba_pipe_handle_data_t
*ph_data
= req_wrp
->wr_ph_data
;
835 usb_pipe_handle_t pipe_handle
= usba_get_pipe_handle(ph_data
);
837 mutex_enter(&req_wrp
->wr_ph_data
->p_mutex
);
838 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
839 "usba_req_exc_cb: %s%d: ph_data=0x%p (ep%x) state=%d wrp=0x%p "
840 "ref=%d reqcnt=%d cr=%d",
841 ddi_driver_name(req_wrp
->wr_dip
),
842 ddi_get_instance(req_wrp
->wr_dip
),
843 (void *)ph_data
, ph_data
->p_ep
.bEndpointAddress
,
844 usba_get_ph_state(ph_data
), (void *)req_wrp
,
845 usba_get_ph_ref_count(ph_data
), ph_data
->p_req_count
,
848 ASSERT(req_wrp
->wr_ph_data
->p_req_count
>= 0);
850 usba_req_set_cb_flags(req_wrp
, cb_flags
);
852 /* if there was no CR set already, set it now */
853 if (req_wrp
->wr_cr
== USB_CR_OK
) {
854 req_wrp
->wr_cr
= (cr
!= USB_CR_OK
) ?
855 cr
: USB_CR_UNSPECIFIED_ERR
;
858 ASSERT(req_wrp
->wr_done
== B_FALSE
);
859 req_wrp
->wr_done
= B_TRUE
;
861 switch (req_wrp
->wr_ph_data
->p_ep
.bmAttributes
&
863 case USB_EP_ATTR_CONTROL
:
864 if (USBA_WRP2CTRL_REQ(req_wrp
)->
865 ctrl_completion_reason
== USB_CR_OK
) {
866 USBA_WRP2CTRL_REQ(req_wrp
)->
867 ctrl_completion_reason
= req_wrp
->wr_cr
;
870 case USB_EP_ATTR_INTR
:
871 if (USBA_WRP2INTR_REQ(req_wrp
)->
872 intr_completion_reason
== USB_CR_OK
) {
873 USBA_WRP2INTR_REQ(req_wrp
)->
874 intr_completion_reason
= req_wrp
->wr_cr
;
877 case USB_EP_ATTR_BULK
:
878 if (USBA_WRP2BULK_REQ(req_wrp
)->
879 bulk_completion_reason
== USB_CR_OK
) {
880 USBA_WRP2BULK_REQ(req_wrp
)->
881 bulk_completion_reason
= req_wrp
->wr_cr
;
884 case USB_EP_ATTR_ISOCH
:
885 if (USBA_WRP2ISOC_REQ(req_wrp
)->
886 isoc_completion_reason
== USB_CR_OK
) {
887 USBA_WRP2ISOC_REQ(req_wrp
)->
888 isoc_completion_reason
= req_wrp
->wr_cr
;
893 if (req_wrp
->wr_usb_flags
& USBA_WRP_FLAGS_WAIT
) {
894 cv_signal(&req_wrp
->wr_cv
);
895 if (ph_data
->p_active_cntrl_req_wrp
== (usb_opaque_t
)req_wrp
) {
896 ph_data
->p_active_cntrl_req_wrp
= NULL
;
898 mutex_exit(&ph_data
->p_mutex
);
900 mutex_exit(&ph_data
->p_mutex
);
901 switch (req_wrp
->wr_ph_data
->p_ep
.bmAttributes
&
903 case USB_EP_ATTR_CONTROL
:
904 USBA_WRP2CTRL_REQ(req_wrp
)->ctrl_exc_cb(pipe_handle
,
905 USBA_WRP2CTRL_REQ(req_wrp
));
906 mutex_enter(&ph_data
->p_mutex
);
907 if (ph_data
->p_active_cntrl_req_wrp
==
908 (usb_opaque_t
)req_wrp
) {
909 ph_data
->p_active_cntrl_req_wrp
= NULL
;
911 mutex_exit(&ph_data
->p_mutex
);
913 case USB_EP_ATTR_INTR
:
914 USBA_WRP2INTR_REQ(req_wrp
)->intr_exc_cb(pipe_handle
,
915 USBA_WRP2INTR_REQ(req_wrp
));
917 case USB_EP_ATTR_BULK
:
918 USBA_WRP2BULK_REQ(req_wrp
)->bulk_exc_cb(pipe_handle
,
919 USBA_WRP2BULK_REQ(req_wrp
));
921 case USB_EP_ATTR_ISOCH
:
922 USBA_WRP2ISOC_REQ(req_wrp
)->isoc_exc_cb(pipe_handle
,
923 USBA_WRP2ISOC_REQ(req_wrp
));
928 /* we are done with this request */
929 mutex_enter(&ph_data
->p_mutex
);
930 ph_data
->p_req_count
--;
931 ASSERT(ph_data
->p_req_count
>= 0);
932 mutex_exit(&ph_data
->p_mutex
);
937 * usba_do_req_exc_cb:
938 * called when flushing requests. rather than calling usba_req_exc_cb()
939 * directly, this function uses usba_hcdi_cb() which ensures callback
943 usba_do_req_exc_cb(usba_req_wrapper_t
*req_wrp
, usb_cr_t cr
,
944 usb_cb_flags_t cb_flags
)
946 req_wrp
->wr_cb_flags
|= cb_flags
;
947 usba_hcdi_cb(req_wrp
->wr_ph_data
, req_wrp
->wr_req
, cr
);
952 * usba_req_set_cb_flags:
953 * This function sets the request's callback flags to those stored in the
954 * request wrapper ORed with those received as an argument. Additionally
955 * USB_CB_INTR_CONTEXT is set if called from interrupt context.
957 * NOTE: The xfer may have succeeded, which client driver can determine
958 * by looking at usb_cr_t
961 usba_req_set_cb_flags(usba_req_wrapper_t
*req_wrp
,
962 usb_cb_flags_t cb_flags
)
964 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
965 "usba_req_set_cb_flags: wrp=0x%p cb-flags=0x%x",
966 (void *)req_wrp
, cb_flags
);
968 cb_flags
|= req_wrp
->wr_cb_flags
;
969 cb_flags
= usba_check_intr_context(cb_flags
);
971 /* do the callback under taskq context */
972 switch (req_wrp
->wr_ph_data
->p_ep
.bmAttributes
&
974 case USB_EP_ATTR_CONTROL
:
975 USBA_WRP2CTRL_REQ(req_wrp
)->ctrl_cb_flags
|= cb_flags
;
977 case USB_EP_ATTR_INTR
:
978 USBA_WRP2INTR_REQ(req_wrp
)->intr_cb_flags
|= cb_flags
;
980 case USB_EP_ATTR_BULK
:
981 USBA_WRP2BULK_REQ(req_wrp
)->bulk_cb_flags
|= cb_flags
;
983 case USB_EP_ATTR_ISOCH
:
984 USBA_WRP2ISOC_REQ(req_wrp
)->isoc_cb_flags
|= cb_flags
;
991 * usba_pipe_sync_wait:
992 * wait for the request to finish.
993 * usba_hcdi_cb() does a cv_signal thru a soft intr
996 * ph_data - pointer to pipe handle data
997 * wrp - pointer to usba_req_wrapper_structure.
1000 * USB_SUCCESS - request successfully executed
1001 * USB_FAILURE - request failed
1004 usba_pipe_sync_wait(usba_pipe_handle_data_t
*ph_data
,
1005 usba_req_wrapper_t
*wrp
)
1007 ASSERT(wrp
->wr_usb_flags
& USB_FLAGS_SLEEP
);
1008 ASSERT(ph_data
== wrp
->wr_ph_data
);
1010 mutex_enter(&ph_data
->p_mutex
);
1011 while (wrp
->wr_done
!= B_TRUE
) {
1012 cv_wait(&wrp
->wr_cv
, &ph_data
->p_mutex
);
1015 mutex_exit(&ph_data
->p_mutex
);
1017 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1018 "usba_pipe_sync_wait: ph_data=0x%p cr=0x%x", (void *)ph_data
,
1021 /* XXX return something better than USB_FAILURE?? */
1023 return (wrp
->wr_cr
== USB_CR_OK
? USB_SUCCESS
: USB_FAILURE
);
1028 * Allocate usb control request and a USB request wrapper
1031 * dip - dev_info_t of the client driver
1032 * len - length of "data" for this control request
1034 * USB_FLAGS_SLEEP - Sleep if resources are not available
1035 * no USB_FLAGS_SLEEP - Don't Sleep if resources are not available
1037 * Return Values: usb_ctrl_req_t on success, NULL on failure
1040 usb_alloc_ctrl_req(dev_info_t
*dip
,
1044 usb_ctrl_req_t
*ctrl_req
= NULL
;
1045 usba_req_wrapper_t
*wrp
;
1047 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1048 "usb_alloc_ctrl_req: dip=0x%p, wlen=0x%lx, flags=0x%x",
1049 (void *)dip
, len
, flags
);
1051 /* Allocate + Initialize the usba_req_wrapper_t structure */
1053 ((wrp
= usba_req_wrapper_alloc(dip
, sizeof (*ctrl_req
), flags
)) !=
1055 ctrl_req
= USBA_WRP2CTRL_REQ(wrp
);
1057 /* Allocate the usb_ctrl_req data mblk */
1059 if (flags
& USB_FLAGS_SLEEP
) {
1060 ctrl_req
->ctrl_data
= allocb_wait(len
, BPRI_LO
,
1062 } else if ((ctrl_req
->ctrl_data
=
1063 allocb(len
, BPRI_HI
)) == NULL
) {
1064 usba_req_wrapper_free(wrp
);
1070 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1071 "usb_alloc_ctrl_req: ctrl_req = 0x%p", (void *)ctrl_req
);
1078 * usb_free_ctrl_req:
1079 * free USB control request + wrapper
1082 * req - pointer to usb_ctrl_req_t
1085 usb_free_ctrl_req(usb_ctrl_req_t
*req
)
1088 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1089 "usb_free_ctrl_req: req = 0x%p", (void *)req
);
1091 if (req
->ctrl_data
) {
1092 freemsg(req
->ctrl_data
);
1094 usba_req_wrapper_free(USBA_REQ2WRP(req
));
1100 * Client driver calls this function to issue the control
1101 * request to the USBA
1104 * pipe_handle: control pipe pipehandle (obtained via usb_pipe_open()
1105 * req: control request
1107 * USB_FLAGS_SLEEP - wait for the request to complete
1110 * USB_SUCCESS - request successfully executed
1111 * USB_FAILURE - request failed
1114 usb_pipe_ctrl_xfer(usb_pipe_handle_t pipe_handle
,
1115 usb_ctrl_req_t
*req
,
1116 usb_flags_t usb_flags
)
1119 usba_req_wrapper_t
*wrp
= USBA_REQ2WRP(req
);
1120 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1121 usba_device_t
*usba_device
;
1122 usb_flags_t wrp_usb_flags
;
1123 usb_pipe_state_t pipe_state
;
1125 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1126 "usb_pipe_ctrl_xfer: req=0x%p, wrp=0x%p\n\t"
1127 "setup = 0x%x 0x%x 0x%x 0x%x 0x%x uf=0x%x",
1128 (void *)req
, (void *)wrp
, req
->ctrl_bmRequestType
,
1129 req
->ctrl_bRequest
, req
->ctrl_wValue
, req
->ctrl_wIndex
,
1130 req
->ctrl_wLength
, usb_flags
);
1132 if (ph_data
== NULL
) {
1134 return (USB_INVALID_PIPE
);
1137 mutex_enter(&ph_data
->p_mutex
);
1138 usba_device
= ph_data
->p_usba_device
;
1140 if ((rval
= usba_check_req(ph_data
, (usb_opaque_t
)req
, usb_flags
,
1141 USB_EP_ATTR_CONTROL
)) != USB_SUCCESS
) {
1142 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1143 "request rejected: rval=%d", rval
);
1144 mutex_exit(&ph_data
->p_mutex
);
1146 usba_release_ph_data(ph_data
->p_ph_impl
);
1151 ASSERT(ph_data
== wrp
->wr_ph_data
);
1153 /* we accepted the request, so increment the req count */
1154 ph_data
->p_req_count
++;
1156 wrp_usb_flags
= wrp
->wr_usb_flags
;
1158 /* Get the current bulk pipe state */
1159 pipe_state
= usba_get_ph_state(ph_data
);
1162 * if this is for the default pipe, and the pipe is in error,
1163 * just queue the request. autoclearing will start this request
1165 * if there is already an active request in the queue
1166 * then just add this request to the queue.
1168 switch (pipe_state
) {
1169 case USB_PIPE_STATE_IDLE
:
1170 if (ph_data
->p_queue
.next
||
1171 ph_data
->p_active_cntrl_req_wrp
) {
1172 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1173 "usb_pipe_ctrl_xfer: queue request 0x%p",
1176 usba_add_to_list(&ph_data
->p_queue
, &wrp
->wr_queue
);
1178 mutex_exit(&ph_data
->p_mutex
);
1180 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_ACTIVE
);
1181 ph_data
->p_active_cntrl_req_wrp
= (usb_opaque_t
)wrp
;
1182 mutex_exit(&ph_data
->p_mutex
);
1184 /* issue the request to HCD */
1185 rval
= usba_device
->usb_hcdi_ops
->
1186 usba_hcdi_pipe_ctrl_xfer(ph_data
, req
, usb_flags
);
1189 case USB_PIPE_STATE_ACTIVE
:
1190 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1191 "usb_pipe_ctrl_xfer: queue request 0x%p", (void *)req
);
1193 usba_add_to_list(&ph_data
->p_queue
, &wrp
->wr_queue
);
1195 mutex_exit(&ph_data
->p_mutex
);
1197 case USB_PIPE_STATE_ERROR
:
1198 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
1199 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1200 "usb_pipe_ctrl_xfer: queue request 0x%p on "
1201 "pending def pipe error", (void *)req
);
1203 usba_add_to_list(&ph_data
->p_queue
, &wrp
->wr_queue
);
1206 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1207 "usb_pipe_ctrl_xfer: pipe is in error state ");
1209 rval
= USB_PIPE_ERROR
;
1211 mutex_exit(&ph_data
->p_mutex
);
1214 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1215 "usb_pipe_ctrl_xfer: pipe state %d", pipe_state
);
1217 rval
= USB_PIPE_ERROR
;
1218 mutex_exit(&ph_data
->p_mutex
);
1222 /* if there has been a failure, decrement req count */
1223 if (rval
!= USB_SUCCESS
) {
1224 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1225 "usb_pipe_ctrl_xfer: hcd failed req 0x%p", (void *)req
);
1227 if (req
->ctrl_completion_reason
== USB_CR_OK
) {
1228 req
->ctrl_completion_reason
= usba_rval2cr(rval
);
1230 mutex_enter(&ph_data
->p_mutex
);
1231 ASSERT(wrp
->wr_done
== B_FALSE
);
1232 ph_data
->p_req_count
--;
1233 ASSERT(ph_data
->p_req_count
>= 0);
1234 ph_data
->p_active_cntrl_req_wrp
= NULL
;
1235 if ((ph_data
->p_req_count
== 0) &&
1236 (usba_get_ph_state(ph_data
) == USB_PIPE_STATE_ACTIVE
)) {
1237 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
1239 mutex_exit(&ph_data
->p_mutex
);
1241 /* if success and sleep specified, wait for completion */
1242 } else if (wrp_usb_flags
& USBA_WRP_FLAGS_WAIT
) {
1243 rval
= usba_pipe_sync_wait(ph_data
, wrp
);
1246 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1247 "usb_pipe_ctrl_xfer: rval=0x%x", rval
);
1249 usba_release_ph_data(ph_data
->p_ph_impl
);
1256 * usb_pipe_sync_ctrl_xfer():
1257 * for simple synchronous control transactions this wrapper function
1258 * will perform the allocation, xfer, and deallocation
1259 * USB_ATTRS_AUTOCLEARING will be enabled
1262 * dip - pointer to clients devinfo
1263 * pipe_handle - control pipe pipehandle (obtained via usb_pipe_open()
1264 * bmRequestType - characteristics of request
1265 * bRequest - specific request
1266 * wValue - varies according to request
1267 * wIndex - index or offset
1268 * wLength - number of bytes to xfer
1269 * data - pointer to pointer to data and may be NULL if
1271 * attrs - required request attributes
1272 * completion_reason - completion status
1273 * cb_flags - request completions flags
1277 * USB_SUCCESS - request successfully executed
1278 * USB_* - request failed
1281 * - in the case of failure, the client should check completion_reason and
1282 * and cb_flags and determine further recovery action
1283 * - the client should check data and if non-zero, free the data on
1287 usb_pipe_sync_ctrl_xfer(dev_info_t
*dip
,
1288 usb_pipe_handle_t pipe_handle
,
1289 uchar_t bmRequestType
,
1295 usb_req_attrs_t attributes
,
1296 usb_cr_t
*completion_reason
,
1297 usb_cb_flags_t
*cb_flags
,
1300 usba_pipe_handle_data_t
*ph_data
;
1302 usb_ctrl_req_t
*ctrl_req
;
1306 char *buf
= kmem_alloc(BUFSIZE
, KM_SLEEP
);
1309 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1310 "usb_pipe_sync_ctrl_xfer: ph=0x%p\n\t"
1311 "setup = 0x%x 0x%x 0x%x 0x%x 0x%x uf = 0x%x", (void *)pipe_handle
,
1312 bmRequestType
, bRequest
, wValue
, wIndex
, wLength
, flags
);
1314 if ((ph_data
= usba_hold_ph_data(pipe_handle
)) == NULL
) {
1315 rval
= USB_INVALID_PIPE
;
1319 if (servicing_interrupt()) {
1320 rval
= USB_INVALID_CONTEXT
;
1325 rval
= USB_INVALID_ARGS
;
1330 length
= ((data
) && (*data
)) ? 0: wLength
;
1332 ctrl_req
= usb_alloc_ctrl_req(dip
,
1333 length
, flags
| USB_FLAGS_SLEEP
);
1335 /* Initialize the ctrl_req structure */
1336 ctrl_req
->ctrl_bmRequestType
= bmRequestType
;
1337 ctrl_req
->ctrl_bRequest
= bRequest
;
1338 ctrl_req
->ctrl_wValue
= wValue
;
1339 ctrl_req
->ctrl_wIndex
= wIndex
;
1340 ctrl_req
->ctrl_wLength
= wLength
;
1341 ctrl_req
->ctrl_data
= ctrl_req
->ctrl_data
?
1342 ctrl_req
->ctrl_data
: ((data
) ? *data
: NULL
);
1343 ctrl_req
->ctrl_timeout
= USB_PIPE_TIMEOUT
;
1344 ctrl_req
->ctrl_attributes
= attributes
| USB_ATTRS_AUTOCLEARING
;
1346 /* Issue control xfer to the HCD */
1347 rval
= usb_pipe_ctrl_xfer(pipe_handle
, ctrl_req
,
1348 flags
| USB_FLAGS_SLEEP
);
1351 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1352 "req=0x%p, cr=%s cb_flags=%s data=0x%p rval=%s",
1353 (void *)ctrl_req
, usb_str_cr(ctrl_req
->ctrl_completion_reason
),
1354 usb_str_cb_flags(ctrl_req
->ctrl_cb_flags
, buf
, BUFSIZE
),
1355 (void *)ctrl_req
->ctrl_data
, usb_str_rval(rval
));
1358 /* copy back ctrl_req values */
1360 *data
= ctrl_req
->ctrl_data
;
1362 if (completion_reason
) {
1363 *completion_reason
= ctrl_req
->ctrl_completion_reason
;
1366 *cb_flags
= ctrl_req
->ctrl_cb_flags
;
1369 /* Free up the control request now */
1370 ctrl_req
->ctrl_data
= NULL
; /* leave to client to free */
1371 usb_free_ctrl_req(ctrl_req
);
1375 kmem_free(buf
, BUFSIZE
);
1378 usba_release_ph_data(ph_data
->p_ph_impl
);
1386 * usb_pipe_ctrl_xfer_wait():
1387 * Easy-to-use wrapper around usb_pipe_sync_ctrl_xfer.
1390 * pipe_handle - control pipe pipehandle (obtained via usb_pipe_open())
1391 * setup - setup descriptor params, attributes
1392 * data - pointer to pointer to data and may be NULL when
1394 * completion_reason - completion status.
1395 * cb_flags - request completions flags.
1399 * USB_SUCCESS - request successfully executed.
1403 usb_pipe_ctrl_xfer_wait(
1404 usb_pipe_handle_t pipe_handle
,
1405 usb_ctrl_setup_t
*setup
,
1407 usb_cr_t
*completion_reason
,
1408 usb_cb_flags_t
*cb_flags
,
1411 return (usb_pipe_sync_ctrl_xfer(
1412 usba_get_dip(pipe_handle
),
1414 setup
->bmRequestType
,
1428 * usb_alloc_bulk_req:
1429 * Allocate a usb bulk request + usba_req_wrapper_t
1432 * dip - dev_info_t of the client driver
1433 * len - length of "data" for this bulk request
1435 * USB_FLAGS_SLEEP - Sleep if resources are not available
1438 * usb_bulk_req_t on success, NULL on failure
1441 usb_alloc_bulk_req(dev_info_t
*dip
,
1445 usb_bulk_req_t
*bulk_req
= NULL
;
1446 usba_req_wrapper_t
*wrp
;
1448 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1449 "usb_alloc_bulk_req: dip=0x%p wlen=0x%lx flags=0x%x",
1450 (void *)dip
, len
, flags
);
1452 /* Allocate + Initialize the usba_req_wrapper_t structure */
1454 ((wrp
= usba_req_wrapper_alloc(dip
, sizeof (*bulk_req
), flags
)) !=
1456 bulk_req
= USBA_WRP2BULK_REQ(wrp
);
1458 /* Allocate the usb_bulk_req data mblk */
1460 if (flags
& USB_FLAGS_SLEEP
) {
1461 bulk_req
->bulk_data
= allocb_wait(len
,
1462 BPRI_LO
, STR_NOSIG
, NULL
);
1463 } else if ((bulk_req
->bulk_data
=
1464 allocb(len
, BPRI_HI
)) == NULL
) {
1465 usba_req_wrapper_free(wrp
);
1472 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1473 "usb_alloc_bulk_req: bulk_req = 0x%p", (void *)bulk_req
);
1480 * usb_free_bulk_req:
1481 * free USB bulk request + wrapper
1484 * req - pointer to usb_bulk_req_t
1487 usb_free_bulk_req(usb_bulk_req_t
*req
)
1490 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1491 "usb_free_bulk_req: req=0x%p", (void *)req
);
1493 if (req
->bulk_data
) {
1494 freemsg(req
->bulk_data
);
1496 usba_req_wrapper_free(USBA_REQ2WRP(req
));
1502 * Client driver calls this function to issue the bulk xfer to the USBA
1505 * pipe_handle - bulk pipe handle (obtained via usb_pipe_open()
1506 * req - bulk data xfer request (IN or OUT)
1507 * usb_flags - USB_FLAGS_SLEEP - wait for the request to complete
1510 * USB_SUCCESS - success
1511 * USB_FAILURE - unspecified failure
1514 usb_pipe_bulk_xfer(usb_pipe_handle_t pipe_handle
,
1515 usb_bulk_req_t
*req
,
1516 usb_flags_t usb_flags
)
1519 usba_req_wrapper_t
*wrp
= USBA_REQ2WRP(req
);
1520 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1521 usba_device_t
*usba_device
;
1522 usb_flags_t wrp_usb_flags
;
1523 usb_pipe_state_t pipe_state
;
1525 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1526 "usb_pipe_bulk_xfer: req=0x%p uf=0x%x", (void *)req
, usb_flags
);
1528 if (ph_data
== NULL
) {
1530 return (USB_INVALID_PIPE
);
1533 mutex_enter(&ph_data
->p_mutex
);
1534 usba_device
= ph_data
->p_usba_device
;
1536 if ((rval
= usba_check_req(ph_data
, (usb_opaque_t
)req
, usb_flags
,
1537 USB_EP_ATTR_BULK
)) != USB_SUCCESS
) {
1538 mutex_exit(&ph_data
->p_mutex
);
1540 usba_release_ph_data(ph_data
->p_ph_impl
);
1545 /* we accepted the request */
1546 ph_data
->p_req_count
++;
1547 wrp_usb_flags
= wrp
->wr_usb_flags
;
1549 /* Get the current bulk pipe state */
1550 pipe_state
= usba_get_ph_state(ph_data
);
1553 * if there is already an active request in the queue
1554 * then just add this request to the queue.
1556 switch (pipe_state
) {
1557 case USB_PIPE_STATE_IDLE
:
1558 if (ph_data
->p_queue
.next
) {
1559 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1560 "usb_pipe_bulk_xfer: queue request 0x%p",
1563 usba_add_to_list(&ph_data
->p_queue
, &wrp
->wr_queue
);
1565 mutex_exit(&ph_data
->p_mutex
);
1567 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_ACTIVE
);
1568 mutex_exit(&ph_data
->p_mutex
);
1570 /* issue the request to HCD */
1571 rval
= usba_device
->usb_hcdi_ops
->
1572 usba_hcdi_pipe_bulk_xfer(ph_data
, req
, usb_flags
);
1575 case USB_PIPE_STATE_ACTIVE
:
1576 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1577 "usb_pipe_bulk_xfer: queue request 0x%p", (void *)req
);
1579 usba_add_to_list(&ph_data
->p_queue
, &wrp
->wr_queue
);
1581 mutex_exit(&ph_data
->p_mutex
);
1584 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1585 "usb_pipe_bulk_xfer: pipe state %d", pipe_state
);
1587 rval
= USB_PIPE_ERROR
;
1588 mutex_exit(&ph_data
->p_mutex
);
1592 if (rval
!= USB_SUCCESS
) {
1593 if (req
->bulk_completion_reason
== USB_CR_OK
) {
1594 req
->bulk_completion_reason
= usba_rval2cr(rval
);
1596 mutex_enter(&ph_data
->p_mutex
);
1597 ASSERT(wrp
->wr_done
== B_FALSE
);
1598 ph_data
->p_req_count
--;
1599 ASSERT(ph_data
->p_req_count
>= 0);
1600 if ((ph_data
->p_req_count
== 0) &&
1601 (usba_get_ph_state(ph_data
) == USB_PIPE_STATE_ACTIVE
)) {
1602 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
1604 mutex_exit(&ph_data
->p_mutex
);
1605 } else if (wrp_usb_flags
& USBA_WRP_FLAGS_WAIT
) {
1606 rval
= usba_pipe_sync_wait(ph_data
, wrp
);
1609 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1610 "usb_pipe_bulk_xfer: rval=%d", rval
);
1612 usba_release_ph_data(ph_data
->p_ph_impl
);
1619 * usb_pipe_bulk_transfer_size:
1620 * - request HCD to return bulk max transfer data size
1623 * dip - pointer to dev_info_t
1624 * size - pointer to bulk_transfer_size
1627 * USB_SUCCESS - request successfully executed
1628 * USB_FAILURE - request failed
1631 usb_pipe_bulk_transfer_size(dev_info_t
*dip
,
1634 return (usb_pipe_get_max_bulk_transfer_size(dip
, size
));
1639 usb_pipe_get_max_bulk_transfer_size(dev_info_t
*dip
,
1642 usba_device_t
*usba_device
;
1644 if ((dip
== NULL
) || (size
== NULL
)) {
1646 return (USB_INVALID_ARGS
);
1648 usba_device
= usba_get_usba_device(dip
);
1650 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1651 "usb_pipe_bulk_transfer_size: usba_device=0x%p",
1652 (void *)usba_device
);
1654 if ((usba_device
) &&
1655 (usba_device
->usb_hcdi_ops
->usba_hcdi_bulk_transfer_size
)) {
1657 return (usba_device
->usb_hcdi_ops
->
1658 usba_hcdi_bulk_transfer_size(usba_device
, size
));
1662 return (USB_FAILURE
);
1668 * usb_alloc_intr_req:
1669 * Allocate usb interrupt request
1672 * dip - dev_info_t of the client driver
1673 * len - length of "data" for this interrupt request
1675 * USB_FLAGS_SLEEP - Sleep if resources are not available
1678 * usb_intr_req_t on success, NULL on failure
1681 usb_alloc_intr_req(dev_info_t
*dip
,
1685 usb_intr_req_t
*intr_req
= NULL
;
1686 usba_req_wrapper_t
*wrp
;
1688 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1689 "usb_alloc_intr_req: dip=0x%p, len=0x%lx, flags=0x%x",
1690 (void *)dip
, len
, flags
);
1692 /* Allocate + Initialize the usba_req_wrapper_t structure */
1694 (wrp
= usba_req_wrapper_alloc(dip
, sizeof (*intr_req
), flags
)) !=
1696 intr_req
= (usb_intr_req_t
*)USBA_WRP2INTR_REQ(wrp
);
1698 /* Allocate the usb_intr_req data mblk */
1700 if (flags
& USB_FLAGS_SLEEP
) {
1701 intr_req
->intr_data
= allocb_wait(len
, BPRI_LO
,
1703 } else if ((intr_req
->intr_data
=
1704 allocb(len
, BPRI_HI
)) == NULL
) {
1705 usba_req_wrapper_free(wrp
);
1711 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1712 "usb_alloc_intr_req: intr_req=0x%p", (void *)intr_req
);
1719 * usba_hcdi_dup_intr_req:
1720 * create duplicate of interrupt request
1723 * dip - devinfo pointer
1724 * reqp - original requestp pointer
1725 * len - length of "data" for this interrupt request
1727 * USB_FLAGS_SLEEP - Sleep if resources are not available
1730 * usb_intr_req_t on success, NULL on failure
1733 usba_hcdi_dup_intr_req(
1735 usb_intr_req_t
*reqp
,
1739 usb_intr_req_t
*intr_reqp
= NULL
;
1740 usba_req_wrapper_t
*intr_wrp
, *req_wrp
;
1747 req_wrp
= USBA_REQ2WRP(reqp
);
1749 if (((intr_reqp
= usb_alloc_intr_req(dip
, len
, flags
)) != NULL
)) {
1750 intr_reqp
->intr_client_private
= reqp
->intr_client_private
;
1751 intr_reqp
->intr_timeout
= reqp
->intr_timeout
;
1752 intr_reqp
->intr_attributes
= reqp
->intr_attributes
;
1753 intr_reqp
->intr_len
= reqp
->intr_len
;
1754 intr_reqp
->intr_cb
= reqp
->intr_cb
;
1755 intr_reqp
->intr_exc_cb
= reqp
->intr_exc_cb
;
1757 intr_wrp
= USBA_REQ2WRP(intr_reqp
);
1758 intr_wrp
->wr_dip
= req_wrp
->wr_dip
;
1759 intr_wrp
->wr_ph_data
= req_wrp
->wr_ph_data
;
1760 intr_wrp
->wr_attrs
= req_wrp
->wr_attrs
;
1761 intr_wrp
->wr_usb_flags
= req_wrp
->wr_usb_flags
;
1769 * usb_free_intr_req:
1770 * free USB intr request + wrapper
1773 * req - pointer to usb_intr_req_t
1776 usb_free_intr_req(usb_intr_req_t
*req
)
1779 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1780 "usb_free_intr_req: req = 0x%p", (void *)req
);
1782 if (req
->intr_data
) {
1783 freemsg(req
->intr_data
);
1786 usba_req_wrapper_free(USBA_REQ2WRP(req
));
1792 * Client driver calls this function to issue the intr xfer to the USBA
1795 * pipe_handle - intr pipe handle (obtained via usb_pipe_open()
1796 * req - intr data xfer request (IN or OUT)
1798 * USB_FLAGS_SLEEP - wait for the request to complete
1800 * USB_SUCCESS - success
1801 * USB_FAILURE - unspecified failure
1804 usb_pipe_intr_xfer(usb_pipe_handle_t pipe_handle
,
1805 usb_intr_req_t
*req
,
1806 usb_flags_t usb_flags
)
1809 usba_req_wrapper_t
*wrp
= USBA_REQ2WRP(req
);
1810 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
1811 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1812 usba_device_t
*usba_device
;
1814 usb_flags_t wrp_usb_flags
;
1815 usb_pipe_state_t pipe_state
;
1817 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1818 "usb_pipe_intr_req: req=0x%p uf=0x%x",
1819 (void *)req
, usb_flags
);
1821 if (ph_data
== NULL
) {
1823 return (USB_INVALID_PIPE
);
1825 usba_device
= ph_data
->p_usba_device
;
1826 direction
= ph_data
->p_ep
.bEndpointAddress
& USB_EP_DIR_MASK
;
1828 mutex_enter(&ph_data
->p_mutex
);
1829 if ((rval
= usba_check_req(ph_data
, (usb_opaque_t
)req
, usb_flags
,
1830 USB_EP_ATTR_INTR
)) != USB_SUCCESS
) {
1831 mutex_exit(&ph_data
->p_mutex
);
1833 usba_release_ph_data(ph_data
->p_ph_impl
);
1838 /* Get the current interrupt pipe state */
1839 pipe_state
= usba_get_ph_state(ph_data
);
1841 switch (pipe_state
) {
1842 case USB_PIPE_STATE_IDLE
:
1844 * if the pipe state is in middle of transition,
1845 * i.e. stop polling is in progress, fail any
1846 * attempt to do a start polling
1848 mutex_enter(&ph_impl
->usba_ph_mutex
);
1849 if (ph_impl
->usba_ph_state_changing
> 0) {
1850 mutex_exit(&ph_impl
->usba_ph_mutex
);
1852 mutex_exit(&ph_data
->p_mutex
);
1853 usba_release_ph_data(ph_data
->p_ph_impl
);
1855 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1856 "usb_pipe_intr_req: fail request - "
1857 "stop polling in progress");
1859 return (USB_FAILURE
);
1861 mutex_exit(&ph_impl
->usba_ph_mutex
);
1862 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_ACTIVE
);
1866 case USB_PIPE_STATE_ACTIVE
:
1868 * If this is interrupt IN pipe and if we are
1869 * already polling, return failure.
1871 if (direction
== USB_EP_DIR_IN
) {
1872 USB_DPRINTF_L4(DPRINT_MASK_USBAI
,
1874 "usb_pipe_intr_req: already polling");
1876 mutex_exit(&ph_data
->p_mutex
);
1877 usba_release_ph_data(ph_data
->p_ph_impl
);
1879 return (USB_FAILURE
);
1884 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1885 "usb_pipe_intr_req: pipe state %d", pipe_state
);
1887 mutex_exit(&ph_data
->p_mutex
);
1888 usba_release_ph_data(ph_data
->p_ph_impl
);
1890 return (USB_PIPE_ERROR
);
1893 /* we accept the request */
1894 wrp_usb_flags
= wrp
->wr_usb_flags
;
1895 ph_data
->p_req_count
++;
1897 mutex_exit(&ph_data
->p_mutex
);
1899 /* issue the request out */
1900 if ((rval
= usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_intr_xfer(ph_data
,
1901 req
, usb_flags
)) != USB_SUCCESS
) {
1903 /* the request failed, decrement the ref_count */
1904 if (req
->intr_completion_reason
== USB_CR_OK
) {
1905 req
->intr_completion_reason
= usba_rval2cr(rval
);
1907 mutex_enter(&ph_data
->p_mutex
);
1908 ASSERT(wrp
->wr_done
== B_FALSE
);
1909 ph_data
->p_req_count
--;
1910 ASSERT(ph_data
->p_req_count
>= 0);
1911 if ((ph_data
->p_req_count
== 0) &&
1912 (usba_get_ph_state(ph_data
) == USB_PIPE_STATE_ACTIVE
)) {
1913 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
1915 mutex_exit(&ph_data
->p_mutex
);
1917 /* if sleep specified, wait for completion */
1918 } else if (wrp_usb_flags
& USBA_WRP_FLAGS_WAIT
) {
1919 rval
= usba_pipe_sync_wait(ph_data
, wrp
);
1922 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1923 "usb_pipe_intr_req: rval=0x%x", rval
);
1925 usba_release_ph_data(ph_data
->p_ph_impl
);
1932 * usba_pipe_sync_stop_intr_polling:
1933 * - set up for sync transport, if necessary
1934 * - request HCD to stop polling
1935 * - wait for draining of all callbacks
1939 usba_pipe_sync_stop_intr_polling(dev_info_t
*dip
,
1940 usba_ph_impl_t
*ph_impl
,
1941 usba_pipe_async_req_t
*request
,
1945 usba_pipe_handle_data_t
*ph_data
;
1946 usba_device_t
*usba_device
;
1948 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1949 "usba_pipe_sync_stop_intr_polling: flags=0x%x", flags
);
1951 ph_data
= usba_get_ph_data((usb_pipe_handle_t
)ph_impl
);
1952 if (ph_data
== NULL
) {
1953 usba_release_ph_data(ph_impl
);
1954 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1955 "usba_pipe_sync_stop_intr_polling: pipe closed");
1957 return (USB_INVALID_PIPE
);
1960 usba_device
= ph_data
->p_usba_device
;
1962 mutex_enter(&ph_data
->p_mutex
);
1964 if (usba_get_ph_state(ph_data
) == USB_PIPE_STATE_ERROR
) {
1965 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1966 "usba_pipe_sync_stop_intr_polling: pipe error");
1967 mutex_exit(&ph_data
->p_mutex
);
1969 usba_release_ph_data(ph_impl
);
1971 return (USB_PIPE_ERROR
);
1974 if (usba_get_ph_state(ph_data
) == USB_PIPE_STATE_IDLE
) {
1975 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1976 "usba_pipe_sync_stop_intr_polling: already idle");
1977 mutex_exit(&ph_data
->p_mutex
);
1979 usba_release_ph_data(ph_impl
);
1981 return (USB_SUCCESS
);
1983 mutex_exit(&ph_data
->p_mutex
);
1985 mutex_enter(&ph_impl
->usba_ph_mutex
);
1986 ph_impl
->usba_ph_state_changing
++;
1987 mutex_exit(&ph_impl
->usba_ph_mutex
);
1989 flags
|= USB_FLAGS_SLEEP
;
1992 rval
= usba_device
->usb_hcdi_ops
->
1993 usba_hcdi_pipe_stop_intr_polling(ph_data
, flags
);
1996 * The host controller has stopped polling of the endpoint.
1997 * Now, drain the callbacks if there are any on the callback
2000 if (rval
== USB_SUCCESS
) {
2001 mutex_enter(&ph_data
->p_mutex
);
2004 * there is a tiny window that the client driver
2005 * may still have restarted the polling and we
2006 * have to let the stop polling win)
2008 rval
= usba_drain_cbs(ph_data
, 0,
2009 USB_CR_STOPPED_POLLING
);
2010 mutex_exit(&ph_data
->p_mutex
);
2011 if (rval
!= USB_SUCCESS
) {
2020 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2021 "usba_pipe_sync_stop_intr_polling: rval=0x%x", rval
);
2023 mutex_enter(&ph_impl
->usba_ph_mutex
);
2024 ph_impl
->usba_ph_state_changing
--;
2025 mutex_exit(&ph_impl
->usba_ph_mutex
);
2027 usba_release_ph_data(ph_impl
);
2034 * dummy callback function for stop polling
2037 usba_dummy_callback(
2038 usb_pipe_handle_t ph
,
2041 usb_cb_flags_t flags
)
2043 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2044 "usba_dummy_callback: "
2045 "ph=0x%p rval=0x%x flags=0x%x cb_arg=0x%p",
2046 (void *)ph
, rval
, flags
, (void *)arg
);
2051 * usb_pipe_stop_intr_polling:
2052 * stop polling for interrupt pipe IN data
2053 * The HCD doesn't do a usba_hcdi_cb().
2054 * It just returns success/failure
2056 * pipe_handle - pipe handle
2058 * USB_FLAGS_SLEEP: wait for completion
2061 usb_pipe_stop_intr_polling(usb_pipe_handle_t pipe_handle
,
2064 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
2066 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2067 "usba_pipe_stop_intr_polling: flags=0x%x", flags
);
2069 if (ph_data
== NULL
) {
2070 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2071 "usba_pipe_stop_intr_polling: pipe closed");
2076 if ((ph_data
->p_ep
.bmAttributes
&
2077 USB_EP_ATTR_MASK
) != USB_EP_ATTR_INTR
) {
2078 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2079 "usba_pipe_stop_intr_polling: wrong pipe type");
2081 usba_release_ph_data(ph_data
->p_ph_impl
);
2086 if ((ph_data
->p_ep
.bEndpointAddress
& USB_EP_DIR_IN
) == 0) {
2087 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2088 "usba_pipe_stop_intr_polling: wrong pipe direction");
2090 usba_release_ph_data(ph_data
->p_ph_impl
);
2095 if (servicing_interrupt() && (flags
& USB_FLAGS_SLEEP
)) {
2096 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2097 "usba_pipe_stop_intr_polling: invalid context");
2099 usba_release_ph_data(ph_data
->p_ph_impl
);
2104 (void) usba_pipe_setup_func_call(ph_data
->p_dip
,
2105 usba_pipe_sync_stop_intr_polling
,
2106 (usba_ph_impl_t
*)pipe_handle
, (usb_opaque_t
)flags
,
2107 flags
, usba_dummy_callback
, NULL
);
2112 * usb_alloc_isoc_req:
2113 * - Allocate usb isochronous resources that includes usb isochronous
2114 * request and array of packet descriptor structures and wrapper.
2117 * dip - dev_info_t of the client driver
2118 * isoc_pkts_count - number of isoc_pkt_descr_t's
2119 * len - length of "data" for this isochronous request
2121 * USB_FLAGS_SLEEP - Sleep if resources are not available
2122 * no USB_FLAGS_SLEEP - Don't Sleep if resources are not available
2125 * usb_isoc_req_t on success, NULL on failure
2129 usb_alloc_isoc_req(dev_info_t
*dip
,
2130 uint_t isoc_pkts_count
,
2134 usb_isoc_req_t
*isoc_req
= NULL
;
2135 usba_req_wrapper_t
*wrp
;
2136 size_t length
= sizeof (*isoc_req
) +
2137 (sizeof (usb_isoc_pkt_descr_t
) * isoc_pkts_count
);
2139 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2140 "usb_alloc_isoc_req: dip=0x%p pkt_cnt=%d len=%lu flags=0x%x",
2141 (void *)dip
, isoc_pkts_count
, len
, flags
);
2143 /* client needs to set isoc_pks_count */
2144 if (dip
&& isoc_pkts_count
) {
2145 /* Allocate + Initialize the usba_req_wrapper_t structure */
2146 if ((wrp
= usba_req_wrapper_alloc(dip
, length
, flags
)) !=
2148 isoc_req
= (usb_isoc_req_t
*)USBA_WRP2ISOC_REQ(wrp
);
2150 /* Allocate the usb_isoc_req data mblk */
2152 if ((isoc_req
->isoc_data
=
2153 allocb(len
, BPRI_HI
)) == NULL
) {
2154 usba_req_wrapper_free(wrp
);
2162 isoc_req
->isoc_pkt_descr
= (usb_isoc_pkt_descr_t
*)
2163 (((intptr_t)isoc_req
) + (sizeof (usb_isoc_req_t
)));
2165 /* Initialize all the fields of usb isochronous request */
2166 isoc_req
->isoc_pkts_count
= (ushort_t
)isoc_pkts_count
;
2169 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2170 "usb_alloc_isoc_req: isoc_req = 0x%p", (void *)isoc_req
);
2177 * usba_hcdi_dup_isoc_req:
2178 * create duplicate of isoc request
2181 * dip - devinfo pointer
2182 * reqp - original request pointer
2183 * len - length of "data" for this isoc request
2185 * USB_FLAGS_SLEEP - Sleep if resources are not available
2188 * usb_isoc_req_t on success, NULL on failure
2191 usba_hcdi_dup_isoc_req(
2193 usb_isoc_req_t
*reqp
,
2196 usb_isoc_req_t
*isoc_reqp
= NULL
;
2197 usba_req_wrapper_t
*isoc_wrp
, *req_wrp
;
2199 ushort_t isoc_pkts_count
;
2207 isoc_pkts_count
= reqp
->isoc_pkts_count
;
2209 /* calculate total data length required in original request */
2210 for (count
= length
= 0; count
< isoc_pkts_count
; count
++) {
2211 length
+= reqp
->isoc_pkt_descr
[count
].isoc_pkt_length
;
2214 req_wrp
= USBA_REQ2WRP(reqp
);
2216 if (((isoc_reqp
= usb_alloc_isoc_req(dip
,
2217 isoc_pkts_count
, length
, flags
)) != NULL
)) {
2218 isoc_reqp
->isoc_frame_no
= reqp
->isoc_frame_no
;
2219 isoc_reqp
->isoc_pkts_count
= reqp
->isoc_pkts_count
;
2220 isoc_reqp
->isoc_pkts_length
= reqp
->isoc_pkts_length
;
2221 isoc_reqp
->isoc_attributes
= reqp
->isoc_attributes
;
2222 isoc_reqp
->isoc_client_private
= reqp
->isoc_client_private
;
2223 isoc_reqp
->isoc_cb
= reqp
->isoc_cb
;
2224 isoc_reqp
->isoc_exc_cb
= reqp
->isoc_exc_cb
;
2226 isoc_wrp
= USBA_REQ2WRP(isoc_reqp
);
2227 isoc_wrp
->wr_dip
= req_wrp
->wr_dip
;
2228 isoc_wrp
->wr_ph_data
= req_wrp
->wr_ph_data
;
2229 isoc_wrp
->wr_attrs
= req_wrp
->wr_attrs
;
2230 isoc_wrp
->wr_usb_flags
= req_wrp
->wr_usb_flags
;
2232 for (count
= 0; count
< isoc_pkts_count
; count
++) {
2233 isoc_reqp
->isoc_pkt_descr
[count
].isoc_pkt_length
=
2234 reqp
->isoc_pkt_descr
[count
].isoc_pkt_length
;
2243 * usb_free_isoc_req:
2244 * - Deallocate usb isochronous resources that includes usb isochronous
2245 * request and array of packet descriptor strcutures.
2248 * req - pointer to usb_isoc_req_t
2251 usb_free_isoc_req(usb_isoc_req_t
*req
)
2254 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2255 "usb_free_isoc_req: req=0x%p", (void *)req
);
2257 if (req
->isoc_data
) {
2258 freemsg(req
->isoc_data
);
2261 usba_req_wrapper_free(USBA_REQ2WRP(req
));
2267 * usb_get_current_frame_number:
2268 * - request HCD to return current usb frame number
2271 * dip - pointer to dev_info_t
2274 * current_frame_number - request successfully executed
2275 * 0 - request failed
2278 usb_get_current_frame_number(dev_info_t
*dip
)
2280 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2281 "usb_get_current_frame_number: dip=0x%p", (void *)dip
);
2284 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
2285 usb_frame_number_t frame_number
;
2287 if (usba_device
->usb_hcdi_ops
->
2288 usba_hcdi_get_current_frame_number
) {
2290 if (usba_device
->usb_hcdi_ops
->
2291 usba_hcdi_get_current_frame_number(usba_device
,
2292 &frame_number
) == USB_SUCCESS
) {
2294 return (frame_number
);
2304 * usb_get_max_isoc_pkts:
2305 * - request HCD to return maximum isochronous packets per request
2308 * dip - pointer to dev_info_t
2311 * isoc_pkt - request successfully executed
2312 * 0 - request failed
2315 usb_get_max_isoc_pkts(dev_info_t
*dip
)
2317 return (usb_get_max_pkts_per_isoc_request(dip
));
2322 usb_get_max_pkts_per_isoc_request(dev_info_t
*dip
)
2325 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
2326 uint_t max_isoc_pkts_per_request
;
2328 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2329 "usb_get_max_isoc_pkts: usba_device=0x%p",
2330 (void *)usba_device
);
2332 if (usba_device
->usb_hcdi_ops
->usba_hcdi_get_max_isoc_pkts
) {
2334 if (usba_device
->usb_hcdi_ops
->
2335 usba_hcdi_get_max_isoc_pkts(usba_device
,
2336 &max_isoc_pkts_per_request
) == USB_SUCCESS
) {
2338 return (max_isoc_pkts_per_request
);
2348 * usb_pipe_isoc_xfer:
2349 * - check for pipe stalled
2350 * - request HCD to transport isoc data asynchronously
2353 * pipe_handle - isoc pipe pipehandle (obtained via usb_pipe_open())
2354 * req - isochronous request
2357 * USB_SUCCESS - request successfully executed
2358 * USB_FAILURE - request failed
2361 usb_pipe_isoc_xfer(usb_pipe_handle_t pipe_handle
,
2362 usb_isoc_req_t
*req
,
2366 usba_req_wrapper_t
*wrp
= USBA_REQ2WRP(req
);
2367 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
2368 usba_device_t
*usba_device
;
2370 usb_pipe_state_t pipe_state
;
2372 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2373 "usb_pipe_isoc_xfer: flags=0x%x", flags
);
2375 if (ph_data
== NULL
) {
2377 return (USB_INVALID_PIPE
);
2380 usba_device
= ph_data
->p_usba_device
;
2381 direction
= ph_data
->p_ep
.bEndpointAddress
& USB_EP_DIR_MASK
;
2383 mutex_enter(&ph_data
->p_mutex
);
2384 if ((rval
= usba_check_req(ph_data
, (usb_opaque_t
)req
, flags
,
2385 USB_EP_ATTR_ISOCH
)) != USB_SUCCESS
) {
2386 mutex_exit(&ph_data
->p_mutex
);
2388 usba_release_ph_data(ph_data
->p_ph_impl
);
2393 req
->isoc_error_count
= 0;
2395 /* Get the current isoch pipe state */
2396 pipe_state
= usba_get_ph_state(ph_data
);
2398 switch (pipe_state
) {
2399 case USB_PIPE_STATE_IDLE
:
2400 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_ACTIVE
);
2402 case USB_PIPE_STATE_ACTIVE
:
2403 if (direction
== USB_EP_DIR_IN
) {
2404 USB_DPRINTF_L4(DPRINT_MASK_USBAI
,
2406 "usb_pipe_isoc_req: already polling");
2408 mutex_exit(&ph_data
->p_mutex
);
2409 usba_release_ph_data(ph_data
->p_ph_impl
);
2411 return (USB_FAILURE
);
2415 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2416 "usb_pipe_isoc_req: pipe state %d", pipe_state
);
2418 mutex_exit(&ph_data
->p_mutex
);
2419 usba_release_ph_data(ph_data
->p_ph_impl
);
2421 return (USB_PIPE_ERROR
);
2424 /* we accept the request */
2425 ph_data
->p_req_count
++;
2426 mutex_exit(&ph_data
->p_mutex
);
2428 if ((rval
= usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_isoc_xfer(
2429 ph_data
, req
, flags
)) != USB_SUCCESS
) {
2430 if (req
->isoc_completion_reason
== USB_CR_OK
) {
2431 req
->isoc_completion_reason
= usba_rval2cr(rval
);
2433 mutex_enter(&ph_data
->p_mutex
);
2434 ASSERT(wrp
->wr_done
== B_FALSE
);
2435 ph_data
->p_req_count
--;
2436 if ((ph_data
->p_req_count
== 0) &&
2437 (usba_get_ph_state(ph_data
) == USB_PIPE_STATE_ACTIVE
)) {
2438 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
2440 mutex_exit(&ph_data
->p_mutex
);
2443 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2444 "usb_pipe_isoc_req: rval=%x", rval
);
2446 usba_release_ph_data(ph_data
->p_ph_impl
);
2453 * usba_pipe_sync_stop_isoc_polling:
2454 * - set up for sync transport, if necessary
2455 * - request HCD to stop polling
2456 * - wait for draining of all callbacks
2459 * dip - dev_info pointer
2460 * pipe_handle - pointer to pipe handle
2461 * flags - USB_FLAGS_SLEEP: wait for completion
2465 usba_pipe_sync_stop_isoc_polling(dev_info_t
*dip
,
2466 usba_ph_impl_t
*ph_impl
,
2467 usba_pipe_async_req_t
*request
,
2471 usba_pipe_handle_data_t
*ph_data
= usba_get_ph_data(
2472 (usb_pipe_handle_t
)ph_impl
);
2473 usba_device_t
*usba_device
;
2475 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2476 "usba_pipe_sync_stop_isoc_polling: uf=0x%x", flags
);
2478 if (ph_data
== NULL
) {
2479 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2480 "usba_pipe_stop_isoc_polling: pipe closed");
2482 return (USB_INVALID_PIPE
);
2485 usba_device
= ph_data
->p_usba_device
;
2487 mutex_enter(&ph_data
->p_mutex
);
2489 if (usba_get_ph_state(ph_data
) == USB_PIPE_STATE_ERROR
) {
2490 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2491 "usba_pipe_sync_stop_isoc_polling: pipe error");
2492 mutex_exit(&ph_data
->p_mutex
);
2494 usba_release_ph_data(ph_impl
);
2496 return (USB_PIPE_ERROR
);
2499 if (usba_get_ph_state(ph_data
) == USB_PIPE_STATE_IDLE
) {
2500 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2501 "usba_pipe_sync_stop_isoc_polling: already stopped");
2502 mutex_exit(&ph_data
->p_mutex
);
2504 usba_release_ph_data(ph_impl
);
2506 return (USB_SUCCESS
);
2510 mutex_exit(&ph_data
->p_mutex
);
2512 flags
|= USB_FLAGS_SLEEP
;
2515 rval
= usba_device
->usb_hcdi_ops
->
2516 usba_hcdi_pipe_stop_isoc_polling(ph_data
, flags
);
2519 * The host controller has stopped polling of the endpoint.
2520 * Now, drain the callbacks if there are any on the callback
2523 if (rval
== USB_SUCCESS
) {
2524 mutex_enter(&ph_data
->p_mutex
);
2527 * there is a tiny window that the client driver
2528 * may still have restarted the polling and we
2529 * let the stop polling win
2531 rval
= usba_drain_cbs(ph_data
, 0,
2532 USB_CR_STOPPED_POLLING
);
2533 mutex_exit(&ph_data
->p_mutex
);
2534 if (rval
!= USB_SUCCESS
) {
2543 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2544 "usba_pipe_sync_stop_isoc_polling: rval=0x%x", rval
);
2546 usba_release_ph_data(ph_impl
);
2553 * usb_pipe_stop_isoc_polling:
2554 * stop polling for isoc IN data
2557 * pipe_handle - pipe handle
2559 * USB_FLAGS_SLEEP: wait for completion
2562 usb_pipe_stop_isoc_polling(usb_pipe_handle_t pipe_handle
,
2565 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
2567 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
2568 "usba_pipe_stop_isoc_polling: uf=0x%x", flags
);
2570 if (ph_data
== NULL
) {
2571 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2572 "usba_pipe_stop_isoc_polling: pipe closed");
2577 if ((ph_data
->p_ep
.bmAttributes
& USB_EP_ATTR_MASK
) !=
2578 USB_EP_ATTR_ISOCH
) {
2579 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2580 "usba_pipe_stop_isoc_polling: wrong pipe type");
2582 usba_release_ph_data(ph_data
->p_ph_impl
);
2586 if ((ph_data
->p_ep
.bEndpointAddress
& USB_EP_DIR_IN
) == 0) {
2587 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2588 "usba_pipe_stop_isoc_polling: wrong pipe direction");
2590 usba_release_ph_data(ph_data
->p_ph_impl
);
2595 if (servicing_interrupt() && (flags
& USB_FLAGS_SLEEP
)) {
2596 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
2597 "usba_pipe_stop_intr_polling: invalid context");
2599 usba_release_ph_data(ph_data
->p_ph_impl
);
2604 (void) usba_pipe_setup_func_call(ph_data
->p_dip
,
2605 usba_pipe_sync_stop_isoc_polling
,
2606 (usba_ph_impl_t
*)pipe_handle
, (usb_opaque_t
)flags
,
2607 flags
, usba_dummy_callback
, NULL
);