summaryrefslogtreecommitdiff
path: root/sys/src/9/bcm/dma.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2019-07-25 08:41:37 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2019-07-25 08:41:37 +0200
commit5a0c2e2d17617ece4819e2f66514a498849ee088 (patch)
tree5bf2e35026e3eb4ed3657f57637965a2e6731b3d /sys/src/9/bcm/dma.c
parent4983adfa2cd403eda22d862917c2ff5ed35b48b3 (diff)
bcm, bcm64: add dmaflush() function and make virtio size and virtual address configurable in Soc.virtio and Soc.iosize
Diffstat (limited to 'sys/src/9/bcm/dma.c')
-rw-r--r--sys/src/9/bcm/dma.c50
1 files changed, 43 insertions, 7 deletions
diff --git a/sys/src/9/bcm/dma.c b/sys/src/9/bcm/dma.c
index e0d073ae1..81b68199f 100644
--- a/sys/src/9/bcm/dma.c
+++ b/sys/src/9/bcm/dma.c
@@ -82,6 +82,8 @@ struct Ctlr {
Cb *cb;
Rendez r;
int dmadone;
+ void *flush;
+ int len;
};
struct Cb {
@@ -108,7 +110,7 @@ dmaaddr(void *va)
static uintptr
dmaioaddr(void *va)
{
- return soc.busio | ((uintptr)va - VIRTIO);
+ return soc.busio | ((uintptr)va - soc.virtio);
}
static void
@@ -164,26 +166,28 @@ dmastart(int chan, int dev, int dir, void *src, void *dst, int len)
ctlr->regs[Cs] = Reset;
while(ctlr->regs[Cs] & Reset)
;
- intrenable(IRQDMA(chan), dmainterrupt, ctlr, 0, "dma");
+ intrenable(IRQDMA(chan), dmainterrupt, ctlr, BUSUNKNOWN, "dma");
}
+ ctlr->len = len;
cb = ctlr->cb;
ti = 0;
switch(dir){
case DmaD2M:
- cachedwbinvse(dst, len);
+ ctlr->flush = dst;
ti = Srcdreq | Destinc;
cb->sourcead = dmaioaddr(src);
cb->destad = dmaaddr(dst);
break;
case DmaM2D:
- cachedwbse(src, len);
+ ctlr->flush = nil;
+ dmaflush(1, src, len);
ti = Destdreq | Srcinc;
cb->sourcead = dmaaddr(src);
cb->destad = dmaioaddr(dst);
break;
case DmaM2M:
- cachedwbse(src, len);
- cachedwbinvse(dst, len);
+ ctlr->flush = dst;
+ dmaflush(1, src, len);
ti = Srcinc | Destinc;
cb->sourcead = dmaaddr(src);
cb->destad = dmaaddr(dst);
@@ -193,7 +197,7 @@ dmastart(int chan, int dev, int dir, void *src, void *dst, int len)
cb->txfrlen = len;
cb->stride = 0;
cb->nextconbk = 0;
- cachedwbse(cb, sizeof(Cb));
+ dmaflush(1, cb, sizeof(Cb));
ctlr->regs[Cs] = 0;
microdelay(1);
ctlr->regs[Conblkad] = dmaaddr(cb);
@@ -220,6 +224,10 @@ dmawait(int chan)
ctlr = &dma[chan];
tsleep(&ctlr->r, dmadone, ctlr, 3000);
ctlr->dmadone = 0;
+ if(ctlr->flush != nil){
+ dmaflush(0, ctlr->flush, ctlr->len);
+ ctlr->flush = nil;
+ }
r = ctlr->regs;
DBG dumpdregs("after sleep", r);
s = r[Cs];
@@ -233,3 +241,31 @@ dmawait(int chan)
r[Cs] = Int|End;
return 0;
}
+
+void
+dmaflush(int clean, void *p, ulong len)
+{
+ uintptr s = (uintptr)p;
+ uintptr e = (uintptr)p + len;
+
+ if(clean){
+ s &= ~(BLOCKALIGN-1);
+ e += BLOCKALIGN-1;
+ e &= ~(BLOCKALIGN-1);
+ cachedwbse((void*)s, e - s);
+ return;
+ }
+ if(s & BLOCKALIGN-1){
+ s &= ~(BLOCKALIGN-1);
+ cachedwbinvse((void*)s, BLOCKALIGN);
+ s += BLOCKALIGN;
+ }
+ if(e & BLOCKALIGN-1){
+ e &= ~(BLOCKALIGN-1);
+ if(e < s)
+ return;
+ cachedwbinvse((void*)e, BLOCKALIGN);
+ }
+ if(s < e)
+ cachedinvse((void*)s, e - s);
+}