isadma.c revision 1.34 1 /* $NetBSD: isadma.c,v 1.34 1998/06/09 00:00:21 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Device driver for the ISA on-board DMA controller.
42 */
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/proc.h>
47 #include <sys/device.h>
48 #include <sys/malloc.h>
49
50 #include <vm/vm.h>
51
52 #include <machine/bus.h>
53
54 #include <dev/isa/isareg.h>
55 #include <dev/isa/isavar.h>
56 #include <dev/isa/isadmavar.h>
57 #include <dev/isa/isadmareg.h>
58
59 struct isa_mem *isa_mem_head;
60
61 /*
62 * High byte of DMA address is stored in this DMAPG register for
63 * the Nth DMA channel.
64 */
65 static int dmapageport[2][4] = {
66 {0x7, 0x3, 0x1, 0x2},
67 {0xf, 0xb, 0x9, 0xa}
68 };
69
70 static u_int8_t dmamode[4] = {
71 DMA37MD_READ | DMA37MD_SINGLE,
72 DMA37MD_WRITE | DMA37MD_SINGLE,
73 DMA37MD_READ | DMA37MD_SINGLE | DMA37MD_LOOP,
74 DMA37MD_WRITE | DMA37MD_SINGLE | DMA37MD_LOOP
75 };
76
77 static inline void _isa_dmaunmask __P((struct isa_dma_state *, int));
78 static inline void _isa_dmamask __P((struct isa_dma_state *, int));
79
80 static inline void
81 _isa_dmaunmask(ids, chan)
82 struct isa_dma_state *ids;
83 int chan;
84 {
85 int ochan = chan & 3;
86
87 /* set dma channel mode, and set dma channel mode */
88 if ((chan & 4) == 0)
89 bus_space_write_1(ids->ids_bst, ids->ids_dma1h,
90 DMA1_SMSK, ochan | DMA37SM_CLEAR);
91 else
92 bus_space_write_1(ids->ids_bst, ids->ids_dma2h,
93 DMA2_SMSK, ochan | DMA37SM_CLEAR);
94 }
95
96 static inline void
97 _isa_dmamask(ids, chan)
98 struct isa_dma_state *ids;
99 int chan;
100 {
101 int ochan = chan & 3;
102
103 /* set dma channel mode, and set dma channel mode */
104 if ((chan & 4) == 0) {
105 bus_space_write_1(ids->ids_bst, ids->ids_dma1h,
106 DMA1_SMSK, ochan | DMA37SM_SET);
107 bus_space_write_1(ids->ids_bst, ids->ids_dma1h,
108 DMA1_FFC, 0);
109 } else {
110 bus_space_write_1(ids->ids_bst, ids->ids_dma2h,
111 DMA2_SMSK, ochan | DMA37SM_SET);
112 bus_space_write_1(ids->ids_bst, ids->ids_dma2h,
113 DMA2_FFC, 0);
114 }
115 }
116
117 /*
118 * _isa_dmainit(): Initialize the isa_dma_state for this chipset.
119 */
120 void
121 _isa_dmainit(ids, bst, dmat, dev)
122 struct isa_dma_state *ids;
123 bus_space_tag_t bst;
124 bus_dma_tag_t dmat;
125 struct device *dev;
126 {
127
128 ids->ids_dev = dev;
129
130 if (ids->ids_initialized) {
131 /*
132 * Some systems may have e.g. `ofisa' (OpenFirmware
133 * configuration of ISA bus) and a regular `isa'.
134 * We allow both to call the initialization function,
135 * and take the device name from the last caller
136 * (assuming it will be the indirect ISA bus). Since
137 * `ofisa' and `isa' are the same bus with different
138 * configuration mechanisms, the space and dma tags
139 * must be the same!
140 */
141 if (ids->ids_bst != bst || ids->ids_dmat != dmat)
142 panic("_isa_dmainit: inconsistent ISA tags");
143 } else {
144 ids->ids_bst = bst;
145 ids->ids_dmat = dmat;
146
147 /*
148 * Map the registers used by the ISA DMA controller.
149 */
150 if (bus_space_map(ids->ids_bst, IO_DMA1, DMA1_IOSIZE, 0,
151 &ids->ids_dma1h))
152 panic("_isa_dmainit: unable to map DMA controller #1");
153 if (bus_space_map(ids->ids_bst, IO_DMA2, DMA2_IOSIZE, 0,
154 &ids->ids_dma2h))
155 panic("_isa_dmainit: unable to map DMA controller #2");
156 if (bus_space_map(ids->ids_bst, IO_DMAPG, 0xf, 0,
157 &ids->ids_dmapgh))
158 panic("_isa_dmainit: unable to map DMA page registers");
159
160 ids->ids_initialized = 1;
161 }
162 }
163
164 /*
165 * _isa_dmacascade(): program 8237 DMA controller channel to accept
166 * external dma control by a board.
167 */
168 void
169 _isa_dmacascade(ids, chan)
170 struct isa_dma_state *ids;
171 int chan;
172 {
173 int ochan = chan & 3;
174
175 if (chan < 0 || chan > 7) {
176 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
177 goto lose;
178 }
179
180 if (ISA_DMA_DRQ_ISFREE(ids, chan) == 0) {
181 printf("%s: DRQ %d is not free\n", ids->ids_dev->dv_xname,
182 chan);
183 goto lose;
184 }
185
186 ISA_DMA_DRQ_ALLOC(ids, chan);
187
188 /* set dma channel mode, and set dma channel mode */
189 if ((chan & 4) == 0)
190 bus_space_write_1(ids->ids_bst, ids->ids_dma1h,
191 DMA1_MODE, ochan | DMA37MD_CASCADE);
192 else
193 bus_space_write_1(ids->ids_bst, ids->ids_dma2h,
194 DMA2_MODE, ochan | DMA37MD_CASCADE);
195
196 _isa_dmaunmask(ids, chan);
197 return;
198
199 lose:
200 panic("_isa_dmacascade");
201 }
202
203 int
204 _isa_dmamap_create(ids, chan, size, flags)
205 struct isa_dma_state *ids;
206 int chan;
207 bus_size_t size;
208 int flags;
209 {
210 bus_size_t maxsize;
211
212 if (chan < 0 || chan > 7) {
213 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
214 goto lose;
215 }
216
217 if (chan & 4)
218 maxsize = (1 << 17);
219 else
220 maxsize = (1 << 16);
221
222 if (size > maxsize)
223 return (EINVAL);
224
225 if (ISA_DMA_DRQ_ISFREE(ids, chan) == 0) {
226 printf("%s: drq %d is not free\n", ids->ids_dev->dv_xname,
227 chan);
228 goto lose;
229 }
230
231 ISA_DMA_DRQ_ALLOC(ids, chan);
232
233 return (bus_dmamap_create(ids->ids_dmat, size, 1, size, maxsize,
234 flags, &ids->ids_dmamaps[chan]));
235
236 lose:
237 panic("_isa_dmamap_create");
238 }
239
240 void
241 _isa_dmamap_destroy(ids, chan)
242 struct isa_dma_state *ids;
243 int chan;
244 {
245
246 if (chan < 0 || chan > 7) {
247 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
248 goto lose;
249 }
250
251 if (ISA_DMA_DRQ_ISFREE(ids, chan)) {
252 printf("%s: drq %d is already free\n",
253 ids->ids_dev->dv_xname, chan);
254 goto lose;
255 }
256
257 ISA_DMA_DRQ_FREE(ids, chan);
258
259 bus_dmamap_destroy(ids->ids_dmat, ids->ids_dmamaps[chan]);
260 return;
261
262 lose:
263 panic("_isa_dmamap_destroy");
264 }
265
266 /*
267 * _isa_dmastart(): program 8237 DMA controller channel and set it
268 * in motion.
269 */
270 int
271 _isa_dmastart(ids, chan, addr, nbytes, p, flags, busdmaflags)
272 struct isa_dma_state *ids;
273 int chan;
274 void *addr;
275 bus_size_t nbytes;
276 struct proc *p;
277 int flags;
278 int busdmaflags;
279 {
280 bus_dmamap_t dmam;
281 bus_addr_t dmaaddr;
282 int waport;
283 int ochan = chan & 3;
284 int error;
285
286 if (chan < 0 || chan > 7) {
287 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
288 goto lose;
289 }
290
291 #ifdef ISADMA_DEBUG
292 printf("_isa_dmastart: drq %d, addr %p, nbytes 0x%lx, p %p, "
293 "flags 0x%x, dmaflags 0x%x\n",
294 chan, addr, nbytes, p, flags, busdmaflags);
295 #endif
296
297 if (chan & 4) {
298 if (nbytes > (1 << 17) || nbytes & 1 || (u_long)addr & 1) {
299 printf("%s: drq %d, nbytes 0x%lx, addr %p\n",
300 ids->ids_dev->dv_xname, chan, nbytes, addr);
301 goto lose;
302 }
303 } else {
304 if (nbytes > (1 << 16)) {
305 printf("%s: drq %d, nbytes 0x%lx\n",
306 ids->ids_dev->dv_xname, chan, nbytes);
307 goto lose;
308 }
309 }
310
311 dmam = ids->ids_dmamaps[chan];
312 if (dmam == NULL)
313 panic("_isa_dmastart: no DMA map for chan %d\n", chan);
314
315 error = bus_dmamap_load(ids->ids_dmat, dmam, addr, nbytes,
316 p, busdmaflags);
317 if (error)
318 return (error);
319
320 #ifdef ISADMA_DEBUG
321 __asm(".globl isa_dmastart_afterload ; isa_dmastart_afterload:");
322 #endif
323
324 if (flags & DMAMODE_READ) {
325 bus_dmamap_sync(ids->ids_dmat, dmam, 0, dmam->dm_mapsize,
326 BUS_DMASYNC_PREREAD);
327 ids->ids_dmareads |= (1 << chan);
328 } else {
329 bus_dmamap_sync(ids->ids_dmat, dmam, 0, dmam->dm_mapsize,
330 BUS_DMASYNC_PREWRITE);
331 ids->ids_dmareads &= ~(1 << chan);
332 }
333
334 dmaaddr = dmam->dm_segs[0].ds_addr;
335
336 #ifdef ISADMA_DEBUG
337 printf(" dmaaddr 0x%lx\n", dmaaddr);
338
339 __asm(".globl isa_dmastart_aftersync ; isa_dmastart_aftersync:");
340 #endif
341
342 ids->ids_dmalength[chan] = nbytes;
343
344 _isa_dmamask(ids, chan);
345 ids->ids_dmafinished &= ~(1 << chan);
346
347 if ((chan & 4) == 0) {
348 /* set dma channel mode */
349 bus_space_write_1(ids->ids_bst, ids->ids_dma1h, DMA1_MODE,
350 ochan | dmamode[flags]);
351
352 /* send start address */
353 waport = DMA1_CHN(ochan);
354 bus_space_write_1(ids->ids_bst, ids->ids_dmapgh,
355 dmapageport[0][ochan], (dmaaddr >> 16) & 0xff);
356 bus_space_write_1(ids->ids_bst, ids->ids_dma1h, waport,
357 dmaaddr & 0xff);
358 bus_space_write_1(ids->ids_bst, ids->ids_dma1h, waport,
359 (dmaaddr >> 8) & 0xff);
360
361 /* send count */
362 bus_space_write_1(ids->ids_bst, ids->ids_dma1h, waport + 1,
363 (--nbytes) & 0xff);
364 bus_space_write_1(ids->ids_bst, ids->ids_dma1h, waport + 1,
365 (nbytes >> 8) & 0xff);
366 } else {
367 /* set dma channel mode */
368 bus_space_write_1(ids->ids_bst, ids->ids_dma2h, DMA2_MODE,
369 ochan | dmamode[flags]);
370
371 /* send start address */
372 waport = DMA2_CHN(ochan);
373 bus_space_write_1(ids->ids_bst, ids->ids_dmapgh,
374 dmapageport[1][ochan], (dmaaddr >> 16) & 0xff);
375 dmaaddr >>= 1;
376 bus_space_write_1(ids->ids_bst, ids->ids_dma2h, waport,
377 dmaaddr & 0xff);
378 bus_space_write_1(ids->ids_bst, ids->ids_dma2h, waport,
379 (dmaaddr >> 8) & 0xff);
380
381 /* send count */
382 nbytes >>= 1;
383 bus_space_write_1(ids->ids_bst, ids->ids_dma2h, waport + 2,
384 (--nbytes) & 0xff);
385 bus_space_write_1(ids->ids_bst, ids->ids_dma2h, waport + 2,
386 (nbytes >> 8) & 0xff);
387 }
388
389 _isa_dmaunmask(ids, chan);
390 return (0);
391
392 lose:
393 panic("_isa_dmastart");
394 }
395
396 void
397 _isa_dmaabort(ids, chan)
398 struct isa_dma_state *ids;
399 int chan;
400 {
401
402 if (chan < 0 || chan > 7) {
403 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
404 panic("_isa_dmaabort");
405 }
406
407 _isa_dmamask(ids, chan);
408 bus_dmamap_unload(ids->ids_dmat, ids->ids_dmamaps[chan]);
409 ids->ids_dmareads &= ~(1 << chan);
410 }
411
412 bus_size_t
413 _isa_dmacount(ids, chan)
414 struct isa_dma_state *ids;
415 int chan;
416 {
417 int waport;
418 bus_size_t nbytes;
419 int ochan = chan & 3;
420
421 if (chan < 0 || chan > 7) {
422 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
423 panic("isa_dmacount");
424 }
425
426 _isa_dmamask(ids, chan);
427
428 /*
429 * We have to shift the byte count by 1. If we're in auto-initialize
430 * mode, the count may have wrapped around to the initial value. We
431 * can't use the TC bit to check for this case, so instead we compare
432 * against the original byte count.
433 * If we're not in auto-initialize mode, then the count will wrap to
434 * -1, so we also handle that case.
435 */
436 if ((chan & 4) == 0) {
437 waport = DMA1_CHN(ochan);
438 nbytes = bus_space_read_1(ids->ids_bst, ids->ids_dma1h,
439 waport + 1) + 1;
440 nbytes += bus_space_read_1(ids->ids_bst, ids->ids_dma1h,
441 waport + 1) << 8;
442 nbytes &= 0xffff;
443 } else {
444 waport = DMA2_CHN(ochan);
445 nbytes = bus_space_read_1(ids->ids_bst, ids->ids_dma2h,
446 waport + 2) + 1;
447 nbytes += bus_space_read_1(ids->ids_bst, ids->ids_dma2h,
448 waport + 2) << 8;
449 nbytes <<= 1;
450 nbytes &= 0x1ffff;
451 }
452
453 if (nbytes == ids->ids_dmalength[chan])
454 nbytes = 0;
455
456 _isa_dmaunmask(ids, chan);
457 return (nbytes);
458 }
459
460 int
461 _isa_dmafinished(ids, chan)
462 struct isa_dma_state *ids;
463 int chan;
464 {
465
466 if (chan < 0 || chan > 7) {
467 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
468 panic("_isa_dmafinished");
469 }
470
471 /* check that the terminal count was reached */
472 if ((chan & 4) == 0)
473 ids->ids_dmafinished |= bus_space_read_1(ids->ids_bst,
474 ids->ids_dma1h, DMA1_SR) & 0x0f;
475 else
476 ids->ids_dmafinished |= (bus_space_read_1(ids->ids_bst,
477 ids->ids_dma2h, DMA2_SR) & 0x0f) << 4;
478
479 return ((ids->ids_dmafinished & (1 << chan)) != 0);
480 }
481
482 void
483 _isa_dmadone(ids, chan)
484 struct isa_dma_state *ids;
485 int chan;
486 {
487 bus_dmamap_t dmam;
488
489 if (chan < 0 || chan > 7) {
490 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
491 panic("_isa_dmadone");
492 }
493
494 dmam = ids->ids_dmamaps[chan];
495
496 _isa_dmamask(ids, chan);
497
498 if (_isa_dmafinished(ids, chan) == 0)
499 printf("%s: _isa_dmadone: channel %d not finished\n",
500 ids->ids_dev->dv_xname, chan);
501
502 bus_dmamap_sync(ids->ids_dmat, dmam, 0, dmam->dm_mapsize,
503 (ids->ids_dmareads & (1 << chan)) ? BUS_DMASYNC_POSTREAD :
504 BUS_DMASYNC_POSTWRITE);
505
506 bus_dmamap_unload(ids->ids_dmat, dmam);
507 ids->ids_dmareads &= ~(1 << chan);
508 }
509
510 int
511 _isa_dmamem_alloc(ids, chan, size, addrp, flags)
512 struct isa_dma_state *ids;
513 int chan;
514 bus_size_t size;
515 bus_addr_t *addrp;
516 int flags;
517 {
518 bus_dma_segment_t seg;
519 int error, boundary, rsegs;
520
521 if (chan < 0 || chan > 7) {
522 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
523 panic("_isa_dmamem_alloc");
524 }
525
526 boundary = (chan & 4) ? (1 << 17) : (1 << 16);
527
528 size = round_page(size);
529
530 error = bus_dmamem_alloc(ids->ids_dmat, size, NBPG, boundary,
531 &seg, 1, &rsegs, flags);
532 if (error)
533 return (error);
534
535 *addrp = seg.ds_addr;
536 return (0);
537 }
538
539 void
540 _isa_dmamem_free(ids, chan, addr, size)
541 struct isa_dma_state *ids;
542 int chan;
543 bus_addr_t addr;
544 bus_size_t size;
545 {
546 bus_dma_segment_t seg;
547
548 if (chan < 0 || chan > 7) {
549 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
550 panic("_isa_dmamem_free");
551 }
552
553 seg.ds_addr = addr;
554 seg.ds_len = size;
555
556 bus_dmamem_free(ids->ids_dmat, &seg, 1);
557 }
558
559 int
560 _isa_dmamem_map(ids, chan, addr, size, kvap, flags)
561 struct isa_dma_state *ids;
562 int chan;
563 bus_addr_t addr;
564 bus_size_t size;
565 caddr_t *kvap;
566 int flags;
567 {
568 bus_dma_segment_t seg;
569
570 if (chan < 0 || chan > 7) {
571 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
572 panic("_isa_dmamem_map");
573 }
574
575 seg.ds_addr = addr;
576 seg.ds_len = size;
577
578 return (bus_dmamem_map(ids->ids_dmat, &seg, 1, size, kvap, flags));
579 }
580
581 void
582 _isa_dmamem_unmap(ids, chan, kva, size)
583 struct isa_dma_state *ids;
584 int chan;
585 caddr_t kva;
586 size_t size;
587 {
588
589 if (chan < 0 || chan > 7) {
590 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
591 panic("_isa_dmamem_unmap");
592 }
593
594 bus_dmamem_unmap(ids->ids_dmat, kva, size);
595 }
596
597 int
598 _isa_dmamem_mmap(ids, chan, addr, size, off, prot, flags)
599 struct isa_dma_state *ids;
600 int chan;
601 bus_addr_t addr;
602 bus_size_t size;
603 int off, prot, flags;
604 {
605 bus_dma_segment_t seg;
606
607 if (chan < 0 || chan > 7) {
608 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
609 panic("_isa_dmamem_mmap");
610 }
611
612 seg.ds_addr = addr;
613 seg.ds_len = size;
614
615 return (bus_dmamem_mmap(ids->ids_dmat, &seg, 1, off, prot, flags));
616 }
617
618 int
619 _isa_drq_isfree(ids, chan)
620 struct isa_dma_state *ids;
621 int chan;
622 {
623
624 if (chan < 0 || chan > 7) {
625 printf("%s: bogus drq %d\n", ids->ids_dev->dv_xname, chan);
626 panic("_isa_drq_isfree");
627 }
628
629 return ISA_DMA_DRQ_ISFREE(ids, chan);
630 }
631
632 void *
633 _isa_malloc(ids, chan, size, pool, flags)
634 struct isa_dma_state *ids;
635 int chan;
636 size_t size;
637 int pool;
638 int flags;
639 {
640 bus_addr_t addr;
641 caddr_t kva;
642 int bflags;
643 struct isa_mem *m;
644
645 bflags = flags & M_WAITOK ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT;
646
647 if (_isa_dmamem_alloc(ids, chan, size, &addr, bflags))
648 return 0;
649 if (_isa_dmamem_map(ids, chan, addr, size, &kva, bflags)) {
650 _isa_dmamem_free(ids, chan, addr, size);
651 return 0;
652 }
653 m = malloc(sizeof(*m), pool, flags);
654 if (m == 0) {
655 _isa_dmamem_unmap(ids, chan, kva, size);
656 _isa_dmamem_free(ids, chan, addr, size);
657 return 0;
658 }
659 m->ids = ids;
660 m->chan = chan;
661 m->size = size;
662 m->addr = addr;
663 m->kva = kva;
664 m->next = isa_mem_head;
665 isa_mem_head = m;
666 return (void *)kva;
667 }
668
669 void
670 _isa_free(addr, pool)
671 void *addr;
672 int pool;
673 {
674 struct isa_mem **mp, *m;
675 caddr_t kva = (caddr_t)addr;
676
677 for(mp = &isa_mem_head; *mp && (*mp)->kva != kva;
678 mp = &(*mp)->next)
679 ;
680 m = *mp;
681 if (!m) {
682 printf("_isa_free: freeing unallocted memory\n");
683 return;
684 }
685 *mp = m->next;
686 _isa_dmamem_unmap(m->ids, m->chan, kva, m->size);
687 _isa_dmamem_free(m->ids, m->chan, m->addr, m->size);
688 free(m, pool);
689 }
690
691 int
692 _isa_mappage(mem, off, prot)
693 void *mem;
694 int off;
695 int prot;
696 {
697 struct isa_mem *m;
698
699 for(m = isa_mem_head; m && m->kva != (caddr_t)mem; m = m->next)
700 ;
701 if (!m) {
702 printf("_isa_mappage: mapping unallocted memory\n");
703 return -1;
704 }
705 return _isa_dmamem_mmap(m->ids, m->chan, m->addr,
706 m->size, off, prot, BUS_DMA_WAITOK);
707 }
708