#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #include "sa1110dma.h" static int debug = 0; /* * DMA helper routines */ enum { NDMA = 6, /* Number of DMA channels */ DMAREGS = 0xb0000000, /* DMA registers, physical */ }; enum { /* Device Address Register, DDAR */ RW = 0, E = 1, BS = 2, DW = 3, DS = 4, /* bits 4 - 7 */ DA = 8 /* bits 8 - 31 */ }; enum { /* Device Control & Status Register, DCSR */ RUN = 0, IE = 1, ERROR = 2, DONEA = 3, STRTA = 4, DONEB = 5, STRTB = 6, BIU = 7 }; typedef struct DMAchan { int allocated; Rendez r; void (*intr)(void*, ulong); void *param; } DMAchan; struct { Lock; DMAchan chan[6]; } dma; struct dmaregs { ulong ddar; ulong dcsr_set; ulong dcsr_clr; ulong dcsr_rd; ulong dstrtA; ulong dxcntA; ulong dstrtB; ulong dxcntB; } *dmaregs; static void dmaintr(Ureg*, void *); void dmainit(void) { int i; /* map the lcd regs into the kernel's virtual space */ dmaregs = (struct dmaregs*)mapspecial(DMAREGS, NDMA*sizeof(struct dmaregs)); if (debug) print("dma: dmaalloc registers 0x%ux mapped at 0x%p\n", DMAREGS, dmaregs); for (i = 0; i < NDMA; i++) { intrenable(IRQ, IRQdma0+i, dmaintr, &dmaregs[i], "DMA"); } } void dmareset(int i, int rd, int bigendian, int burstsize, int datumsize, int device, ulong port) { ulong ddar; ddar = (rd?1:0)< 1) iprint("dma: dmastart 0x%lux\n", status); if ((status & (1< 1) print("dmaidle: 0x%lux\n", status); return (status & (1<dcsr_rd; if (debug > 1) iprint("dma: interrupt channel %d, status 0x%lux\n", i, dcsr); if (dcsr & 1<dcsr_clr = 1<dcsr_clr = ERROR; iprint("DMA error, channel %d, status 0x%lux\n", i, dcsr); if (dma.chan[i].intr) { (*dma.chan[i].intr)(dma.chan[i].param, 0); } wakeup(&dma.chan[i].r); return; } iprint("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr); }