xref: /freebsd/sys/x86/include/bus_dma.h (revision d1bdc2821fcd416ab9b238580386eb605a6128d0)
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