M carrera/audio.h => carrera/audio.h +2 -0
@@ 5,6 5,8 @@ enum
Dma = 6,
Irq = 7,
+ SBswab = 1,
+
DMA2_WRMASK = 0xd4,
DMA2_WRMODE = 0xd6,
DMA2_CLRBP = 0xd8,
M carrera/dat.h => carrera/dat.h +7 -0
@@ 1,5 1,6 @@
typedef struct Conf Conf;
typedef struct FPsave FPsave;
+typedef struct ISAConf ISAConf;
typedef struct KMap KMap;
typedef struct Lance Lance;
typedef struct Lancemem Lancemem;
@@ 150,6 151,12 @@ struct
short exiting;
}active;
+struct ISAConf {
+ char type[NAMELEN];
+ ulong port;
+ ulong irq;
+};
+
extern KMap kpte[];
extern register Mach *m;
extern register Proc *up;
A carrera/dma.c => carrera/dma.c +125 -0
@@ 0,0 1,125 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * headland chip set for the safari.
+ */
+typedef struct DMAport DMAport;
+typedef struct DMA DMA;
+
+enum
+{
+ /*
+ * the byte registers for DMA0 are all one byte apart
+ */
+ Dma0= 0x00,
+ Dma0status= Dma0+0x8, /* status port */
+ Dma0reset= Dma0+0xD, /* reset port */
+
+ /*
+ * the byte registers for DMA1 are all two bytes apart (why?)
+ */
+ Dma1= 0xC0,
+ Dma1status= Dma1+2*0x8, /* status port */
+ Dma1reset= Dma1+2*0xD, /* reset port */
+};
+
+/*
+ * the dma controllers. the first half of this structure specifies
+ * the I/O ports used by the DMA controllers.
+ */
+struct DMAport
+{
+ uchar addr[4]; /* current address (4 channels) */
+ uchar count[4]; /* current count (4 channels) */
+ uchar page[4]; /* page registers (4 channels) */
+ uchar cmd; /* command status register */
+ uchar req; /* request registers */
+ uchar sbm; /* single bit mask register */
+ uchar mode; /* mode register */
+ uchar cbp; /* clear byte pointer */
+ uchar mc; /* master clear */
+ uchar cmask; /* clear mask register */
+ uchar wam; /* write all mask register bit */
+};
+
+struct DMA
+{
+ DMAport;
+ int shift;
+ Lock;
+};
+
+DMA dma[2] = {
+ { 0x00, 0x02, 0x04, 0x06,
+ 0x01, 0x03, 0x05, 0x07,
+ 0x87, 0x83, 0x81, 0x82,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0 },
+
+ { 0xc0, 0xc4, 0xc8, 0xcc,
+ 0xc2, 0xc6, 0xca, 0xce,
+ 0x8f, 0x8b, 0x89, 0x8a,
+ 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+ 1 },
+};
+
+/*
+ * setup a dma transfer.
+ * needs to change if the address is over 16meg
+ *
+ * we assume BIOS has set up the command register before we
+ * are booted.
+ */
+long
+dmasetup(int chan, void *va, long len, int isread)
+{
+ DMA *dp;
+ ulong pa;
+ uchar mode;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+
+ pa = PADDR(va);
+
+ /*
+ * this setup must be atomic
+ */
+ ilock(dp);
+ mode = (isread ? 0x44 : 0x48) | chan;
+ EISAOUTB(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */
+ EISAOUTB(dp->page[chan], pa>>16);
+ EISAOUTB(dp->cbp, 0); /* set count & address to their first byte */
+ EISAOUTB(dp->addr[chan], pa>>dp->shift); /* set address */
+ EISAOUTB(dp->addr[chan], pa>>(8+dp->shift));
+ EISAOUTB(dp->count[chan], (len>>dp->shift)-1); /* set count */
+ EISAOUTB(dp->count[chan], ((len>>dp->shift)-1)>>8);
+ EISAOUTB(dp->sbm, chan); /* enable the channel */
+ iunlock(dp);
+
+ return len;
+}
+
+/*
+ * this must be called after a dma has been completed.
+ */
+void
+dmaend(int chan)
+{
+ DMA *dp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+
+ /*
+ * disable the channel
+ */
+ ilock(dp);
+ EISAOUTB(dp->sbm, 4|chan);
+ iunlock(dp);
+}
M carrera/fns.h => carrera/fns.h +3 -0
@@ 19,6 19,8 @@ void consoff(void);
int consputc(int);
void dcflush(void*, ulong);
void dcinvalidate(void*, ulong);
+void dmaend(int);
+long dmasetup(int, void*, long, int);
void epcenable(ulong);
void epcinit(int, int);
void evenaddr(ulong);
@@ 42,6 44,7 @@ void icflush(void *, ulong);
void intr(Ureg*);
void ioinit(int);
int iprint(char*, ...);
+int isaconfig(char*, int, ISAConf*);
int kbdinit(void);
void kbdintr(void);
void kfault(Ureg*);
M carrera/main.c => carrera/main.c +15 -0
@@ 480,6 480,21 @@ buzz(int f, int d)
}
/*
+ * dummy routine for interoperability with pc's
+ */
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ if(strcmp(class, "audio") == 0 && ctlrno == 0){
+ strcpy(isa->type, "sb16");
+ isa->port = 0x220;
+ isa->irq = 7;
+ return 1;
+ }
+ return 0;
+}
+
+/*
register offsets of ARCS prom jmpbuf
JB_PC 0
JB_SP 1
M pc/audio.h => pc/audio.h +1 -25
@@ 3,31 3,7 @@ enum
Bufsize = 16*1024, /* 92 ms each */
Nbuf = 16, /* 1.5 seconds total */
Dma = 6,
- Irq = 7,
-
- DMA2_WRMASK = 0xd4,
- DMA2_WRMODE = 0xd6,
- DMA2_CLRBP = 0xd8,
-
- DMA6_ADDRESS = 0xc8,
- DMA6_COUNT = 0xca,
- DMA6_LPAGE = 0x89,
- DMA6_HPAGE = 0x489,
-
- Dspport = 0x220,
-
- PORT_RESET = Dspport + 0x6,
- PORT_READ = Dspport + 0xA,
- PORT_WRITE = Dspport + 0xC,
- PORT_WSTATUS = Dspport + 0xC,
- PORT_RSTATUS = Dspport + 0xE,
-
- PORT_MIXER_ADDR = Dspport + 0x4,
- PORT_MIXER_DATA = Dspport + 0x5,
-
- PORT_CLRI8 = Dspport + 0xE,
- PORT_CLRI16 = Dspport + 0xF,
- PORT_CLRI401 = Dspport + 0x100,
+ SBswab = 0,
};
#define seteisadma(a, b) ;
M pc/devata.c => pc/devata.c +13 -13
@@ 118,7 118,7 @@ struct Controller
{
QLock; /* exclusive access to the controller */
- Lock; /* exclusive access to the registers */
+ Lock reglock; /* exclusive access to the registers */
int confused; /* needs to be recalibrated (or worse) */
int pbase; /* base port */
@@ 566,7 566,7 @@ ataxfer(Drive *dp, Partition *pp, int cmd, long start, long len, char *buf)
dp->usetime = m->ticks;
cmdreadywait(dp);
- ilock(cp);
+ ilock(&cp->reglock);
cp->sofar = 0;
cp->buf = buf;
cp->nsecs = len;
@@ 589,7 589,7 @@ ataxfer(Drive *dp, Partition *pp, int cmd, long start, long len, char *buf)
outss(cp->pbase+Pdata, cp->buf, dp->bytes/2);
} else
stat = 0;
- iunlock(cp);
+ iunlock(&cp->reglock);
if(stat & Serr)
error(Eio);
@@ 646,12 646,12 @@ atasetbuf(Drive *dp, int on)
cmdreadywait(dp);
- ilock(cp);
+ ilock(&cp->reglock);
cp->cmd = Csetbuf;
outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55); /* read look ahead */
outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4));
outb(cp->pbase+Pcmd, Csetbuf);
- iunlock(cp);
+ iunlock(&cp->reglock);
sleep(&cp->r, cmddone, cp);
@@ 727,7 727,7 @@ ataident(Drive *dp)
cmdreadywait(dp);
- ilock(cp);
+ ilock(&cp->reglock);
cp->nsecs = 1;
cp->sofar = 0;
cp->cmd = Cident;
@@ 735,7 735,7 @@ ataident(Drive *dp)
cp->buf = buf;
outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4));
outb(cp->pbase+Pcmd, Cident);
- iunlock(cp);
+ iunlock(&cp->reglock);
sleep(&cp->r, cmddone, cp);
if(cp->status & Serr){
@@ 812,7 812,7 @@ ataprobe(Drive *dp, int cyl, int sec, int head)
cmdreadywait(dp);
- ilock(cp);
+ ilock(&cp->reglock);
cp->cmd = Cread;
cp->dp = dp;
cp->status = 0;
@@ 825,7 825,7 @@ ataprobe(Drive *dp, int cyl, int sec, int head)
outb(cp->pbase+Pcyllsb, cyl);
outb(cp->pbase+Pcylmsb, cyl>>8);
outb(cp->pbase+Pcmd, Cread);
- iunlock(cp);
+ iunlock(&cp->reglock);
sleep(&cp->r, cmddone, cp);
@@ 1058,7 1058,7 @@ ataintr(Ureg *ur, void *arg)
cp = &atac[0];
dp = cp->dp;
- ilock(cp);
+ ilock(&cp->reglock);
loop = 0;
while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy){
@@ 1152,7 1152,7 @@ ataintr(Ureg *ur, void *arg)
break;
}
- iunlock(cp);
+ iunlock(&cp->reglock);
}
void
@@ 1172,12 1172,12 @@ hardclock(void)
diff = TK2SEC(m->ticks - dp->usetime);
if((dp->state == Sspinning) && (diff >= spindowntime)){
- ilock(cp);
+ ilock(&cp->reglock);
cp->cmd = Cstandby;
outb(cp->pbase+Pcount, 0);
outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4) | 0);
outb(cp->pbase+Pcmd, cp->cmd);
- iunlock(cp);
+ iunlock(&cp->reglock);
dp->state = Sstandby;
}
}
M pc/dma.c => pc/dma.c +20 -16
@@ 56,13 56,12 @@ struct DMAport
uchar mc; /* master clear */
uchar cmask; /* clear mask register */
uchar wam; /* write all mask register bit */
-
- Lock;
};
struct DMA
{
DMAport;
+ int shift;
Lock;
DMAxfer x[4];
};
@@ 71,11 70,14 @@ DMA dma[2] = {
{ 0x00, 0x02, 0x04, 0x06,
0x01, 0x03, 0x05, 0x07,
0x87, 0x83, 0x81, 0x82,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
- { 0xc0, 0xc6, 0xca, 0xce,
- 0xc4, 0xc8, 0xcc, 0xcf,
- 0x80, 0x8b, 0x89, 0x8a,
- 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde },
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0 },
+
+ { 0xc0, 0xc4, 0xc8, 0xcc,
+ 0xc2, 0xc6, 0xca, 0xce,
+ 0x8f, 0x8b, 0x89, 0x8a,
+ 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+ 1 },
};
/*
@@ 95,6 97,8 @@ dmainit(void)
xp = &dp->x[chan];
xp->pg.pa = (ulong)xspanalloc(BY2PG, BY2PG, 0);
xp->pg.va = KZERO|xp->pg.pa;
+ xp->len = 0;
+ xp->isread = 0;
}
}
}
@@ 143,17 147,17 @@ dmasetup(int chan, void *va, long len, int isread)
/*
* this setup must be atomic
*/
- lock(dp);
- outb(dp->cbp, 0); /* set count & address to their first byte */
+ ilock(dp);
mode = (isread ? 0x44 : 0x48) | chan;
outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */
- outb(dp->addr[chan], pa); /* set address */
- outb(dp->addr[chan], pa>>8);
outb(dp->page[chan], pa>>16);
- outb(dp->count[chan], len-1); /* set count */
- outb(dp->count[chan], (len-1)>>8);
+ outb(dp->cbp, 0); /* set count & address to their first byte */
+ outb(dp->addr[chan], pa>>dp->shift); /* set address */
+ outb(dp->addr[chan], pa>>(8+dp->shift));
+ outb(dp->count[chan], (len>>dp->shift)-1); /* set count */
+ outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
outb(dp->sbm, chan); /* enable the channel */
- unlock(dp);
+ iunlock(dp);
return len;
}
@@ 177,9 181,9 @@ dmaend(int chan)
/*
* disable the channel
*/
- lock(dp);
+ ilock(dp);
outb(dp->sbm, 4|chan);
- unlock(dp);
+ iunlock(dp);
xp = &dp->x[chan];
if(xp->len == 0 || !xp->isread)
M port/devaudio.c => port/devaudio.c +135 -58
@@ 11,8 11,6 @@
#include "io.h"
#include "audio.h"
-
-#define nelem(x) (sizeof (x)/sizeof(x[0]))
#define NPORT (sizeof audiodir/sizeof(Dirtab))
typedef struct Buf Buf;
@@ 26,7 24,8 @@ enum
Fmono = 1,
- Aread = 0,
+ Aclosed = 0,
+ Aread,
Awrite,
Speed = 44100,
@@ 67,12 66,13 @@ struct Queue
};
static struct
{
+ QLock;
Rendez vous;
int bufinit; /* boolean if buffers allocated */
int curcount; /* how much data in current buffer */
int active; /* boolean dma running */
int intr; /* boolean an interrupt has happened */
- int amode; /* Aread/Awrite for /audio */
+ int amode; /* Aclosed/Aread/Awrite for /audio */
Level left; /* all of left volumes */
Level right; /* all of right volumes */
int mic; /* mono level */
@@ 121,9 121,24 @@ static struct
0
};
+static struct
+{
+ Lock;
+ int reset; /* io ports to the sound blaster */
+ int read;
+ int write;
+ int wstatus;
+ int rstatus;
+ int mixaddr;
+ int mixdata;
+ int clri8;
+ int clri16;
+ int clri401;
+} blaster;
+
static void swab(uchar*);
-static char Emajor[] = "SB16 version too old";
+static char Emajor[] = "SoundBlaster version too old";
static char Emode[] = "illegal open mode";
static char Evolume[] = "illegal volume specifier";
@@ 133,9 148,9 @@ sbcmd(int val)
int i, s;
for(i=1<<16; i!=0; i--) {
- s = inb(PORT_WSTATUS);
+ s = inb(blaster.wstatus);
if((s & 0x80) == 0) {
- outb(PORT_WRITE, val);
+ outb(blaster.write, val);
return 0;
}
}
@@ 149,9 164,9 @@ sbread(void)
int i, s;
for(i=1<<16; i!=0; i--) {
- s = inb(PORT_RSTATUS);
+ s = inb(blaster.rstatus);
if((s & 0x80) != 0) {
- return inb(PORT_READ);
+ return inb(blaster.read);
}
}
/* print("SB16 sbread did not respond\n"); /**/
@@ 162,8 177,8 @@ static int
mxcmd(int addr, int val)
{
- outb(PORT_MIXER_ADDR, addr);
- outb(PORT_MIXER_DATA, val);
+ outb(blaster.mixaddr, addr);
+ outb(blaster.mixdata, val);
return 1;
}
@@ 172,8 187,8 @@ mxread(int addr)
{
int s;
- outb(PORT_MIXER_ADDR, addr);
- s = inb(PORT_MIXER_DATA);
+ outb(blaster.mixaddr, addr);
+ s = inb(blaster.mixdata);
return s;
}
@@ 214,9 229,7 @@ mxcmdu(int s, int v)
static void
mxvolume(void)
{
- ulong sp;
-
- sp = splhi();
+ ilock(&blaster);
mxcmds(0x30, audio.left.master);
mxcmds(0x31, audio.right.master);
@@ 249,7 262,7 @@ mxvolume(void)
mxcmd(0x3c, audio.oswitch);
mxcmd(0x3d, audio.left.iswitch);
mxcmd(0x3e, audio.right.iswitch);
- splx(sp);
+ iunlock(&blaster);
}
static Buf*
@@ 287,7 300,6 @@ static void
contindma(void)
{
Buf *b;
- ulong count, addr;
if(!audio.active)
goto shutdown;
@@ 306,24 318,11 @@ contindma(void)
if(b == 0)
goto shutdown;
- addr = b->phys;
- count = ((Bufsize) >> 1) - 1;
-
-/* outb(DMA2_WRMASK, 4|(Dma&3)); /* disable dma */
- outb(DMA6_LPAGE, (addr>>16) & 0xfe);
- outb(DMA2_CLRBP, 0); /* clear ff */
- outb(DMA6_ADDRESS, addr>>1);
- outb(DMA6_ADDRESS, addr>>9);
-
- outb(DMA2_CLRBP, 0); /* clear ff */
- outb(DMA6_COUNT, count);
- outb(DMA6_COUNT, count>>8);
- outb(DMA2_WRMASK, (Dma&3)); /* enable dma */
-
+ dmasetup(Dma, b->virt, Bufsize, audio.amode == Aread);
return;
shutdown:
- outb(DMA2_WRMASK, 4|(Dma&3)); /* disable dma */
+ dmaend(Dma);
sbcmd(0xd9); /* exit at end of count */
sbcmd(0xd5); /* pause */
audio.curcount = 0;
@@ 339,14 338,12 @@ startdma(void)
{
ulong count;
- outb(DMA2_WRMASK, 4|(Dma&3)); /* disable dma */
- if(audio.amode == Aread) {
- outb(DMA2_WRMODE, 0x44 | (Dma&3)); /* set mode */
+ ilock(&blaster);
+ dmaend(Dma);
+ if(audio.amode == Aread)
sbcmd(0x42); /* input sampling rate */
- } else {
- outb(DMA2_WRMODE, 0x48 | (Dma&3)); /* set mode */
+ else
sbcmd(0x41); /* output sampling rate */
- }
sbcmd(audio.speed>>8);
sbcmd(audio.speed);
@@ 361,6 358,7 @@ startdma(void)
audio.active = 1;
contindma();
+ iunlock(&blaster);
}
/*
@@ 370,12 368,8 @@ startdma(void)
static void
pokeaudio(void)
{
- ulong sp;
-
- sp = splhi();
if(!audio.active)
startdma();
- splx(sp);
}
void
@@ 387,22 381,32 @@ audiosbintr(void)
if(stat) {
dummy = 0;
if(stat & 2) {
- dummy = inb(PORT_CLRI16);
+ ilock(&blaster);
+ dummy = inb(blaster.clri16);
contindma();
+ iunlock(&blaster);
audio.intr = 1;
wakeup(&audio.vous);
}
if(stat & 1) {
- dummy = inb(PORT_CLRI8);
+ dummy = inb(blaster.clri8);
}
if(stat & 4) {
- dummy = inb(PORT_CLRI401);
+ dummy = inb(blaster.clri401);
}
USED(dummy);
}
}
void
+pcaudiosbintr(Ureg *ureg, void *rock)
+{
+ USED(ureg, rock);
+/* print("sb16 audio interrupt\n"); /**/
+ audiosbintr();
+}
+
+void
audiodmaintr(void)
{
/* print("sb16 dma interrupt\n"); /**/
@@ 427,7 431,7 @@ waitaudio(void)
pokeaudio();
tsleep(&audio.vous, anybuf, 0, 10*1000);
if(audio.intr == 0) {
-/* print("audio timeout\n"); /**/
+ print("audio timeout\n"); /**/
audio.active = 0;
pokeaudio();
}
@@ 452,6 456,7 @@ setempty(void)
{
int i;
+ ilock(&blaster);
audio.empty.first = 0;
audio.empty.last = 0;
audio.full.first = 0;
@@ 460,6 465,7 @@ setempty(void)
audio.filling = 0;
for(i=0; i<Nbuf; i++)
putbuf(&audio.empty, &audio.buf[i]);
+ iunlock(&blaster);
}
void
@@ 481,15 487,56 @@ resetlevel(void)
void
audioinit(void)
{
+ ISAConf sbconf;
int i;
+ sbconf.port = 0x220;
+ sbconf.irq = 7;
+ if(isaconfig("audio", 0, &sbconf) == 0)
+ return;
+ if(strcmp(sbconf.type, "sb16") != 0)
+ return;
+ switch(sbconf.port){
+ case 0x220:
+ case 0x240:
+ case 0x260:
+ case 0x280:
+ break;
+ default:
+ print("bad sb16 port 0x%x\n", sbconf.port);
+ return;
+ }
+ switch(sbconf.irq){
+ case 2:
+ case 5:
+ case 7:
+ case 10:
+ break;
+ default:
+ print("bad sb16 irq %d\n", sbconf.irq);
+ return;
+ }
+
+ 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;
+
seteisadma(Dma, audiodmaintr);
+ setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0);
+ audio.amode = Aclosed;
resetlevel();
- outb(PORT_RESET, 1);
+ outb(blaster.reset, 1);
delay(1); /* >3 υs */
- outb(PORT_RESET, 0);
+ outb(blaster.reset, 0);
delay(1);
i = sbread();
@@ 516,10 563,10 @@ audioinit(void)
* set up irq/dma chans
*/
mxcmd(0x80, /* irq */
- (Irq==2)? 1:
- (Irq==5)? 2:
- (Irq==7)? 4:
- (Irq==10)? 8:
+ (sbconf.irq==2)? 1:
+ (sbconf.irq==5)? 2:
+ (sbconf.irq==7)? 4:
+ (sbconf.irq==10)? 8:
0);
mxcmd(0x81, 1<<Dma); /* dma */
}
@@ 551,6 598,7 @@ audiostat(Chan *c, char *db)
Chan*
audioopen(Chan *c, int omode)
{
+ int amode;
if(audio.major != 4)
error(Emajor);
@@ 565,17 613,22 @@ audioopen(Chan *c, int omode)
break;
case Qaudio:
+ amode = Awrite;
+ if((omode&7) == OREAD)
+ amode = Aread;
+ qlock(&audio);
+ if(audio.amode != Aclosed){
+ qunlock(&audio);
+ error(Einuse);
+ }
if(audio.bufinit == 0) {
audio.bufinit = 1;
sbbufinit();
}
-
- audio.amode = Awrite;
- if((omode&7) == OREAD)
- audio.amode = Aread;
-
+ audio.amode = amode;
setempty();
audio.curcount = 0;
+ qunlock(&audio);
break;
}
c = devopen(c, omode, audiodir, NPORT, devgen);
@@ 612,9 665,17 @@ audioclose(Chan *c)
case Qaudio:
if(c->flag & COPEN) {
+ qlock(&audio);
+ audio.amode = Aclosed;
+ if(waserror()){
+ qunlock(&audio);
+ nexterror();
+ }
while(audio.active)
waitaudio();
setempty();
+ poperror();
+ qunlock(&audio);
}
break;
}
@@ 640,6 701,11 @@ audioread(Chan *c, char *a, long n, ulong offset)
case Qaudio:
if(audio.amode != Aread)
error(Emode);
+ qlock(&audio);
+ if(waserror()){
+ qunlock(&audio);
+ nexterror();
+ }
while(n > 0) {
b = audio.filling;
if(b == 0) {
@@ 665,6 731,8 @@ audioread(Chan *c, char *a, long n, ulong offset)
putbuf(&audio.empty, b);
}
}
+ poperror();
+ qunlock(&audio);
break;
case Qvolume:
@@ 770,6 838,11 @@ audiowrite(Chan *c, char *a, long n, ulong offset)
case Qaudio:
if(audio.amode != Awrite)
error(Emode);
+ qlock(&audio);
+ if(waserror()){
+ qunlock(&audio);
+ nexterror();
+ }
while(n > 0) {
b = audio.filling;
if(b == 0) {
@@ 796,6 869,8 @@ audiowrite(Chan *c, char *a, long n, ulong offset)
putbuf(&audio.full, b);
}
}
+ poperror();
+ qunlock(&audio);
break;
}
return n0 - n;
@@ 829,6 904,8 @@ swab(uchar *a)
{
ulong *p, *ep, b;
+ if(!SBswab)
+ return;
p = (ulong*)a;
ep = p + (Bufsize>>2);
while(p < ep) {