1*f7f39addSMarkus Pfeiffer /* $FreeBSD: head/sys/dev/usb/usb_busdma.h 266969 2014-06-02 07:08:34Z hselasky $ */ 212bd3c8bSSascha Wildner /*- 312bd3c8bSSascha Wildner * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 412bd3c8bSSascha Wildner * 512bd3c8bSSascha Wildner * Redistribution and use in source and binary forms, with or without 612bd3c8bSSascha Wildner * modification, are permitted provided that the following conditions 712bd3c8bSSascha Wildner * are met: 812bd3c8bSSascha Wildner * 1. Redistributions of source code must retain the above copyright 912bd3c8bSSascha Wildner * notice, this list of conditions and the following disclaimer. 1012bd3c8bSSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 1112bd3c8bSSascha Wildner * notice, this list of conditions and the following disclaimer in the 1212bd3c8bSSascha Wildner * documentation and/or other materials provided with the distribution. 1312bd3c8bSSascha Wildner * 1412bd3c8bSSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1512bd3c8bSSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1612bd3c8bSSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1712bd3c8bSSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1812bd3c8bSSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1912bd3c8bSSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2012bd3c8bSSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2112bd3c8bSSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2212bd3c8bSSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2312bd3c8bSSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2412bd3c8bSSascha Wildner * SUCH DAMAGE. 2512bd3c8bSSascha Wildner */ 2612bd3c8bSSascha Wildner 2712bd3c8bSSascha Wildner #ifndef _USB_BUSDMA_H_ 2812bd3c8bSSascha Wildner #define _USB_BUSDMA_H_ 2912bd3c8bSSascha Wildner 3012bd3c8bSSascha Wildner #include <sys/uio.h> 3112bd3c8bSSascha Wildner #include <sys/mbuf.h> 3212bd3c8bSSascha Wildner 33722d05c3SSascha Wildner #include <sys/bus.h> 34722d05c3SSascha Wildner 35722d05c3SSascha Wildner #define USB_HAVE_BUSDMA 1 3612bd3c8bSSascha Wildner 3712bd3c8bSSascha Wildner /* defines */ 3812bd3c8bSSascha Wildner 3912bd3c8bSSascha Wildner #define USB_PAGE_SIZE PAGE_SIZE /* use system PAGE_SIZE */ 4012bd3c8bSSascha Wildner 4112bd3c8bSSascha Wildner #define USB_GET_DMA_TAG(dev) NULL /* XXX */ 4212bd3c8bSSascha Wildner 4312bd3c8bSSascha Wildner /* structure prototypes */ 4412bd3c8bSSascha Wildner 4512bd3c8bSSascha Wildner struct usb_xfer_root; 4612bd3c8bSSascha Wildner struct usb_dma_parent_tag; 4712bd3c8bSSascha Wildner struct usb_dma_tag; 4812bd3c8bSSascha Wildner 4912bd3c8bSSascha Wildner /* 5012bd3c8bSSascha Wildner * The following typedef defines the USB DMA load done callback. 5112bd3c8bSSascha Wildner */ 5212bd3c8bSSascha Wildner 5312bd3c8bSSascha Wildner typedef void (usb_dma_callback_t)(struct usb_dma_parent_tag *udpt); 5412bd3c8bSSascha Wildner 5512bd3c8bSSascha Wildner /* 5612bd3c8bSSascha Wildner * The following structure defines physical and non kernel virtual 5712bd3c8bSSascha Wildner * address of a memory page having size USB_PAGE_SIZE. 5812bd3c8bSSascha Wildner */ 5912bd3c8bSSascha Wildner struct usb_page { 6012bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA 6112bd3c8bSSascha Wildner bus_size_t physaddr; 6212bd3c8bSSascha Wildner void *buffer; /* non Kernel Virtual Address */ 6312bd3c8bSSascha Wildner #endif 6412bd3c8bSSascha Wildner }; 6512bd3c8bSSascha Wildner 6612bd3c8bSSascha Wildner /* 6712bd3c8bSSascha Wildner * The following structure is used when needing the kernel virtual 6812bd3c8bSSascha Wildner * pointer and the physical address belonging to an offset in an USB 6912bd3c8bSSascha Wildner * page cache. 7012bd3c8bSSascha Wildner */ 7112bd3c8bSSascha Wildner struct usb_page_search { 7212bd3c8bSSascha Wildner void *buffer; 7312bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA 7412bd3c8bSSascha Wildner bus_size_t physaddr; 7512bd3c8bSSascha Wildner #endif 7612bd3c8bSSascha Wildner usb_size_t length; 7712bd3c8bSSascha Wildner }; 7812bd3c8bSSascha Wildner 7912bd3c8bSSascha Wildner /* 8012bd3c8bSSascha Wildner * The following structure is used to keep information about a DMA 8112bd3c8bSSascha Wildner * memory allocation. 8212bd3c8bSSascha Wildner */ 8312bd3c8bSSascha Wildner struct usb_page_cache { 8412bd3c8bSSascha Wildner 8512bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA 8612bd3c8bSSascha Wildner bus_dma_tag_t tag; 8712bd3c8bSSascha Wildner bus_dmamap_t map; 8812bd3c8bSSascha Wildner struct usb_page *page_start; 8912bd3c8bSSascha Wildner #endif 9012bd3c8bSSascha Wildner struct usb_dma_parent_tag *tag_parent; /* always set */ 9112bd3c8bSSascha Wildner void *buffer; /* virtual buffer pointer */ 9212bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA 9312bd3c8bSSascha Wildner usb_size_t page_offset_buf; 9412bd3c8bSSascha Wildner usb_size_t page_offset_end; 9512bd3c8bSSascha Wildner uint8_t isread:1; /* set if we are currently reading 9612bd3c8bSSascha Wildner * from the memory. Else write. */ 9712bd3c8bSSascha Wildner uint8_t ismultiseg:1; /* set if we can have multiple 9812bd3c8bSSascha Wildner * segments */ 9912bd3c8bSSascha Wildner #endif 10012bd3c8bSSascha Wildner }; 10112bd3c8bSSascha Wildner 10212bd3c8bSSascha Wildner /* 10312bd3c8bSSascha Wildner * The following structure describes the parent USB DMA tag. 10412bd3c8bSSascha Wildner */ 10512bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA 10612bd3c8bSSascha Wildner struct usb_dma_parent_tag { 10712bd3c8bSSascha Wildner struct cv cv[1]; /* internal condition variable */ 10812bd3c8bSSascha Wildner bus_dma_tag_t tag; /* always set */ 10912bd3c8bSSascha Wildner 110722d05c3SSascha Wildner struct lock *lock; /* private mutex, always set */ 11112bd3c8bSSascha Wildner usb_dma_callback_t *func; /* load complete callback function */ 11212bd3c8bSSascha Wildner struct usb_dma_tag *utag_first;/* pointer to first USB DMA tag */ 11312bd3c8bSSascha Wildner uint8_t dma_error; /* set if DMA load operation failed */ 11412bd3c8bSSascha Wildner uint8_t dma_bits; /* number of DMA address lines */ 11512bd3c8bSSascha Wildner uint8_t utag_max; /* number of USB DMA tags */ 11612bd3c8bSSascha Wildner }; 11712bd3c8bSSascha Wildner #else 11812bd3c8bSSascha Wildner struct usb_dma_parent_tag {}; /* empty struct */ 11912bd3c8bSSascha Wildner #endif 12012bd3c8bSSascha Wildner 12112bd3c8bSSascha Wildner /* 12212bd3c8bSSascha Wildner * The following structure describes an USB DMA tag. 12312bd3c8bSSascha Wildner */ 12412bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA 12512bd3c8bSSascha Wildner struct usb_dma_tag { 12612bd3c8bSSascha Wildner struct usb_dma_parent_tag *tag_parent; 12712bd3c8bSSascha Wildner bus_dma_tag_t tag; 12812bd3c8bSSascha Wildner usb_size_t align; 12912bd3c8bSSascha Wildner usb_size_t size; 13012bd3c8bSSascha Wildner }; 13112bd3c8bSSascha Wildner #else 13212bd3c8bSSascha Wildner struct usb_dma_tag {}; /* empty struct */ 13312bd3c8bSSascha Wildner #endif 13412bd3c8bSSascha Wildner 13512bd3c8bSSascha Wildner /* function prototypes */ 13612bd3c8bSSascha Wildner 13712bd3c8bSSascha Wildner int usb_uiomove(struct usb_page_cache *pc, struct uio *uio, 13812bd3c8bSSascha Wildner usb_frlength_t pc_offset, usb_frlength_t len); 13912bd3c8bSSascha Wildner struct usb_dma_tag *usb_dma_tag_find(struct usb_dma_parent_tag *udpt, 14012bd3c8bSSascha Wildner usb_size_t size, usb_size_t align); 14112bd3c8bSSascha Wildner uint8_t usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg, 14212bd3c8bSSascha Wildner usb_size_t size, usb_size_t align); 14312bd3c8bSSascha Wildner uint8_t usb_pc_dmamap_create(struct usb_page_cache *pc, usb_size_t size); 14412bd3c8bSSascha Wildner uint8_t usb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size, 14512bd3c8bSSascha Wildner uint8_t sync); 14612bd3c8bSSascha Wildner void usb_bdma_done_event(struct usb_dma_parent_tag *udpt); 14712bd3c8bSSascha Wildner void usb_bdma_post_sync(struct usb_xfer *xfer); 14812bd3c8bSSascha Wildner void usb_bdma_pre_sync(struct usb_xfer *xfer); 14912bd3c8bSSascha Wildner void usb_bdma_work_loop(struct usb_xfer_queue *pq); 15012bd3c8bSSascha Wildner void usb_dma_tag_setup(struct usb_dma_parent_tag *udpt, 151722d05c3SSascha Wildner struct usb_dma_tag *udt, bus_dma_tag_t dmat, struct lock *lock, 15212bd3c8bSSascha Wildner usb_dma_callback_t *func, uint8_t ndmabits, uint8_t nudt); 15312bd3c8bSSascha Wildner void usb_dma_tag_unsetup(struct usb_dma_parent_tag *udpt); 15412bd3c8bSSascha Wildner void usb_pc_cpu_flush(struct usb_page_cache *pc); 15512bd3c8bSSascha Wildner void usb_pc_cpu_invalidate(struct usb_page_cache *pc); 15612bd3c8bSSascha Wildner void usb_pc_dmamap_destroy(struct usb_page_cache *pc); 15712bd3c8bSSascha Wildner void usb_pc_free_mem(struct usb_page_cache *pc); 15812bd3c8bSSascha Wildner 15912bd3c8bSSascha Wildner #endif /* _USB_BUSDMA_H_ */ 160