199767f8919635c4928607450d9e0abb932109ceToomas Soome/* $FreeBSD$ */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*-
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Redistribution and use in source and binary forms, with or without
199767f8919635c4928607450d9e0abb932109ceToomas Soome * modification, are permitted provided that the following conditions
199767f8919635c4928607450d9e0abb932109ceToomas Soome * are met:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 1. Redistributions of source code must retain the above copyright
199767f8919635c4928607450d9e0abb932109ceToomas Soome * notice, this list of conditions and the following disclaimer.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
199767f8919635c4928607450d9e0abb932109ceToomas Soome * notice, this list of conditions and the following disclaimer in the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * documentation and/or other materials provided with the distribution.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
199767f8919635c4928607450d9e0abb932109ceToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
199767f8919635c4928607450d9e0abb932109ceToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
199767f8919635c4928607450d9e0abb932109ceToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
199767f8919635c4928607450d9e0abb932109ceToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
199767f8919635c4928607450d9e0abb932109ceToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
199767f8919635c4928607450d9e0abb932109ceToomas Soome * SUCH DAMAGE.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <bsd_global.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if USB_HAVE_BUSDMA
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void usb_pc_common_mem_cb(struct usb_page_cache *pc,
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *vaddr, uint32_t length);
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usbd_get_page - lookup DMA-able memory for the given offset
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * NOTE: Only call this function when the "page_cache" structure has
199767f8919635c4928607450d9e0abb932109ceToomas Soome * been properly initialized !
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusbd_get_page(struct usb_page_cache *pc, usb_frlength_t offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_page_search *res)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if USB_HAVE_BUSDMA
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_page *page;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (pc->page_start) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Case 1 - something has been loaded into DMA */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (pc->buffer) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Case 1a - Kernel Virtual Address */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->buffer = USB_ADD_BYTES(pc->buffer, offset);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome offset += pc->page_offset_buf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* compute destination page */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome page = pc->page_start;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (pc->ismultiseg) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome page += (offset / USB_PAGE_SIZE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome offset %= USB_PAGE_SIZE;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->length = USB_PAGE_SIZE - offset;
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->physaddr = page->physaddr + offset;
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->length = (usb_size_t)-1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->physaddr = page->physaddr + offset;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!pc->buffer) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Case 1b - Non Kernel Virtual Address */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->buffer = USB_ADD_BYTES(page->buffer, offset);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Case 2 - Plain PIO */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->buffer = USB_ADD_BYTES(pc->buffer, offset);
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->length = (usb_size_t)-1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if USB_HAVE_BUSDMA
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->physaddr = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usbd_copy_in - copy directly to DMA-able memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome const void *ptr, usb_frlength_t len)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_page_search buf_res;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (len != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome usbd_get_page(cache, offset, &buf_res);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (buf_res.length > len) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf_res.length = len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome memcpy(buf_res.buffer, ptr, buf_res.length);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome offset += buf_res.length;
199767f8919635c4928607450d9e0abb932109ceToomas Soome len -= buf_res.length;
199767f8919635c4928607450d9e0abb932109ceToomas Soome ptr = USB_ADD_BYTES(ptr, buf_res.length);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usbd_copy_out - copy directly from DMA-able memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *ptr, usb_frlength_t len)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_page_search res;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (len != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome usbd_get_page(cache, offset, &res);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (res.length > len) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome res.length = len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome memcpy(ptr, res.buffer, res.length);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome offset += res.length;
199767f8919635c4928607450d9e0abb932109ceToomas Soome len -= res.length;
199767f8919635c4928607450d9e0abb932109ceToomas Soome ptr = USB_ADD_BYTES(ptr, res.length);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usbd_frame_zero - zero DMA-able memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_frlength_t len)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_page_search res;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (len != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome usbd_get_page(cache, offset, &res);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (res.length > len) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome res.length = len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome memset(res.buffer, 0, res.length);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome offset += res.length;
199767f8919635c4928607450d9e0abb932109ceToomas Soome len -= res.length;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if USB_HAVE_BUSDMA
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_common_mem_cb - BUS-DMA callback function
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_common_mem_cb(struct usb_page_cache *pc,
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *vaddr, uint32_t length)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_page *pg;
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_size_t rem;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bus_size_t off;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bus_addr_t phys = (uintptr_t)vaddr; /* XXX */
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint32_t nseg;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (length == 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome nseg = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome else
199767f8919635c4928607450d9e0abb932109ceToomas Soome nseg = ((length + USB_PAGE_SIZE - 1) / USB_PAGE_SIZE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg = pc->page_start;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg->physaddr = phys & ~(USB_PAGE_SIZE - 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome rem = phys & (USB_PAGE_SIZE - 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->page_offset_buf = rem;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->page_offset_end += rem;
199767f8919635c4928607450d9e0abb932109ceToomas Soome length += rem;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (off = USB_PAGE_SIZE; off < length; off += USB_PAGE_SIZE) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg->physaddr = (phys + off) & ~(USB_PAGE_SIZE - 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_alloc_mem - allocate DMA'able memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Returns:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 0: Success
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Else: Failure
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeuint8_t
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg,
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_size_t size, usb_size_t align)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *ptr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint32_t rem;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* allocate zeroed memory */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (align != 1) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome ptr = malloc(size + align, XXX, XXX);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ptr == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto error;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome rem = (-((uintptr_t)ptr)) & (align - 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome ptr = malloc(size, XXX, XXX);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ptr == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto error;
199767f8919635c4928607450d9e0abb932109ceToomas Soome rem = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* setup page cache */
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->buffer = ((uint8_t *)ptr) + rem;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->page_start = pg;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->page_offset_buf = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->page_offset_end = size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->map = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->tag = ptr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->ismultiseg = (align == 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* compute physical address */
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_pc_common_mem_cb(pc, pc->buffer, size);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_pc_cpu_flush(pc);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomeerror:
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* reset most of the page cache */
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->buffer = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->page_start = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->page_offset_buf = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->page_offset_end = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->map = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->tag = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_free_mem - free DMA memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function is NULL safe.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_free_mem(struct usb_page_cache *pc)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (pc != NULL && pc->buffer != NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(pc->tag, XXX);
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->buffer = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_load_mem - load virtual memory into DMA
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Return values:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 0: Success
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Else: Error
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeuint8_t
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size, uint8_t sync)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* setup page cache */
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->page_offset_buf = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->page_offset_end = size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->ismultiseg = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome mtx_assert(pc->tag_parent->mtx, MA_OWNED);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (size > 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* compute physical address */
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_pc_common_mem_cb(pc, pc->buffer, size);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (sync == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Call callback so that refcount is decremented
199767f8919635c4928607450d9e0abb932109ceToomas Soome * properly:
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc->tag_parent->dma_error = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome (pc->tag_parent->func) (pc->tag_parent);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_cpu_invalidate - invalidate CPU cache
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_cpu_invalidate(struct usb_page_cache *pc)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (pc->page_offset_end == pc->page_offset_buf) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* nothing has been loaded into this page cache! */
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* NOP */
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_cpu_flush - flush CPU cache
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_cpu_flush(struct usb_page_cache *pc)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (pc->page_offset_end == pc->page_offset_buf) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* nothing has been loaded into this page cache! */
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* NOP */
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_dmamap_create - create a DMA map
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Returns:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 0: Success
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Else: Failure
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeuint8_t
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_dmamap_create(struct usb_page_cache *pc, usb_size_t size)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0); /* NOP, success */
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_dmamap_destroy
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function is NULL safe.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_dmamap_destroy(struct usb_page_cache *pc)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* NOP */
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_dma_tag_setup - initialise USB DMA tags
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_dma_tag_setup(struct usb_dma_parent_tag *udpt,
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_dma_tag *udt, bus_dma_tag_t dmat,
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct mtx *mtx, usb_dma_callback_t *func,
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint8_t ndmabits, uint8_t nudt)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome memset(udpt, 0, sizeof(*udpt));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* sanity checking */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((nudt == 0) ||
199767f8919635c4928607450d9e0abb932109ceToomas Soome (ndmabits == 0) ||
199767f8919635c4928607450d9e0abb932109ceToomas Soome (mtx == NULL)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* something is corrupt */
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* initialise condition variable */
199767f8919635c4928607450d9e0abb932109ceToomas Soome cv_init(udpt->cv, "USB DMA CV");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* store some information */
199767f8919635c4928607450d9e0abb932109ceToomas Soome udpt->mtx = mtx;
199767f8919635c4928607450d9e0abb932109ceToomas Soome udpt->func = func;
199767f8919635c4928607450d9e0abb932109ceToomas Soome udpt->tag = dmat;
199767f8919635c4928607450d9e0abb932109ceToomas Soome udpt->utag_first = udt;
199767f8919635c4928607450d9e0abb932109ceToomas Soome udpt->utag_max = nudt;
199767f8919635c4928607450d9e0abb932109ceToomas Soome udpt->dma_bits = ndmabits;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (nudt--) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome memset(udt, 0, sizeof(*udt));
199767f8919635c4928607450d9e0abb932109ceToomas Soome udt->tag_parent = udpt;
199767f8919635c4928607450d9e0abb932109ceToomas Soome udt++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_bus_tag_unsetup - factored out code
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_dma_tag_unsetup(struct usb_dma_parent_tag *udpt)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_dma_tag *udt;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint8_t nudt;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome udt = udpt->utag_first;
199767f8919635c4928607450d9e0abb932109ceToomas Soome nudt = udpt->utag_max;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (nudt--) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome udt->align = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome udt++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (udpt->utag_max) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* destroy the condition variable */
199767f8919635c4928607450d9e0abb932109ceToomas Soome cv_destroy(udpt->cv);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_bdma_work_loop
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function handles loading of virtual buffers into DMA and is
199767f8919635c4928607450d9e0abb932109ceToomas Soome * only called when "dma_refcount" is zero.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_bdma_work_loop(struct usb_xfer_queue *pq)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_xfer_root *info;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_xfer *xfer;
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_frcount_t nframes;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome xfer = pq->curr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome info = xfer->xroot;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome mtx_assert(info->xfer_mtx, MA_OWNED);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (xfer->error) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* some error happened */
199767f8919635c4928607450d9e0abb932109ceToomas Soome USB_BUS_LOCK(info->bus);
199767f8919635c4928607450d9e0abb932109ceToomas Soome usbd_transfer_done(xfer, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome USB_BUS_UNLOCK(info->bus);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!xfer->flags_int.bdma_setup) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_page *pg;
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_frlength_t frlength_0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint8_t isread;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome xfer->flags_int.bdma_setup = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* reset BUS-DMA load state */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome info->dma_error = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (xfer->flags_int.isochronous_xfr) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* only one frame buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nframes = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome frlength_0 = xfer->sumlen;
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* can be multiple frame buffers */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nframes = xfer->nframes;
199767f8919635c4928607450d9e0abb932109ceToomas Soome frlength_0 = xfer->frlengths[0];
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Set DMA direction first. This is needed to
199767f8919635c4928607450d9e0abb932109ceToomas Soome * select the correct cache invalidate and cache
199767f8919635c4928607450d9e0abb932109ceToomas Soome * flush operations.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome isread = USB_GET_DATA_ISREAD(xfer);
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg = xfer->dma_page_ptr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (xfer->flags_int.control_xfr &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome xfer->flags_int.control_hdr) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* special case */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* The device controller writes to memory */
199767f8919635c4928607450d9e0abb932109ceToomas Soome xfer->frbuffers[0].isread = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* The host controller reads from memory */
199767f8919635c4928607450d9e0abb932109ceToomas Soome xfer->frbuffers[0].isread = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* default case */
199767f8919635c4928607450d9e0abb932109ceToomas Soome xfer->frbuffers[0].isread = isread;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Setup the "page_start" pointer which points to an array of
199767f8919635c4928607450d9e0abb932109ceToomas Soome * USB pages where information about the physical address of a
199767f8919635c4928607450d9e0abb932109ceToomas Soome * page will be stored. Also initialise the "isread" field of
199767f8919635c4928607450d9e0abb932109ceToomas Soome * the USB page caches.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome xfer->frbuffers[0].page_start = pg;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome info->dma_nframes = nframes;
199767f8919635c4928607450d9e0abb932109ceToomas Soome info->dma_currframe = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome info->dma_frlength_0 = frlength_0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg += (frlength_0 / USB_PAGE_SIZE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg += 2;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (--nframes > 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome xfer->frbuffers[nframes].isread = isread;
199767f8919635c4928607450d9e0abb932109ceToomas Soome xfer->frbuffers[nframes].page_start = pg;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg += (xfer->frlengths[nframes] / USB_PAGE_SIZE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg += 2;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (info->dma_error) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome USB_BUS_LOCK(info->bus);
199767f8919635c4928607450d9e0abb932109ceToomas Soome usbd_transfer_done(xfer, USB_ERR_DMA_LOAD_FAILED);
199767f8919635c4928607450d9e0abb932109ceToomas Soome USB_BUS_UNLOCK(info->bus);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (info->dma_currframe != info->dma_nframes) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (info->dma_currframe == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* special case */
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_pc_load_mem(xfer->frbuffers,
199767f8919635c4928607450d9e0abb932109ceToomas Soome info->dma_frlength_0, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* default case */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nframes = info->dma_currframe;
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_pc_load_mem(xfer->frbuffers + nframes,
199767f8919635c4928607450d9e0abb932109ceToomas Soome xfer->frlengths[nframes], 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* advance frame index */
199767f8919635c4928607450d9e0abb932109ceToomas Soome info->dma_currframe++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* go ahead */
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_bdma_pre_sync(xfer);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* start loading next USB transfer, if any */
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_command_wrapper(pq, NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* finally start the hardware */
199767f8919635c4928607450d9e0abb932109ceToomas Soome usbd_pipe_enter(xfer);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_bdma_done_event
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function is called when the BUS-DMA has loaded virtual memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome * into DMA, if any.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_bdma_done_event(struct usb_dma_parent_tag *udpt)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_xfer_root *info;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome info = USB_DMATAG_TO_XROOT(udpt);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome mtx_assert(info->xfer_mtx, MA_OWNED);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* copy error */
199767f8919635c4928607450d9e0abb932109ceToomas Soome info->dma_error = udpt->dma_error;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* enter workloop again */
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_command_wrapper(&info->dma_q,
199767f8919635c4928607450d9e0abb932109ceToomas Soome info->dma_q.curr);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_bdma_pre_sync
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function handles DMA synchronisation that must be done before
199767f8919635c4928607450d9e0abb932109ceToomas Soome * an USB transfer is started.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_bdma_pre_sync(struct usb_xfer *xfer)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_page_cache *pc;
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_frcount_t nframes;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (xfer->flags_int.isochronous_xfr) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* only one frame buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nframes = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* can be multiple frame buffers */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nframes = xfer->nframes;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc = xfer->frbuffers;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (nframes--) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (pc->isread) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_pc_cpu_invalidate(pc);
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_pc_cpu_flush(pc);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_bdma_post_sync
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function handles DMA synchronisation that must be done after
199767f8919635c4928607450d9e0abb932109ceToomas Soome * an USB transfer is complete.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_bdma_post_sync(struct usb_xfer *xfer)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct usb_page_cache *pc;
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_frcount_t nframes;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (xfer->flags_int.isochronous_xfr) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* only one frame buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nframes = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* can be multiple frame buffers */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nframes = xfer->nframes;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc = xfer->frbuffers;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (nframes--) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (pc->isread) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb_pc_cpu_invalidate(pc);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome pc++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif