1eb36b1d0SJason A. Harmening /*- 2eb36b1d0SJason A. Harmening * Copyright (c) 2017 Jason A. Harmening. 3eb36b1d0SJason A. Harmening * All rights reserved. 4eb36b1d0SJason A. Harmening * 5eb36b1d0SJason A. Harmening * Redistribution and use in source and binary forms, with or without 6eb36b1d0SJason A. Harmening * modification, are permitted provided that the following conditions 7eb36b1d0SJason A. Harmening * are met: 8eb36b1d0SJason A. Harmening * 1. Redistributions of source code must retain the above copyright 9eb36b1d0SJason A. Harmening * notice, this list of conditions and the following disclaimer. 10eb36b1d0SJason A. Harmening * 2. Redistributions in binary form must reproduce the above copyright 11eb36b1d0SJason A. Harmening * notice, this list of conditions and the following disclaimer in the 12eb36b1d0SJason A. Harmening * documentation and/or other materials provided with the distribution. 13eb36b1d0SJason A. Harmening * 14eb36b1d0SJason A. Harmening * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15eb36b1d0SJason A. Harmening * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16eb36b1d0SJason A. Harmening * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17eb36b1d0SJason A. Harmening * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18eb36b1d0SJason A. Harmening * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19eb36b1d0SJason A. Harmening * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20eb36b1d0SJason A. Harmening * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21eb36b1d0SJason A. Harmening * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22eb36b1d0SJason A. Harmening * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23eb36b1d0SJason A. Harmening * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24eb36b1d0SJason A. Harmening * SUCH DAMAGE. 25eb36b1d0SJason A. Harmening */ 26eb36b1d0SJason A. Harmening 27eb36b1d0SJason A. Harmening #ifndef _X86_BUS_DMA_H_ 28eb36b1d0SJason A. Harmening #define _X86_BUS_DMA_H_ 29eb36b1d0SJason A. Harmening 30eb36b1d0SJason A. Harmening #define WANT_INLINE_DMAMAP 31eb36b1d0SJason A. Harmening #include <sys/bus_dma.h> 32eb36b1d0SJason A. Harmening #include <sys/_null.h> 33eb36b1d0SJason A. Harmening 34eb36b1d0SJason A. Harmening #include <x86/busdma_impl.h> 35eb36b1d0SJason A. Harmening 36eb36b1d0SJason A. Harmening /* 37b961c0f2STycho Nightingale * Is DMA address 1:1 mapping of physical address 38b961c0f2STycho Nightingale */ 39b961c0f2STycho Nightingale static inline bool 40b961c0f2STycho Nightingale bus_dma_id_mapped(bus_dma_tag_t dmat, vm_paddr_t buf, bus_size_t buflen) 41b961c0f2STycho Nightingale { 42b961c0f2STycho Nightingale struct bus_dma_tag_common *tc; 43b961c0f2STycho Nightingale 44b961c0f2STycho Nightingale tc = (struct bus_dma_tag_common *)dmat; 45b961c0f2STycho Nightingale return (tc->impl->id_mapped(dmat, buf, buflen)); 46b961c0f2STycho Nightingale } 47b961c0f2STycho Nightingale 48b961c0f2STycho Nightingale /* 49eb36b1d0SJason A. Harmening * Allocate a handle for mapping from kva/uva/physical 50eb36b1d0SJason A. Harmening * address space into bus device space. 51eb36b1d0SJason A. Harmening */ 52eb36b1d0SJason A. Harmening static inline int 53eb36b1d0SJason A. Harmening bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) 54eb36b1d0SJason A. Harmening { 55eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 56eb36b1d0SJason A. Harmening 57eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 58eb36b1d0SJason A. Harmening return (tc->impl->map_create(dmat, flags, mapp)); 59eb36b1d0SJason A. Harmening } 60eb36b1d0SJason A. Harmening 61eb36b1d0SJason A. Harmening /* 62eb36b1d0SJason A. Harmening * Destroy a handle for mapping from kva/uva/physical 63eb36b1d0SJason A. Harmening * address space into bus device space. 64eb36b1d0SJason A. Harmening */ 65eb36b1d0SJason A. Harmening static inline int 66eb36b1d0SJason A. Harmening bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 67eb36b1d0SJason A. Harmening { 68eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 69eb36b1d0SJason A. Harmening 70eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 71eb36b1d0SJason A. Harmening return (tc->impl->map_destroy(dmat, map)); 72eb36b1d0SJason A. Harmening } 73eb36b1d0SJason A. Harmening 74eb36b1d0SJason A. Harmening /* 75eb36b1d0SJason A. Harmening * Allocate a piece of memory that can be efficiently mapped into 76eb36b1d0SJason A. Harmening * bus device space based on the constraints lited in the dma tag. 77eb36b1d0SJason A. Harmening * A dmamap to for use with dmamap_load is also allocated. 78eb36b1d0SJason A. Harmening */ 79eb36b1d0SJason A. Harmening static inline int 80eb36b1d0SJason A. Harmening bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, 81eb36b1d0SJason A. Harmening bus_dmamap_t *mapp) 82eb36b1d0SJason A. Harmening { 83eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 84eb36b1d0SJason A. Harmening 85eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 86eb36b1d0SJason A. Harmening return (tc->impl->mem_alloc(dmat, vaddr, flags, mapp)); 87eb36b1d0SJason A. Harmening } 88eb36b1d0SJason A. Harmening 89eb36b1d0SJason A. Harmening /* 90eb36b1d0SJason A. Harmening * Free a piece of memory and it's allociated dmamap, that was allocated 91*d1bdc282SBjoern A. Zeeb * via bus_dmamem_alloc. 92eb36b1d0SJason A. Harmening */ 93eb36b1d0SJason A. Harmening static inline void 94eb36b1d0SJason A. Harmening bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) 95eb36b1d0SJason A. Harmening { 96eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 97eb36b1d0SJason A. Harmening 98eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 99eb36b1d0SJason A. Harmening tc->impl->mem_free(dmat, vaddr, map); 100eb36b1d0SJason A. Harmening } 101eb36b1d0SJason A. Harmening 102eb36b1d0SJason A. Harmening /* 103eb36b1d0SJason A. Harmening * Release the mapping held by map. 104eb36b1d0SJason A. Harmening */ 105eb36b1d0SJason A. Harmening static inline void 106eb36b1d0SJason A. Harmening bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) 107eb36b1d0SJason A. Harmening { 108eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 109eb36b1d0SJason A. Harmening 110eb36b1d0SJason A. Harmening if (map != NULL) { 111eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 112eb36b1d0SJason A. Harmening tc->impl->map_unload(dmat, map); 113eb36b1d0SJason A. Harmening } 114eb36b1d0SJason A. Harmening } 115eb36b1d0SJason A. Harmening 116eb36b1d0SJason A. Harmening static inline void 117eb36b1d0SJason A. Harmening bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) 118eb36b1d0SJason A. Harmening { 119eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 120eb36b1d0SJason A. Harmening 121eb36b1d0SJason A. Harmening if (map != NULL) { 122eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 123eb36b1d0SJason A. Harmening tc->impl->map_sync(dmat, map, op); 124eb36b1d0SJason A. Harmening } 125eb36b1d0SJason A. Harmening } 126eb36b1d0SJason A. Harmening 127eb36b1d0SJason A. Harmening /* 128eb36b1d0SJason A. Harmening * Utility function to load a physical buffer. segp contains 129eb36b1d0SJason A. Harmening * the starting segment on entrace, and the ending segment on exit. 130eb36b1d0SJason A. Harmening */ 131eb36b1d0SJason A. Harmening static inline int 132eb36b1d0SJason A. Harmening _bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, 133eb36b1d0SJason A. Harmening bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp) 134eb36b1d0SJason A. Harmening { 135eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 136eb36b1d0SJason A. Harmening 137eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 138eb36b1d0SJason A. Harmening return (tc->impl->load_phys(dmat, map, buf, buflen, flags, segs, 139eb36b1d0SJason A. Harmening segp)); 140eb36b1d0SJason A. Harmening } 141eb36b1d0SJason A. Harmening 142eb36b1d0SJason A. Harmening static inline int 143eb36b1d0SJason A. Harmening _bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map, struct vm_page **ma, 144eb36b1d0SJason A. Harmening bus_size_t tlen, int ma_offs, int flags, bus_dma_segment_t *segs, 145eb36b1d0SJason A. Harmening int *segp) 146eb36b1d0SJason A. Harmening { 147eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 148eb36b1d0SJason A. Harmening 149eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 150eb36b1d0SJason A. Harmening return (tc->impl->load_ma(dmat, map, ma, tlen, ma_offs, flags, 151eb36b1d0SJason A. Harmening segs, segp)); 152eb36b1d0SJason A. Harmening } 153eb36b1d0SJason A. Harmening 154eb36b1d0SJason A. Harmening /* 155eb36b1d0SJason A. Harmening * Utility function to load a linear buffer. segp contains 156eb36b1d0SJason A. Harmening * the starting segment on entrace, and the ending segment on exit. 157eb36b1d0SJason A. Harmening */ 158eb36b1d0SJason A. Harmening static inline int 159eb36b1d0SJason A. Harmening _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 160eb36b1d0SJason A. Harmening bus_size_t buflen, struct pmap *pmap, int flags, bus_dma_segment_t *segs, 161eb36b1d0SJason A. Harmening int *segp) 162eb36b1d0SJason A. Harmening { 163eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 164eb36b1d0SJason A. Harmening 165eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 166eb36b1d0SJason A. Harmening return (tc->impl->load_buffer(dmat, map, buf, buflen, pmap, flags, segs, 167eb36b1d0SJason A. Harmening segp)); 168eb36b1d0SJason A. Harmening } 169eb36b1d0SJason A. Harmening 170eb36b1d0SJason A. Harmening static inline void 171eb36b1d0SJason A. Harmening _bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, 172eb36b1d0SJason A. Harmening struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) 173eb36b1d0SJason A. Harmening { 174eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 175eb36b1d0SJason A. Harmening 176eb36b1d0SJason A. Harmening if (map != NULL) { 177eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 178eb36b1d0SJason A. Harmening tc->impl->map_waitok(dmat, map, mem, callback, callback_arg); 179eb36b1d0SJason A. Harmening } 180eb36b1d0SJason A. Harmening } 181eb36b1d0SJason A. Harmening 182eb36b1d0SJason A. Harmening static inline bus_dma_segment_t * 183eb36b1d0SJason A. Harmening _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, 184eb36b1d0SJason A. Harmening bus_dma_segment_t *segs, int nsegs, int error) 185eb36b1d0SJason A. Harmening { 186eb36b1d0SJason A. Harmening struct bus_dma_tag_common *tc; 187eb36b1d0SJason A. Harmening 188eb36b1d0SJason A. Harmening tc = (struct bus_dma_tag_common *)dmat; 189eb36b1d0SJason A. Harmening return (tc->impl->map_complete(dmat, map, segs, nsegs, error)); 190eb36b1d0SJason A. Harmening } 191eb36b1d0SJason A. Harmening 192693c9516SMark Johnston #ifdef KMSAN 193693c9516SMark Johnston static inline void 194693c9516SMark Johnston _bus_dmamap_load_kmsan(bus_dma_tag_t dmat, bus_dmamap_t map, 195693c9516SMark Johnston struct memdesc *mem) 196693c9516SMark Johnston { 197693c9516SMark Johnston struct bus_dma_tag_common *tc; 198693c9516SMark Johnston 199693c9516SMark Johnston tc = (struct bus_dma_tag_common *)dmat; 200693c9516SMark Johnston return (tc->impl->load_kmsan(map, mem)); 201693c9516SMark Johnston } 202693c9516SMark Johnston #endif 203693c9516SMark Johnston 204eb36b1d0SJason A. Harmening #endif /* !_X86_BUS_DMA_H_ */ 205