Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/devaudio.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## 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; i<Nbuf; i++) {
		p = xspanalloc(Bufsize, CACHELINESZ, 64*1024);
		dcflush(p, Bufsize);
		audio.buf[i].virt = UNCACHED(uchar, p);
		audio.buf[i].phys = (ulong)PADDR(p);
	}
}

static	void
setempty(void)
{
	int i;

	audio.empty.first = 0;
	audio.empty.last = 0;
	audio.full.first = 0;
	audio.full.last = 0;
	audio.current = 0;
	audio.filling = 0;
	for(i=0; i<Nbuf; i++)
		putbuf(&audio.empty, &audio.buf[i]);
}

void
audioreset(void)
{
}

static	void
resetlevel(void)
{
	int i;

	for(i=0; volumes[i].name; i++) {
		*volumes[i].ptr1 = volumes[i].ilval;
		*volumes[i].ptr2 = volumes[i].irval;
	}
}

void
audioinit(void)
{
	int i;

	seteisadma(Dma, audiodmaintr);

	resetlevel();

	outb(PORT_RESET, 1);
	delay(1);			/* >3 υ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<<Dma);	/* dma */
}

Chan*
audioattach(char *param)
{
	return devattach('A', param);
}

Chan*
audioclone(Chan *c, Chan *nc)
{
	return devclone(c, nc);
}

int
audiowalk(Chan *c, char *name)
{
	return devwalk(c, name, audiodir, NPORT, devgen);
}

void
audiostat(Chan *c, char *db)
{
	devstat(c, db, audiodir, NPORT, devgen);
}

Chan*
audioopen(Chan *c, int omode)
{

	if(audio.major != 4)
		error(Emajor);

	switch(c->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<<blaster.dma);	/* dma */
.
573c
		print("bad soundblaster model #%.2x #%.2x; not SB 16\n", audio.major, audio.minor);
.
551c
	seteisadma(blaster.dma, audiodmaintr);
.
539a
	blaster.dma = sbconf.dma;

.
536c
		print("devaudio: bad sb16 irq %d\n", sbconf.irq);
.
526c
		print("devaudio: bad sb16 port 0x%x\n", sbconf.port);
.
513a
	sbconf.dma = 5;
.
359c
	dmaend(blaster.dma);
.
341c
	dmaend(blaster.dma);
.
337c
	dmasetup(blaster.dma, b->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<<i)){
			blaster.dma = i;
			break;
		}

	x = mxread(0x80);
	for(i=0; i<=3; i++)
		if(x & (1<<i)){
			sbconf.irq = irq[i];
			break;
		}

	seteisadma(blaster.dma, audiodmaintr);
	setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0);
.
792c
	 * Attempt to set IRQ/DMA channels.
	 * On old ISA boards, these registers are writable.
	 * On Plug-n-Play boards, these are read-only.
	 *
	 * To accomodate both, we write to the registers,
	 * but then use the contents in case the write is
	 * disallowed.
.
755,757d
710c
	int i, x;
	static int irq[] = {2,5,7,10};
.
627a
	audio.totcount = 0;
	audio.tottime = 0LL;
.
540a
		audio.totcount += Bufsize;
		audio.tottime = todget(nil);
.
518a
			audio.totcount += Bufsize;
			audio.tottime = todget(nil);
.
492a
	audio.tottime = todget(nil);
.
401a
	audio.tottime = todget(nil);
.
78a
	ulong	totcount;	/* how many bytes processed since open */
	vlong	tottime;	/* time at which totcount bytes were processed */
.
49a
	"audiostat",{Qstatus},		0,	0444,
.
20a
	Qstatus,
.
## diffname port/devaudio.c 1999/1015
## diff -e /n/emeliedump/1999/1005/sys/src/brazil/port/devaudio.c /n/emeliedump/1999/1015/sys/src/brazil/port/devaudio.c
745a
	case 9:
.
## diffname port/devaudio.c 1999/1122
## diff -e /n/emeliedump/1999/1015/sys/src/brazil/port/devaudio.c /n/emeliedump/1999/1122/sys/src/9/port/devaudio.c
814a
		(sbconf.irq==9)? 1:
.
## diffname port/devaudio.c 2000/0308
## diff -e /n/emeliedump/1999/1122/sys/src/9/port/devaudio.c /n/emeliedump/2000/0308/sys/src/9/port/devaudio.c
1084c
		nf = getfields(buf, field, Ncmd, 1, " \t\n");
.
## diffname port/devaudio.c 2000/0407
## diff -e /n/emeliedump/2000/0308/sys/src/9/port/devaudio.c /n/emeliedump/2000/0407/sys/src/9/port/devaudio.c
1192a
	}
.
1191c
	if(!SBswab){
		USED(a);
.
## diffname port/devaudio.c 2001/0503
## diff -e /n/emeliedump/2000/0407/sys/src/9/port/devaudio.c /n/emeliedump/2001/0503/sys/src/9/port/devaudio.c
935,938c
			while(waserror())
				;
.
911c
		error(Eperm);		/* can't happen */
.
## diffname port/devaudio.c 2001/0526
## diff -e /n/emeliedump/2001/0503/sys/src/9/port/devaudio.c /n/emeliedump/2001/0526/sys/src/9/port/devaudio.c
192a
	delay(1);
.
191a
	delay(1);
.
146a
			delay(1);
.
## diffname port/devaudio.c 2001/0527
## diff -e /n/emeliedump/2001/0526/sys/src/9/port/devaudio.c /n/emeliedump/2001/0527/sys/src/9/port/devaudio.c
1214d
1069c
	switch((ulong)c->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){
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].