summaryrefslogtreecommitdiff
path: root/sys/src/9/pc/dma.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@localhost>2011-05-18 19:57:31 +0000
committercinap_lenrek <cinap_lenrek@localhost>2011-05-18 19:57:31 +0000
commitb74418c2ce5c64ba39473e2eb50ea1112be63109 (patch)
tree06b3c26e33277e9f2c5e7a2d345d12efdf5d552e /sys/src/9/pc/dma.c
parente7e04b5cbbedfb1411fcc38b7e7f67db98a251c2 (diff)
sb16: new approach, works in qemu
Diffstat (limited to 'sys/src/9/pc/dma.c')
-rw-r--r--sys/src/9/pc/dma.c57
1 files changed, 35 insertions, 22 deletions
diff --git a/sys/src/9/pc/dma.c b/sys/src/9/pc/dma.c
index 7ecbc5f4a..4a81f516a 100644
--- a/sys/src/9/pc/dma.c
+++ b/sys/src/9/pc/dma.c
@@ -18,7 +18,7 @@ struct DMAxfer
int blen; /* bounce buffer length */
void* va; /* virtual address destination/src */
long len; /* bytes to be transferred */
- int isread;
+ int flags;
};
/*
@@ -81,7 +81,7 @@ _i8237alloc(void)
if(i8237dma > 2)
i8237dma = 2;
- bva = xspanalloc(64*1024*i8237dma, BY2PG, 64*1024);
+ bva = xspanalloc(64*1024*i8237dma, 0, 64*1024);
if(bva == nil || PADDR(bva)+64*1024*i8237dma > 16*MB){
/*
* This will panic with the current
@@ -137,11 +137,38 @@ dmainit(int chan, int maxtransfer)
xp->bpa = PADDR(xp->bva);
xp->blen = maxtransfer;
xp->len = 0;
- xp->isread = 0;
+ xp->flags = 0;
return 0;
}
+void*
+dmabva(int chan)
+{
+ DMA *dp;
+ DMAxfer *xp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+ xp = &dp->x[chan];
+ return xp->bva;
+}
+
+int
+dmacount(int chan)
+{
+ int retval;
+ DMA *dp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+ ilock(dp);
+ retval = inb(dp->count[chan]);
+ retval |= inb(dp->count[chan]) << 8;
+ iunlock(dp);
+ return ((retval<<dp->shift)+1) & 0xFFFF;
+}
+
/*
* setup a dma transfer. if the destination is not in kernel
* memory, allocate a page for the transfer.
@@ -153,7 +180,7 @@ dmainit(int chan, int maxtransfer)
* boundaries)
*/
long
-dmasetup(int chan, void *va, long len, int isread)
+dmasetup(int chan, void *va, long len, int flags)
{
DMA *dp;
ulong pa;
@@ -175,11 +202,11 @@ dmasetup(int chan, void *va, long len, int isread)
return -1;
if(len > xp->blen)
len = xp->blen;
- if(!isread)
+ if(!(flags & DMAREAD))
memmove(xp->bva, va, len);
xp->va = va;
xp->len = len;
- xp->isread = isread;
+ xp->flags = flags;
pa = xp->bpa;
}
else
@@ -189,7 +216,7 @@ dmasetup(int chan, void *va, long len, int isread)
* this setup must be atomic
*/
ilock(dp);
- mode = (isread ? 0x44 : 0x48) | chan;
+ mode = ((flags & DMAREAD) ? 0x44 : 0x48) | ((flags & DMALOOP) ? 0x10 : 0) | chan;
outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */
outb(dp->page[chan], pa>>16);
outb(dp->cbp, 0); /* set count & address to their first byte */
@@ -238,7 +265,7 @@ dmaend(int chan)
iunlock(dp);
xp = &dp->x[chan];
- if(xp->len == 0 || !xp->isread)
+ if(xp->len == 0 || !(xp->flags & DMAREAD))
return;
/*
@@ -248,17 +275,3 @@ dmaend(int chan)
xp->len = 0;
}
-/*
-int
-dmacount(int chan)
-{
- int retval;
- DMA *dp;
-
- dp = &dma[(chan>>2)&1];
- outb(dp->cbp, 0);
- retval = inb(dp->count[chan]);
- retval |= inb(dp->count[chan]) << 8;
- return((retval<<dp->shift)+1);
-}
- */