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.
25 * Copyright 2016 Joyent, Inc.
29 * USBA: Solaris USB Architecture support
31 * hcdi.c contains the code for client driver callbacks. A host controller
32 * driver registers/unregisters with usba through usba_hcdi_register/unregister.
34 * When the transfer has finished, the host controller driver will call into
35 * usba with the result. The call is usba_hcdi_cb().
37 * The callback queue is maintained in FIFO order. usba_hcdi_cb
38 * adds to the queue, and hcdi_cb_thread takes the callbacks off the queue
41 #define USBA_FRAMEWORK
42 #include <sys/usb/usba/usba_impl.h>
43 #include <sys/usb/usba/hcdi_impl.h>
44 #include <sys/kstat.h>
45 #include <sys/ddi_impldefs.h>
47 /* function prototypes, XXXX use hcdi_ prefix? */
48 static void usba_hcdi_create_stats(usba_hcdi_t
*, int);
49 static void usba_hcdi_update_error_stats(usba_hcdi_t
*, usb_cr_t
);
50 static void usba_hcdi_destroy_stats(usba_hcdi_t
*);
52 /* internal functions */
53 static uint_t
hcdi_soft_intr(caddr_t arg1
, caddr_t arg2
);
55 static void hcdi_cb_thread(void *);
56 static void hcdi_shared_cb_thread(void *);
57 static void hcdi_do_cb(usba_pipe_handle_data_t
*, usba_req_wrapper_t
*,
59 static void hcdi_autoclearing(usba_req_wrapper_t
*);
61 /* private function from USBAI */
62 void usba_pipe_clear(usb_pipe_handle_t
);
64 /* for debug messages */
65 uint_t hcdi_errmask
= (uint_t
)DPRINT_MASK_ALL
;
66 uint_t hcdi_errlevel
= USB_LOG_L4
;
67 uint_t hcdi_instance_debug
= (uint_t
)-1;
70 usba_hcdi_initialization()
82 * store hcdi structure in the dip
85 usba_hcdi_set_hcdi(dev_info_t
*dip
, usba_hcdi_t
*hcdi
)
87 ddi_set_driver_private(dip
, hcdi
);
92 * retrieve hcdi structure from the dip
95 usba_hcdi_get_hcdi(dev_info_t
*dip
)
97 return (ddi_get_driver_private(dip
));
101 * Called by an HCD to attach an instance of the driver
102 * make this instance known to USBA
103 * the HCD should initialize usba_hcdi structure prior
104 * to calling this interface
107 usba_hcdi_register(usba_hcdi_register_args_t
*args
, uint_t flags
)
111 usba_hcdi_t
*hcdi
= kmem_zalloc(sizeof (usba_hcdi_t
), KM_SLEEP
);
113 if (args
->usba_hcdi_register_version
!= HCDI_REGISTER_VERS_0
) {
114 kmem_free(hcdi
, sizeof (usba_hcdi_t
));
116 return (USB_FAILURE
);
119 hcdi
->hcdi_dip
= args
->usba_hcdi_register_dip
;
122 * The hcd driver cannot use private data as we're going to store our
123 * data there. If it does, fail the registration immediately.
125 if (ddi_get_driver_private(hcdi
->hcdi_dip
) != NULL
) {
126 cmn_err(CE_WARN
, "failed attempt to register USB hcd, "
127 "detected private data!");
128 kmem_free(hcdi
, sizeof (usba_hcdi_t
));
130 return (USB_FAILURE
);
135 * Create a log_handle
137 hcdi
->hcdi_log_handle
= usb_alloc_log_hdl(hcdi
->hcdi_dip
, NULL
,
138 &hcdi_errlevel
, &hcdi_errmask
, &hcdi_instance_debug
,
141 USB_DPRINTF_L4(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
142 "usba_hcdi_register: %s", ddi_node_name(hcdi
->hcdi_dip
));
145 * Initialize the mutex. Use the iblock cookie passed in
146 * by the host controller driver.
148 mutex_init(&hcdi
->hcdi_mutex
, NULL
, MUTEX_DRIVER
,
149 args
->usba_hcdi_register_iblock_cookie
);
151 /* add soft interrupt */
152 if (ddi_intr_add_softint(hcdi
->hcdi_dip
, &hcdi
->hcdi_softint_hdl
,
153 DDI_INTR_SOFTPRI_MAX
, hcdi_soft_intr
, (caddr_t
)hcdi
) !=
155 USB_DPRINTF_L2(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
156 "usba_hcd_register: add soft interrupt failed");
157 mutex_destroy(&hcdi
->hcdi_mutex
);
158 usb_free_log_hdl(hcdi
->hcdi_log_handle
);
159 kmem_free(hcdi
, sizeof (usba_hcdi_t
));
161 return (USB_FAILURE
);
164 if (ddi_intr_get_softint_pri(hcdi
->hcdi_softint_hdl
, &soft_prip
) !=
166 USB_DPRINTF_L2(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
167 "usba_hcd_register: get soft interrupt priority failed");
168 (void) ddi_intr_remove_softint(hcdi
->hcdi_softint_hdl
);
169 mutex_destroy(&hcdi
->hcdi_mutex
);
170 usb_free_log_hdl(hcdi
->hcdi_log_handle
);
171 kmem_free(hcdi
, sizeof (usba_hcdi_t
));
173 return (USB_FAILURE
);
177 * Priority and iblock_cookie are one and the same
178 * (However, retaining hcdi_soft_iblock_cookie for now
179 * assigning it w/ priority. In future all iblock_cookie
182 hcdi
->hcdi_soft_iblock_cookie
=
183 (ddi_iblock_cookie_t
)(uintptr_t)soft_prip
;
185 usba_init_list(&hcdi
->hcdi_cb_queue
, NULL
, NULL
);
187 hcdi
->hcdi_dma_attr
= args
->usba_hcdi_register_dma_attr
;
188 hcdi
->hcdi_flags
= flags
;
189 hcdi
->hcdi_ops
= args
->usba_hcdi_register_ops
;
190 hcdi
->hcdi_iblock_cookie
= args
->usba_hcdi_register_iblock_cookie
;
191 usba_hcdi_create_stats(hcdi
, ddi_get_instance(hcdi
->hcdi_dip
));
193 hcdi
->hcdi_min_xfer
= hcdi
->hcdi_dma_attr
->dma_attr_minxfer
;
194 hcdi
->hcdi_min_burst_size
=
195 (1<<(ddi_ffs(hcdi
->hcdi_dma_attr
->dma_attr_burstsizes
)-1));
196 hcdi
->hcdi_max_burst_size
=
197 (1<<(ddi_fls(hcdi
->hcdi_dma_attr
->dma_attr_burstsizes
)-1));
199 usba_hcdi_set_hcdi(hcdi
->hcdi_dip
, hcdi
);
201 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
,
203 DDI_PROP_DONTPASS
, "ugen-default-binding", &datap
) ==
205 if (strcmp(datap
, "device") == 0) {
206 hcdi
->hcdi_ugen_default_binding
=
207 USBA_UGEN_DEVICE_BINDING
;
208 } else if (strcmp(datap
, "interface") == 0) {
209 hcdi
->hcdi_ugen_default_binding
=
210 USBA_UGEN_INTERFACE_BINDING
;
211 } else if (strcmp(datap
, "interface-association") == 0) {
212 hcdi
->hcdi_ugen_default_binding
=
213 USBA_UGEN_INTERFACE_ASSOCIATION_BINDING
;
215 USB_DPRINTF_L2(DPRINT_MASK_HCDI
,
216 hcdi
->hcdi_log_handle
,
217 "illegal value (%s) for "
218 "ugen_default_binding property",
221 ddi_prop_free(datap
);
224 return (USB_SUCCESS
);
229 * Called by an HCD to detach an instance of the driver
233 usba_hcdi_unregister(dev_info_t
*dip
)
235 usba_hcdi_t
*hcdi
= usba_hcdi_get_hcdi(dip
);
238 USB_DPRINTF_L4(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
239 "usba_hcdi_unregister: %s", ddi_node_name(dip
));
241 usba_hcdi_set_hcdi(dip
, NULL
);
243 mutex_destroy(&hcdi
->hcdi_mutex
);
244 usba_hcdi_destroy_stats(hcdi
);
245 usb_free_log_hdl(hcdi
->hcdi_log_handle
);
247 /* Destroy the soft interrupt */
248 (void) ddi_intr_remove_softint(hcdi
->hcdi_softint_hdl
);
249 kmem_free(hcdi
, sizeof (usba_hcdi_t
));
255 * alloc usba_hcdi_ops structure
256 * called from the HCD attach routine
259 usba_alloc_hcdi_ops()
261 usba_hcdi_ops_t
*usba_hcdi_ops
;
263 usba_hcdi_ops
= kmem_zalloc(sizeof (usba_hcdi_ops_t
), KM_SLEEP
);
265 return (usba_hcdi_ops
);
270 * dealloc usba_hcdi_ops structure
273 usba_free_hcdi_ops(usba_hcdi_ops_t
*hcdi_ops
)
276 kmem_free(hcdi_ops
, sizeof (usba_hcdi_ops_t
));
282 * Allocate the hotplug kstats structure
285 usba_hcdi_create_stats(usba_hcdi_t
*hcdi
, int instance
)
287 char kstatname
[KSTAT_STRLEN
];
288 const char *dname
= ddi_driver_name(hcdi
->hcdi_dip
);
289 hcdi_hotplug_stats_t
*hsp
;
290 hcdi_error_stats_t
*esp
;
292 if (HCDI_HOTPLUG_STATS(hcdi
) == NULL
) {
293 (void) snprintf(kstatname
, KSTAT_STRLEN
, "%s%d,hotplug",
295 HCDI_HOTPLUG_STATS(hcdi
) = kstat_create("usba", instance
,
296 kstatname
, "usb_hotplug", KSTAT_TYPE_NAMED
,
297 sizeof (hcdi_hotplug_stats_t
) / sizeof (kstat_named_t
),
298 KSTAT_FLAG_PERSISTENT
);
300 if (HCDI_HOTPLUG_STATS(hcdi
) == NULL
) {
305 hsp
= HCDI_HOTPLUG_STATS_DATA(hcdi
);
306 kstat_named_init(&hsp
->hcdi_hotplug_total_success
,
307 "Total Hotplug Successes", KSTAT_DATA_UINT64
);
308 kstat_named_init(&hsp
->hcdi_hotplug_success
,
309 "Hotplug Successes", KSTAT_DATA_UINT64
);
310 kstat_named_init(&hsp
->hcdi_hotplug_total_failure
,
311 "Hotplug Total Failures", KSTAT_DATA_UINT64
);
312 kstat_named_init(&hsp
->hcdi_hotplug_failure
,
313 "Hotplug Failures", KSTAT_DATA_UINT64
);
314 kstat_named_init(&hsp
->hcdi_device_count
,
315 "Device Count", KSTAT_DATA_UINT64
);
317 HCDI_HOTPLUG_STATS(hcdi
)->ks_private
= hcdi
;
318 HCDI_HOTPLUG_STATS(hcdi
)->ks_update
= nulldev
;
319 kstat_install(HCDI_HOTPLUG_STATS(hcdi
));
322 if (HCDI_ERROR_STATS(hcdi
) == NULL
) {
323 (void) snprintf(kstatname
, KSTAT_STRLEN
, "%s%d,error",
325 HCDI_ERROR_STATS(hcdi
) = kstat_create("usba", instance
,
326 kstatname
, "usb_errors", KSTAT_TYPE_NAMED
,
327 sizeof (hcdi_error_stats_t
) / sizeof (kstat_named_t
),
328 KSTAT_FLAG_PERSISTENT
);
330 if (HCDI_ERROR_STATS(hcdi
) == NULL
) {
335 esp
= HCDI_ERROR_STATS_DATA(hcdi
);
336 kstat_named_init(&esp
->cc_crc
, "CRC Errors", KSTAT_DATA_UINT64
);
337 kstat_named_init(&esp
->cc_bitstuffing
,
338 "Bit Stuffing Violations", KSTAT_DATA_UINT64
);
339 kstat_named_init(&esp
->cc_data_toggle_mm
,
340 "Data Toggle PID Errors", KSTAT_DATA_UINT64
);
341 kstat_named_init(&esp
->cc_stall
,
342 "Endpoint Stalls", KSTAT_DATA_UINT64
);
343 kstat_named_init(&esp
->cc_dev_not_resp
,
344 "Device Not Responding", KSTAT_DATA_UINT64
);
345 kstat_named_init(&esp
->cc_pid_checkfailure
,
346 "PID Check Bit Errors", KSTAT_DATA_UINT64
);
347 kstat_named_init(&esp
->cc_unexp_pid
,
348 "Invalid PID Errors", KSTAT_DATA_UINT64
);
349 kstat_named_init(&esp
->cc_data_overrun
,
350 "Data Overruns", KSTAT_DATA_UINT64
);
351 kstat_named_init(&esp
->cc_data_underrun
,
352 "Data Underruns", KSTAT_DATA_UINT64
);
353 kstat_named_init(&esp
->cc_buffer_overrun
,
354 "Buffer Overruns", KSTAT_DATA_UINT64
);
355 kstat_named_init(&esp
->cc_buffer_underrun
,
356 "Buffer Underruns", KSTAT_DATA_UINT64
);
357 kstat_named_init(&esp
->cc_timeout
,
358 "Command Timed Out", KSTAT_DATA_UINT64
);
359 kstat_named_init(&esp
->cc_not_accessed
,
360 "Not Accessed By Hardware", KSTAT_DATA_UINT64
);
361 kstat_named_init(&esp
->cc_no_resources
,
362 "No Resources", KSTAT_DATA_UINT64
);
363 kstat_named_init(&esp
->cc_unspecified_err
,
364 "Unspecified Error", KSTAT_DATA_UINT64
);
365 kstat_named_init(&esp
->cc_stopped_polling
,
366 "Stopped Polling", KSTAT_DATA_UINT64
);
367 kstat_named_init(&esp
->cc_pipe_closing
,
368 "Pipe Closing", KSTAT_DATA_UINT64
);
369 kstat_named_init(&esp
->cc_pipe_reset
,
370 "Pipe Reset", KSTAT_DATA_UINT64
);
371 kstat_named_init(&esp
->cc_not_supported
,
372 "Command Not Supported", KSTAT_DATA_UINT64
);
373 kstat_named_init(&esp
->cc_flushed
,
374 "Request Flushed", KSTAT_DATA_UINT64
);
376 HCDI_ERROR_STATS(hcdi
)->ks_private
= hcdi
;
377 HCDI_ERROR_STATS(hcdi
)->ks_update
= nulldev
;
378 kstat_install(HCDI_ERROR_STATS(hcdi
));
384 * Do actual error stats
387 usba_hcdi_update_error_stats(usba_hcdi_t
*hcdi
, usb_cr_t completion_reason
)
389 if (HCDI_ERROR_STATS(hcdi
) == NULL
) {
394 switch (completion_reason
) {
398 HCDI_ERROR_STATS_DATA(hcdi
)->cc_crc
.value
.ui64
++;
400 case USB_CR_BITSTUFFING
:
401 HCDI_ERROR_STATS_DATA(hcdi
)->cc_bitstuffing
.value
.ui64
++;
403 case USB_CR_DATA_TOGGLE_MM
:
404 HCDI_ERROR_STATS_DATA(hcdi
)->cc_data_toggle_mm
.value
.ui64
++;
407 HCDI_ERROR_STATS_DATA(hcdi
)->cc_stall
.value
.ui64
++;
409 case USB_CR_DEV_NOT_RESP
:
410 HCDI_ERROR_STATS_DATA(hcdi
)->cc_dev_not_resp
.value
.ui64
++;
412 case USB_CR_PID_CHECKFAILURE
:
413 HCDI_ERROR_STATS_DATA(hcdi
)->cc_pid_checkfailure
.value
.ui64
++;
415 case USB_CR_UNEXP_PID
:
416 HCDI_ERROR_STATS_DATA(hcdi
)->cc_unexp_pid
.value
.ui64
++;
418 case USB_CR_DATA_OVERRUN
:
419 HCDI_ERROR_STATS_DATA(hcdi
)->cc_data_overrun
.value
.ui64
++;
421 case USB_CR_DATA_UNDERRUN
:
422 HCDI_ERROR_STATS_DATA(hcdi
)->cc_data_underrun
.value
.ui64
++;
424 case USB_CR_BUFFER_OVERRUN
:
425 HCDI_ERROR_STATS_DATA(hcdi
)->cc_buffer_overrun
.value
.ui64
++;
427 case USB_CR_BUFFER_UNDERRUN
:
428 HCDI_ERROR_STATS_DATA(hcdi
)->cc_buffer_underrun
.value
.ui64
++;
431 HCDI_ERROR_STATS_DATA(hcdi
)->cc_timeout
.value
.ui64
++;
433 case USB_CR_NOT_ACCESSED
:
434 HCDI_ERROR_STATS_DATA(hcdi
)->cc_not_accessed
.value
.ui64
++;
436 case USB_CR_NO_RESOURCES
:
437 HCDI_ERROR_STATS_DATA(hcdi
)->cc_no_resources
.value
.ui64
++;
439 case USB_CR_UNSPECIFIED_ERR
:
440 HCDI_ERROR_STATS_DATA(hcdi
)->cc_unspecified_err
.value
.ui64
++;
442 case USB_CR_STOPPED_POLLING
:
443 HCDI_ERROR_STATS_DATA(hcdi
)->cc_stopped_polling
.value
.ui64
++;
445 case USB_CR_PIPE_CLOSING
:
446 HCDI_ERROR_STATS_DATA(hcdi
)->cc_pipe_closing
.value
.ui64
++;
448 case USB_CR_PIPE_RESET
:
449 HCDI_ERROR_STATS_DATA(hcdi
)->cc_pipe_reset
.value
.ui64
++;
451 case USB_CR_NOT_SUPPORTED
:
452 HCDI_ERROR_STATS_DATA(hcdi
)->cc_not_supported
.value
.ui64
++;
455 HCDI_ERROR_STATS_DATA(hcdi
)->cc_flushed
.value
.ui64
++;
464 * Destroy the hotplug kstats structure
467 usba_hcdi_destroy_stats(usba_hcdi_t
*hcdi
)
469 if (HCDI_HOTPLUG_STATS(hcdi
)) {
470 kstat_delete(HCDI_HOTPLUG_STATS(hcdi
));
471 HCDI_HOTPLUG_STATS(hcdi
) = NULL
;
474 if (HCDI_ERROR_STATS(hcdi
)) {
475 kstat_delete(HCDI_ERROR_STATS(hcdi
));
476 HCDI_ERROR_STATS(hcdi
) = NULL
;
482 * HCD callback handling
485 usba_hcdi_cb(usba_pipe_handle_data_t
*ph_data
, usb_opaque_t req
,
486 usb_cr_t completion_reason
)
489 usba_device_t
*usba_device
= ph_data
->p_usba_device
;
490 usba_hcdi_t
*hcdi
= usba_hcdi_get_hcdi(
491 usba_device
->usb_root_hub_dip
);
492 usba_req_wrapper_t
*req_wrp
= USBA_REQ2WRP(req
);
493 usb_ep_descr_t
*eptd
= &ph_data
->p_ep
;
495 mutex_enter(&ph_data
->p_mutex
);
498 mutex_enter(&ph_data
->p_ph_impl
->usba_ph_mutex
);
500 USB_DPRINTF_L4(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
502 "ph_data=0x%p req=0x%p state=%d ref=%d cnt=%d cr=%d",
503 (void *)ph_data
, (void *)req
, ph_data
->p_ph_impl
->usba_ph_state
,
504 ph_data
->p_ph_impl
->usba_ph_ref_count
, ph_data
->p_req_count
,
507 mutex_exit(&ph_data
->p_ph_impl
->usba_ph_mutex
);
510 /* Set the completion reason */
511 switch (eptd
->bmAttributes
& USB_EP_ATTR_MASK
) {
512 case USB_EP_ATTR_CONTROL
:
513 ((usb_ctrl_req_t
*)req
)->
514 ctrl_completion_reason
= completion_reason
;
516 case USB_EP_ATTR_BULK
:
517 ((usb_bulk_req_t
*)req
)->
518 bulk_completion_reason
= completion_reason
;
520 case USB_EP_ATTR_INTR
:
521 ((usb_intr_req_t
*)req
)->
522 intr_completion_reason
= completion_reason
;
524 case USB_EP_ATTR_ISOCH
:
525 ((usb_isoc_req_t
*)req
)->
526 isoc_completion_reason
= completion_reason
;
531 * exception callbacks will still go thru a taskq thread
532 * but should occur after the soft interrupt callback
533 * By design of periodic pipes, polling will stop on any
536 if ((ph_data
->p_spec_flag
& USBA_PH_FLAG_USE_SOFT_INTR
) &&
537 (completion_reason
== USB_CR_OK
)) {
538 ph_data
->p_soft_intr
++;
539 mutex_exit(&ph_data
->p_mutex
);
541 usba_add_to_list(&hcdi
->hcdi_cb_queue
, &req_wrp
->wr_queue
);
543 if (ddi_intr_trigger_softint(hcdi
->hcdi_softint_hdl
, NULL
) !=
545 USB_DPRINTF_L2(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
546 "usba_hcdi_cb: ddi_intr_trigger_softint failed");
552 * USBA_PH_FLAG_TQ_SHARE is for bulk and intr requests,
553 * USBA_PH_FLAG_USE_SOFT_INTR is only for isoch,
554 * so there are no conflicts.
556 if (ph_data
->p_spec_flag
& USBA_PH_FLAG_TQ_SHARE
) {
559 mutex_exit(&ph_data
->p_mutex
);
560 iface
= usb_get_if_number(ph_data
->p_dip
);
562 /* we own the device, use the first taskq */
565 if (taskq_dispatch(usba_device
->usb_shared_taskq
[iface
],
566 hcdi_shared_cb_thread
, req_wrp
, TQ_NOSLEEP
) ==
568 usba_req_exc_cb(req_wrp
,
569 USB_CR_NO_RESOURCES
, USB_CB_ASYNC_REQ_FAILED
);
575 /* Add the callback to the pipehandles callback list */
576 usba_add_to_list(&ph_data
->p_cb_queue
, &req_wrp
->wr_queue
);
578 /* only dispatch if there is no thread running */
579 if (ph_data
->p_thread_id
== 0) {
580 if (usba_async_ph_req(ph_data
, hcdi_cb_thread
,
581 ph_data
, USB_FLAGS_NOSLEEP
) != USB_SUCCESS
) {
582 USB_DPRINTF_L2(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
583 "usba_hcdi_cb: taskq_dispatch failed");
584 if (usba_rm_from_list(&ph_data
->p_cb_queue
,
585 &req_wrp
->wr_queue
) == USB_SUCCESS
) {
586 mutex_exit(&ph_data
->p_mutex
);
587 usba_req_exc_cb(req_wrp
,
589 USB_CB_ASYNC_REQ_FAILED
);
594 ph_data
->p_thread_id
= (kthread_t
*)1;
597 mutex_exit(&ph_data
->p_mutex
);
602 * thread to perform the callbacks
605 hcdi_cb_thread(void *arg
)
607 usba_pipe_handle_data_t
*ph_data
=
608 (usba_pipe_handle_data_t
*)arg
;
609 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
610 usba_hcdi_t
*hcdi
= usba_hcdi_get_hcdi(ph_data
->
611 p_usba_device
->usb_root_hub_dip
);
612 usba_req_wrapper_t
*req_wrp
;
614 mutex_enter(&ph_data
->p_mutex
);
615 ASSERT(ph_data
->p_thread_id
== (kthread_t
*)1);
616 ph_data
->p_thread_id
= curthread
;
619 * hold the ph_data. we can't use usba_hold_ph_data() since
620 * it will return NULL if we are closing the pipe which would
621 * then leave all requests stuck in the cb_queue
623 mutex_enter(&ph_impl
->usba_ph_mutex
);
624 ph_impl
->usba_ph_ref_count
++;
626 USB_DPRINTF_L4(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
627 "hcdi_cb_thread: ph_data=0x%p ref=%d", (void *)ph_data
,
628 ph_impl
->usba_ph_ref_count
);
630 mutex_exit(&ph_impl
->usba_ph_mutex
);
633 * wait till soft interrupt callbacks are taken care of
635 while (ph_data
->p_soft_intr
) {
636 mutex_exit(&ph_data
->p_mutex
);
638 mutex_enter(&ph_data
->p_mutex
);
641 while ((req_wrp
= (usba_req_wrapper_t
*)
642 usba_rm_first_pvt_from_list(&ph_data
->p_cb_queue
)) != NULL
) {
643 hcdi_do_cb(ph_data
, req_wrp
, hcdi
);
646 ph_data
->p_thread_id
= 0;
647 mutex_exit(&ph_data
->p_mutex
);
649 USB_DPRINTF_L4(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
650 "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data
);
652 usba_release_ph_data(ph_impl
);
657 hcdi_do_cb(usba_pipe_handle_data_t
*ph_data
, usba_req_wrapper_t
*req_wrp
,
660 usb_cr_t completion_reason
;
661 usb_req_attrs_t attrs
= req_wrp
->wr_attrs
;
663 switch (req_wrp
->wr_ph_data
->p_ep
.bmAttributes
&
665 case USB_EP_ATTR_CONTROL
:
667 USBA_WRP2CTRL_REQ(req_wrp
)->ctrl_completion_reason
;
669 case USB_EP_ATTR_INTR
:
671 USBA_WRP2INTR_REQ(req_wrp
)->intr_completion_reason
;
673 case USB_EP_ATTR_BULK
:
675 USBA_WRP2BULK_REQ(req_wrp
)->bulk_completion_reason
;
677 case USB_EP_ATTR_ISOCH
:
679 USBA_WRP2ISOC_REQ(req_wrp
)->isoc_completion_reason
;
682 req_wrp
->wr_cr
= completion_reason
;
684 USB_DPRINTF_L4(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
685 "hcdi_do_cb: wrp=0x%p cr=0x%x", (void *)req_wrp
, completion_reason
);
690 if (completion_reason
== USB_CR_OK
) {
691 mutex_exit(&ph_data
->p_mutex
);
692 usba_req_normal_cb(req_wrp
);
693 mutex_enter(&ph_data
->p_mutex
);
695 usb_pipe_state_t pipe_state
;
697 USB_DPRINTF_L4(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
698 "exception callback handling: attrs=0x%x", attrs
);
701 * In exception callback handling, if we were
702 * not able to clear stall, we need to modify
703 * pipe state. Also if auto-clearing is not set
704 * pipe state needs to be modified.
706 pipe_state
= usba_get_ph_state(ph_data
);
708 if (!USBA_PIPE_CLOSING(pipe_state
)) {
709 switch (completion_reason
) {
710 case USB_CR_STOPPED_POLLING
:
712 USB_PIPE_STATE_ACTIVE
) {
713 usba_pipe_new_state(ph_data
,
714 USB_PIPE_STATE_IDLE
);
717 case USB_CR_NOT_SUPPORTED
:
718 usba_pipe_new_state(ph_data
,
719 USB_PIPE_STATE_IDLE
);
721 case USB_CR_PIPE_RESET
:
725 usba_pipe_new_state(ph_data
,
726 USB_PIPE_STATE_ERROR
);
731 pipe_state
= usba_get_ph_state(ph_data
);
733 mutex_exit(&ph_data
->p_mutex
);
734 if (attrs
& USB_ATTRS_PIPE_RESET
) {
735 if ((completion_reason
!= USB_CR_PIPE_RESET
) &&
736 (pipe_state
== USB_PIPE_STATE_ERROR
)) {
738 hcdi_autoclearing(req_wrp
);
742 usba_req_exc_cb(req_wrp
, 0, 0);
743 mutex_enter(&ph_data
->p_mutex
);
746 /* Update the hcdi error kstats */
747 if (completion_reason
) {
748 mutex_enter(&hcdi
->hcdi_mutex
);
749 usba_hcdi_update_error_stats(hcdi
, completion_reason
);
750 mutex_exit(&hcdi
->hcdi_mutex
);
754 * Once the callback is finished, release the pipe handle
755 * we start the next request first to avoid that the
756 * pipe gets closed while starting the next request
758 mutex_exit(&ph_data
->p_mutex
);
759 usba_start_next_req(ph_data
);
761 mutex_enter(&ph_data
->p_mutex
);
766 * thread to perform callbacks on the shared queue
769 hcdi_shared_cb_thread(void *arg
)
771 usba_req_wrapper_t
*req_wrp
= (usba_req_wrapper_t
*)arg
;
772 usba_pipe_handle_data_t
*ph_data
= req_wrp
->wr_ph_data
;
773 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
774 usba_hcdi_t
*hcdi
= usba_hcdi_get_hcdi(ph_data
->
775 p_usba_device
->usb_root_hub_dip
);
777 * hold the ph_data. we can't use usba_hold_ph_data() since
778 * it will return NULL if we are closing the pipe which would
779 * then leave all requests stuck in the cb_queue
781 mutex_enter(&ph_impl
->usba_ph_mutex
);
782 ph_impl
->usba_ph_ref_count
++;
784 USB_DPRINTF_L4(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
785 "hcdi_shared_cb_thread: ph_data=0x%p ref=%d req=0x%p",
786 (void *)ph_data
, ph_impl
->usba_ph_ref_count
, (void *)req_wrp
);
787 mutex_exit(&ph_impl
->usba_ph_mutex
);
789 /* do the callback */
790 mutex_enter(&ph_data
->p_mutex
);
791 hcdi_do_cb(ph_data
, req_wrp
, hcdi
);
792 mutex_exit(&ph_data
->p_mutex
);
794 USB_DPRINTF_L4(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
795 "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data
);
797 usba_release_ph_data(ph_impl
);
802 * soft interrupt handler
806 hcdi_soft_intr(caddr_t arg1
, caddr_t arg2
)
808 usba_hcdi_t
*hcdi
= (void *)arg1
;
809 usba_req_wrapper_t
*req_wrp
;
812 while ((req_wrp
= (usba_req_wrapper_t
*)
813 usba_rm_first_pvt_from_list(&hcdi
->hcdi_cb_queue
)) != NULL
) {
814 usba_pipe_handle_data_t
*ph_data
= req_wrp
->wr_ph_data
;
815 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
818 mutex_enter(&ph_impl
->usba_ph_mutex
);
819 ph_impl
->usba_ph_ref_count
++;
820 mutex_exit(&ph_impl
->usba_ph_mutex
);
822 /* do the callback */
823 usba_req_normal_cb(req_wrp
);
825 /* decrement the soft interrupt count */
826 mutex_enter(&ph_data
->p_mutex
);
827 ph_data
->p_soft_intr
--;
828 mutex_exit(&ph_data
->p_mutex
);
830 /* release the pipe */
831 mutex_enter(&ph_impl
->usba_ph_mutex
);
832 ph_impl
->usba_ph_ref_count
--;
833 mutex_exit(&ph_impl
->usba_ph_mutex
);
838 return (count
== 0 ? DDI_INTR_UNCLAIMED
: DDI_INTR_CLAIMED
);
844 * This function is called under the taskq context. It
845 * resets the pipe, and clears the stall, if necessary
848 hcdi_autoclearing(usba_req_wrapper_t
*req_wrp
)
850 usb_cr_t cr
= req_wrp
->wr_cr
;
851 usb_pipe_handle_t pipe_handle
, def_pipe_handle
;
852 usb_cr_t completion_reason
;
853 usb_cb_flags_t cb_flags
;
855 usba_device_t
*usba_device
=
856 req_wrp
->wr_ph_data
->p_usba_device
;
857 usba_hcdi_t
*hcdi
= usba_hcdi_get_hcdi(
858 usba_device
->usb_root_hub_dip
);
859 usb_req_attrs_t attrs
= req_wrp
->wr_attrs
;
861 USB_DPRINTF_L4(DPRINT_MASK_HCDI
, hcdi
->hcdi_log_handle
,
862 "hcdi_autoclearing: wrp=0x%p", (void *)req_wrp
);
864 pipe_handle
= usba_get_pipe_handle(req_wrp
->wr_ph_data
);
865 def_pipe_handle
= usba_get_dflt_pipe_handle(req_wrp
->wr_ph_data
->p_dip
);
868 * first reset the pipe synchronously
870 if ((attrs
& USB_ATTRS_PIPE_RESET
) == USB_ATTRS_PIPE_RESET
) {
871 usba_pipe_clear(pipe_handle
);
872 usba_req_set_cb_flags(req_wrp
, USB_CB_RESET_PIPE
);
875 ASSERT(def_pipe_handle
);
877 /* Do not clear if this request was a usb_get_status request */
878 if ((pipe_handle
== def_pipe_handle
) &&
879 (USBA_WRP2CTRL_REQ(req_wrp
)->ctrl_bRequest
==
880 USB_REQ_GET_STATUS
)) {
881 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, hcdi
->hcdi_log_handle
,
882 "hcdi_autoclearing: usb_get_status failed, no clearing");
884 /* if default pipe and stall no auto clearing */
885 } else if ((pipe_handle
== def_pipe_handle
) && (cr
== USB_CR_STALL
)) {
886 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, hcdi
->hcdi_log_handle
,
887 "hcdi_autoclearing: default pipe stalled, no clearing");
889 usba_req_set_cb_flags(req_wrp
, USB_CB_PROTOCOL_STALL
);
891 /* else do auto clearing */
892 } else if (((attrs
& USB_ATTRS_AUTOCLEARING
) ==
893 USB_ATTRS_AUTOCLEARING
) && (cr
== USB_CR_STALL
)) {
896 rval
= usb_get_status(req_wrp
->wr_dip
, def_pipe_handle
,
897 USB_DEV_REQ_DEV_TO_HOST
| USB_DEV_REQ_RCPT_EP
,
898 req_wrp
->wr_ph_data
->p_ep
.bEndpointAddress
,
899 &status
, USB_FLAGS_SLEEP
);
900 if (rval
!= USB_SUCCESS
) {
901 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, hcdi
->hcdi_log_handle
,
902 "get status (STALL) failed: rval=%d", rval
);
904 usba_pipe_clear(def_pipe_handle
);
907 if ((rval
!= USB_SUCCESS
) ||
908 (status
& USB_EP_HALT_STATUS
)) {
909 usba_req_set_cb_flags(req_wrp
, USB_CB_FUNCTIONAL_STALL
);
911 if ((rval
= usb_pipe_sync_ctrl_xfer(
912 req_wrp
->wr_dip
, def_pipe_handle
,
913 USB_DEV_REQ_HOST_TO_DEV
|
915 USB_REQ_CLEAR_FEATURE
,
917 req_wrp
->wr_ph_data
->p_ep
.bEndpointAddress
,
921 &cb_flags
, USB_FLAGS_SLEEP
)) != USB_SUCCESS
) {
922 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
923 hcdi
->hcdi_log_handle
,
924 "auto clearing (STALL) failed: "
925 "rval=%d, cr=0x%x cb=0x%x",
926 rval
, completion_reason
, cb_flags
);
928 usba_pipe_clear(def_pipe_handle
);
930 usba_req_set_cb_flags(req_wrp
,
931 USB_CB_STALL_CLEARED
);
934 usba_req_set_cb_flags(req_wrp
, USB_CB_PROTOCOL_STALL
);
941 * usba_hcdi_get_req_private:
942 * This function is used to get the HCD private field
943 * maintained by USBA. HCD calls this function.
946 * req - pointer to usb_*_req_t
949 * wr_hcd_private field from wrapper
952 usba_hcdi_get_req_private(usb_opaque_t req
)
954 usba_req_wrapper_t
*wrp
= USBA_REQ2WRP(req
);
956 return (wrp
->wr_hcd_private
);
961 * usba_hcdi_set_req_private:
962 * This function is used to set the HCD private field
963 * maintained by USBA. HCD calls this function.
966 * req - pointer to usb_*_req_t
967 * hcd_private - wr_hcd_private field from wrapper
970 usba_hcdi_set_req_private(usb_opaque_t req
, usb_opaque_t hcd_private
)
972 usba_req_wrapper_t
*wrp
= USBA_REQ2WRP(req
);
974 wrp
->wr_hcd_private
= hcd_private
;
978 /* get data toggle information for this endpoint */
980 usba_hcdi_get_data_toggle(usba_device_t
*usba_device
, uint8_t ep_addr
)
983 usba_ph_impl_t
*ph_impl
;
986 ep_index
= usb_get_ep_index(ep_addr
);
987 mutex_enter(&usba_device
->usb_mutex
);
988 ph_impl
= &usba_device
->usb_ph_list
[ep_index
];
989 mutex_enter(&ph_impl
->usba_ph_mutex
);
990 toggle
= (uchar_t
)(ph_impl
->usba_ph_flags
& USBA_PH_DATA_TOGGLE
);
991 mutex_exit(&ph_impl
->usba_ph_mutex
);
992 mutex_exit(&usba_device
->usb_mutex
);
998 /* set data toggle information for this endpoint */
1000 usba_hcdi_set_data_toggle(usba_device_t
*usba_device
, uint8_t ep_addr
,
1003 usba_ph_impl_t
*ph_impl
;
1006 ep_index
= usb_get_ep_index(ep_addr
);
1007 mutex_enter(&usba_device
->usb_mutex
);
1008 ph_impl
= &usba_device
->usb_ph_list
[ep_index
];
1009 mutex_enter(&ph_impl
->usba_ph_mutex
);
1010 ph_impl
->usba_ph_flags
&= ~USBA_PH_DATA_TOGGLE
;
1011 ph_impl
->usba_ph_flags
|= (USBA_PH_DATA_TOGGLE
& toggle
);
1012 mutex_exit(&ph_impl
->usba_ph_mutex
);
1013 mutex_exit(&usba_device
->usb_mutex
);
1017 /* get pipe_handle_impl ptr for this ep */
1018 usba_pipe_handle_data_t
*
1019 usba_hcdi_get_ph_data(usba_device_t
*usba_device
, uint8_t ep_addr
)
1021 return (usba_device
->usb_ph_list
[usb_get_ep_index(ep_addr
)].
1026 usba_hcdi_get_device_private(usba_device_t
*usba_device
)
1028 return (usba_device
->usb_hcd_private
);