The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isa/isadma.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: isadma.c,v 1.37 2022/04/06 18:59:28 naddy 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 const struct cfattach isadma_ca = {
   88         sizeof(struct device), isadmamatch, isadmaattach
   89 };
   90 
   91 struct cfdriver isadma_cd = {
   92         NULL, "isadma", DV_DULL, CD_INDIRECT
   93 };
   94 
   95 int
   96 isadmamatch(struct device *parent, void *match, void *aux)
   97 {
   98         struct isa_attach_args *ia = aux;
   99 
  100         /* Sure we exist */
  101         ia->ia_iosize = 0;
  102         return (1);
  103 }
  104 
  105 void
  106 isadmaattach(struct device *parent, struct device *self, void *aux)
  107 {
  108 #ifdef __ISADMA_COMPAT
  109         int i, sz;
  110         struct isa_softc *sc = (struct isa_softc *)parent;
  111 
  112         /* XXX ugly, but will go away soon... */
  113         isa_dev = parent;
  114 
  115         for (i = 0; i < 8; i++) {
  116                 sz = (i & 4) ? 1 << 17 : 1 << 16;
  117                 if ((bus_dmamap_create(sc->sc_dmat, sz, 1, sz, sz,
  118                     BUS_DMA_24BIT|BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
  119                     &isadma_dmam[i])) != 0)
  120                         panic("isadmaattach: can not create DMA map");
  121         }
  122 #endif
  123 
  124         /* XXX I'd like to map the DMA ports here, see isa.c why not... */
  125 
  126         printf("\n");
  127 }
  128 
  129 static inline void isa_dmaunmask(struct isa_softc *, int);
  130 static inline void isa_dmamask(struct isa_softc *, int);
  131 
  132 static inline void
  133 isa_dmaunmask(struct isa_softc *sc, int chan)
  134 {
  135         int ochan = chan & 3;
  136 
  137         /* set dma channel mode, and set dma channel mode */
  138         if ((chan & 4) == 0)
  139                 bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
  140                     DMA1_SMSK, ochan | DMA37SM_CLEAR);
  141         else
  142                 bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
  143                     DMA2_SMSK, ochan | DMA37SM_CLEAR);
  144 }
  145 
  146 static inline void
  147 isa_dmamask(struct isa_softc *sc, int chan)
  148 {
  149         int ochan = chan & 3;
  150 
  151         /* set dma channel mode, and set dma channel mode */
  152         if ((chan & 4) == 0) {
  153                 bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
  154                     DMA1_SMSK, ochan | DMA37SM_SET);
  155                 bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
  156                     DMA1_FFC, 0);
  157         } else {
  158                 bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
  159                     DMA2_SMSK, ochan | DMA37SM_SET);
  160                 bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
  161                     DMA2_FFC, 0);
  162         }
  163 }
  164 
  165 /*
  166  * isa_dmacascade(): program 8237 DMA controller channel to accept
  167  * external dma control by a board.
  168  */
  169 void
  170 isa_dmacascade(struct device *isadev, int chan)
  171 {
  172         struct isa_softc *sc = (struct isa_softc *)isadev;
  173         int ochan = chan & 3;
  174 
  175         if (chan < 0 || chan > 7) {
  176                 printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
  177                 goto lose;
  178         }
  179 
  180         if (ISA_DRQ_ISFREE(sc, chan) == 0) {
  181                 printf("%s: DRQ %d is not free\n", sc->sc_dev.dv_xname, chan);
  182                 goto lose;
  183         }
  184 
  185         ISA_DRQ_ALLOC(sc, chan);
  186 
  187         /* set dma channel mode, and set dma channel mode */
  188         if ((chan & 4) == 0)
  189                 bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
  190                     DMA1_MODE, ochan | DMA37MD_CASCADE);
  191         else
  192                 bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
  193                     DMA2_MODE, ochan | DMA37MD_CASCADE);
  194 
  195         isa_dmaunmask(sc, chan);
  196         return;
  197 
  198  lose:
  199         panic("isa_dmacascade");
  200 }
  201 
  202 int
  203 isa_dmamap_create(struct device *isadev, int chan, bus_size_t size, int flags)
  204 {
  205         struct isa_softc *sc = (struct isa_softc *)isadev;
  206         bus_size_t maxsize;
  207 
  208         if (chan < 0 || chan > 7) {
  209                 printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
  210                 goto lose;
  211         }
  212 
  213         if (chan & 4)
  214                 maxsize = (1 << 17);
  215         else
  216                 maxsize = (1 << 16);
  217 
  218         if (size > maxsize)
  219                 return (EINVAL);
  220 
  221         if (ISA_DRQ_ISFREE(sc, chan) == 0) {
  222                 printf("%s: drq %d is not free\n", sc->sc_dev.dv_xname, chan);
  223                 goto lose;
  224         }
  225 
  226         ISA_DRQ_ALLOC(sc, chan);
  227 
  228         return (bus_dmamap_create(sc->sc_dmat, size, 1, size, maxsize,
  229             flags, &sc->sc_dmamaps[chan]));
  230 
  231  lose:
  232         panic("isa_dmamap_create");
  233 }
  234 
  235 void
  236 isa_dmamap_destroy(struct device *isadev, int chan)
  237 {
  238         struct isa_softc *sc = (struct isa_softc *)isadev;
  239 
  240         if (chan < 0 || chan > 7) {
  241                 printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
  242                 goto lose;
  243         }
  244 
  245         if (ISA_DRQ_ISFREE(sc, chan)) {
  246                 printf("%s: drq %d is already free\n",
  247                     sc->sc_dev.dv_xname, chan);
  248                 goto lose;
  249         }
  250 
  251         ISA_DRQ_FREE(sc, chan);
  252 
  253         bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamaps[chan]);
  254         return;
  255 
  256  lose:
  257         panic("isa_dmamap_destroy");
  258 }
  259 
  260 /*
  261  * isa_dmastart(): program 8237 DMA controller channel and set it
  262  * in motion.
  263  */
  264 int
  265 isa_dmastart(struct device *isadev, int chan, void *addr, bus_size_t nbytes,
  266     struct proc *p, int flags, int busdmaflags)
  267 {
  268         struct isa_softc *sc = (struct isa_softc *)isadev;
  269         bus_dmamap_t dmam;
  270         bus_addr_t dmaaddr;
  271         int waport;
  272         int ochan = chan & 3;
  273         int error;
  274 #ifdef __ISADMA_COMPAT
  275         int compat = busdmaflags & BUS_DMA_BUS1;
  276 
  277         busdmaflags &= ~BUS_DMA_BUS1;
  278 #endif /* __ISADMA_COMPAT */
  279 
  280         if (chan < 0 || chan > 7) {
  281                 printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
  282                 goto lose;
  283         }
  284 
  285 #ifdef ISADMA_DEBUG
  286         printf("isa_dmastart: drq %d, addr %p, nbytes 0x%lx, p %p, "
  287             "flags 0x%x, dmaflags 0x%x\n",
  288             chan, addr, nbytes, p, flags, busdmaflags);
  289 #endif
  290 
  291         if (chan & 4) {
  292                 if (nbytes > (1 << 17) || nbytes & 1 || (u_long)addr & 1) {
  293                         printf("%s: drq %d, nbytes 0x%lx, addr %p\n",
  294                             sc->sc_dev.dv_xname, chan, nbytes, addr);
  295                         goto lose;
  296                 }
  297         } else {
  298                 if (nbytes > (1 << 16)) {
  299                         printf("%s: drq %d, nbytes 0x%lx\n",
  300                             sc->sc_dev.dv_xname, chan, nbytes);
  301                         goto lose;
  302                 }
  303         }
  304 
  305         dmam = sc->sc_dmamaps[chan];
  306         if (dmam == NULL) {
  307 #ifdef __ISADMA_COMPAT
  308                 if (compat)
  309                         dmam = sc->sc_dmamaps[chan] = isadma_dmam[chan];
  310                 else
  311 #endif /* __ISADMA_COMPAT */
  312                 panic("isa_dmastart: no DMA map for chan %d", chan);
  313         }
  314 
  315         error = bus_dmamap_load(sc->sc_dmat, dmam, addr, nbytes, p,
  316             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(sc->sc_dmat, dmam, 0, dmam->dm_mapsize,
  326                     BUS_DMASYNC_PREREAD);
  327                 sc->sc_dmareads |= (1 << chan);
  328         } else {
  329                 bus_dmamap_sync(sc->sc_dmat, dmam, 0, dmam->dm_mapsize,
  330                     BUS_DMASYNC_PREWRITE);
  331                 sc->sc_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         sc->sc_dmalength[chan] = nbytes;
  343 
  344         isa_dmamask(sc, chan);
  345         sc->sc_dmafinished &= ~(1 << chan);
  346 
  347         if ((chan & 4) == 0) {
  348                 /* set dma channel mode */
  349                 bus_space_write_1(sc->sc_iot, sc->sc_dma1h, DMA1_MODE,
  350                     ochan | dmamode[flags]);
  351 
  352                 /* send start address */
  353                 waport = DMA1_CHN(ochan);
  354                 bus_space_write_1(sc->sc_iot, sc->sc_dmapgh,
  355                     dmapageport[0][ochan], (dmaaddr >> 16) & 0xff);
  356                 bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport,
  357                     dmaaddr & 0xff);
  358                 bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport,
  359                     (dmaaddr >> 8) & 0xff);
  360 
  361                 /* send count */
  362                 bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport + 1,
  363                     (--nbytes) & 0xff);
  364                 bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport + 1,
  365                     (nbytes >> 8) & 0xff);
  366         } else {
  367                 /* set dma channel mode */
  368                 bus_space_write_1(sc->sc_iot, sc->sc_dma2h, DMA2_MODE,
  369                     ochan | dmamode[flags]);
  370 
  371                 /* send start address */
  372                 waport = DMA2_CHN(ochan);
  373                 bus_space_write_1(sc->sc_iot, sc->sc_dmapgh,
  374                     dmapageport[1][ochan], (dmaaddr >> 16) & 0xff);
  375                 dmaaddr >>= 1;
  376                 bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport,
  377                     dmaaddr & 0xff);
  378                 bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport,
  379                     (dmaaddr >> 8) & 0xff);
  380 
  381                 /* send count */
  382                 nbytes >>= 1;
  383                 bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport + 2,
  384                     (--nbytes) & 0xff);
  385                 bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport + 2,
  386                     (nbytes >> 8) & 0xff);
  387         }
  388 
  389         isa_dmaunmask(sc, chan);
  390         return (0);
  391 
  392  lose:
  393         panic("isa_dmastart");
  394 }
  395 
  396 void
  397 isa_dmaabort(struct device *isadev, int chan)
  398 {
  399         struct isa_softc *sc = (struct isa_softc *)isadev;
  400 
  401         if (chan < 0 || chan > 7) {
  402                 panic("isa_dmaabort: %s: bogus drq %d", sc->sc_dev.dv_xname,
  403                     chan);
  404         }
  405 
  406         isa_dmamask(sc, chan);
  407         bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamaps[chan]);
  408         sc->sc_dmareads &= ~(1 << chan);
  409 }
  410 
  411 bus_size_t
  412 isa_dmacount(struct device *isadev, int chan)
  413 {
  414         struct isa_softc *sc = (struct isa_softc *)isadev;
  415         int waport;
  416         bus_size_t nbytes;
  417         int ochan = chan & 3;
  418 
  419         if (chan < 0 || chan > 7) {
  420                 panic("isa_dmacount: %s: bogus drq %d", sc->sc_dev.dv_xname,
  421                     chan);
  422         }
  423 
  424         isa_dmamask(sc, chan);
  425 
  426         /*
  427          * We have to shift the byte count by 1.  If we're in auto-initialize
  428          * mode, the count may have wrapped around to the initial value.  We
  429          * can't use the TC bit to check for this case, so instead we compare
  430          * against the original byte count.
  431          * If we're not in auto-initialize mode, then the count will wrap to
  432          * -1, so we also handle that case.
  433          */
  434         if ((chan & 4) == 0) {
  435                 waport = DMA1_CHN(ochan);
  436                 nbytes = bus_space_read_1(sc->sc_iot, sc->sc_dma1h,
  437                     waport + 1) + 1;
  438                 nbytes += bus_space_read_1(sc->sc_iot, sc->sc_dma1h,
  439                     waport + 1) << 8;
  440                 nbytes &= 0xffff;
  441         } else {
  442                 waport = DMA2_CHN(ochan);
  443                 nbytes = bus_space_read_1(sc->sc_iot, sc->sc_dma2h,
  444                     waport + 2) + 1;
  445                 nbytes += bus_space_read_1(sc->sc_iot, sc->sc_dma2h,
  446                     waport + 2) << 8;
  447                 nbytes <<= 1;
  448                 nbytes &= 0x1ffff;
  449         }
  450 
  451         if (nbytes == sc->sc_dmalength[chan])
  452                 nbytes = 0;
  453 
  454         isa_dmaunmask(sc, chan);
  455         return (nbytes);
  456 }
  457 
  458 int
  459 isa_dmafinished(struct device *isadev, int chan)
  460 {
  461         struct isa_softc *sc = (struct isa_softc *)isadev;
  462 
  463         if (chan < 0 || chan > 7) {
  464                 panic("isa_dmafinished: %s: bogus drq %d", sc->sc_dev.dv_xname,
  465                     chan);
  466         }
  467 
  468         /* check that the terminal count was reached */
  469         if ((chan & 4) == 0)
  470                 sc->sc_dmafinished |= bus_space_read_1(sc->sc_iot,
  471                     sc->sc_dma1h, DMA1_SR) & 0x0f;
  472         else
  473                 sc->sc_dmafinished |= (bus_space_read_1(sc->sc_iot,
  474                     sc->sc_dma2h, DMA2_SR) & 0x0f) << 4;
  475 
  476         return ((sc->sc_dmafinished & (1 << chan)) != 0);
  477 }
  478 
  479 void
  480 isa_dmadone(struct device *isadev, int chan)
  481 {
  482         struct isa_softc *sc = (struct isa_softc *)isadev;
  483         bus_dmamap_t dmam;
  484 
  485         if (chan < 0 || chan > 7) {
  486                 panic("isa_dmadone: %s: bogus drq %d", sc->sc_dev.dv_xname,
  487                     chan);
  488         }
  489 
  490         dmam = sc->sc_dmamaps[chan];
  491 
  492         isa_dmamask(sc, chan);
  493 
  494         if (isa_dmafinished(isadev, chan) == 0)
  495                 printf("%s: isa_dmadone: channel %d not finished\n",
  496                     sc->sc_dev.dv_xname, chan);
  497 
  498         bus_dmamap_sync(sc->sc_dmat, dmam, 0, dmam->dm_mapsize,
  499             (sc->sc_dmareads & (1 << chan)) ? BUS_DMASYNC_POSTREAD :
  500             BUS_DMASYNC_POSTWRITE);
  501 
  502         bus_dmamap_unload(sc->sc_dmat, dmam);
  503         sc->sc_dmareads &= ~(1 << chan);
  504 }
  505 
  506 int
  507 isa_dmamem_alloc(struct device *isadev, int chan, bus_size_t size,
  508     bus_addr_t *addrp, int flags)
  509 {
  510         struct isa_softc *sc = (struct isa_softc *)isadev;
  511         bus_dma_segment_t seg;
  512         int error, boundary, rsegs;
  513 
  514         if (chan < 0 || chan > 7) {
  515                 panic("isa_dmamem_alloc: %s: bogus drq %d",
  516                     sc->sc_dev.dv_xname, chan);
  517         }
  518 
  519         boundary = (chan & 4) ? (1 << 17) : (1 << 16);
  520 
  521         size = round_page(size);
  522 
  523         error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, boundary,
  524             &seg, 1, &rsegs, flags);
  525         if (error)
  526                 return (error);
  527 
  528         *addrp = seg.ds_addr;
  529         return (0);
  530 }
  531 
  532 void
  533 isa_dmamem_free(struct device *isadev, int chan, bus_addr_t addr,
  534     bus_size_t size)
  535 {
  536         struct isa_softc *sc = (struct isa_softc *)isadev;
  537         bus_dma_segment_t seg;
  538 
  539         if (chan < 0 || chan > 7) {
  540                 panic("isa_dmamem_free: %s: bogus drq %d",
  541                     sc->sc_dev.dv_xname, chan);
  542         }
  543 
  544         seg.ds_addr = addr;
  545         seg.ds_len = size;
  546 
  547         bus_dmamem_free(sc->sc_dmat, &seg, 1);
  548 }
  549 
  550 int
  551 isa_dmamem_map(struct device *isadev, int chan, bus_addr_t addr,
  552     bus_size_t size, caddr_t *kvap, int flags)
  553 {
  554         struct isa_softc *sc = (struct isa_softc *)isadev;
  555         bus_dma_segment_t seg;
  556 
  557         if (chan < 0 || chan > 7) {
  558                 panic("isa_dmamem_map: %s: bogus drq %d", sc->sc_dev.dv_xname,
  559                     chan);
  560         }
  561 
  562         seg.ds_addr = addr;
  563         seg.ds_len = size;
  564 
  565         return (bus_dmamem_map(sc->sc_dmat, &seg, 1, size, kvap, flags));
  566 }
  567 
  568 void
  569 isa_dmamem_unmap(struct device *isadev, int chan, caddr_t kva, size_t size)
  570 {
  571         struct isa_softc *sc = (struct isa_softc *)isadev;
  572 
  573         if (chan < 0 || chan > 7) {
  574                 panic("isa_dmamem_unmap: %s: bogus drq %d",
  575                     sc->sc_dev.dv_xname, chan);
  576         }
  577 
  578         bus_dmamem_unmap(sc->sc_dmat, kva, size);
  579 }
  580 
  581 int
  582 isa_dmamem_mmap(struct device *isadev, int chan, bus_addr_t addr,
  583     bus_size_t size, int off, int prot, int flags)
  584 {
  585         struct isa_softc *sc = (struct isa_softc *)isadev;
  586         bus_dma_segment_t seg;
  587 
  588         if (chan < 0 || chan > 7) {
  589                 panic("isa_dmamem_mmap: %s: bogus drq %d", sc->sc_dev.dv_xname,
  590                     chan);
  591         }
  592 
  593         if (off < 0)
  594                 return (-1);
  595 
  596         seg.ds_addr = addr;
  597         seg.ds_len = size;
  598 
  599         return (bus_dmamem_mmap(sc->sc_dmat, &seg, 1, off, prot, flags));
  600 }
  601 
  602 int
  603 isa_drq_isfree(struct device *isadev, int chan)
  604 {
  605         struct isa_softc *sc = (struct isa_softc *)isadev;
  606         if (chan < 0 || chan > 7) {
  607                 panic("isa_drq_isfree: %s: bogus drq %d", sc->sc_dev.dv_xname,
  608                     chan);
  609         }
  610         return ISA_DRQ_ISFREE(sc, chan);
  611 }
  612 
  613 void *
  614 isa_malloc(struct device *isadev, int chan, size_t size, int pool, int flags)
  615 {
  616         bus_addr_t addr;
  617         caddr_t kva;
  618         int bflags;
  619         struct isa_mem *m;
  620 
  621         bflags = flags & M_NOWAIT ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
  622 
  623         if (isa_dmamem_alloc(isadev, chan, size, &addr, bflags))
  624                 return 0;
  625         if (isa_dmamem_map(isadev, chan, addr, size, &kva, bflags)) {
  626                 isa_dmamem_free(isadev, chan, addr, size);
  627                 return 0;
  628         }
  629         m = malloc(sizeof(*m), pool, flags);
  630         if (m == 0) {
  631                 isa_dmamem_unmap(isadev, chan, kva, size);
  632                 isa_dmamem_free(isadev, chan, addr, size);
  633                 return 0;
  634         }
  635         m->isadev = isadev;
  636         m->chan = chan;
  637         m->size = size;
  638         m->addr = addr;
  639         m->kva = kva;
  640         m->next = isa_mem_head;
  641         isa_mem_head = m;
  642         return (void *)kva;
  643 }
  644 
  645 void
  646 isa_free(void *addr, int pool)
  647 {
  648         struct isa_mem **mp, *m;
  649         caddr_t kva = (caddr_t)addr;
  650 
  651         for(mp = &isa_mem_head; *mp && (*mp)->kva != kva; mp = &(*mp)->next)
  652                 ;
  653         m = *mp;
  654         if (!m) {
  655                 printf("isa_free: freeing unallocated memory\n");
  656                 return;
  657         }
  658         *mp = m->next;
  659         isa_dmamem_unmap(m->isadev, m->chan, kva, m->size);
  660         isa_dmamem_free(m->isadev, m->chan, m->addr, m->size);
  661         free(m, pool, 0);
  662 }
  663 
  664 paddr_t
  665 isa_mappage(void *mem, off_t off, int prot)
  666 {
  667         struct isa_mem *m;
  668 
  669         for(m = isa_mem_head; m && m->kva != (caddr_t)mem; m = m->next)
  670                 ;
  671         if (!m) {
  672                 printf("isa_mappage: mapping unallocated memory\n");
  673                 return -1;
  674         }
  675         return (isa_dmamem_mmap(m->isadev, m->chan, m->addr, m->size, off,
  676             prot, BUS_DMA_WAITOK));
  677 }

Cache object: edb811c9ad6ecc68dfef8330c6d3add2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.