LCOV - code coverage report
Current view: top level - dev/isa - isadma.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 285 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.13