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