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