1 /* $FreeBSD$ */ 2 /*- 3 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #ifndef _USB_BUSDMA_H_ 28 #define _USB_BUSDMA_H_ 29 30 #ifndef USB_GLOBAL_INCLUDE_FILE 31 #include <sys/uio.h> 32 #include <sys/mbuf.h> 33 34 #include <machine/bus.h> 35 #endif 36 37 /* defines */ 38 39 #define USB_PAGE_SIZE PAGE_SIZE /* use system PAGE_SIZE */ 40 41 #if (__FreeBSD_version >= 700020) 42 #define USB_GET_DMA_TAG(dev) bus_get_dma_tag(dev) 43 #else 44 #define USB_GET_DMA_TAG(dev) NULL /* XXX */ 45 #endif 46 47 /* structure prototypes */ 48 49 struct usb_xfer_root; 50 struct usb_dma_parent_tag; 51 struct usb_dma_tag; 52 53 /* 54 * The following typedef defines the USB DMA load done callback. 55 */ 56 57 typedef void (usb_dma_callback_t)(struct usb_dma_parent_tag *udpt); 58 59 /* 60 * The following structure defines physical and non kernel virtual 61 * address of a memory page having size USB_PAGE_SIZE. 62 */ 63 struct usb_page { 64 #if USB_HAVE_BUSDMA 65 bus_addr_t physaddr; 66 void *buffer; /* non Kernel Virtual Address */ 67 #endif 68 }; 69 70 /* 71 * The following structure is used when needing the kernel virtual 72 * pointer and the physical address belonging to an offset in an USB 73 * page cache. 74 */ 75 struct usb_page_search { 76 void *buffer; 77 #if USB_HAVE_BUSDMA 78 bus_addr_t physaddr; 79 #endif 80 usb_size_t length; 81 }; 82 83 /* 84 * The following structure is used to keep information about a DMA 85 * memory allocation. 86 */ 87 struct usb_page_cache { 88 89 #if USB_HAVE_BUSDMA 90 bus_dma_tag_t tag; 91 bus_dmamap_t map; 92 struct usb_page *page_start; 93 #endif 94 struct usb_dma_parent_tag *tag_parent; /* always set */ 95 void *buffer; /* virtual buffer pointer */ 96 #if USB_HAVE_BUSDMA 97 usb_size_t page_offset_buf; 98 usb_size_t page_offset_end; 99 uint8_t isread:1; /* set if we are currently reading 100 * from the memory. Else write. */ 101 uint8_t ismultiseg:1; /* set if we can have multiple 102 * segments */ 103 #endif 104 }; 105 106 /* 107 * The following structure describes the parent USB DMA tag. 108 */ 109 #if USB_HAVE_BUSDMA 110 struct usb_dma_parent_tag { 111 struct cv cv[1]; /* internal condition variable */ 112 bus_dma_tag_t tag; /* always set */ 113 114 struct mtx *mtx; /* private mutex, always set */ 115 usb_dma_callback_t *func; /* load complete callback function */ 116 struct usb_dma_tag *utag_first;/* pointer to first USB DMA tag */ 117 uint8_t dma_error; /* set if DMA load operation failed */ 118 uint8_t dma_bits; /* number of DMA address lines */ 119 uint8_t utag_max; /* number of USB DMA tags */ 120 }; 121 #else 122 struct usb_dma_parent_tag {}; /* empty struct */ 123 #endif 124 125 /* 126 * The following structure describes an USB DMA tag. 127 */ 128 #if USB_HAVE_BUSDMA 129 struct usb_dma_tag { 130 struct usb_dma_parent_tag *tag_parent; 131 bus_dma_tag_t tag; 132 usb_size_t align; 133 usb_size_t size; 134 }; 135 #else 136 struct usb_dma_tag {}; /* empty struct */ 137 #endif 138 139 /* function prototypes */ 140 141 int usb_uiomove(struct usb_page_cache *pc, struct uio *uio, 142 usb_frlength_t pc_offset, usb_frlength_t len); 143 struct usb_dma_tag *usb_dma_tag_find(struct usb_dma_parent_tag *udpt, 144 usb_size_t size, usb_size_t align); 145 uint8_t usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg, 146 usb_size_t size, usb_size_t align); 147 uint8_t usb_pc_dmamap_create(struct usb_page_cache *pc, usb_size_t size); 148 uint8_t usb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size, 149 uint8_t sync); 150 void usb_bdma_done_event(struct usb_dma_parent_tag *udpt); 151 void usb_bdma_post_sync(struct usb_xfer *xfer); 152 void usb_bdma_pre_sync(struct usb_xfer *xfer); 153 void usb_bdma_work_loop(struct usb_xfer_queue *pq); 154 void usb_dma_tag_setup(struct usb_dma_parent_tag *udpt, 155 struct usb_dma_tag *udt, bus_dma_tag_t dmat, struct mtx *mtx, 156 usb_dma_callback_t *func, uint8_t ndmabits, uint8_t nudt); 157 void usb_dma_tag_unsetup(struct usb_dma_parent_tag *udpt); 158 void usb_pc_cpu_flush(struct usb_page_cache *pc); 159 void usb_pc_cpu_invalidate(struct usb_page_cache *pc); 160 void usb_pc_dmamap_destroy(struct usb_page_cache *pc); 161 void usb_pc_free_mem(struct usb_page_cache *pc); 162 uint8_t usb_pc_buffer_is_aligned(struct usb_page_cache *pc, 163 usb_frlength_t offset, usb_frlength_t len, 164 usb_frlength_t mask); 165 166 #endif /* _USB_BUSDMA_H_ */ 167