root/dev/isa/isadma.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. isadmamatch
  2. isadmaattach
  3. isa_dmaunmask
  4. isa_dmamask
  5. isa_dmacascade
  6. isa_dmamap_create
  7. isa_dmamap_destroy
  8. isa_dmastart
  9. isa_dmaabort
  10. isa_dmacount
  11. isa_dmafinished
  12. isa_dmadone
  13. isa_dmamem_alloc
  14. isa_dmamem_free
  15. isa_dmamem_map
  16. isa_dmamem_unmap
  17. isa_dmamem_mmap
  18. isa_drq_isfree
  19. isa_malloc
  20. isa_free
  21. isa_mappage

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

/* [<][>][^][v][top][bottom][index][help] */