## diffname port/devaudio.c 1995/0119 ## diff -e /dev/null /n/fornaxdump/1995/0119/sys/src/brazil/port/devaudio.c 0a /* * SB 16 driver */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "devtab.h" #include "io.h" #include "audio.h" #define nelem(x) (sizeof (x)/sizeof(x[0])) #define NPORT (sizeof audiodir/sizeof(Dirtab)) typedef struct Buf Buf; typedef struct Level Level; enum { Qdir = 0, Qaudio, Qvolume, Fmono = 1, Aread = 0, Awrite, Speed = 44100, Ncmd = 50, /* max volume command words */ }; Dirtab audiodir[] = { "audio", {Qaudio}, 0, 0666, "volume", {Qvolume}, 0, 0666, }; struct Level { int master; /* mixer output volume control */ int ogain; /* extra gain after master */ int pcm; /* mixer volume on D/A (voice) */ int synth; /* mixer volume on synthesizer (MIDI) */ int cd; /* mixer volume on cd */ int line; /* mixer volume on line */ int igain; /* mixer volume to A/D */ int treb; /* treb control */ int bass; /* bass control */ int iswitch; /* input on/off switches */ }; struct Buf { uchar* virt; ulong phys; Buf* next; }; struct Queue { Lock; Buf* first; Buf* last; }; static struct { 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 */ Level left; /* all of left volumes */ Level right; /* all of right volumes */ int mic; /* mono level */ int speaker; /* mono level */ int oswitch; /* output on/off switches */ int speed; /* pcm sample rate, doesnt change w stereo */ int major; /* SB16 major version number (sb 4) */ int minor; /* SB16 minor version number */ char place[20]; /* static place to decode words */ Buf buf[Nbuf]; /* buffers and queues */ Queue empty; Queue full; Buf* current; Buf* filling; } audio; static struct { char* name; int* ptr1; int* ptr2; int flag; int ilval; int irval; } volumes[] = { "master", &audio.left.master, &audio.right.master, 0, 50, 50, "ogain", &audio.left.ogain, &audio.right.ogain, 0, 0, 0, "igain", &audio.left.igain, &audio.right.igain, 0, 0, 0, "treb", &audio.left.treb, &audio.right.treb, 0, 50, 50, "bass", &audio.left.bass, &audio.right.bass, 0, 50, 50, "pcm", &audio.left.pcm, &audio.right.pcm, 0, 90, 90, "synth", &audio.left.synth, &audio.right.synth, 0, 90, 90, "cd", &audio.left.cd, &audio.right.cd, 0, 81, 81, "line", &audio.left.line, &audio.right.line, 0, 65, 65, "mic", &audio.mic, &audio.mic, Fmono, 0, 0, "speaker", &audio.speaker, &audio.speaker, Fmono, 0, 0, "oswitch", &audio.oswitch, &audio.oswitch, Fmono, 31, 31, "iswitch", &audio.left.iswitch, &audio.right.iswitch, 0, 85, 43, "speed", &audio.speed, &audio.speed, Fmono, Speed, Speed, 0 }; static void swab(uchar*); static char Emajor[] = "SB16 version too old"; static char Emode[] = "illegal open mode"; static char Evolume[] = "illegal volume specifier"; static int sbcmd(int val) { int i, s; for(i=1<<16; i!=0; i--) { s = inb(PORT_WSTATUS); if((s & 0x80) == 0) { outb(PORT_WRITE, val); return 0; } } /* print("SB16 sbcmd (#%.2x) timeout\n", val); /**/ return 1; } static int sbread(void) { int i, s; for(i=1<<16; i!=0; i--) { s = inb(PORT_RSTATUS); if((s & 0x80) != 0) { return inb(PORT_READ); } } /* print("SB16 sbread did not respond\n"); /**/ return 0xbb; } static int mxcmd(int addr, int val) { outb(PORT_MIXER_ADDR, addr); outb(PORT_MIXER_DATA, val); return 1; } static int mxread(int addr) { int s; outb(PORT_MIXER_ADDR, addr); s = inb(PORT_MIXER_DATA); return s; } static void mxcmds(int s, int v) { if(v > 100) v = 100; if(v < 0) v = 0; mxcmd(s, (v*255)/100); } static void mxcmdt(int s, int v) { if(v > 100) v = 100; if(v <= 0) mxcmd(s, 0); else mxcmd(s, 255-100+v); } static void mxcmdu(int s, int v) { if(v > 100) v = 100; if(v <= 0) v = 0; mxcmd(s, 128-50+v); } static void mxvolume(void) { ulong sp; sp = splhi(); mxcmds(0x30, audio.left.master); mxcmds(0x31, audio.right.master); mxcmdt(0x32, audio.left.pcm); mxcmdt(0x33, audio.right.pcm); mxcmdt(0x34, audio.left.synth); mxcmdt(0x35, audio.right.synth); mxcmdt(0x36, audio.left.cd); mxcmdt(0x37, audio.right.cd); mxcmdt(0x38, audio.left.line); mxcmdt(0x39, audio.right.line); mxcmdt(0x3a, audio.mic); mxcmdt(0x3b, audio.speaker); mxcmds(0x3f, audio.left.igain); mxcmds(0x40, audio.right.igain); mxcmds(0x41, audio.left.ogain); mxcmds(0x42, audio.right.ogain); mxcmdu(0x44, audio.left.treb); mxcmdu(0x45, audio.right.treb); mxcmdu(0x46, audio.left.bass); mxcmdu(0x47, audio.right.bass); mxcmd(0x3c, audio.oswitch); mxcmd(0x3d, audio.left.iswitch); mxcmd(0x3e, audio.right.iswitch); splx(sp); } static Buf* getbuf(Queue *q) { Buf *b; ilock(q); b = q->first; if(b) q->first = b->next; iunlock(q); return b; } static void putbuf(Queue *q, Buf *b) { ilock(q); b->next = 0; if(q->first) q->last->next = b; else q->first = b; q->last = b; iunlock(q); } /* * move the dma to the next buffer */ static void contindma(void) { Buf *b; ulong count, addr; if(!audio.active) goto shutdown; b = audio.current; if(audio.amode == Aread) { if(b) /* shouldnt happen */ putbuf(&audio.full, b); b = getbuf(&audio.empty); } else { if(b) /* shouldnt happen */ putbuf(&audio.empty, b); b = getbuf(&audio.full); } audio.current = b; 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 */ return; shutdown: outb(DMA2_WRMASK, 4|(Dma&3)); /* disable dma */ sbcmd(0xd9); /* exit at end of count */ sbcmd(0xd5); /* pause */ audio.curcount = 0; audio.active = 0; } /* * cause sb to get an interrupt per buffer. * start first dma */ static void startdma(void) { ulong count; outb(DMA2_WRMASK, 4|(Dma&3)); /* disable dma */ if(audio.amode == Aread) { outb(DMA2_WRMODE, 0x44 | (Dma&3)); /* set mode */ sbcmd(0x42); /* input sampling rate */ } else { outb(DMA2_WRMODE, 0x48 | (Dma&3)); /* set mode */ sbcmd(0x41); /* output sampling rate */ } sbcmd(audio.speed>>8); sbcmd(audio.speed); count = (Bufsize >> 1) - 1; if(audio.amode == Aread) sbcmd(0xbe); /* A/D, autoinit */ else sbcmd(0xb6); /* D/A, autoinit */ sbcmd(0x30); /* stereo, 16 bit */ sbcmd(count); sbcmd(count>>8); audio.active = 1; contindma(); } /* * if audio is stopped, * start it up again. */ static void pokeaudio(void) { ulong sp; sp = splhi(); if(!audio.active) startdma(); splx(sp); } void audiosbintr(void) { int stat, dummy; stat = mxread(0x82) & 7; /* get irq status */ if(stat) { dummy = 0; if(stat & 2) { dummy = inb(PORT_CLRI16); contindma(); audio.intr = 1; wakeup(&audio.vous); } if(stat & 1) { dummy = inb(PORT_CLRI8); } if(stat & 4) { dummy = inb(PORT_CLRI401); } USED(dummy); } } void audiodmaintr(void) { /* print("sb16 dma interrupt\n"); /**/ } static int anybuf(void *p) { USED(p); return audio.intr; } /* * wait for some output to get * empty buffers back. */ static void waitaudio(void) { audio.intr = 0; pokeaudio(); tsleep(&audio.vous, anybuf, 0, 10*1000); if(audio.intr == 0) { /* print("audio timeout\n"); /**/ audio.active = 0; pokeaudio(); } } static void sbbufinit(void) { int i; void *p; for(i=0; i3 υs */ outb(PORT_RESET, 0); delay(1); i = sbread(); if(i != 0xaa) { print("sound blaster didnt respond #%.2x\n", i); return; } sbcmd(0xe1); /* get version */ audio.major = sbread(); audio.minor = sbread(); if(audio.major != 4) { print("bad soundblaster model #%.2x #.2x\n", audio.major, audio.minor); return; } /* * initialize the mixer */ mxcmd(0x00, 0); /* Reset mixer */ mxvolume(); /* * set up irq/dma chans */ mxcmd(0x80, /* irq */ (Irq==2)? 1: (Irq==5)? 2: (Irq==7)? 4: (Irq==10)? 8: 0); mxcmd(0x81, 1<qid.path & ~CHDIR) { default: error(Eperm); break; case Qvolume: case Qdir: break; case Qaudio: if(audio.bufinit == 0) { audio.bufinit = 1; sbbufinit(); } audio.amode = Awrite; if((omode&7) == OREAD) audio.amode = Aread; setempty(); audio.curcount = 0; break; } c = devopen(c, omode, audiodir, NPORT, devgen); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void audiocreate(Chan *c, char *name, int omode, ulong perm) { USED(c); USED(name); USED(omode); USED(perm); error(Eperm); } void audioclose(Chan *c) { switch(c->qid.path & ~CHDIR) { default: error(Eperm); break; case Qdir: case Qvolume: break; case Qaudio: if(c->flag & COPEN) { while(audio.active) waitaudio(); setempty(); } break; } } long audioread(Chan *c, char *a, long n, ulong offset) { long m, o, n0, bn; char buf[256]; Buf *b; int j; n0 = n; switch(c->qid.path & ~CHDIR) { default: error(Eperm); break; case Qdir: return devdirread(c, a, n, audiodir, NPORT, devgen); case Qaudio: if(audio.amode != Aread) error(Emode); while(n > 0) { b = audio.filling; if(b == 0) { b = getbuf(&audio.full); if(b == 0) { waitaudio(); continue; } audio.filling = b; swab(b->virt); audio.curcount = 0; } m = Bufsize-audio.curcount; if(m > n) m = n; memmove(a, b->virt+audio.curcount, m); audio.curcount += m; n -= m; a += m; if(audio.curcount >= Bufsize) { audio.filling = 0; putbuf(&audio.empty, b); } } break; case Qvolume: j = 0; for(m=0; volumes[m].name; m++) { o = *volumes[m].ptr1; if(volumes[m].flag & Fmono) j += snprint(buf+j, sizeof(buf)-j, "%s %d\n", volumes[m].name, o); else { bn = *volumes[m].ptr2; if(o == bn) j += snprint(buf+j, sizeof(buf)-j, "%s both %d\n", volumes[m].name, o); else j += snprint(buf+j, sizeof(buf)-j, "%s left %d right %d\n", volumes[m].name, o, bn); } } return readstr(offset, a, n, buf); } return n0-n; } Block* audiobread(Chan *c, long n, ulong offset) { return devbread(c, n, offset); } long audiowrite(Chan *c, char *a, long n, ulong offset) { long m, n0; int i, nf, v, left, right; char buf[255], *field[Ncmd]; Buf *b; USED(offset); n0 = n; switch(c->qid.path & ~CHDIR) { default: error(Eperm); break; case Qvolume: v = 0; left = 1; right = 1; if(n > sizeof(buf)-1) n = sizeof(buf)-1; memmove(buf, a, n); buf[n] = '\0'; nf = getfields(buf, field, Ncmd, " \t\n"); for(i = 0; i < nf; i++){ /* * a number is volume */ if(field[i][0] >= '0' && field[i][0] <= '9') { m = strtoul(field[i], 0, 10); if(left) *volumes[v].ptr1 = m; if(right) *volumes[v].ptr2 = m; mxvolume(); goto cont0; } for(m=0; volumes[m].name; m++) { if(strcmp(field[i], volumes[m].name) == 0) { v = m; goto cont0; } } if(strcmp(field[i], "reset") == 0) { resetlevel(); mxvolume(); goto cont0; } if(strcmp(field[i], "left") == 0) { left = 1; right = 0; goto cont0; } if(strcmp(field[i], "right") == 0) { left = 0; right = 1; goto cont0; } if(strcmp(field[i], "both") == 0) { left = 1; right = 1; goto cont0; } error(Evolume); break; cont0:; } break; case Qaudio: if(audio.amode != Awrite) error(Emode); while(n > 0) { b = audio.filling; if(b == 0) { b = getbuf(&audio.empty); if(b == 0) { waitaudio(); continue; } audio.filling = b; audio.curcount = 0; } m = Bufsize-audio.curcount; if(m > n) m = n; memmove(b->virt+audio.curcount, a, m); audio.curcount += m; n -= m; a += m; if(audio.curcount >= Bufsize) { audio.filling = 0; swab(b->virt); putbuf(&audio.full, b); } } break; } return n0 - n; } long audiobwrite(Chan *c, Block *bp, ulong offset) { return devbwrite(c, bp, offset); } void audioremove(Chan *c) { USED(c); error(Eperm); } void audiowstat(Chan *c, char *dp) { USED(c); USED(dp); error(Eperm); } static void swab(uchar *a) { ulong *p, *ep, b; p = (ulong*)a; ep = p + (Bufsize>>2); while(p < ep) { b = *p; b = (b>>24) | (b<<24) | ((b&0xff0000) >> 8) | ((b&0x00ff00) << 8); *p++ = b; } } . ## diffname port/devaudio.c 1995/0214 ## diff -e /n/fornaxdump/1995/0119/sys/src/brazil/port/devaudio.c /n/fornaxdump/1995/0214/sys/src/brazil/port/devaudio.c 831a if(!SBswab) return; . 798a poperror(); qunlock(&audio); . 772a qlock(&audio); if(waserror()){ qunlock(&audio); nexterror(); } . 667a poperror(); qunlock(&audio); . 642a qlock(&audio); if(waserror()){ qunlock(&audio); nexterror(); } . 617a poperror(); qunlock(&audio); . 614a qlock(&audio); audio.amode = Aclosed; if(waserror()){ qunlock(&audio); nexterror(); } . 578a qunlock(&audio); . 572,576c audio.amode = amode; . 567a amode = Awrite; if((omode&7) == OREAD) amode = Aread; qlock(&audio); if(audio.amode != Aclosed){ qunlock(&audio); error(Einuse); } . 553a int amode; . 519,522c (sbconf.irq==2)? 1: (sbconf.irq==5)? 2: (sbconf.irq==7)? 4: (sbconf.irq==10)? 8: . 492c outb(blaster.reset, 0); . 490c outb(blaster.reset, 1); . 487a audio.amode = Aclosed; . 486a setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0); . 485a 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; . 483a ISAConf sbconf; . 462a iunlock(&blaster); . 454a ilock(&blaster); . 430c print("audio timeout\n"); /**/ . 405a pcaudiosbintr(Ureg *ureg, void *rock) { USED(ureg, rock); /* print("sb16 audio interrupt\n"); /**/ audiosbintr(); } void . 399c dummy = inb(blaster.clri401); . 396c dummy = inb(blaster.clri8); . 391a iunlock(&blaster); . 390c ilock(&blaster); dummy = inb(blaster.clri16); . 378d 373,375d 363a iunlock(&blaster); . 349d 346,347c else . 342,344c ilock(&blaster); dmaend(Dma); if(audio.amode == Aread) . 326c dmaend(Dma); . 309,322c dmasetup(Dma, b->virt, Bufsize, audio.amode == Aread); . 290d 252c iunlock(&blaster); . 217,219c ilock(&blaster); . 175,176c outb(blaster.mixaddr, addr); s = inb(blaster.mixdata); . 165,166c outb(blaster.mixaddr, addr); outb(blaster.mixdata, val); . 154c return inb(blaster.read); . 152c s = inb(blaster.rstatus); . 138c outb(blaster.write, val); . 136c s = inb(blaster.wstatus); . 126c static char Emajor[] = "SoundBlaster version too old"; . 123a 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; . 75c int amode; /* Aclosed/Aread/Awrite for /audio */ . 69a QLock; . 29c Aclosed = 0, Aread, . 14,15d ## diffname port/devaudio.c 1995/0215 ## diff -e /n/fornaxdump/1995/0214/sys/src/brazil/port/devaudio.c /n/fornaxdump/1995/0215/sys/src/brazil/port/devaudio.c 84d ## diffname port/devaudio.c 1995/0216 ## diff -e /n/fornaxdump/1995/0215/sys/src/brazil/port/devaudio.c /n/fornaxdump/1995/0216/sys/src/brazil/port/devaudio.c 433c /* print("audio timeout\n"); /**/ . ## diffname port/devaudio.c 1995/0217 ## diff -e /n/fornaxdump/1995/0216/sys/src/brazil/port/devaudio.c /n/fornaxdump/1995/0217/sys/src/brazil/port/devaudio.c 282c putbuf(AQueue *q, Buf *b) . 268c getbuf(AQueue *q) . 86,87c AQueue empty; AQueue full; . 61c struct AQueue . 15a typedef struct AQueue AQueue; . ## diffname port/devaudio.c 1995/0221 ## diff -e /n/fornaxdump/1995/0217/sys/src/brazil/port/devaudio.c /n/fornaxdump/1995/0221/sys/src/brazil/port/devaudio.c 824,828d 816a if(strcmp(field[i], "in") == 0) { in = 1; out = 0; goto cont0; } if(strcmp(field[i], "out") == 0) { in = 0; out = 1; goto cont0; } . 807a in = 1; out = 1; left = 1; right = 1; . 797,800c if(left && out) audio.lovol[v] = m; if(left && in) audio.livol[v] = m; if(right && out) audio.rovol[v] = m; if(right && in) audio.rivol[v] = m; . 784a in = 1; out = 1; . 782c v = Vaudio; . 769c int i, nf, v, left, right, in, out; . 751a j += snprint(buf+j, sizeof(buf)-j, "\n"); . 740,750c buf[0] = 0; for(m=0; volumes[m].name; m++){ liv = audio.livol[m]; riv = audio.rivol[m]; lov = audio.lovol[m]; rov = audio.rovol[m]; j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name); if((volumes[m].flag & Fmono) || liv==riv && lov==rov){ if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov) j += snprint(buf+j, sizeof(buf)-j, " %d", liv); else{ if(volumes[m].flag & Fin) j += snprint(buf+j, sizeof(buf)-j, " in %d", liv); if(volumes[m].flag & Fout) j += snprint(buf+j, sizeof(buf)-j, " out %d", lov); } }else{ if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov && riv==rov) j += snprint(buf+j, sizeof(buf)-j, " left %d right %d", liv, riv); else{ if(volumes[m].flag & Fin) j += snprint(buf+j, sizeof(buf)-j, " in left %d right %d", liv, riv); if(volumes[m].flag & Fout) j += snprint(buf+j, sizeof(buf)-j, " out left %d right %d", lov, rov); } . 687,688c int liv, riv, lov, rov; long m, n0; char buf[300]; . 631a mxvolume(); . 482,483c audio.lovol[i] = volumes[i].ilval; audio.rovol[i] = volumes[i].irval; audio.livol[i] = volumes[i].ilval; audio.rivol[i] = volumes[i].irval; . 347,348c speed = audio.lovol[Vspeed]; } sbcmd(speed>>8); sbcmd(speed); . 345c speed = audio.livol[Vspeed]; } else { . 343c if(audio.amode == Aread) { . 339a int speed; . 262,264c 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(audio.amode == Aread) mxcmd(0x3c, 0); /* output switch */ else mxcmd(0x3c, source); mxcmd(0x3d, source); /* input left switch */ mxcmd(0x3e, source); /* input right switch */ . 259,260c mxcmdu(0x46, left[Vbass]); mxcmdu(0x47, right[Vbass]); . 256,257c mxcmdu(0x44, left[Vtreb]); mxcmdu(0x45, right[Vtreb]); . 251,254c mxcmds(0x3a, left[Vmic]); mxcmds(0x3b, left[Vspeaker]); . 248,249c mxcmds(0x38, left[Vline]); mxcmds(0x39, right[Vline]); . 245,246c mxcmds(0x36, left[Vcd]); mxcmds(0x37, right[Vcd]); . 242,243c mxcmds(0x34, left[Vsynth]); mxcmds(0x35, right[Vsynth]); . 239,240c mxcmds(0x32, left[Vaudio]); mxcmds(0x33, right[Vaudio]); . 236,237c mxcmd(0x30, 255); /* left master */ mxcmd(0x31, 255); /* right master */ mxcmd(0x3f, 0); /* left igain */ mxcmd(0x40, 0); /* right igain */ mxcmd(0x41, 0); /* left ogain */ mxcmd(0x42, 0); /* right ogain */ . 233,234d 231a int *left, *right; int source; if(audio.amode == Aread){ left = audio.livol; right = audio.rivol; }else{ left = audio.lovol; right = audio.rovol; } . 110,120c [Vspeed] "speed", Fin|Fout|Fmono, Speed, Speed, . 107,108c [Vtreb] "treb", Fout, 50, 50, [Vbass] "bass", Fout, 50, 50, . 103,105c [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, . 99c int ilval; /* initial values */ . 96,97d 77,82c int rivol[Nvol]; /* right/left input/output volumes */ int livol[Nvol]; int rovol[Nvol]; int lovol[Nvol]; . 43,55d 31a Vaudio = 0, Vsynth, Vcd, Vline, Vmic, Vspeaker, Vtreb, Vbass, Vspeed, Nvol, . 26a Fin = 2, Fout = 4, . 18d ## diffname port/devaudio.c 1995/0804 ## diff -e /n/fornaxdump/1995/0221/sys/src/brazil/port/devaudio.c /n/fornaxdump/1995/0804/sys/src/brazil/port/devaudio.c 954,956d 952c audiowstat(Chan*, char*) . 946,947d 944c audioremove(Chan*) . 816,817d 809c audiowrite(Chan *c, char *a, long n, ulong) . 669,673d 667c audiocreate(Chan*, char*, int, ulong) . 439d 437c anybuf(void*) . 425d 423c pcaudiosbintr(Ureg*, void*) . ## diffname port/devaudio.c 1996/0223 ## diff -e /n/fornaxdump/1995/0804/sys/src/brazil/port/devaudio.c /n/fornaxdump/1996/0223/sys/src/brazil/port/devaudio.c 10d ## diffname port/devaudio.c 1996/0315 ## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/port/devaudio.c /n/fornaxdump/1996/0315/sys/src/brazil/port/devaudio.c 825c nf = parsefields(buf, field, Ncmd, " \t\n"); . ## diffname port/devaudio.c 1996/1024 ## diff -e /n/fornaxdump/1996/0315/sys/src/brazil/port/devaudio.c /n/fornaxdump/1996/1024/sys/src/brazil/port/devaudio.c 591c mxcmd(0x81, 1<virt, Bufsize, audio.amode == Aread); . 128c static char Emajor[] = "soundblaster not responding/wrong version"; . 123a int dma; . ## diffname port/devaudio.c 1996/1025 ## diff -e /n/fornaxdump/1996/1024/sys/src/brazil/port/devaudio.c /n/fornaxdump/1996/1025/sys/src/brazil/port/devaudio.c 515c sbconf.dma = Dma; . ## diffname port/devaudio.c 1997/0327 ## diff -e /n/fornaxdump/1996/1025/sys/src/brazil/port/devaudio.c /n/emeliedump/1997/0327/sys/src/brazil/port/devaudio.c 965a Dev audiodevtab = { devreset, audioinit, audioattach, devclone, audiowalk, audiostat, audioopen, devcreate, audioclose, audioread, devbread, audiowrite, devbwrite, devremove, devwstat, }; . 931,948d 798,804c static long . 720c return devdirread(c, a, n, audiodir, nelem(audiodir), devgen); . 704c static long . 667,673c static void . 659c c = devopen(c, omode, audiodir, nelem(audiodir), devgen); . 622c static Chan* . 619c devstat(c, db, audiodir, nelem(audiodir), devgen); . 616c static void . 613c return devwalk(c, name, audiodir, nelem(audiodir), devgen); . 604,610c static int . 598c static Chan* . 577c print("#A: model #%.2x #%.2x; not SB 16\n", audio.major, audio.minor); . 568c print("#A: no response #%.2x\n", i); . 553a blaster.dma = sbconf.dma; . 542,543d 538c print("#A: bad irq %d\n", sbconf.irq); . 528c print("#A: bad port 0x%x\n", sbconf.port); . 508c static void . 490,494d 453c /* print("#A: audio timeout\n"); /**/ . 432c /* print("#A: dma interrupt\n"); /**/ . 425c /* print("#A: audio interrupt\n"); /**/ . 160c /* print("#A: sbread did not respond\n"); /**/ . 145c /* print("#A: sbcmd (#%.2x) timeout\n", val); /**/ . 107,108c [Vspeed] "speed", Fin|Fout|Fmono, Speed, Speed, 0 . 97,100c [Vaudio] "audio", Fout, 50, 50, [Vsynth] "synth", Fin|Fout, 0, 0, [Vcd] "cd", Fin|Fout, 0, 0, [Vline] "line", Fin|Fout, 0, 0, . 13,14d ## diffname port/devaudio.c 1997/0408 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/devaudio.c /n/emeliedump/1997/0408/sys/src/brazil/port/devaudio.c 923a 'A', "audio", . ## diffname port/devaudio.c 1998/0317 ## diff -e /n/emeliedump/1997/0408/sys/src/brazil/port/devaudio.c /n/emeliedump/1998/0317/sys/src/brazil/port/devaudio.c 571a . 569,570c if(audio.major != 3 || audio.minor != 1 || ess1688(&sbconf)){ print("#A: model 0x%.2x 0x%.2x; not SB 16 compatible\n", audio.major, audio.minor); return; } audio.major = 4; . 546a blaster.startdma = sb16startdma; blaster.intr = sb16intr; . 512c if(cistrcmp(sbconf.type, "sb16") != 0 && cistrcmp(sbconf.type, "ess1688") != 0) . 500a static int ess1688(ISAConf* sbconf) { int i, major, minor; /* * Try for ESS1688. */ sbcmd(0xE7); /* get version */ major = sbread(); minor = sbread(); if(major != 0x68 || minor != 0x8B){ print("#A: model 0x%.2x 0x%.2x; not ESS1688 compatible\n", major, minor); return 1; } ess1688reset(); switch(sbconf->irq){ case 2: case 9: i = 0x50|(0<<2); break; case 5: i = 0x50|(1<<2); break; case 7: i = 0x50|(2<<2); break; case 10: i = 0x50|(3<<2); break; default: print("#A: bad ESS1688 irq %d\n", sbconf->irq); return 1; } ess1688w(0xB1, i); switch(sbconf->dma){ case 0: i = 0x50|(1<<2); break; case 1: i = 0xF0|(2<<2); break; case 3: i = 0x50|(3<<2); break; default: print("#A: bad ESS1688 dma %d\n", sbconf->dma); return 1; } ess1688w(0xB2, i); ess1688reset(); blaster.startdma = ess1688startdma; blaster.intr = ess1688intr; return 0; } . 423,424c /* * x86 interrupt interface. */ blaster.intr(); . 420a audiosbintr(void) { /* * Carrera interrupt interface. */ blaster.intr(); } static void . 419a static void ess1688intr(void) { int dummy; if(audio.active){ ilock(&blaster); contindma(); dummy = inb(blaster.clri8); iunlock(&blaster); audio.intr = 1; wakeup(&audio.vous); USED(dummy); } else print("#A: unexpected ess1688 interrupt\n"); } . 394,395c static void sb16intr(void) . 391c blaster.startdma(); . 382a static int ess1688reset(void) { int i; outb(blaster.reset, 3); delay(1); /* >3 υs */ outb(blaster.reset, 0); delay(1); i = sbread(); if(i != 0xAA) { print("#A: no response 0x%.2x\n", i); return 1; } if(sbcmd(0xC6)){ /* extended mode */ print("#A: barf 3\n"); return 1; } return 0; } static void ess1688startdma(void) { ulong count; int speed, x; ilock(&blaster); dmaend(blaster.dma); if(audio.amode == Awrite) ess1688reset(); if(audio.amode == Aread) sbcmd(0xD3); /* speaker off */ /* * Set the speed. */ if(audio.amode == Aread) speed = audio.livol[Vspeed]; else speed = audio.lovol[Vspeed]; if(speed < 4000) speed = 4000; else if(speed > 48000) speed = 48000; if(speed > 22000) x = 0x80|(256-(795500+speed/2)/speed); else x = 128-(397700+speed/2)/speed; ess1688w(0xA1, x & 0xFF); speed = (speed * 9) / 20; x = 256 - 7160000 / (speed * 82); ess1688w(0xA2, x & 0xFF); if(audio.amode == Aread) ess1688w(0xB8, 0x0E); /* A/D, autoinit */ else ess1688w(0xB8, 0x04); /* D/A, autoinit */ x = ess1688r(0xA8) & ~0x03; ess1688w(0xA8, x|0x01); /* 2 channels */ ess1688w(0xB9, 2); /* demand mode, 4 bytes per request */ if(audio.amode == Awrite) ess1688w(0xB6, 0); ess1688w(0xB7, 0x71); ess1688w(0xB7, 0xBC); x = ess1688r(0xB1) & 0x0F; ess1688w(0xB1, x|0x50); x = ess1688r(0xB2) & 0x0F; ess1688w(0xB2, x|0x50); if(audio.amode == Awrite) sbcmd(0xD1); /* speaker on */ count = -Bufsize; ess1688w(0xA4, count & 0xFF); ess1688w(0xA5, (count>>8) & 0xFF); x = ess1688r(0xB8); ess1688w(0xB8, x|0x05); audio.active = 1; contindma(); iunlock(&blaster); } . 352c sb16startdma(void) . 336,337c if(dmasetup(blaster.dma, b->virt, Bufsize, audio.amode == Aread) >= 0) return; print("#A: dmasetup fail\n"); putbuf(&audio.empty, b); . 328c if(b) /* shouldn't happen */ . 324c if(b) /* shouldn't happen */ . 161a static int ess1688w(int reg, int val) { if(sbcmd(reg) || sbcmd(val)) return 1; return 0; } static int ess1688r(int reg) { if(sbcmd(0xC0) || sbcmd(reg)) return -1; return sbread(); } . 159c return -1; . 143c /* print("#A: sbcmd (0x%.2x) timeout\n", val); /**/ . 122a void (*startdma)(void); void (*intr)(void); . ## diffname port/devaudio.c 1998/0319 ## diff -e /n/emeliedump/1998/0317/sys/src/brazil/port/devaudio.c /n/emeliedump/1998/0319/sys/src/brazil/port/devaudio.c 992c audiowrite(Chan *c, char *a, long n, vlong) . 904a ulong offset = off; . 898c audioread(Chan *c, char *a, long n, vlong off) . ## diffname port/devaudio.c 1998/0327 ## diff -e /n/emeliedump/1998/0319/sys/src/brazil/port/devaudio.c /n/emeliedump/1998/0327/sys/src/brazil/port/devaudio.c 980c j += snprint(buf+j, sizeof(buf)-j, " out left %d right %d", . 977c j += snprint(buf+j, sizeof(buf)-j, " in left %d right %d", . 972,973c if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov && riv==rov) j += snprint(buf+j, sizeof(buf)-j, " left %d right %d", . 969c j += snprint(buf+j, sizeof(buf)-j, " out %d", lov); . 967c j += snprint(buf+j, sizeof(buf)-j, " in %d", liv); . ## diffname port/devaudio.c 1998/0331 ## diff -e /n/emeliedump/1998/0327/sys/src/brazil/port/devaudio.c /n/emeliedump/1998/0331/sys/src/brazil/port/devaudio.c 971c " out %d", lov); . 968c " in %d", liv); . ## diffname port/devaudio.c 1998/0512 ## diff -e /n/emeliedump/1998/0331/sys/src/brazil/port/devaudio.c /n/emeliedump/1998/0512/sys/src/brazil/port/devaudio.c 784c . ## diffname port/devaudio.c 1998/0603 ## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/devaudio.c /n/emeliedump/1998/0603/sys/src/brazil/port/devaudio.c 881a if (audio.amode == Awrite) { /* flush out last partial buffer */ Buf *b = audio.filling; if (b) { audio.filling = 0; memset(b->virt, 0, Bufsize-audio.curcount); swab(b->virt); putbuf(&audio.full, b); } if (!audio.active && audio.full.first) pokeaudio(); } . ## diffname port/devaudio.c 1998/0624 ## diff -e /n/emeliedump/1998/0603/sys/src/brazil/port/devaudio.c /n/emeliedump/1998/0624/sys/src/brazil/port/devaudio.c 891c if(!audio.active && audio.full.first) . 884,885c b = audio.filling; if(b) { . 882c if(audio.amode == Awrite) { . 868a Buf *b; . ## diffname port/devaudio.c 1998/0825 ## diff -e /n/emeliedump/1998/0624/sys/src/brazil/port/devaudio.c /n/emeliedump/1998/0825/sys/src/brazil/port/devaudio.c 736c print("#A: bad irq %lud\n", sbconf.irq); . 726c print("#A: bad port 0x%lux\n", sbconf.port); . 693c print("#A: bad ESS1688 dma %lud\n", sbconf->dma); . 677c print("#A: bad ESS1688 irq %lud\n", sbconf->irq); . ## diffname port/devaudio.c 1999/0219 ## diff -e /n/emeliedump/1998/0825/sys/src/brazil/port/devaudio.c /n/emeliedump/1999/0219/sys/src/brazil/port/devaudio.c 888c memset(b->virt+audio.curcount, 0, Bufsize-audio.curcount); . ## diffname port/devaudio.c 1999/0320 ## diff -e /n/emeliedump/1999/0219/sys/src/brazil/port/devaudio.c /n/emeliedump/1999/0320/sys/src/brazil/port/devaudio.c 1018a a = vp; . 1017a char *a; . 1012c audiowrite(Chan *c, void *vp, long n, vlong) . 920a a = v; . 918a char *a; . 911c audioread(Chan *c, void *v, long n, vlong off) . ## diffname port/devaudio.c 1999/0504 ## diff -e /n/emeliedump/1999/0320/sys/src/brazil/port/devaudio.c /n/emeliedump/1999/0504/sys/src/brazil/port/devaudio.c 714c sbconf.irq = IrqAUDIO; . ## diffname port/devaudio.c 1999/1005 ## diff -e /n/emeliedump/1999/0504/sys/src/brazil/port/devaudio.c /n/emeliedump/1999/1005/sys/src/brazil/port/devaudio.c 1007d 967a case Qstatus: buf[0] = 0; snprint(buf, sizeof(buf), "bytes %lud\ntime %lld\n", audio.totcount, audio.tottime); return readstr(offset, a, n, buf); . 877a case Qstatus: . 833a case Qstatus: if((omode&7) != OREAD) error(Eperm); . 800a x = mxread(0x81); for(i=5; i<=7; i++) if(x & (1<qid.path) { . 963c switch((ulong)c->qid.path) { . 938,939c if(waserror()){ qunlock(&audio); nexterror(); } . 914c error(Eperm); . 912c switch((ulong)c->qid.path) { . 867c switch((ulong)c->qid.path) { . 856c return devstat(c, db, n, audiodir, nelem(audiodir), devgen); . 853,854c static int audiostat(Chan *c, uchar *db, int n) . 850c return devwalk(c, nc, name, nname, audiodir, nelem(audiodir), devgen); . 847,848c static Walkqid* audiowalk(Chan *c, Chan *nc, char **name, int nname) . 195d 193d 147d 48a ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, . ## diffname port/devaudio.c 2001/1013 ## diff -e /n/emeliedump/2001/0527/sys/src/9/port/devaudio.c /n/emeliedump/2001/1013/sys/src/9/port/devaudio.c 1173a audio.buffered += m; . 998a audio.buffered -= m; . 928a audio.buffered += Bufsize-audio.curcount; . 853a audiodir[Qaudio].length = audio.buffered; . 636a audio.buffered = 0; . 355a audio.buffered -= Bufsize; } . 354c if(b){ . 351a audio.buffered += Bufsize; } . 350c if(b){ . 103,104c [Vline] "line", Fin|Fout, 0, 0, [Vmic] "mic", Fin|Fout|Fmono, 0, 0, . 100,101c [Vaudio] "audio", Fout, 50, 50, [Vsynth] "synth", Fin|Fout, 0, 0, . 85c Buf buf[Nbuf]; /* buffers and queues */ . 83a int buffered; /* number of bytes en route */ . 76c int rivol[Nvol]; /* right/left input/output volumes */ . 74c int intr; /* boolean an interrupt has happened */ . 71,72c int bufinit; /* boolean if buffers allocated */ int curcount; /* how much data in current buffer */ . ## diffname port/devaudio.c 2001/1016 ## diff -e /n/emeliedump/2001/1013/sys/src/9/port/devaudio.c /n/emeliedump/2001/1016/sys/src/9/port/devaudio.c 1019,1020c snprint(buf, sizeof(buf), "bufsize %6d buffered %6d offset %10lud time %19lld\n", Bufsize, audio.buffered, audio.totcount, audio.tottime); . ## diffname port/devaudio.c 2001/1017 ## diff -e /n/emeliedump/2001/1016/sys/src/9/port/devaudio.c /n/emeliedump/2001/1017/sys/src/9/port/devaudio.c 1020c Bufsize, audio.buffered, audio.totcount<0?0:audio.totcount, audio.tottime); . 898a if (amode == Aread) audio.totcount -= Bufsize; . 504d 412d ## diffname port/devaudio.c 2001/1018 ## diff -e /n/emeliedump/2001/1017/sys/src/9/port/devaudio.c /n/emeliedump/2001/1018/sys/src/9/port/devaudio.c 1020c Bufsize, audio.buffered, audio.totcount, audio.tottime); . 897,898d ## diffname port/devaudio.c 2001/1019 ## diff -e /n/emeliedump/2001/1018/sys/src/9/port/devaudio.c /n/emeliedump/2001/1019/sys/src/9/port/devaudio.c 624a p += Bufsize; . 621d 619a p = (uchar*)(((ulong)xalloc((Nbuf+1) * Bufsize) + Bufsize-1)&~(Bufsize-1)); . 618c uchar *p; . 553,554d 529,530d 349a if (b){ audio.totcount += Bufsize; audio.tottime = todget(nil); } . 84d 70a int buffered; /* number of bytes en route */ . ## diffname port/devaudio.c 2001/1117 ## diff -e /n/emeliedump/2001/1019/sys/src/9/port/devaudio.c /n/emeliedump/2001/1117/sys/src/9/port/devaudio.c 1093c nf = tokenize(buf, field, Ncmd); . ## diffname port/devaudio.c 2001/1121 ## diff -e /n/emeliedump/2001/1117/sys/src/9/port/devaudio.c /n/emeliedump/2001/1121/sys/src/9/port/devaudio.c 1151a free(cb); poperror(); . 1143c if(strcmp(cb->f[i], "right") == 0) { . 1138c if(strcmp(cb->f[i], "left") == 0) { . 1133c if(strcmp(cb->f[i], "out") == 0) { . 1128c if(strcmp(cb->f[i], "in") == 0) { . 1123c if(strcmp(cb->f[i], "reset") == 0) { . 1113c if(strcmp(cb->f[i], volumes[m].name) == 0) { . 1098,1099c if(cb->f[i][0] >= '0' && cb->f[i][0] <= '9') { m = strtoul(cb->f[i], 0, 10); . 1093,1094c for(i = 0; i < cb->nf; i++){ . 1088,1091c cb = parsecmd(vp, n); if(waserror()){ free(cb); nexterror(); } . 1070,1071c int i, v, left, right, in, out; Cmdbuf *cb; . ## diffname port/devaudio.c 2002/0109 ## diff -e /n/emeliedump/2001/1121/sys/src/9/port/devaudio.c /n/emeliedump/2002/0109/sys/src/9/port/devaudio.c 1223a devshutdown, . ## diffname port/devaudio.c 2002/0412 ## diff -e /n/emeliedump/2002/0109/sys/src/9/port/devaudio.c /n/emeliedump/2002/0412/sys/src/9/port/devaudio.c 823a . 796a iofree(sbconf.port); iofree(sbconf.port+0x100); . 785a iofree(sbconf.port); iofree(sbconf.port+0x100); . 756a iofree(sbconf.port); iofree(sbconf.port+0x100); . 747a if(ioalloc(sbconf.port, 0x10, 0, "audio") < 0){ print("#A: cannot ioalloc range %x+0x10\n", sbconf.port); return; } if(ioalloc(sbconf.port+0x100, 1, 0, "audio.mpu401") < 0){ iofree(sbconf.port); print("#A: cannot ioalloc range %x+0x01\n", sbconf.port+0x100); return; } . ## diffname port/devaudio.c 2002/0414 ## diff -e /n/emeliedump/2002/0412/sys/src/9/port/devaudio.c /n/emeliedump/2002/0414/sys/src/9/port/devaudio.c 755c print("#A: cannot ioalloc range %lux+0x01\n", sbconf.port+0x100); . 750c print("#A: cannot ioalloc range %lux+0x10\n", sbconf.port); . ## diffname port/devaudio.c 2002/0523 ## diff -e /n/emeliedump/2002/0414/sys/src/9/port/devaudio.c /n/emeliedump/2002/0523/sys/src/9/port/devaudio.c 736c if(sbconf.type == nil || (cistrcmp(sbconf.type, "sb16") != 0 && cistrcmp(sbconf.type, "ess1688") != 0)) . ## diffname port/devaudio.c 2003/0301 ## diff -e /n/emeliedump/2002/0523/sys/src/9/port/devaudio.c /n/emeliedump/2003/0301/sys/src/9/port/devaudio.c 769c print("#A: bad irq %d\n", sbconf.irq); . 695c print("#A: bad ESS1688 irq %d\n", sbconf->irq); . ## diffname port/devaudio.c 2003/0406 ## diff -e /n/emeliedump/2003/0301/sys/src/9/port/devaudio.c /n/emeliedump/2003/0406/sys/src/9/port/devaudio.c 350c if(b){ .