#include "fns.h"
#include "io.h"
#include "../port/error.h"
+#include "../port/audioif.h"
typedef struct Ring Ring;
typedef struct Blaster Blaster;
enum
{
- Fmono = 1,
- Fin = 2,
- Fout = 4,
-
- Vaudio = 0,
+ Vmaster,
+ Vaudio,
Vsynth,
Vcd,
Vline,
Vspeaker,
Vtreb,
Vbass,
+ Vigain,
+ Vogain,
Vspeed,
+ Vdelay,
Nvol,
- Speed = 44100,
- Ncmd = 50, /* max volume command words */
-
Blocksize = 4096,
Blocks = 65536/Blocksize,
};
int clri8;
int clri16;
int clri401;
- int dma;
void (*startdma)(Ctlr*);
void (*intr)(Ctlr*);
struct Ctlr
{
- QLock;
Rendez vous;
int active; /* boolean dma running */
- int rivol[Nvol]; /* right/left input/output volumes */
- int livol[Nvol];
- int rovol[Nvol];
- int lovol[Nvol];
int major; /* SB16 major version number (sb 4) */
int minor; /* SB16 minor version number */
- ulong totcount; /* how many bytes processed since open */
- vlong tottime; /* time at which totcount bytes were processed */
Ring ring; /* dma ring buffer */
Blaster blaster;
+
+ int lvol[Nvol];
+ int rvol[Nvol];
+
+ /* for probe */
Audio *adev;
+ ISAConf conf;
+ Ctlr *next;
};
-static struct
-{
- char* name;
- int flag;
- int ilval; /* initial values */
- int irval;
-} volumes[] = {
- [Vaudio] "audio", Fout, 50, 50,
- [Vsynth] "synth", Fin|Fout, 0, 0,
- [Vcd] "cd", Fin|Fout, 0, 0,
- [Vline] "line", Fin|Fout, 0, 0,
- [Vmic] "mic", Fin|Fout|Fmono, 0, 0,
- [Vspeaker] "speaker", Fout|Fmono, 0, 0,
-
- [Vtreb] "treb", Fout, 50, 50,
- [Vbass] "bass", Fout, 50, 50,
-
- [Vspeed] "speed", Fin|Fout|Fmono, Speed, Speed,
- 0
+static Volume voltab[] = {
+ [Vmaster] "master", 0x30, 0xff, Stereo, 0,
+ [Vaudio] "audio", 0x32, 0xff, Stereo, 0,
+ [Vsynth] "synth", 0x34, 0xff, Stereo, 0,
+ [Vcd] "cd", 0x36, 0xff, Stereo, 0,
+ [Vline] "line", 0x38, 0xff, Stereo, 0,
+ [Vmic] "mic", 0x3a, 0xff, Mono, 0,
+ [Vspeaker] "speaker", 0x3b, 0xff, Mono, 0,
+ [Vtreb] "treb", 0x44, 0xff, Stereo, 0,
+ [Vbass] "bass", 0x46, 0xff, Stereo, 0,
+ [Vigain] "recgain", 0x3f, 0xff, Stereo, 0,
+ [Vogain] "outgain", 0x41, 0xff, Stereo, 0,
+ [Vspeed] "speed", 0, 0, Absolute, 0,
+ [Vdelay] "delay", 0, 0, Absolute, 0,
+ 0,
};
static char Emajor[] = "soundblaster not responding/wrong version";
-static char Emode[] = "illegal open mode";
-static char Evolume[] = "illegal volume specifier";
-
static long
buffered(Ring *r)
return s;
}
-static void
-mxcmds(Blaster *blaster, int s, int v)
-{
-
- if(v > 100)
- v = 100;
- if(v < 0)
- v = 0;
- mxcmd(blaster, s, (v*255)/100);
-}
-
-static void
-mxcmdt(Blaster *blaster, int s, int v)
-{
-
- if(v > 100)
- v = 100;
- if(v <= 0)
- mxcmd(blaster, s, 0);
- else
- mxcmd(blaster, s, 255-100+v);
-}
-
-static void
-mxcmdu(Blaster *blaster, int s, int v)
-{
-
- if(v > 100)
- v = 100;
- if(v <= 0)
- v = 0;
- mxcmd(blaster, s, 128-50+v);
-}
-
-static void
-mxvolume(Ctlr *ctlr)
+static int
+mxsetvol(Audio *adev, int x, int a[2])
{
Blaster *blaster;
- int *left, *right;
- int source;
-
- if(0){
- left = ctlr->livol;
- right = ctlr->rivol;
- }else{
- left = ctlr->lovol;
- right = ctlr->rovol;
- }
+ Ctlr *ctlr = adev->ctlr;
+ Volume *vol;
+ vol = voltab+x;
blaster = &ctlr->blaster;
-
ilock(blaster);
+ switch(vol->type){
+ case Absolute:
+ switch(x){
+ case Vdelay:
+ adev->delay = a[0];
+ break;
+ case Vspeed:
+ adev->speed = a[0];
+ break;
+ }
+ ctlr->lvol[x] = ctlr->rvol[x] = a[0];
+ break;
+ case Stereo:
+ ctlr->rvol[x] = a[1];
+ mxcmd(blaster, vol->reg+1, a[1]);
+ /* no break */
+ case Mono:
+ ctlr->lvol[x] = a[0];
+ mxcmd(blaster, vol->reg, a[0]);
+ }
+ iunlock(blaster);
- mxcmd(blaster, 0x30, 255); /* left master */
- mxcmd(blaster, 0x31, 255); /* right master */
- mxcmd(blaster, 0x3f, 0); /* left igain */
- mxcmd(blaster, 0x40, 0); /* right igain */
- mxcmd(blaster, 0x41, 0); /* left ogain */
- mxcmd(blaster, 0x42, 0); /* right ogain */
-
- mxcmds(blaster, 0x32, left[Vaudio]);
- mxcmds(blaster, 0x33, right[Vaudio]);
-
- mxcmds(blaster, 0x34, left[Vsynth]);
- mxcmds(blaster, 0x35, right[Vsynth]);
-
- mxcmds(blaster, 0x36, left[Vcd]);
- mxcmds(blaster, 0x37, right[Vcd]);
-
- mxcmds(blaster, 0x38, left[Vline]);
- mxcmds(blaster, 0x39, right[Vline]);
-
- mxcmds(blaster, 0x3a, left[Vmic]);
- mxcmds(blaster, 0x3b, left[Vspeaker]);
+ return 0;
+}
- mxcmdu(blaster, 0x44, left[Vtreb]);
- mxcmdu(blaster, 0x45, right[Vtreb]);
+static int
+mxgetvol(Audio *adev, int x, int a[2])
+{
+ Ctlr *ctlr = adev->ctlr;
- mxcmdu(blaster, 0x46, left[Vbass]);
- mxcmdu(blaster, 0x47, right[Vbass]);
+ a[0] = ctlr->lvol[x];
+ a[1] = ctlr->rvol[x];
- source = 0;
- if(left[Vsynth])
- source |= 1<<6;
- if(right[Vsynth])
- source |= 1<<5;
- if(left[Vaudio])
- source |= 1<<4;
- if(right[Vaudio])
- source |= 1<<3;
- if(left[Vcd])
- source |= 1<<2;
- if(right[Vcd])
- source |= 1<<1;
- if(left[Vmic])
- source |= 1<<0;
- if(0)
- mxcmd(blaster, 0x3c, 0); /* output switch */
- else
- mxcmd(blaster, 0x3c, source);
- mxcmd(blaster, 0x3d, source); /* input left switch */
- mxcmd(blaster, 0x3e, source); /* input right switch */
- iunlock(blaster);
+ return 0;
}
static void
blaster = &ctlr->blaster;
ring = &ctlr->ring;
- if(buffered(ring) >= Blocksize){
- ring->ri = ring->nbuf - dmacount(blaster->dma);
-
- ctlr->totcount += Blocksize;
- ctlr->tottime = todget(nil);
- }else{
- dmaend(blaster->dma);
+ if(buffered(ring) >= Blocksize)
+ ring->ri = ring->nbuf - dmacount(ctlr->conf.dma);
+ else{
+ dmaend(ctlr->conf.dma);
sbcmd(blaster, 0xd9); /* exit at end of count */
sbcmd(blaster, 0xd5); /* pause */
ctlr->active = 0;
blaster = &ctlr->blaster;
ring = &ctlr->ring;
ilock(blaster);
- dmaend(blaster->dma);
- if(0) {
- sbcmd(blaster, 0x42); /* input sampling rate */
- speed = ctlr->livol[Vspeed];
- } else {
- sbcmd(blaster, 0x41); /* output sampling rate */
- speed = ctlr->lovol[Vspeed];
- }
+ dmaend(ctlr->conf.dma);
+ if(0)
+ sbcmd(blaster, 0x42); /* input sampling rate */
+ else
+ sbcmd(blaster, 0x41); /* output sampling rate */
+ speed = ctlr->adev->speed;
sbcmd(blaster, speed>>8);
sbcmd(blaster, speed);
if(0)
- sbcmd(blaster, 0xbe); /* A/D, autoinit */
+ sbcmd(blaster, 0xbe); /* A/D, autoinit */
else
- sbcmd(blaster, 0xb6); /* D/A, autoinit */
+ sbcmd(blaster, 0xb6); /* D/A, autoinit */
- sbcmd(blaster, 0x30); /* stereo, signed 16 bit */
+ sbcmd(blaster, 0x30); /* stereo, signed 16 bit */
count = (Blocksize>>1) - 1;
sbcmd(blaster, count);
sbcmd(blaster, count>>8);
ctlr->active = 1;
- if(dmasetup(blaster->dma, ring->buf, ring->nbuf, DMAWRITE|DMALOOP) < 0){
+ if(dmasetup(ctlr->conf.dma, ring->buf, ring->nbuf, DMAWRITE|DMALOOP) < 0){
ctlr->active = 0;
print("#A%d: dmasetup fail\n", ctlr->adev->ctlrno);
}
int i;
outb(blaster->reset, 3);
- delay(1); /* >3 υs */
+ delay(1); /* >3 υs */
outb(blaster->reset, 0);
delay(1);
return 1;
}
- if(sbcmd(blaster, 0xC6)){ /* extended mode */
+ if(sbcmd(blaster, 0xC6)){ /* extended mode */
print("#A%d: barf 3\n", ctlrno);
return 1;
}
ring = &ctlr->ring;
ilock(blaster);
- dmaend(blaster->dma);
+ dmaend(ctlr->conf.dma);
ess1688reset(blaster, ctlr->adev->ctlrno);
/*
* Set the speed.
*/
- if(0)
- speed = ctlr->livol[Vspeed];
- else
- speed = ctlr->lovol[Vspeed];
+ speed = ctlr->adev->speed;
if(speed < 4000)
speed = 4000;
else if(speed > 48000)
speed = 48000;
-
if(speed > 22000)
x = 0x80|(256-(795500+speed/2)/speed);
else
ess1688w(blaster, 0xA2, x & 0xFF);
if(0)
- ess1688w(blaster, 0xB8, 0x0E); /* A/D, autoinit */
+ ess1688w(blaster, 0xB8, 0x0E); /* A/D, autoinit */
else
- ess1688w(blaster, 0xB8, 0x04); /* D/A, autoinit */
+ ess1688w(blaster, 0xB8, 0x04); /* D/A, autoinit */
x = ess1688r(blaster, 0xA8) & ~0x03;
- ess1688w(blaster, 0xA8, x|0x01); /* 2 channels */
- ess1688w(blaster, 0xB9, 2); /* demand mode, 4 bytes per request */
+ ess1688w(blaster, 0xA8, x|0x01); /* 2 channels */
+ ess1688w(blaster, 0xB9, 2); /* demand mode, 4 bytes per request */
if(1)
- ess1688w(blaster, 0xB6, 0); /* for output */
+ ess1688w(blaster, 0xB6, 0); /* for output */
ess1688w(blaster, 0xB7, 0x71);
ess1688w(blaster, 0xB7, 0xBC);
ess1688w(blaster, 0xB2, x|0x50);
if(1)
- sbcmd(blaster, 0xD1); /* speaker on */
+ sbcmd(blaster, 0xD1); /* speaker on */
count = -Blocksize;
ess1688w(blaster, 0xA4, count & 0xFF);
ess1688w(blaster, 0xB8, x|0x05);
ctlr->active = 1;
- if(dmasetup(blaster->dma, ring->buf, ring->nbuf, DMAWRITE|DMALOOP) < 0){
+ if(dmasetup(ctlr->conf.dma, ring->buf, ring->nbuf, DMAWRITE|DMALOOP) < 0){
ctlr->active = 0;
print("#A%d: dmasetup fail\n", ctlr->adev->ctlrno);
}
ilock(&ctlr->blaster);
ctlr->ring.ri = 0;
ctlr->ring.wi = 0;
- ctlr->totcount = 0;
- ctlr->tottime = 0LL;
iunlock(&ctlr->blaster);
}
-static void
-resetlevel(Ctlr *ctlr)
-{
- int i;
-
- for(i=0; volumes[i].name; i++) {
- ctlr->lovol[i] = volumes[i].ilval;
- ctlr->rovol[i] = volumes[i].irval;
- ctlr->livol[i] = volumes[i].ilval;
- ctlr->rivol[i] = volumes[i].irval;
- }
-}
-
static long
audiobuffered(Audio *adev)
{
}
static long
-audiostatus(Audio *adev, void *a, long n, vlong off)
+audiostatus(Audio *adev, void *a, long n, vlong)
{
- char buf[300];
- Ctlr *ctlr;
-
- ctlr = adev->ctlr;
- snprint(buf, sizeof(buf),
- "buffered %.4lx/%.4lx offset %10lud time %19lld\n",
- buffered(&ctlr->ring), available(&ctlr->ring),
- ctlr->totcount, ctlr->tottime);
- return readstr(off, a, n, buf);
+ Ctlr *ctlr = adev->ctlr;
+ return snprint((char*)a, n, "bufsize %6d buffered %6ld\n",
+ Blocksize, buffered(&ctlr->ring));
}
static int
inactive(void *arg)
{
Ctlr *ctlr = arg;
-
return !ctlr->active;
}
anybuf(void *arg)
{
Ctlr *ctlr = arg;
-
return available(&ctlr->ring) || inactive(ctlr);
}
+static int
+ratebuf(void *arg)
+{
+ Ctlr *ctlr = arg;
+ int delay = ctlr->adev->delay*4;
+ return (delay <= 0) || (buffered(&ctlr->ring) <= delay) || inactive(ctlr);
+}
+
static long
audiowrite(Audio *adev, void *vp, long n, vlong)
{
uchar *p, *e;
Ctlr *ctlr;
Ring *ring;
- long m;
p = vp;
e = p + n;
ctlr = adev->ctlr;
- qlock(ctlr);
- if(waserror()){
- qunlock(ctlr);
- nexterror();
- }
ring = &ctlr->ring;
while(p < e) {
- if((m = writering(ring, p, e - p)) <= 0){
+ if((n = writering(ring, p, e - p)) <= 0){
if(!ctlr->active && ring->ri == 0)
ctlr->blaster.startdma(ctlr);
- if(!ctlr->active){
+ if(!ctlr->active)
setempty(ctlr);
- continue;
- }
- sleep(&ctlr->vous, anybuf, ctlr);
- continue;
+ else
+ sleep(&ctlr->vous, anybuf, ctlr);
}
- p += m;
+ p += n;
}
- poperror();
- qunlock(ctlr);
-
+ while(ratebuf(ctlr) == 0)
+ sleep(&ctlr->vous, ratebuf, ctlr);
return p - (uchar*)vp;
}
static void
-audioclose(Audio *adev)
+audioclose(Audio *adev, int mode)
{
Ctlr *ctlr;
+ if(mode == OREAD)
+ return;
ctlr = adev->ctlr;
- qlock(ctlr);
- if(waserror()){
- qunlock(ctlr);
- nexterror();
- }
sleep(&ctlr->vous, inactive, ctlr);
setempty(ctlr);
- poperror();
- qunlock(ctlr);
+}
+
+static long
+audiovolread(Audio *adev, void *a, long n, vlong)
+{
+ return genaudiovolread(adev, a, n, 0, voltab, mxgetvol, 0);
+}
+
+static long
+audiovolwrite(Audio *adev, void *a, long n, vlong)
+{
+ Blaster *blaster;
+ Ctlr *ctlr;
+ int source;
+
+ ctlr = adev->ctlr;
+ blaster = &ctlr->blaster;
+
+ n = genaudiovolwrite(adev, a, n, 0, voltab, mxsetvol, 0);
+
+ source = 0;
+ if(ctlr->lvol[Vsynth])
+ source |= 1<<6;
+ if(ctlr->rvol[Vsynth])
+ source |= 1<<5;
+ if(ctlr->lvol[Vaudio])
+ source |= 1<<4;
+ if(ctlr->rvol[Vaudio])
+ source |= 1<<3;
+ if(ctlr->lvol[Vcd])
+ source |= 1<<2;
+ if(ctlr->rvol[Vcd])
+ source |= 1<<1;
+ if(ctlr->lvol[Vmic])
+ source |= 1<<0;
+
+ ilock(blaster);
+ mxcmd(blaster, 0x3c, source); /* output switch */
+ mxcmd(blaster, 0x3d, source); /* input left switch */
+ mxcmd(blaster, 0x3e, source); /* input right switch */
+ iunlock(blaster);
+
+ return n;
}
static int
major = sbread(blaster);
minor = sbread(blaster);
if(major != 0x68 || minor != 0x8B){
- print("#A%d: model %#.2x %#.2x; not ESS1688 compatible\n", ctlrno, major, minor);
+ print("#A%d: model %#.2x %#.2x; not ESS1688 compatible\n",
+ ctlrno, major, minor);
return -1;
}
audioprobe(Audio *adev)
{
static int irq[] = {9,5,7,10};
+ static Ctlr *cards = nil;
Ctlr *ctlr;
Blaster *blaster;
- ISAConf sbconf;
int i, x;
- sbconf.port = 0x220;
- sbconf.irq = 5;
- sbconf.dma = 0;
- if(isaconfig("audio", adev->ctlrno, &sbconf) == 0)
- return -1;
+ /* make a list of audio isa cards if not already done */
+ if(cards == nil){
+ for(i=0; i<nelem(irq); i++){
+ ctlr = mallocz(sizeof(Ctlr), 1);
+ if(ctlr == nil){
+ print("sb16: can't allocate memory\n");
+ break;
+ }
+ ctlr->conf.port = 0x220 + i*0x10;
+ ctlr->conf.irq = irq[i];
+ ctlr->conf.dma = 0;
+ if(isaconfig("audio", i, &ctlr->conf) == 0){
+ free(ctlr);
+ break;
+ }
+ ctlr->next = cards;
+ cards = ctlr;
+ }
+ }
+
+ /* pick a card */
+ for(ctlr = cards; ctlr; ctlr = ctlr->next){
+ if(ctlr->conf.type && strcmp(adev->name, ctlr->conf.type) == 0){
+ ctlr->conf.type = nil;
+ goto Found;
+ }
+ }
+ return -1;
- switch(sbconf.port){
+Found:
+ switch(ctlr->conf.port){
case 0x220:
case 0x240:
case 0x260:
case 0x280:
break;
default:
- print("#A%d: bad port %#lux\n", adev->ctlrno, sbconf.port);
+ print("#A%d: bad port %#lux\n", adev->ctlrno, ctlr->conf.port);
return -1;
}
- if(ioalloc(sbconf.port, 0x10, 0, "audio") < 0){
- print("#A%d: cannot ioalloc range %lux+0x10\n", adev->ctlrno, sbconf.port);
+ if(ioalloc(ctlr->conf.port, 0x10, 0, "audio") < 0){
+ print("#A%d: cannot ioalloc range %lux+0x10\n",
+ adev->ctlrno, ctlr->conf.port);
return -1;
}
- if(ioalloc(sbconf.port+0x100, 1, 0, "audio.mpu401") < 0){
- iofree(sbconf.port);
- print("#A%d: cannot ioalloc range %lux+0x01\n", adev->ctlrno, sbconf.port+0x100);
+ if(ioalloc(ctlr->conf.port+0x100, 1, 0, "audio.mpu401") < 0){
+ iofree(ctlr->conf.port);
+ print("#A%d: cannot ioalloc range %lux+0x01\n",
+ adev->ctlrno, ctlr->conf.port+0x100);
return -1;
}
- ctlr = malloc(sizeof(Ctlr));
ctlr->adev = adev;
adev->ctlr = ctlr;
blaster = &ctlr->blaster;
- blaster->reset = sbconf.port + 0x6;
- blaster->read = sbconf.port + 0xa;
- blaster->write = sbconf.port + 0xc;
- blaster->wstatus = sbconf.port + 0xc;
- blaster->rstatus = sbconf.port + 0xe;
- blaster->mixaddr = sbconf.port + 0x4;
- blaster->mixdata = sbconf.port + 0x5;
- blaster->clri8 = sbconf.port + 0xe;
- blaster->clri16 = sbconf.port + 0xf;
- blaster->clri401 = sbconf.port + 0x100;
- blaster->dma = sbconf.dma;
+ blaster->reset = ctlr->conf.port + 0x6;
+ blaster->read = ctlr->conf.port + 0xa;
+ blaster->write = ctlr->conf.port + 0xc;
+ blaster->wstatus = ctlr->conf.port + 0xc;
+ blaster->rstatus = ctlr->conf.port + 0xe;
+ blaster->mixaddr = ctlr->conf.port + 0x4;
+ blaster->mixdata = ctlr->conf.port + 0x5;
+ blaster->clri8 = ctlr->conf.port + 0xe;
+ blaster->clri16 = ctlr->conf.port + 0xf;
+ blaster->clri401 = ctlr->conf.port + 0x100;
blaster->startdma = sb16startdma;
blaster->intr = sb16intr;
- resetlevel(ctlr);
-
outb(blaster->reset, 1);
delay(1); /* >3 υs */
outb(blaster->reset, 0);
i = sbread(blaster);
if(i != 0xaa) {
print("#A%d: no response #%.2x\n", adev->ctlrno, i);
- iofree(sbconf.port);
- iofree(sbconf.port+0x100);
- free(ctlr);
+Errout:
+ iofree(ctlr->conf.port);
+ iofree(ctlr->conf.port+0x100);
return -1;
}
ctlr->minor = sbread(blaster);
if(ctlr->major != 4) {
- if(ctlr->major != 3 || ctlr->minor != 1 || ess1688(&sbconf, blaster, adev->ctlrno)){
+ if(ctlr->major != 3 || ctlr->minor != 1 ||
+ ess1688(&ctlr->conf, blaster, adev->ctlrno)){
print("#A%d: model %#.2x %#.2x; not SB 16 compatible\n",
adev->ctlrno, ctlr->major, ctlr->minor);
- iofree(sbconf.port);
- iofree(sbconf.port+0x100);
- return -1;
+ goto Errout;
}
ctlr->major = 4;
}
* initialize the mixer
*/
mxcmd(blaster, 0x00, 0); /* Reset mixer */
- mxvolume(ctlr);
+
+ for(i=0; i<Nvol; i++){
+ int a[2];
+
+ a[0] = 0;
+ a[1] = 0;
+ mxsetvol(adev, i, a);
+ }
/* set irq */
for(i=0; i<nelem(irq); i++){
- if(sbconf.irq == irq[i]){
+ if(ctlr->conf.irq == irq[i]){
mxcmd(blaster, 0x80, 1<<i);
break;
}
x = mxread(blaster, 0x80);
for(i=0; i<nelem(irq); i++){
if(x & (1<<i)){
- sbconf.irq = irq[i];
+ ctlr->conf.irq = irq[i];
break;
}
}
for(;;){
/* set 16bit dma */
- if(blaster->dma>=5 && blaster->dma<=7){
+ if(ctlr->conf.dma>=5 && ctlr->conf.dma<=7){
x = mxread(blaster, 0x81);
- mxcmd(blaster, 0x81, (1<<blaster->dma) & 0xF0 | (x & 0x0F));
+ mxcmd(blaster, 0x81, (1<<ctlr->conf.dma) & 0xF0 | (x & 0x0F));
}
x = mxread(blaster, 0x81);
for(i=5; i<=7; i++){
if(x & (1<<i)){
- blaster->dma = i;
+ ctlr->conf.dma = i;
break;
}
}
- if(blaster->dma<5){
- blaster->dma = 7;
- continue;
- }
- break;
+ if(ctlr->conf.dma>=5)
+ break;
+ ctlr->conf.dma = 7;
}
- print("#A%d: %s port 0x%04lux irq %d dma %d\n", adev->ctlrno, sbconf.type,
- sbconf.port, sbconf.irq, blaster->dma);
+ print("#A%d: %s port 0x%04lux irq %d dma %lud\n", adev->ctlrno, adev->name,
+ ctlr->conf.port, ctlr->conf.irq, ctlr->conf.dma);
ctlr->ring.nbuf = Blocks*Blocksize;
- if(dmainit(blaster->dma, ctlr->ring.nbuf)){
- free(ctlr);
- return -1;
- }
- ctlr->ring.buf = dmabva(blaster->dma);
-
- intrenable(sbconf.irq, audiointr, adev, BUSUNKNOWN, sbconf.type);
+ if(dmainit(ctlr->conf.dma, ctlr->ring.nbuf))
+ goto Errout;
+ ctlr->ring.buf = dmabva(ctlr->conf.dma);
+ print("#A%d: %s dma buffer %p-%p\n", adev->ctlrno, adev->name,
+ ctlr->ring.buf, ctlr->ring.buf+ctlr->ring.nbuf);
setempty(ctlr);
- mxvolume(ctlr);
adev->write = audiowrite;
adev->close = audioclose;
+ adev->volread = audiovolread;
+ adev->volwrite = audiovolwrite;
adev->status = audiostatus;
adev->buffered = audiobuffered;
+ intrenable(ctlr->conf.irq, audiointr, adev, BUSUNKNOWN, adev->name);
+
return 0;
}