199767f8919635c4928607450d9e0abb932109ceToomas Soome/* $FreeBSD$ */
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
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 * 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 * 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 Soomestatic void usb_pc_common_mem_cb(struct usb_page_cache *pc,
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usbd_get_page - lookup DMA-able memory for the given offset
199767f8919635c4928607450d9e0abb932109ceToomas Soome * NOTE: Only call this function when the "page_cache" structure has
199767f8919635c4928607450d9e0abb932109ceToomas Soome * been properly initialized !
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusbd_get_page(struct usb_page_cache *pc, usb_frlength_t offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Case 1 - something has been loaded into DMA */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Case 1a - Kernel Virtual Address */
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->buffer = USB_ADD_BYTES(pc->buffer, offset);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* compute destination page */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Case 1b - Non Kernel Virtual Address */
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->buffer = USB_ADD_BYTES(page->buffer, offset);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Case 2 - Plain PIO */
199767f8919635c4928607450d9e0abb932109ceToomas Soome res->buffer = USB_ADD_BYTES(pc->buffer, offset);
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usbd_copy_in - copy directly to DMA-able memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (len != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usbd_copy_out - copy directly from DMA-able memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (len != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usbd_frame_zero - zero DMA-able memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (len != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_common_mem_cb - BUS-DMA callback function
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soome nseg = ((length + USB_PAGE_SIZE - 1) / USB_PAGE_SIZE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (off = USB_PAGE_SIZE; off < length; off += USB_PAGE_SIZE) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg->physaddr = (phys + off) & ~(USB_PAGE_SIZE - 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_alloc_mem - allocate DMA'able memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 0: Success
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Else: Failure
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg,
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* allocate zeroed memory */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* setup page cache */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* compute physical address */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* reset most of the page cache */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_free_mem - free DMA memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function is NULL safe.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_load_mem - load virtual memory into DMA
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Return values:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 0: Success
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Else: Error
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size, uint8_t sync)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* setup page cache */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* compute physical address */
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Call callback so that refcount is decremented
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_cpu_invalidate - invalidate CPU cache
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_cpu_invalidate(struct usb_page_cache *pc)
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (pc->page_offset_end == pc->page_offset_buf) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* nothing has been loaded into this page cache! */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_cpu_flush - flush CPU cache
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/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_dmamap_create - create a DMA map
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 0: Success
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Else: Failure
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_dmamap_create(struct usb_page_cache *pc, usb_size_t size)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0); /* NOP, success */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_pc_dmamap_destroy
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function is NULL safe.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_pc_dmamap_destroy(struct usb_page_cache *pc)
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_dma_tag_setup - initialise USB DMA tags
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_dma_tag_setup(struct usb_dma_parent_tag *udpt,
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* sanity checking */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((nudt == 0) ||
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* something is corrupt */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* initialise condition variable */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* store some information */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_bus_tag_unsetup - factored out code
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_dma_tag_unsetup(struct usb_dma_parent_tag *udpt)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* destroy the condition variable */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_bdma_work_loop
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 Soome /* some error happened */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* reset BUS-DMA load state */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* only one frame buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* can be multiple frame buffers */
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 /* special case */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* The device controller writes to memory */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* The host controller reads from memory */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* default case */
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 while (--nframes > 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome pg += (xfer->frlengths[nframes] / USB_PAGE_SIZE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome usbd_transfer_done(xfer, USB_ERR_DMA_LOAD_FAILED);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (info->dma_currframe != info->dma_nframes) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* special case */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* default case */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* advance frame index */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* go ahead */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* start loading next USB transfer, if any */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* finally start the hardware */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_bdma_done_event
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function is called when the BUS-DMA has loaded virtual memory
199767f8919635c4928607450d9e0abb932109ceToomas Soome * into DMA, if any.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soomeusb_bdma_done_event(struct usb_dma_parent_tag *udpt)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* copy error */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* enter workloop again */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_bdma_pre_sync
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function handles DMA synchronisation that must be done before
199767f8919635c4928607450d9e0abb932109ceToomas Soome * an USB transfer is started.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* only one frame buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* can be multiple frame buffers */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*------------------------------------------------------------------------*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * usb_bdma_post_sync
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This function handles DMA synchronisation that must be done after
199767f8919635c4928607450d9e0abb932109ceToomas Soome * an USB transfer is complete.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *------------------------------------------------------------------------*/
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* only one frame buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* can be multiple frame buffers */