Switch to the generic bounce buffer support.diff -r1.15 -r1.16 src/sys/arch/arm/footbridge/isa/isadma_machdep.c
(matt)
--- src/sys/arch/arm/footbridge/isa/isadma_machdep.c 2012/02/12 16:34:07 1.15
+++ src/sys/arch/arm/footbridge/isa/isadma_machdep.c 2012/09/21 14:21:58 1.16
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: isadma_machdep.c,v 1.15 2012/02/12 16:34:07 matt Exp $ */ | 1 | /* $NetBSD: isadma_machdep.c,v 1.16 2012/09/21 14:21:58 matt Exp $ */ | |
2 | 2 | |||
3 | #define ISA_DMA_STATS | 3 | #define ISA_DMA_STATS | |
4 | 4 | |||
5 | /*- | 5 | /*- | |
6 | * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. | 6 | * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. | |
7 | * All rights reserved. | 7 | * All rights reserved. | |
8 | * | 8 | * | |
9 | * This code is derived from software contributed to The NetBSD Foundation | 9 | * This code is derived from software contributed to The NetBSD Foundation | |
10 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | 10 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
11 | * NASA Ames Research Center. | 11 | * NASA Ames Research Center. | |
12 | * | 12 | * | |
13 | * Redistribution and use in source and binary forms, with or without | 13 | * Redistribution and use in source and binary forms, with or without | |
14 | * modification, are permitted provided that the following conditions | 14 | * modification, are permitted provided that the following conditions | |
@@ -23,27 +23,27 @@ | @@ -23,27 +23,27 @@ | |||
23 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 23 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
24 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 24 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
25 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 25 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
26 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 26 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
32 | * POSSIBILITY OF SUCH DAMAGE. | 32 | * POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | #include <sys/cdefs.h> | 35 | #include <sys/cdefs.h> | |
36 | __KERNEL_RCSID(0, "$NetBSD: isadma_machdep.c,v 1.15 2012/02/12 16:34:07 matt Exp $"); | 36 | __KERNEL_RCSID(0, "$NetBSD: isadma_machdep.c,v 1.16 2012/09/21 14:21:58 matt Exp $"); | |
37 | 37 | |||
38 | #include <sys/param.h> | 38 | #include <sys/param.h> | |
39 | #include <sys/systm.h> | 39 | #include <sys/systm.h> | |
40 | #include <sys/syslog.h> | 40 | #include <sys/syslog.h> | |
41 | #include <sys/device.h> | 41 | #include <sys/device.h> | |
42 | #include <sys/malloc.h> | 42 | #include <sys/malloc.h> | |
43 | #include <sys/proc.h> | 43 | #include <sys/proc.h> | |
44 | #include <sys/mbuf.h> | 44 | #include <sys/mbuf.h> | |
45 | 45 | |||
46 | #define _ARM32_BUS_DMA_PRIVATE | 46 | #define _ARM32_BUS_DMA_PRIVATE | |
47 | #include <sys/bus.h> | 47 | #include <sys/bus.h> | |
48 | 48 | |||
49 | #include <dev/isa/isareg.h> | 49 | #include <dev/isa/isareg.h> | |
@@ -55,579 +55,34 @@ __KERNEL_RCSID(0, "$NetBSD: isadma_machd | @@ -55,579 +55,34 @@ __KERNEL_RCSID(0, "$NetBSD: isadma_machd | |||
55 | * ISA has a 24-bit address limitation, so at most it has a 16M | 55 | * ISA has a 24-bit address limitation, so at most it has a 16M | |
56 | * DMA range. However, some platforms have a more limited range, | 56 | * DMA range. However, some platforms have a more limited range, | |
57 | * e.g. the Shark NC. On these systems, we are provided with | 57 | * e.g. the Shark NC. On these systems, we are provided with | |
58 | * a set of DMA ranges. The pmap module is aware of these ranges | 58 | * a set of DMA ranges. The pmap module is aware of these ranges | |
59 | * and places DMA-safe memory for them onto an alternate free list | 59 | * and places DMA-safe memory for them onto an alternate free list | |
60 | * so that they are protected from being used to service page faults, | 60 | * so that they are protected from being used to service page faults, | |
61 | * etc. (unless we've run out of memory elsewhere). | 61 | * etc. (unless we've run out of memory elsewhere). | |
62 | */ | 62 | */ | |
63 | #define ISA_DMA_BOUNCE_THRESHOLD (16 * 1024 * 1024) | 63 | #define ISA_DMA_BOUNCE_THRESHOLD (16 * 1024 * 1024) | |
64 | 64 | |||
65 | struct arm32_dma_range *footbridge_isa_dma_ranges; | 65 | struct arm32_dma_range *footbridge_isa_dma_ranges; | |
66 | int footbridge_isa_dma_nranges; | 66 | int footbridge_isa_dma_nranges; | |
67 | 67 | |||
68 | int _isa_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, | |||
69 | bus_size_t, bus_size_t, int, bus_dmamap_t *); | |||
70 | void _isa_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); | |||
71 | int _isa_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, | |||
72 | bus_size_t, struct proc *, int); | |||
73 | int _isa_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, | |||
74 | struct mbuf *, int); | |||
75 | int _isa_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, | |||
76 | struct uio *, int); | |||
77 | int _isa_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, | |||
78 | bus_dma_segment_t *, int, bus_size_t, int); | |||
79 | void _isa_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); | |||
80 | void _isa_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, | |||
81 | bus_addr_t, bus_size_t, int); | |||
82 | ||||
83 | int _isa_bus_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, | |||
84 | bus_size_t, bus_dma_segment_t *, int, int *, int); | |||
85 | ||||
86 | int _isa_dma_alloc_bouncebuf(bus_dma_tag_t, bus_dmamap_t, | |||
87 | bus_size_t, int); | |||
88 | void _isa_dma_free_bouncebuf(bus_dma_tag_t, bus_dmamap_t); | |||
89 | ||||
90 | /* | 68 | /* | |
91 | * Entry points for ISA DMA. These are mostly wrappers around | 69 | * Entry points for ISA DMA. These are mostly wrappers around | |
92 | * the generic functions that understand how to deal with bounce | 70 | * the generic functions that understand how to deal with bounce | |
93 | * buffers, if necessary. | 71 | * buffers, if necessary. | |
94 | */ | 72 | */ | |
95 | struct arm32_bus_dma_tag isa_bus_dma_tag = { | 73 | struct arm32_bus_dma_tag isa_bus_dma_tag = { | |
96 | 0, /* _ranges */ | 74 | _BUS_DMAMAP_FUNCS, | |
97 | 0, /* _nranges */ | 75 | _BUS_DMAMEM_FUNCS, | |
98 | NULL, | 76 | _BUS_DMATAG_FUNCS, | |
99 | _isa_bus_dmamap_create, | |||
100 | _isa_bus_dmamap_destroy, | |||
101 | _isa_bus_dmamap_load, | |||
102 | _isa_bus_dmamap_load_mbuf, | |||
103 | _isa_bus_dmamap_load_uio, | |||
104 | _isa_bus_dmamap_load_raw, | |||
105 | _isa_bus_dmamap_unload, | |||
106 | _isa_bus_dmamap_sync, /* pre */ | |||
107 | _isa_bus_dmamap_sync, /* post */ | |||
108 | _isa_bus_dmamem_alloc, | |||
109 | _bus_dmamem_free, | |||
110 | _bus_dmamem_map, | |||
111 | _bus_dmamem_unmap, | |||
112 | _bus_dmamem_mmap, | |||
113 | }; | 77 | }; | |
114 | 78 | |||
115 | /* | 79 | /* | |
116 | * Initialize ISA DMA. | 80 | * Initialize ISA DMA. | |
117 | */ | 81 | */ | |
118 | void | 82 | void | |
119 | isa_dma_init(void) | 83 | isa_dma_init(void) | |
120 | { | 84 | { | |
121 | 85 | |||
122 | isa_bus_dma_tag._ranges = footbridge_isa_dma_ranges; | 86 | isa_bus_dma_tag._ranges = footbridge_isa_dma_ranges; | |
123 | isa_bus_dma_tag._nranges = footbridge_isa_dma_nranges; | 87 | isa_bus_dma_tag._nranges = footbridge_isa_dma_nranges; | |
124 | } | 88 | } | |
125 | ||||
126 | /********************************************************************** | |||
127 | * bus.h dma interface entry points | |||
128 | **********************************************************************/ | |||
129 | ||||
130 | #ifdef ISA_DMA_STATS | |||
131 | #define STAT_INCR(v) (v)++ | |||
132 | #define STAT_DECR(v) do { \ | |||
133 | if ((v) == 0) \ | |||
134 | printf("%s:%d -- Already 0!\n", __FILE__, __LINE__); \ | |||
135 | else \ | |||
136 | (v)--; \ | |||
137 | } while (0) | |||
138 | u_long isa_dma_stats_loads; | |||
139 | u_long isa_dma_stats_bounces; | |||
140 | u_long isa_dma_stats_nbouncebufs; | |||
141 | #else | |||
142 | #define STAT_INCR(v) | |||
143 | #define STAT_DECR(v) | |||
144 | #endif | |||
145 | ||||
146 | /* | |||
147 | * Create an ISA DMA map. | |||
148 | */ | |||
149 | int | |||
150 | _isa_bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) | |||
151 | { | |||
152 | struct arm32_isa_dma_cookie *cookie; | |||
153 | bus_dmamap_t map; | |||
154 | int error, cookieflags; | |||
155 | void *cookiestore; | |||
156 | size_t cookiesize; | |||
157 | ||||
158 | /* Call common function to create the basic map. */ | |||
159 | error = _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, | |||
160 | flags, dmamp); | |||
161 | if (error) | |||
162 | return (error); | |||
163 | ||||
164 | map = *dmamp; | |||
165 | map->_dm_cookie = NULL; | |||
166 | ||||
167 | cookiesize = sizeof(struct arm32_isa_dma_cookie); | |||
168 | ||||
169 | /* | |||
170 | * ISA only has 24-bits of address space. This means | |||
171 | * we can't DMA to pages over 16M. In order to DMA to | |||
172 | * arbitrary buffers, we use "bounce buffers" - pages | |||
173 | * in memory below the 16M boundary. On DMA reads, | |||
174 | * DMA happens to the bounce buffers, and is copied into | |||
175 | * the caller's buffer. On writes, data is copied into | |||
176 | * but bounce buffer, and the DMA happens from those | |||
177 | * pages. To software using the DMA mapping interface, | |||
178 | * this looks simply like a data cache. | |||
179 | * | |||
180 | * If we have more than 16M of RAM in the system, we may | |||
181 | * need bounce buffers. We check and remember that here. | |||
182 | * | |||
183 | * There are exceptions, however. VLB devices can do | |||
184 | * 32-bit DMA, and indicate that here. | |||
185 | * | |||
186 | * ...or, there is an opposite case. The most segments | |||
187 | * a transfer will require is (maxxfer / PAGE_SIZE) + 1. If | |||
188 | * the caller can't handle that many segments (e.g. the | |||
189 | * ISA DMA controller), we may have to bounce it as well. | |||
190 | * | |||
191 | * Well, not really... see note above regarding DMA ranges. | |||
192 | * Because of the range issue on this platform, we just | |||
193 | * always "might bounce". | |||
194 | */ | |||
195 | cookieflags = ID_MIGHT_NEED_BOUNCE; | |||
196 | cookiesize += (sizeof(bus_dma_segment_t) * map->_dm_segcnt); | |||
197 | ||||
198 | /* | |||
199 | * Allocate our cookie. | |||
200 | */ | |||
201 | if ((cookiestore = malloc(cookiesize, M_DMAMAP, | |||
202 | (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL) { | |||
203 | error = ENOMEM; | |||
204 | goto out; | |||
205 | } | |||
206 | memset(cookiestore, 0, cookiesize); | |||
207 | cookie = (struct arm32_isa_dma_cookie *)cookiestore; | |||
208 | cookie->id_flags = cookieflags; | |||
209 | map->_dm_cookie = cookie; | |||
210 | ||||
211 | if (cookieflags & ID_MIGHT_NEED_BOUNCE) { | |||
212 | /* | |||
213 | * Allocate the bounce pages now if the caller | |||
214 | * wishes us to do so. | |||
215 | */ | |||
216 | if ((flags & BUS_DMA_ALLOCNOW) == 0) | |||
217 | goto out; | |||
218 | ||||
219 | error = _isa_dma_alloc_bouncebuf(t, map, size, flags); | |||
220 | } | |||
221 | ||||
222 | out: | |||
223 | if (error) { | |||
224 | if (map->_dm_cookie != NULL) | |||
225 | free(map->_dm_cookie, M_DMAMAP); | |||
226 | _bus_dmamap_destroy(t, map); | |||
227 | } | |||
228 | return (error); | |||
229 | } | |||
230 | ||||
231 | /* | |||
232 | * Destroy an ISA DMA map. | |||
233 | */ | |||
234 | void | |||
235 | _isa_bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map) | |||
236 | { | |||
237 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
238 | ||||
239 | /* | |||
240 | * Free any bounce pages this map might hold. | |||
241 | */ | |||
242 | if (cookie->id_flags & ID_HAS_BOUNCE) | |||
243 | _isa_dma_free_bouncebuf(t, map); | |||
244 | ||||
245 | free(cookie, M_DMAMAP); | |||
246 | _bus_dmamap_destroy(t, map); | |||
247 | } | |||
248 | ||||
249 | /* | |||
250 | * Load an ISA DMA map with a linear buffer. | |||
251 | */ | |||
252 | int | |||
253 | _isa_bus_dmamap_load( | |||
254 | bus_dma_tag_t t, | |||
255 | bus_dmamap_t map, | |||
256 | void *buf, | |||
257 | bus_size_t buflen, | |||
258 | struct proc *p, | |||
259 | int flags) | |||
260 | { | |||
261 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
262 | int error; | |||
263 | ||||
264 | STAT_INCR(isa_dma_stats_loads); | |||
265 | ||||
266 | /* | |||
267 | * Make sure that on error condition we return "no valid mappings." | |||
268 | */ | |||
269 | map->dm_mapsize = 0; | |||
270 | map->dm_nsegs = 0; | |||
271 | ||||
272 | /* | |||
273 | * Try to load the map the normal way. If this errors out, | |||
274 | * and we can bounce, we will. | |||
275 | */ | |||
276 | error = _bus_dmamap_load(t, map, buf, buflen, p, flags); | |||
277 | if (error == 0 || | |||
278 | (error != 0 && (cookie->id_flags & ID_MIGHT_NEED_BOUNCE) == 0)) | |||
279 | return (error); | |||
280 | ||||
281 | /* | |||
282 | * First attempt failed; bounce it. | |||
283 | */ | |||
284 | ||||
285 | STAT_INCR(isa_dma_stats_bounces); | |||
286 | ||||
287 | /* | |||
288 | * Allocate bounce pages, if necessary. | |||
289 | */ | |||
290 | if ((cookie->id_flags & ID_HAS_BOUNCE) == 0) { | |||
291 | error = _isa_dma_alloc_bouncebuf(t, map, buflen, flags); | |||
292 | if (error) | |||
293 | return (error); | |||
294 | } | |||
295 | ||||
296 | /* | |||
297 | * Cache a pointer to the caller's buffer and load the DMA map | |||
298 | * with the bounce buffer. | |||
299 | */ | |||
300 | cookie->id_origbuf = buf; | |||
301 | cookie->id_origbuflen = buflen; | |||
302 | cookie->id_buftype = ID_BUFTYPE_LINEAR; | |||
303 | error = _bus_dmamap_load(t, map, cookie->id_bouncebuf, buflen, | |||
304 | NULL, flags); | |||
305 | if (error) { | |||
306 | /* | |||
307 | * Free the bounce pages, unless our resources | |||
308 | * are reserved for our exclusive use. | |||
309 | */ | |||
310 | if ((map->_dm_flags & BUS_DMA_ALLOCNOW) == 0) | |||
311 | _isa_dma_free_bouncebuf(t, map); | |||
312 | return (error); | |||
313 | } | |||
314 | ||||
315 | /* ...so _isa_bus_dmamap_sync() knows we're bouncing */ | |||
316 | cookie->id_flags |= ID_IS_BOUNCING; | |||
317 | return (0); | |||
318 | } | |||
319 | ||||
320 | /* | |||
321 | * Like _isa_bus_dmamap_load(), but for mbufs. | |||
322 | */ | |||
323 | int | |||
324 | _isa_bus_dmamap_load_mbuf( | |||
325 | bus_dma_tag_t t, | |||
326 | bus_dmamap_t map, | |||
327 | struct mbuf *m0, | |||
328 | int flags) | |||
329 | { | |||
330 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
331 | int error; | |||
332 | ||||
333 | /* | |||
334 | * Make sure that on error condition we return "no valid mappings." | |||
335 | */ | |||
336 | map->dm_mapsize = 0; | |||
337 | map->dm_nsegs = 0; | |||
338 | ||||
339 | #ifdef DIAGNOSTIC | |||
340 | if ((m0->m_flags & M_PKTHDR) == 0) | |||
341 | panic("_isa_bus_dmamap_load_mbuf: no packet header"); | |||
342 | #endif | |||
343 | ||||
344 | if (m0->m_pkthdr.len > map->_dm_size) | |||
345 | return (EINVAL); | |||
346 | ||||
347 | /* | |||
348 | * Try to load the map the normal way. If this errors out, | |||
349 | * and we can bounce, we will. | |||
350 | */ | |||
351 | error = _bus_dmamap_load_mbuf(t, map, m0, flags); | |||
352 | if (error == 0 || | |||
353 | (error != 0 && (cookie->id_flags & ID_MIGHT_NEED_BOUNCE) == 0)) | |||
354 | return (error); | |||
355 | ||||
356 | /* | |||
357 | * First attempt failed; bounce it. | |||
358 | */ | |||
359 | ||||
360 | STAT_INCR(isa_dma_stats_bounces); | |||
361 | ||||
362 | /* | |||
363 | * Allocate bounce pages, if necessary. | |||
364 | */ | |||
365 | if ((cookie->id_flags & ID_HAS_BOUNCE) == 0) { | |||
366 | error = _isa_dma_alloc_bouncebuf(t, map, m0->m_pkthdr.len, | |||
367 | flags); | |||
368 | if (error) | |||
369 | return (error); | |||
370 | } | |||
371 | ||||
372 | /* | |||
373 | * Cache a pointer to the caller's buffer and load the DMA map | |||
374 | * with the bounce buffer. | |||
375 | */ | |||
376 | cookie->id_origbuf = m0; | |||
377 | cookie->id_origbuflen = m0->m_pkthdr.len; /* not really used */ | |||
378 | cookie->id_buftype = ID_BUFTYPE_MBUF; | |||
379 | error = _bus_dmamap_load(t, map, cookie->id_bouncebuf, | |||
380 | m0->m_pkthdr.len, NULL, flags); | |||
381 | if (error) { | |||
382 | /* | |||
383 | * Free the bounce pages, unless our resources | |||
384 | * are reserved for our exclusive use. | |||
385 | */ | |||
386 | if ((map->_dm_flags & BUS_DMA_ALLOCNOW) == 0) | |||
387 | _isa_dma_free_bouncebuf(t, map); | |||
388 | return (error); | |||
389 | } | |||
390 | ||||
391 | /* ...so _isa_bus_dmamap_sync() knows we're bouncing */ | |||
392 | cookie->id_flags |= ID_IS_BOUNCING; | |||
393 | return (0); | |||
394 | } | |||
395 | ||||
396 | /* | |||
397 | * Like _isa_bus_dmamap_load(), but for uios. | |||
398 | */ | |||
399 | int | |||
400 | _isa_bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio, int flags) | |||
401 | { | |||
402 | ||||
403 | panic("_isa_bus_dmamap_load_uio: not implemented"); | |||
404 | } | |||
405 | ||||
406 | /* | |||
407 | * Like _isa_bus_dmamap_load(), but for raw memory allocated with | |||
408 | * bus_dmamem_alloc(). | |||
409 | */ | |||
410 | int | |||
411 | _isa_bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) | |||
412 | { | |||
413 | ||||
414 | panic("_isa_bus_dmamap_load_raw: not implemented"); | |||
415 | } | |||
416 | ||||
417 | /* | |||
418 | * Unload an ISA DMA map. | |||
419 | */ | |||
420 | void | |||
421 | _isa_bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map) | |||
422 | { | |||
423 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
424 | ||||
425 | /* | |||
426 | * If we have bounce pages, free them, unless they're | |||
427 | * reserved for our exclusive use. | |||
428 | */ | |||
429 | if ((cookie->id_flags & ID_HAS_BOUNCE) && | |||
430 | (map->_dm_flags & BUS_DMA_ALLOCNOW) == 0) | |||
431 | _isa_dma_free_bouncebuf(t, map); | |||
432 | ||||
433 | cookie->id_flags &= ~ID_IS_BOUNCING; | |||
434 | cookie->id_buftype = ID_BUFTYPE_INVALID; | |||
435 | ||||
436 | /* | |||
437 | * Do the generic bits of the unload. | |||
438 | */ | |||
439 | _bus_dmamap_unload(t, map); | |||
440 | } | |||
441 | ||||
442 | /* | |||
443 | * Synchronize an ISA DMA map. | |||
444 | */ | |||
445 | void | |||
446 | _isa_bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset, bus_size_t len, int ops) | |||
447 | { | |||
448 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
449 | ||||
450 | /* | |||
451 | * Mixing PRE and POST operations is not allowed. | |||
452 | */ | |||
453 | if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 && | |||
454 | (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0) | |||
455 | panic("_isa_bus_dmamap_sync: mix PRE and POST"); | |||
456 | ||||
457 | #ifdef DIAGNOSTIC | |||
458 | if ((ops & (BUS_DMASYNC_PREWRITE|BUS_DMASYNC_POSTREAD)) != 0) { | |||
459 | if (offset >= map->dm_mapsize) | |||
460 | panic("_isa_bus_dmamap_sync: bad offset"); | |||
461 | if (len == 0 || (offset + len) > map->dm_mapsize) | |||
462 | panic("_isa_bus_dmamap_sync: bad length"); | |||
463 | } | |||
464 | #endif | |||
465 | ||||
466 | /* | |||
467 | * If we're not bouncing, just return; nothing to do. | |||
468 | */ | |||
469 | if ((cookie->id_flags & ID_IS_BOUNCING) == 0) | |||
470 | return; | |||
471 | ||||
472 | switch (cookie->id_buftype) { | |||
473 | case ID_BUFTYPE_LINEAR: | |||
474 | /* | |||
475 | * Nothing to do for pre-read. | |||
476 | */ | |||
477 | ||||
478 | if (ops & BUS_DMASYNC_PREWRITE) { | |||
479 | /* | |||
480 | * Copy the caller's buffer to the bounce buffer. | |||
481 | */ | |||
482 | memcpy((char *)cookie->id_bouncebuf + offset, | |||
483 | (char *)cookie->id_origbuf + offset, len); | |||
484 | } | |||
485 | ||||
486 | if (ops & BUS_DMASYNC_POSTREAD) { | |||
487 | /* | |||
488 | * Copy the bounce buffer to the caller's buffer. | |||
489 | */ | |||
490 | memcpy((char *)cookie->id_origbuf + offset, | |||
491 | (char *)cookie->id_bouncebuf + offset, len); | |||
492 | } | |||
493 | ||||
494 | /* | |||
495 | * Nothing to do for post-write. | |||
496 | */ | |||
497 | break; | |||
498 | ||||
499 | case ID_BUFTYPE_MBUF: | |||
500 | { | |||
501 | struct mbuf *m, *m0 = cookie->id_origbuf; | |||
502 | bus_size_t minlen, moff; | |||
503 | ||||
504 | /* | |||
505 | * Nothing to do for pre-read. | |||
506 | */ | |||
507 | ||||
508 | if (ops & BUS_DMASYNC_PREWRITE) { | |||
509 | /* | |||
510 | * Copy the caller's buffer to the bounce buffer. | |||
511 | */ | |||
512 | m_copydata(m0, offset, len, | |||
513 | (char *)cookie->id_bouncebuf + offset); | |||
514 | } | |||
515 | ||||
516 | if (ops & BUS_DMASYNC_POSTREAD) { | |||
517 | /* | |||
518 | * Copy the bounce buffer to the caller's buffer. | |||
519 | */ | |||
520 | for (moff = offset, m = m0; m != NULL && len != 0; | |||
521 | m = m->m_next) { | |||
522 | /* Find the beginning mbuf. */ | |||
523 | if (moff >= m->m_len) { | |||
524 | moff -= m->m_len; | |||
525 | continue; | |||
526 | } | |||
527 | ||||
528 | /* | |||
529 | * Now at the first mbuf to sync; nail | |||
530 | * each one until we have exhausted the | |||
531 | * length. | |||
532 | */ | |||
533 | minlen = len < m->m_len - moff ? | |||
534 | len : m->m_len - moff; | |||
535 | ||||
536 | memcpy(mtod(m, char *) + moff, | |||
537 | (char *)cookie->id_bouncebuf + offset, | |||
538 | minlen); | |||
539 | ||||
540 | moff = 0; | |||
541 | len -= minlen; | |||
542 | offset += minlen; | |||
543 | } | |||
544 | } | |||
545 | ||||
546 | /* | |||
547 | * Nothing to do for post-write. | |||
548 | */ | |||
549 | break; | |||
550 | } | |||
551 | ||||
552 | case ID_BUFTYPE_UIO: | |||
553 | panic("_isa_bus_dmamap_sync: ID_BUFTYPE_UIO"); | |||
554 | break; | |||
555 | ||||
556 | case ID_BUFTYPE_RAW: | |||
557 | panic("_isa_bus_dmamap_sync: ID_BUFTYPE_RAW"); | |||
558 | break; | |||
559 | ||||
560 | case ID_BUFTYPE_INVALID: | |||
561 | panic("_isa_bus_dmamap_sync: ID_BUFTYPE_INVALID"); | |||
562 | break; | |||
563 | ||||
564 | default: | |||
565 | printf("unknown buffer type %d\n", cookie->id_buftype); | |||
566 | panic("_isa_bus_dmamap_sync"); | |||
567 | } | |||
568 | } | |||
569 | ||||
570 | /* | |||
571 | * Allocate memory safe for ISA DMA. | |||
572 | */ | |||
573 | int | |||
574 | _isa_bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags) | |||
575 | { | |||
576 | ||||
577 | if (t->_ranges == NULL) | |||
578 | return (ENOMEM); | |||
579 | ||||
580 | /* _bus_dmamem_alloc() does the range checks for us. */ | |||
581 | return (_bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, | |||
582 | rsegs, flags)); | |||
583 | } | |||
584 | ||||
585 | /********************************************************************** | |||
586 | * ISA DMA utility functions | |||
587 | **********************************************************************/ | |||
588 | ||||
589 | int | |||
590 | _isa_dma_alloc_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map, bus_size_t size, int flags) | |||
591 | { | |||
592 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
593 | int error = 0; | |||
594 | ||||
595 | cookie->id_bouncebuflen = round_page(size); | |||
596 | error = _isa_bus_dmamem_alloc(t, cookie->id_bouncebuflen, | |||
597 | PAGE_SIZE, map->_dm_boundary, cookie->id_bouncesegs, | |||
598 | map->_dm_segcnt, &cookie->id_nbouncesegs, flags); | |||
599 | if (error) | |||
600 | goto out; | |||
601 | error = _bus_dmamem_map(t, cookie->id_bouncesegs, | |||
602 | cookie->id_nbouncesegs, cookie->id_bouncebuflen, | |||
603 | (void **)&cookie->id_bouncebuf, flags); | |||
604 | ||||
605 | out: | |||
606 | if (error) { | |||
607 | _bus_dmamem_free(t, cookie->id_bouncesegs, | |||
608 | cookie->id_nbouncesegs); | |||
609 | cookie->id_bouncebuflen = 0; | |||
610 | cookie->id_nbouncesegs = 0; | |||
611 | } else { | |||
612 | cookie->id_flags |= ID_HAS_BOUNCE; | |||
613 | STAT_INCR(isa_dma_stats_nbouncebufs); | |||
614 | } | |||
615 | ||||
616 | return (error); | |||
617 | } | |||
618 | ||||
619 | void | |||
620 | _isa_dma_free_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map) | |||
621 | { | |||
622 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
623 | ||||
624 | STAT_DECR(isa_dma_stats_nbouncebufs); | |||
625 | ||||
626 | _bus_dmamem_unmap(t, cookie->id_bouncebuf, | |||
627 | cookie->id_bouncebuflen); | |||
628 | _bus_dmamem_free(t, cookie->id_bouncesegs, | |||
629 | cookie->id_nbouncesegs); | |||
630 | cookie->id_bouncebuflen = 0; | |||
631 | cookie->id_nbouncesegs = 0; | |||
632 | cookie->id_flags &= ~ID_HAS_BOUNCE; | |||
633 | } |
--- src/sys/arch/arm/include/isa_machdep.h 2011/07/01 21:16:40 1.8
+++ src/sys/arch/arm/include/isa_machdep.h 2012/09/21 14:21:57 1.9
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: isa_machdep.h,v 1.8 2011/07/01 21:16:40 dyoung Exp $ */ | 1 | /* $NetBSD: isa_machdep.h,v 1.9 2012/09/21 14:21:57 matt Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
9 | * NASA Ames Research Center. | 9 | * NASA Ames Research Center. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -105,62 +105,26 @@ void isa_intr_disestablish(isa_chipset_t | @@ -105,62 +105,26 @@ void isa_intr_disestablish(isa_chipset_t | |||
105 | _isa_malloc(&(ic)->ic_dmastate, (c), (s), (p), (f)) | 105 | _isa_malloc(&(ic)->ic_dmastate, (c), (s), (p), (f)) | |
106 | #define isa_free(a, p) \ | 106 | #define isa_free(a, p) \ | |
107 | _isa_free((a), (p)) | 107 | _isa_free((a), (p)) | |
108 | #define isa_mappage(m, o, p) \ | 108 | #define isa_mappage(m, o, p) \ | |
109 | _isa_mappage((m), (o), (p)) | 109 | _isa_mappage((m), (o), (p)) | |
110 | 110 | |||
111 | /* | 111 | /* | |
112 | * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED | 112 | * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED | |
113 | * BY PORTABLE CODE. | 113 | * BY PORTABLE CODE. | |
114 | */ | 114 | */ | |
115 | 115 | |||
116 | extern struct arm32_bus_dma_tag isa_bus_dma_tag; | 116 | extern struct arm32_bus_dma_tag isa_bus_dma_tag; | |
117 | 117 | |||
118 | /* | |||
119 | * Cookie used by ISA DMA. A pointer to one of these is stashed in | |||
120 | * the DMA map. | |||
121 | */ | |||
122 | struct arm32_isa_dma_cookie { | |||
123 | int id_flags; /* flags; see below */ | |||
124 | ||||
125 | /* | |||
126 | * Information about the original buffer used during | |||
127 | * DMA map syncs. Note that origbuflen is only used | |||
128 | * for ID_BUFTYPE_LINEAR. | |||
129 | */ | |||
130 | void *id_origbuf; /* pointer to orig buffer if | |||
131 | bouncing */ | |||
132 | bus_size_t id_origbuflen; /* ...and size */ | |||
133 | int id_buftype; /* type of buffer */ | |||
134 | ||||
135 | void *id_bouncebuf; /* pointer to the bounce buffer */ | |||
136 | bus_size_t id_bouncebuflen; /* ...and size */ | |||
137 | int id_nbouncesegs; /* number of valid bounce segs */ | |||
138 | bus_dma_segment_t id_bouncesegs[0]; /* array of bounce buffer | |||
139 | physical memory segments */ | |||
140 | }; | |||
141 | ||||
142 | /* id_flags */ | |||
143 | #define ID_MIGHT_NEED_BOUNCE 0x01 /* map could need bounce buffers */ | |||
144 | #define ID_HAS_BOUNCE 0x02 /* map currently has bounce buffers */ | |||
145 | #define ID_IS_BOUNCING 0x04 /* map is bouncing current xfer */ | |||
146 | ||||
147 | /* id_buftype */ | |||
148 | #define ID_BUFTYPE_INVALID 0 | |||
149 | #define ID_BUFTYPE_LINEAR 1 | |||
150 | #define ID_BUFTYPE_MBUF 2 | |||
151 | #define ID_BUFTYPE_UIO 3 | |||
152 | #define ID_BUFTYPE_RAW 4 | |||
153 | ||||
154 | /* bus space tags */ | 118 | /* bus space tags */ | |
155 | extern struct bus_space isa_io_bs_tag; | 119 | extern struct bus_space isa_io_bs_tag; | |
156 | extern struct bus_space isa_mem_bs_tag; | 120 | extern struct bus_space isa_mem_bs_tag; | |
157 | 121 | |||
158 | /* ISA chipset */ | 122 | /* ISA chipset */ | |
159 | extern struct arm32_isa_chipset isa_chipset_tag; | 123 | extern struct arm32_isa_chipset isa_chipset_tag; | |
160 | 124 | |||
161 | /* for pccons.c */ | 125 | /* for pccons.c */ | |
162 | #define MONO_BASE 0x3B4 | 126 | #define MONO_BASE 0x3B4 | |
163 | #define MONO_BUF 0x000B0000 | 127 | #define MONO_BUF 0x000B0000 | |
164 | #define CGA_BASE 0x3D4 | 128 | #define CGA_BASE 0x3D4 | |
165 | #define CGA_BUF 0x000B8000 | 129 | #define CGA_BUF 0x000B8000 | |
166 | #define VGA_BUF 0xA0000 | 130 | #define VGA_BUF 0xA0000 |
--- src/sys/arch/shark/conf/std.shark 2008/01/27 12:37:12 1.8
+++ src/sys/arch/shark/conf/std.shark 2012/09/21 14:21:58 1.9
@@ -1,24 +1,25 @@ | @@ -1,24 +1,25 @@ | |||
1 | # $NetBSD: std.shark,v 1.8 2008/01/27 12:37:12 chris Exp $ | 1 | # $NetBSD: std.shark,v 1.9 2012/09/21 14:21:58 matt Exp $ | |
2 | # | 2 | # | |
3 | # standard NetBSD/shark options | 3 | # standard NetBSD/shark options | |
4 | 4 | |||
5 | machine shark arm | 5 | machine shark arm | |
6 | include "conf/std" # MI standard options | 6 | include "conf/std" # MI standard options | |
7 | include "arch/arm/conf/std.arm" # arch standard options | 7 | include "arch/arm/conf/std.arm" # arch standard options | |
8 | 8 | |||
9 | options EXEC_AOUT | 9 | options EXEC_AOUT | |
10 | options EXEC_ELF32 | 10 | options EXEC_ELF32 | |
11 | options EXEC_SCRIPT | 11 | options EXEC_SCRIPT | |
12 | 12 | |||
13 | # To support easy transit to ../arch/arm/arm32 | 13 | # To support easy transit to ../arch/arm/arm32 | |
14 | options ARM32 | 14 | options ARM32 | |
15 | options _ARM32_NEED_BUS_DMA_BOUNCE | |||
15 | 16 | |||
16 | #options ARM32_NEW_VM_LAYOUT # Not yet ready for prime-time | 17 | #options ARM32_NEW_VM_LAYOUT # Not yet ready for prime-time | |
17 | 18 | |||
18 | # XXX | 19 | # XXX | |
19 | options OFW | 20 | options OFW | |
20 | 21 | |||
21 | # The font to be used by vga(4); the hardware built-in font is broken. | 22 | # The font to be used by vga(4); the hardware built-in font is broken. | |
22 | # This also requires wsfont to be useful. Does not disturb if it is | 23 | # This also requires wsfont to be useful. Does not disturb if it is | |
23 | # not enabled. | 24 | # not enabled. | |
24 | options FONT_VT220L8x16 | 25 | options FONT_VT220L8x16 |
--- src/sys/arch/shark/isa/isadma_machdep.c 2012/01/31 04:28:50 1.16
+++ src/sys/arch/shark/isa/isadma_machdep.c 2012/09/21 14:21:58 1.17
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: isadma_machdep.c,v 1.16 2012/01/31 04:28:50 matt Exp $ */ | 1 | /* $NetBSD: isadma_machdep.c,v 1.17 2012/09/21 14:21:58 matt Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
9 | * NASA Ames Research Center. | 9 | * NASA Ames Research Center. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -21,27 +21,27 @@ | @@ -21,27 +21,27 @@ | |||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/cdefs.h> | 33 | #include <sys/cdefs.h> | |
34 | __KERNEL_RCSID(0, "$NetBSD: isadma_machdep.c,v 1.16 2012/01/31 04:28:50 matt Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: isadma_machdep.c,v 1.17 2012/09/21 14:21:58 matt Exp $"); | |
35 | 35 | |||
36 | #define ISA_DMA_STATS | 36 | #define ISA_DMA_STATS | |
37 | 37 | |||
38 | #include <sys/param.h> | 38 | #include <sys/param.h> | |
39 | #include <sys/systm.h> | 39 | #include <sys/systm.h> | |
40 | #include <sys/syslog.h> | 40 | #include <sys/syslog.h> | |
41 | #include <sys/device.h> | 41 | #include <sys/device.h> | |
42 | #include <sys/malloc.h> | 42 | #include <sys/malloc.h> | |
43 | #include <sys/proc.h> | 43 | #include <sys/proc.h> | |
44 | #include <sys/mbuf.h> | 44 | #include <sys/mbuf.h> | |
45 | 45 | |||
46 | #define _ARM32_BUS_DMA_PRIVATE | 46 | #define _ARM32_BUS_DMA_PRIVATE | |
47 | #include <sys/bus.h> | 47 | #include <sys/bus.h> | |
@@ -53,571 +53,34 @@ __KERNEL_RCSID(0, "$NetBSD: isadma_machd | @@ -53,571 +53,34 @@ __KERNEL_RCSID(0, "$NetBSD: isadma_machd | |||
53 | 53 | |||
54 | /* | 54 | /* | |
55 | * ISA has a 24-bit address limitation, so at most it has a 16M | 55 | * ISA has a 24-bit address limitation, so at most it has a 16M | |
56 | * DMA range. However, some platforms have a more limited range, | 56 | * DMA range. However, some platforms have a more limited range, | |
57 | * e.g. the Shark NC. On these systems, we are provided with | 57 | * e.g. the Shark NC. On these systems, we are provided with | |
58 | * a set of DMA ranges. The pmap module is aware of these ranges | 58 | * a set of DMA ranges. The pmap module is aware of these ranges | |
59 | * and places DMA-safe memory for them onto an alternate free list | 59 | * and places DMA-safe memory for them onto an alternate free list | |
60 | * so that they are protected from being used to service page faults, | 60 | * so that they are protected from being used to service page faults, | |
61 | * etc. (unless we've run out of memory elsewhere). | 61 | * etc. (unless we've run out of memory elsewhere). | |
62 | */ | 62 | */ | |
63 | extern struct arm32_dma_range *shark_isa_dma_ranges; | 63 | extern struct arm32_dma_range *shark_isa_dma_ranges; | |
64 | extern int shark_isa_dma_nranges; | 64 | extern int shark_isa_dma_nranges; | |
65 | 65 | |||
66 | int _isa_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, | |||
67 | bus_size_t, bus_size_t, int, bus_dmamap_t *); | |||
68 | void _isa_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); | |||
69 | int _isa_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, | |||
70 | bus_size_t, struct proc *, int); | |||
71 | int _isa_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, | |||
72 | struct mbuf *, int); | |||
73 | int _isa_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, | |||
74 | struct uio *, int); | |||
75 | int _isa_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, | |||
76 | bus_dma_segment_t *, int, bus_size_t, int); | |||
77 | void _isa_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); | |||
78 | void _isa_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, | |||
79 | bus_addr_t, bus_size_t, int); | |||
80 | ||||
81 | int _isa_bus_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, | |||
82 | bus_size_t, bus_dma_segment_t *, int, int *, int); | |||
83 | ||||
84 | int _isa_dma_alloc_bouncebuf(bus_dma_tag_t, bus_dmamap_t, | |||
85 | bus_size_t, int); | |||
86 | void _isa_dma_free_bouncebuf(bus_dma_tag_t, bus_dmamap_t); | |||
87 | ||||
88 | /* | 66 | /* | |
89 | * Entry points for ISA DMA. These are mostly wrappers around | 67 | * Entry points for ISA DMA. These are mostly wrappers around | |
90 | * the generic functions that understand how to deal with bounce | 68 | * the generic functions that understand how to deal with bounce | |
91 | * buffers, if necessary. | 69 | * buffers, if necessary. | |
92 | */ | 70 | */ | |
93 | struct arm32_bus_dma_tag isa_bus_dma_tag = { | 71 | struct arm32_bus_dma_tag isa_bus_dma_tag = { | |
94 | 0, /* _ranges */ | 72 | _BUS_DMAMAP_FUNCS, | |
95 | 0, /* _nranges */ | 73 | _BUS_DMAMEM_FUNCS, | |
96 | NULL, /* _cookie */ | 74 | _BUS_DMATAG_FUNCS, | |
97 | _isa_bus_dmamap_create, | |||
98 | _isa_bus_dmamap_destroy, | |||
99 | _isa_bus_dmamap_load, | |||
100 | _isa_bus_dmamap_load_mbuf, | |||
101 | _isa_bus_dmamap_load_uio, | |||
102 | _isa_bus_dmamap_load_raw, | |||
103 | _isa_bus_dmamap_unload, | |||
104 | _isa_bus_dmamap_sync, /* pre */ | |||
105 | _isa_bus_dmamap_sync, /* post */ | |||
106 | _isa_bus_dmamem_alloc, | |||
107 | _bus_dmamem_free, | |||
108 | _bus_dmamem_map, | |||
109 | _bus_dmamem_unmap, | |||
110 | _bus_dmamem_mmap, | |||
111 | }; | 75 | }; | |
112 | 76 | |||
113 | /* | 77 | /* | |
114 | * Initialize ISA DMA. | 78 | * Initialize ISA DMA. | |
115 | */ | 79 | */ | |
116 | void | 80 | void | |
117 | isa_dma_init(void) | 81 | isa_dma_init(void) | |
118 | { | 82 | { | |
119 | 83 | |||
120 | isa_bus_dma_tag._ranges = shark_isa_dma_ranges; | 84 | isa_bus_dma_tag._ranges = shark_isa_dma_ranges; | |
121 | isa_bus_dma_tag._nranges = shark_isa_dma_nranges; | 85 | isa_bus_dma_tag._nranges = shark_isa_dma_nranges; | |
122 | } | 86 | } | |
123 | ||||
124 | /********************************************************************** | |||
125 | * bus.h dma interface entry points | |||
126 | **********************************************************************/ | |||
127 | ||||
128 | #ifdef ISA_DMA_STATS | |||
129 | #define STAT_INCR(v) (v)++ | |||
130 | #define STAT_DECR(v) do { \ | |||
131 | if ((v) == 0) \ | |||
132 | printf("%s:%d -- Already 0!\n", __FILE__, __LINE__); \ | |||
133 | else \ | |||
134 | (v)--; \ | |||
135 | } while (0) | |||
136 | u_long isa_dma_stats_loads; | |||
137 | u_long isa_dma_stats_bounces; | |||
138 | u_long isa_dma_stats_nbouncebufs; | |||
139 | #else | |||
140 | #define STAT_INCR(v) | |||
141 | #define STAT_DECR(v) | |||
142 | #endif | |||
143 | ||||
144 | /* | |||
145 | * Create an ISA DMA map. | |||
146 | */ | |||
147 | int | |||
148 | _isa_bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) | |||
149 | { | |||
150 | struct arm32_isa_dma_cookie *cookie; | |||
151 | bus_dmamap_t map; | |||
152 | int error, cookieflags; | |||
153 | void *cookiestore; | |||
154 | size_t cookiesize; | |||
155 | ||||
156 | /* Call common function to create the basic map. */ | |||
157 | error = _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, | |||
158 | flags, dmamp); | |||
159 | if (error) | |||
160 | return (error); | |||
161 | ||||
162 | map = *dmamp; | |||
163 | map->_dm_cookie = NULL; | |||
164 | ||||
165 | cookiesize = sizeof(struct arm32_isa_dma_cookie); | |||
166 | ||||
167 | /* | |||
168 | * ISA only has 24-bits of address space. This means | |||
169 | * we can't DMA to pages over 16M. In order to DMA to | |||
170 | * arbitrary buffers, we use "bounce buffers" - pages | |||
171 | * in memory below the 16M boundary. On DMA reads, | |||
172 | * DMA happens to the bounce buffers, and is copied into | |||
173 | * the caller's buffer. On writes, data is copied into | |||
174 | * but bounce buffer, and the DMA happens from those | |||
175 | * pages. To software using the DMA mapping interface, | |||
176 | * this looks simply like a data cache. | |||
177 | * | |||
178 | * If we have more than 16M of RAM in the system, we may | |||
179 | * need bounce buffers. We check and remember that here. | |||
180 | * | |||
181 | * There are exceptions, however. VLB devices can do | |||
182 | * 32-bit DMA, and indicate that here. | |||
183 | * | |||
184 | * ...or, there is an opposite case. The most segments | |||
185 | * a transfer will require is (maxxfer / PAGE_SIZE) + 1. If | |||
186 | * the caller can't handle that many segments (e.g. the | |||
187 | * ISA DMA controller), we may have to bounce it as well. | |||
188 | * | |||
189 | * Well, not really... see note above regarding DMA ranges. | |||
190 | * Because of the range issue on this platform, we just | |||
191 | * always "might bounce". | |||
192 | */ | |||
193 | cookieflags = ID_MIGHT_NEED_BOUNCE; | |||
194 | cookiesize += (sizeof(bus_dma_segment_t) * map->_dm_segcnt); | |||
195 | ||||
196 | /* | |||
197 | * Allocate our cookie. | |||
198 | */ | |||
199 | if ((cookiestore = malloc(cookiesize, M_DMAMAP, | |||
200 | (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL) { | |||
201 | error = ENOMEM; | |||
202 | goto out; | |||
203 | } | |||
204 | memset(cookiestore, 0, cookiesize); | |||
205 | cookie = (struct arm32_isa_dma_cookie *)cookiestore; | |||
206 | cookie->id_flags = cookieflags; | |||
207 | map->_dm_cookie = cookie; | |||
208 | ||||
209 | if (cookieflags & ID_MIGHT_NEED_BOUNCE) { | |||
210 | /* | |||
211 | * Allocate the bounce pages now if the caller | |||
212 | * wishes us to do so. | |||
213 | */ | |||
214 | if ((flags & BUS_DMA_ALLOCNOW) == 0) | |||
215 | goto out; | |||
216 | ||||
217 | error = _isa_dma_alloc_bouncebuf(t, map, size, flags); | |||
218 | } | |||
219 | ||||
220 | out: | |||
221 | if (error) { | |||
222 | if (map->_dm_cookie != NULL) | |||
223 | free(map->_dm_cookie, M_DMAMAP); | |||
224 | _bus_dmamap_destroy(t, map); | |||
225 | } | |||
226 | return (error); | |||
227 | } | |||
228 | ||||
229 | /* | |||
230 | * Destroy an ISA DMA map. | |||
231 | */ | |||
232 | void | |||
233 | _isa_bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map) | |||
234 | { | |||
235 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
236 | ||||
237 | /* | |||
238 | * Free any bounce pages this map might hold. | |||
239 | */ | |||
240 | if (cookie->id_flags & ID_HAS_BOUNCE) | |||
241 | _isa_dma_free_bouncebuf(t, map); | |||
242 | ||||
243 | free(cookie, M_DMAMAP); | |||
244 | _bus_dmamap_destroy(t, map); | |||
245 | } | |||
246 | ||||
247 | /* | |||
248 | * Load an ISA DMA map with a linear buffer. | |||
249 | */ | |||
250 | int | |||
251 | _isa_bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf, | |||
252 | bus_size_t buflen, struct proc *p, int flags) | |||
253 | { | |||
254 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
255 | int error; | |||
256 | ||||
257 | STAT_INCR(isa_dma_stats_loads); | |||
258 | ||||
259 | /* | |||
260 | * Make sure that on error condition we return "no valid mappings." | |||
261 | */ | |||
262 | map->dm_mapsize = 0; | |||
263 | map->dm_nsegs = 0; | |||
264 | ||||
265 | /* | |||
266 | * Try to load the map the normal way. If this errors out, | |||
267 | * and we can bounce, we will. | |||
268 | */ | |||
269 | error = _bus_dmamap_load(t, map, buf, buflen, p, flags); | |||
270 | if (error == 0 || | |||
271 | (error != 0 && (cookie->id_flags & ID_MIGHT_NEED_BOUNCE) == 0)) | |||
272 | return (error); | |||
273 | ||||
274 | /* | |||
275 | * First attempt failed; bounce it. | |||
276 | */ | |||
277 | ||||
278 | STAT_INCR(isa_dma_stats_bounces); | |||
279 | ||||
280 | /* | |||
281 | * Allocate bounce pages, if necessary. | |||
282 | */ | |||
283 | if ((cookie->id_flags & ID_HAS_BOUNCE) == 0) { | |||
284 | error = _isa_dma_alloc_bouncebuf(t, map, buflen, flags); | |||
285 | if (error) | |||
286 | return (error); | |||
287 | } | |||
288 | ||||
289 | /* | |||
290 | * Cache a pointer to the caller's buffer and load the DMA map | |||
291 | * with the bounce buffer. | |||
292 | */ | |||
293 | cookie->id_origbuf = buf; | |||
294 | cookie->id_origbuflen = buflen; | |||
295 | cookie->id_buftype = ID_BUFTYPE_LINEAR; | |||
296 | error = _bus_dmamap_load(t, map, cookie->id_bouncebuf, buflen, | |||
297 | NULL, flags); | |||
298 | if (error) { | |||
299 | /* | |||
300 | * Free the bounce pages, unless our resources | |||
301 | * are reserved for our exclusive use. | |||
302 | */ | |||
303 | if ((map->_dm_flags & BUS_DMA_ALLOCNOW) == 0) | |||
304 | _isa_dma_free_bouncebuf(t, map); | |||
305 | return (error); | |||
306 | } | |||
307 | ||||
308 | /* ...so _isa_bus_dmamap_sync() knows we're bouncing */ | |||
309 | cookie->id_flags |= ID_IS_BOUNCING; | |||
310 | return (0); | |||
311 | } | |||
312 | ||||
313 | /* | |||
314 | * Like _isa_bus_dmamap_load(), but for mbufs. | |||
315 | */ | |||
316 | int | |||
317 | _isa_bus_dmamap_load_mbuf( bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m0, | |||
318 | int flags) | |||
319 | { | |||
320 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
321 | int error; | |||
322 | ||||
323 | /* | |||
324 | * Make sure that on error condition we return "no valid mappings." | |||
325 | */ | |||
326 | map->dm_mapsize = 0; | |||
327 | map->dm_nsegs = 0; | |||
328 | ||||
329 | #ifdef DIAGNOSTIC | |||
330 | if ((m0->m_flags & M_PKTHDR) == 0) | |||
331 | panic("_isa_bus_dmamap_load_mbuf: no packet header"); | |||
332 | #endif | |||
333 | ||||
334 | if (m0->m_pkthdr.len > map->_dm_size) | |||
335 | return (EINVAL); | |||
336 | ||||
337 | /* | |||
338 | * Try to load the map the normal way. If this errors out, | |||
339 | * and we can bounce, we will. | |||
340 | */ | |||
341 | error = _bus_dmamap_load_mbuf(t, map, m0, flags); | |||
342 | if (error == 0 || | |||
343 | (error != 0 && (cookie->id_flags & ID_MIGHT_NEED_BOUNCE) == 0)) | |||
344 | return (error); | |||
345 | ||||
346 | /* | |||
347 | * First attempt failed; bounce it. | |||
348 | */ | |||
349 | ||||
350 | STAT_INCR(isa_dma_stats_bounces); | |||
351 | ||||
352 | /* | |||
353 | * Allocate bounce pages, if necessary. | |||
354 | */ | |||
355 | if ((cookie->id_flags & ID_HAS_BOUNCE) == 0) { | |||
356 | error = _isa_dma_alloc_bouncebuf(t, map, m0->m_pkthdr.len, | |||
357 | flags); | |||
358 | if (error) | |||
359 | return (error); | |||
360 | } | |||
361 | ||||
362 | /* | |||
363 | * Cache a pointer to the caller's buffer and load the DMA map | |||
364 | * with the bounce buffer. | |||
365 | */ | |||
366 | cookie->id_origbuf = m0; | |||
367 | cookie->id_origbuflen = m0->m_pkthdr.len; /* not really used */ | |||
368 | cookie->id_buftype = ID_BUFTYPE_MBUF; | |||
369 | error = _bus_dmamap_load(t, map, cookie->id_bouncebuf, | |||
370 | m0->m_pkthdr.len, NULL, flags); | |||
371 | if (error) { | |||
372 | /* | |||
373 | * Free the bounce pages, unless our resources | |||
374 | * are reserved for our exclusive use. | |||
375 | */ | |||
376 | if ((map->_dm_flags & BUS_DMA_ALLOCNOW) == 0) | |||
377 | _isa_dma_free_bouncebuf(t, map); | |||
378 | return (error); | |||
379 | } | |||
380 | ||||
381 | /* ...so _isa_bus_dmamap_sync() knows we're bouncing */ | |||
382 | cookie->id_flags |= ID_IS_BOUNCING; | |||
383 | return (0); | |||
384 | } | |||
385 | ||||
386 | /* | |||
387 | * Like _isa_bus_dmamap_load(), but for uios. | |||
388 | */ | |||
389 | int | |||
390 | _isa_bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio, int flags) | |||
391 | { | |||
392 | ||||
393 | panic("_isa_bus_dmamap_load_uio: not implemented"); | |||
394 | } | |||
395 | ||||
396 | /* | |||
397 | * Like _isa_bus_dmamap_load(), but for raw memory allocated with | |||
398 | * bus_dmamem_alloc(). | |||
399 | */ | |||
400 | int | |||
401 | _isa_bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) | |||
402 | { | |||
403 | ||||
404 | panic("_isa_bus_dmamap_load_raw: not implemented"); | |||
405 | } | |||
406 | ||||
407 | /* | |||
408 | * Unload an ISA DMA map. | |||
409 | */ | |||
410 | void | |||
411 | _isa_bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map) | |||
412 | { | |||
413 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
414 | ||||
415 | /* | |||
416 | * If we have bounce pages, free them, unless they're | |||
417 | * reserved for our exclusive use. | |||
418 | */ | |||
419 | if ((cookie->id_flags & ID_HAS_BOUNCE) && | |||
420 | (map->_dm_flags & BUS_DMA_ALLOCNOW) == 0) | |||
421 | _isa_dma_free_bouncebuf(t, map); | |||
422 | ||||
423 | cookie->id_flags &= ~ID_IS_BOUNCING; | |||
424 | cookie->id_buftype = ID_BUFTYPE_INVALID; | |||
425 | ||||
426 | /* | |||
427 | * Do the generic bits of the unload. | |||
428 | */ | |||
429 | _bus_dmamap_unload(t, map); | |||
430 | } | |||
431 | ||||
432 | /* | |||
433 | * Synchronize an ISA DMA map. | |||
434 | */ | |||
435 | void | |||
436 | _isa_bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset, bus_size_t len, int ops) | |||
437 | { | |||
438 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
439 | ||||
440 | /* | |||
441 | * Mixing PRE and POST operations is not allowed. | |||
442 | */ | |||
443 | if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 && | |||
444 | (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0) | |||
445 | panic("_isa_bus_dmamap_sync: mix PRE and POST"); | |||
446 | ||||
447 | #ifdef DIAGNOSTIC | |||
448 | if ((ops & (BUS_DMASYNC_PREWRITE|BUS_DMASYNC_POSTREAD)) != 0) { | |||
449 | if (offset >= map->dm_mapsize) | |||
450 | panic("_isa_bus_dmamap_sync: bad offset"); | |||
451 | if (len == 0 || (offset + len) > map->dm_mapsize) | |||
452 | panic("_isa_bus_dmamap_sync: bad length"); | |||
453 | } | |||
454 | #endif | |||
455 | ||||
456 | /* | |||
457 | * If we're not bouncing, just return; nothing to do. | |||
458 | */ | |||
459 | if ((cookie->id_flags & ID_IS_BOUNCING) == 0) | |||
460 | return; | |||
461 | ||||
462 | switch (cookie->id_buftype) { | |||
463 | case ID_BUFTYPE_LINEAR: | |||
464 | /* | |||
465 | * Nothing to do for pre-read. | |||
466 | */ | |||
467 | ||||
468 | if (ops & BUS_DMASYNC_PREWRITE) { | |||
469 | /* | |||
470 | * Copy the caller's buffer to the bounce buffer. | |||
471 | */ | |||
472 | memcpy((char *)cookie->id_bouncebuf + offset, | |||
473 | (char *)cookie->id_origbuf + offset, len); | |||
474 | } | |||
475 | ||||
476 | if (ops & BUS_DMASYNC_POSTREAD) { | |||
477 | /* | |||
478 | * Copy the bounce buffer to the caller's buffer. | |||
479 | */ | |||
480 | memcpy((char *)cookie->id_origbuf + offset, | |||
481 | (char *)cookie->id_bouncebuf + offset, len); | |||
482 | } | |||
483 | ||||
484 | /* | |||
485 | * Nothing to do for post-write. | |||
486 | */ | |||
487 | break; | |||
488 | ||||
489 | case ID_BUFTYPE_MBUF: | |||
490 | { | |||
491 | struct mbuf *m, *m0 = cookie->id_origbuf; | |||
492 | bus_size_t minlen, moff; | |||
493 | ||||
494 | /* | |||
495 | * Nothing to do for pre-read. | |||
496 | */ | |||
497 | ||||
498 | if (ops & BUS_DMASYNC_PREWRITE) { | |||
499 | /* | |||
500 | * Copy the caller's buffer to the bounce buffer. | |||
501 | */ | |||
502 | m_copydata(m0, offset, len, | |||
503 | (char *)cookie->id_bouncebuf + offset); | |||
504 | } | |||
505 | ||||
506 | if (ops & BUS_DMASYNC_POSTREAD) { | |||
507 | /* | |||
508 | * Copy the bounce buffer to the caller's buffer. | |||
509 | */ | |||
510 | for (moff = offset, m = m0; m != NULL && len != 0; | |||
511 | m = m->m_next) { | |||
512 | /* Find the beginning mbuf. */ | |||
513 | if (moff >= m->m_len) { | |||
514 | moff -= m->m_len; | |||
515 | continue; | |||
516 | } | |||
517 | ||||
518 | /* | |||
519 | * Now at the first mbuf to sync; nail | |||
520 | * each one until we have exhausted the | |||
521 | * length. | |||
522 | */ | |||
523 | minlen = len < m->m_len - moff ? | |||
524 | len : m->m_len - moff; | |||
525 | ||||
526 | memcpy(mtod(m, char *) + moff, | |||
527 | (char *)cookie->id_bouncebuf + offset, | |||
528 | minlen); | |||
529 | ||||
530 | moff = 0; | |||
531 | len -= minlen; | |||
532 | offset += minlen; | |||
533 | } | |||
534 | } | |||
535 | ||||
536 | /* | |||
537 | * Nothing to do for post-write. | |||
538 | */ | |||
539 | break; | |||
540 | } | |||
541 | ||||
542 | case ID_BUFTYPE_UIO: | |||
543 | panic("_isa_bus_dmamap_sync: ID_BUFTYPE_UIO"); | |||
544 | break; | |||
545 | ||||
546 | case ID_BUFTYPE_RAW: | |||
547 | panic("_isa_bus_dmamap_sync: ID_BUFTYPE_RAW"); | |||
548 | break; | |||
549 | ||||
550 | case ID_BUFTYPE_INVALID: | |||
551 | panic("_isa_bus_dmamap_sync: ID_BUFTYPE_INVALID"); | |||
552 | break; | |||
553 | ||||
554 | default: | |||
555 | printf("unknown buffer type %d\n", cookie->id_buftype); | |||
556 | panic("_isa_bus_dmamap_sync"); | |||
557 | } | |||
558 | } | |||
559 | ||||
560 | /* | |||
561 | * Allocate memory safe for ISA DMA. | |||
562 | */ | |||
563 | int | |||
564 | _isa_bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags) | |||
565 | { | |||
566 | ||||
567 | if (t->_ranges == NULL) | |||
568 | return (ENOMEM); | |||
569 | ||||
570 | /* _bus_dmamem_alloc() does the range checks for us. */ | |||
571 | return (_bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, | |||
572 | rsegs, flags)); | |||
573 | } | |||
574 | ||||
575 | /********************************************************************** | |||
576 | * ISA DMA utility functions | |||
577 | **********************************************************************/ | |||
578 | ||||
579 | int | |||
580 | _isa_dma_alloc_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map, bus_size_t size, int flags) | |||
581 | { | |||
582 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
583 | int error = 0; | |||
584 | ||||
585 | cookie->id_bouncebuflen = round_page(size); | |||
586 | error = _isa_bus_dmamem_alloc(t, cookie->id_bouncebuflen, | |||
587 | PAGE_SIZE, map->_dm_boundary, cookie->id_bouncesegs, | |||
588 | map->_dm_segcnt, &cookie->id_nbouncesegs, flags); | |||
589 | if (error) | |||
590 | goto out; | |||
591 | error = _bus_dmamem_map(t, cookie->id_bouncesegs, | |||
592 | cookie->id_nbouncesegs, cookie->id_bouncebuflen, | |||
593 | (void **)&cookie->id_bouncebuf, flags); | |||
594 | ||||
595 | out: | |||
596 | if (error) { | |||
597 | _bus_dmamem_free(t, cookie->id_bouncesegs, | |||
598 | cookie->id_nbouncesegs); | |||
599 | cookie->id_bouncebuflen = 0; | |||
600 | cookie->id_nbouncesegs = 0; | |||
601 | } else { | |||
602 | cookie->id_flags |= ID_HAS_BOUNCE; | |||
603 | STAT_INCR(isa_dma_stats_nbouncebufs); | |||
604 | } | |||
605 | ||||
606 | return (error); | |||
607 | } | |||
608 | ||||
609 | void | |||
610 | _isa_dma_free_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map) | |||
611 | { | |||
612 | struct arm32_isa_dma_cookie *cookie = map->_dm_cookie; | |||
613 | ||||
614 | STAT_DECR(isa_dma_stats_nbouncebufs); | |||
615 | ||||
616 | _bus_dmamem_unmap(t, cookie->id_bouncebuf, | |||
617 | cookie->id_bouncebuflen); | |||
618 | _bus_dmamem_free(t, cookie->id_bouncesegs, | |||
619 | cookie->id_nbouncesegs); | |||
620 | cookie->id_bouncebuflen = 0; | |||
621 | cookie->id_nbouncesegs = 0; | |||
622 | cookie->id_flags &= ~ID_HAS_BOUNCE; | |||
623 | } |