1184610Salfred/* $FreeBSD: stable/10/sys/dev/usb/usb_transfer.c 361912 2020-06-08 09:28:26Z 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.
25246616Shselasky */
26184610Salfred
27246122Shselasky#ifdef USB_GLOBAL_INCLUDE_FILE
28246122Shselasky#include USB_GLOBAL_INCLUDE_FILE
29246122Shselasky#else
30194677Sthompsa#include <sys/stdint.h>
31194677Sthompsa#include <sys/stddef.h>
32194677Sthompsa#include <sys/param.h>
33194677Sthompsa#include <sys/queue.h>
34194677Sthompsa#include <sys/types.h>
35194677Sthompsa#include <sys/systm.h>
36194677Sthompsa#include <sys/kernel.h>
37194677Sthompsa#include <sys/bus.h>
38194677Sthompsa#include <sys/module.h>
39194677Sthompsa#include <sys/lock.h>
40194677Sthompsa#include <sys/mutex.h>
41194677Sthompsa#include <sys/condvar.h>
42194677Sthompsa#include <sys/sysctl.h>
43194677Sthompsa#include <sys/sx.h>
44194677Sthompsa#include <sys/unistd.h>
45194677Sthompsa#include <sys/callout.h>
46194677Sthompsa#include <sys/malloc.h>
47194677Sthompsa#include <sys/priv.h>
48230643Sattilio#include <sys/proc.h>
49194677Sthompsa
50188942Sthompsa#include <dev/usb/usb.h>
51194677Sthompsa#include <dev/usb/usbdi.h>
52194677Sthompsa#include <dev/usb/usbdi_util.h>
53184610Salfred
54194228Sthompsa#define	USB_DEBUG_VAR usb_debug
55184610Salfred
56188942Sthompsa#include <dev/usb/usb_core.h>
57188942Sthompsa#include <dev/usb/usb_busdma.h>
58188942Sthompsa#include <dev/usb/usb_process.h>
59188942Sthompsa#include <dev/usb/usb_transfer.h>
60188942Sthompsa#include <dev/usb/usb_device.h>
61188942Sthompsa#include <dev/usb/usb_debug.h>
62188942Sthompsa#include <dev/usb/usb_util.h>
63184610Salfred
64188942Sthompsa#include <dev/usb/usb_controller.h>
65188942Sthompsa#include <dev/usb/usb_bus.h>
66215649Sweongyo#include <dev/usb/usb_pf.h>
67246122Shselasky#endif			/* USB_GLOBAL_INCLUDE_FILE */
68184610Salfred
69194228Sthompsastruct usb_std_packet_size {
70184610Salfred	struct {
71184610Salfred		uint16_t min;		/* inclusive */
72184610Salfred		uint16_t max;		/* inclusive */
73184610Salfred	}	range;
74184610Salfred
75184610Salfred	uint16_t fixed[4];
76184610Salfred};
77184610Salfred
78194228Sthompsastatic usb_callback_t usb_request_callback;
79184610Salfred
80207080Sthompsastatic const struct usb_config usb_control_ep_cfg[USB_CTRL_XFER_MAX] = {
81184610Salfred
82184610Salfred	/* This transfer is used for generic control endpoint transfers */
83184610Salfred
84184610Salfred	[0] = {
85184610Salfred		.type = UE_CONTROL,
86184610Salfred		.endpoint = 0x00,	/* Control endpoint */
87184610Salfred		.direction = UE_DIR_ANY,
88190734Sthompsa		.bufsize = USB_EP0_BUFSIZE,	/* bytes */
89190734Sthompsa		.flags = {.proxy_buffer = 1,},
90194228Sthompsa		.callback = &usb_request_callback,
91192499Sthompsa		.usb_mode = USB_MODE_DUAL,	/* both modes */
92184610Salfred	},
93184610Salfred
94184610Salfred	/* This transfer is used for generic clear stall only */
95184610Salfred
96184610Salfred	[1] = {
97184610Salfred		.type = UE_CONTROL,
98184610Salfred		.endpoint = 0x00,	/* Control pipe */
99184610Salfred		.direction = UE_DIR_ANY,
100192984Sthompsa		.bufsize = sizeof(struct usb_device_request),
101194228Sthompsa		.callback = &usb_do_clear_stall_callback,
102190734Sthompsa		.timeout = 1000,	/* 1 second */
103190734Sthompsa		.interval = 50,	/* 50ms */
104190734Sthompsa		.usb_mode = USB_MODE_HOST,
105184610Salfred	},
106184610Salfred};
107184610Salfred
108353179Shselaskystatic const struct usb_config usb_control_ep_quirk_cfg[USB_CTRL_XFER_MAX] = {
109353179Shselasky
110353179Shselasky	/* This transfer is used for generic control endpoint transfers */
111353179Shselasky
112353179Shselasky	[0] = {
113353179Shselasky		.type = UE_CONTROL,
114353179Shselasky		.endpoint = 0x00,	/* Control endpoint */
115353179Shselasky		.direction = UE_DIR_ANY,
116353179Shselasky		.bufsize = 65535,	/* bytes */
117353179Shselasky		.callback = &usb_request_callback,
118353179Shselasky		.usb_mode = USB_MODE_DUAL,	/* both modes */
119353179Shselasky	},
120353179Shselasky
121353179Shselasky	/* This transfer is used for generic clear stall only */
122353179Shselasky
123353179Shselasky	[1] = {
124353179Shselasky		.type = UE_CONTROL,
125353179Shselasky		.endpoint = 0x00,	/* Control pipe */
126353179Shselasky		.direction = UE_DIR_ANY,
127353179Shselasky		.bufsize = sizeof(struct usb_device_request),
128353179Shselasky		.callback = &usb_do_clear_stall_callback,
129353179Shselasky		.timeout = 1000,	/* 1 second */
130353179Shselasky		.interval = 50,	/* 50ms */
131353179Shselasky		.usb_mode = USB_MODE_HOST,
132353179Shselasky	},
133353179Shselasky};
134353179Shselasky
135184610Salfred/* function prototypes */
136184610Salfred
137194228Sthompsastatic void	usbd_update_max_frame_size(struct usb_xfer *);
138194228Sthompsastatic void	usbd_transfer_unsetup_sub(struct usb_xfer_root *, uint8_t);
139194228Sthompsastatic void	usbd_control_transfer_init(struct usb_xfer *);
140194677Sthompsastatic int	usbd_setup_ctrl_transfer(struct usb_xfer *);
141194228Sthompsastatic void	usb_callback_proc(struct usb_proc_msg *);
142194228Sthompsastatic void	usbd_callback_ss_done_defer(struct usb_xfer *);
143194228Sthompsastatic void	usbd_callback_wrapper(struct usb_xfer_queue *);
144194228Sthompsastatic void	usbd_transfer_start_cb(void *);
145194228Sthompsastatic uint8_t	usbd_callback_wrapper_sub(struct usb_xfer *);
146194228Sthompsastatic void	usbd_get_std_packet_size(struct usb_std_packet_size *ptr,
147192500Sthompsa		    uint8_t type, enum usb_dev_speed speed);
148184610Salfred
149184610Salfred/*------------------------------------------------------------------------*
150194228Sthompsa *	usb_request_callback
151190734Sthompsa *------------------------------------------------------------------------*/
152190734Sthompsastatic void
153194677Sthompsausb_request_callback(struct usb_xfer *xfer, usb_error_t error)
154190734Sthompsa{
155192499Sthompsa	if (xfer->flags_int.usb_mode == USB_MODE_DEVICE)
156194677Sthompsa		usb_handle_request_callback(xfer, error);
157190734Sthompsa	else
158194677Sthompsa		usbd_do_request_callback(xfer, error);
159190734Sthompsa}
160190734Sthompsa
161190734Sthompsa/*------------------------------------------------------------------------*
162194228Sthompsa *	usbd_update_max_frame_size
163184610Salfred *
164184610Salfred * This function updates the maximum frame size, hence high speed USB
165184610Salfred * can transfer multiple consecutive packets.
166184610Salfred *------------------------------------------------------------------------*/
167184610Salfredstatic void
168194228Sthompsausbd_update_max_frame_size(struct usb_xfer *xfer)
169184610Salfred{
170184610Salfred	/* compute maximum frame size */
171213435Shselasky	/* this computation should not overflow 16-bit */
172213435Shselasky	/* max = 15 * 1024 */
173184610Salfred
174213435Shselasky	xfer->max_frame_size = xfer->max_packet_size * xfer->max_packet_count;
175184610Salfred}
176184610Salfred
177184610Salfred/*------------------------------------------------------------------------*
178194228Sthompsa *	usbd_get_dma_delay
179184610Salfred *
180184610Salfred * The following function is called when we need to
181184610Salfred * synchronize with DMA hardware.
182184610Salfred *
183184610Salfred * Returns:
184184610Salfred *    0: no DMA delay required
185184610Salfred * Else: milliseconds of DMA delay
186184610Salfred *------------------------------------------------------------------------*/
187193045Sthompsausb_timeout_t
188212134Sthompsausbd_get_dma_delay(struct usb_device *udev)
189184610Salfred{
190212134Sthompsa	struct usb_bus_methods *mtod;
191212134Sthompsa	uint32_t temp;
192184610Salfred
193212134Sthompsa	mtod = udev->bus->methods;
194212134Sthompsa	temp = 0;
195212134Sthompsa
196212134Sthompsa	if (mtod->get_dma_delay) {
197212134Sthompsa		(mtod->get_dma_delay) (udev, &temp);
198184610Salfred		/*
199184610Salfred		 * Round up and convert to milliseconds. Note that we use
200184610Salfred		 * 1024 milliseconds per second. to save a division.
201184610Salfred		 */
202184610Salfred		temp += 0x3FF;
203184610Salfred		temp /= 0x400;
204184610Salfred	}
205184610Salfred	return (temp);
206184610Salfred}
207184610Salfred
208184610Salfred/*------------------------------------------------------------------------*
209194228Sthompsa *	usbd_transfer_setup_sub_malloc
210184610Salfred *
211184610Salfred * This function will allocate one or more DMA'able memory chunks
212184610Salfred * according to "size", "align" and "count" arguments. "ppc" is
213184610Salfred * pointed to a linear array of USB page caches afterwards.
214184610Salfred *
215244500Shselasky * If the "align" argument is equal to "1" a non-contiguous allocation
216244500Shselasky * can happen. Else if the "align" argument is greater than "1", the
217244500Shselasky * allocation will always be contiguous in memory.
218244500Shselasky *
219184610Salfred * Returns:
220184610Salfred *    0: Success
221184610Salfred * Else: Failure
222184610Salfred *------------------------------------------------------------------------*/
223190180Sthompsa#if USB_HAVE_BUSDMA
224184610Salfreduint8_t
225194228Sthompsausbd_transfer_setup_sub_malloc(struct usb_setup_params *parm,
226193074Sthompsa    struct usb_page_cache **ppc, usb_size_t size, usb_size_t align,
227193074Sthompsa    usb_size_t count)
228184610Salfred{
229192984Sthompsa	struct usb_page_cache *pc;
230192984Sthompsa	struct usb_page *pg;
231184610Salfred	void *buf;
232193074Sthompsa	usb_size_t n_dma_pc;
233244500Shselasky	usb_size_t n_dma_pg;
234193074Sthompsa	usb_size_t n_obj;
235193074Sthompsa	usb_size_t x;
236193074Sthompsa	usb_size_t y;
237193074Sthompsa	usb_size_t r;
238193074Sthompsa	usb_size_t z;
239184610Salfred
240244500Shselasky	USB_ASSERT(align > 0, ("Invalid alignment, 0x%08x\n",
241184610Salfred	    align));
242199816Sthompsa	USB_ASSERT(size > 0, ("Invalid size = 0\n"));
243184610Salfred
244184610Salfred	if (count == 0) {
245184610Salfred		return (0);		/* nothing to allocate */
246184610Salfred	}
247184610Salfred	/*
248184610Salfred	 * Make sure that the size is aligned properly.
249184610Salfred	 */
250184610Salfred	size = -((-size) & (-align));
251184610Salfred
252184610Salfred	/*
253184610Salfred	 * Try multi-allocation chunks to reduce the number of DMA
254184610Salfred	 * allocations, hence DMA allocations are slow.
255184610Salfred	 */
256244500Shselasky	if (align == 1) {
257244500Shselasky		/* special case - non-cached multi page DMA memory */
258184610Salfred		n_dma_pc = count;
259244500Shselasky		n_dma_pg = (2 + (size / USB_PAGE_SIZE));
260184610Salfred		n_obj = 1;
261244500Shselasky	} else if (size >= USB_PAGE_SIZE) {
262244500Shselasky		n_dma_pc = count;
263244500Shselasky		n_dma_pg = 1;
264244500Shselasky		n_obj = 1;
265184610Salfred	} else {
266184610Salfred		/* compute number of objects per page */
267278510Shselasky#ifdef USB_DMA_SINGLE_ALLOC
268278510Shselasky		n_obj = 1;
269278510Shselasky#else
270236070Smarius		n_obj = (USB_PAGE_SIZE / size);
271278510Shselasky#endif
272184610Salfred		/*
273184610Salfred		 * Compute number of DMA chunks, rounded up
274184610Salfred		 * to nearest one:
275184610Salfred		 */
276184610Salfred		n_dma_pc = ((count + n_obj - 1) / n_obj);
277244500Shselasky		n_dma_pg = 1;
278184610Salfred	}
279184610Salfred
280244500Shselasky	/*
281244500Shselasky	 * DMA memory is allocated once, but mapped twice. That's why
282244500Shselasky	 * there is one list for auto-free and another list for
283244500Shselasky	 * non-auto-free which only holds the mapping and not the
284244500Shselasky	 * allocation.
285244500Shselasky	 */
286184610Salfred	if (parm->buf == NULL) {
287244500Shselasky		/* reserve memory (auto-free) */
288244500Shselasky		parm->dma_page_ptr += n_dma_pc * n_dma_pg;
289184610Salfred		parm->dma_page_cache_ptr += n_dma_pc;
290244500Shselasky
291244500Shselasky		/* reserve memory (no-auto-free) */
292244500Shselasky		parm->dma_page_ptr += count * n_dma_pg;
293184610Salfred		parm->xfer_page_cache_ptr += count;
294184610Salfred		return (0);
295184610Salfred	}
296184610Salfred	for (x = 0; x != n_dma_pc; x++) {
297184610Salfred		/* need to initialize the page cache */
298184610Salfred		parm->dma_page_cache_ptr[x].tag_parent =
299187173Sthompsa		    &parm->curr_xfer->xroot->dma_parent_tag;
300184610Salfred	}
301184610Salfred	for (x = 0; x != count; x++) {
302184610Salfred		/* need to initialize the page cache */
303184610Salfred		parm->xfer_page_cache_ptr[x].tag_parent =
304187173Sthompsa		    &parm->curr_xfer->xroot->dma_parent_tag;
305184610Salfred	}
306184610Salfred
307278510Shselasky	if (ppc != NULL) {
308278510Shselasky		if (n_obj != 1)
309278510Shselasky			*ppc = parm->xfer_page_cache_ptr;
310278510Shselasky		else
311278510Shselasky			*ppc = parm->dma_page_cache_ptr;
312184610Salfred	}
313184610Salfred	r = count;			/* set remainder count */
314184610Salfred	z = n_obj * size;		/* set allocation size */
315184610Salfred	pc = parm->xfer_page_cache_ptr;
316184610Salfred	pg = parm->dma_page_ptr;
317184610Salfred
318278510Shselasky	if (n_obj == 1) {
319278510Shselasky	    /*
320278510Shselasky	     * Avoid mapping memory twice if only a single object
321278510Shselasky	     * should be allocated per page cache:
322278510Shselasky	     */
323278510Shselasky	    for (x = 0; x != n_dma_pc; x++) {
324278510Shselasky		if (usb_pc_alloc_mem(parm->dma_page_cache_ptr,
325278510Shselasky		    pg, z, align)) {
326278510Shselasky			return (1);	/* failure */
327278510Shselasky		}
328278510Shselasky		/* Make room for one DMA page cache and "n_dma_pg" pages */
329278510Shselasky		parm->dma_page_cache_ptr++;
330278510Shselasky		pg += n_dma_pg;
331278510Shselasky	    }
332278510Shselasky	} else {
333278510Shselasky	    for (x = 0; x != n_dma_pc; x++) {
334184610Salfred
335184610Salfred		if (r < n_obj) {
336184610Salfred			/* compute last remainder */
337184610Salfred			z = r * size;
338184610Salfred			n_obj = r;
339184610Salfred		}
340194228Sthompsa		if (usb_pc_alloc_mem(parm->dma_page_cache_ptr,
341184610Salfred		    pg, z, align)) {
342184610Salfred			return (1);	/* failure */
343184610Salfred		}
344184610Salfred		/* Set beginning of current buffer */
345184610Salfred		buf = parm->dma_page_cache_ptr->buffer;
346278510Shselasky		/* Make room for one DMA page cache and "n_dma_pg" pages */
347184610Salfred		parm->dma_page_cache_ptr++;
348244500Shselasky		pg += n_dma_pg;
349184610Salfred
350244500Shselasky		for (y = 0; (y != n_obj); y++, r--, pc++, pg += n_dma_pg) {
351184610Salfred
352184610Salfred			/* Load sub-chunk into DMA */
353194228Sthompsa			if (usb_pc_dmamap_create(pc, size)) {
354184610Salfred				return (1);	/* failure */
355184610Salfred			}
356184610Salfred			pc->buffer = USB_ADD_BYTES(buf, y * size);
357184610Salfred			pc->page_start = pg;
358184610Salfred
359184610Salfred			mtx_lock(pc->tag_parent->mtx);
360194228Sthompsa			if (usb_pc_load_mem(pc, size, 1 /* synchronous */ )) {
361184610Salfred				mtx_unlock(pc->tag_parent->mtx);
362184610Salfred				return (1);	/* failure */
363184610Salfred			}
364184610Salfred			mtx_unlock(pc->tag_parent->mtx);
365184610Salfred		}
366278510Shselasky	    }
367184610Salfred	}
368184610Salfred
369184610Salfred	parm->xfer_page_cache_ptr = pc;
370184610Salfred	parm->dma_page_ptr = pg;
371184610Salfred	return (0);
372184610Salfred}
373190180Sthompsa#endif
374184610Salfred
375184610Salfred/*------------------------------------------------------------------------*
376361912Shselasky *	usbd_get_max_frame_length
377361912Shselasky *
378361912Shselasky * This function returns the maximum single frame length as computed by
379361912Shselasky * usbd_transfer_setup(). It is useful when computing buffer sizes for
380361912Shselasky * devices having multiple alternate settings. The SuperSpeed endpoint
381361912Shselasky * companion pointer is allowed to be NULL.
382361912Shselasky *------------------------------------------------------------------------*/
383361912Shselaskyuint32_t
384361912Shselaskyusbd_get_max_frame_length(const struct usb_endpoint_descriptor *edesc,
385361912Shselasky    const struct usb_endpoint_ss_comp_descriptor *ecomp,
386361912Shselasky    enum usb_dev_speed speed)
387361912Shselasky{
388361912Shselasky	uint32_t max_packet_size;
389361912Shselasky	uint32_t max_packet_count;
390361912Shselasky	uint8_t type;
391361912Shselasky
392361912Shselasky	max_packet_size = UGETW(edesc->wMaxPacketSize);
393361912Shselasky	max_packet_count = 1;
394361912Shselasky	type = (edesc->bmAttributes & UE_XFERTYPE);
395361912Shselasky
396361912Shselasky	switch (speed) {
397361912Shselasky	case USB_SPEED_HIGH:
398361912Shselasky		switch (type) {
399361912Shselasky		case UE_ISOCHRONOUS:
400361912Shselasky		case UE_INTERRUPT:
401361912Shselasky			max_packet_count +=
402361912Shselasky			    (max_packet_size >> 11) & 3;
403361912Shselasky
404361912Shselasky			/* check for invalid max packet count */
405361912Shselasky			if (max_packet_count > 3)
406361912Shselasky				max_packet_count = 3;
407361912Shselasky			break;
408361912Shselasky		default:
409361912Shselasky			break;
410361912Shselasky		}
411361912Shselasky		max_packet_size &= 0x7FF;
412361912Shselasky		break;
413361912Shselasky	case USB_SPEED_SUPER:
414361912Shselasky		max_packet_count += (max_packet_size >> 11) & 3;
415361912Shselasky
416361912Shselasky		if (ecomp != NULL)
417361912Shselasky			max_packet_count += ecomp->bMaxBurst;
418361912Shselasky
419361912Shselasky		if ((max_packet_count == 0) ||
420361912Shselasky		    (max_packet_count > 16))
421361912Shselasky			max_packet_count = 16;
422361912Shselasky
423361912Shselasky		switch (type) {
424361912Shselasky		case UE_CONTROL:
425361912Shselasky			max_packet_count = 1;
426361912Shselasky			break;
427361912Shselasky		case UE_ISOCHRONOUS:
428361912Shselasky			if (ecomp != NULL) {
429361912Shselasky				uint8_t mult;
430361912Shselasky
431361912Shselasky				mult = UE_GET_SS_ISO_MULT(
432361912Shselasky				    ecomp->bmAttributes) + 1;
433361912Shselasky				if (mult > 3)
434361912Shselasky					mult = 3;
435361912Shselasky
436361912Shselasky				max_packet_count *= mult;
437361912Shselasky			}
438361912Shselasky			break;
439361912Shselasky		default:
440361912Shselasky			break;
441361912Shselasky		}
442361912Shselasky		max_packet_size &= 0x7FF;
443361912Shselasky		break;
444361912Shselasky	default:
445361912Shselasky		break;
446361912Shselasky	}
447361912Shselasky	return (max_packet_size * max_packet_count);
448361912Shselasky}
449361912Shselasky
450361912Shselasky/*------------------------------------------------------------------------*
451194228Sthompsa *	usbd_transfer_setup_sub - transfer setup subroutine
452184610Salfred *
453184610Salfred * This function must be called from the "xfer_setup" callback of the
454184610Salfred * USB Host or Device controller driver when setting up an USB
455184610Salfred * transfer. This function will setup correct packet sizes, buffer
456192984Sthompsa * sizes, flags and more, that are stored in the "usb_xfer"
457184610Salfred * structure.
458184610Salfred *------------------------------------------------------------------------*/
459184610Salfredvoid
460194228Sthompsausbd_transfer_setup_sub(struct usb_setup_params *parm)
461184610Salfred{
462184610Salfred	enum {
463184610Salfred		REQ_SIZE = 8,
464184610Salfred		MIN_PKT = 8,
465184610Salfred	};
466192984Sthompsa	struct usb_xfer *xfer = parm->curr_xfer;
467192984Sthompsa	const struct usb_config *setup = parm->curr_setup;
468213435Shselasky	struct usb_endpoint_ss_comp_descriptor *ecomp;
469192984Sthompsa	struct usb_endpoint_descriptor *edesc;
470194228Sthompsa	struct usb_std_packet_size std_size;
471193045Sthompsa	usb_frcount_t n_frlengths;
472193045Sthompsa	usb_frcount_t n_frbuffers;
473193045Sthompsa	usb_frcount_t x;
474263643Shselasky	uint16_t maxp_old;
475184610Salfred	uint8_t type;
476184610Salfred	uint8_t zmps;
477184610Salfred
478184610Salfred	/*
479184610Salfred	 * Sanity check. The following parameters must be initialized before
480184610Salfred	 * calling this function.
481184610Salfred	 */
482184610Salfred	if ((parm->hc_max_packet_size == 0) ||
483184610Salfred	    (parm->hc_max_packet_count == 0) ||
484184610Salfred	    (parm->hc_max_frame_size == 0)) {
485184610Salfred		parm->err = USB_ERR_INVAL;
486184610Salfred		goto done;
487184610Salfred	}
488193644Sthompsa	edesc = xfer->endpoint->edesc;
489213435Shselasky	ecomp = xfer->endpoint->ecomp;
490184610Salfred
491184610Salfred	type = (edesc->bmAttributes & UE_XFERTYPE);
492184610Salfred
493190734Sthompsa	xfer->flags = setup->flags;
494190734Sthompsa	xfer->nframes = setup->frames;
495190734Sthompsa	xfer->timeout = setup->timeout;
496190734Sthompsa	xfer->callback = setup->callback;
497190734Sthompsa	xfer->interval = setup->interval;
498193644Sthompsa	xfer->endpointno = edesc->bEndpointAddress;
499184610Salfred	xfer->max_packet_size = UGETW(edesc->wMaxPacketSize);
500184610Salfred	xfer->max_packet_count = 1;
501184610Salfred	/* make a shadow copy: */
502192499Sthompsa	xfer->flags_int.usb_mode = parm->udev->flags.usb_mode;
503184610Salfred
504190734Sthompsa	parm->bufsize = setup->bufsize;
505184610Salfred
506213435Shselasky	switch (parm->speed) {
507213435Shselasky	case USB_SPEED_HIGH:
508213435Shselasky		switch (type) {
509213435Shselasky		case UE_ISOCHRONOUS:
510213435Shselasky		case UE_INTERRUPT:
511239214Shselasky			xfer->max_packet_count +=
512239214Shselasky			    (xfer->max_packet_size >> 11) & 3;
513213435Shselasky
514213435Shselasky			/* check for invalid max packet count */
515213435Shselasky			if (xfer->max_packet_count > 3)
516213435Shselasky				xfer->max_packet_count = 3;
517213435Shselasky			break;
518213435Shselasky		default:
519213435Shselasky			break;
520213435Shselasky		}
521213435Shselasky		xfer->max_packet_size &= 0x7FF;
522213435Shselasky		break;
523213435Shselasky	case USB_SPEED_SUPER:
524184610Salfred		xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
525213435Shselasky
526213435Shselasky		if (ecomp != NULL)
527213435Shselasky			xfer->max_packet_count += ecomp->bMaxBurst;
528213435Shselasky
529213435Shselasky		if ((xfer->max_packet_count == 0) ||
530213435Shselasky		    (xfer->max_packet_count > 16))
531213435Shselasky			xfer->max_packet_count = 16;
532213435Shselasky
533213435Shselasky		switch (type) {
534213435Shselasky		case UE_CONTROL:
535213435Shselasky			xfer->max_packet_count = 1;
536213435Shselasky			break;
537213435Shselasky		case UE_ISOCHRONOUS:
538213435Shselasky			if (ecomp != NULL) {
539213435Shselasky				uint8_t mult;
540213435Shselasky
541239214Shselasky				mult = UE_GET_SS_ISO_MULT(
542239214Shselasky				    ecomp->bmAttributes) + 1;
543213435Shselasky				if (mult > 3)
544213435Shselasky					mult = 3;
545213435Shselasky
546213435Shselasky				xfer->max_packet_count *= mult;
547213435Shselasky			}
548213435Shselasky			break;
549213435Shselasky		default:
550213435Shselasky			break;
551213435Shselasky		}
552184610Salfred		xfer->max_packet_size &= 0x7FF;
553213435Shselasky		break;
554213435Shselasky	default:
555213435Shselasky		break;
556184610Salfred	}
557184610Salfred	/* range check "max_packet_count" */
558184610Salfred
559184610Salfred	if (xfer->max_packet_count > parm->hc_max_packet_count) {
560184610Salfred		xfer->max_packet_count = parm->hc_max_packet_count;
561184610Salfred	}
562263643Shselasky
563263643Shselasky	/* store max packet size value before filtering */
564263643Shselasky
565263643Shselasky	maxp_old = xfer->max_packet_size;
566263643Shselasky
567184610Salfred	/* filter "wMaxPacketSize" according to HC capabilities */
568184610Salfred
569184610Salfred	if ((xfer->max_packet_size > parm->hc_max_packet_size) ||
570184610Salfred	    (xfer->max_packet_size == 0)) {
571184610Salfred		xfer->max_packet_size = parm->hc_max_packet_size;
572184610Salfred	}
573184610Salfred	/* filter "wMaxPacketSize" according to standard sizes */
574184610Salfred
575194228Sthompsa	usbd_get_std_packet_size(&std_size, type, parm->speed);
576184610Salfred
577184610Salfred	if (std_size.range.min || std_size.range.max) {
578184610Salfred
579184610Salfred		if (xfer->max_packet_size < std_size.range.min) {
580184610Salfred			xfer->max_packet_size = std_size.range.min;
581184610Salfred		}
582184610Salfred		if (xfer->max_packet_size > std_size.range.max) {
583184610Salfred			xfer->max_packet_size = std_size.range.max;
584184610Salfred		}
585184610Salfred	} else {
586184610Salfred
587184610Salfred		if (xfer->max_packet_size >= std_size.fixed[3]) {
588184610Salfred			xfer->max_packet_size = std_size.fixed[3];
589184610Salfred		} else if (xfer->max_packet_size >= std_size.fixed[2]) {
590184610Salfred			xfer->max_packet_size = std_size.fixed[2];
591184610Salfred		} else if (xfer->max_packet_size >= std_size.fixed[1]) {
592184610Salfred			xfer->max_packet_size = std_size.fixed[1];
593184610Salfred		} else {
594184610Salfred			/* only one possibility left */
595184610Salfred			xfer->max_packet_size = std_size.fixed[0];
596184610Salfred		}
597184610Salfred	}
598184610Salfred
599263643Shselasky	/*
600263643Shselasky	 * Check if the max packet size was outside its allowed range
601263643Shselasky	 * and clamped to a valid value:
602263643Shselasky	 */
603263643Shselasky	if (maxp_old != xfer->max_packet_size)
604263643Shselasky		xfer->flags_int.maxp_was_clamped = 1;
605263643Shselasky
606184610Salfred	/* compute "max_frame_size" */
607184610Salfred
608194228Sthompsa	usbd_update_max_frame_size(xfer);
609184610Salfred
610184610Salfred	/* check interrupt interval and transfer pre-delay */
611184610Salfred
612184610Salfred	if (type == UE_ISOCHRONOUS) {
613184610Salfred
614190181Sthompsa		uint16_t frame_limit;
615184610Salfred
616184610Salfred		xfer->interval = 0;	/* not used, must be zero */
617184610Salfred		xfer->flags_int.isochronous_xfr = 1;	/* set flag */
618184610Salfred
619184610Salfred		if (xfer->timeout == 0) {
620184610Salfred			/*
621184610Salfred			 * set a default timeout in
622184610Salfred			 * case something goes wrong!
623184610Salfred			 */
624184610Salfred			xfer->timeout = 1000 / 4;
625184610Salfred		}
626187180Sthompsa		switch (parm->speed) {
627187180Sthompsa		case USB_SPEED_LOW:
628187180Sthompsa		case USB_SPEED_FULL:
629187180Sthompsa			frame_limit = USB_MAX_FS_ISOC_FRAMES_PER_XFER;
630199059Sthompsa			xfer->fps_shift = 0;
631187180Sthompsa			break;
632187180Sthompsa		default:
633184610Salfred			frame_limit = USB_MAX_HS_ISOC_FRAMES_PER_XFER;
634199059Sthompsa			xfer->fps_shift = edesc->bInterval;
635199059Sthompsa			if (xfer->fps_shift > 0)
636199059Sthompsa				xfer->fps_shift--;
637199059Sthompsa			if (xfer->fps_shift > 3)
638199059Sthompsa				xfer->fps_shift = 3;
639219100Shselasky			if (xfer->flags.pre_scale_frames != 0)
640219100Shselasky				xfer->nframes <<= (3 - xfer->fps_shift);
641187180Sthompsa			break;
642184610Salfred		}
643184610Salfred
644184610Salfred		if (xfer->nframes > frame_limit) {
645184610Salfred			/*
646184610Salfred			 * this is not going to work
647184610Salfred			 * cross hardware
648184610Salfred			 */
649184610Salfred			parm->err = USB_ERR_INVAL;
650184610Salfred			goto done;
651184610Salfred		}
652184610Salfred		if (xfer->nframes == 0) {
653184610Salfred			/*
654184610Salfred			 * this is not a valid value
655184610Salfred			 */
656184610Salfred			parm->err = USB_ERR_ZERO_NFRAMES;
657184610Salfred			goto done;
658184610Salfred		}
659184610Salfred	} else {
660184610Salfred
661184610Salfred		/*
662213435Shselasky		 * If a value is specified use that else check the
663213435Shselasky		 * endpoint descriptor!
664184610Salfred		 */
665213435Shselasky		if (type == UE_INTERRUPT) {
666184610Salfred
667213435Shselasky			uint32_t temp;
668184610Salfred
669213435Shselasky			if (xfer->interval == 0) {
670213435Shselasky
671184610Salfred				xfer->interval = edesc->bInterval;
672184610Salfred
673187180Sthompsa				switch (parm->speed) {
674213435Shselasky				case USB_SPEED_LOW:
675213435Shselasky				case USB_SPEED_FULL:
676213435Shselasky					break;
677213435Shselasky				default:
678187180Sthompsa					/* 125us -> 1ms */
679187180Sthompsa					if (xfer->interval < 4)
680187180Sthompsa						xfer->interval = 1;
681187180Sthompsa					else if (xfer->interval > 16)
682213435Shselasky						xfer->interval = (1 << (16 - 4));
683187180Sthompsa					else
684187180Sthompsa						xfer->interval =
685213435Shselasky						    (1 << (xfer->interval - 4));
686187180Sthompsa					break;
687184610Salfred				}
688184610Salfred			}
689213435Shselasky
690213435Shselasky			if (xfer->interval == 0) {
691213435Shselasky				/*
692213435Shselasky				 * One millisecond is the smallest
693213435Shselasky				 * interval we support:
694213435Shselasky				 */
695213435Shselasky				xfer->interval = 1;
696213435Shselasky			}
697213435Shselasky
698213435Shselasky			xfer->fps_shift = 0;
699213435Shselasky			temp = 1;
700213435Shselasky
701213435Shselasky			while ((temp != 0) && (temp < xfer->interval)) {
702213435Shselasky				xfer->fps_shift++;
703213435Shselasky				temp *= 2;
704213435Shselasky			}
705213435Shselasky
706213435Shselasky			switch (parm->speed) {
707213435Shselasky			case USB_SPEED_LOW:
708213435Shselasky			case USB_SPEED_FULL:
709213435Shselasky				break;
710213435Shselasky			default:
711213435Shselasky				xfer->fps_shift += 3;
712213435Shselasky				break;
713213435Shselasky			}
714184610Salfred		}
715184610Salfred	}
716184610Salfred
717184610Salfred	/*
718184610Salfred	 * NOTE: we do not allow "max_packet_size" or "max_frame_size"
719184610Salfred	 * to be equal to zero when setting up USB transfers, hence
720184610Salfred	 * this leads to alot of extra code in the USB kernel.
721184610Salfred	 */
722184610Salfred
723184610Salfred	if ((xfer->max_frame_size == 0) ||
724184610Salfred	    (xfer->max_packet_size == 0)) {
725184610Salfred
726184610Salfred		zmps = 1;
727184610Salfred
728184610Salfred		if ((parm->bufsize <= MIN_PKT) &&
729184610Salfred		    (type != UE_CONTROL) &&
730184610Salfred		    (type != UE_BULK)) {
731184610Salfred
732184610Salfred			/* workaround */
733184610Salfred			xfer->max_packet_size = MIN_PKT;
734184610Salfred			xfer->max_packet_count = 1;
735184610Salfred			parm->bufsize = 0;	/* automatic setup length */
736194228Sthompsa			usbd_update_max_frame_size(xfer);
737184610Salfred
738184610Salfred		} else {
739184610Salfred			parm->err = USB_ERR_ZERO_MAXP;
740184610Salfred			goto done;
741184610Salfred		}
742184610Salfred
743184610Salfred	} else {
744184610Salfred		zmps = 0;
745184610Salfred	}
746184610Salfred
747184610Salfred	/*
748184610Salfred	 * check if we should setup a default
749184610Salfred	 * length:
750184610Salfred	 */
751184610Salfred
752184610Salfred	if (parm->bufsize == 0) {
753184610Salfred
754184610Salfred		parm->bufsize = xfer->max_frame_size;
755184610Salfred
756184610Salfred		if (type == UE_ISOCHRONOUS) {
757184610Salfred			parm->bufsize *= xfer->nframes;
758184610Salfred		}
759184610Salfred	}
760184610Salfred	/*
761184610Salfred	 * check if we are about to setup a proxy
762184610Salfred	 * type of buffer:
763184610Salfred	 */
764184610Salfred
765184610Salfred	if (xfer->flags.proxy_buffer) {
766184610Salfred
767184610Salfred		/* round bufsize up */
768184610Salfred
769184610Salfred		parm->bufsize += (xfer->max_frame_size - 1);
770184610Salfred
771184610Salfred		if (parm->bufsize < xfer->max_frame_size) {
772184610Salfred			/* length wrapped around */
773184610Salfred			parm->err = USB_ERR_INVAL;
774184610Salfred			goto done;
775184610Salfred		}
776184610Salfred		/* subtract remainder */
777184610Salfred
778184610Salfred		parm->bufsize -= (parm->bufsize % xfer->max_frame_size);
779184610Salfred
780184610Salfred		/* add length of USB device request structure, if any */
781184610Salfred
782184610Salfred		if (type == UE_CONTROL) {
783184610Salfred			parm->bufsize += REQ_SIZE;	/* SETUP message */
784184610Salfred		}
785184610Salfred	}
786184610Salfred	xfer->max_data_length = parm->bufsize;
787184610Salfred
788184610Salfred	/* Setup "n_frlengths" and "n_frbuffers" */
789184610Salfred
790184610Salfred	if (type == UE_ISOCHRONOUS) {
791184610Salfred		n_frlengths = xfer->nframes;
792184610Salfred		n_frbuffers = 1;
793184610Salfred	} else {
794184610Salfred
795184610Salfred		if (type == UE_CONTROL) {
796184610Salfred			xfer->flags_int.control_xfr = 1;
797184610Salfred			if (xfer->nframes == 0) {
798184610Salfred				if (parm->bufsize <= REQ_SIZE) {
799184610Salfred					/*
800184610Salfred					 * there will never be any data
801184610Salfred					 * stage
802184610Salfred					 */
803184610Salfred					xfer->nframes = 1;
804184610Salfred				} else {
805184610Salfred					xfer->nframes = 2;
806184610Salfred				}
807184610Salfred			}
808184610Salfred		} else {
809184610Salfred			if (xfer->nframes == 0) {
810184610Salfred				xfer->nframes = 1;
811184610Salfred			}
812184610Salfred		}
813184610Salfred
814184610Salfred		n_frlengths = xfer->nframes;
815184610Salfred		n_frbuffers = xfer->nframes;
816184610Salfred	}
817184610Salfred
818184610Salfred	/*
819184610Salfred	 * check if we have room for the
820184610Salfred	 * USB device request structure:
821184610Salfred	 */
822184610Salfred
823184610Salfred	if (type == UE_CONTROL) {
824184610Salfred
825184610Salfred		if (xfer->max_data_length < REQ_SIZE) {
826184610Salfred			/* length wrapped around or too small bufsize */
827184610Salfred			parm->err = USB_ERR_INVAL;
828184610Salfred			goto done;
829184610Salfred		}
830184610Salfred		xfer->max_data_length -= REQ_SIZE;
831184610Salfred	}
832220301Shselasky	/*
833220301Shselasky	 * Setup "frlengths" and shadow "frlengths" for keeping the
834220301Shselasky	 * initial frame lengths when a USB transfer is complete. This
835220301Shselasky	 * information is useful when computing isochronous offsets.
836220301Shselasky	 */
837184610Salfred	xfer->frlengths = parm->xfer_length_ptr;
838220301Shselasky	parm->xfer_length_ptr += 2 * n_frlengths;
839184610Salfred
840184610Salfred	/* setup "frbuffers" */
841184610Salfred	xfer->frbuffers = parm->xfer_page_cache_ptr;
842184610Salfred	parm->xfer_page_cache_ptr += n_frbuffers;
843184610Salfred
844194677Sthompsa	/* initialize max frame count */
845194677Sthompsa	xfer->max_frame_count = xfer->nframes;
846194677Sthompsa
847184610Salfred	/*
848184610Salfred	 * check if we need to setup
849184610Salfred	 * a local buffer:
850184610Salfred	 */
851184610Salfred
852184610Salfred	if (!xfer->flags.ext_buffer) {
853244500Shselasky#if USB_HAVE_BUSDMA
854244500Shselasky		struct usb_page_search page_info;
855244500Shselasky		struct usb_page_cache *pc;
856184610Salfred
857244500Shselasky		if (usbd_transfer_setup_sub_malloc(parm,
858244500Shselasky		    &pc, parm->bufsize, 1, 1)) {
859244500Shselasky			parm->err = USB_ERR_NOMEM;
860244500Shselasky		} else if (parm->buf != NULL) {
861244500Shselasky
862244500Shselasky			usbd_get_page(pc, 0, &page_info);
863244500Shselasky
864244500Shselasky			xfer->local_buffer = page_info.buffer;
865244500Shselasky
866244500Shselasky			usbd_xfer_set_frame_offset(xfer, 0, 0);
867244500Shselasky
868244500Shselasky			if ((type == UE_CONTROL) && (n_frbuffers > 1)) {
869244500Shselasky				usbd_xfer_set_frame_offset(xfer, REQ_SIZE, 1);
870244500Shselasky			}
871244500Shselasky		}
872244500Shselasky#else
873184610Salfred		/* align data */
874184610Salfred		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
875184610Salfred
876244500Shselasky		if (parm->buf != NULL) {
877184610Salfred			xfer->local_buffer =
878184610Salfred			    USB_ADD_BYTES(parm->buf, parm->size[0]);
879184610Salfred
880194677Sthompsa			usbd_xfer_set_frame_offset(xfer, 0, 0);
881184610Salfred
882184610Salfred			if ((type == UE_CONTROL) && (n_frbuffers > 1)) {
883194677Sthompsa				usbd_xfer_set_frame_offset(xfer, REQ_SIZE, 1);
884184610Salfred			}
885184610Salfred		}
886184610Salfred		parm->size[0] += parm->bufsize;
887184610Salfred
888184610Salfred		/* align data again */
889184610Salfred		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
890244500Shselasky#endif
891184610Salfred	}
892184610Salfred	/*
893184610Salfred	 * Compute maximum buffer size
894184610Salfred	 */
895184610Salfred
896184610Salfred	if (parm->bufsize_max < parm->bufsize) {
897184610Salfred		parm->bufsize_max = parm->bufsize;
898184610Salfred	}
899190180Sthompsa#if USB_HAVE_BUSDMA
900184610Salfred	if (xfer->flags_int.bdma_enable) {
901184610Salfred		/*
902184610Salfred		 * Setup "dma_page_ptr".
903184610Salfred		 *
904184610Salfred		 * Proof for formula below:
905184610Salfred		 *
906184610Salfred		 * Assume there are three USB frames having length "a", "b" and
907184610Salfred		 * "c". These USB frames will at maximum need "z"
908192984Sthompsa		 * "usb_page" structures. "z" is given by:
909184610Salfred		 *
910184610Salfred		 * z = ((a / USB_PAGE_SIZE) + 2) + ((b / USB_PAGE_SIZE) + 2) +
911184610Salfred		 * ((c / USB_PAGE_SIZE) + 2);
912184610Salfred		 *
913184610Salfred		 * Constraining "a", "b" and "c" like this:
914184610Salfred		 *
915184610Salfred		 * (a + b + c) <= parm->bufsize
916184610Salfred		 *
917184610Salfred		 * We know that:
918184610Salfred		 *
919184610Salfred		 * z <= ((parm->bufsize / USB_PAGE_SIZE) + (3*2));
920184610Salfred		 *
921184610Salfred		 * Here is the general formula:
922184610Salfred		 */
923184610Salfred		xfer->dma_page_ptr = parm->dma_page_ptr;
924184610Salfred		parm->dma_page_ptr += (2 * n_frbuffers);
925184610Salfred		parm->dma_page_ptr += (parm->bufsize / USB_PAGE_SIZE);
926184610Salfred	}
927190180Sthompsa#endif
928184610Salfred	if (zmps) {
929184610Salfred		/* correct maximum data length */
930184610Salfred		xfer->max_data_length = 0;
931184610Salfred	}
932184610Salfred	/* subtract USB frame remainder from "hc_max_frame_size" */
933184610Salfred
934190181Sthompsa	xfer->max_hc_frame_size =
935184610Salfred	    (parm->hc_max_frame_size -
936184610Salfred	    (parm->hc_max_frame_size % xfer->max_frame_size));
937184610Salfred
938190181Sthompsa	if (xfer->max_hc_frame_size == 0) {
939184610Salfred		parm->err = USB_ERR_INVAL;
940184610Salfred		goto done;
941184610Salfred	}
942184610Salfred
943184610Salfred	/* initialize frame buffers */
944184610Salfred
945184610Salfred	if (parm->buf) {
946184610Salfred		for (x = 0; x != n_frbuffers; x++) {
947184610Salfred			xfer->frbuffers[x].tag_parent =
948187173Sthompsa			    &xfer->xroot->dma_parent_tag;
949190180Sthompsa#if USB_HAVE_BUSDMA
950184610Salfred			if (xfer->flags_int.bdma_enable &&
951184610Salfred			    (parm->bufsize_max > 0)) {
952184610Salfred
953194228Sthompsa				if (usb_pc_dmamap_create(
954184610Salfred				    xfer->frbuffers + x,
955184610Salfred				    parm->bufsize_max)) {
956184610Salfred					parm->err = USB_ERR_NOMEM;
957184610Salfred					goto done;
958184610Salfred				}
959184610Salfred			}
960190180Sthompsa#endif
961184610Salfred		}
962184610Salfred	}
963184610Salfreddone:
964184610Salfred	if (parm->err) {
965184610Salfred		/*
966184610Salfred		 * Set some dummy values so that we avoid division by zero:
967184610Salfred		 */
968190181Sthompsa		xfer->max_hc_frame_size = 1;
969184610Salfred		xfer->max_frame_size = 1;
970184610Salfred		xfer->max_packet_size = 1;
971184610Salfred		xfer->max_data_length = 0;
972184610Salfred		xfer->nframes = 0;
973184610Salfred		xfer->max_frame_count = 0;
974184610Salfred	}
975184610Salfred}
976184610Salfred
977287274Shselaskystatic uint8_t
978287274Shselaskyusbd_transfer_setup_has_bulk(const struct usb_config *setup_start,
979287274Shselasky    uint16_t n_setup)
980287274Shselasky{
981287274Shselasky	while (n_setup--) {
982287274Shselasky		uint8_t type = setup_start[n_setup].type;
983287274Shselasky		if (type == UE_BULK || type == UE_BULK_INTR ||
984287274Shselasky		    type == UE_TYPE_ANY)
985287274Shselasky			return (1);
986287274Shselasky	}
987287274Shselasky	return (0);
988287274Shselasky}
989287274Shselasky
990184610Salfred/*------------------------------------------------------------------------*
991194228Sthompsa *	usbd_transfer_setup - setup an array of USB transfers
992184610Salfred *
993194228Sthompsa * NOTE: You must always call "usbd_transfer_unsetup" after calling
994194228Sthompsa * "usbd_transfer_setup" if success was returned.
995184610Salfred *
996184610Salfred * The idea is that the USB device driver should pre-allocate all its
997184610Salfred * transfers by one call to this function.
998184610Salfred *
999184610Salfred * Return values:
1000184610Salfred *    0: Success
1001184610Salfred * Else: Failure
1002184610Salfred *------------------------------------------------------------------------*/
1003193045Sthompsausb_error_t
1004194228Sthompsausbd_transfer_setup(struct usb_device *udev,
1005192984Sthompsa    const uint8_t *ifaces, struct usb_xfer **ppxfer,
1006192984Sthompsa    const struct usb_config *setup_start, uint16_t n_setup,
1007187173Sthompsa    void *priv_sc, struct mtx *xfer_mtx)
1008184610Salfred{
1009192984Sthompsa	const struct usb_config *setup_end = setup_start + n_setup;
1010192984Sthompsa	const struct usb_config *setup;
1011246616Shselasky	struct usb_setup_params *parm;
1012193644Sthompsa	struct usb_endpoint *ep;
1013192984Sthompsa	struct usb_xfer_root *info;
1014192984Sthompsa	struct usb_xfer *xfer;
1015184610Salfred	void *buf = NULL;
1016246616Shselasky	usb_error_t error = 0;
1017184610Salfred	uint16_t n;
1018184610Salfred	uint16_t refcount;
1019246616Shselasky	uint8_t do_unlock;
1020184610Salfred
1021184610Salfred	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
1022194228Sthompsa	    "usbd_transfer_setup can sleep!");
1023184610Salfred
1024184610Salfred	/* do some checking first */
1025184610Salfred
1026184610Salfred	if (n_setup == 0) {
1027184610Salfred		DPRINTFN(6, "setup array has zero length!\n");
1028184610Salfred		return (USB_ERR_INVAL);
1029184610Salfred	}
1030184610Salfred	if (ifaces == 0) {
1031184610Salfred		DPRINTFN(6, "ifaces array is NULL!\n");
1032184610Salfred		return (USB_ERR_INVAL);
1033184610Salfred	}
1034187173Sthompsa	if (xfer_mtx == NULL) {
1035184610Salfred		DPRINTFN(6, "using global lock\n");
1036187173Sthompsa		xfer_mtx = &Giant;
1037184610Salfred	}
1038246616Shselasky
1039246616Shselasky	/* more sanity checks */
1040246616Shselasky
1041184610Salfred	for (setup = setup_start, n = 0;
1042184610Salfred	    setup != setup_end; setup++, n++) {
1043193045Sthompsa		if (setup->bufsize == (usb_frlength_t)-1) {
1044246616Shselasky			error = USB_ERR_BAD_BUFSIZE;
1045184610Salfred			DPRINTF("invalid bufsize\n");
1046184610Salfred		}
1047190734Sthompsa		if (setup->callback == NULL) {
1048246616Shselasky			error = USB_ERR_NO_CALLBACK;
1049184610Salfred			DPRINTF("no callback\n");
1050184610Salfred		}
1051184610Salfred		ppxfer[n] = NULL;
1052184610Salfred	}
1053184610Salfred
1054246616Shselasky	if (error)
1055246616Shselasky		return (error);
1056184610Salfred
1057246616Shselasky	/* Protect scratch area */
1058305734Shselasky	do_unlock = usbd_ctrl_lock(udev);
1059184610Salfred
1060246616Shselasky	refcount = 0;
1061246616Shselasky	info = NULL;
1062246616Shselasky
1063246616Shselasky	parm = &udev->scratch.xfer_setup[0].parm;
1064246616Shselasky	memset(parm, 0, sizeof(*parm));
1065246616Shselasky
1066246616Shselasky	parm->udev = udev;
1067246616Shselasky	parm->speed = usbd_get_speed(udev);
1068246616Shselasky	parm->hc_max_packet_count = 1;
1069246616Shselasky
1070246616Shselasky	if (parm->speed >= USB_SPEED_MAX) {
1071246616Shselasky		parm->err = USB_ERR_INVAL;
1072184610Salfred		goto done;
1073184610Salfred	}
1074184610Salfred	/* setup all transfers */
1075184610Salfred
1076184610Salfred	while (1) {
1077184610Salfred
1078184610Salfred		if (buf) {
1079184610Salfred			/*
1080192984Sthompsa			 * Initialize the "usb_xfer_root" structure,
1081184610Salfred			 * which is common for all our USB transfers.
1082184610Salfred			 */
1083184610Salfred			info = USB_ADD_BYTES(buf, 0);
1084184610Salfred
1085184610Salfred			info->memory_base = buf;
1086246616Shselasky			info->memory_size = parm->size[0];
1087184610Salfred
1088190180Sthompsa#if USB_HAVE_BUSDMA
1089246616Shselasky			info->dma_page_cache_start = USB_ADD_BYTES(buf, parm->size[4]);
1090246616Shselasky			info->dma_page_cache_end = USB_ADD_BYTES(buf, parm->size[5]);
1091190180Sthompsa#endif
1092246616Shselasky			info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm->size[5]);
1093246616Shselasky			info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm->size[2]);
1094184610Salfred
1095194227Sthompsa			cv_init(&info->cv_drain, "WDRAIN");
1096184610Salfred
1097187173Sthompsa			info->xfer_mtx = xfer_mtx;
1098190180Sthompsa#if USB_HAVE_BUSDMA
1099194228Sthompsa			usb_dma_tag_setup(&info->dma_parent_tag,
1100246616Shselasky			    parm->dma_tag_p, udev->bus->dma_parent_tag[0].tag,
1101278278Shselasky			    xfer_mtx, &usb_bdma_done_event, udev->bus->dma_bits,
1102278278Shselasky			    parm->dma_tag_max);
1103190180Sthompsa#endif
1104184610Salfred
1105184610Salfred			info->bus = udev->bus;
1106187173Sthompsa			info->udev = udev;
1107184610Salfred
1108184610Salfred			TAILQ_INIT(&info->done_q.head);
1109194228Sthompsa			info->done_q.command = &usbd_callback_wrapper;
1110190180Sthompsa#if USB_HAVE_BUSDMA
1111184610Salfred			TAILQ_INIT(&info->dma_q.head);
1112194228Sthompsa			info->dma_q.command = &usb_bdma_work_loop;
1113190180Sthompsa#endif
1114194228Sthompsa			info->done_m[0].hdr.pm_callback = &usb_callback_proc;
1115187173Sthompsa			info->done_m[0].xroot = info;
1116194228Sthompsa			info->done_m[1].hdr.pm_callback = &usb_callback_proc;
1117187173Sthompsa			info->done_m[1].xroot = info;
1118184610Salfred
1119191400Sthompsa			/*
1120191400Sthompsa			 * In device side mode control endpoint
1121191400Sthompsa			 * requests need to run from a separate
1122191400Sthompsa			 * context, else there is a chance of
1123191400Sthompsa			 * deadlock!
1124191400Sthompsa			 */
1125353179Shselasky			if (setup_start == usb_control_ep_cfg ||
1126353179Shselasky			    setup_start == usb_control_ep_quirk_cfg)
1127246363Shselasky				info->done_p =
1128246363Shselasky				    USB_BUS_CONTROL_XFER_PROC(udev->bus);
1129191400Sthompsa			else if (xfer_mtx == &Giant)
1130246363Shselasky				info->done_p =
1131246363Shselasky				    USB_BUS_GIANT_PROC(udev->bus);
1132287274Shselasky			else if (usbd_transfer_setup_has_bulk(setup_start, n_setup))
1133287274Shselasky				info->done_p =
1134287274Shselasky				    USB_BUS_NON_GIANT_BULK_PROC(udev->bus);
1135187174Sthompsa			else
1136246363Shselasky				info->done_p =
1137287274Shselasky				    USB_BUS_NON_GIANT_ISOC_PROC(udev->bus);
1138184610Salfred		}
1139184610Salfred		/* reset sizes */
1140184610Salfred
1141246616Shselasky		parm->size[0] = 0;
1142246616Shselasky		parm->buf = buf;
1143246616Shselasky		parm->size[0] += sizeof(info[0]);
1144184610Salfred
1145184610Salfred		for (setup = setup_start, n = 0;
1146184610Salfred		    setup != setup_end; setup++, n++) {
1147184610Salfred
1148184610Salfred			/* skip USB transfers without callbacks: */
1149190734Sthompsa			if (setup->callback == NULL) {
1150184610Salfred				continue;
1151184610Salfred			}
1152184610Salfred			/* see if there is a matching endpoint */
1153194228Sthompsa			ep = usbd_get_endpoint(udev,
1154184610Salfred			    ifaces[setup->if_index], setup);
1155184610Salfred
1156239214Shselasky			/*
1157239214Shselasky			 * Check that the USB PIPE is valid and that
1158239214Shselasky			 * the endpoint mode is proper.
1159239214Shselasky			 *
1160239214Shselasky			 * Make sure we don't allocate a streams
1161239214Shselasky			 * transfer when such a combination is not
1162239214Shselasky			 * valid.
1163239214Shselasky			 */
1164239214Shselasky			if ((ep == NULL) || (ep->methods == NULL) ||
1165239214Shselasky			    ((ep->ep_mode != USB_EP_MODE_STREAMS) &&
1166239214Shselasky			    (ep->ep_mode != USB_EP_MODE_DEFAULT)) ||
1167239214Shselasky			    (setup->stream_id != 0 &&
1168239214Shselasky			    (setup->stream_id >= USB_MAX_EP_STREAMS ||
1169239214Shselasky			    (ep->ep_mode != USB_EP_MODE_STREAMS)))) {
1170190734Sthompsa				if (setup->flags.no_pipe_ok)
1171184610Salfred					continue;
1172192499Sthompsa				if ((setup->usb_mode != USB_MODE_DUAL) &&
1173192499Sthompsa				    (setup->usb_mode != udev->flags.usb_mode))
1174190734Sthompsa					continue;
1175246616Shselasky				parm->err = USB_ERR_NO_PIPE;
1176184610Salfred				goto done;
1177184610Salfred			}
1178184610Salfred
1179184610Salfred			/* align data properly */
1180246616Shselasky			parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
1181184610Salfred
1182190734Sthompsa			/* store current setup pointer */
1183246616Shselasky			parm->curr_setup = setup;
1184190734Sthompsa
1185184610Salfred			if (buf) {
1186184610Salfred				/*
1187184610Salfred				 * Common initialization of the
1188192984Sthompsa				 * "usb_xfer" structure.
1189184610Salfred				 */
1190246616Shselasky				xfer = USB_ADD_BYTES(buf, parm->size[0]);
1191184610Salfred				xfer->address = udev->address;
1192184610Salfred				xfer->priv_sc = priv_sc;
1193187173Sthompsa				xfer->xroot = info;
1194184610Salfred
1195194228Sthompsa				usb_callout_init_mtx(&xfer->timeout_handle,
1196186454Sthompsa				    &udev->bus->bus_mtx, 0);
1197184610Salfred			} else {
1198184610Salfred				/*
1199184610Salfred				 * Setup a dummy xfer, hence we are
1200192984Sthompsa				 * writing to the "usb_xfer"
1201184610Salfred				 * structure pointed to by "xfer"
1202184610Salfred				 * before we have allocated any
1203184610Salfred				 * memory:
1204184610Salfred				 */
1205246616Shselasky				xfer = &udev->scratch.xfer_setup[0].dummy;
1206246616Shselasky				memset(xfer, 0, sizeof(*xfer));
1207184610Salfred				refcount++;
1208184610Salfred			}
1209184610Salfred
1210193644Sthompsa			/* set transfer endpoint pointer */
1211193644Sthompsa			xfer->endpoint = ep;
1212188982Sthompsa
1213239214Shselasky			/* set transfer stream ID */
1214239214Shselasky			xfer->stream_id = setup->stream_id;
1215239214Shselasky
1216246616Shselasky			parm->size[0] += sizeof(xfer[0]);
1217246616Shselasky			parm->methods = xfer->endpoint->methods;
1218246616Shselasky			parm->curr_xfer = xfer;
1219184610Salfred
1220188982Sthompsa			/*
1221188982Sthompsa			 * Call the Host or Device controller transfer
1222188982Sthompsa			 * setup routine:
1223188982Sthompsa			 */
1224246616Shselasky			(udev->bus->methods->xfer_setup) (parm);
1225184610Salfred
1226188982Sthompsa			/* check for error */
1227246616Shselasky			if (parm->err)
1228188982Sthompsa				goto done;
1229188982Sthompsa
1230184610Salfred			if (buf) {
1231184610Salfred				/*
1232193644Sthompsa				 * Increment the endpoint refcount. This
1233184610Salfred				 * basically prevents setting a new
1234184610Salfred				 * configuration and alternate setting
1235184610Salfred				 * when USB transfers are in use on
1236184610Salfred				 * the given interface. Search the USB
1237199672Sthompsa				 * code for "endpoint->refcount_alloc" if you
1238184610Salfred				 * want more information.
1239184610Salfred				 */
1240199672Sthompsa				USB_BUS_LOCK(info->bus);
1241199672Sthompsa				if (xfer->endpoint->refcount_alloc >= USB_EP_REF_MAX)
1242246616Shselasky					parm->err = USB_ERR_INVAL;
1243184610Salfred
1244199672Sthompsa				xfer->endpoint->refcount_alloc++;
1245199672Sthompsa
1246199672Sthompsa				if (xfer->endpoint->refcount_alloc == 0)
1247199672Sthompsa					panic("usbd_transfer_setup(): Refcount wrapped to zero\n");
1248199672Sthompsa				USB_BUS_UNLOCK(info->bus);
1249199672Sthompsa
1250188982Sthompsa				/*
1251188982Sthompsa				 * Whenever we set ppxfer[] then we
1252188982Sthompsa				 * also need to increment the
1253188982Sthompsa				 * "setup_refcount":
1254188982Sthompsa				 */
1255188982Sthompsa				info->setup_refcount++;
1256184610Salfred
1257188982Sthompsa				/*
1258188982Sthompsa				 * Transfer is successfully setup and
1259188982Sthompsa				 * can be used:
1260188982Sthompsa				 */
1261188982Sthompsa				ppxfer[n] = xfer;
1262184610Salfred			}
1263199672Sthompsa
1264199672Sthompsa			/* check for error */
1265246616Shselasky			if (parm->err)
1266199672Sthompsa				goto done;
1267184610Salfred		}
1268184610Salfred
1269246616Shselasky		if (buf != NULL || parm->err != 0)
1270184610Salfred			goto done;
1271246616Shselasky
1272246616Shselasky		/* if no transfers, nothing to do */
1273246616Shselasky		if (refcount == 0)
1274184610Salfred			goto done;
1275246616Shselasky
1276184610Salfred		/* align data properly */
1277246616Shselasky		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
1278184610Salfred
1279184610Salfred		/* store offset temporarily */
1280246616Shselasky		parm->size[1] = parm->size[0];
1281184610Salfred
1282184610Salfred		/*
1283184610Salfred		 * The number of DMA tags required depends on
1284184610Salfred		 * the number of endpoints. The current estimate
1285184610Salfred		 * for maximum number of DMA tags per endpoint
1286244500Shselasky		 * is three:
1287244500Shselasky		 * 1) for loading memory
1288244500Shselasky		 * 2) for allocating memory
1289244500Shselasky		 * 3) for fixing memory [UHCI]
1290184610Salfred		 */
1291246616Shselasky		parm->dma_tag_max += 3 * MIN(n_setup, USB_EP_MAX);
1292184610Salfred
1293184610Salfred		/*
1294184610Salfred		 * DMA tags for QH, TD, Data and more.
1295184610Salfred		 */
1296246616Shselasky		parm->dma_tag_max += 8;
1297184610Salfred
1298246616Shselasky		parm->dma_tag_p += parm->dma_tag_max;
1299184610Salfred
1300246616Shselasky		parm->size[0] += ((uint8_t *)parm->dma_tag_p) -
1301184610Salfred		    ((uint8_t *)0);
1302184610Salfred
1303184610Salfred		/* align data properly */
1304246616Shselasky		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
1305184610Salfred
1306184610Salfred		/* store offset temporarily */
1307246616Shselasky		parm->size[3] = parm->size[0];
1308184610Salfred
1309246616Shselasky		parm->size[0] += ((uint8_t *)parm->dma_page_ptr) -
1310184610Salfred		    ((uint8_t *)0);
1311184610Salfred
1312184610Salfred		/* align data properly */
1313246616Shselasky		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
1314184610Salfred
1315184610Salfred		/* store offset temporarily */
1316246616Shselasky		parm->size[4] = parm->size[0];
1317184610Salfred
1318246616Shselasky		parm->size[0] += ((uint8_t *)parm->dma_page_cache_ptr) -
1319184610Salfred		    ((uint8_t *)0);
1320184610Salfred
1321184610Salfred		/* store end offset temporarily */
1322246616Shselasky		parm->size[5] = parm->size[0];
1323184610Salfred
1324246616Shselasky		parm->size[0] += ((uint8_t *)parm->xfer_page_cache_ptr) -
1325184610Salfred		    ((uint8_t *)0);
1326184610Salfred
1327184610Salfred		/* store end offset temporarily */
1328184610Salfred
1329246616Shselasky		parm->size[2] = parm->size[0];
1330184610Salfred
1331184610Salfred		/* align data properly */
1332246616Shselasky		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
1333184610Salfred
1334246616Shselasky		parm->size[6] = parm->size[0];
1335184610Salfred
1336246616Shselasky		parm->size[0] += ((uint8_t *)parm->xfer_length_ptr) -
1337184610Salfred		    ((uint8_t *)0);
1338184610Salfred
1339184610Salfred		/* align data properly */
1340246616Shselasky		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
1341184610Salfred
1342184610Salfred		/* allocate zeroed memory */
1343246616Shselasky		buf = malloc(parm->size[0], M_USB, M_WAITOK | M_ZERO);
1344184610Salfred
1345184610Salfred		if (buf == NULL) {
1346246616Shselasky			parm->err = USB_ERR_NOMEM;
1347184610Salfred			DPRINTFN(0, "cannot allocate memory block for "
1348184610Salfred			    "configuration (%d bytes)\n",
1349246616Shselasky			    parm->size[0]);
1350184610Salfred			goto done;
1351184610Salfred		}
1352246616Shselasky		parm->dma_tag_p = USB_ADD_BYTES(buf, parm->size[1]);
1353246616Shselasky		parm->dma_page_ptr = USB_ADD_BYTES(buf, parm->size[3]);
1354246616Shselasky		parm->dma_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[4]);
1355246616Shselasky		parm->xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[5]);
1356246616Shselasky		parm->xfer_length_ptr = USB_ADD_BYTES(buf, parm->size[6]);
1357184610Salfred	}
1358184610Salfred
1359184610Salfreddone:
1360184610Salfred	if (buf) {
1361184610Salfred		if (info->setup_refcount == 0) {
1362184610Salfred			/*
1363194228Sthompsa			 * "usbd_transfer_unsetup_sub" will unlock
1364184824Sthompsa			 * the bus mutex before returning !
1365184610Salfred			 */
1366184824Sthompsa			USB_BUS_LOCK(info->bus);
1367184610Salfred
1368184610Salfred			/* something went wrong */
1369194228Sthompsa			usbd_transfer_unsetup_sub(info, 0);
1370184610Salfred		}
1371184610Salfred	}
1372246616Shselasky
1373246616Shselasky	/* check if any errors happened */
1374246616Shselasky	if (parm->err)
1375194228Sthompsa		usbd_transfer_unsetup(ppxfer, n_setup);
1376246616Shselasky
1377246616Shselasky	error = parm->err;
1378246616Shselasky
1379246616Shselasky	if (do_unlock)
1380305734Shselasky		usbd_ctrl_unlock(udev);
1381246616Shselasky
1382246616Shselasky	return (error);
1383184610Salfred}
1384184610Salfred
1385184610Salfred/*------------------------------------------------------------------------*
1386194228Sthompsa *	usbd_transfer_unsetup_sub - factored out code
1387184610Salfred *------------------------------------------------------------------------*/
1388184610Salfredstatic void
1389194228Sthompsausbd_transfer_unsetup_sub(struct usb_xfer_root *info, uint8_t needs_delay)
1390184610Salfred{
1391218475Shselasky#if USB_HAVE_BUSDMA
1392192984Sthompsa	struct usb_page_cache *pc;
1393218475Shselasky#endif
1394184610Salfred
1395184824Sthompsa	USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
1396184610Salfred
1397184610Salfred	/* wait for any outstanding DMA operations */
1398184610Salfred
1399184610Salfred	if (needs_delay) {
1400193045Sthompsa		usb_timeout_t temp;
1401212134Sthompsa		temp = usbd_get_dma_delay(info->udev);
1402212134Sthompsa		if (temp != 0) {
1403212134Sthompsa			usb_pause_mtx(&info->bus->bus_mtx,
1404212134Sthompsa			    USB_MS_TO_TICKS(temp));
1405212134Sthompsa		}
1406184610Salfred	}
1407187174Sthompsa
1408187174Sthompsa	/* make sure that our done messages are not queued anywhere */
1409194228Sthompsa	usb_proc_mwait(info->done_p, &info->done_m[0], &info->done_m[1]);
1410187174Sthompsa
1411184824Sthompsa	USB_BUS_UNLOCK(info->bus);
1412184610Salfred
1413190180Sthompsa#if USB_HAVE_BUSDMA
1414184610Salfred	/* free DMA'able memory, if any */
1415184610Salfred	pc = info->dma_page_cache_start;
1416184610Salfred	while (pc != info->dma_page_cache_end) {
1417194228Sthompsa		usb_pc_free_mem(pc);
1418184610Salfred		pc++;
1419184610Salfred	}
1420184610Salfred
1421184610Salfred	/* free DMA maps in all "xfer->frbuffers" */
1422184610Salfred	pc = info->xfer_page_cache_start;
1423184610Salfred	while (pc != info->xfer_page_cache_end) {
1424194228Sthompsa		usb_pc_dmamap_destroy(pc);
1425184610Salfred		pc++;
1426184610Salfred	}
1427184610Salfred
1428184610Salfred	/* free all DMA tags */
1429194228Sthompsa	usb_dma_tag_unsetup(&info->dma_parent_tag);
1430190180Sthompsa#endif
1431184610Salfred
1432194227Sthompsa	cv_destroy(&info->cv_drain);
1433184610Salfred
1434184610Salfred	/*
1435184610Salfred	 * free the "memory_base" last, hence the "info" structure is
1436184610Salfred	 * contained within the "memory_base"!
1437184610Salfred	 */
1438184610Salfred	free(info->memory_base, M_USB);
1439184610Salfred}
1440184610Salfred
1441184610Salfred/*------------------------------------------------------------------------*
1442194228Sthompsa *	usbd_transfer_unsetup - unsetup/free an array of USB transfers
1443184610Salfred *
1444184610Salfred * NOTE: All USB transfers in progress will get called back passing
1445184610Salfred * the error code "USB_ERR_CANCELLED" before this function
1446184610Salfred * returns.
1447184610Salfred *------------------------------------------------------------------------*/
1448184610Salfredvoid
1449194228Sthompsausbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
1450184610Salfred{
1451192984Sthompsa	struct usb_xfer *xfer;
1452192984Sthompsa	struct usb_xfer_root *info;
1453184610Salfred	uint8_t needs_delay = 0;
1454184610Salfred
1455184610Salfred	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
1456194228Sthompsa	    "usbd_transfer_unsetup can sleep!");
1457184610Salfred
1458184610Salfred	while (n_setup--) {
1459184610Salfred		xfer = pxfer[n_setup];
1460184610Salfred
1461188982Sthompsa		if (xfer == NULL)
1462188982Sthompsa			continue;
1463184610Salfred
1464188982Sthompsa		info = xfer->xroot;
1465184610Salfred
1466188982Sthompsa		USB_XFER_LOCK(xfer);
1467188982Sthompsa		USB_BUS_LOCK(info->bus);
1468184610Salfred
1469188982Sthompsa		/*
1470188982Sthompsa		 * HINT: when you start/stop a transfer, it might be a
1471188982Sthompsa		 * good idea to directly use the "pxfer[]" structure:
1472188982Sthompsa		 *
1473194228Sthompsa		 * usbd_transfer_start(sc->pxfer[0]);
1474194228Sthompsa		 * usbd_transfer_stop(sc->pxfer[0]);
1475188982Sthompsa		 *
1476188982Sthompsa		 * That way, if your code has many parts that will not
1477188982Sthompsa		 * stop running under the same lock, in other words
1478194228Sthompsa		 * "xfer_mtx", the usbd_transfer_start and
1479194228Sthompsa		 * usbd_transfer_stop functions will simply return
1480188982Sthompsa		 * when they detect a NULL pointer argument.
1481188982Sthompsa		 *
1482188982Sthompsa		 * To avoid any races we clear the "pxfer[]" pointer
1483188982Sthompsa		 * while holding the private mutex of the driver:
1484188982Sthompsa		 */
1485188982Sthompsa		pxfer[n_setup] = NULL;
1486184610Salfred
1487188982Sthompsa		USB_BUS_UNLOCK(info->bus);
1488188982Sthompsa		USB_XFER_UNLOCK(xfer);
1489184610Salfred
1490194228Sthompsa		usbd_transfer_drain(xfer);
1491184610Salfred
1492190180Sthompsa#if USB_HAVE_BUSDMA
1493188982Sthompsa		if (xfer->flags_int.bdma_enable)
1494188982Sthompsa			needs_delay = 1;
1495190180Sthompsa#endif
1496188982Sthompsa		/*
1497193644Sthompsa		 * NOTE: default endpoint does not have an
1498193644Sthompsa		 * interface, even if endpoint->iface_index == 0
1499188982Sthompsa		 */
1500199672Sthompsa		USB_BUS_LOCK(info->bus);
1501199672Sthompsa		xfer->endpoint->refcount_alloc--;
1502199672Sthompsa		USB_BUS_UNLOCK(info->bus);
1503184610Salfred
1504194228Sthompsa		usb_callout_drain(&xfer->timeout_handle);
1505184610Salfred
1506188982Sthompsa		USB_BUS_LOCK(info->bus);
1507184610Salfred
1508188982Sthompsa		USB_ASSERT(info->setup_refcount != 0, ("Invalid setup "
1509199816Sthompsa		    "reference count\n"));
1510184610Salfred
1511188982Sthompsa		info->setup_refcount--;
1512188982Sthompsa
1513188982Sthompsa		if (info->setup_refcount == 0) {
1514194228Sthompsa			usbd_transfer_unsetup_sub(info,
1515188982Sthompsa			    needs_delay);
1516188982Sthompsa		} else {
1517188982Sthompsa			USB_BUS_UNLOCK(info->bus);
1518184610Salfred		}
1519184610Salfred	}
1520184610Salfred}
1521184610Salfred
1522184610Salfred/*------------------------------------------------------------------------*
1523194228Sthompsa *	usbd_control_transfer_init - factored out code
1524184610Salfred *
1525184610Salfred * In USB Device Mode we have to wait for the SETUP packet which
1526192984Sthompsa * containst the "struct usb_device_request" structure, before we can
1527184610Salfred * transfer any data. In USB Host Mode we already have the SETUP
1528184610Salfred * packet at the moment the USB transfer is started. This leads us to
1529184610Salfred * having to setup the USB transfer at two different places in
1530184610Salfred * time. This function just contains factored out control transfer
1531184610Salfred * initialisation code, so that we don't duplicate the code.
1532184610Salfred *------------------------------------------------------------------------*/
1533184610Salfredstatic void
1534194228Sthompsausbd_control_transfer_init(struct usb_xfer *xfer)
1535184610Salfred{
1536192984Sthompsa	struct usb_device_request req;
1537184610Salfred
1538184610Salfred	/* copy out the USB request header */
1539184610Salfred
1540194228Sthompsa	usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
1541184610Salfred
1542184610Salfred	/* setup remainder */
1543184610Salfred
1544184610Salfred	xfer->flags_int.control_rem = UGETW(req.wLength);
1545184610Salfred
1546184610Salfred	/* copy direction to endpoint variable */
1547184610Salfred
1548193644Sthompsa	xfer->endpointno &= ~(UE_DIR_IN | UE_DIR_OUT);
1549193644Sthompsa	xfer->endpointno |=
1550184610Salfred	    (req.bmRequestType & UT_READ) ? UE_DIR_IN : UE_DIR_OUT;
1551184610Salfred}
1552184610Salfred
1553184610Salfred/*------------------------------------------------------------------------*
1554278507Shselasky *	usbd_control_transfer_did_data
1555278507Shselasky *
1556278507Shselasky * This function returns non-zero if a control endpoint has
1557278507Shselasky * transferred the first DATA packet after the SETUP packet.
1558278507Shselasky * Else it returns zero.
1559278507Shselasky *------------------------------------------------------------------------*/
1560278507Shselaskystatic uint8_t
1561278507Shselaskyusbd_control_transfer_did_data(struct usb_xfer *xfer)
1562278507Shselasky{
1563278507Shselasky	struct usb_device_request req;
1564278507Shselasky
1565278507Shselasky	/* SETUP packet is not yet sent */
1566278507Shselasky	if (xfer->flags_int.control_hdr != 0)
1567278507Shselasky		return (0);
1568278507Shselasky
1569278507Shselasky	/* copy out the USB request header */
1570278507Shselasky	usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
1571278507Shselasky
1572278507Shselasky	/* compare remainder to the initial value */
1573278507Shselasky	return (xfer->flags_int.control_rem != UGETW(req.wLength));
1574278507Shselasky}
1575278507Shselasky
1576278507Shselasky/*------------------------------------------------------------------------*
1577194677Sthompsa *	usbd_setup_ctrl_transfer
1578184610Salfred *
1579184610Salfred * This function handles initialisation of control transfers. Control
1580184610Salfred * transfers are special in that regard that they can both transmit
1581184610Salfred * and receive data.
1582184610Salfred *
1583184610Salfred * Return values:
1584184610Salfred *    0: Success
1585184610Salfred * Else: Failure
1586184610Salfred *------------------------------------------------------------------------*/
1587194677Sthompsastatic int
1588194677Sthompsausbd_setup_ctrl_transfer(struct usb_xfer *xfer)
1589184610Salfred{
1590193045Sthompsa	usb_frlength_t len;
1591184610Salfred
1592184610Salfred	/* Check for control endpoint stall */
1593192552Sthompsa	if (xfer->flags.stall_pipe && xfer->flags_int.control_act) {
1594192552Sthompsa		/* the control transfer is no longer active */
1595192552Sthompsa		xfer->flags_int.control_stall = 1;
1596184610Salfred		xfer->flags_int.control_act = 0;
1597192552Sthompsa	} else {
1598192552Sthompsa		/* don't stall control transfer by default */
1599192552Sthompsa		xfer->flags_int.control_stall = 0;
1600184610Salfred	}
1601190184Sthompsa
1602190184Sthompsa	/* Check for invalid number of frames */
1603190184Sthompsa	if (xfer->nframes > 2) {
1604190184Sthompsa		/*
1605190184Sthompsa		 * If you need to split a control transfer, you
1606190184Sthompsa		 * have to do one part at a time. Only with
1607190184Sthompsa		 * non-control transfers you can do multiple
1608190184Sthompsa		 * parts a time.
1609190184Sthompsa		 */
1610190184Sthompsa		DPRINTFN(0, "Too many frames: %u\n",
1611190184Sthompsa		    (unsigned int)xfer->nframes);
1612190184Sthompsa		goto error;
1613190184Sthompsa	}
1614190184Sthompsa
1615184610Salfred	/*
1616184610Salfred         * Check if there is a control
1617184610Salfred         * transfer in progress:
1618184610Salfred         */
1619184610Salfred	if (xfer->flags_int.control_act) {
1620184610Salfred
1621184610Salfred		if (xfer->flags_int.control_hdr) {
1622184610Salfred
1623184610Salfred			/* clear send header flag */
1624184610Salfred
1625184610Salfred			xfer->flags_int.control_hdr = 0;
1626184610Salfred
1627184610Salfred			/* setup control transfer */
1628192499Sthompsa			if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
1629194228Sthompsa				usbd_control_transfer_init(xfer);
1630184610Salfred			}
1631184610Salfred		}
1632184610Salfred		/* get data length */
1633184610Salfred
1634184610Salfred		len = xfer->sumlen;
1635184610Salfred
1636184610Salfred	} else {
1637184610Salfred
1638184610Salfred		/* the size of the SETUP structure is hardcoded ! */
1639184610Salfred
1640192984Sthompsa		if (xfer->frlengths[0] != sizeof(struct usb_device_request)) {
1641184610Salfred			DPRINTFN(0, "Wrong framelength %u != %zu\n",
1642184610Salfred			    xfer->frlengths[0], sizeof(struct
1643192984Sthompsa			    usb_device_request));
1644184610Salfred			goto error;
1645184610Salfred		}
1646184610Salfred		/* check USB mode */
1647192499Sthompsa		if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
1648184610Salfred
1649184610Salfred			/* check number of frames */
1650184610Salfred			if (xfer->nframes != 1) {
1651184610Salfred				/*
1652184610Salfred			         * We need to receive the setup
1653184610Salfred			         * message first so that we know the
1654184610Salfred			         * data direction!
1655184610Salfred			         */
1656184610Salfred				DPRINTF("Misconfigured transfer\n");
1657184610Salfred				goto error;
1658184610Salfred			}
1659184610Salfred			/*
1660184610Salfred			 * Set a dummy "control_rem" value.  This
1661184610Salfred			 * variable will be overwritten later by a
1662194228Sthompsa			 * call to "usbd_control_transfer_init()" !
1663184610Salfred			 */
1664184610Salfred			xfer->flags_int.control_rem = 0xFFFF;
1665184610Salfred		} else {
1666184610Salfred
1667184610Salfred			/* setup "endpoint" and "control_rem" */
1668184610Salfred
1669194228Sthompsa			usbd_control_transfer_init(xfer);
1670184610Salfred		}
1671184610Salfred
1672184610Salfred		/* set transfer-header flag */
1673184610Salfred
1674184610Salfred		xfer->flags_int.control_hdr = 1;
1675184610Salfred
1676184610Salfred		/* get data length */
1677184610Salfred
1678192984Sthompsa		len = (xfer->sumlen - sizeof(struct usb_device_request));
1679184610Salfred	}
1680184610Salfred
1681278507Shselasky	/* update did data flag */
1682278507Shselasky
1683278507Shselasky	xfer->flags_int.control_did_data =
1684278507Shselasky	    usbd_control_transfer_did_data(xfer);
1685278507Shselasky
1686184610Salfred	/* check if there is a length mismatch */
1687184610Salfred
1688184610Salfred	if (len > xfer->flags_int.control_rem) {
1689197562Sthompsa		DPRINTFN(0, "Length (%d) greater than "
1690199816Sthompsa		    "remaining length (%d)\n", len,
1691197562Sthompsa		    xfer->flags_int.control_rem);
1692184610Salfred		goto error;
1693184610Salfred	}
1694184610Salfred	/* check if we are doing a short transfer */
1695184610Salfred
1696184610Salfred	if (xfer->flags.force_short_xfer) {
1697184610Salfred		xfer->flags_int.control_rem = 0;
1698184610Salfred	} else {
1699184610Salfred		if ((len != xfer->max_data_length) &&
1700184610Salfred		    (len != xfer->flags_int.control_rem) &&
1701184610Salfred		    (xfer->nframes != 1)) {
1702184610Salfred			DPRINTFN(0, "Short control transfer without "
1703199816Sthompsa			    "force_short_xfer set\n");
1704184610Salfred			goto error;
1705184610Salfred		}
1706184610Salfred		xfer->flags_int.control_rem -= len;
1707184610Salfred	}
1708184610Salfred
1709184610Salfred	/* the status part is executed when "control_act" is 0 */
1710184610Salfred
1711184610Salfred	if ((xfer->flags_int.control_rem > 0) ||
1712184610Salfred	    (xfer->flags.manual_status)) {
1713184610Salfred		/* don't execute the STATUS stage yet */
1714184610Salfred		xfer->flags_int.control_act = 1;
1715184610Salfred
1716184610Salfred		/* sanity check */
1717184610Salfred		if ((!xfer->flags_int.control_hdr) &&
1718184610Salfred		    (xfer->nframes == 1)) {
1719184610Salfred			/*
1720184610Salfred		         * This is not a valid operation!
1721184610Salfred		         */
1722184610Salfred			DPRINTFN(0, "Invalid parameter "
1723184610Salfred			    "combination\n");
1724184610Salfred			goto error;
1725184610Salfred		}
1726184610Salfred	} else {
1727184610Salfred		/* time to execute the STATUS stage */
1728184610Salfred		xfer->flags_int.control_act = 0;
1729184610Salfred	}
1730184610Salfred	return (0);			/* success */
1731184610Salfred
1732184610Salfrederror:
1733184610Salfred	return (1);			/* failure */
1734184610Salfred}
1735184610Salfred
1736184610Salfred/*------------------------------------------------------------------------*
1737194228Sthompsa *	usbd_transfer_submit - start USB hardware for the given transfer
1738184610Salfred *
1739184610Salfred * This function should only be called from the USB callback.
1740184610Salfred *------------------------------------------------------------------------*/
1741184610Salfredvoid
1742194228Sthompsausbd_transfer_submit(struct usb_xfer *xfer)
1743184610Salfred{
1744192984Sthompsa	struct usb_xfer_root *info;
1745192984Sthompsa	struct usb_bus *bus;
1746193045Sthompsa	usb_frcount_t x;
1747184610Salfred
1748191494Sthompsa	info = xfer->xroot;
1749191494Sthompsa	bus = info->bus;
1750191494Sthompsa
1751193644Sthompsa	DPRINTF("xfer=%p, endpoint=%p, nframes=%d, dir=%s\n",
1752193644Sthompsa	    xfer, xfer->endpoint, xfer->nframes, USB_GET_DATA_ISREAD(xfer) ?
1753184610Salfred	    "read" : "write");
1754184610Salfred
1755207077Sthompsa#ifdef USB_DEBUG
1756184610Salfred	if (USB_DEBUG_VAR > 0) {
1757191494Sthompsa		USB_BUS_LOCK(bus);
1758184610Salfred
1759194228Sthompsa		usb_dump_endpoint(xfer->endpoint);
1760184610Salfred
1761191494Sthompsa		USB_BUS_UNLOCK(bus);
1762184610Salfred	}
1763184610Salfred#endif
1764184610Salfred
1765184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
1766191494Sthompsa	USB_BUS_LOCK_ASSERT(bus, MA_NOTOWNED);
1767184610Salfred
1768184610Salfred	/* Only open the USB transfer once! */
1769184610Salfred	if (!xfer->flags_int.open) {
1770184610Salfred		xfer->flags_int.open = 1;
1771184610Salfred
1772184610Salfred		DPRINTF("open\n");
1773184610Salfred
1774191494Sthompsa		USB_BUS_LOCK(bus);
1775193644Sthompsa		(xfer->endpoint->methods->open) (xfer);
1776191494Sthompsa		USB_BUS_UNLOCK(bus);
1777184610Salfred	}
1778184610Salfred	/* set "transferring" flag */
1779184610Salfred	xfer->flags_int.transferring = 1;
1780184610Salfred
1781190734Sthompsa#if USB_HAVE_POWERD
1782186730Salfred	/* increment power reference */
1783194228Sthompsa	usbd_transfer_power_ref(xfer, 1);
1784190734Sthompsa#endif
1785184610Salfred	/*
1786184610Salfred	 * Check if the transfer is waiting on a queue, most
1787184610Salfred	 * frequently the "done_q":
1788184610Salfred	 */
1789184610Salfred	if (xfer->wait_queue) {
1790191494Sthompsa		USB_BUS_LOCK(bus);
1791194228Sthompsa		usbd_transfer_dequeue(xfer);
1792191494Sthompsa		USB_BUS_UNLOCK(bus);
1793184610Salfred	}
1794184610Salfred	/* clear "did_dma_delay" flag */
1795184610Salfred	xfer->flags_int.did_dma_delay = 0;
1796184610Salfred
1797184610Salfred	/* clear "did_close" flag */
1798184610Salfred	xfer->flags_int.did_close = 0;
1799184610Salfred
1800190180Sthompsa#if USB_HAVE_BUSDMA
1801184610Salfred	/* clear "bdma_setup" flag */
1802184610Salfred	xfer->flags_int.bdma_setup = 0;
1803190180Sthompsa#endif
1804184610Salfred	/* by default we cannot cancel any USB transfer immediately */
1805184610Salfred	xfer->flags_int.can_cancel_immed = 0;
1806184610Salfred
1807184610Salfred	/* clear lengths and frame counts by default */
1808184610Salfred	xfer->sumlen = 0;
1809184610Salfred	xfer->actlen = 0;
1810184610Salfred	xfer->aframes = 0;
1811184610Salfred
1812184610Salfred	/* clear any previous errors */
1813184610Salfred	xfer->error = 0;
1814184610Salfred
1815191824Sthompsa	/* Check if the device is still alive */
1816191824Sthompsa	if (info->udev->state < USB_STATE_POWERED) {
1817191824Sthompsa		USB_BUS_LOCK(bus);
1818192051Sthompsa		/*
1819192051Sthompsa		 * Must return cancelled error code else
1820192051Sthompsa		 * device drivers can hang.
1821192051Sthompsa		 */
1822194228Sthompsa		usbd_transfer_done(xfer, USB_ERR_CANCELLED);
1823191824Sthompsa		USB_BUS_UNLOCK(bus);
1824191824Sthompsa		return;
1825191824Sthompsa	}
1826191824Sthompsa
1827184610Salfred	/* sanity check */
1828184610Salfred	if (xfer->nframes == 0) {
1829184610Salfred		if (xfer->flags.stall_pipe) {
1830184610Salfred			/*
1831184610Salfred			 * Special case - want to stall without transferring
1832184610Salfred			 * any data:
1833184610Salfred			 */
1834184610Salfred			DPRINTF("xfer=%p nframes=0: stall "
1835184610Salfred			    "or clear stall!\n", xfer);
1836191494Sthompsa			USB_BUS_LOCK(bus);
1837184610Salfred			xfer->flags_int.can_cancel_immed = 1;
1838184610Salfred			/* start the transfer */
1839239214Shselasky			usb_command_wrapper(&xfer->endpoint->
1840239214Shselasky			    endpoint_q[xfer->stream_id], xfer);
1841191494Sthompsa			USB_BUS_UNLOCK(bus);
1842184610Salfred			return;
1843184610Salfred		}
1844191494Sthompsa		USB_BUS_LOCK(bus);
1845194228Sthompsa		usbd_transfer_done(xfer, USB_ERR_INVAL);
1846191494Sthompsa		USB_BUS_UNLOCK(bus);
1847184610Salfred		return;
1848184610Salfred	}
1849220301Shselasky	/* compute some variables */
1850184610Salfred
1851184610Salfred	for (x = 0; x != xfer->nframes; x++) {
1852220301Shselasky		/* make a copy of the frlenghts[] */
1853220301Shselasky		xfer->frlengths[x + xfer->max_frame_count] = xfer->frlengths[x];
1854220301Shselasky		/* compute total transfer length */
1855184610Salfred		xfer->sumlen += xfer->frlengths[x];
1856184610Salfred		if (xfer->sumlen < xfer->frlengths[x]) {
1857184610Salfred			/* length wrapped around */
1858191494Sthompsa			USB_BUS_LOCK(bus);
1859194228Sthompsa			usbd_transfer_done(xfer, USB_ERR_INVAL);
1860191494Sthompsa			USB_BUS_UNLOCK(bus);
1861184610Salfred			return;
1862184610Salfred		}
1863184610Salfred	}
1864184610Salfred
1865184610Salfred	/* clear some internal flags */
1866184610Salfred
1867184610Salfred	xfer->flags_int.short_xfer_ok = 0;
1868184610Salfred	xfer->flags_int.short_frames_ok = 0;
1869184610Salfred
1870184610Salfred	/* check if this is a control transfer */
1871184610Salfred
1872184610Salfred	if (xfer->flags_int.control_xfr) {
1873184610Salfred
1874194677Sthompsa		if (usbd_setup_ctrl_transfer(xfer)) {
1875191494Sthompsa			USB_BUS_LOCK(bus);
1876194228Sthompsa			usbd_transfer_done(xfer, USB_ERR_STALLED);
1877191494Sthompsa			USB_BUS_UNLOCK(bus);
1878184610Salfred			return;
1879184610Salfred		}
1880184610Salfred	}
1881184610Salfred	/*
1882184610Salfred	 * Setup filtered version of some transfer flags,
1883184610Salfred	 * in case of data read direction
1884184610Salfred	 */
1885184610Salfred	if (USB_GET_DATA_ISREAD(xfer)) {
1886184610Salfred
1887190184Sthompsa		if (xfer->flags.short_frames_ok) {
1888190184Sthompsa			xfer->flags_int.short_xfer_ok = 1;
1889190184Sthompsa			xfer->flags_int.short_frames_ok = 1;
1890190184Sthompsa		} else if (xfer->flags.short_xfer_ok) {
1891190184Sthompsa			xfer->flags_int.short_xfer_ok = 1;
1892184610Salfred
1893190184Sthompsa			/* check for control transfer */
1894190184Sthompsa			if (xfer->flags_int.control_xfr) {
1895190184Sthompsa				/*
1896190184Sthompsa				 * 1) Control transfers do not support
1897190184Sthompsa				 * reception of multiple short USB
1898190184Sthompsa				 * frames in host mode and device side
1899190184Sthompsa				 * mode, with exception of:
1900190184Sthompsa				 *
1901190184Sthompsa				 * 2) Due to sometimes buggy device
1902190184Sthompsa				 * side firmware we need to do a
1903190184Sthompsa				 * STATUS stage in case of short
1904190184Sthompsa				 * control transfers in USB host mode.
1905190184Sthompsa				 * The STATUS stage then becomes the
1906190184Sthompsa				 * "alt_next" to the DATA stage.
1907190184Sthompsa				 */
1908184610Salfred				xfer->flags_int.short_frames_ok = 1;
1909184610Salfred			}
1910184610Salfred		}
1911184610Salfred	}
1912184610Salfred	/*
1913184610Salfred	 * Check if BUS-DMA support is enabled and try to load virtual
1914184610Salfred	 * buffers into DMA, if any:
1915184610Salfred	 */
1916190180Sthompsa#if USB_HAVE_BUSDMA
1917184610Salfred	if (xfer->flags_int.bdma_enable) {
1918184610Salfred		/* insert the USB transfer last in the BUS-DMA queue */
1919194228Sthompsa		usb_command_wrapper(&xfer->xroot->dma_q, xfer);
1920184610Salfred		return;
1921184610Salfred	}
1922190180Sthompsa#endif
1923184610Salfred	/*
1924184610Salfred	 * Enter the USB transfer into the Host Controller or
1925184610Salfred	 * Device Controller schedule:
1926184610Salfred	 */
1927194228Sthompsa	usbd_pipe_enter(xfer);
1928184610Salfred}
1929184610Salfred
1930184610Salfred/*------------------------------------------------------------------------*
1931194228Sthompsa *	usbd_pipe_enter - factored out code
1932184610Salfred *------------------------------------------------------------------------*/
1933184610Salfredvoid
1934194228Sthompsausbd_pipe_enter(struct usb_xfer *xfer)
1935184610Salfred{
1936193644Sthompsa	struct usb_endpoint *ep;
1937184610Salfred
1938184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
1939184610Salfred
1940187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
1941184610Salfred
1942193644Sthompsa	ep = xfer->endpoint;
1943184610Salfred
1944184610Salfred	DPRINTF("enter\n");
1945184610Salfred
1946234961Shselasky	/* the transfer can now be cancelled */
1947234961Shselasky	xfer->flags_int.can_cancel_immed = 1;
1948234961Shselasky
1949184610Salfred	/* enter the transfer */
1950193644Sthompsa	(ep->methods->enter) (xfer);
1951184610Salfred
1952190738Sthompsa	/* check for transfer error */
1953190738Sthompsa	if (xfer->error) {
1954190738Sthompsa		/* some error has happened */
1955194228Sthompsa		usbd_transfer_done(xfer, 0);
1956190738Sthompsa		USB_BUS_UNLOCK(xfer->xroot->bus);
1957190738Sthompsa		return;
1958184610Salfred	}
1959184610Salfred
1960184610Salfred	/* start the transfer */
1961239214Shselasky	usb_command_wrapper(&ep->endpoint_q[xfer->stream_id], xfer);
1962187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
1963184610Salfred}
1964184610Salfred
1965184610Salfred/*------------------------------------------------------------------------*
1966194228Sthompsa *	usbd_transfer_start - start an USB transfer
1967184610Salfred *
1968184610Salfred * NOTE: Calling this function more than one time will only
1969184610Salfred *       result in a single transfer start, until the USB transfer
1970184610Salfred *       completes.
1971184610Salfred *------------------------------------------------------------------------*/
1972184610Salfredvoid
1973194228Sthompsausbd_transfer_start(struct usb_xfer *xfer)
1974184610Salfred{
1975184610Salfred	if (xfer == NULL) {
1976184610Salfred		/* transfer is gone */
1977184610Salfred		return;
1978184610Salfred	}
1979184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
1980184610Salfred
1981184610Salfred	/* mark the USB transfer started */
1982184610Salfred
1983184610Salfred	if (!xfer->flags_int.started) {
1984197562Sthompsa		/* lock the BUS lock to avoid races updating flags_int */
1985197562Sthompsa		USB_BUS_LOCK(xfer->xroot->bus);
1986184610Salfred		xfer->flags_int.started = 1;
1987197562Sthompsa		USB_BUS_UNLOCK(xfer->xroot->bus);
1988184610Salfred	}
1989184610Salfred	/* check if the USB transfer callback is already transferring */
1990184610Salfred
1991184610Salfred	if (xfer->flags_int.transferring) {
1992184610Salfred		return;
1993184610Salfred	}
1994187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
1995184610Salfred	/* call the USB transfer callback */
1996194228Sthompsa	usbd_callback_ss_done_defer(xfer);
1997187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
1998184610Salfred}
1999184610Salfred
2000184610Salfred/*------------------------------------------------------------------------*
2001194228Sthompsa *	usbd_transfer_stop - stop an USB transfer
2002184610Salfred *
2003184610Salfred * NOTE: Calling this function more than one time will only
2004184610Salfred *       result in a single transfer stop.
2005184610Salfred * NOTE: When this function returns it is not safe to free nor
2006194228Sthompsa *       reuse any DMA buffers. See "usbd_transfer_drain()".
2007184610Salfred *------------------------------------------------------------------------*/
2008184610Salfredvoid
2009194228Sthompsausbd_transfer_stop(struct usb_xfer *xfer)
2010184610Salfred{
2011193644Sthompsa	struct usb_endpoint *ep;
2012184610Salfred
2013184610Salfred	if (xfer == NULL) {
2014184610Salfred		/* transfer is gone */
2015184610Salfred		return;
2016184610Salfred	}
2017184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
2018184610Salfred
2019184610Salfred	/* check if the USB transfer was ever opened */
2020184610Salfred
2021184610Salfred	if (!xfer->flags_int.open) {
2022197562Sthompsa		if (xfer->flags_int.started) {
2023197562Sthompsa			/* nothing to do except clearing the "started" flag */
2024197562Sthompsa			/* lock the BUS lock to avoid races updating flags_int */
2025197562Sthompsa			USB_BUS_LOCK(xfer->xroot->bus);
2026197562Sthompsa			xfer->flags_int.started = 0;
2027197562Sthompsa			USB_BUS_UNLOCK(xfer->xroot->bus);
2028197562Sthompsa		}
2029184610Salfred		return;
2030184610Salfred	}
2031184610Salfred	/* try to stop the current USB transfer */
2032184610Salfred
2033187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
2034197562Sthompsa	/* override any previous error */
2035197562Sthompsa	xfer->error = USB_ERR_CANCELLED;
2036197562Sthompsa
2037184610Salfred	/*
2038184610Salfred	 * Clear "open" and "started" when both private and USB lock
2039184610Salfred	 * is locked so that we don't get a race updating "flags_int"
2040184610Salfred	 */
2041184610Salfred	xfer->flags_int.open = 0;
2042184610Salfred	xfer->flags_int.started = 0;
2043184610Salfred
2044184610Salfred	/*
2045184610Salfred	 * Check if we can cancel the USB transfer immediately.
2046184610Salfred	 */
2047184610Salfred	if (xfer->flags_int.transferring) {
2048184610Salfred		if (xfer->flags_int.can_cancel_immed &&
2049184610Salfred		    (!xfer->flags_int.did_close)) {
2050184610Salfred			DPRINTF("close\n");
2051184610Salfred			/*
2052184610Salfred			 * The following will lead to an USB_ERR_CANCELLED
2053184610Salfred			 * error code being passed to the USB callback.
2054184610Salfred			 */
2055193644Sthompsa			(xfer->endpoint->methods->close) (xfer);
2056184610Salfred			/* only close once */
2057184610Salfred			xfer->flags_int.did_close = 1;
2058184610Salfred		} else {
2059184610Salfred			/* need to wait for the next done callback */
2060184610Salfred		}
2061184610Salfred	} else {
2062184610Salfred		DPRINTF("close\n");
2063184610Salfred
2064184610Salfred		/* close here and now */
2065193644Sthompsa		(xfer->endpoint->methods->close) (xfer);
2066184610Salfred
2067184610Salfred		/*
2068184610Salfred		 * Any additional DMA delay is done by
2069194228Sthompsa		 * "usbd_transfer_unsetup()".
2070184610Salfred		 */
2071184610Salfred
2072184610Salfred		/*
2073184610Salfred		 * Special case. Check if we need to restart a blocked
2074193644Sthompsa		 * endpoint.
2075184610Salfred		 */
2076193644Sthompsa		ep = xfer->endpoint;
2077184610Salfred
2078184610Salfred		/*
2079184610Salfred		 * If the current USB transfer is completing we need
2080184610Salfred		 * to start the next one:
2081184610Salfred		 */
2082239214Shselasky		if (ep->endpoint_q[xfer->stream_id].curr == xfer) {
2083239214Shselasky			usb_command_wrapper(
2084239214Shselasky			    &ep->endpoint_q[xfer->stream_id], NULL);
2085184610Salfred		}
2086184610Salfred	}
2087184610Salfred
2088187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
2089184610Salfred}
2090184610Salfred
2091184610Salfred/*------------------------------------------------------------------------*
2092194228Sthompsa *	usbd_transfer_pending
2093184610Salfred *
2094184610Salfred * This function will check if an USB transfer is pending which is a
2095184610Salfred * little bit complicated!
2096184610Salfred * Return values:
2097184610Salfred * 0: Not pending
2098184610Salfred * 1: Pending: The USB transfer will receive a callback in the future.
2099184610Salfred *------------------------------------------------------------------------*/
2100184610Salfreduint8_t
2101194228Sthompsausbd_transfer_pending(struct usb_xfer *xfer)
2102184610Salfred{
2103192984Sthompsa	struct usb_xfer_root *info;
2104192984Sthompsa	struct usb_xfer_queue *pq;
2105184610Salfred
2106188600Sthompsa	if (xfer == NULL) {
2107188600Sthompsa		/* transfer is gone */
2108188600Sthompsa		return (0);
2109188600Sthompsa	}
2110184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
2111184610Salfred
2112184610Salfred	if (xfer->flags_int.transferring) {
2113184610Salfred		/* trivial case */
2114184610Salfred		return (1);
2115184610Salfred	}
2116187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
2117184610Salfred	if (xfer->wait_queue) {
2118184610Salfred		/* we are waiting on a queue somewhere */
2119187173Sthompsa		USB_BUS_UNLOCK(xfer->xroot->bus);
2120184610Salfred		return (1);
2121184610Salfred	}
2122187173Sthompsa	info = xfer->xroot;
2123184610Salfred	pq = &info->done_q;
2124184610Salfred
2125184610Salfred	if (pq->curr == xfer) {
2126184610Salfred		/* we are currently scheduled for callback */
2127187173Sthompsa		USB_BUS_UNLOCK(xfer->xroot->bus);
2128184610Salfred		return (1);
2129184610Salfred	}
2130184610Salfred	/* we are not pending */
2131187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
2132184610Salfred	return (0);
2133184610Salfred}
2134184610Salfred
2135184610Salfred/*------------------------------------------------------------------------*
2136194228Sthompsa *	usbd_transfer_drain
2137184610Salfred *
2138184610Salfred * This function will stop the USB transfer and wait for any
2139184610Salfred * additional BUS-DMA and HW-DMA operations to complete. Buffers that
2140184610Salfred * are loaded into DMA can safely be freed or reused after that this
2141184610Salfred * function has returned.
2142184610Salfred *------------------------------------------------------------------------*/
2143184610Salfredvoid
2144194228Sthompsausbd_transfer_drain(struct usb_xfer *xfer)
2145184610Salfred{
2146184610Salfred	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
2147194228Sthompsa	    "usbd_transfer_drain can sleep!");
2148184610Salfred
2149184610Salfred	if (xfer == NULL) {
2150184610Salfred		/* transfer is gone */
2151184610Salfred		return;
2152184610Salfred	}
2153187173Sthompsa	if (xfer->xroot->xfer_mtx != &Giant) {
2154184824Sthompsa		USB_XFER_LOCK_ASSERT(xfer, MA_NOTOWNED);
2155184610Salfred	}
2156184824Sthompsa	USB_XFER_LOCK(xfer);
2157184610Salfred
2158194228Sthompsa	usbd_transfer_stop(xfer);
2159184610Salfred
2160198775Sthompsa	while (usbd_transfer_pending(xfer) ||
2161198775Sthompsa	    xfer->flags_int.doing_callback) {
2162198775Sthompsa
2163198775Sthompsa		/*
2164198775Sthompsa		 * It is allowed that the callback can drop its
2165198775Sthompsa		 * transfer mutex. In that case checking only
2166198775Sthompsa		 * "usbd_transfer_pending()" is not enough to tell if
2167198775Sthompsa		 * the USB transfer is fully drained. We also need to
2168198775Sthompsa		 * check the internal "doing_callback" flag.
2169198775Sthompsa		 */
2170184610Salfred		xfer->flags_int.draining = 1;
2171198775Sthompsa
2172184610Salfred		/*
2173184610Salfred		 * Wait until the current outstanding USB
2174184610Salfred		 * transfer is complete !
2175184610Salfred		 */
2176194227Sthompsa		cv_wait(&xfer->xroot->cv_drain, xfer->xroot->xfer_mtx);
2177184610Salfred	}
2178184824Sthompsa	USB_XFER_UNLOCK(xfer);
2179184610Salfred}
2180184610Salfred
2181194677Sthompsastruct usb_page_cache *
2182194677Sthompsausbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
2183194677Sthompsa{
2184194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
2185194677Sthompsa
2186194677Sthompsa	return (&xfer->frbuffers[frindex]);
2187194677Sthompsa}
2188194677Sthompsa
2189244500Shselaskyvoid *
2190244500Shselaskyusbd_xfer_get_frame_buffer(struct usb_xfer *xfer, usb_frcount_t frindex)
2191244500Shselasky{
2192244500Shselasky	struct usb_page_search page_info;
2193244500Shselasky
2194244500Shselasky	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
2195244500Shselasky
2196244500Shselasky	usbd_get_page(&xfer->frbuffers[frindex], 0, &page_info);
2197244500Shselasky	return (page_info.buffer);
2198244500Shselasky}
2199244500Shselasky
2200199059Sthompsa/*------------------------------------------------------------------------*
2201199059Sthompsa *	usbd_xfer_get_fps_shift
2202199059Sthompsa *
2203199059Sthompsa * The following function is only useful for isochronous transfers. It
2204199059Sthompsa * returns how many times the frame execution rate has been shifted
2205199059Sthompsa * down.
2206199059Sthompsa *
2207199059Sthompsa * Return value:
2208199059Sthompsa * Success: 0..3
2209199059Sthompsa * Failure: 0
2210199059Sthompsa *------------------------------------------------------------------------*/
2211199059Sthompsauint8_t
2212199059Sthompsausbd_xfer_get_fps_shift(struct usb_xfer *xfer)
2213199059Sthompsa{
2214199059Sthompsa	return (xfer->fps_shift);
2215199059Sthompsa}
2216199059Sthompsa
2217194677Sthompsausb_frlength_t
2218194682Sthompsausbd_xfer_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex)
2219194677Sthompsa{
2220194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
2221194677Sthompsa
2222194677Sthompsa	return (xfer->frlengths[frindex]);
2223194677Sthompsa}
2224194677Sthompsa
2225184610Salfred/*------------------------------------------------------------------------*
2226194677Sthompsa *	usbd_xfer_set_frame_data
2227184610Salfred *
2228184610Salfred * This function sets the pointer of the buffer that should
2229184610Salfred * loaded directly into DMA for the given USB frame. Passing "ptr"
2230184610Salfred * equal to NULL while the corresponding "frlength" is greater
2231184610Salfred * than zero gives undefined results!
2232184610Salfred *------------------------------------------------------------------------*/
2233184610Salfredvoid
2234194677Sthompsausbd_xfer_set_frame_data(struct usb_xfer *xfer, usb_frcount_t frindex,
2235194677Sthompsa    void *ptr, usb_frlength_t len)
2236184610Salfred{
2237194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
2238194677Sthompsa
2239184610Salfred	/* set virtual address to load and length */
2240184610Salfred	xfer->frbuffers[frindex].buffer = ptr;
2241194677Sthompsa	usbd_xfer_set_frame_len(xfer, frindex, len);
2242184610Salfred}
2243184610Salfred
2244194677Sthompsavoid
2245194682Sthompsausbd_xfer_frame_data(struct usb_xfer *xfer, usb_frcount_t frindex,
2246194677Sthompsa    void **ptr, int *len)
2247194677Sthompsa{
2248194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
2249194677Sthompsa
2250194677Sthompsa	if (ptr != NULL)
2251194677Sthompsa		*ptr = xfer->frbuffers[frindex].buffer;
2252194677Sthompsa	if (len != NULL)
2253194677Sthompsa		*len = xfer->frlengths[frindex];
2254194677Sthompsa}
2255194677Sthompsa
2256220301Shselasky/*------------------------------------------------------------------------*
2257220301Shselasky *	usbd_xfer_old_frame_length
2258220301Shselasky *
2259220301Shselasky * This function returns the framelength of the given frame at the
2260220301Shselasky * time the transfer was submitted. This function can be used to
2261220301Shselasky * compute the starting data pointer of the next isochronous frame
2262220301Shselasky * when an isochronous transfer has completed.
2263220301Shselasky *------------------------------------------------------------------------*/
2264220301Shselaskyusb_frlength_t
2265220301Shselaskyusbd_xfer_old_frame_length(struct usb_xfer *xfer, usb_frcount_t frindex)
2266220301Shselasky{
2267220301Shselasky	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
2268220301Shselasky
2269220301Shselasky	return (xfer->frlengths[frindex + xfer->max_frame_count]);
2270220301Shselasky}
2271220301Shselasky
2272194677Sthompsavoid
2273194677Sthompsausbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes,
2274194677Sthompsa    int *nframes)
2275194677Sthompsa{
2276194677Sthompsa	if (actlen != NULL)
2277194677Sthompsa		*actlen = xfer->actlen;
2278194677Sthompsa	if (sumlen != NULL)
2279194677Sthompsa		*sumlen = xfer->sumlen;
2280194677Sthompsa	if (aframes != NULL)
2281194677Sthompsa		*aframes = xfer->aframes;
2282194677Sthompsa	if (nframes != NULL)
2283194677Sthompsa		*nframes = xfer->nframes;
2284194677Sthompsa}
2285194677Sthompsa
2286184610Salfred/*------------------------------------------------------------------------*
2287194677Sthompsa *	usbd_xfer_set_frame_offset
2288184610Salfred *
2289184610Salfred * This function sets the frame data buffer offset relative to the beginning
2290184610Salfred * of the USB DMA buffer allocated for this USB transfer.
2291184610Salfred *------------------------------------------------------------------------*/
2292184610Salfredvoid
2293194677Sthompsausbd_xfer_set_frame_offset(struct usb_xfer *xfer, usb_frlength_t offset,
2294193045Sthompsa    usb_frcount_t frindex)
2295184610Salfred{
2296194677Sthompsa	KASSERT(!xfer->flags.ext_buffer, ("Cannot offset data frame "
2297199816Sthompsa	    "when the USB buffer is external\n"));
2298194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
2299184610Salfred
2300184610Salfred	/* set virtual address to load */
2301184610Salfred	xfer->frbuffers[frindex].buffer =
2302184610Salfred	    USB_ADD_BYTES(xfer->local_buffer, offset);
2303184610Salfred}
2304184610Salfred
2305194677Sthompsavoid
2306194677Sthompsausbd_xfer_set_interval(struct usb_xfer *xfer, int i)
2307194677Sthompsa{
2308194677Sthompsa	xfer->interval = i;
2309194677Sthompsa}
2310194677Sthompsa
2311194677Sthompsavoid
2312194677Sthompsausbd_xfer_set_timeout(struct usb_xfer *xfer, int t)
2313194677Sthompsa{
2314194677Sthompsa	xfer->timeout = t;
2315194677Sthompsa}
2316194677Sthompsa
2317194677Sthompsavoid
2318194677Sthompsausbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
2319194677Sthompsa{
2320194677Sthompsa	xfer->nframes = n;
2321194677Sthompsa}
2322194677Sthompsa
2323194677Sthompsausb_frcount_t
2324194677Sthompsausbd_xfer_max_frames(struct usb_xfer *xfer)
2325194677Sthompsa{
2326194677Sthompsa	return (xfer->max_frame_count);
2327194677Sthompsa}
2328194677Sthompsa
2329194677Sthompsausb_frlength_t
2330194677Sthompsausbd_xfer_max_len(struct usb_xfer *xfer)
2331194677Sthompsa{
2332194677Sthompsa	return (xfer->max_data_length);
2333194677Sthompsa}
2334194677Sthompsa
2335194677Sthompsausb_frlength_t
2336194677Sthompsausbd_xfer_max_framelen(struct usb_xfer *xfer)
2337194677Sthompsa{
2338194677Sthompsa	return (xfer->max_frame_size);
2339194677Sthompsa}
2340194677Sthompsa
2341194677Sthompsavoid
2342194677Sthompsausbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex,
2343194677Sthompsa    usb_frlength_t len)
2344194677Sthompsa{
2345194677Sthompsa	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
2346194677Sthompsa
2347194677Sthompsa	xfer->frlengths[frindex] = len;
2348194677Sthompsa}
2349194677Sthompsa
2350184610Salfred/*------------------------------------------------------------------------*
2351194228Sthompsa *	usb_callback_proc - factored out code
2352184610Salfred *
2353184610Salfred * This function performs USB callbacks.
2354184610Salfred *------------------------------------------------------------------------*/
2355184610Salfredstatic void
2356194228Sthompsausb_callback_proc(struct usb_proc_msg *_pm)
2357184610Salfred{
2358192984Sthompsa	struct usb_done_msg *pm = (void *)_pm;
2359192984Sthompsa	struct usb_xfer_root *info = pm->xroot;
2360184610Salfred
2361184610Salfred	/* Change locking order */
2362184824Sthompsa	USB_BUS_UNLOCK(info->bus);
2363184610Salfred
2364184610Salfred	/*
2365184610Salfred	 * We exploit the fact that the mutex is the same for all
2366184610Salfred	 * callbacks that will be called from this thread:
2367184610Salfred	 */
2368187173Sthompsa	mtx_lock(info->xfer_mtx);
2369184824Sthompsa	USB_BUS_LOCK(info->bus);
2370184610Salfred
2371184610Salfred	/* Continue where we lost track */
2372194228Sthompsa	usb_command_wrapper(&info->done_q,
2373184610Salfred	    info->done_q.curr);
2374184610Salfred
2375187173Sthompsa	mtx_unlock(info->xfer_mtx);
2376184610Salfred}
2377184610Salfred
2378184610Salfred/*------------------------------------------------------------------------*
2379194228Sthompsa *	usbd_callback_ss_done_defer
2380184610Salfred *
2381184610Salfred * This function will defer the start, stop and done callback to the
2382184610Salfred * correct thread.
2383184610Salfred *------------------------------------------------------------------------*/
2384184610Salfredstatic void
2385194228Sthompsausbd_callback_ss_done_defer(struct usb_xfer *xfer)
2386184610Salfred{
2387192984Sthompsa	struct usb_xfer_root *info = xfer->xroot;
2388192984Sthompsa	struct usb_xfer_queue *pq = &info->done_q;
2389184610Salfred
2390187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2391184824Sthompsa
2392184610Salfred	if (pq->curr != xfer) {
2393194228Sthompsa		usbd_transfer_enqueue(pq, xfer);
2394184610Salfred	}
2395184610Salfred	if (!pq->recurse_1) {
2396184610Salfred
2397184610Salfred		/*
2398184610Salfred	         * We have to postpone the callback due to the fact we
2399184610Salfred	         * will have a Lock Order Reversal, LOR, if we try to
2400184610Salfred	         * proceed !
2401184610Salfred	         */
2402287274Shselasky		(void) usb_proc_msignal(info->done_p,
2403287274Shselasky		    &info->done_m[0], &info->done_m[1]);
2404184610Salfred	} else {
2405184610Salfred		/* clear second recurse flag */
2406184610Salfred		pq->recurse_2 = 0;
2407184610Salfred	}
2408184610Salfred	return;
2409184610Salfred
2410184610Salfred}
2411184610Salfred
2412184610Salfred/*------------------------------------------------------------------------*
2413194228Sthompsa *	usbd_callback_wrapper
2414184610Salfred *
2415184610Salfred * This is a wrapper for USB callbacks. This wrapper does some
2416184610Salfred * auto-magic things like figuring out if we can call the callback
2417184610Salfred * directly from the current context or if we need to wakeup the
2418184610Salfred * interrupt process.
2419184610Salfred *------------------------------------------------------------------------*/
2420184610Salfredstatic void
2421194228Sthompsausbd_callback_wrapper(struct usb_xfer_queue *pq)
2422184610Salfred{
2423192984Sthompsa	struct usb_xfer *xfer = pq->curr;
2424192984Sthompsa	struct usb_xfer_root *info = xfer->xroot;
2425184610Salfred
2426190738Sthompsa	USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
2427287274Shselasky	if ((pq->recurse_3 != 0 || mtx_owned(info->xfer_mtx) == 0) &&
2428287274Shselasky	    SCHEDULER_STOPPED() == 0) {
2429184610Salfred		/*
2430184610Salfred	       	 * Cases that end up here:
2431184610Salfred		 *
2432184610Salfred		 * 5) HW interrupt done callback or other source.
2433287274Shselasky		 * 6) HW completed transfer during callback
2434184610Salfred		 */
2435287274Shselasky		DPRINTFN(3, "case 5 and 6\n");
2436184610Salfred
2437184610Salfred		/*
2438184610Salfred	         * We have to postpone the callback due to the fact we
2439184610Salfred	         * will have a Lock Order Reversal, LOR, if we try to
2440287274Shselasky	         * proceed!
2441287274Shselasky		 *
2442287274Shselasky		 * Postponing the callback also ensures that other USB
2443287274Shselasky		 * transfer queues get a chance.
2444184610Salfred	         */
2445287274Shselasky		(void) usb_proc_msignal(info->done_p,
2446287274Shselasky		    &info->done_m[0], &info->done_m[1]);
2447184610Salfred		return;
2448184610Salfred	}
2449184610Salfred	/*
2450184610Salfred	 * Cases that end up here:
2451184610Salfred	 *
2452184610Salfred	 * 1) We are starting a transfer
2453184610Salfred	 * 2) We are prematurely calling back a transfer
2454184610Salfred	 * 3) We are stopping a transfer
2455184610Salfred	 * 4) We are doing an ordinary callback
2456184610Salfred	 */
2457184610Salfred	DPRINTFN(3, "case 1-4\n");
2458184610Salfred	/* get next USB transfer in the queue */
2459184610Salfred	info->done_q.curr = NULL;
2460184610Salfred
2461198775Sthompsa	/* set flag in case of drain */
2462198775Sthompsa	xfer->flags_int.doing_callback = 1;
2463198775Sthompsa
2464190738Sthompsa	USB_BUS_UNLOCK(info->bus);
2465190738Sthompsa	USB_BUS_LOCK_ASSERT(info->bus, MA_NOTOWNED);
2466184610Salfred
2467184610Salfred	/* set correct USB state for callback */
2468184610Salfred	if (!xfer->flags_int.transferring) {
2469194228Sthompsa		xfer->usb_state = USB_ST_SETUP;
2470184610Salfred		if (!xfer->flags_int.started) {
2471184610Salfred			/* we got stopped before we even got started */
2472190738Sthompsa			USB_BUS_LOCK(info->bus);
2473184610Salfred			goto done;
2474184610Salfred		}
2475184610Salfred	} else {
2476184610Salfred
2477194228Sthompsa		if (usbd_callback_wrapper_sub(xfer)) {
2478184610Salfred			/* the callback has been deferred */
2479190738Sthompsa			USB_BUS_LOCK(info->bus);
2480184610Salfred			goto done;
2481184610Salfred		}
2482190734Sthompsa#if USB_HAVE_POWERD
2483186730Salfred		/* decrement power reference */
2484194228Sthompsa		usbd_transfer_power_ref(xfer, -1);
2485190734Sthompsa#endif
2486184610Salfred		xfer->flags_int.transferring = 0;
2487184610Salfred
2488184610Salfred		if (xfer->error) {
2489194228Sthompsa			xfer->usb_state = USB_ST_ERROR;
2490184610Salfred		} else {
2491184610Salfred			/* set transferred state */
2492194228Sthompsa			xfer->usb_state = USB_ST_TRANSFERRED;
2493190180Sthompsa#if USB_HAVE_BUSDMA
2494184610Salfred			/* sync DMA memory, if any */
2495184610Salfred			if (xfer->flags_int.bdma_enable &&
2496184610Salfred			    (!xfer->flags_int.bdma_no_post_sync)) {
2497194228Sthompsa				usb_bdma_post_sync(xfer);
2498184610Salfred			}
2499190180Sthompsa#endif
2500184610Salfred		}
2501184610Salfred	}
2502184610Salfred
2503217558Shselasky#if USB_HAVE_PF
2504287272Shselasky	if (xfer->usb_state != USB_ST_SETUP) {
2505287272Shselasky		USB_BUS_LOCK(info->bus);
2506215649Sweongyo		usbpf_xfertap(xfer, USBPF_XFERTAP_DONE);
2507287272Shselasky		USB_BUS_UNLOCK(info->bus);
2508287272Shselasky	}
2509217558Shselasky#endif
2510184610Salfred	/* call processing routine */
2511194677Sthompsa	(xfer->callback) (xfer, xfer->error);
2512184610Salfred
2513184610Salfred	/* pickup the USB mutex again */
2514190738Sthompsa	USB_BUS_LOCK(info->bus);
2515184610Salfred
2516184610Salfred	/*
2517184610Salfred	 * Check if we got started after that we got cancelled, but
2518187166Sthompsa	 * before we managed to do the callback.
2519184610Salfred	 */
2520184610Salfred	if ((!xfer->flags_int.open) &&
2521184610Salfred	    (xfer->flags_int.started) &&
2522194228Sthompsa	    (xfer->usb_state == USB_ST_ERROR)) {
2523198775Sthompsa		/* clear flag in case of drain */
2524198775Sthompsa		xfer->flags_int.doing_callback = 0;
2525184610Salfred		/* try to loop, but not recursivly */
2526194228Sthompsa		usb_command_wrapper(&info->done_q, xfer);
2527184610Salfred		return;
2528187166Sthompsa	}
2529187166Sthompsa
2530187166Sthompsadone:
2531198775Sthompsa	/* clear flag in case of drain */
2532198775Sthompsa	xfer->flags_int.doing_callback = 0;
2533198775Sthompsa
2534187166Sthompsa	/*
2535187166Sthompsa	 * Check if we are draining.
2536187166Sthompsa	 */
2537187166Sthompsa	if (xfer->flags_int.draining &&
2538184610Salfred	    (!xfer->flags_int.transferring)) {
2539194228Sthompsa		/* "usbd_transfer_drain()" is waiting for end of transfer */
2540184610Salfred		xfer->flags_int.draining = 0;
2541194227Sthompsa		cv_broadcast(&info->cv_drain);
2542184610Salfred	}
2543187166Sthompsa
2544184610Salfred	/* do the next callback, if any */
2545194228Sthompsa	usb_command_wrapper(&info->done_q,
2546184610Salfred	    info->done_q.curr);
2547184610Salfred}
2548184610Salfred
2549184610Salfred/*------------------------------------------------------------------------*
2550194228Sthompsa *	usb_dma_delay_done_cb
2551184610Salfred *
2552184610Salfred * This function is called when the DMA delay has been exectuded, and
2553184610Salfred * will make sure that the callback is called to complete the USB
2554184610Salfred * transfer. This code path is ususally only used when there is an USB
2555184610Salfred * error like USB_ERR_CANCELLED.
2556184610Salfred *------------------------------------------------------------------------*/
2557213435Shselaskyvoid
2558213435Shselaskyusb_dma_delay_done_cb(struct usb_xfer *xfer)
2559184610Salfred{
2560187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2561184610Salfred
2562184610Salfred	DPRINTFN(3, "Completed %p\n", xfer);
2563184610Salfred
2564184610Salfred	/* queue callback for execution, again */
2565194228Sthompsa	usbd_transfer_done(xfer, 0);
2566184610Salfred}
2567184610Salfred
2568184610Salfred/*------------------------------------------------------------------------*
2569194228Sthompsa *	usbd_transfer_dequeue
2570184610Salfred *
2571184610Salfred *  - This function is used to remove an USB transfer from a USB
2572184610Salfred *  transfer queue.
2573184610Salfred *
2574184610Salfred *  - This function can be called multiple times in a row.
2575184610Salfred *------------------------------------------------------------------------*/
2576184610Salfredvoid
2577194228Sthompsausbd_transfer_dequeue(struct usb_xfer *xfer)
2578184610Salfred{
2579192984Sthompsa	struct usb_xfer_queue *pq;
2580184610Salfred
2581184610Salfred	pq = xfer->wait_queue;
2582184610Salfred	if (pq) {
2583184610Salfred		TAILQ_REMOVE(&pq->head, xfer, wait_entry);
2584184610Salfred		xfer->wait_queue = NULL;
2585184610Salfred	}
2586184610Salfred}
2587184610Salfred
2588184610Salfred/*------------------------------------------------------------------------*
2589194228Sthompsa *	usbd_transfer_enqueue
2590184610Salfred *
2591184610Salfred *  - This function is used to insert an USB transfer into a USB *
2592184610Salfred *  transfer queue.
2593184610Salfred *
2594184610Salfred *  - This function can be called multiple times in a row.
2595184610Salfred *------------------------------------------------------------------------*/
2596184610Salfredvoid
2597194228Sthompsausbd_transfer_enqueue(struct usb_xfer_queue *pq, struct usb_xfer *xfer)
2598184610Salfred{
2599184610Salfred	/*
2600184610Salfred	 * Insert the USB transfer into the queue, if it is not
2601184610Salfred	 * already on a USB transfer queue:
2602184610Salfred	 */
2603184610Salfred	if (xfer->wait_queue == NULL) {
2604184610Salfred		xfer->wait_queue = pq;
2605184610Salfred		TAILQ_INSERT_TAIL(&pq->head, xfer, wait_entry);
2606184610Salfred	}
2607184610Salfred}
2608184610Salfred
2609184610Salfred/*------------------------------------------------------------------------*
2610194228Sthompsa *	usbd_transfer_done
2611184610Salfred *
2612184610Salfred *  - This function is used to remove an USB transfer from the busdma,
2613184610Salfred *  pipe or interrupt queue.
2614184610Salfred *
2615184610Salfred *  - This function is used to queue the USB transfer on the done
2616184610Salfred *  queue.
2617184610Salfred *
2618184610Salfred *  - This function is used to stop any USB transfer timeouts.
2619184610Salfred *------------------------------------------------------------------------*/
2620184610Salfredvoid
2621194228Sthompsausbd_transfer_done(struct usb_xfer *xfer, usb_error_t error)
2622184610Salfred{
2623261105Shselasky	struct usb_xfer_root *info = xfer->xroot;
2624184610Salfred
2625261105Shselasky	USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
2626261105Shselasky
2627194228Sthompsa	DPRINTF("err=%s\n", usbd_errstr(error));
2628184610Salfred
2629184610Salfred	/*
2630184610Salfred	 * If we are not transferring then just return.
2631184610Salfred	 * This can happen during transfer cancel.
2632184610Salfred	 */
2633184610Salfred	if (!xfer->flags_int.transferring) {
2634184610Salfred		DPRINTF("not transferring\n");
2635197562Sthompsa		/* end of control transfer, if any */
2636197562Sthompsa		xfer->flags_int.control_act = 0;
2637184610Salfred		return;
2638184610Salfred	}
2639261105Shselasky	/* only set transfer error, if not already set */
2640261105Shselasky	if (xfer->error == USB_ERR_NORMAL_COMPLETION)
2641184610Salfred		xfer->error = error;
2642261105Shselasky
2643184610Salfred	/* stop any callouts */
2644194228Sthompsa	usb_callout_stop(&xfer->timeout_handle);
2645184610Salfred
2646184610Salfred	/*
2647184610Salfred	 * If we are waiting on a queue, just remove the USB transfer
2648184610Salfred	 * from the queue, if any. We should have the required locks
2649184610Salfred	 * locked to do the remove when this function is called.
2650184610Salfred	 */
2651194228Sthompsa	usbd_transfer_dequeue(xfer);
2652184610Salfred
2653190180Sthompsa#if USB_HAVE_BUSDMA
2654261105Shselasky	if (mtx_owned(info->xfer_mtx)) {
2655192984Sthompsa		struct usb_xfer_queue *pq;
2656190180Sthompsa
2657184610Salfred		/*
2658184610Salfred		 * If the private USB lock is not locked, then we assume
2659184610Salfred		 * that the BUS-DMA load stage has been passed:
2660184610Salfred		 */
2661261105Shselasky		pq = &info->dma_q;
2662184610Salfred
2663184610Salfred		if (pq->curr == xfer) {
2664184610Salfred			/* start the next BUS-DMA load, if any */
2665194228Sthompsa			usb_command_wrapper(pq, NULL);
2666184610Salfred		}
2667184610Salfred	}
2668190180Sthompsa#endif
2669184610Salfred	/* keep some statistics */
2670356681Shselasky	if (xfer->error == USB_ERR_CANCELLED) {
2671356681Shselasky		info->udev->stats_cancelled.uds_requests
2672356681Shselasky		    [xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
2673356681Shselasky	} else if (xfer->error != USB_ERR_NORMAL_COMPLETION) {
2674356396Shselasky		info->udev->stats_err.uds_requests
2675193644Sthompsa		    [xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
2676184610Salfred	} else {
2677356396Shselasky		info->udev->stats_ok.uds_requests
2678193644Sthompsa		    [xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
2679184610Salfred	}
2680184610Salfred
2681184610Salfred	/* call the USB transfer callback */
2682194228Sthompsa	usbd_callback_ss_done_defer(xfer);
2683184610Salfred}
2684184610Salfred
2685184610Salfred/*------------------------------------------------------------------------*
2686194228Sthompsa *	usbd_transfer_start_cb
2687184610Salfred *
2688184610Salfred * This function is called to start the USB transfer when
2689184610Salfred * "xfer->interval" is greater than zero, and and the endpoint type is
2690184610Salfred * BULK or CONTROL.
2691184610Salfred *------------------------------------------------------------------------*/
2692184610Salfredstatic void
2693194228Sthompsausbd_transfer_start_cb(void *arg)
2694184610Salfred{
2695192984Sthompsa	struct usb_xfer *xfer = arg;
2696193644Sthompsa	struct usb_endpoint *ep = xfer->endpoint;
2697184610Salfred
2698187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2699184610Salfred
2700184610Salfred	DPRINTF("start\n");
2701184610Salfred
2702217558Shselasky#if USB_HAVE_PF
2703215649Sweongyo	usbpf_xfertap(xfer, USBPF_XFERTAP_SUBMIT);
2704217558Shselasky#endif
2705234961Shselasky
2706234961Shselasky	/* the transfer can now be cancelled */
2707234961Shselasky	xfer->flags_int.can_cancel_immed = 1;
2708234961Shselasky
2709225695Shselasky	/* start USB transfer, if no error */
2710225695Shselasky	if (xfer->error == 0)
2711225695Shselasky		(ep->methods->start) (xfer);
2712184610Salfred
2713234961Shselasky	/* check for transfer error */
2714190738Sthompsa	if (xfer->error) {
2715190738Sthompsa		/* some error has happened */
2716194228Sthompsa		usbd_transfer_done(xfer, 0);
2717184610Salfred	}
2718184610Salfred}
2719184610Salfred
2720184610Salfred/*------------------------------------------------------------------------*
2721194677Sthompsa *	usbd_xfer_set_stall
2722184610Salfred *
2723184610Salfred * This function is used to set the stall flag outside the
2724184610Salfred * callback. This function is NULL safe.
2725184610Salfred *------------------------------------------------------------------------*/
2726184610Salfredvoid
2727194677Sthompsausbd_xfer_set_stall(struct usb_xfer *xfer)
2728184610Salfred{
2729184610Salfred	if (xfer == NULL) {
2730184610Salfred		/* tearing down */
2731184610Salfred		return;
2732184610Salfred	}
2733184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
2734184610Salfred
2735184610Salfred	/* avoid any races by locking the USB mutex */
2736187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
2737184610Salfred	xfer->flags.stall_pipe = 1;
2738187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
2739184610Salfred}
2740184610Salfred
2741194677Sthompsaint
2742194677Sthompsausbd_xfer_is_stalled(struct usb_xfer *xfer)
2743194677Sthompsa{
2744194677Sthompsa	return (xfer->endpoint->is_stalled);
2745194677Sthompsa}
2746194677Sthompsa
2747184610Salfred/*------------------------------------------------------------------------*
2748194228Sthompsa *	usbd_transfer_clear_stall
2749184610Salfred *
2750184610Salfred * This function is used to clear the stall flag outside the
2751184610Salfred * callback. This function is NULL safe.
2752184610Salfred *------------------------------------------------------------------------*/
2753184610Salfredvoid
2754194228Sthompsausbd_transfer_clear_stall(struct usb_xfer *xfer)
2755184610Salfred{
2756184610Salfred	if (xfer == NULL) {
2757184610Salfred		/* tearing down */
2758184610Salfred		return;
2759184610Salfred	}
2760184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
2761184610Salfred
2762184610Salfred	/* avoid any races by locking the USB mutex */
2763187173Sthompsa	USB_BUS_LOCK(xfer->xroot->bus);
2764184610Salfred
2765184610Salfred	xfer->flags.stall_pipe = 0;
2766184610Salfred
2767187173Sthompsa	USB_BUS_UNLOCK(xfer->xroot->bus);
2768184610Salfred}
2769184610Salfred
2770184610Salfred/*------------------------------------------------------------------------*
2771194228Sthompsa *	usbd_pipe_start
2772184610Salfred *
2773184610Salfred * This function is used to add an USB transfer to the pipe transfer list.
2774184610Salfred *------------------------------------------------------------------------*/
2775184610Salfredvoid
2776194228Sthompsausbd_pipe_start(struct usb_xfer_queue *pq)
2777184610Salfred{
2778193644Sthompsa	struct usb_endpoint *ep;
2779192984Sthompsa	struct usb_xfer *xfer;
2780184610Salfred	uint8_t type;
2781184610Salfred
2782184610Salfred	xfer = pq->curr;
2783193644Sthompsa	ep = xfer->endpoint;
2784184610Salfred
2785187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2786184610Salfred
2787184610Salfred	/*
2788193644Sthompsa	 * If the endpoint is already stalled we do nothing !
2789184610Salfred	 */
2790193644Sthompsa	if (ep->is_stalled) {
2791184610Salfred		return;
2792184610Salfred	}
2793184610Salfred	/*
2794193644Sthompsa	 * Check if we are supposed to stall the endpoint:
2795184610Salfred	 */
2796184610Salfred	if (xfer->flags.stall_pipe) {
2797205035Sthompsa		struct usb_device *udev;
2798205035Sthompsa		struct usb_xfer_root *info;
2799205035Sthompsa
2800184610Salfred		/* clear stall command */
2801184610Salfred		xfer->flags.stall_pipe = 0;
2802184610Salfred
2803205035Sthompsa		/* get pointer to USB device */
2804205035Sthompsa		info = xfer->xroot;
2805205035Sthompsa		udev = info->udev;
2806205035Sthompsa
2807184610Salfred		/*
2808184610Salfred		 * Only stall BULK and INTERRUPT endpoints.
2809184610Salfred		 */
2810193644Sthompsa		type = (ep->edesc->bmAttributes & UE_XFERTYPE);
2811184610Salfred		if ((type == UE_BULK) ||
2812184610Salfred		    (type == UE_INTERRUPT)) {
2813195121Sthompsa			uint8_t did_stall;
2814184610Salfred
2815195121Sthompsa			did_stall = 1;
2816184610Salfred
2817192499Sthompsa			if (udev->flags.usb_mode == USB_MODE_DEVICE) {
2818184610Salfred				(udev->bus->methods->set_stall) (
2819239214Shselasky				    udev, ep, &did_stall);
2820207080Sthompsa			} else if (udev->ctrl_xfer[1]) {
2821207080Sthompsa				info = udev->ctrl_xfer[1]->xroot;
2822195121Sthompsa				usb_proc_msignal(
2823287274Shselasky				    USB_BUS_CS_PROC(info->bus),
2824195121Sthompsa				    &udev->cs_msg[0], &udev->cs_msg[1]);
2825184610Salfred			} else {
2826184610Salfred				/* should not happen */
2827199816Sthompsa				DPRINTFN(0, "No stall handler\n");
2828184610Salfred			}
2829184610Salfred			/*
2830195121Sthompsa			 * Check if we should stall. Some USB hardware
2831195121Sthompsa			 * handles set- and clear-stall in hardware.
2832184610Salfred			 */
2833195121Sthompsa			if (did_stall) {
2834195121Sthompsa				/*
2835195121Sthompsa				 * The transfer will be continued when
2836195121Sthompsa				 * the clear-stall control endpoint
2837195121Sthompsa				 * message is received.
2838195121Sthompsa				 */
2839195121Sthompsa				ep->is_stalled = 1;
2840195121Sthompsa				return;
2841195121Sthompsa			}
2842205035Sthompsa		} else if (type == UE_ISOCHRONOUS) {
2843205035Sthompsa
2844205035Sthompsa			/*
2845205035Sthompsa			 * Make sure any FIFO overflow or other FIFO
2846205035Sthompsa			 * error conditions go away by resetting the
2847205035Sthompsa			 * endpoint FIFO through the clear stall
2848205035Sthompsa			 * method.
2849205035Sthompsa			 */
2850205035Sthompsa			if (udev->flags.usb_mode == USB_MODE_DEVICE) {
2851205035Sthompsa				(udev->bus->methods->clear_stall) (udev, ep);
2852205035Sthompsa			}
2853184610Salfred		}
2854184610Salfred	}
2855184610Salfred	/* Set or clear stall complete - special case */
2856184610Salfred	if (xfer->nframes == 0) {
2857184610Salfred		/* we are complete */
2858184610Salfred		xfer->aframes = 0;
2859194228Sthompsa		usbd_transfer_done(xfer, 0);
2860184610Salfred		return;
2861184610Salfred	}
2862184610Salfred	/*
2863184610Salfred	 * Handled cases:
2864184610Salfred	 *
2865184610Salfred	 * 1) Start the first transfer queued.
2866184610Salfred	 *
2867184610Salfred	 * 2) Re-start the current USB transfer.
2868184610Salfred	 */
2869184610Salfred	/*
2870184610Salfred	 * Check if there should be any
2871184610Salfred	 * pre transfer start delay:
2872184610Salfred	 */
2873184610Salfred	if (xfer->interval > 0) {
2874193644Sthompsa		type = (ep->edesc->bmAttributes & UE_XFERTYPE);
2875184610Salfred		if ((type == UE_BULK) ||
2876184610Salfred		    (type == UE_CONTROL)) {
2877194228Sthompsa			usbd_transfer_timeout_ms(xfer,
2878194228Sthompsa			    &usbd_transfer_start_cb,
2879184610Salfred			    xfer->interval);
2880184610Salfred			return;
2881184610Salfred		}
2882184610Salfred	}
2883184610Salfred	DPRINTF("start\n");
2884184610Salfred
2885217558Shselasky#if USB_HAVE_PF
2886215649Sweongyo	usbpf_xfertap(xfer, USBPF_XFERTAP_SUBMIT);
2887217558Shselasky#endif
2888234961Shselasky	/* the transfer can now be cancelled */
2889234961Shselasky	xfer->flags_int.can_cancel_immed = 1;
2890234961Shselasky
2891225695Shselasky	/* start USB transfer, if no error */
2892225695Shselasky	if (xfer->error == 0)
2893225695Shselasky		(ep->methods->start) (xfer);
2894184610Salfred
2895234961Shselasky	/* check for transfer error */
2896190738Sthompsa	if (xfer->error) {
2897190738Sthompsa		/* some error has happened */
2898194228Sthompsa		usbd_transfer_done(xfer, 0);
2899184610Salfred	}
2900184610Salfred}
2901184610Salfred
2902184610Salfred/*------------------------------------------------------------------------*
2903194228Sthompsa *	usbd_transfer_timeout_ms
2904184610Salfred *
2905184610Salfred * This function is used to setup a timeout on the given USB
2906184610Salfred * transfer. If the timeout has been deferred the callback given by
2907184610Salfred * "cb" will get called after "ms" milliseconds.
2908184610Salfred *------------------------------------------------------------------------*/
2909184610Salfredvoid
2910194228Sthompsausbd_transfer_timeout_ms(struct usb_xfer *xfer,
2911193045Sthompsa    void (*cb) (void *arg), usb_timeout_t ms)
2912184610Salfred{
2913187173Sthompsa	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
2914184610Salfred
2915184610Salfred	/* defer delay */
2916194228Sthompsa	usb_callout_reset(&xfer->timeout_handle,
2917261465Shselasky	    USB_MS_TO_TICKS(ms) + USB_CALLOUT_ZERO_TICKS, cb, xfer);
2918184610Salfred}
2919184610Salfred
2920184610Salfred/*------------------------------------------------------------------------*
2921194228Sthompsa *	usbd_callback_wrapper_sub
2922184610Salfred *
2923184610Salfred *  - This function will update variables in an USB transfer after
2924184610Salfred *  that the USB transfer is complete.
2925184610Salfred *
2926184610Salfred *  - This function is used to start the next USB transfer on the
2927193644Sthompsa *  ep transfer queue, if any.
2928184610Salfred *
2929184610Salfred * NOTE: In some special cases the USB transfer will not be removed from
2930184610Salfred * the pipe queue, but remain first. To enforce USB transfer removal call
2931184610Salfred * this function passing the error code "USB_ERR_CANCELLED".
2932184610Salfred *
2933184610Salfred * Return values:
2934184610Salfred * 0: Success.
2935184610Salfred * Else: The callback has been deferred.
2936184610Salfred *------------------------------------------------------------------------*/
2937184610Salfredstatic uint8_t
2938194228Sthompsausbd_callback_wrapper_sub(struct usb_xfer *xfer)
2939184610Salfred{
2940193644Sthompsa	struct usb_endpoint *ep;
2941213435Shselasky	struct usb_bus *bus;
2942193045Sthompsa	usb_frcount_t x;
2943184610Salfred
2944213435Shselasky	bus = xfer->xroot->bus;
2945213435Shselasky
2946184610Salfred	if ((!xfer->flags_int.open) &&
2947184610Salfred	    (!xfer->flags_int.did_close)) {
2948184610Salfred		DPRINTF("close\n");
2949213435Shselasky		USB_BUS_LOCK(bus);
2950193644Sthompsa		(xfer->endpoint->methods->close) (xfer);
2951213435Shselasky		USB_BUS_UNLOCK(bus);
2952184610Salfred		/* only close once */
2953184610Salfred		xfer->flags_int.did_close = 1;
2954184610Salfred		return (1);		/* wait for new callback */
2955184610Salfred	}
2956184610Salfred	/*
2957184610Salfred	 * If we have a non-hardware induced error we
2958184610Salfred	 * need to do the DMA delay!
2959184610Salfred	 */
2960213435Shselasky	if (xfer->error != 0 && !xfer->flags_int.did_dma_delay &&
2961213435Shselasky	    (xfer->error == USB_ERR_CANCELLED ||
2962213435Shselasky	    xfer->error == USB_ERR_TIMEOUT ||
2963213435Shselasky	    bus->methods->start_dma_delay != NULL)) {
2964184610Salfred
2965193045Sthompsa		usb_timeout_t temp;
2966184610Salfred
2967197562Sthompsa		/* only delay once */
2968197562Sthompsa		xfer->flags_int.did_dma_delay = 1;
2969197562Sthompsa
2970184610Salfred		/* we can not cancel this delay */
2971184610Salfred		xfer->flags_int.can_cancel_immed = 0;
2972184610Salfred
2973212134Sthompsa		temp = usbd_get_dma_delay(xfer->xroot->udev);
2974184610Salfred
2975184610Salfred		DPRINTFN(3, "DMA delay, %u ms, "
2976184610Salfred		    "on %p\n", temp, xfer);
2977184610Salfred
2978184610Salfred		if (temp != 0) {
2979213435Shselasky			USB_BUS_LOCK(bus);
2980213435Shselasky			/*
2981213435Shselasky			 * Some hardware solutions have dedicated
2982213435Shselasky			 * events when it is safe to free DMA'ed
2983213435Shselasky			 * memory. For the other hardware platforms we
2984213435Shselasky			 * use a static delay.
2985213435Shselasky			 */
2986213435Shselasky			if (bus->methods->start_dma_delay != NULL) {
2987213435Shselasky				(bus->methods->start_dma_delay) (xfer);
2988213435Shselasky			} else {
2989213435Shselasky				usbd_transfer_timeout_ms(xfer,
2990233774Shselasky				    (void (*)(void *))&usb_dma_delay_done_cb,
2991233774Shselasky				    temp);
2992213435Shselasky			}
2993213435Shselasky			USB_BUS_UNLOCK(bus);
2994184610Salfred			return (1);	/* wait for new callback */
2995184610Salfred		}
2996184610Salfred	}
2997184610Salfred	/* check actual number of frames */
2998184610Salfred	if (xfer->aframes > xfer->nframes) {
2999184610Salfred		if (xfer->error == 0) {
3000184610Salfred			panic("%s: actual number of frames, %d, is "
3001199816Sthompsa			    "greater than initial number of frames, %d\n",
3002184610Salfred			    __FUNCTION__, xfer->aframes, xfer->nframes);
3003184610Salfred		} else {
3004184610Salfred			/* just set some valid value */
3005184610Salfred			xfer->aframes = xfer->nframes;
3006184610Salfred		}
3007184610Salfred	}
3008184610Salfred	/* compute actual length */
3009184610Salfred	xfer->actlen = 0;
3010184610Salfred
3011184610Salfred	for (x = 0; x != xfer->aframes; x++) {
3012184610Salfred		xfer->actlen += xfer->frlengths[x];
3013184610Salfred	}
3014184610Salfred
3015184610Salfred	/*
3016184610Salfred	 * Frames that were not transferred get zero actual length in
3017184610Salfred	 * case the USB device driver does not check the actual number
3018184610Salfred	 * of frames transferred, "xfer->aframes":
3019184610Salfred	 */
3020184610Salfred	for (; x < xfer->nframes; x++) {
3021194677Sthompsa		usbd_xfer_set_frame_len(xfer, x, 0);
3022184610Salfred	}
3023184610Salfred
3024184610Salfred	/* check actual length */
3025184610Salfred	if (xfer->actlen > xfer->sumlen) {
3026184610Salfred		if (xfer->error == 0) {
3027184610Salfred			panic("%s: actual length, %d, is greater than "
3028199816Sthompsa			    "initial length, %d\n",
3029184610Salfred			    __FUNCTION__, xfer->actlen, xfer->sumlen);
3030184610Salfred		} else {
3031184610Salfred			/* just set some valid value */
3032184610Salfred			xfer->actlen = xfer->sumlen;
3033184610Salfred		}
3034184610Salfred	}
3035194677Sthompsa	DPRINTFN(1, "xfer=%p endpoint=%p sts=%d alen=%d, slen=%d, afrm=%d, nfrm=%d\n",
3036193644Sthompsa	    xfer, xfer->endpoint, xfer->error, xfer->actlen, xfer->sumlen,
3037184610Salfred	    xfer->aframes, xfer->nframes);
3038184610Salfred
3039184610Salfred	if (xfer->error) {
3040184610Salfred		/* end of control transfer, if any */
3041184610Salfred		xfer->flags_int.control_act = 0;
3042184610Salfred
3043261105Shselasky#if USB_HAVE_TT_SUPPORT
3044261105Shselasky		switch (xfer->error) {
3045261105Shselasky		case USB_ERR_NORMAL_COMPLETION:
3046261105Shselasky		case USB_ERR_SHORT_XFER:
3047261105Shselasky		case USB_ERR_STALLED:
3048261105Shselasky		case USB_ERR_CANCELLED:
3049261105Shselasky			/* nothing to do */
3050261105Shselasky			break;
3051261105Shselasky		default:
3052261105Shselasky			/* try to reset the TT, if any */
3053261105Shselasky			USB_BUS_LOCK(bus);
3054261105Shselasky			uhub_tt_buffer_reset_async_locked(xfer->xroot->udev, xfer->endpoint);
3055261105Shselasky			USB_BUS_UNLOCK(bus);
3056261105Shselasky			break;
3057261105Shselasky		}
3058261105Shselasky#endif
3059184610Salfred		/* check if we should block the execution queue */
3060184610Salfred		if ((xfer->error != USB_ERR_CANCELLED) &&
3061184610Salfred		    (xfer->flags.pipe_bof)) {
3062184610Salfred			DPRINTFN(2, "xfer=%p: Block On Failure "
3063193644Sthompsa			    "on endpoint=%p\n", xfer, xfer->endpoint);
3064184610Salfred			goto done;
3065184610Salfred		}
3066184610Salfred	} else {
3067184610Salfred		/* check for short transfers */
3068184610Salfred		if (xfer->actlen < xfer->sumlen) {
3069184610Salfred
3070184610Salfred			/* end of control transfer, if any */
3071184610Salfred			xfer->flags_int.control_act = 0;
3072184610Salfred
3073184610Salfred			if (!xfer->flags_int.short_xfer_ok) {
3074184610Salfred				xfer->error = USB_ERR_SHORT_XFER;
3075184610Salfred				if (xfer->flags.pipe_bof) {
3076184610Salfred					DPRINTFN(2, "xfer=%p: Block On Failure on "
3077193644Sthompsa					    "Short Transfer on endpoint %p.\n",
3078193644Sthompsa					    xfer, xfer->endpoint);
3079184610Salfred					goto done;
3080184610Salfred				}
3081184610Salfred			}
3082184610Salfred		} else {
3083184610Salfred			/*
3084184610Salfred			 * Check if we are in the middle of a
3085184610Salfred			 * control transfer:
3086184610Salfred			 */
3087184610Salfred			if (xfer->flags_int.control_act) {
3088184610Salfred				DPRINTFN(5, "xfer=%p: Control transfer "
3089193644Sthompsa				    "active on endpoint=%p\n", xfer, xfer->endpoint);
3090184610Salfred				goto done;
3091184610Salfred			}
3092184610Salfred		}
3093184610Salfred	}
3094184610Salfred
3095193644Sthompsa	ep = xfer->endpoint;
3096184610Salfred
3097184610Salfred	/*
3098184610Salfred	 * If the current USB transfer is completing we need to start the
3099184610Salfred	 * next one:
3100184610Salfred	 */
3101213435Shselasky	USB_BUS_LOCK(bus);
3102239214Shselasky	if (ep->endpoint_q[xfer->stream_id].curr == xfer) {
3103239214Shselasky		usb_command_wrapper(&ep->endpoint_q[xfer->stream_id], NULL);
3104184610Salfred
3105239214Shselasky		if (ep->endpoint_q[xfer->stream_id].curr != NULL ||
3106239214Shselasky		    TAILQ_FIRST(&ep->endpoint_q[xfer->stream_id].head) != NULL) {
3107184610Salfred			/* there is another USB transfer waiting */
3108184610Salfred		} else {
3109184610Salfred			/* this is the last USB transfer */
3110184610Salfred			/* clear isochronous sync flag */
3111193644Sthompsa			xfer->endpoint->is_synced = 0;
3112184610Salfred		}
3113184610Salfred	}
3114213435Shselasky	USB_BUS_UNLOCK(bus);
3115184610Salfreddone:
3116184610Salfred	return (0);
3117184610Salfred}
3118184610Salfred
3119184610Salfred/*------------------------------------------------------------------------*
3120194228Sthompsa *	usb_command_wrapper
3121184610Salfred *
3122184610Salfred * This function is used to execute commands non-recursivly on an USB
3123184610Salfred * transfer.
3124184610Salfred *------------------------------------------------------------------------*/
3125184610Salfredvoid
3126194228Sthompsausb_command_wrapper(struct usb_xfer_queue *pq, struct usb_xfer *xfer)
3127184610Salfred{
3128184610Salfred	if (xfer) {
3129184610Salfred		/*
3130184610Salfred		 * If the transfer is not already processing,
3131184610Salfred		 * queue it!
3132184610Salfred		 */
3133184610Salfred		if (pq->curr != xfer) {
3134194228Sthompsa			usbd_transfer_enqueue(pq, xfer);
3135184610Salfred			if (pq->curr != NULL) {
3136184610Salfred				/* something is already processing */
3137184610Salfred				DPRINTFN(6, "busy %p\n", pq->curr);
3138184610Salfred				return;
3139184610Salfred			}
3140184610Salfred		}
3141184610Salfred	} else {
3142184610Salfred		/* Get next element in queue */
3143184610Salfred		pq->curr = NULL;
3144184610Salfred	}
3145184610Salfred
3146184610Salfred	if (!pq->recurse_1) {
3147184610Salfred
3148287274Shselasky		/* clear third recurse flag */
3149287274Shselasky		pq->recurse_3 = 0;
3150287274Shselasky
3151184610Salfred		do {
3152287274Shselasky			/* set two first recurse flags */
3153184610Salfred			pq->recurse_1 = 1;
3154184610Salfred			pq->recurse_2 = 1;
3155184610Salfred
3156184610Salfred			if (pq->curr == NULL) {
3157184610Salfred				xfer = TAILQ_FIRST(&pq->head);
3158184610Salfred				if (xfer) {
3159184610Salfred					TAILQ_REMOVE(&pq->head, xfer,
3160184610Salfred					    wait_entry);
3161184610Salfred					xfer->wait_queue = NULL;
3162184610Salfred					pq->curr = xfer;
3163184610Salfred				} else {
3164184610Salfred					break;
3165184610Salfred				}
3166184610Salfred			}
3167184610Salfred			DPRINTFN(6, "cb %p (enter)\n", pq->curr);
3168184610Salfred			(pq->command) (pq);
3169184610Salfred			DPRINTFN(6, "cb %p (leave)\n", pq->curr);
3170184610Salfred
3171287274Shselasky			/*
3172287274Shselasky			 * Set third recurse flag to indicate
3173287274Shselasky			 * recursion happened:
3174287274Shselasky			 */
3175287274Shselasky			pq->recurse_3 = 1;
3176287274Shselasky
3177184610Salfred		} while (!pq->recurse_2);
3178184610Salfred
3179184610Salfred		/* clear first recurse flag */
3180184610Salfred		pq->recurse_1 = 0;
3181184610Salfred
3182184610Salfred	} else {
3183184610Salfred		/* clear second recurse flag */
3184184610Salfred		pq->recurse_2 = 0;
3185184610Salfred	}
3186184610Salfred}
3187184610Salfred
3188184610Salfred/*------------------------------------------------------------------------*
3189207080Sthompsa *	usbd_ctrl_transfer_setup
3190184610Salfred *
3191184610Salfred * This function is used to setup the default USB control endpoint
3192184610Salfred * transfer.
3193184610Salfred *------------------------------------------------------------------------*/
3194184610Salfredvoid
3195207080Sthompsausbd_ctrl_transfer_setup(struct usb_device *udev)
3196184610Salfred{
3197192984Sthompsa	struct usb_xfer *xfer;
3198184610Salfred	uint8_t no_resetup;
3199184610Salfred	uint8_t iface_index;
3200184610Salfred
3201190735Sthompsa	/* check for root HUB */
3202190735Sthompsa	if (udev->parent_hub == NULL)
3203190735Sthompsa		return;
3204184610Salfredrepeat:
3205184610Salfred
3206207080Sthompsa	xfer = udev->ctrl_xfer[0];
3207184610Salfred	if (xfer) {
3208184824Sthompsa		USB_XFER_LOCK(xfer);
3209184610Salfred		no_resetup =
3210184610Salfred		    ((xfer->address == udev->address) &&
3211207080Sthompsa		    (udev->ctrl_ep_desc.wMaxPacketSize[0] ==
3212184610Salfred		    udev->ddesc.bMaxPacketSize));
3213192499Sthompsa		if (udev->flags.usb_mode == USB_MODE_DEVICE) {
3214184610Salfred			if (no_resetup) {
3215184610Salfred				/*
3216184610Salfred				 * NOTE: checking "xfer->address" and
3217184610Salfred				 * starting the USB transfer must be
3218184610Salfred				 * atomic!
3219184610Salfred				 */
3220194228Sthompsa				usbd_transfer_start(xfer);
3221184610Salfred			}
3222184610Salfred		}
3223184824Sthompsa		USB_XFER_UNLOCK(xfer);
3224184610Salfred	} else {
3225184610Salfred		no_resetup = 0;
3226184610Salfred	}
3227184610Salfred
3228184610Salfred	if (no_resetup) {
3229184610Salfred		/*
3230184610Salfred	         * All parameters are exactly the same like before.
3231184610Salfred	         * Just return.
3232184610Salfred	         */
3233184610Salfred		return;
3234184610Salfred	}
3235184610Salfred	/*
3236184610Salfred	 * Update wMaxPacketSize for the default control endpoint:
3237184610Salfred	 */
3238207080Sthompsa	udev->ctrl_ep_desc.wMaxPacketSize[0] =
3239184610Salfred	    udev->ddesc.bMaxPacketSize;
3240184610Salfred
3241184610Salfred	/*
3242184610Salfred	 * Unsetup any existing USB transfer:
3243184610Salfred	 */
3244207080Sthompsa	usbd_transfer_unsetup(udev->ctrl_xfer, USB_CTRL_XFER_MAX);
3245184610Salfred
3246184610Salfred	/*
3247222790Shselasky	 * Reset clear stall error counter.
3248222790Shselasky	 */
3249222790Shselasky	udev->clear_stall_errors = 0;
3250222790Shselasky
3251222790Shselasky	/*
3252184610Salfred	 * Try to setup a new USB transfer for the
3253184610Salfred	 * default control endpoint:
3254184610Salfred	 */
3255184610Salfred	iface_index = 0;
3256194228Sthompsa	if (usbd_transfer_setup(udev, &iface_index,
3257353179Shselasky	    udev->ctrl_xfer, udev->bus->control_ep_quirk ?
3258353179Shselasky	    usb_control_ep_quirk_cfg : usb_control_ep_cfg, USB_CTRL_XFER_MAX, NULL,
3259207079Sthompsa	    &udev->device_mtx)) {
3260184610Salfred		DPRINTFN(0, "could not setup default "
3261199816Sthompsa		    "USB transfer\n");
3262184610Salfred	} else {
3263184610Salfred		goto repeat;
3264184610Salfred	}
3265184610Salfred}
3266184610Salfred
3267184610Salfred/*------------------------------------------------------------------------*
3268194228Sthompsa *	usbd_clear_data_toggle - factored out code
3269184610Salfred *
3270184610Salfred * NOTE: the intention of this function is not to reset the hardware
3271184610Salfred * data toggle.
3272184610Salfred *------------------------------------------------------------------------*/
3273184610Salfredvoid
3274213435Shselaskyusbd_clear_stall_locked(struct usb_device *udev, struct usb_endpoint *ep)
3275213435Shselasky{
3276213435Shselasky	USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
3277213435Shselasky
3278213435Shselasky	/* check that we have a valid case */
3279213435Shselasky	if (udev->flags.usb_mode == USB_MODE_HOST &&
3280213435Shselasky	    udev->parent_hub != NULL &&
3281213435Shselasky	    udev->bus->methods->clear_stall != NULL &&
3282213435Shselasky	    ep->methods != NULL) {
3283213435Shselasky		(udev->bus->methods->clear_stall) (udev, ep);
3284213435Shselasky	}
3285213435Shselasky}
3286213435Shselasky
3287213435Shselasky/*------------------------------------------------------------------------*
3288213435Shselasky *	usbd_clear_data_toggle - factored out code
3289213435Shselasky *
3290213435Shselasky * NOTE: the intention of this function is not to reset the hardware
3291213435Shselasky * data toggle on the USB device side.
3292213435Shselasky *------------------------------------------------------------------------*/
3293213435Shselaskyvoid
3294194228Sthompsausbd_clear_data_toggle(struct usb_device *udev, struct usb_endpoint *ep)
3295184610Salfred{
3296193644Sthompsa	DPRINTFN(5, "udev=%p endpoint=%p\n", udev, ep);
3297184610Salfred
3298184824Sthompsa	USB_BUS_LOCK(udev->bus);
3299193644Sthompsa	ep->toggle_next = 0;
3300213435Shselasky	/* some hardware needs a callback to clear the data toggle */
3301213435Shselasky	usbd_clear_stall_locked(udev, ep);
3302184824Sthompsa	USB_BUS_UNLOCK(udev->bus);
3303184610Salfred}
3304184610Salfred
3305184610Salfred/*------------------------------------------------------------------------*
3306194228Sthompsa *	usbd_clear_stall_callback - factored out clear stall callback
3307184610Salfred *
3308184610Salfred * Input parameters:
3309184610Salfred *  xfer1: Clear Stall Control Transfer
3310184610Salfred *  xfer2: Stalled USB Transfer
3311184610Salfred *
3312184610Salfred * This function is NULL safe.
3313184610Salfred *
3314184610Salfred * Return values:
3315184610Salfred *   0: In progress
3316184610Salfred *   Else: Finished
3317184610Salfred *
3318184610Salfred * Clear stall config example:
3319184610Salfred *
3320192984Sthompsa * static const struct usb_config my_clearstall =  {
3321184610Salfred *	.type = UE_CONTROL,
3322184610Salfred *	.endpoint = 0,
3323184610Salfred *	.direction = UE_DIR_ANY,
3324184610Salfred *	.interval = 50, //50 milliseconds
3325192984Sthompsa *	.bufsize = sizeof(struct usb_device_request),
3326190734Sthompsa *	.timeout = 1000, //1.000 seconds
3327190734Sthompsa *	.callback = &my_clear_stall_callback, // **
3328190734Sthompsa *	.usb_mode = USB_MODE_HOST,
3329184610Salfred * };
3330184610Salfred *
3331194228Sthompsa * ** "my_clear_stall_callback" calls "usbd_clear_stall_callback"
3332184610Salfred * passing the correct parameters.
3333184610Salfred *------------------------------------------------------------------------*/
3334184610Salfreduint8_t
3335194228Sthompsausbd_clear_stall_callback(struct usb_xfer *xfer1,
3336192984Sthompsa    struct usb_xfer *xfer2)
3337184610Salfred{
3338192984Sthompsa	struct usb_device_request req;
3339184610Salfred
3340184610Salfred	if (xfer2 == NULL) {
3341184610Salfred		/* looks like we are tearing down */
3342184610Salfred		DPRINTF("NULL input parameter\n");
3343184610Salfred		return (0);
3344184610Salfred	}
3345184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer1, MA_OWNED);
3346184824Sthompsa	USB_XFER_LOCK_ASSERT(xfer2, MA_OWNED);
3347184610Salfred
3348184610Salfred	switch (USB_GET_STATE(xfer1)) {
3349184610Salfred	case USB_ST_SETUP:
3350184610Salfred
3351184610Salfred		/*
3352184610Salfred		 * pre-clear the data toggle to DATA0 ("umass.c" and
3353184610Salfred		 * "ata-usb.c" depends on this)
3354184610Salfred		 */
3355184610Salfred
3356194228Sthompsa		usbd_clear_data_toggle(xfer2->xroot->udev, xfer2->endpoint);
3357184610Salfred
3358184610Salfred		/* setup a clear-stall packet */
3359184610Salfred
3360184610Salfred		req.bmRequestType = UT_WRITE_ENDPOINT;
3361184610Salfred		req.bRequest = UR_CLEAR_FEATURE;
3362184610Salfred		USETW(req.wValue, UF_ENDPOINT_HALT);
3363193644Sthompsa		req.wIndex[0] = xfer2->endpoint->edesc->bEndpointAddress;
3364184610Salfred		req.wIndex[1] = 0;
3365184610Salfred		USETW(req.wLength, 0);
3366184610Salfred
3367184610Salfred		/*
3368194228Sthompsa		 * "usbd_transfer_setup_sub()" will ensure that
3369184610Salfred		 * we have sufficient room in the buffer for
3370184610Salfred		 * the request structure!
3371184610Salfred		 */
3372184610Salfred
3373184610Salfred		/* copy in the transfer */
3374184610Salfred
3375194228Sthompsa		usbd_copy_in(xfer1->frbuffers, 0, &req, sizeof(req));
3376184610Salfred
3377184610Salfred		/* set length */
3378184610Salfred		xfer1->frlengths[0] = sizeof(req);
3379184610Salfred		xfer1->nframes = 1;
3380184610Salfred
3381194228Sthompsa		usbd_transfer_submit(xfer1);
3382184610Salfred		return (0);
3383184610Salfred
3384184610Salfred	case USB_ST_TRANSFERRED:
3385184610Salfred		break;
3386184610Salfred
3387184610Salfred	default:			/* Error */
3388184610Salfred		if (xfer1->error == USB_ERR_CANCELLED) {
3389184610Salfred			return (0);
3390184610Salfred		}
3391184610Salfred		break;
3392184610Salfred	}
3393184610Salfred	return (1);			/* Clear Stall Finished */
3394184610Salfred}
3395184610Salfred
3396195960Salfred/*------------------------------------------------------------------------*
3397195960Salfred *	usbd_transfer_poll
3398195960Salfred *
3399195960Salfred * The following function gets called from the USB keyboard driver and
3400195960Salfred * UMASS when the system has paniced.
3401195960Salfred *
3402195960Salfred * NOTE: It is currently not possible to resume normal operation on
3403195960Salfred * the USB controller which has been polled, due to clearing of the
3404195960Salfred * "up_dsleep" and "up_msleep" flags.
3405195960Salfred *------------------------------------------------------------------------*/
3406184610Salfredvoid
3407194677Sthompsausbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
3408184610Salfred{
3409195960Salfred	struct usb_xfer *xfer;
3410195960Salfred	struct usb_xfer_root *xroot;
3411195960Salfred	struct usb_device *udev;
3412195960Salfred	struct usb_proc_msg *pm;
3413195960Salfred	uint16_t n;
3414195960Salfred	uint16_t drop_bus;
3415195960Salfred	uint16_t drop_xfer;
3416195960Salfred
3417195960Salfred	for (n = 0; n != max; n++) {
3418195960Salfred		/* Extra checks to avoid panic */
3419195960Salfred		xfer = ppxfer[n];
3420195960Salfred		if (xfer == NULL)
3421195960Salfred			continue;	/* no USB transfer */
3422195960Salfred		xroot = xfer->xroot;
3423195960Salfred		if (xroot == NULL)
3424195960Salfred			continue;	/* no USB root */
3425195960Salfred		udev = xroot->udev;
3426195960Salfred		if (udev == NULL)
3427195960Salfred			continue;	/* no USB device */
3428195960Salfred		if (udev->bus == NULL)
3429195960Salfred			continue;	/* no BUS structure */
3430195960Salfred		if (udev->bus->methods == NULL)
3431195960Salfred			continue;	/* no BUS methods */
3432195960Salfred		if (udev->bus->methods->xfer_poll == NULL)
3433195960Salfred			continue;	/* no poll method */
3434195960Salfred
3435195960Salfred		/* make sure that the BUS mutex is not locked */
3436195960Salfred		drop_bus = 0;
3437228760Savg		while (mtx_owned(&xroot->udev->bus->bus_mtx) && !SCHEDULER_STOPPED()) {
3438195960Salfred			mtx_unlock(&xroot->udev->bus->bus_mtx);
3439195960Salfred			drop_bus++;
3440195960Salfred		}
3441195960Salfred
3442195960Salfred		/* make sure that the transfer mutex is not locked */
3443195960Salfred		drop_xfer = 0;
3444228760Savg		while (mtx_owned(xroot->xfer_mtx) && !SCHEDULER_STOPPED()) {
3445195960Salfred			mtx_unlock(xroot->xfer_mtx);
3446195960Salfred			drop_xfer++;
3447195960Salfred		}
3448195960Salfred
3449195960Salfred		/* Make sure cv_signal() and cv_broadcast() is not called */
3450246363Shselasky		USB_BUS_CONTROL_XFER_PROC(udev->bus)->up_msleep = 0;
3451246363Shselasky		USB_BUS_EXPLORE_PROC(udev->bus)->up_msleep = 0;
3452246363Shselasky		USB_BUS_GIANT_PROC(udev->bus)->up_msleep = 0;
3453287274Shselasky		USB_BUS_NON_GIANT_ISOC_PROC(udev->bus)->up_msleep = 0;
3454287274Shselasky		USB_BUS_NON_GIANT_BULK_PROC(udev->bus)->up_msleep = 0;
3455195960Salfred
3456195960Salfred		/* poll USB hardware */
3457195960Salfred		(udev->bus->methods->xfer_poll) (udev->bus);
3458195960Salfred
3459195960Salfred		USB_BUS_LOCK(xroot->bus);
3460195960Salfred
3461195960Salfred		/* check for clear stall */
3462207080Sthompsa		if (udev->ctrl_xfer[1] != NULL) {
3463195960Salfred
3464195960Salfred			/* poll clear stall start */
3465195960Salfred			pm = &udev->cs_msg[0].hdr;
3466195960Salfred			(pm->pm_callback) (pm);
3467195960Salfred			/* poll clear stall done thread */
3468207080Sthompsa			pm = &udev->ctrl_xfer[1]->
3469195960Salfred			    xroot->done_m[0].hdr;
3470195960Salfred			(pm->pm_callback) (pm);
3471195960Salfred		}
3472195960Salfred
3473195960Salfred		/* poll done thread */
3474195960Salfred		pm = &xroot->done_m[0].hdr;
3475195960Salfred		(pm->pm_callback) (pm);
3476195960Salfred
3477195960Salfred		USB_BUS_UNLOCK(xroot->bus);
3478195960Salfred
3479195960Salfred		/* restore transfer mutex */
3480195960Salfred		while (drop_xfer--)
3481195960Salfred			mtx_lock(xroot->xfer_mtx);
3482195960Salfred
3483195960Salfred		/* restore BUS mutex */
3484195960Salfred		while (drop_bus--)
3485195960Salfred			mtx_lock(&xroot->udev->bus->bus_mtx);
3486184610Salfred	}
3487184610Salfred}
3488190734Sthompsa
3489190734Sthompsastatic void
3490194228Sthompsausbd_get_std_packet_size(struct usb_std_packet_size *ptr,
3491192500Sthompsa    uint8_t type, enum usb_dev_speed speed)
3492190734Sthompsa{
3493190734Sthompsa	static const uint16_t intr_range_max[USB_SPEED_MAX] = {
3494190734Sthompsa		[USB_SPEED_LOW] = 8,
3495190734Sthompsa		[USB_SPEED_FULL] = 64,
3496190734Sthompsa		[USB_SPEED_HIGH] = 1024,
3497190734Sthompsa		[USB_SPEED_VARIABLE] = 1024,
3498190734Sthompsa		[USB_SPEED_SUPER] = 1024,
3499190734Sthompsa	};
3500190734Sthompsa
3501190734Sthompsa	static const uint16_t isoc_range_max[USB_SPEED_MAX] = {
3502190734Sthompsa		[USB_SPEED_LOW] = 0,	/* invalid */
3503190734Sthompsa		[USB_SPEED_FULL] = 1023,
3504190734Sthompsa		[USB_SPEED_HIGH] = 1024,
3505190734Sthompsa		[USB_SPEED_VARIABLE] = 3584,
3506190734Sthompsa		[USB_SPEED_SUPER] = 1024,
3507190734Sthompsa	};
3508190734Sthompsa
3509190734Sthompsa	static const uint16_t control_min[USB_SPEED_MAX] = {
3510190734Sthompsa		[USB_SPEED_LOW] = 8,
3511190734Sthompsa		[USB_SPEED_FULL] = 8,
3512190734Sthompsa		[USB_SPEED_HIGH] = 64,
3513190734Sthompsa		[USB_SPEED_VARIABLE] = 512,
3514190734Sthompsa		[USB_SPEED_SUPER] = 512,
3515190734Sthompsa	};
3516190734Sthompsa
3517190734Sthompsa	static const uint16_t bulk_min[USB_SPEED_MAX] = {
3518209443Sthompsa		[USB_SPEED_LOW] = 8,
3519190734Sthompsa		[USB_SPEED_FULL] = 8,
3520190734Sthompsa		[USB_SPEED_HIGH] = 512,
3521190734Sthompsa		[USB_SPEED_VARIABLE] = 512,
3522190734Sthompsa		[USB_SPEED_SUPER] = 1024,
3523190734Sthompsa	};
3524190734Sthompsa
3525190734Sthompsa	uint16_t temp;
3526190734Sthompsa
3527190734Sthompsa	memset(ptr, 0, sizeof(*ptr));
3528190734Sthompsa
3529190734Sthompsa	switch (type) {
3530190734Sthompsa	case UE_INTERRUPT:
3531192500Sthompsa		ptr->range.max = intr_range_max[speed];
3532190734Sthompsa		break;
3533190734Sthompsa	case UE_ISOCHRONOUS:
3534192500Sthompsa		ptr->range.max = isoc_range_max[speed];
3535190734Sthompsa		break;
3536190734Sthompsa	default:
3537190734Sthompsa		if (type == UE_BULK)
3538192500Sthompsa			temp = bulk_min[speed];
3539190734Sthompsa		else /* UE_CONTROL */
3540192500Sthompsa			temp = control_min[speed];
3541190734Sthompsa
3542190734Sthompsa		/* default is fixed */
3543190734Sthompsa		ptr->fixed[0] = temp;
3544190734Sthompsa		ptr->fixed[1] = temp;
3545190734Sthompsa		ptr->fixed[2] = temp;
3546190734Sthompsa		ptr->fixed[3] = temp;
3547190734Sthompsa
3548192500Sthompsa		if (speed == USB_SPEED_FULL) {
3549190734Sthompsa			/* multiple sizes */
3550190734Sthompsa			ptr->fixed[1] = 16;
3551190734Sthompsa			ptr->fixed[2] = 32;
3552190734Sthompsa			ptr->fixed[3] = 64;
3553190734Sthompsa		}
3554192500Sthompsa		if ((speed == USB_SPEED_VARIABLE) &&
3555190734Sthompsa		    (type == UE_BULK)) {
3556190734Sthompsa			/* multiple sizes */
3557190734Sthompsa			ptr->fixed[2] = 1024;
3558190734Sthompsa			ptr->fixed[3] = 1536;
3559190734Sthompsa		}
3560190734Sthompsa		break;
3561190734Sthompsa	}
3562190734Sthompsa}
3563194677Sthompsa
3564194677Sthompsavoid	*
3565194677Sthompsausbd_xfer_softc(struct usb_xfer *xfer)
3566194677Sthompsa{
3567194677Sthompsa	return (xfer->priv_sc);
3568194677Sthompsa}
3569194677Sthompsa
3570194677Sthompsavoid *
3571194677Sthompsausbd_xfer_get_priv(struct usb_xfer *xfer)
3572194677Sthompsa{
3573194677Sthompsa	return (xfer->priv_fifo);
3574194677Sthompsa}
3575194677Sthompsa
3576194677Sthompsavoid
3577194677Sthompsausbd_xfer_set_priv(struct usb_xfer *xfer, void *ptr)
3578194677Sthompsa{
3579194677Sthompsa	xfer->priv_fifo = ptr;
3580194677Sthompsa}
3581194677Sthompsa
3582194677Sthompsauint8_t
3583194677Sthompsausbd_xfer_state(struct usb_xfer *xfer)
3584194677Sthompsa{
3585194677Sthompsa	return (xfer->usb_state);
3586194677Sthompsa}
3587194677Sthompsa
3588194677Sthompsavoid
3589194677Sthompsausbd_xfer_set_flag(struct usb_xfer *xfer, int flag)
3590194677Sthompsa{
3591194677Sthompsa	switch (flag) {
3592194677Sthompsa		case USB_FORCE_SHORT_XFER:
3593194677Sthompsa			xfer->flags.force_short_xfer = 1;
3594194677Sthompsa			break;
3595194677Sthompsa		case USB_SHORT_XFER_OK:
3596194677Sthompsa			xfer->flags.short_xfer_ok = 1;
3597194677Sthompsa			break;
3598195121Sthompsa		case USB_MULTI_SHORT_OK:
3599195121Sthompsa			xfer->flags.short_frames_ok = 1;
3600195121Sthompsa			break;
3601195121Sthompsa		case USB_MANUAL_STATUS:
3602195121Sthompsa			xfer->flags.manual_status = 1;
3603195121Sthompsa			break;
3604194677Sthompsa	}
3605194677Sthompsa}
3606194677Sthompsa
3607194677Sthompsavoid
3608194677Sthompsausbd_xfer_clr_flag(struct usb_xfer *xfer, int flag)
3609194677Sthompsa{
3610194677Sthompsa	switch (flag) {
3611194677Sthompsa		case USB_FORCE_SHORT_XFER:
3612194677Sthompsa			xfer->flags.force_short_xfer = 0;
3613194677Sthompsa			break;
3614194677Sthompsa		case USB_SHORT_XFER_OK:
3615194677Sthompsa			xfer->flags.short_xfer_ok = 0;
3616194677Sthompsa			break;
3617195121Sthompsa		case USB_MULTI_SHORT_OK:
3618195121Sthompsa			xfer->flags.short_frames_ok = 0;
3619195121Sthompsa			break;
3620195121Sthompsa		case USB_MANUAL_STATUS:
3621195121Sthompsa			xfer->flags.manual_status = 0;
3622195121Sthompsa			break;
3623194677Sthompsa	}
3624194677Sthompsa}
3625195121Sthompsa
3626195121Sthompsa/*
3627195121Sthompsa * The following function returns in milliseconds when the isochronous
3628195121Sthompsa * transfer was completed by the hardware. The returned value wraps
3629195121Sthompsa * around 65536 milliseconds.
3630195121Sthompsa */
3631195121Sthompsauint16_t
3632195121Sthompsausbd_xfer_get_timestamp(struct usb_xfer *xfer)
3633195121Sthompsa{
3634195121Sthompsa	return (xfer->isoc_time_complete);
3635195121Sthompsa}
3636263643Shselasky
3637263643Shselasky/*
3638263643Shselasky * The following function returns non-zero if the max packet size
3639263643Shselasky * field was clamped to a valid value. Else it returns zero.
3640263643Shselasky */
3641263643Shselaskyuint8_t
3642263643Shselaskyusbd_xfer_maxp_was_clamped(struct usb_xfer *xfer)
3643263643Shselasky{
3644263643Shselasky	return (xfer->flags_int.maxp_was_clamped);
3645263643Shselasky}
3646