1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * USBA: Solaris USB Architecture support
28 *
29 * hcdi.c contains the code for client driver callbacks.  A host controller
30 * driver registers/unregisters with usba through usba_hcdi_register/unregister.
31 *
32 * When the transfer has finished, the host controller driver will call into
33 * usba with the result.  The call is usba_hcdi_cb().
34 *
35 * The callback queue is maintained in FIFO order.  usba_hcdi_cb
36 * adds to the queue, and hcdi_cb_thread takes the callbacks off the queue
37 * and executes them.
38 */
39#define	USBA_FRAMEWORK
40#include <sys/usb/usba/usba_impl.h>
41#include <sys/usb/usba/hcdi_impl.h>
42#include <sys/kstat.h>
43#include <sys/ddi_impldefs.h>
44
45/* function prototypes, XXXX use hcdi_ prefix?	*/
46static void usba_hcdi_create_stats(usba_hcdi_t *, int);
47static void usba_hcdi_update_error_stats(usba_hcdi_t *, usb_cr_t);
48static void usba_hcdi_destroy_stats(usba_hcdi_t *);
49
50/* internal functions */
51static uint_t hcdi_soft_intr(caddr_t arg1, caddr_t arg2);
52
53static void hcdi_cb_thread(void *);
54static void hcdi_shared_cb_thread(void *);
55static void hcdi_do_cb(usba_pipe_handle_data_t *, usba_req_wrapper_t *,
56							usba_hcdi_t *);
57static void hcdi_autoclearing(usba_req_wrapper_t *);
58
59/* private function from USBAI */
60void	usba_pipe_clear(usb_pipe_handle_t);
61
62/* for debug messages */
63uint_t	hcdi_errmask	= (uint_t)DPRINT_MASK_ALL;
64uint_t	hcdi_errlevel	= USB_LOG_L4;
65uint_t	hcdi_instance_debug = (uint_t)-1;
66
67void
68usba_hcdi_initialization()
69{
70}
71
72
73void
74usba_hcdi_destroy()
75{
76}
77
78
79/*
80 * store hcdi structure in the dip
81 */
82void
83usba_hcdi_set_hcdi(dev_info_t *dip, usba_hcdi_t *hcdi)
84{
85	ddi_set_driver_private(dip, hcdi);
86}
87
88
89/*
90 * retrieve hcdi structure from the dip
91 */
92usba_hcdi_t *
93usba_hcdi_get_hcdi(dev_info_t *dip)
94{
95	return (ddi_get_driver_private(dip));
96}
97
98/*
99 * Called by an	HCD to attach an instance of the driver
100 *	make this instance known to USBA
101 *	the HCD	should initialize usba_hcdi structure prior
102 *	to calling this	interface
103 */
104int
105usba_hcdi_register(usba_hcdi_register_args_t *args, uint_t flags)
106{
107	char		*datap;
108	uint_t		soft_prip;
109	usba_hcdi_t	*hcdi = kmem_zalloc(sizeof (usba_hcdi_t), KM_SLEEP);
110
111	if (args->usba_hcdi_register_version != HCDI_REGISTER_VERS_0) {
112		kmem_free(hcdi, sizeof (usba_hcdi_t));
113
114		return (USB_FAILURE);
115	}
116
117	hcdi->hcdi_dip = args->usba_hcdi_register_dip;
118
119	/*
120	 * Create a log_handle
121	 */
122	hcdi->hcdi_log_handle = usb_alloc_log_hdl(hcdi->hcdi_dip, NULL,
123	    &hcdi_errlevel, &hcdi_errmask, &hcdi_instance_debug,
124	    0);
125
126	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
127	    "usba_hcdi_register: %s", ddi_node_name(hcdi->hcdi_dip));
128
129	/*
130	 * Initialize the mutex.  Use the iblock cookie passed in
131	 * by the host controller driver.
132	 */
133	mutex_init(&hcdi->hcdi_mutex, NULL, MUTEX_DRIVER,
134	    args->usba_hcdi_register_iblock_cookie);
135
136	/* add soft interrupt */
137	if (ddi_intr_add_softint(hcdi->hcdi_dip, &hcdi->hcdi_softint_hdl,
138	    DDI_INTR_SOFTPRI_MAX, hcdi_soft_intr, (caddr_t)hcdi) !=
139	    DDI_SUCCESS) {
140		USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
141		    "usba_hcd_register: add soft interrupt failed");
142		mutex_destroy(&hcdi->hcdi_mutex);
143		usb_free_log_hdl(hcdi->hcdi_log_handle);
144		kmem_free(hcdi, sizeof (usba_hcdi_t));
145
146		return (USB_FAILURE);
147	}
148
149	if (ddi_intr_get_softint_pri(hcdi->hcdi_softint_hdl, &soft_prip) !=
150	    DDI_SUCCESS) {
151		USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
152		    "usba_hcd_register: get soft interrupt priority failed");
153		(void) ddi_intr_remove_softint(hcdi->hcdi_softint_hdl);
154		mutex_destroy(&hcdi->hcdi_mutex);
155		usb_free_log_hdl(hcdi->hcdi_log_handle);
156		kmem_free(hcdi, sizeof (usba_hcdi_t));
157
158		return (USB_FAILURE);
159	}
160
161	/*
162	 * Priority and iblock_cookie are one and the same
163	 * (However, retaining hcdi_soft_iblock_cookie for now
164	 * assigning it w/ priority. In future all iblock_cookie
165	 * could just go)
166	 */
167	hcdi->hcdi_soft_iblock_cookie =
168	    (ddi_iblock_cookie_t)(uintptr_t)soft_prip;
169
170	usba_init_list(&hcdi->hcdi_cb_queue, NULL, NULL);
171
172	hcdi->hcdi_dma_attr	= args->usba_hcdi_register_dma_attr;
173	hcdi->hcdi_flags	= flags;
174	hcdi->hcdi_ops		= args->usba_hcdi_register_ops;
175	hcdi->hcdi_iblock_cookie = args->usba_hcdi_register_iblock_cookie;
176	usba_hcdi_create_stats(hcdi, ddi_get_instance(hcdi->hcdi_dip));
177
178	hcdi->hcdi_min_xfer	= hcdi->hcdi_dma_attr->dma_attr_minxfer;
179	hcdi->hcdi_min_burst_size =
180	    (1<<(ddi_ffs(hcdi->hcdi_dma_attr->dma_attr_burstsizes)-1));
181	hcdi->hcdi_max_burst_size =
182	    (1<<(ddi_fls(hcdi->hcdi_dma_attr->dma_attr_burstsizes)-1));
183
184	usba_hcdi_set_hcdi(hcdi->hcdi_dip, hcdi);
185
186	if (ddi_prop_lookup_string(DDI_DEV_T_ANY,
187	    hcdi->hcdi_dip,
188	    DDI_PROP_DONTPASS, "ugen-default-binding", &datap) ==
189	    DDI_PROP_SUCCESS) {
190		if (strcmp(datap, "device") == 0) {
191			hcdi->hcdi_ugen_default_binding =
192			    USBA_UGEN_DEVICE_BINDING;
193		} else if (strcmp(datap, "interface") == 0) {
194			hcdi->hcdi_ugen_default_binding =
195			    USBA_UGEN_INTERFACE_BINDING;
196		} else if (strcmp(datap, "interface-association") == 0) {
197			hcdi->hcdi_ugen_default_binding =
198			    USBA_UGEN_INTERFACE_ASSOCIATION_BINDING;
199		} else {
200			USB_DPRINTF_L2(DPRINT_MASK_HCDI,
201			    hcdi->hcdi_log_handle,
202			    "illegal value (%s) for "
203			    "ugen_default_binding property",
204			    datap);
205		}
206		ddi_prop_free(datap);
207	}
208
209	return (USB_SUCCESS);
210}
211
212
213/*
214 * Called by an	HCD to detach an instance of the driver
215 */
216/*ARGSUSED*/
217void
218usba_hcdi_unregister(dev_info_t *dip)
219{
220	usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(dip);
221
222	if (hcdi) {
223		USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
224		    "usba_hcdi_unregister: %s", ddi_node_name(dip));
225
226		usba_hcdi_set_hcdi(dip, NULL);
227
228		mutex_destroy(&hcdi->hcdi_mutex);
229		usba_hcdi_destroy_stats(hcdi);
230		usb_free_log_hdl(hcdi->hcdi_log_handle);
231
232		/* Destroy the soft interrupt */
233		(void) ddi_intr_remove_softint(hcdi->hcdi_softint_hdl);
234		kmem_free(hcdi, sizeof (usba_hcdi_t));
235	}
236}
237
238
239/*
240 * alloc usba_hcdi_ops structure
241 *	called from the HCD attach routine
242 */
243usba_hcdi_ops_t *
244usba_alloc_hcdi_ops()
245{
246	usba_hcdi_ops_t	*usba_hcdi_ops;
247
248	usba_hcdi_ops = kmem_zalloc(sizeof (usba_hcdi_ops_t), KM_SLEEP);
249
250	return (usba_hcdi_ops);
251}
252
253
254/*
255 * dealloc usba_hcdi_ops structure
256 */
257void
258usba_free_hcdi_ops(usba_hcdi_ops_t *hcdi_ops)
259{
260	if (hcdi_ops) {
261		kmem_free(hcdi_ops, sizeof (usba_hcdi_ops_t));
262	}
263}
264
265
266/*
267 * Allocate the hotplug kstats structure
268 */
269void
270usba_hcdi_create_stats(usba_hcdi_t *hcdi, int instance)
271{
272	char			kstatname[KSTAT_STRLEN];
273	const char		*dname = ddi_driver_name(hcdi->hcdi_dip);
274	hcdi_hotplug_stats_t	*hsp;
275	hcdi_error_stats_t	*esp;
276
277	if (HCDI_HOTPLUG_STATS(hcdi) == NULL) {
278		(void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,hotplug",
279		    dname, instance);
280		HCDI_HOTPLUG_STATS(hcdi) = kstat_create("usba", instance,
281		    kstatname, "usb_hotplug", KSTAT_TYPE_NAMED,
282		    sizeof (hcdi_hotplug_stats_t) / sizeof (kstat_named_t),
283		    KSTAT_FLAG_PERSISTENT);
284
285		if (HCDI_HOTPLUG_STATS(hcdi) == NULL) {
286
287			return;
288		}
289
290		hsp = HCDI_HOTPLUG_STATS_DATA(hcdi);
291		kstat_named_init(&hsp->hcdi_hotplug_total_success,
292		    "Total Hotplug Successes", KSTAT_DATA_UINT64);
293		kstat_named_init(&hsp->hcdi_hotplug_success,
294		    "Hotplug Successes", KSTAT_DATA_UINT64);
295		kstat_named_init(&hsp->hcdi_hotplug_total_failure,
296		    "Hotplug Total Failures", KSTAT_DATA_UINT64);
297		kstat_named_init(&hsp->hcdi_hotplug_failure,
298		    "Hotplug Failures", KSTAT_DATA_UINT64);
299		kstat_named_init(&hsp->hcdi_device_count,
300		    "Device Count", KSTAT_DATA_UINT64);
301
302		HCDI_HOTPLUG_STATS(hcdi)->ks_private = hcdi;
303		HCDI_HOTPLUG_STATS(hcdi)->ks_update = nulldev;
304		kstat_install(HCDI_HOTPLUG_STATS(hcdi));
305	}
306
307	if (HCDI_ERROR_STATS(hcdi) == NULL) {
308		(void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,error",
309		    dname, instance);
310		HCDI_ERROR_STATS(hcdi) = kstat_create("usba", instance,
311		    kstatname, "usb_errors", KSTAT_TYPE_NAMED,
312		    sizeof (hcdi_error_stats_t) / sizeof (kstat_named_t),
313		    KSTAT_FLAG_PERSISTENT);
314
315		if (HCDI_ERROR_STATS(hcdi) == NULL) {
316
317			return;
318		}
319
320		esp = HCDI_ERROR_STATS_DATA(hcdi);
321		kstat_named_init(&esp->cc_crc, "CRC Errors", KSTAT_DATA_UINT64);
322		kstat_named_init(&esp->cc_bitstuffing,
323		    "Bit Stuffing Violations", KSTAT_DATA_UINT64);
324		kstat_named_init(&esp->cc_data_toggle_mm,
325		    "Data Toggle PID Errors", KSTAT_DATA_UINT64);
326		kstat_named_init(&esp->cc_stall,
327		    "Endpoint Stalls", KSTAT_DATA_UINT64);
328		kstat_named_init(&esp->cc_dev_not_resp,
329		    "Device Not Responding", KSTAT_DATA_UINT64);
330		kstat_named_init(&esp->cc_pid_checkfailure,
331		    "PID Check Bit Errors", KSTAT_DATA_UINT64);
332		kstat_named_init(&esp->cc_unexp_pid,
333		    "Invalid PID Errors", KSTAT_DATA_UINT64);
334		kstat_named_init(&esp->cc_data_overrun,
335		    "Data Overruns", KSTAT_DATA_UINT64);
336		kstat_named_init(&esp->cc_data_underrun,
337		    "Data Underruns", KSTAT_DATA_UINT64);
338		kstat_named_init(&esp->cc_buffer_overrun,
339		    "Buffer Overruns", KSTAT_DATA_UINT64);
340		kstat_named_init(&esp->cc_buffer_underrun,
341		    "Buffer Underruns", KSTAT_DATA_UINT64);
342		kstat_named_init(&esp->cc_timeout,
343		    "Command Timed Out", KSTAT_DATA_UINT64);
344		kstat_named_init(&esp->cc_not_accessed,
345		    "Not Accessed By Hardware", KSTAT_DATA_UINT64);
346		kstat_named_init(&esp->cc_unspecified_err,
347		    "Unspecified Error", KSTAT_DATA_UINT64);
348#ifdef	NOTYETNEEDED
349		kstat_named_init(&esp->hcdi_usb_failure,
350		    "USB Failure", KSTAT_DATA_UINT64);
351		kstat_named_init(&esp->hcdi_usb_no_resources,
352		    "No Resources", KSTAT_DATA_UINT64);
353		kstat_named_init(&esp->hcdi_usb_no_bandwidth,
354		    "No Bandwidth", KSTAT_DATA_UINT64);
355		kstat_named_init(&esp->hcdi_usb_pipe_reserved,
356		    "Pipe Reserved", KSTAT_DATA_UINT64);
357		kstat_named_init(&esp->hcdi_usb_pipe_unshareable,
358		    "Pipe Unshareable", KSTAT_DATA_UINT64);
359		kstat_named_init(&esp->hcdi_usb_not_supported,
360		    "Function Not Supported", KSTAT_DATA_UINT64);
361		kstat_named_init(&esp->hcdi_usb_pipe_error,
362		    "Pipe Error", KSTAT_DATA_UINT64);
363		kstat_named_init(&esp->hcdi_usb_pipe_busy,
364		    "Pipe Busy", KSTAT_DATA_UINT64);
365#endif
366
367		HCDI_ERROR_STATS(hcdi)->ks_private = hcdi;
368		HCDI_ERROR_STATS(hcdi)->ks_update = nulldev;
369		kstat_install(HCDI_ERROR_STATS(hcdi));
370	}
371}
372
373
374/*
375 * Do actual error stats
376 */
377void
378usba_hcdi_update_error_stats(usba_hcdi_t *hcdi, usb_cr_t completion_reason)
379{
380	if (HCDI_ERROR_STATS(hcdi) == NULL) {
381
382		return;
383	}
384
385	switch (completion_reason) {
386	case USB_CR_OK:
387		break;
388	case USB_CR_CRC:
389		HCDI_ERROR_STATS_DATA(hcdi)->cc_crc.value.ui64++;
390		break;
391	case USB_CR_BITSTUFFING:
392		HCDI_ERROR_STATS_DATA(hcdi)->cc_bitstuffing.value.ui64++;
393		break;
394	case USB_CR_DATA_TOGGLE_MM:
395		HCDI_ERROR_STATS_DATA(hcdi)->cc_data_toggle_mm.value.ui64++;
396		break;
397	case USB_CR_STALL:
398		HCDI_ERROR_STATS_DATA(hcdi)->cc_stall.value.ui64++;
399		break;
400	case USB_CR_DEV_NOT_RESP:
401		HCDI_ERROR_STATS_DATA(hcdi)->cc_dev_not_resp.value.ui64++;
402		break;
403	case USB_CR_PID_CHECKFAILURE:
404		HCDI_ERROR_STATS_DATA(hcdi)->cc_pid_checkfailure.value.ui64++;
405		break;
406	case USB_CR_UNEXP_PID:
407		HCDI_ERROR_STATS_DATA(hcdi)->cc_unexp_pid.value.ui64++;
408		break;
409	case USB_CR_DATA_OVERRUN:
410		HCDI_ERROR_STATS_DATA(hcdi)->cc_data_overrun.value.ui64++;
411		break;
412	case USB_CR_DATA_UNDERRUN:
413		HCDI_ERROR_STATS_DATA(hcdi)->cc_data_underrun.value.ui64++;
414		break;
415	case USB_CR_BUFFER_OVERRUN:
416		HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_overrun.value.ui64++;
417		break;
418	case USB_CR_BUFFER_UNDERRUN:
419		HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_underrun.value.ui64++;
420		break;
421	case USB_CR_TIMEOUT:
422		HCDI_ERROR_STATS_DATA(hcdi)->cc_timeout.value.ui64++;
423		break;
424	case USB_CR_NOT_ACCESSED:
425		HCDI_ERROR_STATS_DATA(hcdi)->cc_not_accessed.value.ui64++;
426		break;
427	case USB_CR_NO_RESOURCES:
428		HCDI_ERROR_STATS_DATA(hcdi)->cc_no_resources.value.ui64++;
429		break;
430	case USB_CR_UNSPECIFIED_ERR:
431		HCDI_ERROR_STATS_DATA(hcdi)->cc_unspecified_err.value.ui64++;
432		break;
433	case USB_CR_STOPPED_POLLING:
434		HCDI_ERROR_STATS_DATA(hcdi)->cc_stopped_polling.value.ui64++;
435		break;
436	case USB_CR_PIPE_CLOSING:
437		HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_closing.value.ui64++;
438		break;
439	case USB_CR_PIPE_RESET:
440		HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_reset.value.ui64++;
441		break;
442	case USB_CR_NOT_SUPPORTED:
443		HCDI_ERROR_STATS_DATA(hcdi)->cc_not_supported.value.ui64++;
444		break;
445	case USB_CR_FLUSHED:
446		HCDI_ERROR_STATS_DATA(hcdi)->cc_flushed.value.ui64++;
447		break;
448	default:
449		break;
450	}
451}
452
453
454/*
455 * Destroy the hotplug kstats structure
456 */
457static void
458usba_hcdi_destroy_stats(usba_hcdi_t *hcdi)
459{
460	if (HCDI_HOTPLUG_STATS(hcdi)) {
461		kstat_delete(HCDI_HOTPLUG_STATS(hcdi));
462		HCDI_HOTPLUG_STATS(hcdi) = NULL;
463	}
464
465	if (HCDI_ERROR_STATS(hcdi)) {
466		kstat_delete(HCDI_ERROR_STATS(hcdi));
467		HCDI_ERROR_STATS(hcdi) = NULL;
468	}
469}
470
471
472/*
473 * HCD callback handling
474 */
475void
476usba_hcdi_cb(usba_pipe_handle_data_t *ph_data,
477	usb_opaque_t	req,
478	usb_cr_t	completion_reason)
479{
480
481	usba_device_t		*usba_device = ph_data->p_usba_device;
482	usba_hcdi_t		*hcdi =	usba_hcdi_get_hcdi(
483	    usba_device->usb_root_hub_dip);
484	usba_req_wrapper_t	*req_wrp = USBA_REQ2WRP(req);
485	usb_ep_descr_t		*eptd = &ph_data->p_ep;
486
487	mutex_enter(&ph_data->p_mutex);
488
489#ifdef DEBUG
490	mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
491
492	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
493	    "usba_hcdi_cb: "
494	    "ph_data=0x%p req=0x%p state=%d ref=%d cnt=%d cr=%d",
495	    (void *)ph_data, (void *)req, ph_data->p_ph_impl->usba_ph_state,
496	    ph_data->p_ph_impl->usba_ph_ref_count, ph_data->p_req_count,
497	    completion_reason);
498
499	mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
500#endif
501
502	/* Set the completion reason */
503	switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
504	case USB_EP_ATTR_CONTROL:
505		((usb_ctrl_req_t *)req)->
506		    ctrl_completion_reason = completion_reason;
507		break;
508	case USB_EP_ATTR_BULK:
509		((usb_bulk_req_t *)req)->
510		    bulk_completion_reason = completion_reason;
511		break;
512	case USB_EP_ATTR_INTR:
513		((usb_intr_req_t *)req)->
514		    intr_completion_reason = completion_reason;
515		break;
516	case USB_EP_ATTR_ISOCH:
517		((usb_isoc_req_t *)req)->
518		    isoc_completion_reason = completion_reason;
519		break;
520	}
521
522	/*
523	 * exception callbacks will still go thru a taskq thread
524	 * but should occur after the soft interrupt callback
525	 * By design of periodic pipes, polling will stop on any
526	 * exception
527	 */
528	if ((ph_data->p_spec_flag & USBA_PH_FLAG_USE_SOFT_INTR) &&
529	    (completion_reason == USB_CR_OK)) {
530		ph_data->p_soft_intr++;
531		mutex_exit(&ph_data->p_mutex);
532
533		usba_add_to_list(&hcdi->hcdi_cb_queue, &req_wrp->wr_queue);
534
535		if (ddi_intr_trigger_softint(hcdi->hcdi_softint_hdl, NULL) !=
536		    DDI_SUCCESS)
537			USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
538			    "usba_hcdi_cb: ddi_intr_trigger_softint  failed");
539
540		return;
541	}
542
543	/*
544	 * USBA_PH_FLAG_TQ_SHARE is for bulk and intr requests,
545	 * USBA_PH_FLAG_USE_SOFT_INTR is only for isoch,
546	 * so there are no conflicts.
547	 */
548	if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) {
549		int iface;
550
551		mutex_exit(&ph_data->p_mutex);
552		iface = usb_get_if_number(ph_data->p_dip);
553		if (iface < 0) {
554			/* we own the device, use the first taskq */
555			iface = 0;
556		}
557		if (taskq_dispatch(usba_device->usb_shared_taskq[iface],
558		    hcdi_shared_cb_thread, req_wrp, TQ_NOSLEEP) ==
559		    NULL) {
560			usba_req_exc_cb(req_wrp,
561			    USB_CR_NO_RESOURCES, USB_CB_ASYNC_REQ_FAILED);
562		}
563
564		return;
565	}
566
567	/* Add the callback to the pipehandles callback list */
568	usba_add_to_list(&ph_data->p_cb_queue, &req_wrp->wr_queue);
569
570	/* only dispatch if there is no thread running */
571	if (ph_data->p_thread_id == 0) {
572		if (usba_async_ph_req(ph_data, hcdi_cb_thread,
573		    ph_data, USB_FLAGS_NOSLEEP) != USB_SUCCESS) {
574			USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
575			    "usba_hcdi_cb: taskq_dispatch failed");
576			if (usba_rm_from_list(&ph_data->p_cb_queue,
577			    &req_wrp->wr_queue) == USB_SUCCESS) {
578				mutex_exit(&ph_data->p_mutex);
579				usba_req_exc_cb(req_wrp,
580				    USB_CR_NO_RESOURCES,
581				    USB_CB_ASYNC_REQ_FAILED);
582
583				return;
584			}
585		} else {
586			ph_data->p_thread_id = (kthread_t *)1;
587		}
588	}
589	mutex_exit(&ph_data->p_mutex);
590}
591
592
593/*
594 * thread to perform the callbacks
595 */
596static void
597hcdi_cb_thread(void *arg)
598{
599	usba_pipe_handle_data_t	*ph_data =
600	    (usba_pipe_handle_data_t *)arg;
601	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
602	usba_hcdi_t		*hcdi = usba_hcdi_get_hcdi(ph_data->
603	    p_usba_device->usb_root_hub_dip);
604	usba_req_wrapper_t	*req_wrp;
605
606	mutex_enter(&ph_data->p_mutex);
607	ASSERT(ph_data->p_thread_id == (kthread_t *)1);
608	ph_data->p_thread_id = curthread;
609
610	/*
611	 * hold the ph_data. we can't use usba_hold_ph_data() since
612	 * it will return NULL if we are closing the pipe which would
613	 * then leave all requests stuck in the cb_queue
614	 */
615	mutex_enter(&ph_impl->usba_ph_mutex);
616	ph_impl->usba_ph_ref_count++;
617
618	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
619	    "hcdi_cb_thread: ph_data=0x%p ref=%d", (void *)ph_data,
620	    ph_impl->usba_ph_ref_count);
621
622	mutex_exit(&ph_impl->usba_ph_mutex);
623
624	/*
625	 * wait till soft interrupt callbacks are taken care of
626	 */
627	while (ph_data->p_soft_intr) {
628		mutex_exit(&ph_data->p_mutex);
629		delay(1);
630		mutex_enter(&ph_data->p_mutex);
631	}
632
633	while ((req_wrp = (usba_req_wrapper_t *)
634	    usba_rm_first_pvt_from_list(&ph_data->p_cb_queue)) != NULL) {
635		hcdi_do_cb(ph_data, req_wrp, hcdi);
636	}
637
638	ph_data->p_thread_id = 0;
639	mutex_exit(&ph_data->p_mutex);
640
641	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
642	    "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data);
643
644	usba_release_ph_data(ph_impl);
645}
646
647
648static void
649hcdi_do_cb(usba_pipe_handle_data_t *ph_data, usba_req_wrapper_t *req_wrp,
650    usba_hcdi_t *hcdi)
651{
652	usb_cr_t		completion_reason;
653	usb_req_attrs_t		attrs = req_wrp->wr_attrs;
654
655	switch (req_wrp->wr_ph_data->p_ep.bmAttributes &
656	    USB_EP_ATTR_MASK) {
657	case USB_EP_ATTR_CONTROL:
658		completion_reason =
659		    USBA_WRP2CTRL_REQ(req_wrp)->ctrl_completion_reason;
660		break;
661	case USB_EP_ATTR_INTR:
662		completion_reason =
663		    USBA_WRP2INTR_REQ(req_wrp)->intr_completion_reason;
664		break;
665	case USB_EP_ATTR_BULK:
666		completion_reason =
667		    USBA_WRP2BULK_REQ(req_wrp)->bulk_completion_reason;
668		break;
669	case USB_EP_ATTR_ISOCH:
670		completion_reason =
671		    USBA_WRP2ISOC_REQ(req_wrp)->isoc_completion_reason;
672		break;
673	}
674	req_wrp->wr_cr = completion_reason;
675
676	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
677	    "hcdi_do_cb: wrp=0x%p cr=0x%x", (void *)req_wrp, completion_reason);
678
679	/*
680	 * Normal callbacks:
681	 */
682	if (completion_reason == USB_CR_OK) {
683		mutex_exit(&ph_data->p_mutex);
684		usba_req_normal_cb(req_wrp);
685		mutex_enter(&ph_data->p_mutex);
686	} else {
687		usb_pipe_state_t pipe_state;
688
689		USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
690		    "exception callback handling: attrs=0x%x", attrs);
691
692		/*
693		 * In exception callback handling, if we were
694		 * not able to clear stall, we need to modify
695		 * pipe state. Also if auto-clearing is not set
696		 * pipe state needs to be modified.
697		 */
698		pipe_state = usba_get_ph_state(ph_data);
699
700		if (!USBA_PIPE_CLOSING(pipe_state)) {
701			switch (completion_reason) {
702			case USB_CR_STOPPED_POLLING:
703				if (pipe_state ==
704				    USB_PIPE_STATE_ACTIVE) {
705					usba_pipe_new_state(ph_data,
706					    USB_PIPE_STATE_IDLE);
707				}
708				break;
709			case USB_CR_NOT_SUPPORTED:
710				usba_pipe_new_state(ph_data,
711				    USB_PIPE_STATE_IDLE);
712				break;
713			case USB_CR_PIPE_RESET:
714			case USB_CR_FLUSHED:
715				break;
716			default:
717				usba_pipe_new_state(ph_data,
718				    USB_PIPE_STATE_ERROR);
719				break;
720			}
721		}
722
723		pipe_state = usba_get_ph_state(ph_data);
724
725		mutex_exit(&ph_data->p_mutex);
726		if (attrs & USB_ATTRS_PIPE_RESET) {
727			if ((completion_reason != USB_CR_PIPE_RESET) &&
728			    (pipe_state == USB_PIPE_STATE_ERROR)) {
729
730				hcdi_autoclearing(req_wrp);
731			}
732		}
733
734		usba_req_exc_cb(req_wrp, 0, 0);
735		mutex_enter(&ph_data->p_mutex);
736	}
737
738	/* Update the hcdi error kstats */
739	if (completion_reason) {
740		mutex_enter(&hcdi->hcdi_mutex);
741		usba_hcdi_update_error_stats(hcdi, completion_reason);
742		mutex_exit(&hcdi->hcdi_mutex);
743	}
744
745	/*
746	 * Once the callback is finished, release the pipe handle
747	 * we start the next request first to avoid that the
748	 * pipe gets closed while starting the next request
749	 */
750	mutex_exit(&ph_data->p_mutex);
751	usba_start_next_req(ph_data);
752
753	mutex_enter(&ph_data->p_mutex);
754}
755
756
757/*
758 * thread to perform callbacks on the shared queue
759 */
760static void
761hcdi_shared_cb_thread(void *arg)
762{
763	usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *)arg;
764	usba_pipe_handle_data_t	*ph_data = req_wrp->wr_ph_data;
765	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
766	usba_hcdi_t		*hcdi = usba_hcdi_get_hcdi(ph_data->
767	    p_usba_device->usb_root_hub_dip);
768	/*
769	 * hold the ph_data. we can't use usba_hold_ph_data() since
770	 * it will return NULL if we are closing the pipe which would
771	 * then leave all requests stuck in the cb_queue
772	 */
773	mutex_enter(&ph_impl->usba_ph_mutex);
774	ph_impl->usba_ph_ref_count++;
775
776	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
777	    "hcdi_shared_cb_thread: ph_data=0x%p ref=%d req=0x%p",
778	    (void *)ph_data, ph_impl->usba_ph_ref_count, (void *)req_wrp);
779	mutex_exit(&ph_impl->usba_ph_mutex);
780
781	/* do the callback */
782	mutex_enter(&ph_data->p_mutex);
783	hcdi_do_cb(ph_data, req_wrp, hcdi);
784	mutex_exit(&ph_data->p_mutex);
785
786	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
787	    "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data);
788
789	usba_release_ph_data(ph_impl);
790}
791
792
793/*
794 * soft interrupt handler
795 */
796/*ARGSUSED*/
797static uint_t
798hcdi_soft_intr(caddr_t arg1, caddr_t arg2)
799{
800	usba_hcdi_t		*hcdi = (void *)arg1;
801	usba_req_wrapper_t	*req_wrp;
802	int			count = 0;
803
804	while ((req_wrp = (usba_req_wrapper_t *)
805	    usba_rm_first_pvt_from_list(&hcdi->hcdi_cb_queue)) != NULL) {
806		usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data;
807		usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
808
809		/* hold the pipe */
810		mutex_enter(&ph_impl->usba_ph_mutex);
811		ph_impl->usba_ph_ref_count++;
812		mutex_exit(&ph_impl->usba_ph_mutex);
813
814		/* do the callback */
815		usba_req_normal_cb(req_wrp);
816
817		/* decrement the soft interrupt count */
818		mutex_enter(&ph_data->p_mutex);
819		ph_data->p_soft_intr--;
820		mutex_exit(&ph_data->p_mutex);
821
822		/* release the pipe */
823		mutex_enter(&ph_impl->usba_ph_mutex);
824		ph_impl->usba_ph_ref_count--;
825		mutex_exit(&ph_impl->usba_ph_mutex);
826
827		count++;
828	}
829
830	return (count == 0 ? DDI_INTR_UNCLAIMED : DDI_INTR_CLAIMED);
831}
832
833
834/*
835 * hcdi_autoclearing:
836 *	This function is called under the taskq context. It
837 *	resets the pipe, and clears the stall, if necessary
838 */
839static void
840hcdi_autoclearing(usba_req_wrapper_t *req_wrp)
841{
842	usb_cr_t		cr = req_wrp->wr_cr;
843	usb_pipe_handle_t	pipe_handle, def_pipe_handle;
844	usb_cr_t		completion_reason;
845	usb_cb_flags_t		cb_flags;
846	int			rval;
847	usba_device_t		*usba_device =
848	    req_wrp->wr_ph_data->p_usba_device;
849	usba_hcdi_t		*hcdi = usba_hcdi_get_hcdi(
850	    usba_device->usb_root_hub_dip);
851	usb_req_attrs_t		attrs = req_wrp->wr_attrs;
852
853	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
854	    "hcdi_autoclearing: wrp=0x%p", (void *)req_wrp);
855
856	pipe_handle = usba_get_pipe_handle(req_wrp->wr_ph_data);
857	def_pipe_handle = usba_get_dflt_pipe_handle(req_wrp->wr_ph_data->p_dip);
858
859	/*
860	 * first reset the pipe synchronously
861	 */
862	if ((attrs & USB_ATTRS_PIPE_RESET) == USB_ATTRS_PIPE_RESET) {
863		usba_pipe_clear(pipe_handle);
864		usba_req_set_cb_flags(req_wrp, USB_CB_RESET_PIPE);
865	}
866
867	ASSERT(def_pipe_handle);
868
869	/* Do not clear if this request was a usb_get_status request */
870	if ((pipe_handle == def_pipe_handle) &&
871	    (USBA_WRP2CTRL_REQ(req_wrp)->ctrl_bRequest ==
872	    USB_REQ_GET_STATUS)) {
873		USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
874		    "hcdi_autoclearing: usb_get_status failed, no clearing");
875
876	/* if default pipe and stall no auto clearing */
877	} else if ((pipe_handle == def_pipe_handle) && (cr == USB_CR_STALL)) {
878		USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
879		    "hcdi_autoclearing: default pipe stalled, no clearing");
880
881		usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL);
882
883	/* else do auto clearing */
884	} else if (((attrs & USB_ATTRS_AUTOCLEARING) ==
885	    USB_ATTRS_AUTOCLEARING) && (cr == USB_CR_STALL)) {
886		ushort_t status = 0;
887
888		rval = usb_get_status(req_wrp->wr_dip, def_pipe_handle,
889		    USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_EP,
890		    req_wrp->wr_ph_data->p_ep.bEndpointAddress,
891		    &status, USB_FLAGS_SLEEP);
892		if (rval != USB_SUCCESS) {
893			USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
894			    "get status (STALL) failed: rval=%d", rval);
895
896			usba_pipe_clear(def_pipe_handle);
897		}
898
899		if ((rval != USB_SUCCESS) ||
900		    (status & USB_EP_HALT_STATUS)) {
901			usba_req_set_cb_flags(req_wrp, USB_CB_FUNCTIONAL_STALL);
902
903			if ((rval = usb_pipe_sync_ctrl_xfer(
904			    req_wrp->wr_dip, def_pipe_handle,
905			    USB_DEV_REQ_HOST_TO_DEV |
906			    USB_DEV_REQ_RCPT_EP,
907			    USB_REQ_CLEAR_FEATURE,
908			    0,
909			    req_wrp->wr_ph_data->p_ep.bEndpointAddress,
910			    0,
911			    NULL, 0,
912			    &completion_reason,
913			    &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
914				USB_DPRINTF_L2(DPRINT_MASK_USBAI,
915				    hcdi->hcdi_log_handle,
916				    "auto clearing (STALL) failed: "
917				    "rval=%d, cr=0x%x cb=0x%x",
918				    rval, completion_reason, cb_flags);
919
920				usba_pipe_clear(def_pipe_handle);
921			} else {
922				usba_req_set_cb_flags(req_wrp,
923				    USB_CB_STALL_CLEARED);
924			}
925		} else {
926			usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL);
927		}
928	}
929}
930
931
932/*
933 * usba_hcdi_get_req_private:
934 *	This function is used to get the HCD private field
935 *	maintained by USBA. HCD calls this function.
936 *
937 * Arguments:
938 *	req		- pointer to usb_*_req_t
939 *
940 * Return Values:
941 *	wr_hcd_private field from wrapper
942 */
943usb_opaque_t
944usba_hcdi_get_req_private(usb_opaque_t req)
945{
946	usba_req_wrapper_t *wrp = USBA_REQ2WRP(req);
947
948	return (wrp->wr_hcd_private);
949}
950
951
952/*
953 * usba_hcdi_set_req_private:
954 *	This function is used to set the HCD private field
955 *	maintained by USBA. HCD calls this function.
956 *
957 * Arguments:
958 *	req		- pointer to usb_*_req_t
959 *	hcd_private	- wr_hcd_private field from wrapper
960 */
961void
962usba_hcdi_set_req_private(usb_opaque_t req,
963			usb_opaque_t	hcd_private)
964{
965	usba_req_wrapper_t *wrp = USBA_REQ2WRP(req);
966
967	wrp->wr_hcd_private = hcd_private;
968}
969
970
971/* get data toggle information for this endpoint */
972uchar_t
973usba_hcdi_get_data_toggle(usba_device_t *usba_device, uint8_t ep_addr)
974{
975	uchar_t		toggle;
976	usba_ph_impl_t	*ph_impl;
977	int		ep_index;
978
979	ep_index = usb_get_ep_index(ep_addr);
980	mutex_enter(&usba_device->usb_mutex);
981	ph_impl = &usba_device->usb_ph_list[ep_index];
982	mutex_enter(&ph_impl->usba_ph_mutex);
983	toggle = (uchar_t)(ph_impl->usba_ph_flags & USBA_PH_DATA_TOGGLE);
984	mutex_exit(&ph_impl->usba_ph_mutex);
985	mutex_exit(&usba_device->usb_mutex);
986
987	return (toggle);
988}
989
990
991/* set data toggle information for this endpoint */
992void
993usba_hcdi_set_data_toggle(usba_device_t *usba_device, uint8_t ep_addr,
994    uchar_t toggle)
995{
996	usba_ph_impl_t	*ph_impl;
997	int		ep_index;
998
999	ep_index = usb_get_ep_index(ep_addr);
1000	mutex_enter(&usba_device->usb_mutex);
1001	ph_impl = &usba_device->usb_ph_list[ep_index];
1002	mutex_enter(&ph_impl->usba_ph_mutex);
1003	ph_impl->usba_ph_flags &= ~USBA_PH_DATA_TOGGLE;
1004	ph_impl->usba_ph_flags |= (USBA_PH_DATA_TOGGLE & toggle);
1005	mutex_exit(&ph_impl->usba_ph_mutex);
1006	mutex_exit(&usba_device->usb_mutex);
1007}
1008
1009
1010/* get pipe_handle_impl ptr for this ep */
1011usba_pipe_handle_data_t *
1012usba_hcdi_get_ph_data(usba_device_t *usba_device, uint8_t ep_addr)
1013{
1014	return (usba_device->usb_ph_list[usb_get_ep_index(ep_addr)].
1015	    usba_ph_data);
1016}
1017