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