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