## diffname bitsy/sa1110dma.c 2000/1103
## diff -e /dev/null /n/emeliedump/2000/1103/sys/src/9/bitsy/sa1110dma.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
/*
* 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
};
struct {
Lock;
Rendez r;
int channels;
} dma;
struct dmaregs {
ulong ddar;
ulong dcsr_set;
ulong dcsr_clr;
ulong dcsr_rd;
ulong dstrtA;
ulong dxcntA;
ulong dstrtB;
ulong dxcntB;
} *dmaregs;
void
dmainit(void) {
/* map the lcd regs into the kernel's virtual space */
dmaregs = (struct dmaregs*)mapspecial(DMAREGS, NDMA*sizeof(struct dmaregs));;
}
int
dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, void *port) {
int i;
lock(&dma);
for (i = 0; i < NDMA; i++) {
if (dma.channels & (1 << i))
continue;
dma.channels |= 1 << i;
unlock(&dma);
dmaregs[i].ddar =
(rd?1:0)<<RW |
(bigendian?1:0)<<E |
((burstsize==8)?1:0)<<BS |
((datumsize==2)?1:0)<<DW |
device<<DS |
0x80000000 | (port << 6);
return i;
}
unlock(&dma);
return -1;
}
void
dmafree(i) {
int i;
lock(&dma);
dma.channels &= ~(1<<i);
unlock(&dma);
}
static int
dmaready(void *dcsr) {
return = *(ulong*)dcsr & ((1<<DONEA)|(1<<DONEB));
}
int
dmastart(int chan, void *addr, int count) {
ulong ab;
while ((ab = dmaready(&dma[chan].dcsr_rd)) == 0) {
sleep(&dma.r, dmaready, &dma[chan].dcsr_rd);
}
cachewb();
if (ab & (1<<DONEA)) {
dma[chan].dcsr_clr |= 1<<DONEA | 1<<STARTA;
dma[chan].dstrtA = addr;
dma[chan].dxcntA = count-1;
dma[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STARTA;
} else {
dma[chan].dcsr_clr |= 1<<DONEB | 1<<STARTB;
dma[chan].dstrtB = addr;
dma[chan].dxcntB = count-1;
dma[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STARTB;
}
}
/*
* interrupt routine
*/
static void
dmaintr(Ureg*, void *x)
{
for (i = 0; i < NDMA; i++) {
}
}
.
## diffname bitsy/sa1110dma.c 2000/1104
## diff -e /n/emeliedump/2000/1103/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1104/sys/src/9/bitsy/sa1110dma.c
129a
for (i = 0; i < NDMA; i++) {
if (dmaregs[i].dcsr_rd & (1<<DONEA | 1<<DONEB | 1<<ERROR))
wakeup(&dma.r[i]);
.
128c
int i;
.
121a
ulong
dmadone(int chan, ulong op) {
ulong dcsr;
dcsr = dmaregs[chan].dcsr_rd;
if (dcsr & 1<<ERROR)
pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
return dcsr & (op | 1<<ERROR);
}
void
dmawait(int chan, ulong op) {
ulong dcsr;
while (((dcsr = dmaregs[chan].dcsr_rd) & (op | 1<<ERROR)) == 0)
sleep(&dma.r[chan], dmaready, &dmaregs[chan].dcsr_rd);
if (dcsr & 1<<ERROR)
pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
}
.
115,118c
dmaregs[chan].dcsr_clr |= 1<<DONEB | 1<<STRTB;
dmaregs[chan].dstrtB = addr;
dmaregs[chan].dxcntB = count-1;
dmaregs[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STRTB;
return 1<<DONEB;
.
110,113c
dmaregs[chan].dcsr_clr |= 1<<DONEA | 1<<STRTA;
dmaregs[chan].dstrtA = addr;
dmaregs[chan].dxcntA = count-1;
dmaregs[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STRTA;
return 1<<DONEA;
.
105,106c
while ((ab = dmaready(&dmaregs[chan].dcsr_rd)) == 0) {
sleep(&dma.r[chan], dmaready, &dmaregs[chan].dcsr_rd);
.
101c
ulong
.
97,98c
return *(int*)dcsr & ((1<<DONEA)|(1<<DONEB));
.
87,89c
dmafree(int i) {
.
79c
0x80000000 | ((ulong)port << 6);
.
53c
void* dstrtB;
.
51c
void* dstrtA;
.
42c
Rendez r[6];
.
## diffname bitsy/sa1110dma.c 2000/1109
## diff -e /n/emeliedump/2000/1104/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1109/sys/src/9/bitsy/sa1110dma.c
150,151c
if ((dcsr = dmaregs[i].dcsr_rd) & (1<<DONEA | 1<<DONEB | 1<<ERROR))
wakeup(&dma.chan[i].r);
if (dma.chan[i].f)
(*dma.chan[i].f)(dcsr);
.
147a
ulong dcsr;
.
136c
sleep(&dma.chan[chan].r, dmaready, &dmaregs[chan].dcsr_rd);
.
102,106c
if (((status = dmaregs[chan].dcsr_rd) & ((1<<DONEA)|(1<<DONEB))) == 0)
return 0;
cachewbregion(addr, count);
if ((status & (1<<BIU | 1<<STRTB)) == (1<<BIU | 1<<STRTB) ||
(status & (1<<BIU | 1<<STRTA)) == (1<<STRTA)) {
.
100c
ulong status;
.
88,90c
dma.chan[i].inuse = 0;
.
71c
dma.chan[i].inuse++;
.
69c
if (dma.chan[i].inuse)
.
42,43c
Chan chan[6];
.
39a
typedef struct Chan {
int inuse;
Rendez r;
void (*f)(void);
} Chan;
.
## diffname bitsy/sa1110dma.c 2000/1110
## diff -e /n/emeliedump/2000/1109/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1110/sys/src/9/bitsy/sa1110dma.c
157,158c
if (dma.chan[i].intr)
(*dma.chan[i].intr)(dma.chan[i].param, dcsr);
.
134a
int
dmaidle(int chan) {
ulong dcsr;
dcsr = dmaregs[chan].dcsr_rd;
if (dcsr & 1<<ERROR)
pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
return (dcsr & (1<<DONEA | 1<<DONEB)) == (1<<DONEA | 1<<DONEB);
}
.
93a
dma.chan[i].intr = nil;
.
84a
dma.chan[i].intr = intr;
dma.chan[i].param = param;
.
69c
dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, void *port, void (*intr)(int, ulong), void *param) {
.
43c
void (*intr)(int, ulong);
void *param;
.
7a
#include "sa1110dma.h"
.
## diffname bitsy/sa1110dma.c 2000/1111
## diff -e /n/emeliedump/2000/1110/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1111/sys/src/9/bitsy/sa1110dma.c
169,174c
i = regs - dmaregs;
if ((dcsr = regs->dcsr_rd) & (1<<DONEA | 1<<DONEB | 1<<ERROR)) {
wakeup(&dma.chan[i].r);
if (dma.chan[i].intr)
(*dma.chan[i].intr)(dma.chan[i].param, dcsr);
} else
print("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
.
166a
struct dmaregs *regs = x;
.
113c
cachewbregion((ulong)addr, count);
.
71c
dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, ulong port, void (*intr)(void*, ulong), void *param) {
.
67a
for (i = 0; i < NDMA; i++) {
intrenable(IRQdma0+i, dmaintr, &dmaregs[i], "DMA");
}
.
65a
int i;
.
63a
static void dmaintr(Ureg*, void *);
.
50c
DMAchan chan[6];
.
46c
} DMAchan;
.
44c
void (*intr)(void*, ulong);
.
41c
typedef struct DMAchan {
.
## diffname bitsy/sa1110dma.c 2000/1113
## diff -e /n/emeliedump/2000/1111/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1113/sys/src/9/bitsy/sa1110dma.c
176a
if (debug) print("dma: interrupt\n");
.
116a
if (debug) print("dma: dmastart\n");
.
80a
if (debug) print("dma: dmaalloc\n");
.
9a
static int debug = 1;
.
## diffname bitsy/sa1110dma.c 2000/1115
## diff -e /n/emeliedump/2000/1113/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1115/sys/src/9/bitsy/sa1110dma.c
188c
iprint("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
.
186c
(*dma.chan[i].intr)(dma.chan[i].param, 3-dma.chan[i].active.ref);
/* must call interrupt routine before calling decref */
decref(&dma.chan[i].active);
wakeup(&dma.chan[i].r);
.
183,184c
dcsr = regs->dcsr_rd;
if (debug > 1)
iprint("dma: interrupt channel %d, status 0x%lux\n", i, dcsr);
if (dcsr & 1<<ERROR)
iprint("error, channel %d, status 0x%lux\n", i, dcsr);
donebit = 1<<((dcsr&1<<BIU)?DONEA:DONEB);
if (dcsr & donebit) {
regs->dcsr_clr |= donebit;
.
181d
179c
ulong dcsr, donebit;
.
162,168c
dmawait(int chan) {
while (dma.chan[chan].active.ref)
sleep(&dma.chan[chan].r, _dmaidle, (void*)chan);
.
155,158c
static int
_dmaidle(void* chan) {
return dma.chan[(int)chan].active.ref == 0;
.
153c
return dma.chan[chan].active.ref == 0;
}
.
141,150d
136c
incref(&dma.chan[chan].active);
dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTB;
.
133c
dmaregs[chan].dcsr_clr = 1<<DONEB | 1<<STRTB;
.
130c
incref(&dma.chan[chan].active);
dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTA;
.
126,127c
(status & (1<<BIU | 1<<STRTA)) == 0) {
dmaregs[chan].dcsr_clr = 1<<DONEA | 1<<STRTA;
.
123a
if ((status & (1<<DONEA|1<<DONEB|1<<RUN)) == 1<<RUN)
panic("dmastart called while busy");
.
122a
}
.
120,121c
status = dmaregs[chan].dcsr_rd;
if (debug > 1) print("dma: dmastart 0x%lux\n", status);
if (dma.chan[chan].active.ref >= 2) {
if (debug > 1) print("\n");
.
111,115d
107c
dma.chan[i].allocated = 0;
.
98a
dmaregs[i].dcsr_clr = 0xff;
.
96a
dmaregs[i].ddar = ddar;
if (debug) print("dma: dmaalloc: 0x%lux\n", ddar);
.
90c
ddar =
.
88c
dma.chan[i].allocated++;
.
86c
if (dma.chan[i].allocated)
.
83d
81a
ulong ddar;
.
73a
if (debug) print("dma: dmaalloc registers 0x%ux mapped at 0x%p\n",
DMAREGS, dmaregs);
.
44c
int allocated;
Ref active;
.
## diffname bitsy/sa1110dma.c 2000/1116
## diff -e /n/emeliedump/2000/1115/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1116/sys/src/9/bitsy/sa1110dma.c
191,192c
return;
}
iprint("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
iunlock(&dma.chan[i]);
.
185,189c
regs->dcsr_clr = donebit;
/* try the other bit as well */
donebit ^= 1<<DONEA|1<<DONEB;
if (dcsr & donebit) {
regs->dcsr_clr = donebit;
}
iunlock(&dma.chan[i]);
if (dma.chan[i].intr) {
dcsr &= 1<<STRTA | 1<<STRTB | 1<<RUN;
(*dma.chan[i].intr)(dma.chan[i].param, dcsr == 0);
}
.
177a
ilock(&dma.chan[i]);
.
163c
while (!dmaidle(chan))
.
158c
ulong status;
status = dmaregs[(int)chan].dcsr_rd;
return (status & (1<<STRTA|1<<STRTB|1<<RUN)) == 0;
.
153c
ulong status;
status = dmaregs[chan].dcsr_rd;
return (status & (1<<STRTA|1<<STRTB|1<<RUN)) == 0;
.
148a
iunlock(&dma.chan[chan]);
return n;
.
147d
145d
142c
assert((status & 1<<STRTB) == 0);
if (status & 1<<RUN)
n = 2;
.
140d
138d
135c
assert((status & 1<<STRTA) == 0);
if (status & 1<<RUN)
n = 2;
.
132a
n = 1;
.
128,131d
124,125c
if ((status & (1<<STRTA|1<<STRTB|1<<RUN)) == (1<<STRTA|1<<STRTB|1<<RUN)) {
iunlock(&dma.chan[chan]);
.
122c
if (debug > 1)
iprint("dma: dmastart 0x%lux\n", status);
.
120a
ilock(&dma.chan[chan]);
.
119c
ulong status, n;
.
45d
43a
Lock;
.
## diffname bitsy/sa1110dma.c 2000/1117
## diff -e /n/emeliedump/2000/1116/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1117/sys/src/9/bitsy/sa1110dma.c
208d
201,202c
(*dma.chan[i].intr)(dma.chan[i].param, dcsr & (1<<DONEA|1<<DONEB));
.
194,199d
185d
165c
return (status & (1<<STRTA|1<<STRTB)) == 0;
.
157c
if (debug > 1) print("dmaidle: 0x%lux\n", status);
return (status & (1<<STRTA|1<<STRTB)) == 0;
.
148d
141,143c
if (status & 1<<STRTB)
iprint("writing busy dma entry 0x%lux\n", status);
if (status & 1<<STRTA)
n = (last == 2)?2:3;
last = 1;
.
134,136c
if (status & 1<<STRTA)
iprint("writing busy dma entry 0x%lux\n", status);
if (status & 1<<STRTB)
n = (last == 1)?2:3;
last = 2;
.
127d
121c
/* If this gets called from interrupt routines, make sure ilocks are used */
.
119a
static int last;
.
112a
dmaregs[i].dcsr_clr = 0xff;
dmaregs[i].ddar = 0;
.
74c
dmaregs = (struct dmaregs*)mapspecial(DMAREGS, NDMA*sizeof(struct dmaregs));
.
44d
## diffname bitsy/sa1110dma.c 2000/1118
## diff -e /n/emeliedump/2000/1117/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1118/sys/src/9/bitsy/sa1110dma.c
131c
cachewbregion(addr, count);
.
119c
dmastart(int chan, ulong addr, int count) {
.
62c
ulong dstrtB;
.
60c
ulong dstrtA;
.
## diffname bitsy/sa1110dma.c 2000/1120
## diff -e /n/emeliedump/2000/1118/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1120/sys/src/9/bitsy/sa1110dma.c
150c
dmaregs[chan].dxcntB = count;
.
141c
dmaregs[chan].dxcntA = count;
.
10c
static int debug = 0;
.
## diffname bitsy/sa1110dma.c 2000/1122
## diff -e /n/emeliedump/2000/1120/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1122/sys/src/9/bitsy/sa1110dma.c
199a
}
wakeup(&dma.chan[i].r);
return;
}
if (dcsr & 1<<ERROR) {
regs->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);
.
197c
regs->dcsr_clr = 1<<DONEA|1<<DONEB;
.
117a
void
dmastop(int i) {
dmaregs[i].dcsr_clr = 0xff;
}
.
## diffname bitsy/sa1110dma.c 2000/1125
## diff -e /n/emeliedump/2000/1122/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1125/sys/src/9/bitsy/sa1110dma.c
103d
92,100c
dmareset(i, rd, bigendian, burstsize, datumsize, device, port);
.
84d
80a
void
dmareset(int i, int rd, int bigendian, int burstsize, int datumsize, int device, ulong port) {
ulong ddar;
ddar =
(rd?1:0)<<RW |
(bigendian?1:0)<<E |
((burstsize==8)?1:0)<<BS |
((datumsize==2)?1:0)<<DW |
device<<DS |
0x80000000 | ((ulong)port << 6);
dmaregs[i].ddar = ddar;
dmaregs[i].dcsr_clr = 0xff;
if (debug) print("dma: dmareset: 0x%lux\n", ddar);
}
.
## diffname bitsy/sa1110dma.c 2000/1205
## diff -e /n/emeliedump/2000/1125/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2000/1205/sys/src/9/bitsy/sa1110dma.c
77c
intrenable(IRQ, IRQdma0+i, dmaintr, &dmaregs[i], "DMA");
.
## diffname bitsy/sa1110dma.c 2001/0501
## diff -e /n/emeliedump/2000/1205/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2001/0501/sys/src/9/bitsy/sa1110dma.c
10c
static int debug = 2;
.
## diffname bitsy/sa1110dma.c 2001/0502
## diff -e /n/emeliedump/2001/0501/sys/src/9/bitsy/sa1110dma.c /n/emeliedump/2001/0502/sys/src/9/bitsy/sa1110dma.c
162a
n |= 1<<DONEB;
.
158c
n = (last == 2)?0x200:0x300;
.
153a
n |= 1<<DONEA;
.
149c
n = (last == 1)?0x200:0x300;
.
143c
n = 0x100;
.
10c
static int debug = 0;
.
|