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); dmaend(DMAchan);
nexterror(); 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) if(dp->len < 0)
error(Eio); error(Eio);
@ -999,7 +999,7 @@ floppyformat(FDrive *dp, Cmdbuf *cb)
dmaend(DMAchan); dmaend(DMAchan);
nexterror(); nexterror();
} }
if(dmasetup(DMAchan, buf, bp-buf, 0) < 0) if(dmasetup(DMAchan, buf, bp-buf, DMAWRITE) < 0)
error(Eio); error(Eio);
/* /*

View file

@ -18,7 +18,7 @@ struct DMAxfer
int blen; /* bounce buffer length */ int blen; /* bounce buffer length */
void* va; /* virtual address destination/src */ void* va; /* virtual address destination/src */
long len; /* bytes to be transferred */ long len; /* bytes to be transferred */
int isread; int flags;
}; };
/* /*
@ -81,7 +81,7 @@ _i8237alloc(void)
if(i8237dma > 2) if(i8237dma > 2)
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){ if(bva == nil || PADDR(bva)+64*1024*i8237dma > 16*MB){
/* /*
* This will panic with the current * This will panic with the current
@ -137,11 +137,38 @@ dmainit(int chan, int maxtransfer)
xp->bpa = PADDR(xp->bva); xp->bpa = PADDR(xp->bva);
xp->blen = maxtransfer; xp->blen = maxtransfer;
xp->len = 0; xp->len = 0;
xp->isread = 0; xp->flags = 0;
return 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 * setup a dma transfer. if the destination is not in kernel
* memory, allocate a page for the transfer. * memory, allocate a page for the transfer.
@ -153,7 +180,7 @@ dmainit(int chan, int maxtransfer)
* boundaries) * boundaries)
*/ */
long long
dmasetup(int chan, void *va, long len, int isread) dmasetup(int chan, void *va, long len, int flags)
{ {
DMA *dp; DMA *dp;
ulong pa; ulong pa;
@ -175,11 +202,11 @@ dmasetup(int chan, void *va, long len, int isread)
return -1; return -1;
if(len > xp->blen) if(len > xp->blen)
len = xp->blen; len = xp->blen;
if(!isread) if(!(flags & DMAREAD))
memmove(xp->bva, va, len); memmove(xp->bva, va, len);
xp->va = va; xp->va = va;
xp->len = len; xp->len = len;
xp->isread = isread; xp->flags = flags;
pa = xp->bpa; pa = xp->bpa;
} }
else else
@ -189,7 +216,7 @@ dmasetup(int chan, void *va, long len, int isread)
* this setup must be atomic * this setup must be atomic
*/ */
ilock(dp); 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->mode, mode); /* single mode dma (give CPU a chance at mem) */
outb(dp->page[chan], pa>>16); outb(dp->page[chan], pa>>16);
outb(dp->cbp, 0); /* set count & address to their first byte */ outb(dp->cbp, 0); /* set count & address to their first byte */
@ -238,7 +265,7 @@ dmaend(int chan)
iunlock(dp); iunlock(dp);
xp = &dp->x[chan]; xp = &dp->x[chan];
if(xp->len == 0 || !xp->isread) if(xp->len == 0 || !(xp->flags & DMAREAD))
return; return;
/* /*
@ -248,17 +275,3 @@ dmaend(int chan)
xp->len = 0; 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 cpuidprint(void);
void (*cycles)(uvlong*); void (*cycles)(uvlong*);
void delay(int); void delay(int);
void* dmabva(int);
int dmacount(int); int dmacount(int);
int dmadone(int); int dmadone(int);
void dmaend(int); void dmaend(int);
int dmainit(int, int); int dmainit(int, int);
#define DMAWRITE 0
#define DMAREAD 1
#define DMALOOP 2
long dmasetup(int, void*, long, int); long dmasetup(int, void*, long, int);
#define evenaddr(x) /* x86 doesn't care */ #define evenaddr(x) /* x86 doesn't care */
void fpclear(void); void fpclear(void);
@ -181,5 +185,3 @@ int xchgw(ushort*, int);
#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1])) #define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
#define KADDR(a) kaddr(a) #define KADDR(a) kaddr(a)
#define PADDR(a) paddr((void*)(a)) #define PADDR(a) paddr((void*)(a))
#define dcflush(a, b)

View file

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