1 /*- 2 * Copyright (c) 2017 Jason A. Harmening. 3 * 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 * $FreeBSD$ 27 */ 28 29 #ifndef _X86_BUS_DMA_H_ 30 #define _X86_BUS_DMA_H_ 31 32 #define WANT_INLINE_DMAMAP 33 #include <sys/bus_dma.h> 34 #include <sys/_null.h> 35 36 #include <x86/busdma_impl.h> 37 38 /* 39 * Is DMA address 1:1 mapping of physical address 40 */ 41 static inline bool 42 bus_dma_id_mapped(bus_dma_tag_t dmat, vm_paddr_t buf, bus_size_t buflen) 43 { 44 struct bus_dma_tag_common *tc; 45 46 tc = (struct bus_dma_tag_common *)dmat; 47 return (tc->impl->id_mapped(dmat, buf, buflen)); 48 } 49 50 /* 51 * Allocate a handle for mapping from kva/uva/physical 52 * address space into bus device space. 53 */ 54 static inline int 55 bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) 56 { 57 struct bus_dma_tag_common *tc; 58 59 tc = (struct bus_dma_tag_common *)dmat; 60 return (tc->impl->map_create(dmat, flags, mapp)); 61 } 62 63 /* 64 * Destroy a handle for mapping from kva/uva/physical 65 * address space into bus device space. 66 */ 67 static inline int 68 bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 69 { 70 struct bus_dma_tag_common *tc; 71 72 tc = (struct bus_dma_tag_common *)dmat; 73 return (tc->impl->map_destroy(dmat, map)); 74 } 75 76 /* 77 * Allocate a piece of memory that can be efficiently mapped into 78 * bus device space based on the constraints lited in the dma tag. 79 * A dmamap to for use with dmamap_load is also allocated. 80 */ 81 static inline int 82 bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, 83 bus_dmamap_t *mapp) 84 { 85 struct bus_dma_tag_common *tc; 86 87 tc = (struct bus_dma_tag_common *)dmat; 88 return (tc->impl->mem_alloc(dmat, vaddr, flags, mapp)); 89 } 90 91 /* 92 * Free a piece of memory and it's allociated dmamap, that was allocated 93 * via bus_dmamem_alloc. Make the same choice for free/contigfree. 94 */ 95 static inline void 96 bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) 97 { 98 struct bus_dma_tag_common *tc; 99 100 tc = (struct bus_dma_tag_common *)dmat; 101 tc->impl->mem_free(dmat, vaddr, map); 102 } 103 104 /* 105 * Release the mapping held by map. 106 */ 107 static inline void 108 bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) 109 { 110 struct bus_dma_tag_common *tc; 111 112 if (map != NULL) { 113 tc = (struct bus_dma_tag_common *)dmat; 114 tc->impl->map_unload(dmat, map); 115 } 116 } 117 118 static inline void 119 bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) 120 { 121 struct bus_dma_tag_common *tc; 122 123 if (map != NULL) { 124 tc = (struct bus_dma_tag_common *)dmat; 125 tc->impl->map_sync(dmat, map, op); 126 } 127 } 128 129 /* 130 * Utility function to load a physical buffer. segp contains 131 * the starting segment on entrace, and the ending segment on exit. 132 */ 133 static inline int 134 _bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, 135 bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp) 136 { 137 struct bus_dma_tag_common *tc; 138 139 tc = (struct bus_dma_tag_common *)dmat; 140 return (tc->impl->load_phys(dmat, map, buf, buflen, flags, segs, 141 segp)); 142 } 143 144 static inline int 145 _bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map, struct vm_page **ma, 146 bus_size_t tlen, int ma_offs, int flags, bus_dma_segment_t *segs, 147 int *segp) 148 { 149 struct bus_dma_tag_common *tc; 150 151 tc = (struct bus_dma_tag_common *)dmat; 152 return (tc->impl->load_ma(dmat, map, ma, tlen, ma_offs, flags, 153 segs, segp)); 154 } 155 156 /* 157 * Utility function to load a linear buffer. segp contains 158 * the starting segment on entrace, and the ending segment on exit. 159 */ 160 static inline int 161 _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 162 bus_size_t buflen, struct pmap *pmap, int flags, bus_dma_segment_t *segs, 163 int *segp) 164 { 165 struct bus_dma_tag_common *tc; 166 167 tc = (struct bus_dma_tag_common *)dmat; 168 return (tc->impl->load_buffer(dmat, map, buf, buflen, pmap, flags, segs, 169 segp)); 170 } 171 172 static inline void 173 _bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, 174 struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) 175 { 176 struct bus_dma_tag_common *tc; 177 178 if (map != NULL) { 179 tc = (struct bus_dma_tag_common *)dmat; 180 tc->impl->map_waitok(dmat, map, mem, callback, callback_arg); 181 } 182 } 183 184 static inline bus_dma_segment_t * 185 _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, 186 bus_dma_segment_t *segs, int nsegs, int error) 187 { 188 struct bus_dma_tag_common *tc; 189 190 tc = (struct bus_dma_tag_common *)dmat; 191 return (tc->impl->map_complete(dmat, map, segs, nsegs, error)); 192 } 193 194 #ifdef KMSAN 195 static inline void 196 _bus_dmamap_load_kmsan(bus_dma_tag_t dmat, bus_dmamap_t map, 197 struct memdesc *mem) 198 { 199 struct bus_dma_tag_common *tc; 200 201 tc = (struct bus_dma_tag_common *)dmat; 202 return (tc->impl->load_kmsan(map, mem)); 203 } 204 #endif 205 206 #endif /* !_X86_BUS_DMA_H_ */ 207