usb_transfer.c revision 218475
1184610Salfred/* $FreeBSD: head/sys/dev/usb/usb_transfer.c 218475 2011-02-09 08:01:45Z hselasky $ */
2184610Salfred/*-
3184610Salfred * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
4184610Salfred *
5184610Salfred * Redistribution and use in source and binary forms, with or without
6184610Salfred * modification, are permitted provided that the following conditions
7184610Salfred * are met:
8184610Salfred * 1. Redistributions of source code must retain the above copyright
9184610Salfred *    notice, this list of conditions and the following disclaimer.
10184610Salfred * 2. Redistributions in binary form must reproduce the above copyright
11184610Salfred *    notice, this list of conditions and the following disclaimer in the
12184610Salfred *    documentation and/or other materials provided with the distribution.
13184610Salfred *
14184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17184610Salfred * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24184610Salfred * SUCH DAMAGE.
25190754Sthompsa */
26184610Salfred
27194677Sthompsa#include <sys/stdint.h>
28194677Sthompsa#include <sys/stddef.h>
29194677Sthompsa#include <sys/param.h>
30194677Sthompsa#include <sys/queue.h>
31194677Sthompsa#include <sys/types.h>
32194677Sthompsa#include <sys/systm.h>
33194677Sthompsa#include <sys/kernel.h>
34194677Sthompsa#include <sys/bus.h>
35194677Sthompsa#include <sys/module.h>
36194677Sthompsa#include <sys/lock.h>
37194677Sthompsa#include <sys/mutex.h>
38194677Sthompsa#include <sys/condvar.h>
39194677Sthompsa#include <sys/sysctl.h>
40194677Sthompsa#include <sys/sx.h>
41194677Sthompsa#include <sys/unistd.h>
42194677Sthompsa#include <sys/callout.h>
43194677Sthompsa#include <sys/malloc.h>
44194677Sthompsa#include <sys/priv.h>
45194677Sthompsa
46188942Sthompsa#include <dev/usb/usb.h>
47194677Sthompsa#include <dev/usb/usbdi.h>
48194677Sthompsa#include <dev/usb/usbdi_util.h>
49184610Salfred
50194228Sthompsa#define	USB_DEBUG_VAR usb_debug
51184610Salfred
52188942Sthompsa#include <dev/usb/usb_core.h>
53188942Sthompsa#include <dev/usb/usb_busdma.h>
54188942Sthompsa#include <dev/usb/usb_process.h>
55188942Sthompsa#include <dev/usb/usb_transfer.h>
56188942Sthompsa#include <dev/usb/usb_device.h>
57188942Sthompsa#include <dev/usb/usb_debug.h>
58188942Sthompsa#include <dev/usb/usb_util.h>
59184610Salfred
60188942Sthompsa#include <dev/usb/usb_controller.h>
61188942Sthompsa#include <dev/usb/usb_bus.h>
62215649Sweongyo#include <dev/usb/usb_pf.h>
63184610Salfred
64194228Sthompsastruct usb_std_packet_size {
65184610Salfred	struct {
66184610Salfred		uint16_t min;		/* inclusive */
67184610Salfred		uint16_t max;		/* inclusive */
68184610Salfred	}	range;
69184610Salfred
70184610Salfred	uint16_t fixed[4];
71184610Salfred};
72184610Salfred
73194228Sthompsastatic usb_callback_t usb_request_callback;
74184610Salfred
75207080Sthompsastatic const struct usb_config usb_control_ep_cfg[USB_CTRL_XFER_MAX] = {
76184610Salfred
77184610Salfred	/* This transfer is used for generic control endpoint transfers */
78184610Salfred
79184610Salfred	[0] = {
80184610Salfred		.type = UE_CONTROL,
81184610Salfred		.endpoint = 0x00,	/* Control endpoint */
82184610Salfred		.direction = UE_DIR_ANY,
83190734Sthompsa		.bufsize = USB_EP0_BUFSIZE,	/* bytes */
84190734Sthompsa		.flags = {.proxy_buffer = 1,},
85194228Sthompsa		.callback = &usb_request_callback,
86192499Sthompsa		.usb_mode = USB_MODE_DUAL,	/* both modes */
87184610Salfred	},
88184610Salfred
89184610Salfred	/* This transfer is used for generic clear stall only */
90184610Salfred
91184610Salfred	[1] = {
92184610Salfred		.type = UE_CONTROL,
93184610Salfred		.endpoint = 0x00,	/* Control pipe */
94184610Salfred		.direction = UE_DIR_ANY,
95192984Sthompsa		.bufsize = sizeof(struct usb_device_request),
96194228Sthompsa		.callback = &usb_do_clear_stall_callback,
97190734Sthompsa		.timeout = 1000,	/* 1 second */
98190734Sthompsa		.interval = 50,	/* 50ms */
99190734Sthompsa		.usb_mode = USB_MODE_HOST,
100184610Salfred	},
101184610Salfred};
102184610Salfred
103184610Salfred/* function prototypes */
104184610Salfred
105194228Sthompsastatic void	usbd_update_max_frame_size(struct usb_xfer *);
106194228Sthompsastatic void	usbd_transfer_unsetup_sub(struct usb_xfer_root *, uint8_t);
107194228Sthompsastatic void	usbd_control_transfer_init(struct usb_xfer *);
108194677Sthompsastatic int	usbd_setup_ctrl_transfer(struct usb_xfer *);
109194228Sthompsastatic void	usb_callback_proc(struct usb_proc_msg *);
110194228Sthompsastatic void	usbd_callback_ss_done_defer(struct usb_xfer *);
111194228Sthompsastatic void	usbd_callback_wrapper(struct usb_xfer_queue *);
112194228Sthompsastatic void	usbd_transfer_start_cb(void *);
113194228Sthompsastatic uint8_t	usbd_callback_wrapper_sub(struct usb_xfer *);
114194228Sthompsastatic void	usbd_get_std_packet_size(struct usb_std_packet_size *ptr,
115192500Sthompsa		    uint8_t type, enum usb_dev_speed speed);
116184610Salfred
117184610Salfred/*------------------------------------------------------------------------*
118194228Sthompsa *	usb_request_callback
119190734Sthompsa *------------------------------------------------------------------------*/
120190734Sthompsastatic void
121194677Sthompsausb_request_callback(struct usb_xfer *xfer, usb_error_t error)
122190734Sthompsa{
123192499Sthompsa	if (xfer->flags_int.usb_mode == USB_MODE_DEVICE)
124194677Sthompsa		usb_handle_request_callback(xfer, error);
125190734Sthompsa	else
126194677Sthompsa		usbd_do_request_callback(xfer, error);
127190734Sthompsa}
128190734Sthompsa
129190734Sthompsa/*------------------------------------------------------------------------*
130194228Sthompsa *	usbd_update_max_frame_size
131184610Salfred *
132184610Salfred * This function updates the maximum frame size, hence high speed USB
133184610Salfred * can transfer multiple consecutive packets.
134184610Salfred *------------------------------------------------------------------------*/
135184610Salfredstatic void
136194228Sthompsausbd_update_max_frame_size(struct usb_xfer *xfer)
137184610Salfred{
138184610Salfred	/* compute maximum frame size */
139213435Shselasky	/* this computation should not overflow 16-bit */
140213435Shselasky	/* max = 15 * 1024 */
141184610Salfred
142213435Shselasky	xfer->max_frame_size = xfer->max_packet_size * xfer->max_packet_count;
143184610Salfred}
144184610Salfred
145184610Salfred/*------------------------------------------------------------------------*
146194228Sthompsa *	usbd_get_dma_delay
147184610Salfred *
148184610Salfred * The following function is called when we need to
149184610Salfred * synchronize with DMA hardware.
150184610Salfred *
151184610Salfred * Returns:
152184610Salfred *    0: no DMA delay required
153184610Salfred * Else: milliseconds of DMA delay
154184610Salfred *------------------------------------------------------------------------*/
155193045Sthompsausb_timeout_t
156212134Sthompsausbd_get_dma_delay(struct usb_device *udev)
157184610Salfred{
158212134Sthompsa	struct usb_bus_methods *mtod;
159212134Sthompsa	uint32_t temp;
160184610Salfred
161212134Sthompsa	mtod = udev->bus->methods;
162212134Sthompsa	temp = 0;
163212134Sthompsa
164212134Sthompsa	if (mtod->get_dma_delay) {
165212134Sthompsa		(mtod->get_dma_delay) (udev, &temp);
166184610Salfred		/*
167184610Salfred		 * Round up and convert to milliseconds. Note that we use
168184610Salfred		 * 1024 milliseconds per second. to save a division.
169184610Salfred		 */
170184610Salfred		temp += 0x3FF;
171184610Salfred		temp /= 0x400;
172184610Salfred	}
173184610Salfred	return (temp);
174184610Salfred}
175184610Salfred
176184610Salfred/*------------------------------------------------------------------------*
177194228Sthompsa *	usbd_transfer_setup_sub_malloc
178184610Salfred *
179184610Salfred * This function will allocate one or more DMA'able memory chunks
180184610Salfred * according to "size", "align" and "count" arguments. "ppc" is
181184610Salfred * pointed to a linear array of USB page caches afterwards.
182184610Salfred *
183184610Salfred * Returns:
184184610Salfred *    0: Success
185184610Salfred * Else: Failure
186184610Salfred *------------------------------------------------------------------------*/
187190180Sthompsa#if USB_HAVE_BUSDMA
188184610Salfreduint8_t
189194228Sthompsausbd_transfer_setup_sub_malloc(struct usb_setup_params *parm,
190193074Sthompsa    struct usb_page_cache **ppc, usb_size_t size, usb_size_t align,
191193074Sthompsa    usb_size_t count)
192184610Salfred{
193192984Sthompsa	struct usb_page_cache *pc;
194192984Sthompsa	struct usb_page *pg;
195184610Salfred	void *buf;
196193074Sthompsa	usb_size_t n_dma_pc;
197193074Sthompsa	usb_size_t n_obj;
198193074Sthompsa	usb_size_t x;
199193074Sthompsa	usb_size_t y;
200193074Sthompsa	usb_size_t r;
201193074Sthompsa	usb_size_t z;
202184610Salfred
203199816Sthompsa	USB_ASSERT(align > 1, ("Invalid alignment, 0x%08x\n",
204184610Salfred	    align));
205199816Sthompsa	USB_ASSERT(size > 0, ("Invalid size = 0\n"));
206184610Salfred
207184610Salfred	if (count == 0) {
208184610Salfred		return (0);		/* nothing to allocate */
209184610Salfred	}
210184610Salfred	/*
211184610Salfred	 * Make sure that the size is aligned properly.
212184610Salfred	 */
213184610Salfred	size = -((-size) & (-align));
214184610Salfred
215184610Salfred	/*
216184610Salfred	 * Try multi-allocation chunks to reduce the number of DMA
217184610Salfred	 * allocations, hence DMA allocations are slow.
218184610Salfred	 */
219184610Salfred	if (size >= PAGE_SIZE) {
220184610Salfred		n_dma_pc = count;
221184610Salfred		n_obj = 1;
222184610Salfred	} else {
223184610Salfred		/* compute number of objects per page */
224184610Salfred		n_obj = (PAGE_SIZE / size);
225184610Salfred		/*
226184610Salfred		 * Compute number of DMA chunks, rounded up
227184610Salfred		 * to nearest one:
228184610Salfred		 */
229184610Salfred		n_dma_pc = ((count + n_obj - 1) / n_obj);
230184610Salfred	}
231184610Salfred
232184610Salfred	if (parm->buf == NULL) {
233184610Salfred		/* for the future */
234184610Salfred		parm->dma_page_ptr += n_dma_pc;
235184610Salfred		parm->dma_page_cache_ptr += n_dma_pc;
236184610Salfred		parm->dma_page_ptr += count;
237184610Salfred		parm->xfer_page_cache_ptr += count;
238184610Salfred		return (0);
239184610Salfred	}
240184610Salfred	for (x = 0; x != n_dma_pc; x++) {
241184610Salfred		/* need to initialize the page cache */
242184610Salfred		parm->dma_page_cache_ptr[x].tag_parent =
243187173Sthompsa		    &parm->curr_xfer->xroot->dma_parent_tag;
244184610Salfred	}
245184610Salfred	for (x = 0; x != count; x++) {
246184610Salfred		/* need to initialize the page cache */
247184610Salfred		parm->xfer_page_cache_ptr[x].tag_parent =
248187173Sthompsa		    &parm->curr_xfer->xroot->dma_parent_tag;
249184610Salfred	}
250184610Salfred
251184610Salfred	if (ppc) {
252184610Salfred		*ppc = parm->xfer_page_cache_ptr;
253184610Salfred	}
254184610Salfred	r = count;			/* set remainder count */
255184610Salfred	z = n_obj * size;		/* set allocation size */
256184610Salfred	pc = parm->xfer_page_cache_ptr;
257184610Salfred	pg = parm->dma_page_ptr;
258184610Salfred
259184610Salfred	for (x = 0; x != n_dma_pc; x++) {
260184610Salfred
261184610Salfred		if (r < n_obj) {
262184610Salfred			/* compute last remainder */
263184610Salfred			z = r * size;
264184610Salfred			n_obj = r;
265184610Salfred		}
266194228Sthompsa		if (usb_pc_alloc_mem(parm->dma_page_cache_ptr,
267184610Salfred		    pg, z, align)) {
268184610Salfred			return (1);	/* failure */
269184610Salfred		}
270184610Salfred		/* Set beginning of current buffer */
271184610Salfred		buf = parm->dma_page_cache_ptr->buffer;
272184610Salfred		/* Make room for one DMA page cache and one page */
273184610Salfred		parm->dma_page_cache_ptr++;
274184610Salfred		pg++;
275184610Salfred
276184610Salfred		for (y = 0; (y != n_obj); y++, r--, pc++, pg++) {
277184610Salfred
278184610Salfred			/* Load sub-chunk into DMA */
279194228Sthompsa			if (usb_pc_dmamap_create(pc, size)) {
280184610Salfred				return (1);	/* failure */
281184610Salfred			}
282184610Salfred			pc->buffer = USB_ADD_BYTES(buf, y * size);
283184610Salfred			pc->page_start = pg;
284184610Salfred
285184610Salfred			mtx_lock(pc->tag_parent->mtx);
286194228Sthompsa			if (usb_pc_load_mem(pc, size, 1 /* synchronous */ )) {
287184610Salfred				mtx_unlock(pc->tag_parent->mtx);
288184610Salfred				return (1);	/* failure */
289184610Salfred			}
290184610Salfred			mtx_unlock(pc->tag_parent->mtx);
291184610Salfred		}
292184610Salfred	}
293184610Salfred
294184610Salfred	parm->xfer_page_cache_ptr = pc;
295184610Salfred	parm->dma_page_ptr = pg;
296184610Salfred	return (0);
297184610Salfred}
298190180Sthompsa#endif
299184610Salfred
300184610Salfred/*------------------------------------------------------------------------*
301194228Sthompsa *	usbd_transfer_setup_sub - transfer setup subroutine
302184610Salfred *
303184610Salfred * This function must be called from the "xfer_setup" callback of the
304184610Salfred * USB Host or Device controller driver when setting up an USB
305184610Salfred * transfer. This function will setup correct packet sizes, buffer
306192984Sthompsa * sizes, flags and more, that are stored in the "usb_xfer"
307184610Salfred * structure.
308184610Salfred *------------------------------------------------------------------------*/
309184610Salfredvoid
310194228Sthompsausbd_transfer_setup_sub(struct usb_setup_params *parm)
311184610Salfred{
312184610Salfred	enum {
313184610Salfred		REQ_SIZE = 8,
314184610Salfred		MIN_PKT = 8,
315184610Salfred	};
316192984Sthompsa	struct usb_xfer *xfer = parm->curr_xfer;
317192984Sthompsa	const struct usb_config *setup = parm->curr_setup;
318213435Shselasky	struct usb_endpoint_ss_comp_descriptor *ecomp;
319192984Sthompsa	struct usb_endpoint_descriptor *edesc;
320194228Sthompsa	struct usb_std_packet_size std_size;
321193045Sthompsa	usb_frcount_t n_frlengths;
322193045Sthompsa	usb_frcount_t n_frbuffers;
323193045Sthompsa	usb_frcount_t x;
324184610Salfred	uint8_t type;
325184610Salfred	uint8_t zmps;
326184610Salfred
327184610Salfred	/*
328184610Salfred	 * Sanity check. The following parameters must be initialized before
329184610Salfred	 * calling this function.
330184610Salfred	 */
331184610Salfred	if ((parm->hc_max_packet_size == 0) ||
332184610Salfred	    (parm->hc_max_packet_count == 0) ||
333184610Salfred	    (parm->hc_max_frame_size == 0)) {
334184610Salfred		parm->err = USB_ERR_INVAL;
335184610Salfred		goto done;
336184610Salfred	}
337193644Sthompsa	edesc = xfer->endpoint->edesc;
338213435Shselasky	ecomp = xfer->endpoint->ecomp;
339184610Salfred
340184610Salfred	type = (edesc->bmAttributes & UE_XFERTYPE);
341184610Salfred
342190734Sthompsa	xfer->flags = setup->flags;
343190734Sthompsa	xfer->nframes = setup->frames;
344190734Sthompsa	xfer->timeout = setup->timeout;
345190734Sthompsa	xfer->callback = setup->callback;
346190734Sthompsa	xfer->interval = setup->interval;
347193644Sthompsa	xfer->endpointno = edesc->bEndpointAddress;
348184610Salfred	xfer->max_packet_size = UGETW(edesc->wMaxPacketSize);
349184610Salfred	xfer->max_packet_count = 1;
350184610Salfred	/* make a shadow copy: */
351192499Sthompsa	xfer->flags_int.usb_mode = parm->udev->flags.usb_mode;
352184610Salfred
353190734Sthompsa	parm->bufsize = setup->bufsize;
354184610Salfred
355213435Shselasky	switch (parm->speed) {
356213435Shselasky	case USB_SPEED_HIGH:
357213435Shselasky		switch (type) {
358213435Shselasky		case UE_ISOCHRONOUS:
359213435Shselasky		case UE_INTERRUPT:
360213435Shselasky			xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
361213435Shselasky
362213435Shselasky			/* check for invalid max packet count */
363213435Shselasky			if (xfer->max_packet_count > 3)
364213435Shselasky				xfer->max_packet_count = 3;
365213435Shselasky			break;
366213435Shselasky		default:
367213435Shselasky			break;
368213435Shselasky		}
369213435Shselasky		xfer->max_packet_size &= 0x7FF;
370213435Shselasky		break;
371213435Shselasky	case USB_SPEED_SUPER:
372184610Salfred		xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
373213435Shselasky
374213435Shselasky		if (ecomp != NULL)
375213435Shselasky			xfer->max_packet_count += ecomp->bMaxBurst;
376213435Shselasky
377213435Shselasky		if ((xfer->max_packet_count == 0) ||
378213435Shselasky		    (xfer->max_packet_count > 16))
379213435Shselasky			xfer->max_packet_count = 16;
380213435Shselasky
381213435Shselasky		switch (type) {
382213435Shselasky		case UE_CONTROL:
383213435Shselasky			xfer->max_packet_count = 1;
384213435Shselasky			break;
385213435Shselasky		case UE_ISOCHRONOUS:
386213435Shselasky			if (ecomp != NULL) {
387213435Shselasky				uint8_t mult;
388213435Shselasky
389213435Shselasky				mult = (ecomp->bmAttributes & 3) + 1;
390213435Shselasky				if (mult > 3)
391213435Shselasky					mult = 3;
392213435Shselasky
393213435Shselasky				xfer->max_packet_count *= mult;
394213435Shselasky			}
395213435Shselasky			break;
396213435Shselasky		default:
397213435Shselasky			break;
398213435Shselasky		}
399184610Salfred		xfer->max_packet_size &= 0x7FF;
400213435Shselasky		break;
401213435Shselasky	default:
402213435Shselasky		break;
403184610Salfred	}
404184610Salfred	/* range check "max_packet_count" */
405184610Salfred
406184610Salfred	if (xfer->max_packet_count > parm->hc_max_packet_count) {
407184610Salfred		xfer->max_packet_count = parm->hc_max_packet_count;
408184610Salfred	}
409184610Salfred	/* filter "wMaxPacketSize" according to HC capabilities */
410184610Salfred
411184610Salfred	if ((xfer->max_packet_size > parm->hc_max_packet_size) ||
412184610Salfred	    (xfer->max_packet_size == 0)) {
413184610Salfred		xfer->max_packet_size = parm->hc_max_packet_size;
414184610Salfred	}
415184610Salfred	/* filter "wMaxPacketSize" according to standard sizes */
416184610Salfred
417194228Sthompsa	usbd_get_std_packet_size(&std_size, type, parm->speed);
418184610Salfred
419184610Salfred	if (std_size.range.min || std_size.range.max) {
420184610Salfred
421184610Salfred		if (xfer->max_packet_size < std_size.range.min) {
422184610Salfred			xfer->max_packet_size = std_size.range.min;
423184610Salfred		}
424184610Salfred		if (xfer->max_packet_size > std_size.range.max) {
425184610Salfred			xfer->max_packet_size = std_size.range.max;
426184610Salfred		}
427184610Salfred	} else {
428184610Salfred
429184610Salfred		if (xfer->max_packet_size >= std_size.fixed[3]) {
430184610Salfred			xfer->max_packet_size = std_size.fixed[3];
431184610Salfred		} else if (xfer->max_packet_size >= std_size.fixed[2]) {
432184610Salfred			xfer->max_packet_size = std_size.fixed[2];
433184610Salfred		} else if (xfer->max_packet_size >= std_size.fixed[1]) {
434184610Salfred			xfer->max_packet_size = std_size.fixed[1];
435184610Salfred		} else {
436184610Salfred			/* only one possibility left */
437184610Salfred			xfer->max_packet_size = std_size.fixed[0];
438184610Salfred		}
439184610Salfred	}
440184610Salfred
441184610Salfred	/* compute "max_frame_size" */
442184610Salfred
443194228Sthompsa	usbd_update_max_frame_size(xfer);
444184610Salfred
445184610Salfred	/* check interrupt interval and transfer pre-delay */
446184610Salfred
447184610Salfred	if (type == UE_ISOCHRONOUS) {
448184610Salfred
449190181Sthompsa		uint16_t frame_limit;
450184610Salfred
451184610Salfred		xfer->interval = 0;	/* not used, must be zero */
452184610Salfred		xfer->flags_int.isochronous_xfr = 1;	/* set flag */
453184610Salfred
454184610Salfred		if (xfer->timeout == 0) {
455184610Salfred			/*
456184610Salfred			 * set a default timeout in
457184610Salfred			 * case something goes wrong!
458184610Salfred			 */
459184610Salfred			xfer->timeout = 1000 / 4;
460184610Salfred		}
461187180Sthompsa		switch (parm->speed) {
462187180Sthompsa		case USB_SPEED_LOW:
463187180Sthompsa		case USB_SPEED_FULL:
464187180Sthompsa			frame_limit = USB_MAX_FS_ISOC_FRAMES_PER_XFER;
465199059Sthompsa			xfer->fps_shift = 0;
466187180Sthompsa			break;
467187180Sthompsa		default:
468184610Salfred			frame_limit = USB_MAX_HS_ISOC_FRAMES_PER_XFER;
469199059Sthompsa			xfer->fps_shift = edesc->bInterval;
470199059Sthompsa			if (xfer->fps_shift > 0)
471199059Sthompsa				xfer->fps_shift--;
472199059Sthompsa			if (xfer->fps_shift > 3)
473199059Sthompsa				xfer->fps_shift = 3;
474187180Sthompsa			break;
475184610Salfred		}
476184610Salfred
477184610Salfred		if (xfer->nframes > frame_limit) {
478184610Salfred			/*
479184610Salfred			 * this is not going to work
480184610Salfred			 * cross hardware
481184610Salfred			 */
482184610Salfred			parm->err = USB_ERR_INVAL;
483184610Salfred			goto done;
484184610Salfred		}
485184610Salfred		if (xfer->nframes == 0) {
486184610Salfred			/*
487184610Salfred			 * this is not a valid value
488184610Salfred			 */
489184610Salfred			parm->err = USB_ERR_ZERO_NFRAMES;
490184610Salfred			goto done;
491184610Salfred		}
492184610Salfred	} else {
493184610Salfred
494184610Salfred		/*
495213435Shselasky		 * If a value is specified use that else check the
496213435Shselasky		 * endpoint descriptor!
497184610Salfred		 */
498213435Shselasky		if (type == UE_INTERRUPT) {
499184610Salfred
500213435Shselasky			uint32_t temp;
501184610Salfred
502213435Shselasky			if (xfer->interval == 0) {
503213435Shselasky
504184610Salfred				xfer->interval = edesc->bInterval;
505184610Salfred
506187180Sthompsa				switch (parm->speed) {
507213435Shselasky				case USB_SPEED_LOW:
508213435Shselasky				case USB_SPEED_FULL:
509213435Shselasky					break;
510213435Shselasky				default:
511187180Sthompsa					/* 125us -> 1ms */
512187180Sthompsa					if (xfer->interval < 4)
513187180Sthompsa						xfer->interval = 1;
514187180Sthompsa					else if (xfer->interval > 16)
515213435Shselasky						xfer->interval = (1 << (16 - 4));
516187180Sthompsa					else
517187180Sthompsa						xfer->interval =
518213435Shselasky						    (1 << (xfer->interval - 4));
519187180Sthompsa					break;
520184610Salfred				}
521184610Salfred			}
522213435Shselasky
523213435Shselasky			if (xfer->interval == 0) {
524213435Shselasky				/*
525213435Shselasky				 * One millisecond is the smallest
526213435Shselasky				 * interval we support:
527213435Shselasky				 */
528213435Shselasky				xfer->interval = 1;
529213435Shselasky			}
530213435Shselasky
531213435Shselasky			xfer->fps_shift = 0;
532213435Shselasky			temp = 1;
533213435Shselasky
534213435Shselasky			while ((temp != 0) && (temp < xfer->interval)) {
535213435Shselasky				xfer->fps_shift++;
536213435Shselasky				temp *= 2;
537213435Shselasky			}
538213435Shselasky
539213435Shselasky			switch (parm->speed) {
540213435Shselasky			case USB_SPEED_LOW:
541213435Shselasky			case USB_SPEED_FULL:
542213435Shselasky				break;
543213435Shselasky			default:
544213435Shselasky				xfer->fps_shift += 3;
545213435Shselasky				break;
546213435Shselasky			}
547184610Salfred		}
548184610Salfred	}
549184610Salfred
550184610Salfred	/*
551184610Salfred	 * NOTE: we do not allow "max_packet_size" or "max_frame_size"
552184610Salfred	 * to be equal to zero when setting up USB transfers, hence
553184610Salfred	 * this leads to alot of extra code in the USB kernel.
554184610Salfred	 */
555184610Salfred
556184610Salfred	if ((xfer->max_frame_size == 0) ||
557184610Salfred	    (xfer->max_packet_size == 0)) {
558184610Salfred
559184610Salfred		zmps = 1;
560184610Salfred
561184610Salfred		if ((parm->bufsize <= MIN_PKT) &&
562184610Salfred		    (type != UE_CONTROL) &&
563184610Salfred		    (type != UE_BULK)) {
564184610Salfred
565184610Salfred			/* workaround */
566184610Salfred			xfer->max_packet_size = MIN_PKT;
567184610Salfred			xfer->max_packet_count = 1;
568184610Salfred			parm->bufsize = 0;	/* automatic setup length */
569194228Sthompsa			usbd_update_max_frame_size(xfer);
570184610Salfred
571184610Salfred		} else {
572184610Salfred			parm->err = USB_ERR_ZERO_MAXP;
573184610Salfred			goto done;
574184610Salfred		}
575184610Salfred
576184610Salfred	} else {
577184610Salfred		zmps = 0;
578184610Salfred	}
579184610Salfred
580184610Salfred	/*
581184610Salfred	 * check if we should setup a default
582184610Salfred	 * length:
583184610Salfred	 */
584184610Salfred
585184610Salfred	if (parm->bufsize == 0) {
586184610Salfred
587184610Salfred		parm->bufsize = xfer->max_frame_size;
588184610Salfred
589184610Salfred		if (type == UE_ISOCHRONOUS) {
590184610Salfred			parm->bufsize *= xfer->nframes;
591184610Salfred		}
592184610Salfred	}
593184610Salfred	/*
594184610Salfred	 * check if we are about to setup a proxy
595184610Salfred	 * type of buffer:
596184610Salfred	 */
597184610Salfred
598184610Salfred	if (xfer->flags.proxy_buffer) {
599184610Salfred
600184610Salfred		/* round bufsize up */
601184610Salfred
602184610Salfred		parm->bufsize += (xfer->max_frame_size - 1);
603184610Salfred
604184610Salfred		if (parm->bufsize < xfer->max_frame_size) {
605184610Salfred			/* length wrapped around */
606184610Salfred			parm->err = USB_ERR_INVAL;
607184610Salfred			goto done;
608184610Salfred		}
609184610Salfred		/* subtract remainder */
610184610Salfred
611184610Salfred		parm->bufsize -= (parm->bufsize % xfer->max_frame_size);
612184610Salfred
613184610Salfred		/* add length of USB device request structure, if any */
614184610Salfred
615184610Salfred		if (type == UE_CONTROL) {
616184610Salfred			parm->bufsize += REQ_SIZE;	/* SETUP message */
617184610Salfred		}
618184610Salfred	}
619184610Salfred	xfer->max_data_length = parm->bufsize;
620184610Salfred
621184610Salfred	/* Setup "n_frlengths" and "n_frbuffers" */
622184610Salfred
623184610Salfred	if (type == UE_ISOCHRONOUS) {
624184610Salfred		n_frlengths = xfer->nframes;
625184610Salfred		n_frbuffers = 1;
626184610Salfred	} else {
627184610Salfred
628184610Salfred		if (type == UE_CONTROL) {
629184610Salfred			xfer->flags_int.control_xfr = 1;
630184610Salfred			if (xfer->nframes == 0) {
631184610Salfred				if (parm->bufsize <= REQ_SIZE) {
632184610Salfred					/*
633184610Salfred					 * there will never be any data
634184610Salfred					 * stage
635184610Salfred					 */
636184610Salfred					xfer->nframes = 1;
637184610Salfred				} else {
638184610Salfred					xfer->nframes = 2;
639184610Salfred				}
640184610Salfred			}
641184610Salfred		} else {
642184610Salfred			if (xfer->nframes == 0) {
643184610Salfred				xfer->nframes = 1;
644184610Salfred			}
645184610Salfred		}
646184610Salfred
647184610Salfred		n_frlengths = xfer->nframes;
648184610Salfred		n_frbuffers = xfer->nframes;
649184610Salfred	}
650184610Salfred
651184610Salfred	/*
652184610Salfred	 * check if we have room for the
653184610Salfred	 * USB device request structure:
654184610Salfred	 */
655184610Salfred
656184610Salfred	if (type == UE_CONTROL) {
657184610Salfred
658184610Salfred		if (xfer->max_data_length < REQ_SIZE) {
659184610Salfred			/* length wrapped around or too small bufsize */
660184610Salfred			parm->err = USB_ERR_INVAL;
661184610Salfred			goto done;
662184610Salfred		}
663184610Salfred		xfer->max_data_length -= REQ_SIZE;
664184610Salfred	}
665184610Salfred	/* setup "frlengths" */
666184610Salfred	xfer->frlengths = parm->xfer_length_ptr;
667184610Salfred	parm->xfer_length_ptr += n_frlengths;
668184610Salfred
669184610Salfred	/* setup "frbuffers" */
670184610Salfred	xfer->frbuffers = parm->xfer_page_cache_ptr;
671184610Salfred	parm->xfer_page_cache_ptr += n_frbuffers;
672184610Salfred
673194677Sthompsa	/* initialize max frame count */
674194677Sthompsa	xfer->max_frame_count = xfer->nframes;
675194677Sthompsa
676184610Salfred	/*
677184610Salfred	 * check if we need to setup
678184610Salfred	 * a local buffer:
679184610Salfred	 */
680184610Salfred
681184610Salfred	if (!xfer->flags.ext_buffer) {
682184610Salfred
683184610Salfred		/* align data */
684184610Salfred		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
685184610Salfred
686184610Salfred		if (parm->buf) {
687184610Salfred
688184610Salfred			xfer->local_buffer =
689184610Salfred			    USB_ADD_BYTES(parm->buf, parm->size[0]);
690184610Salfred
691194677Sthompsa			usbd_xfer_set_frame_offset(xfer, 0, 0);
692184610Salfred
693184610Salfred			if ((type == UE_CONTROL) && (n_frbuffers > 1)) {
694194677Sthompsa				usbd_xfer_set_frame_offset(xfer, REQ_SIZE, 1);
695184610Salfred			}
696184610Salfred		}
697184610Salfred		parm->size[0] += parm->bufsize;
698184610Salfred
699184610Salfred		/* align data again */
700184610Salfred		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
701184610Salfred	}
702184610Salfred	/*
703184610Salfred	 * Compute maximum buffer size
704184610Salfred	 */
705184610Salfred
706184610Salfred	if (parm->bufsize_max < parm->bufsize) {
707184610Salfred		parm->bufsize_max = parm->bufsize;
708184610Salfred	}
709190180Sthompsa#if USB_HAVE_BUSDMA
710184610Salfred	if (xfer->flags_int.bdma_enable) {
711184610Salfred		/*
712184610Salfred		 * Setup "dma_page_ptr".
713184610Salfred		 *
714184610Salfred		 * Proof for formula below:
715184610Salfred		 *
716184610Salfred		 * Assume there are three USB frames having length "a", "b" and
717184610Salfred		 * "c". These USB frames will at maximum need "z"
718192984Sthompsa		 * "usb_page" structures. "z" is given by:
719184610Salfred		 *
720184610Salfred		 * z = ((a / USB_PAGE_SIZE) + 2) + ((b / USB_PAGE_SIZE) + 2) +
721184610Salfred		 * ((c / USB_PAGE_SIZE) + 2);
722184610Salfred		 *
723184610Salfred		 * Constraining "a", "b" and "c" like this:
724184610Salfred		 *
725184610Salfred		 * (a + b + c) <= parm->bufsize
726184610Salfred		 *
727184610Salfred		 * We know that:
728184610Salfred		 *
729184610Salfred		 * z <= ((parm->bufsize / USB_PAGE_SIZE) + (3*2));
730184610Salfred		 *
731184610Salfred		 * Here is the general formula:
732184610Salfred		 */
733184610Salfred		xfer->dma_page_ptr = parm->dma_page_ptr;
734184610Salfred		parm->dma_page_ptr += (2 * n_frbuffers);
735184610Salfred		parm->dma_page_ptr += (parm->bufsize / USB_PAGE_SIZE);
736184610Salfred	}
737190180Sthompsa#endif
738184610Salfred	if (zmps) {
739184610Salfred		/* correct maximum data length */
740184610Salfred		xfer->max_data_length = 0;
741184610Salfred	}
742184610Salfred	/* subtract USB frame remainder from "hc_max_frame_size" */
743184610Salfred
744190181Sthompsa	xfer->max_hc_frame_size =
745184610Salfred	    (parm->hc_max_frame_size -
746184610Salfred	    (parm->hc_max_frame_size % xfer->max_frame_size));
747184610Salfred
748190181Sthompsa	if (xfer->max_hc_frame_size == 0) {
749184610Salfred		parm->err = USB_ERR_INVAL;
750184610Salfred		goto done;
751184610Salfred	}
752184610Salfred
753184610Salfred	/* initialize frame buffers */
754184610Salfred
755184610Salfred	if (parm->buf) {
756184610Salfred		for (x = 0; x != n_frbuffers; x++) {
757184610Salfred			xfer->frbuffers[x].tag_parent =
758187173Sthompsa			    &xfer->xroot->dma_parent_tag;
759190180Sthompsa#if USB_HAVE_BUSDMA
760184610Salfred			if (xfer->flags_int.bdma_enable &&
761184610Salfred			    (parm->bufsize_max > 0)) {
762184610Salfred
763194228Sthompsa				if (usb_pc_dmamap_create(
764184610Salfred				    xfer->frbuffers + x,
765184610Salfred				    parm->bufsize_max)) {
766184610Salfred					parm->err = USB_ERR_NOMEM;
767184610Salfred					goto done;
768184610Salfred				}
769184610Salfred			}
770190180Sthompsa#endif
771184610Salfred		}
772184610Salfred	}
773184610Salfreddone:
774184610Salfred	if (parm->err) {
775184610Salfred		/*
776184610Salfred		 * Set some dummy values so that we avoid division by zero:
777184610Salfred		 */
778190181Sthompsa		xfer->max_hc_frame_size = 1;
779184610Salfred		xfer->max_frame_size = 1;
780184610Salfred		xfer->max_packet_size = 1;
781184610Salfred		xfer->max_data_length = 0;
782184610Salfred		xfer->nframes = 0;
783184610Salfred		xfer->max_frame_count = 0;
784184610Salfred	}
785184610Salfred}
786184610Salfred
787184610Salfred/*------------------------------------------------------------------------*
788194228Sthompsa *	usbd_transfer_setup - setup an array of USB transfers
789184610Salfred *
790194228Sthompsa * NOTE: You must always call "usbd_transfer_unsetup" after calling
791194228Sthompsa * "usbd_transfer_setup" if success was returned.
792184610Salfred *
793184610Salfred * The idea is that the USB device driver should pre-allocate all its
794184610Salfred * transfers by one call to this function.
795184610Salfred *
796184610Salfred * Return values:
797184610Salfred *    0: Success
798184610Salfred * Else: Failure
799184610Salfred *------------------------------------------------------------------------*/
800193045Sthompsausb_error_t
801194228Sthompsausbd_transfer_setup(struct usb_device *udev,
802192984Sthompsa    const uint8_t *ifaces, struct usb_xfer **ppxfer,
803192984Sthompsa    const struct usb_config *setup_start, uint16_t n_setup,
804187173Sthompsa    void *priv_sc, struct mtx *xfer_mtx)
805184610Salfred{
806192984Sthompsa	struct usb_xfer dummy;
807192984Sthompsa	struct usb_setup_params parm;
808192984Sthompsa	const struct usb_config *setup_end = setup_start + n_setup;
809192984Sthompsa	const struct usb_config *setup;
810193644Sthompsa	struct usb_endpoint *ep;
811192984Sthompsa	struct usb_xfer_root *info;
812192984Sthompsa	struct usb_xfer *xfer;
813184610Salfred	void *buf = NULL;
814184610Salfred	uint16_t n;
815184610Salfred	uint16_t refcount;
816184610Salfred
817184610Salfred	parm.err = 0;
818184610Salfred	refcount = 0;
819184610Salfred	info = NULL;
820184610Salfred
821184610Salfred	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
822194228Sthompsa	    "usbd_transfer_setup can sleep!");
823184610Salfred
824184610Salfred	/* do some checking first */
825184610Salfred
826184610Salfred	if (n_setup == 0) {
827184610Salfred		DPRINTFN(6, "setup array has zero length!\n");
828184610Salfred		return (USB_ERR_INVAL);
829184610Salfred	}
830184610Salfred	if (ifaces == 0) {
831184610Salfred		DPRINTFN(6, "ifaces array is NULL!\n");
832184610Salfred		return (USB_ERR_INVAL);
833184610Salfred	}
834187173Sthompsa	if (xfer_mtx == NULL) {
835184610Salfred		DPRINTFN(6, "using global lock\n");
836187173Sthompsa		xfer_mtx = &Giant;
837184610Salfred	}
838184610Salfred	/* sanity checks */
839184610Salfred	for (setup = setup_start, n = 0;
840184610Salfred	    setup != setup_end; setup++, n++) {
841193045Sthompsa		if (setup->bufsize == (usb_frlength_t)-1) {
842184610Salfred			parm.err = USB_ERR_BAD_BUFSIZE;
843184610Salfred			DPRINTF("invalid bufsize\n");
844184610Salfred		}
845190734Sthompsa		if (setup->callback == NULL) {
846184610Salfred			parm.err = USB_ERR_NO_CALLBACK;
847184610Salfred			DPRINTF("no callback\n");
848184610Salfred		}
849184610Salfred		ppxfer[n] = NULL;
850184610Salfred	}
851184610Salfred
852184610Salfred	if (parm.err) {
853184610Salfred		goto done;
854184610Salfred	}
855184610Salfred	bzero(&parm, sizeof(parm));
856184610Salfred
857184610Salfred	parm.udev = udev;
858194228Sthompsa	parm.speed = usbd_get_speed(udev);
859184610Salfred	parm.hc_max_packet_count = 1;
860184610Salfred
861184610Salfred	if (parm.speed >= USB_SPEED_MAX) {
862184610Salfred		parm.err = USB_ERR_INVAL;
863184610Salfred		goto done;
864184610Salfred	}
865184610Salfred	/* setup all transfers */
866184610Salfred
867184610Salfred	while (1) {
868184610Salfred
869184610Salfred		if (buf) {
870184610Salfred			/*
871192984Sthompsa			 * Initialize the "usb_xfer_root" structure,
872184610Salfred			 * which is common for all our USB transfers.
873184610Salfred			 */
874184610Salfred			info = USB_ADD_BYTES(buf, 0);
875184610Salfred
876184610Salfred			info->memory_base = buf;
877184610Salfred			info->memory_size = parm.size[0];
878184610Salfred
879190180Sthompsa#if USB_HAVE_BUSDMA
880184610Salfred			info->dma_page_cache_start = USB_ADD_BYTES(buf, parm.size[4]);
881184610Salfred			info->dma_page_cache_end = USB_ADD_BYTES(buf, parm.size[5]);
882190180Sthompsa#endif
883184610Salfred			info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm.size[5]);
884184610Salfred			info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm.size[2]);
885184610Salfred
886194227Sthompsa			cv_init(&info->cv_drain, "WDRAIN");
887184610Salfred
888187173Sthompsa			info->xfer_mtx = xfer_mtx;
889190180Sthompsa#if USB_HAVE_BUSDMA
890194228Sthompsa			usb_dma_tag_setup(&info->dma_parent_tag,
891184610Salfred			    parm.dma_tag_p, udev->bus->dma_parent_tag[0].tag,
892194228Sthompsa			    xfer_mtx, &usb_bdma_done_event, 32, parm.dma_tag_max);
893190180Sthompsa#endif
894184610Salfred
895184610Salfred			info->bus = udev->bus;
896187173Sthompsa			info->udev = udev;
897184610Salfred
898184610Salfred			TAILQ_INIT(&info->done_q.head);
899194228Sthompsa			info->done_q.command = &usbd_callback_wrapper;
900190180Sthompsa#if USB_HAVE_BUSDMA
901184610Salfred			TAILQ_INIT(&info->dma_q.head);
902194228Sthompsa			info->dma_q.command = &usb_bdma_work_loop;
903190180Sthompsa#endif
904194228Sthompsa			info->done_m[0].hdr.pm_callback = &usb_callback_proc;
905187173Sthompsa			info->done_m[0].xroot = info;
906194228Sthompsa			info->done_m[1].hdr.pm_callback = &usb_callback_proc;
907187173Sthompsa			info->done_m[1].xroot = info;
908184610Salfred
909191400Sthompsa			/*
910191400Sthompsa			 * In device side mode control endpoint
911191400Sthompsa			 * requests need to run from a separate
912191400Sthompsa			 * context, else there is a chance of
913191400Sthompsa			 * deadlock!
914191400Sthompsa			 */
915194228Sthompsa			if (setup_start == usb_control_ep_cfg)
916187174Sthompsa				info->done_p =
917191400Sthompsa				    &udev->bus->control_xfer_proc;
918191400Sthompsa			else if (xfer_mtx == &Giant)
919191400Sthompsa				info->done_p =
920187174Sthompsa				    &udev->bus->giant_callback_proc;
921187174Sthompsa			else
922187174Sthompsa				info->done_p =
923187174Sthompsa				    &udev->bus->non_giant_callback_proc;
924184610Salfred		}
925184610Salfred		/* reset sizes */
926184610Salfred
927184610Salfred		parm.size[0] = 0;
928184610Salfred		parm.buf = buf;
929184610Salfred		parm.size[0] += sizeof(info[0]);
930184610Salfred
931184610Salfred		for (setup = setup_start, n = 0;
932184610Salfred		    setup != setup_end; setup++, n++) {
933184610Salfred
934184610Salfred			/* skip USB transfers without callbacks: */
935190734Sthompsa			if (setup->callback == NULL) {
936184610Salfred				continue;
937184610Salfred			}
938184610Salfred			/* see if there is a matching endpoint */
939194228Sthompsa			ep = usbd_get_endpoint(udev,
940184610Salfred			    ifaces[setup->if_index], setup);
941184610Salfred
942193644Sthompsa			if ((ep == NULL) || (ep->methods == NULL)) {
943190734Sthompsa				if (setup->flags.no_pipe_ok)
944184610Salfred					continue;
945192499Sthompsa				if ((setup->usb_mode != USB_MODE_DUAL) &&
946192499Sthompsa				    (setup->usb_mode != udev->flags.usb_mode))
947190734Sthompsa					continue;
948184610Salfred				parm.err = USB_ERR_NO_PIPE;
949184610Salfred				goto done;
950184610Salfred			}
951184610Salfred
952184610Salfred			/* align data properly */
953184610Salfred			parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
954184610Salfred
955190734Sthompsa			/* store current setup pointer */
956190734Sthompsa			parm.curr_setup = setup;
957190734Sthompsa
958184610Salfred			if (buf) {
959184610Salfred				/*
960184610Salfred				 * Common initialization of the
961192984Sthompsa				 * "usb_xfer" structure.
962184610Salfred				 */
963184610Salfred				xfer = USB_ADD_BYTES(buf, parm.size[0]);
964184610Salfred				xfer->address = udev->address;
965184610Salfred				xfer->priv_sc = priv_sc;
966187173Sthompsa				xfer->xroot = info;
967184610Salfred
968194228Sthompsa				usb_callout_init_mtx(&xfer->timeout_handle,
969186454Sthompsa				    &udev->bus->bus_mtx, 0);
970184610Salfred			} else {
971184610Salfred				/*
972184610Salfred				 * Setup a dummy xfer, hence we are
973192984Sthompsa				 * writing to the "usb_xfer"
974184610Salfred				 * structure pointed to by "xfer"
975184610Salfred				 * before we have allocated any
976184610Salfred				 * memory:
977184610Salfred				 */
978184610Salfred				xfer = &dummy;
979184610Salfred				bzero(&dummy, sizeof(dummy));
980184610Salfred				refcount++;
981184610Salfred			}
982184610Salfred
983193644Sthompsa			/* set transfer endpoint pointer */
984193644Sthompsa			xfer->endpoint = ep;
985188982Sthompsa
986184610Salfred			parm.size[0] += sizeof(xfer[0]);
987193644Sthompsa			parm.methods = xfer->endpoint->methods;
988188982Sthompsa			parm.curr_xfer = xfer;
989184610Salfred
990188982Sthompsa			/*
991188982Sthompsa			 * Call the Host or Device controller transfer
992188982Sthompsa			 * setup routine:
993188982Sthompsa			 */
994188982Sthompsa			(udev->bus->methods->xfer_setup) (&parm);
995184610Salfred
996188982Sthompsa			/* check for error */
997188982Sthompsa			if (parm.err)
998188982Sthompsa				goto done;
999188982Sthompsa
1000184610Salfred			if (buf) {
1001184610Salfred				/*
1002193644Sthompsa				 * Increment the endpoint refcount. This
1003184610Salfred				 * basically prevents setting a new
1004184610Salfred				 * configuration and alternate setting
1005184610Salfred				 * when USB transfers are in use on
1006184610Salfred				 * the given interface. Search the USB
1007199672Sthompsa				 * code for "endpoint->refcount_alloc" if you
1008184610Salfred				 * want more information.
1009184610Salfred				 */
1010199672Sthompsa				USB_BUS_LOCK(info->bus);
1011199672Sthompsa				if (xfer->endpoint->refcount_alloc >= USB_EP_REF_MAX)
1012199672Sthompsa					parm.err = USB_ERR_INVAL;
1013184610Salfred
1014199672Sthompsa				xfer->endpoint->refcount_alloc++;
1015199672Sthompsa
1016199672Sthompsa				if (xfer->endpoint->refcount_alloc == 0)
1017199672Sthompsa					panic("usbd_transfer_setup(): Refcount wrapped to zero\n");
1018199672Sthompsa				USB_BUS_UNLOCK(info->bus);
1019199672Sthompsa
1020188982Sthompsa				/*
1021188982Sthompsa				 * Whenever we set ppxfer[] then we
1022188982Sthompsa				 * also need to increment the
1023188982Sthompsa				 * "setup_refcount":
1024188982Sthompsa				 */
1025188982Sthompsa				info->setup_refcount++;
1026184610Salfred
1027188982Sthompsa				/*
1028188982Sthompsa				 * Transfer is successfully setup and
1029188982Sthompsa				 * can be used:
1030188982Sthompsa				 */
1031188982Sthompsa				ppxfer[n] = xfer;
1032184610Salfred			}
1033199672Sthompsa
1034199672Sthompsa			/* check for error */
1035199672Sthompsa			if (parm.err)
1036199672Sthompsa				goto done;
1037184610Salfred		}
1038184610Salfred
1039184610Salfred		if (buf || parm.err) {
1040184610Salfred			goto done;
1041184610Salfred		}
1042184610Salfred		if (refcount == 0) {
1043184610Salfred			/* no transfers - nothing to do ! */
1044184610Salfred			goto done;
1045184610Salfred		}
1046184610Salfred		/* align data properly */
1047184610Salfred		parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
1048184610Salfred
1049184610Salfred		/* store offset temporarily */
1050184610Salfred		parm.size[1] = parm.size[0];
1051184610Salfred
1052184610Salfred		/*
1053184610Salfred		 * The number of DMA tags required depends on
1054184610Salfred		 * the number of endpoints. The current estimate
1055184610Salfred		 * for maximum number of DMA tags per endpoint
1056184610Salfred		 * is two.
1057184610Salfred		 */
1058184610Salfred		parm.dma_tag_max += 2 * MIN(n_setup, USB_EP_MAX);
1059184610Salfred
1060184610Salfred		/*
1061184610Salfred		 * DMA tags for QH, TD, Data and more.
1062184610Salfred		 */
1063184610Salfred		parm.dma_tag_max += 8;
1064184610Salfred
1065184610Salfred		parm.dma_tag_p += parm.dma_tag_max;
1066184610Salfred
1067184610Salfred		parm.size[0] += ((uint8_t *)parm.dma_tag_p) -
1068184610Salfred		    ((uint8_t *)0);
1069184610Salfred
1070184610Salfred		/* align data properly */
1071184610Salfred		parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
1072184610Salfred
1073184610Salfred		/* store offset temporarily */
1074184610Salfred		parm.size[3] = parm.size[0];
1075184610Salfred
1076184610Salfred		parm.size[0] += ((uint8_t *)parm.dma_page_ptr) -
1077184610Salfred		    ((uint8_t *)0);
1078184610Salfred
1079184610Salfred		/* align data properly */
1080184610Salfred		parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
1081184610Salfred
1082184610Salfred		/* store offset temporarily */
1083184610Salfred		parm.size[4] = parm.size[0];
1084184610Salfred
1085184610Salfred		parm.size[0] += ((uint8_t *)parm.dma_page_cache_ptr) -
1086184610Salfred		    ((uint8_t *)0);
1087184610Salfred
1088184610Salfred		/* store end offset temporarily */
1089184610Salfred		parm.size[5] = parm.size[0];
1090184610Salfred
1091184610Salfred		parm.size[0] += ((uint8_t *)parm.xfer_page_cache_ptr) -
1092184610Salfred		    ((uint8_t *)0);
1093184610Salfred
1094184610Salfred		/* store end offset temporarily */
1095184610Salfred
1096184610Salfred		parm.size[2] = parm.size[0];
1097184610Salfred
1098184610Salfred		/* align data properly */
1099184610Salfred		parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
1100184610Salfred
1101184610Salfred		parm.size[6] = parm.size[0];
1102184610Salfred
1103184610Salfred		parm.size[0] += ((uint8_t *)parm.xfer_length_ptr) -
1104184610Salfred		    ((uint8_t *)0);
1105184610Salfred
1106184610Salfred		/* align data properly */
1107184610Salfred		parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
1108184610Salfred
1109184610Salfred		/* allocate zeroed memory */
1110184610Salfred		buf = malloc(parm.size[0], M_USB, M_WAITOK | M_ZERO);
1111184610Salfred
1112184610Salfred		if (buf == NULL) {
1113184610Salfred			parm.err = USB_ERR_NOMEM;
1114184610Salfred			DPRINTFN(0, "cannot allocate memory block for "
1115184610Salfred			    "configuration (%d bytes)\n",
1116184610Salfred			    parm.size[0]);
1117184610Salfred			goto done;
1118184610Salfred		}
1119184610Salfred		parm.dma_tag_p = USB_ADD_BYTES(buf, parm.size[1]);
1120184610Salfred		parm.dma_page_ptr = USB_ADD_BYTES(buf, parm.size[3]);
1121184610Salfred		parm.dma_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[4]);
1122184610Salfred		parm.xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[5]);
1123184610Salfred		parm.xfer_length_ptr = USB_ADD_BYTES(buf, parm.size[6]);
1124184610Salfred	}
1125184610Salfred
1126184610Salfreddone:
1127184610Salfred	if (buf) {
1128184610Salfred		if (info->setup_refcount == 0) {
1129184610Salfred			/*
1130194228Sthompsa			 * "usbd_transfer_unsetup_sub" will unlock
1131184824Sthompsa			 * the bus mutex before returning !
1132184610Salfred			 */
1133184824Sthompsa			USB_BUS_LOCK(info->bus);
1134184610Salfred
1135184610Salfred			/* something went wrong */
1136194228Sthompsa			usbd_transfer_unsetup_sub(info, 0);
1137184610Salfred		}
1138184610Salfred	}
1139184610Salfred	if (parm.err) {
1140194228Sthompsa		usbd_transfer_unsetup(ppxfer, n_setup);
1141184610Salfred	}
1142184610Salfred	return (parm.err);
1143184610Salfred}
1144184610Salfred
1145184610Salfred/*------------------------------------------------------------------------*
1146194228Sthompsa *	usbd_transfer_unsetup_sub - factored out code
1147184610Salfred *------------------------------------------------------------------------*/
1148184610Salfredstatic void
1149194228Sthompsausbd_transfer_unsetup_sub(struct usb_xfer_root *info, uint8_t needs_delay)
1150184610Salfred{
1151218475Shselasky#if USB_HAVE_BUSDMA
1152192984Sthompsa	struct usb_page_cache *pc;
1153218475Shselasky#endif
1154184610Salfred
1155184824Sthompsa	USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
1156184610Salfred
1157184610Salfred	/* wait for any outstanding DMA operations */
1158184610Salfred
1159184610Salfred	if (needs_delay) {
1160193045Sthompsa		usb_timeout_t temp;
1161212134Sthompsa		temp = usbd_get_dma_delay(info->udev);
1162212134Sthompsa		if (temp != 0) {
1163212134Sthompsa			usb_pause_mtx(&info->bus->bus_mtx,
1164212134Sthompsa			    USB_MS_TO_TICKS(temp));
1165212134Sthompsa		}
1166184610Salfred	}
1167187174Sthompsa
1168187174Sthompsa	/* make sure that our done messages are not queued anywhere */
1169194228Sthompsa	usb_proc_mwait(info->done_p, &info->done_m[0], &info->done_m[1]);
1170187174Sthompsa
1171184824Sthompsa	USB_BUS_UNLOCK(info->bus);
1172184610Salfred
1173190180Sthompsa#if USB_HAVE_BUSDMA
1174184610Salfred	/* free DMA'able memory, if any */
1175184610Salfred	pc = info->dma_page_cache_start;
1176184610Salfred	while (pc != info->dma_page_cache_end) {
1177194228Sthompsa		usb_pc_free_mem(pc);
1178184610Salfred		pc++;
1179184610Salfred	}
1180184610Salfred
1181184610Salfred	/* free DMA maps in all "xfer->frbuffers" */
1182184610Salfred	pc = info->xfer_page_cache_start;
1183184610Salfred	while (pc != info->xfer_page_cache_end) {
1184194228Sthompsa		usb_pc_dmamap_destroy(pc);
1185184610Salfred		pc++;
1186184610Salfred	}
1187184610Salfred
1188184610Salfred	/* free all DMA tags */
1189194228Sthompsa	usb_dma_tag_unsetup(&info->dma_parent_tag);
1190190180Sthompsa#endif
1191184610Salfred
1192194227Sthompsa	cv_destroy(&info->cv_drain);
1193184610Salfred
1194184610Salfred	/*
1195184610Salfred	 * free the "memory_base" last, hence the "info" structure is
1196184610Salfred	 * contained within the "memory_base"!
1197184610Salfred	 */
1198184610Salfred	free(info->memory_base, M_USB);
1199184610Salfred}
1200184610Salfred
1201184610Salfred/*------------------------------------------------------------------------*
1202194228Sthompsa *	usbd_transfer_unsetup - unsetup/free an array of USB transfers
1203184610Salfred *
1204184610Salfred * NOTE: All USB transfers in progress will get called back passing
1205184610Salfred * the error code "USB_ERR_CANCELLED" before this function
1206184610Salfred * returns.
1207184610Salfred *------------------------------------------------------------------------*/
1208184610Salfredvoid
1209194228Sthompsausbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
1210184610Salfred{
1211192984Sthompsa	struct usb_xfer *xfer;
1212192984Sthompsa	struct usb_xfer_root *info;
1213184610Salfred	uint8_t needs_delay = 0;
1214184610Salfred
1215184610Salfred	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
1216194228Sthompsa	    "usbd_transfer_unsetup can sleep!");
1217184610Salfred
1218184610Salfred	while (n_setup--) {
1219184610Salfred		xfer = pxfer[n_setup];
1220184610Salfred
1221188982Sthompsa		if (xfer == NULL)
1222188982Sthompsa			continue;
1223184610Salfred
1224188982Sthompsa		info = xfer->xroot;
1225184610Salfred
1226188982Sthompsa		USB_XFER_LOCK(xfer);
1227188982Sthompsa		USB_BUS_LOCK(info->bus);
1228184610Salfred
1229188982Sthompsa		/*
1230188982Sthompsa		 * HINT: when you start/stop a transfer, it might be a
1231188982Sthompsa		 * good idea to directly use the "pxfer[]" structure:
1232188982Sthompsa		 *
1233194228Sthompsa		 * usbd_transfer_start(sc->pxfer[0]);
1234194228Sthompsa		 * usbd_transfer_stop(sc->pxfer[0]);
1235188982Sthompsa		 *
1236188982Sthompsa		 * That way, if your code has many parts that will not
1237188982Sthompsa		 * stop running under the same lock, in other words
1238194228Sthompsa		 * "xfer_mtx", the usbd_transfer_start and
1239194228Sthompsa		 * usbd_transfer_stop functions will simply return
1240188982Sthompsa		 * when they detect a NULL pointer argument.
1241188982Sthompsa		 *
1242188982Sthompsa		 * To avoid any races we clear the "pxfer[]" pointer
1243188982Sthompsa		 * while holding the private mutex of the driver:
1244188982Sthompsa		 */
1245188982Sthompsa		pxfer[n_setup] = NULL;
1246184610Salfred
1247188982Sthompsa		USB_BUS_UNLOCK(info->bus);
1248188982Sthompsa		USB_XFER_UNLOCK(xfer);
1249184610Salfred
1250194228Sthompsa		usbd_transfer_drain(xfer);
1251184610Salfred
1252190180Sthompsa#if USB_HAVE_BUSDMA
1253188982Sthompsa		if (xfer->flags_int.bdma_enable)
1254188982Sthompsa			needs_delay = 1;
1255190180Sthompsa#endif
1256188982Sthompsa		/*
1257193644Sthompsa		 * NOTE: default endpoint does not have an
1258193644Sthompsa		 * interface, even if endpoint->iface_index == 0
1259188982Sthompsa		 */
1260199672Sthompsa		USB_BUS_LOCK(info->bus);
1261199672Sthompsa		xfer->endpoint->refcount_alloc--;
1262199672Sthompsa		USB_BUS_UNLOCK(info->bus);
1263184610Salfred
1264194228Sthompsa		usb_callout_drain(&xfer->timeout_handle);
1265184610Salfred
1266188982Sthompsa		USB_BUS_LOCK(info->bus);
1267184610Salfred
1268188982Sthompsa		USB_ASSERT(info->setup_refcount != 0, ("Invalid setup "
1269199816Sthompsa		    "reference count\n"));
1270184610Salfred
1271188982Sthompsa		info->setup_refcount--;
1272188982Sthompsa
1273188982Sthompsa		if (info->setup_refcount == 0) {
1274194228Sthompsa			usbd_transfer_unsetup_sub(info,
1275188982Sthompsa			    needs_delay);
1276188982Sthompsa		} else {
1277188982Sthompsa			USB_BUS_UNLOCK(info->bus);
1278184610Salfred		}
1279184610Salfred	}
1280184610Salfred}
1281184610Salfred
1282184610Salfred/*------------------------------------------------------------------------*
1283194228Sthompsa *	usbd_control_transfer_init - factored out code
1284184610Salfred *
1285184610Salfred * In USB Device Mode we have to wait for the SETUP packet which
1286192984Sthompsa * containst the "struct usb_device_request" structure, before we can
1287184610Salfred * transfer any data. In USB Host Mode we already have the SETUP
1288184610Salfred * packet at the moment the USB transfer is started. This leads us to
1289184610Salfred * having to setup the USB transfer at two different places in
1290184610Salfred * time. This function just contains factored out control transfer
1291184610Salfred * initialisation code, so that we don't duplicate the code.
1292184610Salfred *------------------------------------------------------------------------*/
1293184610Salfredstatic void
1294194228Sthompsausbd_control_transfer_init(struct usb_xfer *xfer)
1295184610Salfred{
1296192984Sthompsa	struct usb_device_request req;
1297184610Salfred
1298184610Salfred	/* copy out the USB request header */
1299184610Salfred
1300194228Sthompsa	usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
1301184610Salfred
1302184610Salfred	/* setup remainder */
1303184610Salfred
1304184610Salfred	xfer->flags_int.control_rem = UGETW(req.wLength);
1305184610Salfred
1306184610Salfred	/* copy direction to endpoint variable */
1307184610Salfred
1308193644Sthompsa	xfer->endpointno &= ~(UE_DIR_IN | UE_DIR_OUT);
1309193644Sthompsa	xfer->endpointno |=
1310184610Salfred	    (req.bmRequestType & UT_READ) ? UE_DIR_IN : UE_DIR_OUT;
1311184610Salfred}
1312184610Salfred
1313184610Salfred/*------------------------------------------------------------------------*
1314194677Sthompsa *	usbd_setup_ctrl_transfer
1315184610Salfred *
1316184610Salfred * This function handles initialisation of control transfers. Control
1317184610Salfred * transfers are special in that regard that they can both transmit
1318184610Salfred * and receive data.
1319184610Salfred *
1320184610Salfred * Return values:
1321184610Salfred *    0: Success
1322184610Salfred * Else: Failure
1323184610Salfred *------------------------------------------------------------------------*/
1324194677Sthompsastatic int
1325194677Sthompsausbd_setup_ctrl_transfer(struct usb_xfer *xfer)
1326184610Salfred{
1327193045Sthompsa	usb_frlength_t len;
1328184610Salfred
1329184610Salfred	/* Check for control endpoint stall */
1330192552Sthompsa	if (xfer->flags.stall_pipe && xfer->flags_int.control_act) {
1331192552Sthompsa		/* the control transfer is no longer active */
1332192552Sthompsa		xfer->flags_int.control_stall = 1;
1333184610Salfred		xfer->flags_int.control_act = 0;
1334192552Sthompsa	} else {
1335192552Sthompsa		/* don't stall control transfer by default */
1336192552Sthompsa		xfer->flags_int.control_stall = 0;
1337184610Salfred	}
1338190184Sthompsa
1339190184Sthompsa	/* Check for invalid number of frames */
1340190184Sthompsa	if (xfer->nframes > 2) {
1341190184Sthompsa		/*
1342190184Sthompsa		 * If you need to split a control transfer, you
1343190184Sthompsa		 * have to do one part at a time. Only with
1344190184Sthompsa		 * non-control transfers you can do multiple
1345190184Sthompsa		 * parts a time.
1346190184Sthompsa		 */
1347190184Sthompsa		DPRINTFN(0, "Too many frames: %u\n",
1348190184Sthompsa		    (unsigned int)xfer->nframes);
1349190184Sthompsa		goto error;
1350190184Sthompsa	}
1351190184Sthompsa
1352184610Salfred	/*
1353184610Salfred         * Check if there is a control
1354184610Salfred         * transfer in progress:
1355184610Salfred         */
1356184610Salfred	if (xfer->flags_int.control_act) {
1357184610Salfred
1358184610Salfred		if (xfer->flags_int.control_hdr) {
1359184610Salfred
1360184610Salfred			/* clear send header flag */
1361184610Salfred
1362184610Salfred			xfer->flags_int.control_hdr = 0;
1363184610Salfred
1364184610Salfred			/* setup control transfer */
1365192499Sthompsa			if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
1366194228Sthompsa				usbd_control_transfer_init(xfer);
1367184610Salfred			}
1368184610Salfred		}
1369184610Salfred		/* get data length */
1370184610Salfred
1371184610Salfred		len = xfer->sumlen;
1372184610Salfred
1373184610Salfred	} else {
1374184610Salfred
1375184610Salfred		/* the size of the SETUP structure is hardcoded ! */
1376184610Salfred
1377192984Sthompsa		if (xfer->frlengths[0] != sizeof(struct usb_device_request)) {
1378184610Salfred			DPRINTFN(0, "Wrong framelength %u != %zu\n",
1379184610Salfred			    xfer->frlengths[0], sizeof(struct
1380192984Sthompsa			    usb_device_request));
1381184610Salfred			goto error;
1382184610Salfred		}
1383184610Salfred		/* check USB mode */
1384192499Sthompsa		if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
1385184610Salfred
1386184610Salfred			/* check number of frames */
1387184610Salfred			if (xfer->nframes != 1) {
1388184610Salfred				/*
1389184610Salfred			         * We need to receive the setup
1390184610Salfred			         * message first so that we know the
1391184610Salfred			         * data direction!
1392184610Salfred			         */
1393184610Salfred				DPRINTF("Misconfigured transfer\n");
1394184610Salfred				goto error;
1395184610Salfred			}
1396184610Salfred			/*
1397184610Salfred			 * Set a dummy "control_rem" value.  This
1398184610Salfred			 * variable will be overwritten later by a
1399194228Sthompsa			 * call to "usbd_control_transfer_init()" !
1400184610Salfred			 */
1401184610Salfred			xfer->flags_int.control_rem = 0xFFFF;
1402184610Salfred		} else {
1403184610Salfred
1404184610Salfred			/* setup "endpoint" and "control_rem" */
1405184610Salfred
1406194228Sthompsa			usbd_control_transfer_init(xfer);
1407184610Salfred		}
1408184610Salfred
1409184610Salfred		/* set transfer-header flag */
1410184610Salfred
1411184610Salfred		xfer->flags_int.control_hdr = 1;
1412184610Salfred
1413184610Salfred		/* get data length */
1414184610Salfred
1415192984Sthompsa		len = (xfer->sumlen - sizeof(struct usb_device_request));
1416184610Salfred	}
1417184610Salfred
1418184610Salfred	/* check if there is a length mismatch */
1419184610Salfred
1420184610Salfred	if (len > xfer->flags_int.control_rem) {
1421197562Sthompsa		DPRINTFN(0, "Length (%d) greater than "
1422199816Sthompsa		    "remaining length (%d)\n", len,
1423197562Sthompsa		    xfer->flags_int.control_rem);
1424184610Salfred		goto error;
1425184610Salfred	}
1426184610Salfred	/* check if we are doing a short transfer */
1427184610Salfred
1428184610Salfred	if (xfer->flags.force_short_xfer) {
1429184610Salfred		xfer->flags_int.control_rem = 0;
1430184610Salfred	} else {
1431184610Salfred		if ((len != xfer->max_data_length) &&
1432184610Salfred		    (len != xfer->flags_int.control_rem) &&
1433184610Salfred		    (xfer->nframes != 1)) {
1434184610Salfred			DPRINTFN(0, "Short control transfer without "
1435199816Sthompsa			    "force_short_xfer set\n");
1436184610Salfred			goto error;
1437184610Salfred		}
1438184610Salfred		xfer->flags_int.control_rem -= len;
1439184610Salfred	}
1440184610Salfred
1441184610Salfred	/* the status part is executed when "control_act" is 0 */
1442184610Salfred
1443184610Salfred	if ((xfer->flags_int.control_rem > 0) ||
1444184610Salfred	    (xfer->flags.manual_status)) {
1445184610Salfred		/* don't execute the STATUS stage yet */
1446184610Salfred		xfer->flags_int.control_act = 1;
1447184610Salfred
1448184610Salfred		/* sanity check */
1449184610Salfred		if ((!xfer->flags_int.control_hdr) &&
1450184610Salfred		    (xfer->nframes == 1)) {
1451184610Salfred			/*
1452184610Salfred		         * This is not a valid operation!
1453184610Salfred		         */
1454184610Salfred			DPRINTFN(0, "Invalid parameter "
1455184610Salfred			    "combination\n");
1456184610Salfred			goto error;
1457184610Salfred		}
1458184610Salfred	} else {
1459184610Salfred		/* time to execute the STATUS stage */
1460184610Salfred		xfer->flags_int.control_act = 0;
1461184610Salfred	}
1462184610Salfred	return (0);			/* success */
1463184610Salfred
1464184610Salfrederror:
1465184610Salfred	return (1);			/* failure */
1466184610Salfred}
1467184610Salfred
1468184610Salfred/*------------------------------------------------------------------------*
1469194228Sthompsa *	usbd_transfer_submit - start USB hardware for the given transfer
1470184610Salfred *
1471184610Salfred * This function should only be called from the USB callback.
1472184610Salfred *------------------------------------------------------------------------*/
1473184610Salfredvoid
1474194228Sthompsausbd_transfer_submit(struct usb_xfer *xfer)
1475184610Salfred{
1476192984Sthompsa	struct usb_xfer_root *info;
1477192984Sthompsa	struct usb_bus *bus;
1478193045Sthompsa	usb_frcount_t x;
1479184610Salfred
1480191494Sthompsa	info = xfer->xroot;
1481191494Sthompsa	bus = info->bus;
1482191494Sthompsa
1483193644Sthompsa	DPRINTF("xfer=%p, endpoint=%p, nframes=%d, dir=%s\n",
1484193644Sthompsa	    xfer, xfer->endpoint, xfer->nframes, USB_GET_DATA_ISREAD(xfer) ?
1485184610Salfred	    "read" : "write");
1486184610Salfred
1487207077Sthompsa#ifdef USB_DEBUG
1488184610Salfred	if (USB_DEBUG_VAR > 0) {
1489191494Sthompsa		USB_BUS_LOCK(bus);
1490184610Salfred
1491194228Sthompsa		usb_dump_endpoint(xfer->endpoint);
1492184610Salfred
1493191494Sthompsa		USB_BUS_UNLOCK(bus);
1494184610Salfred	}
1495184610Salfred#endif
1496184610Salfred
1497184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
1498191494Sthompsa	USB_BUS_LOCK_ASSERT(bus, MA_NOTOWNED);
1499184610Salfred
1500184610Salfred	/* Only open the USB transfer once! */
1501184610Salfred	if (!xfer->flags_int.open) {
1502184610Salfred		xfer->flags_int.open = 1;
1503184610Salfred
1504184610Salfred		DPRINTF("open\n");
1505184610Salfred
1506191494Sthompsa		USB_BUS_LOCK(bus);
1507193644Sthompsa		(xfer->endpoint->methods->open) (xfer);
1508191494Sthompsa		USB_BUS_UNLOCK(bus);
1509184610Salfred	}
1510184610Salfred	/* set "transferring" flag */
1511184610Salfred	xfer->flags_int.transferring = 1;
1512184610Salfred
1513190734Sthompsa#if USB_HAVE_POWERD
1514186730Salfred	/* increment power reference */
1515194228Sthompsa	usbd_transfer_power_ref(xfer, 1);
1516190734Sthompsa#endif
1517184610Salfred	/*
1518184610Salfred	 * Check if the transfer is waiting on a queue, most
1519184610Salfred	 * frequently the "done_q":
1520184610Salfred	 */
1521184610Salfred	if (xfer->wait_queue) {
1522191494Sthompsa		USB_BUS_LOCK(bus);
1523194228Sthompsa		usbd_transfer_dequeue(xfer);
1524191494Sthompsa		USB_BUS_UNLOCK(bus);
1525184610Salfred	}
1526184610Salfred	/* clear "did_dma_delay" flag */
1527184610Salfred	xfer->flags_int.did_dma_delay = 0;
1528184610Salfred
1529184610Salfred	/* clear "did_close" flag */
1530184610Salfred	xfer->flags_int.did_close = 0;
1531184610Salfred
1532190180Sthompsa#if USB_HAVE_BUSDMA
1533184610Salfred	/* clear "bdma_setup" flag */
1534184610Salfred	xfer->flags_int.bdma_setup = 0;
1535190180Sthompsa#endif
1536184610Salfred	/* by default we cannot cancel any USB transfer immediately */
1537184610Salfred	xfer->flags_int.can_cancel_immed = 0;
1538184610Salfred
1539184610Salfred	/* clear lengths and frame counts by default */
1540184610Salfred	xfer->sumlen = 0;
1541184610Salfred	xfer->actlen = 0;
1542184610Salfred	xfer->aframes = 0;
1543184610Salfred
1544184610Salfred	/* clear any previous errors */
1545184610Salfred	xfer->error = 0;
1546184610Salfred
1547191824Sthompsa	/* Check if the device is still alive */
1548191824Sthompsa	if (info->udev->state < USB_STATE_POWERED) {
1549191824Sthompsa		USB_BUS_LOCK(bus);
1550192051Sthompsa		/*
1551192051Sthompsa		 * Must return cancelled error code else
1552192051Sthompsa		 * device drivers can hang.
1553192051Sthompsa		 */
1554194228Sthompsa		usbd_transfer_done(xfer, USB_ERR_CANCELLED);
1555191824Sthompsa		USB_BUS_UNLOCK(bus);
1556191824Sthompsa		return;
1557191824Sthompsa	}
1558191824Sthompsa
1559184610Salfred	/* sanity check */
1560184610Salfred	if (xfer->nframes == 0) {
1561184610Salfred		if (xfer->flags.stall_pipe) {
1562184610Salfred			/*
1563184610Salfred			 * Special case - want to stall without transferring
1564184610Salfred			 * any data:
1565184610Salfred			 */
1566184610Salfred			DPRINTF("xfer=%p nframes=0: stall "
1567184610Salfred			    "or clear stall!\n", xfer);
1568191494Sthompsa			USB_BUS_LOCK(bus);
1569184610Salfred			xfer->flags_int.can_cancel_immed = 1;
1570184610Salfred			/* start the transfer */
1571194228Sthompsa			usb_command_wrapper(&xfer->endpoint->endpoint_q, xfer);
1572191494Sthompsa			USB_BUS_UNLOCK(bus);
1573184610Salfred			return;
1574184610Salfred		}
1575191494Sthompsa		USB_BUS_LOCK(bus);
1576194228Sthompsa		usbd_transfer_done(xfer, USB_ERR_INVAL);
1577191494Sthompsa		USB_BUS_UNLOCK(bus);
1578184610Salfred		return;
1579184610Salfred	}
1580184610Salfred	/* compute total transfer length */
1581184610Salfred
1582184610Salfred	for (x = 0; x != xfer->nframes; x++) {
1583184610Salfred		xfer->sumlen += xfer->frlengths[x];
1584184610Salfred		if (xfer->sumlen < xfer->frlengths[x]) {
1585184610Salfred			/* length wrapped around */
1586191494Sthompsa			USB_BUS_LOCK(bus);
1587194228Sthompsa			usbd_transfer_done(xfer, USB_ERR_INVAL);
1588191494Sthompsa			USB_BUS_UNLOCK(bus);
1589184610Salfred			return;
1590184610Salfred		}
1591184610Salfred	}
1592184610Salfred
1593184610Salfred	/* clear some internal flags */
1594184610Salfred
1595184610Salfred	xfer->flags_int.short_xfer_ok = 0;
1596184610Salfred	xfer->flags_int.short_frames_ok = 0;
1597184610Salfred
1598184610Salfred	/* check if this is a control transfer */
1599184610Salfred
1600184610Salfred	if (xfer->flags_int.control_xfr) {
1601184610Salfred
1602194677Sthompsa		if (usbd_setup_ctrl_transfer(xfer)) {
1603191494Sthompsa			USB_BUS_LOCK(bus);
1604194228Sthompsa			usbd_transfer_done(xfer, USB_ERR_STALLED);
1605191494Sthompsa			USB_BUS_UNLOCK(bus);
1606184610Salfred			return;
1607184610Salfred		}
1608184610Salfred	}
1609184610Salfred	/*
1610184610Salfred	 * Setup filtered version of some transfer flags,
1611184610Salfred	 * in case of data read direction
1612184610Salfred	 */
1613184610Salfred	if (USB_GET_DATA_ISREAD(xfer)) {
1614184610Salfred
1615190184Sthompsa		if (xfer->flags.short_frames_ok) {
1616190184Sthompsa			xfer->flags_int.short_xfer_ok = 1;
1617190184Sthompsa			xfer->flags_int.short_frames_ok = 1;
1618190184Sthompsa		} else if (xfer->flags.short_xfer_ok) {
1619190184Sthompsa			xfer->flags_int.short_xfer_ok = 1;
1620184610Salfred
1621190184Sthompsa			/* check for control transfer */
1622190184Sthompsa			if (xfer->flags_int.control_xfr) {
1623190184Sthompsa				/*
1624190184Sthompsa				 * 1) Control transfers do not support
1625190184Sthompsa				 * reception of multiple short USB
1626190184Sthompsa				 * frames in host mode and device side
1627190184Sthompsa				 * mode, with exception of:
1628190184Sthompsa				 *
1629190184Sthompsa				 * 2) Due to sometimes buggy device
1630190184Sthompsa				 * side firmware we need to do a
1631190184Sthompsa				 * STATUS stage in case of short
1632190184Sthompsa				 * control transfers in USB host mode.
1633190184Sthompsa				 * The STATUS stage then becomes the
1634190184Sthompsa				 * "alt_next" to the DATA stage.
1635190184Sthompsa				 */
1636184610Salfred				xfer->flags_int.short_frames_ok = 1;
1637184610Salfred			}
1638184610Salfred		}
1639184610Salfred	}
1640184610Salfred	/*
1641184610Salfred	 * Check if BUS-DMA support is enabled and try to load virtual
1642184610Salfred	 * buffers into DMA, if any:
1643184610Salfred	 */
1644190180Sthompsa#if USB_HAVE_BUSDMA
1645184610Salfred	if (xfer->flags_int.bdma_enable) {
1646184610Salfred		/* insert the USB transfer last in the BUS-DMA queue */
1647194228Sthompsa		usb_command_wrapper(&xfer->xroot->dma_q, xfer);
1648184610Salfred		return;
1649184610Salfred	}
1650190180Sthompsa#endif
1651184610Salfred	/*
1652184610Salfred	 * Enter the USB transfer into the Host Controller or
1653184610Salfred	 * Device Controller schedule:
1654184610Salfred	 */
1655194228Sthompsa	usbd_pipe_enter(xfer);
1656184610Salfred}
1657184610Salfred
1658184610Salfred/*------------------------------------------------------------------------*
1659194228Sthompsa *	usbd_pipe_enter - factored out code
1660184610Salfred *------------------------------------------------------------------------*/
1661184610Salfredvoid
1662194228Sthompsausbd_pipe_enter(struct usb_xfer *xfer)
1663184610Salfred{
1664193644Sthompsa	struct usb_endpoint *ep;
1665184610Salfred
1666184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
1667184610Salfred
1668187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
1669184610Salfred
1670193644Sthompsa	ep = xfer->endpoint;
1671184610Salfred
1672184610Salfred	DPRINTF("enter\n");
1673184610Salfred
1674184610Salfred	/* enter the transfer */
1675193644Sthompsa	(ep->methods->enter) (xfer);
1676184610Salfred
1677190738Sthompsa	xfer->flags_int.can_cancel_immed = 1;
1678190738Sthompsa
1679190738Sthompsa	/* check for transfer error */
1680190738Sthompsa	if (xfer->error) {
1681190738Sthompsa		/* some error has happened */
1682194228Sthompsa		usbd_transfer_done(xfer, 0);
1683190738Sthompsa		USB_BUS_UNLOCK(xfer->xroot->bus);
1684190738Sthompsa		return;
1685184610Salfred	}
1686184610Salfred
1687184610Salfred	/* start the transfer */
1688194228Sthompsa	usb_command_wrapper(&ep->endpoint_q, xfer);
1689187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
1690184610Salfred}
1691184610Salfred
1692184610Salfred/*------------------------------------------------------------------------*
1693194228Sthompsa *	usbd_transfer_start - start an USB transfer
1694184610Salfred *
1695184610Salfred * NOTE: Calling this function more than one time will only
1696184610Salfred *       result in a single transfer start, until the USB transfer
1697184610Salfred *       completes.
1698184610Salfred *------------------------------------------------------------------------*/
1699184610Salfredvoid
1700194228Sthompsausbd_transfer_start(struct usb_xfer *xfer)
1701184610Salfred{
1702184610Salfred	if (xfer == NULL) {
1703184610Salfred		/* transfer is gone */
1704184610Salfred		return;
1705184610Salfred	}
1706184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
1707184610Salfred
1708184610Salfred	/* mark the USB transfer started */
1709184610Salfred
1710184610Salfred	if (!xfer->flags_int.started) {
1711197562Sthompsa		/* lock the BUS lock to avoid races updating flags_int */
1712197562Sthompsa		USB_BUS_LOCK(xfer->xroot->bus);
1713184610Salfred		xfer->flags_int.started = 1;
1714197562Sthompsa		USB_BUS_UNLOCK(xfer->xroot->bus);
1715184610Salfred	}
1716184610Salfred	/* check if the USB transfer callback is already transferring */
1717184610Salfred
1718184610Salfred	if (xfer->flags_int.transferring) {
1719184610Salfred		return;
1720184610Salfred	}
1721187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
1722184610Salfred	/* call the USB transfer callback */
1723194228Sthompsa	usbd_callback_ss_done_defer(xfer);
1724187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
1725184610Salfred}
1726184610Salfred
1727184610Salfred/*------------------------------------------------------------------------*
1728194228Sthompsa *	usbd_transfer_stop - stop an USB transfer
1729184610Salfred *
1730184610Salfred * NOTE: Calling this function more than one time will only
1731184610Salfred *       result in a single transfer stop.
1732184610Salfred * NOTE: When this function returns it is not safe to free nor
1733194228Sthompsa *       reuse any DMA buffers. See "usbd_transfer_drain()".
1734184610Salfred *------------------------------------------------------------------------*/
1735184610Salfredvoid
1736194228Sthompsausbd_transfer_stop(struct usb_xfer *xfer)
1737184610Salfred{
1738193644Sthompsa	struct usb_endpoint *ep;
1739184610Salfred
1740184610Salfred	if (xfer == NULL) {
1741184610Salfred		/* transfer is gone */
1742184610Salfred		return;
1743184610Salfred	}
1744184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
1745184610Salfred
1746184610Salfred	/* check if the USB transfer was ever opened */
1747184610Salfred
1748184610Salfred	if (!xfer->flags_int.open) {
1749197562Sthompsa		if (xfer->flags_int.started) {
1750197562Sthompsa			/* nothing to do except clearing the "started" flag */
1751197562Sthompsa			/* lock the BUS lock to avoid races updating flags_int */
1752197562Sthompsa			USB_BUS_LOCK(xfer->xroot->bus);
1753197562Sthompsa			xfer->flags_int.started = 0;
1754197562Sthompsa			USB_BUS_UNLOCK(xfer->xroot->bus);
1755197562Sthompsa		}
1756184610Salfred		return;
1757184610Salfred	}
1758184610Salfred	/* try to stop the current USB transfer */
1759184610Salfred
1760187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
1761197562Sthompsa	/* override any previous error */
1762197562Sthompsa	xfer->error = USB_ERR_CANCELLED;
1763197562Sthompsa
1764184610Salfred	/*
1765184610Salfred	 * Clear "open" and "started" when both private and USB lock
1766184610Salfred	 * is locked so that we don't get a race updating "flags_int"
1767184610Salfred	 */
1768184610Salfred	xfer->flags_int.open = 0;
1769184610Salfred	xfer->flags_int.started = 0;
1770184610Salfred
1771184610Salfred	/*
1772184610Salfred	 * Check if we can cancel the USB transfer immediately.
1773184610Salfred	 */
1774184610Salfred	if (xfer->flags_int.transferring) {
1775184610Salfred		if (xfer->flags_int.can_cancel_immed &&
1776184610Salfred		    (!xfer->flags_int.did_close)) {
1777184610Salfred			DPRINTF("close\n");
1778184610Salfred			/*
1779184610Salfred			 * The following will lead to an USB_ERR_CANCELLED
1780184610Salfred			 * error code being passed to the USB callback.
1781184610Salfred			 */
1782193644Sthompsa			(xfer->endpoint->methods->close) (xfer);
1783184610Salfred			/* only close once */
1784184610Salfred			xfer->flags_int.did_close = 1;
1785184610Salfred		} else {
1786184610Salfred			/* need to wait for the next done callback */
1787184610Salfred		}
1788184610Salfred	} else {
1789184610Salfred		DPRINTF("close\n");
1790184610Salfred
1791184610Salfred		/* close here and now */
1792193644Sthompsa		(xfer->endpoint->methods->close) (xfer);
1793184610Salfred
1794184610Salfred		/*
1795184610Salfred		 * Any additional DMA delay is done by
1796194228Sthompsa		 * "usbd_transfer_unsetup()".
1797184610Salfred		 */
1798184610Salfred
1799184610Salfred		/*
1800184610Salfred		 * Special case. Check if we need to restart a blocked
1801193644Sthompsa		 * endpoint.
1802184610Salfred		 */
1803193644Sthompsa		ep = xfer->endpoint;
1804184610Salfred
1805184610Salfred		/*
1806184610Salfred		 * If the current USB transfer is completing we need
1807184610Salfred		 * to start the next one:
1808184610Salfred		 */
1809193644Sthompsa		if (ep->endpoint_q.curr == xfer) {
1810194228Sthompsa			usb_command_wrapper(&ep->endpoint_q, NULL);
1811184610Salfred		}
1812184610Salfred	}
1813184610Salfred
1814187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
1815184610Salfred}
1816184610Salfred
1817184610Salfred/*------------------------------------------------------------------------*
1818194228Sthompsa *	usbd_transfer_pending
1819184610Salfred *
1820184610Salfred * This function will check if an USB transfer is pending which is a
1821184610Salfred * little bit complicated!
1822184610Salfred * Return values:
1823184610Salfred * 0: Not pending
1824184610Salfred * 1: Pending: The USB transfer will receive a callback in the future.
1825184610Salfred *------------------------------------------------------------------------*/
1826184610Salfreduint8_t
1827194228Sthompsausbd_transfer_pending(struct usb_xfer *xfer)
1828184610Salfred{
1829192984Sthompsa	struct usb_xfer_root *info;
1830192984Sthompsa	struct usb_xfer_queue *pq;
1831184610Salfred
1832188600Sthompsa	if (xfer == NULL) {
1833188600Sthompsa		/* transfer is gone */
1834188600Sthompsa		return (0);
1835188600Sthompsa	}
1836184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
1837184610Salfred
1838184610Salfred	if (xfer->flags_int.transferring) {
1839184610Salfred		/* trivial case */
1840184610Salfred		return (1);
1841184610Salfred	}
1842187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
1843184610Salfred	if (xfer->wait_queue) {
1844184610Salfred		/* we are waiting on a queue somewhere */
1845187173Sthompsa		USB_BUS_UNLOCK(xfer->xroot->bus);
1846184610Salfred		return (1);
1847184610Salfred	}
1848187173Sthompsa	info = xfer->xroot;
1849184610Salfred	pq = &info->done_q;
1850184610Salfred
1851184610Salfred	if (pq->curr == xfer) {
1852184610Salfred		/* we are currently scheduled for callback */
1853187173Sthompsa		USB_BUS_UNLOCK(xfer->xroot->bus);
1854184610Salfred		return (1);
1855184610Salfred	}
1856184610Salfred	/* we are not pending */
1857187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
1858184610Salfred	return (0);
1859184610Salfred}
1860184610Salfred
1861184610Salfred/*------------------------------------------------------------------------*
1862194228Sthompsa *	usbd_transfer_drain
1863184610Salfred *
1864184610Salfred * This function will stop the USB transfer and wait for any
1865184610Salfred * additional BUS-DMA and HW-DMA operations to complete. Buffers that
1866184610Salfred * are loaded into DMA can safely be freed or reused after that this
1867184610Salfred * function has returned.
1868184610Salfred *------------------------------------------------------------------------*/
1869184610Salfredvoid
1870194228Sthompsausbd_transfer_drain(struct usb_xfer *xfer)
1871184610Salfred{
1872184610Salfred	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
1873194228Sthompsa	    "usbd_transfer_drain can sleep!");
1874184610Salfred
1875184610Salfred	if (xfer == NULL) {
1876184610Salfred		/* transfer is gone */
1877184610Salfred		return;
1878184610Salfred	}
1879187173Sthompsa	if (xfer->xroot->xfer_mtx != &Giant) {
1880184824Sthompsa		USB_XFER_LOCK_ASSERT(xfer, MA_NOTOWNED);
1881184610Salfred	}
1882184824Sthompsa	USB_XFER_LOCK(xfer);
1883184610Salfred
1884194228Sthompsa	usbd_transfer_stop(xfer);
1885184610Salfred
1886198775Sthompsa	while (usbd_transfer_pending(xfer) ||
1887198775Sthompsa	    xfer->flags_int.doing_callback) {
1888198775Sthompsa
1889198775Sthompsa		/*
1890198775Sthompsa		 * It is allowed that the callback can drop its
1891198775Sthompsa		 * transfer mutex. In that case checking only
1892198775Sthompsa		 * "usbd_transfer_pending()" is not enough to tell if
1893198775Sthompsa		 * the USB transfer is fully drained. We also need to
1894198775Sthompsa		 * check the internal "doing_callback" flag.
1895198775Sthompsa		 */
1896184610Salfred		xfer->flags_int.draining = 1;
1897198775Sthompsa
1898184610Salfred		/*
1899184610Salfred		 * Wait until the current outstanding USB
1900184610Salfred		 * transfer is complete !
1901184610Salfred		 */
1902194227Sthompsa		cv_wait(&xfer->xroot->cv_drain, xfer->xroot->xfer_mtx);
1903184610Salfred	}
1904184824Sthompsa	USB_XFER_UNLOCK(xfer);
1905184610Salfred}
1906184610Salfred
1907194677Sthompsastruct usb_page_cache *
1908194677Sthompsausbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
1909194677Sthompsa{
1910194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
1911194677Sthompsa
1912194677Sthompsa	return (&xfer->frbuffers[frindex]);
1913194677Sthompsa}
1914194677Sthompsa
1915199059Sthompsa/*------------------------------------------------------------------------*
1916199059Sthompsa *	usbd_xfer_get_fps_shift
1917199059Sthompsa *
1918199059Sthompsa * The following function is only useful for isochronous transfers. It
1919199059Sthompsa * returns how many times the frame execution rate has been shifted
1920199059Sthompsa * down.
1921199059Sthompsa *
1922199059Sthompsa * Return value:
1923199059Sthompsa * Success: 0..3
1924199059Sthompsa * Failure: 0
1925199059Sthompsa *------------------------------------------------------------------------*/
1926199059Sthompsauint8_t
1927199059Sthompsausbd_xfer_get_fps_shift(struct usb_xfer *xfer)
1928199059Sthompsa{
1929199059Sthompsa	return (xfer->fps_shift);
1930199059Sthompsa}
1931199059Sthompsa
1932194677Sthompsausb_frlength_t
1933194682Sthompsausbd_xfer_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex)
1934194677Sthompsa{
1935194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
1936194677Sthompsa
1937194677Sthompsa	return (xfer->frlengths[frindex]);
1938194677Sthompsa}
1939194677Sthompsa
1940184610Salfred/*------------------------------------------------------------------------*
1941194677Sthompsa *	usbd_xfer_set_frame_data
1942184610Salfred *
1943184610Salfred * This function sets the pointer of the buffer that should
1944184610Salfred * loaded directly into DMA for the given USB frame. Passing "ptr"
1945184610Salfred * equal to NULL while the corresponding "frlength" is greater
1946184610Salfred * than zero gives undefined results!
1947184610Salfred *------------------------------------------------------------------------*/
1948184610Salfredvoid
1949194677Sthompsausbd_xfer_set_frame_data(struct usb_xfer *xfer, usb_frcount_t frindex,
1950194677Sthompsa    void *ptr, usb_frlength_t len)
1951184610Salfred{
1952194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
1953194677Sthompsa
1954184610Salfred	/* set virtual address to load and length */
1955184610Salfred	xfer->frbuffers[frindex].buffer = ptr;
1956194677Sthompsa	usbd_xfer_set_frame_len(xfer, frindex, len);
1957184610Salfred}
1958184610Salfred
1959194677Sthompsavoid
1960194682Sthompsausbd_xfer_frame_data(struct usb_xfer *xfer, usb_frcount_t frindex,
1961194677Sthompsa    void **ptr, int *len)
1962194677Sthompsa{
1963194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
1964194677Sthompsa
1965194677Sthompsa	if (ptr != NULL)
1966194677Sthompsa		*ptr = xfer->frbuffers[frindex].buffer;
1967194677Sthompsa	if (len != NULL)
1968194677Sthompsa		*len = xfer->frlengths[frindex];
1969194677Sthompsa}
1970194677Sthompsa
1971194677Sthompsavoid
1972194677Sthompsausbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes,
1973194677Sthompsa    int *nframes)
1974194677Sthompsa{
1975194677Sthompsa	if (actlen != NULL)
1976194677Sthompsa		*actlen = xfer->actlen;
1977194677Sthompsa	if (sumlen != NULL)
1978194677Sthompsa		*sumlen = xfer->sumlen;
1979194677Sthompsa	if (aframes != NULL)
1980194677Sthompsa		*aframes = xfer->aframes;
1981194677Sthompsa	if (nframes != NULL)
1982194677Sthompsa		*nframes = xfer->nframes;
1983194677Sthompsa}
1984194677Sthompsa
1985184610Salfred/*------------------------------------------------------------------------*
1986194677Sthompsa *	usbd_xfer_set_frame_offset
1987184610Salfred *
1988184610Salfred * This function sets the frame data buffer offset relative to the beginning
1989184610Salfred * of the USB DMA buffer allocated for this USB transfer.
1990184610Salfred *------------------------------------------------------------------------*/
1991184610Salfredvoid
1992194677Sthompsausbd_xfer_set_frame_offset(struct usb_xfer *xfer, usb_frlength_t offset,
1993193045Sthompsa    usb_frcount_t frindex)
1994184610Salfred{
1995194677Sthompsa	KASSERT(!xfer->flags.ext_buffer, ("Cannot offset data frame "
1996199816Sthompsa	    "when the USB buffer is external\n"));
1997194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
1998184610Salfred
1999184610Salfred	/* set virtual address to load */
2000184610Salfred	xfer->frbuffers[frindex].buffer =
2001184610Salfred	    USB_ADD_BYTES(xfer->local_buffer, offset);
2002184610Salfred}
2003184610Salfred
2004194677Sthompsavoid
2005194677Sthompsausbd_xfer_set_interval(struct usb_xfer *xfer, int i)
2006194677Sthompsa{
2007194677Sthompsa	xfer->interval = i;
2008194677Sthompsa}
2009194677Sthompsa
2010194677Sthompsavoid
2011194677Sthompsausbd_xfer_set_timeout(struct usb_xfer *xfer, int t)
2012194677Sthompsa{
2013194677Sthompsa	xfer->timeout = t;
2014194677Sthompsa}
2015194677Sthompsa
2016194677Sthompsavoid
2017194677Sthompsausbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
2018194677Sthompsa{
2019194677Sthompsa	xfer->nframes = n;
2020194677Sthompsa}
2021194677Sthompsa
2022194677Sthompsausb_frcount_t
2023194677Sthompsausbd_xfer_max_frames(struct usb_xfer *xfer)
2024194677Sthompsa{
2025194677Sthompsa	return (xfer->max_frame_count);
2026194677Sthompsa}
2027194677Sthompsa
2028194677Sthompsausb_frlength_t
2029194677Sthompsausbd_xfer_max_len(struct usb_xfer *xfer)
2030194677Sthompsa{
2031194677Sthompsa	return (xfer->max_data_length);
2032194677Sthompsa}
2033194677Sthompsa
2034194677Sthompsausb_frlength_t
2035194677Sthompsausbd_xfer_max_framelen(struct usb_xfer *xfer)
2036194677Sthompsa{
2037194677Sthompsa	return (xfer->max_frame_size);
2038194677Sthompsa}
2039194677Sthompsa
2040194677Sthompsavoid
2041194677Sthompsausbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex,
2042194677Sthompsa    usb_frlength_t len)
2043194677Sthompsa{
2044194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
2045194677Sthompsa
2046194677Sthompsa	xfer->frlengths[frindex] = len;
2047194677Sthompsa}
2048194677Sthompsa
2049184610Salfred/*------------------------------------------------------------------------*
2050194228Sthompsa *	usb_callback_proc - factored out code
2051184610Salfred *
2052184610Salfred * This function performs USB callbacks.
2053184610Salfred *------------------------------------------------------------------------*/
2054184610Salfredstatic void
2055194228Sthompsausb_callback_proc(struct usb_proc_msg *_pm)
2056184610Salfred{
2057192984Sthompsa	struct usb_done_msg *pm = (void *)_pm;
2058192984Sthompsa	struct usb_xfer_root *info = pm->xroot;
2059184610Salfred
2060184610Salfred	/* Change locking order */
2061184824Sthompsa	USB_BUS_UNLOCK(info->bus);
2062184610Salfred
2063184610Salfred	/*
2064184610Salfred	 * We exploit the fact that the mutex is the same for all
2065184610Salfred	 * callbacks that will be called from this thread:
2066184610Salfred	 */
2067187173Sthompsa	mtx_lock(info->xfer_mtx);
2068184824Sthompsa	USB_BUS_LOCK(info->bus);
2069184610Salfred
2070184610Salfred	/* Continue where we lost track */
2071194228Sthompsa	usb_command_wrapper(&info->done_q,
2072184610Salfred	    info->done_q.curr);
2073184610Salfred
2074187173Sthompsa	mtx_unlock(info->xfer_mtx);
2075184610Salfred}
2076184610Salfred
2077184610Salfred/*------------------------------------------------------------------------*
2078194228Sthompsa *	usbd_callback_ss_done_defer
2079184610Salfred *
2080184610Salfred * This function will defer the start, stop and done callback to the
2081184610Salfred * correct thread.
2082184610Salfred *------------------------------------------------------------------------*/
2083184610Salfredstatic void
2084194228Sthompsausbd_callback_ss_done_defer(struct usb_xfer *xfer)
2085184610Salfred{
2086192984Sthompsa	struct usb_xfer_root *info = xfer->xroot;
2087192984Sthompsa	struct usb_xfer_queue *pq = &info->done_q;
2088184610Salfred
2089187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2090184824Sthompsa
2091184610Salfred	if (pq->curr != xfer) {
2092194228Sthompsa		usbd_transfer_enqueue(pq, xfer);
2093184610Salfred	}
2094184610Salfred	if (!pq->recurse_1) {
2095184610Salfred
2096184610Salfred		/*
2097184610Salfred	         * We have to postpone the callback due to the fact we
2098184610Salfred	         * will have a Lock Order Reversal, LOR, if we try to
2099184610Salfred	         * proceed !
2100184610Salfred	         */
2101194228Sthompsa		if (usb_proc_msignal(info->done_p,
2102184610Salfred		    &info->done_m[0], &info->done_m[1])) {
2103184610Salfred			/* ignore */
2104184610Salfred		}
2105184610Salfred	} else {
2106184610Salfred		/* clear second recurse flag */
2107184610Salfred		pq->recurse_2 = 0;
2108184610Salfred	}
2109184610Salfred	return;
2110184610Salfred
2111184610Salfred}
2112184610Salfred
2113184610Salfred/*------------------------------------------------------------------------*
2114194228Sthompsa *	usbd_callback_wrapper
2115184610Salfred *
2116184610Salfred * This is a wrapper for USB callbacks. This wrapper does some
2117184610Salfred * auto-magic things like figuring out if we can call the callback
2118184610Salfred * directly from the current context or if we need to wakeup the
2119184610Salfred * interrupt process.
2120184610Salfred *------------------------------------------------------------------------*/
2121184610Salfredstatic void
2122194228Sthompsausbd_callback_wrapper(struct usb_xfer_queue *pq)
2123184610Salfred{
2124192984Sthompsa	struct usb_xfer *xfer = pq->curr;
2125192984Sthompsa	struct usb_xfer_root *info = xfer->xroot;
2126184610Salfred
2127190738Sthompsa	USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
2128190738Sthompsa	if (!mtx_owned(info->xfer_mtx)) {
2129184610Salfred		/*
2130184610Salfred	       	 * Cases that end up here:
2131184610Salfred		 *
2132184610Salfred		 * 5) HW interrupt done callback or other source.
2133184610Salfred		 */
2134184610Salfred		DPRINTFN(3, "case 5\n");
2135184610Salfred
2136184610Salfred		/*
2137184610Salfred	         * We have to postpone the callback due to the fact we
2138184610Salfred	         * will have a Lock Order Reversal, LOR, if we try to
2139184610Salfred	         * proceed !
2140184610Salfred	         */
2141194228Sthompsa		if (usb_proc_msignal(info->done_p,
2142184610Salfred		    &info->done_m[0], &info->done_m[1])) {
2143184610Salfred			/* ignore */
2144184610Salfred		}
2145184610Salfred		return;
2146184610Salfred	}
2147184610Salfred	/*
2148184610Salfred	 * Cases that end up here:
2149184610Salfred	 *
2150184610Salfred	 * 1) We are starting a transfer
2151184610Salfred	 * 2) We are prematurely calling back a transfer
2152184610Salfred	 * 3) We are stopping a transfer
2153184610Salfred	 * 4) We are doing an ordinary callback
2154184610Salfred	 */
2155184610Salfred	DPRINTFN(3, "case 1-4\n");
2156184610Salfred	/* get next USB transfer in the queue */
2157184610Salfred	info->done_q.curr = NULL;
2158184610Salfred
2159198775Sthompsa	/* set flag in case of drain */
2160198775Sthompsa	xfer->flags_int.doing_callback = 1;
2161198775Sthompsa
2162190738Sthompsa	USB_BUS_UNLOCK(info->bus);
2163190738Sthompsa	USB_BUS_LOCK_ASSERT(info->bus, MA_NOTOWNED);
2164184610Salfred
2165184610Salfred	/* set correct USB state for callback */
2166184610Salfred	if (!xfer->flags_int.transferring) {
2167194228Sthompsa		xfer->usb_state = USB_ST_SETUP;
2168184610Salfred		if (!xfer->flags_int.started) {
2169184610Salfred			/* we got stopped before we even got started */
2170190738Sthompsa			USB_BUS_LOCK(info->bus);
2171184610Salfred			goto done;
2172184610Salfred		}
2173184610Salfred	} else {
2174184610Salfred
2175194228Sthompsa		if (usbd_callback_wrapper_sub(xfer)) {
2176184610Salfred			/* the callback has been deferred */
2177190738Sthompsa			USB_BUS_LOCK(info->bus);
2178184610Salfred			goto done;
2179184610Salfred		}
2180190734Sthompsa#if USB_HAVE_POWERD
2181186730Salfred		/* decrement power reference */
2182194228Sthompsa		usbd_transfer_power_ref(xfer, -1);
2183190734Sthompsa#endif
2184184610Salfred		xfer->flags_int.transferring = 0;
2185184610Salfred
2186184610Salfred		if (xfer->error) {
2187194228Sthompsa			xfer->usb_state = USB_ST_ERROR;
2188184610Salfred		} else {
2189184610Salfred			/* set transferred state */
2190194228Sthompsa			xfer->usb_state = USB_ST_TRANSFERRED;
2191190180Sthompsa#if USB_HAVE_BUSDMA
2192184610Salfred			/* sync DMA memory, if any */
2193184610Salfred			if (xfer->flags_int.bdma_enable &&
2194184610Salfred			    (!xfer->flags_int.bdma_no_post_sync)) {
2195194228Sthompsa				usb_bdma_post_sync(xfer);
2196184610Salfred			}
2197190180Sthompsa#endif
2198184610Salfred		}
2199184610Salfred	}
2200184610Salfred
2201217558Shselasky#if USB_HAVE_PF
2202215649Sweongyo	if (xfer->usb_state != USB_ST_SETUP)
2203215649Sweongyo		usbpf_xfertap(xfer, USBPF_XFERTAP_DONE);
2204217558Shselasky#endif
2205184610Salfred	/* call processing routine */
2206194677Sthompsa	(xfer->callback) (xfer, xfer->error);
2207184610Salfred
2208184610Salfred	/* pickup the USB mutex again */
2209190738Sthompsa	USB_BUS_LOCK(info->bus);
2210184610Salfred
2211184610Salfred	/*
2212184610Salfred	 * Check if we got started after that we got cancelled, but
2213187166Sthompsa	 * before we managed to do the callback.
2214184610Salfred	 */
2215184610Salfred	if ((!xfer->flags_int.open) &&
2216184610Salfred	    (xfer->flags_int.started) &&
2217194228Sthompsa	    (xfer->usb_state == USB_ST_ERROR)) {
2218198775Sthompsa		/* clear flag in case of drain */
2219198775Sthompsa		xfer->flags_int.doing_callback = 0;
2220184610Salfred		/* try to loop, but not recursivly */
2221194228Sthompsa		usb_command_wrapper(&info->done_q, xfer);
2222184610Salfred		return;
2223187166Sthompsa	}
2224187166Sthompsa
2225187166Sthompsadone:
2226198775Sthompsa	/* clear flag in case of drain */
2227198775Sthompsa	xfer->flags_int.doing_callback = 0;
2228198775Sthompsa
2229187166Sthompsa	/*
2230187166Sthompsa	 * Check if we are draining.
2231187166Sthompsa	 */
2232187166Sthompsa	if (xfer->flags_int.draining &&
2233184610Salfred	    (!xfer->flags_int.transferring)) {
2234194228Sthompsa		/* "usbd_transfer_drain()" is waiting for end of transfer */
2235184610Salfred		xfer->flags_int.draining = 0;
2236194227Sthompsa		cv_broadcast(&info->cv_drain);
2237184610Salfred	}
2238187166Sthompsa
2239184610Salfred	/* do the next callback, if any */
2240194228Sthompsa	usb_command_wrapper(&info->done_q,
2241184610Salfred	    info->done_q.curr);
2242184610Salfred}
2243184610Salfred
2244184610Salfred/*------------------------------------------------------------------------*
2245194228Sthompsa *	usb_dma_delay_done_cb
2246184610Salfred *
2247184610Salfred * This function is called when the DMA delay has been exectuded, and
2248184610Salfred * will make sure that the callback is called to complete the USB
2249184610Salfred * transfer. This code path is ususally only used when there is an USB
2250184610Salfred * error like USB_ERR_CANCELLED.
2251184610Salfred *------------------------------------------------------------------------*/
2252213435Shselaskyvoid
2253213435Shselaskyusb_dma_delay_done_cb(struct usb_xfer *xfer)
2254184610Salfred{
2255187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2256184610Salfred
2257184610Salfred	DPRINTFN(3, "Completed %p\n", xfer);
2258184610Salfred
2259184610Salfred	/* queue callback for execution, again */
2260194228Sthompsa	usbd_transfer_done(xfer, 0);
2261184610Salfred}
2262184610Salfred
2263184610Salfred/*------------------------------------------------------------------------*
2264194228Sthompsa *	usbd_transfer_dequeue
2265184610Salfred *
2266184610Salfred *  - This function is used to remove an USB transfer from a USB
2267184610Salfred *  transfer queue.
2268184610Salfred *
2269184610Salfred *  - This function can be called multiple times in a row.
2270184610Salfred *------------------------------------------------------------------------*/
2271184610Salfredvoid
2272194228Sthompsausbd_transfer_dequeue(struct usb_xfer *xfer)
2273184610Salfred{
2274192984Sthompsa	struct usb_xfer_queue *pq;
2275184610Salfred
2276184610Salfred	pq = xfer->wait_queue;
2277184610Salfred	if (pq) {
2278184610Salfred		TAILQ_REMOVE(&pq->head, xfer, wait_entry);
2279184610Salfred		xfer->wait_queue = NULL;
2280184610Salfred	}
2281184610Salfred}
2282184610Salfred
2283184610Salfred/*------------------------------------------------------------------------*
2284194228Sthompsa *	usbd_transfer_enqueue
2285184610Salfred *
2286184610Salfred *  - This function is used to insert an USB transfer into a USB *
2287184610Salfred *  transfer queue.
2288184610Salfred *
2289184610Salfred *  - This function can be called multiple times in a row.
2290184610Salfred *------------------------------------------------------------------------*/
2291184610Salfredvoid
2292194228Sthompsausbd_transfer_enqueue(struct usb_xfer_queue *pq, struct usb_xfer *xfer)
2293184610Salfred{
2294184610Salfred	/*
2295184610Salfred	 * Insert the USB transfer into the queue, if it is not
2296184610Salfred	 * already on a USB transfer queue:
2297184610Salfred	 */
2298184610Salfred	if (xfer->wait_queue == NULL) {
2299184610Salfred		xfer->wait_queue = pq;
2300184610Salfred		TAILQ_INSERT_TAIL(&pq->head, xfer, wait_entry);
2301184610Salfred	}
2302184610Salfred}
2303184610Salfred
2304184610Salfred/*------------------------------------------------------------------------*
2305194228Sthompsa *	usbd_transfer_done
2306184610Salfred *
2307184610Salfred *  - This function is used to remove an USB transfer from the busdma,
2308184610Salfred *  pipe or interrupt queue.
2309184610Salfred *
2310184610Salfred *  - This function is used to queue the USB transfer on the done
2311184610Salfred *  queue.
2312184610Salfred *
2313184610Salfred *  - This function is used to stop any USB transfer timeouts.
2314184610Salfred *------------------------------------------------------------------------*/
2315184610Salfredvoid
2316194228Sthompsausbd_transfer_done(struct usb_xfer *xfer, usb_error_t error)
2317184610Salfred{
2318187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2319184610Salfred
2320194228Sthompsa	DPRINTF("err=%s\n", usbd_errstr(error));
2321184610Salfred
2322184610Salfred	/*
2323184610Salfred	 * If we are not transferring then just return.
2324184610Salfred	 * This can happen during transfer cancel.
2325184610Salfred	 */
2326184610Salfred	if (!xfer->flags_int.transferring) {
2327184610Salfred		DPRINTF("not transferring\n");
2328197562Sthompsa		/* end of control transfer, if any */
2329197562Sthompsa		xfer->flags_int.control_act = 0;
2330184610Salfred		return;
2331184610Salfred	}
2332184610Salfred	/* only set transfer error if not already set */
2333184610Salfred	if (!xfer->error) {
2334184610Salfred		xfer->error = error;
2335184610Salfred	}
2336184610Salfred	/* stop any callouts */
2337194228Sthompsa	usb_callout_stop(&xfer->timeout_handle);
2338184610Salfred
2339184610Salfred	/*
2340184610Salfred	 * If we are waiting on a queue, just remove the USB transfer
2341184610Salfred	 * from the queue, if any. We should have the required locks
2342184610Salfred	 * locked to do the remove when this function is called.
2343184610Salfred	 */
2344194228Sthompsa	usbd_transfer_dequeue(xfer);
2345184610Salfred
2346190180Sthompsa#if USB_HAVE_BUSDMA
2347187173Sthompsa	if (mtx_owned(xfer->xroot->xfer_mtx)) {
2348192984Sthompsa		struct usb_xfer_queue *pq;
2349190180Sthompsa
2350184610Salfred		/*
2351184610Salfred		 * If the private USB lock is not locked, then we assume
2352184610Salfred		 * that the BUS-DMA load stage has been passed:
2353184610Salfred		 */
2354187173Sthompsa		pq = &xfer->xroot->dma_q;
2355184610Salfred
2356184610Salfred		if (pq->curr == xfer) {
2357184610Salfred			/* start the next BUS-DMA load, if any */
2358194228Sthompsa			usb_command_wrapper(pq, NULL);
2359184610Salfred		}
2360184610Salfred	}
2361190180Sthompsa#endif
2362184610Salfred	/* keep some statistics */
2363184610Salfred	if (xfer->error) {
2364187173Sthompsa		xfer->xroot->bus->stats_err.uds_requests
2365193644Sthompsa		    [xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
2366184610Salfred	} else {
2367187173Sthompsa		xfer->xroot->bus->stats_ok.uds_requests
2368193644Sthompsa		    [xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
2369184610Salfred	}
2370184610Salfred
2371184610Salfred	/* call the USB transfer callback */
2372194228Sthompsa	usbd_callback_ss_done_defer(xfer);
2373184610Salfred}
2374184610Salfred
2375184610Salfred/*------------------------------------------------------------------------*
2376194228Sthompsa *	usbd_transfer_start_cb
2377184610Salfred *
2378184610Salfred * This function is called to start the USB transfer when
2379184610Salfred * "xfer->interval" is greater than zero, and and the endpoint type is
2380184610Salfred * BULK or CONTROL.
2381184610Salfred *------------------------------------------------------------------------*/
2382184610Salfredstatic void
2383194228Sthompsausbd_transfer_start_cb(void *arg)
2384184610Salfred{
2385192984Sthompsa	struct usb_xfer *xfer = arg;
2386193644Sthompsa	struct usb_endpoint *ep = xfer->endpoint;
2387184610Salfred
2388187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2389184610Salfred
2390184610Salfred	DPRINTF("start\n");
2391184610Salfred
2392217558Shselasky#if USB_HAVE_PF
2393215649Sweongyo	usbpf_xfertap(xfer, USBPF_XFERTAP_SUBMIT);
2394217558Shselasky#endif
2395184610Salfred	/* start the transfer */
2396193644Sthompsa	(ep->methods->start) (xfer);
2397184610Salfred
2398190738Sthompsa	xfer->flags_int.can_cancel_immed = 1;
2399190738Sthompsa
2400190738Sthompsa	/* check for error */
2401190738Sthompsa	if (xfer->error) {
2402190738Sthompsa		/* some error has happened */
2403194228Sthompsa		usbd_transfer_done(xfer, 0);
2404184610Salfred	}
2405184610Salfred}
2406184610Salfred
2407184610Salfred/*------------------------------------------------------------------------*
2408194677Sthompsa *	usbd_xfer_set_stall
2409184610Salfred *
2410184610Salfred * This function is used to set the stall flag outside the
2411184610Salfred * callback. This function is NULL safe.
2412184610Salfred *------------------------------------------------------------------------*/
2413184610Salfredvoid
2414194677Sthompsausbd_xfer_set_stall(struct usb_xfer *xfer)
2415184610Salfred{
2416184610Salfred	if (xfer == NULL) {
2417184610Salfred		/* tearing down */
2418184610Salfred		return;
2419184610Salfred	}
2420184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
2421184610Salfred
2422184610Salfred	/* avoid any races by locking the USB mutex */
2423187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
2424184610Salfred	xfer->flags.stall_pipe = 1;
2425187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
2426184610Salfred}
2427184610Salfred
2428194677Sthompsaint
2429194677Sthompsausbd_xfer_is_stalled(struct usb_xfer *xfer)
2430194677Sthompsa{
2431194677Sthompsa	return (xfer->endpoint->is_stalled);
2432194677Sthompsa}
2433194677Sthompsa
2434184610Salfred/*------------------------------------------------------------------------*
2435194228Sthompsa *	usbd_transfer_clear_stall
2436184610Salfred *
2437184610Salfred * This function is used to clear the stall flag outside the
2438184610Salfred * callback. This function is NULL safe.
2439184610Salfred *------------------------------------------------------------------------*/
2440184610Salfredvoid
2441194228Sthompsausbd_transfer_clear_stall(struct usb_xfer *xfer)
2442184610Salfred{
2443184610Salfred	if (xfer == NULL) {
2444184610Salfred		/* tearing down */
2445184610Salfred		return;
2446184610Salfred	}
2447184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
2448184610Salfred
2449184610Salfred	/* avoid any races by locking the USB mutex */
2450187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
2451184610Salfred
2452184610Salfred	xfer->flags.stall_pipe = 0;
2453184610Salfred
2454187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
2455184610Salfred}
2456184610Salfred
2457184610Salfred/*------------------------------------------------------------------------*
2458194228Sthompsa *	usbd_pipe_start
2459184610Salfred *
2460184610Salfred * This function is used to add an USB transfer to the pipe transfer list.
2461184610Salfred *------------------------------------------------------------------------*/
2462184610Salfredvoid
2463194228Sthompsausbd_pipe_start(struct usb_xfer_queue *pq)
2464184610Salfred{
2465193644Sthompsa	struct usb_endpoint *ep;
2466192984Sthompsa	struct usb_xfer *xfer;
2467184610Salfred	uint8_t type;
2468184610Salfred
2469184610Salfred	xfer = pq->curr;
2470193644Sthompsa	ep = xfer->endpoint;
2471184610Salfred
2472187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2473184610Salfred
2474184610Salfred	/*
2475193644Sthompsa	 * If the endpoint is already stalled we do nothing !
2476184610Salfred	 */
2477193644Sthompsa	if (ep->is_stalled) {
2478184610Salfred		return;
2479184610Salfred	}
2480184610Salfred	/*
2481193644Sthompsa	 * Check if we are supposed to stall the endpoint:
2482184610Salfred	 */
2483184610Salfred	if (xfer->flags.stall_pipe) {
2484205035Sthompsa		struct usb_device *udev;
2485205035Sthompsa		struct usb_xfer_root *info;
2486205035Sthompsa
2487184610Salfred		/* clear stall command */
2488184610Salfred		xfer->flags.stall_pipe = 0;
2489184610Salfred
2490205035Sthompsa		/* get pointer to USB device */
2491205035Sthompsa		info = xfer->xroot;
2492205035Sthompsa		udev = info->udev;
2493205035Sthompsa
2494184610Salfred		/*
2495184610Salfred		 * Only stall BULK and INTERRUPT endpoints.
2496184610Salfred		 */
2497193644Sthompsa		type = (ep->edesc->bmAttributes & UE_XFERTYPE);
2498184610Salfred		if ((type == UE_BULK) ||
2499184610Salfred		    (type == UE_INTERRUPT)) {
2500195121Sthompsa			uint8_t did_stall;
2501184610Salfred
2502195121Sthompsa			did_stall = 1;
2503184610Salfred
2504192499Sthompsa			if (udev->flags.usb_mode == USB_MODE_DEVICE) {
2505184610Salfred				(udev->bus->methods->set_stall) (
2506195121Sthompsa				    udev, NULL, ep, &did_stall);
2507207080Sthompsa			} else if (udev->ctrl_xfer[1]) {
2508207080Sthompsa				info = udev->ctrl_xfer[1]->xroot;
2509195121Sthompsa				usb_proc_msignal(
2510187174Sthompsa				    &info->bus->non_giant_callback_proc,
2511195121Sthompsa				    &udev->cs_msg[0], &udev->cs_msg[1]);
2512184610Salfred			} else {
2513184610Salfred				/* should not happen */
2514199816Sthompsa				DPRINTFN(0, "No stall handler\n");
2515184610Salfred			}
2516184610Salfred			/*
2517195121Sthompsa			 * Check if we should stall. Some USB hardware
2518195121Sthompsa			 * handles set- and clear-stall in hardware.
2519184610Salfred			 */
2520195121Sthompsa			if (did_stall) {
2521195121Sthompsa				/*
2522195121Sthompsa				 * The transfer will be continued when
2523195121Sthompsa				 * the clear-stall control endpoint
2524195121Sthompsa				 * message is received.
2525195121Sthompsa				 */
2526195121Sthompsa				ep->is_stalled = 1;
2527195121Sthompsa				return;
2528195121Sthompsa			}
2529205035Sthompsa		} else if (type == UE_ISOCHRONOUS) {
2530205035Sthompsa
2531205035Sthompsa			/*
2532205035Sthompsa			 * Make sure any FIFO overflow or other FIFO
2533205035Sthompsa			 * error conditions go away by resetting the
2534205035Sthompsa			 * endpoint FIFO through the clear stall
2535205035Sthompsa			 * method.
2536205035Sthompsa			 */
2537205035Sthompsa			if (udev->flags.usb_mode == USB_MODE_DEVICE) {
2538205035Sthompsa				(udev->bus->methods->clear_stall) (udev, ep);
2539205035Sthompsa			}
2540184610Salfred		}
2541184610Salfred	}
2542184610Salfred	/* Set or clear stall complete - special case */
2543184610Salfred	if (xfer->nframes == 0) {
2544184610Salfred		/* we are complete */
2545184610Salfred		xfer->aframes = 0;
2546194228Sthompsa		usbd_transfer_done(xfer, 0);
2547184610Salfred		return;
2548184610Salfred	}
2549184610Salfred	/*
2550184610Salfred	 * Handled cases:
2551184610Salfred	 *
2552184610Salfred	 * 1) Start the first transfer queued.
2553184610Salfred	 *
2554184610Salfred	 * 2) Re-start the current USB transfer.
2555184610Salfred	 */
2556184610Salfred	/*
2557184610Salfred	 * Check if there should be any
2558184610Salfred	 * pre transfer start delay:
2559184610Salfred	 */
2560184610Salfred	if (xfer->interval > 0) {
2561193644Sthompsa		type = (ep->edesc->bmAttributes & UE_XFERTYPE);
2562184610Salfred		if ((type == UE_BULK) ||
2563184610Salfred		    (type == UE_CONTROL)) {
2564194228Sthompsa			usbd_transfer_timeout_ms(xfer,
2565194228Sthompsa			    &usbd_transfer_start_cb,
2566184610Salfred			    xfer->interval);
2567184610Salfred			return;
2568184610Salfred		}
2569184610Salfred	}
2570184610Salfred	DPRINTF("start\n");
2571184610Salfred
2572217558Shselasky#if USB_HAVE_PF
2573215649Sweongyo	usbpf_xfertap(xfer, USBPF_XFERTAP_SUBMIT);
2574217558Shselasky#endif
2575184610Salfred	/* start USB transfer */
2576193644Sthompsa	(ep->methods->start) (xfer);
2577184610Salfred
2578190738Sthompsa	xfer->flags_int.can_cancel_immed = 1;
2579190738Sthompsa
2580190738Sthompsa	/* check for error */
2581190738Sthompsa	if (xfer->error) {
2582190738Sthompsa		/* some error has happened */
2583194228Sthompsa		usbd_transfer_done(xfer, 0);
2584184610Salfred	}
2585184610Salfred}
2586184610Salfred
2587184610Salfred/*------------------------------------------------------------------------*
2588194228Sthompsa *	usbd_transfer_timeout_ms
2589184610Salfred *
2590184610Salfred * This function is used to setup a timeout on the given USB
2591184610Salfred * transfer. If the timeout has been deferred the callback given by
2592184610Salfred * "cb" will get called after "ms" milliseconds.
2593184610Salfred *------------------------------------------------------------------------*/
2594184610Salfredvoid
2595194228Sthompsausbd_transfer_timeout_ms(struct usb_xfer *xfer,
2596193045Sthompsa    void (*cb) (void *arg), usb_timeout_t ms)
2597184610Salfred{
2598187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2599184610Salfred
2600184610Salfred	/* defer delay */
2601194228Sthompsa	usb_callout_reset(&xfer->timeout_handle,
2602184610Salfred	    USB_MS_TO_TICKS(ms), cb, xfer);
2603184610Salfred}
2604184610Salfred
2605184610Salfred/*------------------------------------------------------------------------*
2606194228Sthompsa *	usbd_callback_wrapper_sub
2607184610Salfred *
2608184610Salfred *  - This function will update variables in an USB transfer after
2609184610Salfred *  that the USB transfer is complete.
2610184610Salfred *
2611184610Salfred *  - This function is used to start the next USB transfer on the
2612193644Sthompsa *  ep transfer queue, if any.
2613184610Salfred *
2614184610Salfred * NOTE: In some special cases the USB transfer will not be removed from
2615184610Salfred * the pipe queue, but remain first. To enforce USB transfer removal call
2616184610Salfred * this function passing the error code "USB_ERR_CANCELLED".
2617184610Salfred *
2618184610Salfred * Return values:
2619184610Salfred * 0: Success.
2620184610Salfred * Else: The callback has been deferred.
2621184610Salfred *------------------------------------------------------------------------*/
2622184610Salfredstatic uint8_t
2623194228Sthompsausbd_callback_wrapper_sub(struct usb_xfer *xfer)
2624184610Salfred{
2625193644Sthompsa	struct usb_endpoint *ep;
2626213435Shselasky	struct usb_bus *bus;
2627193045Sthompsa	usb_frcount_t x;
2628184610Salfred
2629213435Shselasky	bus = xfer->xroot->bus;
2630213435Shselasky
2631184610Salfred	if ((!xfer->flags_int.open) &&
2632184610Salfred	    (!xfer->flags_int.did_close)) {
2633184610Salfred		DPRINTF("close\n");
2634213435Shselasky		USB_BUS_LOCK(bus);
2635193644Sthompsa		(xfer->endpoint->methods->close) (xfer);
2636213435Shselasky		USB_BUS_UNLOCK(bus);
2637184610Salfred		/* only close once */
2638184610Salfred		xfer->flags_int.did_close = 1;
2639184610Salfred		return (1);		/* wait for new callback */
2640184610Salfred	}
2641184610Salfred	/*
2642184610Salfred	 * If we have a non-hardware induced error we
2643184610Salfred	 * need to do the DMA delay!
2644184610Salfred	 */
2645213435Shselasky	if (xfer->error != 0 && !xfer->flags_int.did_dma_delay &&
2646213435Shselasky	    (xfer->error == USB_ERR_CANCELLED ||
2647213435Shselasky	    xfer->error == USB_ERR_TIMEOUT ||
2648213435Shselasky	    bus->methods->start_dma_delay != NULL)) {
2649184610Salfred
2650193045Sthompsa		usb_timeout_t temp;
2651184610Salfred
2652197562Sthompsa		/* only delay once */
2653197562Sthompsa		xfer->flags_int.did_dma_delay = 1;
2654197562Sthompsa
2655184610Salfred		/* we can not cancel this delay */
2656184610Salfred		xfer->flags_int.can_cancel_immed = 0;
2657184610Salfred
2658212134Sthompsa		temp = usbd_get_dma_delay(xfer->xroot->udev);
2659184610Salfred
2660184610Salfred		DPRINTFN(3, "DMA delay, %u ms, "
2661184610Salfred		    "on %p\n", temp, xfer);
2662184610Salfred
2663184610Salfred		if (temp != 0) {
2664213435Shselasky			USB_BUS_LOCK(bus);
2665213435Shselasky			/*
2666213435Shselasky			 * Some hardware solutions have dedicated
2667213435Shselasky			 * events when it is safe to free DMA'ed
2668213435Shselasky			 * memory. For the other hardware platforms we
2669213435Shselasky			 * use a static delay.
2670213435Shselasky			 */
2671213435Shselasky			if (bus->methods->start_dma_delay != NULL) {
2672213435Shselasky				(bus->methods->start_dma_delay) (xfer);
2673213435Shselasky			} else {
2674213435Shselasky				usbd_transfer_timeout_ms(xfer,
2675213435Shselasky				    (void *)&usb_dma_delay_done_cb, temp);
2676213435Shselasky			}
2677213435Shselasky			USB_BUS_UNLOCK(bus);
2678184610Salfred			return (1);	/* wait for new callback */
2679184610Salfred		}
2680184610Salfred	}
2681184610Salfred	/* check actual number of frames */
2682184610Salfred	if (xfer->aframes > xfer->nframes) {
2683184610Salfred		if (xfer->error == 0) {
2684184610Salfred			panic("%s: actual number of frames, %d, is "
2685199816Sthompsa			    "greater than initial number of frames, %d\n",
2686184610Salfred			    __FUNCTION__, xfer->aframes, xfer->nframes);
2687184610Salfred		} else {
2688184610Salfred			/* just set some valid value */
2689184610Salfred			xfer->aframes = xfer->nframes;
2690184610Salfred		}
2691184610Salfred	}
2692184610Salfred	/* compute actual length */
2693184610Salfred	xfer->actlen = 0;
2694184610Salfred
2695184610Salfred	for (x = 0; x != xfer->aframes; x++) {
2696184610Salfred		xfer->actlen += xfer->frlengths[x];
2697184610Salfred	}
2698184610Salfred
2699184610Salfred	/*
2700184610Salfred	 * Frames that were not transferred get zero actual length in
2701184610Salfred	 * case the USB device driver does not check the actual number
2702184610Salfred	 * of frames transferred, "xfer->aframes":
2703184610Salfred	 */
2704184610Salfred	for (; x < xfer->nframes; x++) {
2705194677Sthompsa		usbd_xfer_set_frame_len(xfer, x, 0);
2706184610Salfred	}
2707184610Salfred
2708184610Salfred	/* check actual length */
2709184610Salfred	if (xfer->actlen > xfer->sumlen) {
2710184610Salfred		if (xfer->error == 0) {
2711184610Salfred			panic("%s: actual length, %d, is greater than "
2712199816Sthompsa			    "initial length, %d\n",
2713184610Salfred			    __FUNCTION__, xfer->actlen, xfer->sumlen);
2714184610Salfred		} else {
2715184610Salfred			/* just set some valid value */
2716184610Salfred			xfer->actlen = xfer->sumlen;
2717184610Salfred		}
2718184610Salfred	}
2719194677Sthompsa	DPRINTFN(1, "xfer=%p endpoint=%p sts=%d alen=%d, slen=%d, afrm=%d, nfrm=%d\n",
2720193644Sthompsa	    xfer, xfer->endpoint, xfer->error, xfer->actlen, xfer->sumlen,
2721184610Salfred	    xfer->aframes, xfer->nframes);
2722184610Salfred
2723184610Salfred	if (xfer->error) {
2724184610Salfred		/* end of control transfer, if any */
2725184610Salfred		xfer->flags_int.control_act = 0;
2726184610Salfred
2727184610Salfred		/* check if we should block the execution queue */
2728184610Salfred		if ((xfer->error != USB_ERR_CANCELLED) &&
2729184610Salfred		    (xfer->flags.pipe_bof)) {
2730184610Salfred			DPRINTFN(2, "xfer=%p: Block On Failure "
2731193644Sthompsa			    "on endpoint=%p\n", xfer, xfer->endpoint);
2732184610Salfred			goto done;
2733184610Salfred		}
2734184610Salfred	} else {
2735184610Salfred		/* check for short transfers */
2736184610Salfred		if (xfer->actlen < xfer->sumlen) {
2737184610Salfred
2738184610Salfred			/* end of control transfer, if any */
2739184610Salfred			xfer->flags_int.control_act = 0;
2740184610Salfred
2741184610Salfred			if (!xfer->flags_int.short_xfer_ok) {
2742184610Salfred				xfer->error = USB_ERR_SHORT_XFER;
2743184610Salfred				if (xfer->flags.pipe_bof) {
2744184610Salfred					DPRINTFN(2, "xfer=%p: Block On Failure on "
2745193644Sthompsa					    "Short Transfer on endpoint %p.\n",
2746193644Sthompsa					    xfer, xfer->endpoint);
2747184610Salfred					goto done;
2748184610Salfred				}
2749184610Salfred			}
2750184610Salfred		} else {
2751184610Salfred			/*
2752184610Salfred			 * Check if we are in the middle of a
2753184610Salfred			 * control transfer:
2754184610Salfred			 */
2755184610Salfred			if (xfer->flags_int.control_act) {
2756184610Salfred				DPRINTFN(5, "xfer=%p: Control transfer "
2757193644Sthompsa				    "active on endpoint=%p\n", xfer, xfer->endpoint);
2758184610Salfred				goto done;
2759184610Salfred			}
2760184610Salfred		}
2761184610Salfred	}
2762184610Salfred
2763193644Sthompsa	ep = xfer->endpoint;
2764184610Salfred
2765184610Salfred	/*
2766184610Salfred	 * If the current USB transfer is completing we need to start the
2767184610Salfred	 * next one:
2768184610Salfred	 */
2769213435Shselasky	USB_BUS_LOCK(bus);
2770193644Sthompsa	if (ep->endpoint_q.curr == xfer) {
2771194228Sthompsa		usb_command_wrapper(&ep->endpoint_q, NULL);
2772184610Salfred
2773193644Sthompsa		if (ep->endpoint_q.curr || TAILQ_FIRST(&ep->endpoint_q.head)) {
2774184610Salfred			/* there is another USB transfer waiting */
2775184610Salfred		} else {
2776184610Salfred			/* this is the last USB transfer */
2777184610Salfred			/* clear isochronous sync flag */
2778193644Sthompsa			xfer->endpoint->is_synced = 0;
2779184610Salfred		}
2780184610Salfred	}
2781213435Shselasky	USB_BUS_UNLOCK(bus);
2782184610Salfreddone:
2783184610Salfred	return (0);
2784184610Salfred}
2785184610Salfred
2786184610Salfred/*------------------------------------------------------------------------*
2787194228Sthompsa *	usb_command_wrapper
2788184610Salfred *
2789184610Salfred * This function is used to execute commands non-recursivly on an USB
2790184610Salfred * transfer.
2791184610Salfred *------------------------------------------------------------------------*/
2792184610Salfredvoid
2793194228Sthompsausb_command_wrapper(struct usb_xfer_queue *pq, struct usb_xfer *xfer)
2794184610Salfred{
2795184610Salfred	if (xfer) {
2796184610Salfred		/*
2797184610Salfred		 * If the transfer is not already processing,
2798184610Salfred		 * queue it!
2799184610Salfred		 */
2800184610Salfred		if (pq->curr != xfer) {
2801194228Sthompsa			usbd_transfer_enqueue(pq, xfer);
2802184610Salfred			if (pq->curr != NULL) {
2803184610Salfred				/* something is already processing */
2804184610Salfred				DPRINTFN(6, "busy %p\n", pq->curr);
2805184610Salfred				return;
2806184610Salfred			}
2807184610Salfred		}
2808184610Salfred	} else {
2809184610Salfred		/* Get next element in queue */
2810184610Salfred		pq->curr = NULL;
2811184610Salfred	}
2812184610Salfred
2813184610Salfred	if (!pq->recurse_1) {
2814184610Salfred
2815184610Salfred		do {
2816184610Salfred
2817184610Salfred			/* set both recurse flags */
2818184610Salfred			pq->recurse_1 = 1;
2819184610Salfred			pq->recurse_2 = 1;
2820184610Salfred
2821184610Salfred			if (pq->curr == NULL) {
2822184610Salfred				xfer = TAILQ_FIRST(&pq->head);
2823184610Salfred				if (xfer) {
2824184610Salfred					TAILQ_REMOVE(&pq->head, xfer,
2825184610Salfred					    wait_entry);
2826184610Salfred					xfer->wait_queue = NULL;
2827184610Salfred					pq->curr = xfer;
2828184610Salfred				} else {
2829184610Salfred					break;
2830184610Salfred				}
2831184610Salfred			}
2832184610Salfred			DPRINTFN(6, "cb %p (enter)\n", pq->curr);
2833184610Salfred			(pq->command) (pq);
2834184610Salfred			DPRINTFN(6, "cb %p (leave)\n", pq->curr);
2835184610Salfred
2836184610Salfred		} while (!pq->recurse_2);
2837184610Salfred
2838184610Salfred		/* clear first recurse flag */
2839184610Salfred		pq->recurse_1 = 0;
2840184610Salfred
2841184610Salfred	} else {
2842184610Salfred		/* clear second recurse flag */
2843184610Salfred		pq->recurse_2 = 0;
2844184610Salfred	}
2845184610Salfred}
2846184610Salfred
2847184610Salfred/*------------------------------------------------------------------------*
2848207080Sthompsa *	usbd_ctrl_transfer_setup
2849184610Salfred *
2850184610Salfred * This function is used to setup the default USB control endpoint
2851184610Salfred * transfer.
2852184610Salfred *------------------------------------------------------------------------*/
2853184610Salfredvoid
2854207080Sthompsausbd_ctrl_transfer_setup(struct usb_device *udev)
2855184610Salfred{
2856192984Sthompsa	struct usb_xfer *xfer;
2857184610Salfred	uint8_t no_resetup;
2858184610Salfred	uint8_t iface_index;
2859184610Salfred
2860190735Sthompsa	/* check for root HUB */
2861190735Sthompsa	if (udev->parent_hub == NULL)
2862190735Sthompsa		return;
2863184610Salfredrepeat:
2864184610Salfred
2865207080Sthompsa	xfer = udev->ctrl_xfer[0];
2866184610Salfred	if (xfer) {
2867184824Sthompsa		USB_XFER_LOCK(xfer);
2868184610Salfred		no_resetup =
2869184610Salfred		    ((xfer->address == udev->address) &&
2870207080Sthompsa		    (udev->ctrl_ep_desc.wMaxPacketSize[0] ==
2871184610Salfred		    udev->ddesc.bMaxPacketSize));
2872192499Sthompsa		if (udev->flags.usb_mode == USB_MODE_DEVICE) {
2873184610Salfred			if (no_resetup) {
2874184610Salfred				/*
2875184610Salfred				 * NOTE: checking "xfer->address" and
2876184610Salfred				 * starting the USB transfer must be
2877184610Salfred				 * atomic!
2878184610Salfred				 */
2879194228Sthompsa				usbd_transfer_start(xfer);
2880184610Salfred			}
2881184610Salfred		}
2882184824Sthompsa		USB_XFER_UNLOCK(xfer);
2883184610Salfred	} else {
2884184610Salfred		no_resetup = 0;
2885184610Salfred	}
2886184610Salfred
2887184610Salfred	if (no_resetup) {
2888184610Salfred		/*
2889184610Salfred	         * All parameters are exactly the same like before.
2890184610Salfred	         * Just return.
2891184610Salfred	         */
2892184610Salfred		return;
2893184610Salfred	}
2894184610Salfred	/*
2895184610Salfred	 * Update wMaxPacketSize for the default control endpoint:
2896184610Salfred	 */
2897207080Sthompsa	udev->ctrl_ep_desc.wMaxPacketSize[0] =
2898184610Salfred	    udev->ddesc.bMaxPacketSize;
2899184610Salfred
2900184610Salfred	/*
2901184610Salfred	 * Unsetup any existing USB transfer:
2902184610Salfred	 */
2903207080Sthompsa	usbd_transfer_unsetup(udev->ctrl_xfer, USB_CTRL_XFER_MAX);
2904184610Salfred
2905184610Salfred	/*
2906184610Salfred	 * Try to setup a new USB transfer for the
2907184610Salfred	 * default control endpoint:
2908184610Salfred	 */
2909184610Salfred	iface_index = 0;
2910194228Sthompsa	if (usbd_transfer_setup(udev, &iface_index,
2911207080Sthompsa	    udev->ctrl_xfer, usb_control_ep_cfg, USB_CTRL_XFER_MAX, NULL,
2912207079Sthompsa	    &udev->device_mtx)) {
2913184610Salfred		DPRINTFN(0, "could not setup default "
2914199816Sthompsa		    "USB transfer\n");
2915184610Salfred	} else {
2916184610Salfred		goto repeat;
2917184610Salfred	}
2918184610Salfred}
2919184610Salfred
2920184610Salfred/*------------------------------------------------------------------------*
2921194228Sthompsa *	usbd_clear_data_toggle - factored out code
2922184610Salfred *
2923184610Salfred * NOTE: the intention of this function is not to reset the hardware
2924184610Salfred * data toggle.
2925184610Salfred *------------------------------------------------------------------------*/
2926184610Salfredvoid
2927213435Shselaskyusbd_clear_stall_locked(struct usb_device *udev, struct usb_endpoint *ep)
2928213435Shselasky{
2929213435Shselasky	USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
2930213435Shselasky
2931213435Shselasky	/* check that we have a valid case */
2932213435Shselasky	if (udev->flags.usb_mode == USB_MODE_HOST &&
2933213435Shselasky	    udev->parent_hub != NULL &&
2934213435Shselasky	    udev->bus->methods->clear_stall != NULL &&
2935213435Shselasky	    ep->methods != NULL) {
2936213435Shselasky		(udev->bus->methods->clear_stall) (udev, ep);
2937213435Shselasky	}
2938213435Shselasky}
2939213435Shselasky
2940213435Shselasky/*------------------------------------------------------------------------*
2941213435Shselasky *	usbd_clear_data_toggle - factored out code
2942213435Shselasky *
2943213435Shselasky * NOTE: the intention of this function is not to reset the hardware
2944213435Shselasky * data toggle on the USB device side.
2945213435Shselasky *------------------------------------------------------------------------*/
2946213435Shselaskyvoid
2947194228Sthompsausbd_clear_data_toggle(struct usb_device *udev, struct usb_endpoint *ep)
2948184610Salfred{
2949193644Sthompsa	DPRINTFN(5, "udev=%p endpoint=%p\n", udev, ep);
2950184610Salfred
2951184824Sthompsa	USB_BUS_LOCK(udev->bus);
2952193644Sthompsa	ep->toggle_next = 0;
2953213435Shselasky	/* some hardware needs a callback to clear the data toggle */
2954213435Shselasky	usbd_clear_stall_locked(udev, ep);
2955184824Sthompsa	USB_BUS_UNLOCK(udev->bus);
2956184610Salfred}
2957184610Salfred
2958184610Salfred/*------------------------------------------------------------------------*
2959194228Sthompsa *	usbd_clear_stall_callback - factored out clear stall callback
2960184610Salfred *
2961184610Salfred * Input parameters:
2962184610Salfred *  xfer1: Clear Stall Control Transfer
2963184610Salfred *  xfer2: Stalled USB Transfer
2964184610Salfred *
2965184610Salfred * This function is NULL safe.
2966184610Salfred *
2967184610Salfred * Return values:
2968184610Salfred *   0: In progress
2969184610Salfred *   Else: Finished
2970184610Salfred *
2971184610Salfred * Clear stall config example:
2972184610Salfred *
2973192984Sthompsa * static const struct usb_config my_clearstall =  {
2974184610Salfred *	.type = UE_CONTROL,
2975184610Salfred *	.endpoint = 0,
2976184610Salfred *	.direction = UE_DIR_ANY,
2977184610Salfred *	.interval = 50, //50 milliseconds
2978192984Sthompsa *	.bufsize = sizeof(struct usb_device_request),
2979190734Sthompsa *	.timeout = 1000, //1.000 seconds
2980190734Sthompsa *	.callback = &my_clear_stall_callback, // **
2981190734Sthompsa *	.usb_mode = USB_MODE_HOST,
2982184610Salfred * };
2983184610Salfred *
2984194228Sthompsa * ** "my_clear_stall_callback" calls "usbd_clear_stall_callback"
2985184610Salfred * passing the correct parameters.
2986184610Salfred *------------------------------------------------------------------------*/
2987184610Salfreduint8_t
2988194228Sthompsausbd_clear_stall_callback(struct usb_xfer *xfer1,
2989192984Sthompsa    struct usb_xfer *xfer2)
2990184610Salfred{
2991192984Sthompsa	struct usb_device_request req;
2992184610Salfred
2993184610Salfred	if (xfer2 == NULL) {
2994184610Salfred		/* looks like we are tearing down */
2995184610Salfred		DPRINTF("NULL input parameter\n");
2996184610Salfred		return (0);
2997184610Salfred	}
2998184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer1, MA_OWNED);
2999184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer2, MA_OWNED);
3000184610Salfred
3001184610Salfred	switch (USB_GET_STATE(xfer1)) {
3002184610Salfred	case USB_ST_SETUP:
3003184610Salfred
3004184610Salfred		/*
3005184610Salfred		 * pre-clear the data toggle to DATA0 ("umass.c" and
3006184610Salfred		 * "ata-usb.c" depends on this)
3007184610Salfred		 */
3008184610Salfred
3009194228Sthompsa		usbd_clear_data_toggle(xfer2->xroot->udev, xfer2->endpoint);
3010184610Salfred
3011184610Salfred		/* setup a clear-stall packet */
3012184610Salfred
3013184610Salfred		req.bmRequestType = UT_WRITE_ENDPOINT;
3014184610Salfred		req.bRequest = UR_CLEAR_FEATURE;
3015184610Salfred		USETW(req.wValue, UF_ENDPOINT_HALT);
3016193644Sthompsa		req.wIndex[0] = xfer2->endpoint->edesc->bEndpointAddress;
3017184610Salfred		req.wIndex[1] = 0;
3018184610Salfred		USETW(req.wLength, 0);
3019184610Salfred
3020184610Salfred		/*
3021194228Sthompsa		 * "usbd_transfer_setup_sub()" will ensure that
3022184610Salfred		 * we have sufficient room in the buffer for
3023184610Salfred		 * the request structure!
3024184610Salfred		 */
3025184610Salfred
3026184610Salfred		/* copy in the transfer */
3027184610Salfred
3028194228Sthompsa		usbd_copy_in(xfer1->frbuffers, 0, &req, sizeof(req));
3029184610Salfred
3030184610Salfred		/* set length */
3031184610Salfred		xfer1->frlengths[0] = sizeof(req);
3032184610Salfred		xfer1->nframes = 1;
3033184610Salfred
3034194228Sthompsa		usbd_transfer_submit(xfer1);
3035184610Salfred		return (0);
3036184610Salfred
3037184610Salfred	case USB_ST_TRANSFERRED:
3038184610Salfred		break;
3039184610Salfred
3040184610Salfred	default:			/* Error */
3041184610Salfred		if (xfer1->error == USB_ERR_CANCELLED) {
3042184610Salfred			return (0);
3043184610Salfred		}
3044184610Salfred		break;
3045184610Salfred	}
3046184610Salfred	return (1);			/* Clear Stall Finished */
3047184610Salfred}
3048184610Salfred
3049195960Salfred/*------------------------------------------------------------------------*
3050195960Salfred *	usbd_transfer_poll
3051195960Salfred *
3052195960Salfred * The following function gets called from the USB keyboard driver and
3053195960Salfred * UMASS when the system has paniced.
3054195960Salfred *
3055195960Salfred * NOTE: It is currently not possible to resume normal operation on
3056195960Salfred * the USB controller which has been polled, due to clearing of the
3057195960Salfred * "up_dsleep" and "up_msleep" flags.
3058195960Salfred *------------------------------------------------------------------------*/
3059184610Salfredvoid
3060194677Sthompsausbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
3061184610Salfred{
3062195960Salfred	struct usb_xfer *xfer;
3063195960Salfred	struct usb_xfer_root *xroot;
3064195960Salfred	struct usb_device *udev;
3065195960Salfred	struct usb_proc_msg *pm;
3066195960Salfred	uint16_t n;
3067195960Salfred	uint16_t drop_bus;
3068195960Salfred	uint16_t drop_xfer;
3069195960Salfred
3070195960Salfred	for (n = 0; n != max; n++) {
3071195960Salfred		/* Extra checks to avoid panic */
3072195960Salfred		xfer = ppxfer[n];
3073195960Salfred		if (xfer == NULL)
3074195960Salfred			continue;	/* no USB transfer */
3075195960Salfred		xroot = xfer->xroot;
3076195960Salfred		if (xroot == NULL)
3077195960Salfred			continue;	/* no USB root */
3078195960Salfred		udev = xroot->udev;
3079195960Salfred		if (udev == NULL)
3080195960Salfred			continue;	/* no USB device */
3081195960Salfred		if (udev->bus == NULL)
3082195960Salfred			continue;	/* no BUS structure */
3083195960Salfred		if (udev->bus->methods == NULL)
3084195960Salfred			continue;	/* no BUS methods */
3085195960Salfred		if (udev->bus->methods->xfer_poll == NULL)
3086195960Salfred			continue;	/* no poll method */
3087195960Salfred
3088195960Salfred		/* make sure that the BUS mutex is not locked */
3089195960Salfred		drop_bus = 0;
3090195960Salfred		while (mtx_owned(&xroot->udev->bus->bus_mtx)) {
3091195960Salfred			mtx_unlock(&xroot->udev->bus->bus_mtx);
3092195960Salfred			drop_bus++;
3093195960Salfred		}
3094195960Salfred
3095195960Salfred		/* make sure that the transfer mutex is not locked */
3096195960Salfred		drop_xfer = 0;
3097195960Salfred		while (mtx_owned(xroot->xfer_mtx)) {
3098195960Salfred			mtx_unlock(xroot->xfer_mtx);
3099195960Salfred			drop_xfer++;
3100195960Salfred		}
3101195960Salfred
3102195960Salfred		/* Make sure cv_signal() and cv_broadcast() is not called */
3103195960Salfred		udev->bus->control_xfer_proc.up_msleep = 0;
3104195960Salfred		udev->bus->explore_proc.up_msleep = 0;
3105195960Salfred		udev->bus->giant_callback_proc.up_msleep = 0;
3106195960Salfred		udev->bus->non_giant_callback_proc.up_msleep = 0;
3107195960Salfred
3108195960Salfred		/* poll USB hardware */
3109195960Salfred		(udev->bus->methods->xfer_poll) (udev->bus);
3110195960Salfred
3111195960Salfred		USB_BUS_LOCK(xroot->bus);
3112195960Salfred
3113195960Salfred		/* check for clear stall */
3114207080Sthompsa		if (udev->ctrl_xfer[1] != NULL) {
3115195960Salfred
3116195960Salfred			/* poll clear stall start */
3117195960Salfred			pm = &udev->cs_msg[0].hdr;
3118195960Salfred			(pm->pm_callback) (pm);
3119195960Salfred			/* poll clear stall done thread */
3120207080Sthompsa			pm = &udev->ctrl_xfer[1]->
3121195960Salfred			    xroot->done_m[0].hdr;
3122195960Salfred			(pm->pm_callback) (pm);
3123195960Salfred		}
3124195960Salfred
3125195960Salfred		/* poll done thread */
3126195960Salfred		pm = &xroot->done_m[0].hdr;
3127195960Salfred		(pm->pm_callback) (pm);
3128195960Salfred
3129195960Salfred		USB_BUS_UNLOCK(xroot->bus);
3130195960Salfred
3131195960Salfred		/* restore transfer mutex */
3132195960Salfred		while (drop_xfer--)
3133195960Salfred			mtx_lock(xroot->xfer_mtx);
3134195960Salfred
3135195960Salfred		/* restore BUS mutex */
3136195960Salfred		while (drop_bus--)
3137195960Salfred			mtx_lock(&xroot->udev->bus->bus_mtx);
3138184610Salfred	}
3139184610Salfred}
3140190734Sthompsa
3141190734Sthompsastatic void
3142194228Sthompsausbd_get_std_packet_size(struct usb_std_packet_size *ptr,
3143192500Sthompsa    uint8_t type, enum usb_dev_speed speed)
3144190734Sthompsa{
3145190734Sthompsa	static const uint16_t intr_range_max[USB_SPEED_MAX] = {
3146190734Sthompsa		[USB_SPEED_LOW] = 8,
3147190734Sthompsa		[USB_SPEED_FULL] = 64,
3148190734Sthompsa		[USB_SPEED_HIGH] = 1024,
3149190734Sthompsa		[USB_SPEED_VARIABLE] = 1024,
3150190734Sthompsa		[USB_SPEED_SUPER] = 1024,
3151190734Sthompsa	};
3152190734Sthompsa
3153190734Sthompsa	static const uint16_t isoc_range_max[USB_SPEED_MAX] = {
3154190734Sthompsa		[USB_SPEED_LOW] = 0,	/* invalid */
3155190734Sthompsa		[USB_SPEED_FULL] = 1023,
3156190734Sthompsa		[USB_SPEED_HIGH] = 1024,
3157190734Sthompsa		[USB_SPEED_VARIABLE] = 3584,
3158190734Sthompsa		[USB_SPEED_SUPER] = 1024,
3159190734Sthompsa	};
3160190734Sthompsa
3161190734Sthompsa	static const uint16_t control_min[USB_SPEED_MAX] = {
3162190734Sthompsa		[USB_SPEED_LOW] = 8,
3163190734Sthompsa		[USB_SPEED_FULL] = 8,
3164190734Sthompsa		[USB_SPEED_HIGH] = 64,
3165190734Sthompsa		[USB_SPEED_VARIABLE] = 512,
3166190734Sthompsa		[USB_SPEED_SUPER] = 512,
3167190734Sthompsa	};
3168190734Sthompsa
3169190734Sthompsa	static const uint16_t bulk_min[USB_SPEED_MAX] = {
3170209443Sthompsa		[USB_SPEED_LOW] = 8,
3171190734Sthompsa		[USB_SPEED_FULL] = 8,
3172190734Sthompsa		[USB_SPEED_HIGH] = 512,
3173190734Sthompsa		[USB_SPEED_VARIABLE] = 512,
3174190734Sthompsa		[USB_SPEED_SUPER] = 1024,
3175190734Sthompsa	};
3176190734Sthompsa
3177190734Sthompsa	uint16_t temp;
3178190734Sthompsa
3179190734Sthompsa	memset(ptr, 0, sizeof(*ptr));
3180190734Sthompsa
3181190734Sthompsa	switch (type) {
3182190734Sthompsa	case UE_INTERRUPT:
3183192500Sthompsa		ptr->range.max = intr_range_max[speed];
3184190734Sthompsa		break;
3185190734Sthompsa	case UE_ISOCHRONOUS:
3186192500Sthompsa		ptr->range.max = isoc_range_max[speed];
3187190734Sthompsa		break;
3188190734Sthompsa	default:
3189190734Sthompsa		if (type == UE_BULK)
3190192500Sthompsa			temp = bulk_min[speed];
3191190734Sthompsa		else /* UE_CONTROL */
3192192500Sthompsa			temp = control_min[speed];
3193190734Sthompsa
3194190734Sthompsa		/* default is fixed */
3195190734Sthompsa		ptr->fixed[0] = temp;
3196190734Sthompsa		ptr->fixed[1] = temp;
3197190734Sthompsa		ptr->fixed[2] = temp;
3198190734Sthompsa		ptr->fixed[3] = temp;
3199190734Sthompsa
3200192500Sthompsa		if (speed == USB_SPEED_FULL) {
3201190734Sthompsa			/* multiple sizes */
3202190734Sthompsa			ptr->fixed[1] = 16;
3203190734Sthompsa			ptr->fixed[2] = 32;
3204190734Sthompsa			ptr->fixed[3] = 64;
3205190734Sthompsa		}
3206192500Sthompsa		if ((speed == USB_SPEED_VARIABLE) &&
3207190734Sthompsa		    (type == UE_BULK)) {
3208190734Sthompsa			/* multiple sizes */
3209190734Sthompsa			ptr->fixed[2] = 1024;
3210190734Sthompsa			ptr->fixed[3] = 1536;
3211190734Sthompsa		}
3212190734Sthompsa		break;
3213190734Sthompsa	}
3214190734Sthompsa}
3215194677Sthompsa
3216194677Sthompsavoid	*
3217194677Sthompsausbd_xfer_softc(struct usb_xfer *xfer)
3218194677Sthompsa{
3219194677Sthompsa	return (xfer->priv_sc);
3220194677Sthompsa}
3221194677Sthompsa
3222194677Sthompsavoid *
3223194677Sthompsausbd_xfer_get_priv(struct usb_xfer *xfer)
3224194677Sthompsa{
3225194677Sthompsa	return (xfer->priv_fifo);
3226194677Sthompsa}
3227194677Sthompsa
3228194677Sthompsavoid
3229194677Sthompsausbd_xfer_set_priv(struct usb_xfer *xfer, void *ptr)
3230194677Sthompsa{
3231194677Sthompsa	xfer->priv_fifo = ptr;
3232194677Sthompsa}
3233194677Sthompsa
3234194677Sthompsauint8_t
3235194677Sthompsausbd_xfer_state(struct usb_xfer *xfer)
3236194677Sthompsa{
3237194677Sthompsa	return (xfer->usb_state);
3238194677Sthompsa}
3239194677Sthompsa
3240194677Sthompsavoid
3241194677Sthompsausbd_xfer_set_flag(struct usb_xfer *xfer, int flag)
3242194677Sthompsa{
3243194677Sthompsa	switch (flag) {
3244194677Sthompsa		case USB_FORCE_SHORT_XFER:
3245194677Sthompsa			xfer->flags.force_short_xfer = 1;
3246194677Sthompsa			break;
3247194677Sthompsa		case USB_SHORT_XFER_OK:
3248194677Sthompsa			xfer->flags.short_xfer_ok = 1;
3249194677Sthompsa			break;
3250195121Sthompsa		case USB_MULTI_SHORT_OK:
3251195121Sthompsa			xfer->flags.short_frames_ok = 1;
3252195121Sthompsa			break;
3253195121Sthompsa		case USB_MANUAL_STATUS:
3254195121Sthompsa			xfer->flags.manual_status = 1;
3255195121Sthompsa			break;
3256194677Sthompsa	}
3257194677Sthompsa}
3258194677Sthompsa
3259194677Sthompsavoid
3260194677Sthompsausbd_xfer_clr_flag(struct usb_xfer *xfer, int flag)
3261194677Sthompsa{
3262194677Sthompsa	switch (flag) {
3263194677Sthompsa		case USB_FORCE_SHORT_XFER:
3264194677Sthompsa			xfer->flags.force_short_xfer = 0;
3265194677Sthompsa			break;
3266194677Sthompsa		case USB_SHORT_XFER_OK:
3267194677Sthompsa			xfer->flags.short_xfer_ok = 0;
3268194677Sthompsa			break;
3269195121Sthompsa		case USB_MULTI_SHORT_OK:
3270195121Sthompsa			xfer->flags.short_frames_ok = 0;
3271195121Sthompsa			break;
3272195121Sthompsa		case USB_MANUAL_STATUS:
3273195121Sthompsa			xfer->flags.manual_status = 0;
3274195121Sthompsa			break;
3275194677Sthompsa	}
3276194677Sthompsa}
3277195121Sthompsa
3278195121Sthompsa/*
3279195121Sthompsa * The following function returns in milliseconds when the isochronous
3280195121Sthompsa * transfer was completed by the hardware. The returned value wraps
3281195121Sthompsa * around 65536 milliseconds.
3282195121Sthompsa */
3283195121Sthompsauint16_t
3284195121Sthompsausbd_xfer_get_timestamp(struct usb_xfer *xfer)
3285195121Sthompsa{
3286195121Sthompsa	return (xfer->isoc_time_complete);
3287195121Sthompsa}
3288