sb16: new approach, works in qemu

This commit is contained in:
cinap_lenrek 2011-05-18 19:57:31 +00:00
parent e7e04b5cbb
commit b74418c2ce
5 changed files with 533 additions and 607 deletions

File diff suppressed because it is too large Load diff

View file

@ -857,7 +857,7 @@ floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
dmaend(DMAchan);
nexterror();
}
dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread ? DMAREAD : DMAWRITE);
if(dp->len < 0)
error(Eio);
@ -999,7 +999,7 @@ floppyformat(FDrive *dp, Cmdbuf *cb)
dmaend(DMAchan);
nexterror();
}
if(dmasetup(DMAchan, buf, bp-buf, 0) < 0)
if(dmasetup(DMAchan, buf, bp-buf, DMAWRITE) < 0)
error(Eio);
/*

View file

@ -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);
}
*/

View file

@ -18,10 +18,14 @@ int cpuidentify(void);
void cpuidprint(void);
void (*cycles)(uvlong*);
void delay(int);
void* dmabva(int);
int dmacount(int);
int dmadone(int);
void dmaend(int);
int dmainit(int, int);
#define DMAWRITE 0
#define DMAREAD 1
#define DMALOOP 2
long dmasetup(int, void*, long, int);
#define evenaddr(x) /* x86 doesn't care */
void fpclear(void);
@ -181,5 +185,3 @@ int xchgw(ushort*, int);
#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
#define KADDR(a) kaddr(a)
#define PADDR(a) paddr((void*)(a))
#define dcflush(a, b)

View file

@ -18,6 +18,7 @@ enum {
Qaudioctl,
Qaudiostatus,
Qvolume,
Maxaudioprobes = 8,
};
@ -48,19 +49,26 @@ audioreset(void)
int i, ctlrno = 0;
Audio **pp;
Audioprobe *probe;
pp = &audiodevs;
*pp = malloc(sizeof(Audio));
(*pp)->ctlrno = ctlrno++;
for(i = 0; i < naudioprobes; i++){
for(i=0; i<naudioprobes; i++){
probe = &audioprobes[i];
(*pp)->name = probe->name;
while(!probe->probe(*pp)){
for(;;){
memset(*pp, 0, sizeof(Audio));
(*pp)->ctlrno = ctlrno;
(*pp)->name = probe->name;
if(probe->probe(*pp))
break;
ctlrno++;
pp = &(*pp)->next;
*pp = malloc(sizeof(Audio));
(*pp)->ctlrno = ctlrno++;
(*pp)->name = probe->name;
}
}
free(*pp);
*pp = nil;
}