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/bitsy/sa1110dma.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 #include        "u.h"
    2 #include        "../port/lib.h"
    3 #include        "mem.h"
    4 #include        "dat.h"
    5 #include        "fns.h"
    6 #include        "io.h"
    7 #include        "../port/error.h"
    8 #include        "sa1110dma.h"
    9 
   10 static int debug = 0;
   11 
   12 /*
   13  *      DMA helper routines
   14  */
   15 
   16 enum {
   17         NDMA    =       6,                      /* Number of DMA channels */
   18         DMAREGS =       0xb0000000,     /* DMA registers, physical */
   19 };
   20 
   21 enum {
   22         /* Device Address Register, DDAR */
   23         RW              =       0,
   24         E               =       1,
   25         BS              =       2,
   26         DW              =       3,
   27         DS              =       4,      /* bits 4 - 7 */
   28         DA              =       8       /* bits 8 - 31 */
   29 };
   30 
   31 enum {
   32         /* Device Control & Status Register, DCSR */
   33         RUN             =       0,
   34         IE              =       1,
   35         ERROR   =       2,
   36         DONEA   =       3,
   37         STRTA   =       4,
   38         DONEB   =       5,
   39         STRTB   =       6,
   40         BIU             =       7
   41 };
   42 
   43 typedef struct DMAchan {
   44         int             allocated;
   45         Rendez  r;
   46         void    (*intr)(void*, ulong);
   47         void    *param;
   48 } DMAchan;
   49 
   50 struct {
   51         Lock;
   52         DMAchan chan[6];
   53 } dma;
   54 
   55 struct dmaregs {
   56         ulong   ddar;
   57         ulong   dcsr_set;
   58         ulong   dcsr_clr;
   59         ulong   dcsr_rd;
   60         ulong   dstrtA;
   61         ulong   dxcntA;
   62         ulong   dstrtB;
   63         ulong   dxcntB;
   64 } *dmaregs;
   65 
   66 static void     dmaintr(Ureg*, void *);
   67 
   68 void
   69 dmainit(void) {
   70         int i;
   71 
   72         /* map the lcd regs into the kernel's virtual space */
   73         dmaregs = (struct dmaregs*)mapspecial(DMAREGS, NDMA*sizeof(struct dmaregs));
   74         if (debug) print("dma: dmaalloc registers 0x%ux mapped at 0x%p\n",
   75                 DMAREGS, dmaregs);
   76         for (i = 0; i < NDMA; i++) {
   77                 intrenable(IRQ, IRQdma0+i, dmaintr, &dmaregs[i], "DMA");
   78         }
   79 }
   80 
   81 void
   82 dmareset(int i, int rd, int bigendian, int burstsize, int datumsize, int device, ulong port) {
   83         ulong ddar;
   84 
   85         ddar =
   86                 (rd?1:0)<<RW |
   87                 (bigendian?1:0)<<E |
   88                 ((burstsize==8)?1:0)<<BS |
   89                 ((datumsize==2)?1:0)<<DW |
   90                 device<<DS |
   91                 0x80000000 | ((ulong)port << 6);
   92         dmaregs[i].ddar = ddar;
   93         dmaregs[i].dcsr_clr = 0xff;
   94         if (debug) print("dma: dmareset: 0x%lux\n", ddar);
   95 }
   96 
   97 int
   98 dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, ulong port, void (*intr)(void*, ulong), void *param) {
   99         int i;
  100 
  101         lock(&dma);
  102         for (i = 0; i < NDMA; i++) {
  103                 if (dma.chan[i].allocated)
  104                         continue;
  105                 dma.chan[i].allocated++;
  106                 unlock(&dma);
  107                 dmareset(i, rd, bigendian, burstsize, datumsize, device, port);
  108                 dma.chan[i].intr = intr;
  109                 dma.chan[i].param = param;
  110                 return i;
  111         }
  112         unlock(&dma);
  113         return -1;
  114 }
  115 
  116 void
  117 dmafree(int i) {
  118         dmaregs[i].dcsr_clr = 0xff;
  119         dmaregs[i].ddar = 0;
  120         dma.chan[i].allocated = 0;
  121         dma.chan[i].intr = nil;
  122 }
  123 
  124 void
  125 dmastop(int i) {
  126         dmaregs[i].dcsr_clr = 0xff;
  127 }
  128 
  129 ulong
  130 dmastart(int chan,  ulong addr, int count) {
  131         ulong status, n;
  132         static int last;
  133 
  134         /* If this gets called from interrupt routines, make sure ilocks are used */
  135         status = dmaregs[chan].dcsr_rd;
  136         if (debug > 1)
  137                 iprint("dma: dmastart 0x%lux\n", status);
  138 
  139         if ((status & (1<<STRTA|1<<STRTB|1<<RUN)) == (1<<STRTA|1<<STRTB|1<<RUN)) {
  140                 return 0;
  141         }
  142         cachewbregion(addr, count);
  143         n = 0x100;
  144         if ((status & (1<<BIU | 1<<STRTB)) == (1<<BIU | 1<<STRTB) ||
  145                 (status & (1<<BIU | 1<<STRTA)) == 0) {
  146                 if (status & 1<<STRTA)
  147                         iprint("writing busy dma entry 0x%lux\n", status);
  148                 if (status & 1<<STRTB)
  149                         n = (last == 1)?0x200:0x300;
  150                 last = 2;
  151                 dmaregs[chan].dstrtA = addr;
  152                 dmaregs[chan].dxcntA = count;
  153                 dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTA;
  154                 n |= 1<<DONEA;
  155         } else {
  156                 if (status & 1<<STRTB)
  157                         iprint("writing busy dma entry 0x%lux\n", status);
  158                 if (status & 1<<STRTA)
  159                         n = (last == 2)?0x200:0x300;
  160                 last = 1;
  161                 dmaregs[chan].dstrtB = addr;
  162                 dmaregs[chan].dxcntB = count;
  163                 dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTB;
  164                 n |= 1<<DONEB;
  165         }
  166         return n;
  167 }
  168 
  169 int
  170 dmaidle(int chan) {
  171         ulong status;
  172 
  173         status = dmaregs[chan].dcsr_rd;
  174         if (debug > 1) print("dmaidle: 0x%lux\n", status);
  175         return (status & (1<<STRTA|1<<STRTB)) == 0;
  176 }
  177 
  178 static int
  179 _dmaidle(void* chan) {
  180         ulong status;
  181 
  182         status = dmaregs[(int)chan].dcsr_rd;
  183         return (status & (1<<STRTA|1<<STRTB)) == 0;
  184 }
  185 
  186 void
  187 dmawait(int chan) {
  188         while (!dmaidle(chan))
  189                 sleep(&dma.chan[chan].r, _dmaidle, (void*)chan);
  190 }
  191 
  192 /*
  193  *  interrupt routine
  194  */
  195 static void
  196 dmaintr(Ureg*, void *x)
  197 {
  198         int i;
  199         struct dmaregs *regs = x;
  200         ulong dcsr, donebit;
  201 
  202         i = regs - dmaregs;
  203         dcsr = regs->dcsr_rd;
  204         if (debug > 1)
  205                 iprint("dma: interrupt channel %d, status 0x%lux\n", i, dcsr);
  206         if (dcsr & 1<<ERROR)
  207                 iprint("error, channel %d, status 0x%lux\n", i, dcsr);
  208         donebit = 1<<((dcsr&1<<BIU)?DONEA:DONEB);
  209         if (dcsr & donebit) {
  210                 regs->dcsr_clr = 1<<DONEA|1<<DONEB;
  211                 if (dma.chan[i].intr) {
  212                         (*dma.chan[i].intr)(dma.chan[i].param, dcsr & (1<<DONEA|1<<DONEB));
  213                 }
  214                 wakeup(&dma.chan[i].r);
  215                 return;
  216         }
  217         if (dcsr & 1<<ERROR) {
  218                 regs->dcsr_clr = ERROR;
  219                 iprint("DMA error, channel %d, status 0x%lux\n", i, dcsr);
  220                 if (dma.chan[i].intr) {
  221                         (*dma.chan[i].intr)(dma.chan[i].param, 0);
  222                 }
  223                 wakeup(&dma.chan[i].r);
  224                 return;
  225         }
  226         iprint("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
  227 }

Cache object: 96dabf9c3461d7290f970d87ce1598f0


[ 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.