Fri Sep 21 14:21:58 2012 UTC ()
Switch to the generic bounce buffer support.


(matt)
diff -r1.15 -r1.16 src/sys/arch/arm/footbridge/isa/isadma_machdep.c
diff -r1.8 -r1.9 src/sys/arch/arm/include/isa_machdep.h
diff -r1.8 -r1.9 src/sys/arch/shark/conf/std.shark
diff -r1.16 -r1.17 src/sys/arch/shark/isa/isadma_machdep.c

cvs diff -r1.15 -r1.16 src/sys/arch/arm/footbridge/isa/isadma_machdep.c (expand / switch to unified diff)

--- 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
65struct arm32_dma_range *footbridge_isa_dma_ranges; 65struct arm32_dma_range *footbridge_isa_dma_ranges;
66int footbridge_isa_dma_nranges; 66int footbridge_isa_dma_nranges;
67 67
68int _isa_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, 
69 bus_size_t, bus_size_t, int, bus_dmamap_t *); 
70void _isa_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); 
71int _isa_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, 
72 bus_size_t, struct proc *, int); 
73int _isa_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, 
74 struct mbuf *, int); 
75int _isa_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, 
76 struct uio *, int); 
77int _isa_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, 
78 bus_dma_segment_t *, int, bus_size_t, int); 
79void _isa_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); 
80void _isa_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, 
81 bus_addr_t, bus_size_t, int); 
82 
83int _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 
86int _isa_dma_alloc_bouncebuf(bus_dma_tag_t, bus_dmamap_t, 
87 bus_size_t, int); 
88void _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 */
95struct arm32_bus_dma_tag isa_bus_dma_tag = { 73struct 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 */
118void 82void
119isa_dma_init(void) 83isa_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) 
138u_long isa_dma_stats_loads; 
139u_long isa_dma_stats_bounces; 
140u_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 */ 
149int 
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 */ 
234void 
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 */ 
252int 
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 */ 
323int 
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 */ 
399int 
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 */ 
410int 
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 */ 
420void 
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 */ 
445void 
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 */ 
573int 
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 
589int 
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 
619void 
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} 

cvs diff -r1.8 -r1.9 src/sys/arch/arm/include/isa_machdep.h (expand / switch to unified diff)

--- 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
116extern struct arm32_bus_dma_tag isa_bus_dma_tag; 116extern 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 */ 
122struct 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 */
155extern struct bus_space isa_io_bs_tag; 119extern struct bus_space isa_io_bs_tag;
156extern struct bus_space isa_mem_bs_tag; 120extern struct bus_space isa_mem_bs_tag;
157 121
158/* ISA chipset */ 122/* ISA chipset */
159extern struct arm32_isa_chipset isa_chipset_tag; 123extern 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

cvs diff -r1.8 -r1.9 src/sys/arch/shark/conf/std.shark (expand / switch to unified diff)

--- 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
5machine shark arm 5machine shark arm
6include "conf/std" # MI standard options 6include "conf/std" # MI standard options
7include "arch/arm/conf/std.arm" # arch standard options 7include "arch/arm/conf/std.arm" # arch standard options
8 8
9options EXEC_AOUT 9options EXEC_AOUT
10options EXEC_ELF32 10options EXEC_ELF32
11options EXEC_SCRIPT 11options EXEC_SCRIPT
12 12
13# To support easy transit to ../arch/arm/arm32 13# To support easy transit to ../arch/arm/arm32
14options ARM32 14options ARM32
 15options _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
19options OFW 20options 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.
24options FONT_VT220L8x16 25options FONT_VT220L8x16

cvs diff -r1.16 -r1.17 src/sys/arch/shark/isa/isadma_machdep.c (expand / switch to unified diff)

--- 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 */
63extern struct arm32_dma_range *shark_isa_dma_ranges; 63extern struct arm32_dma_range *shark_isa_dma_ranges;
64extern int shark_isa_dma_nranges; 64extern int shark_isa_dma_nranges;
65 65
66int _isa_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, 
67 bus_size_t, bus_size_t, int, bus_dmamap_t *); 
68void _isa_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); 
69int _isa_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, 
70 bus_size_t, struct proc *, int); 
71int _isa_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, 
72 struct mbuf *, int); 
73int _isa_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, 
74 struct uio *, int); 
75int _isa_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, 
76 bus_dma_segment_t *, int, bus_size_t, int); 
77void _isa_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); 
78void _isa_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, 
79 bus_addr_t, bus_size_t, int); 
80 
81int _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 
84int _isa_dma_alloc_bouncebuf(bus_dma_tag_t, bus_dmamap_t, 
85 bus_size_t, int); 
86void _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 */
93struct arm32_bus_dma_tag isa_bus_dma_tag = { 71struct 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 */
116void 80void
117isa_dma_init(void) 81isa_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) 
136u_long isa_dma_stats_loads; 
137u_long isa_dma_stats_bounces; 
138u_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 */ 
147int 
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 */ 
232void 
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 */ 
250int 
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 */ 
316int 
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 */ 
389int 
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 */ 
400int 
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 */ 
410void 
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 */ 
435void 
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 */ 
563int 
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 
579int 
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 
609void 
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}