plan 9 kernel history: overview | file list | diff list

port/devaudio.c (diff list | history)

1995/0119/sys/src/9/port/devaudio.c:11,181995/0214/sys/src/9/port/devaudio.c:11,16 (short | long)
1995/0119    
#include	"io.h" 
#include	"audio.h" 
 
                 
#define	nelem(x)	(sizeof (x)/sizeof(x[0])) 
#define	NPORT		(sizeof audiodir/sizeof(Dirtab)) 
 
typedef struct	Buf	Buf; 
1995/0119/sys/src/9/port/devaudio.c:26,321995/0214/sys/src/9/port/devaudio.c:24,31
1995/0119    
 
	Fmono		= 1, 
 
	Aread		= 0, 
1995/0214    
	Aclosed		= 0, 
	Aread, 
1995/0119    
	Awrite, 
 
	Speed		= 44100, 
1995/0119/sys/src/9/port/devaudio.c:67,781995/0214/sys/src/9/port/devaudio.c:66,78
1995/0119    
}; 
static	struct 
{ 
1995/0214    
	QLock; 
1995/0119    
	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 */ 
1995/0214    
	int	amode;		/* Aclosed/Aread/Awrite for /audio */ 
1995/0119    
	Level	left;		/* all of left volumes */ 
	Level	right;		/* all of right volumes */ 
	int	mic;		/* mono level */ 
1995/0119/sys/src/9/port/devaudio.c:121,1291995/0214/sys/src/9/port/devaudio.c:121,144
1995/0119    
	0 
}; 
 
1995/0214    
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; 
 
1995/0119    
static	void	swab(uchar*); 
 
static	char	Emajor[]	= "SB16 version too old"; 
1995/0214    
static	char	Emajor[]	= "SoundBlaster version too old"; 
1995/0119    
static	char	Emode[]		= "illegal open mode"; 
static	char	Evolume[]	= "illegal volume specifier"; 
 
1995/0119/sys/src/9/port/devaudio.c:133,1411995/0214/sys/src/9/port/devaudio.c:148,156
1995/0119    
	int i, s; 
 
	for(i=1<<16; i!=0; i--) { 
		s = inb(PORT_WSTATUS); 
1995/0214    
		s = inb(blaster.wstatus); 
1995/0119    
		if((s & 0x80) == 0) { 
			outb(PORT_WRITE, val); 
1995/0214    
			outb(blaster.write, val); 
1995/0119    
			return 0; 
		} 
	} 
1995/0119/sys/src/9/port/devaudio.c:149,1571995/0214/sys/src/9/port/devaudio.c:164,172
1995/0119    
	int i, s; 
 
	for(i=1<<16; i!=0; i--) { 
		s = inb(PORT_RSTATUS); 
1995/0214    
		s = inb(blaster.rstatus); 
1995/0119    
		if((s & 0x80) != 0) { 
			return inb(PORT_READ); 
1995/0214    
			return inb(blaster.read); 
1995/0119    
		} 
	} 
/*	print("SB16 sbread did not respond\n");	/**/ 
1995/0119/sys/src/9/port/devaudio.c:162,1691995/0214/sys/src/9/port/devaudio.c:177,184
1995/0119    
mxcmd(int addr, int val) 
{ 
 
	outb(PORT_MIXER_ADDR, addr); 
	outb(PORT_MIXER_DATA, val); 
1995/0214    
	outb(blaster.mixaddr, addr); 
	outb(blaster.mixdata, val); 
1995/0119    
	return 1; 
} 
 
1995/0119/sys/src/9/port/devaudio.c:172,1791995/0214/sys/src/9/port/devaudio.c:187,194
1995/0119    
{ 
	int s; 
 
	outb(PORT_MIXER_ADDR, addr); 
	s = inb(PORT_MIXER_DATA); 
1995/0214    
	outb(blaster.mixaddr, addr); 
	s = inb(blaster.mixdata); 
1995/0119    
	return s; 
} 
 
1995/0119/sys/src/9/port/devaudio.c:214,2221995/0214/sys/src/9/port/devaudio.c:229,235
1995/0119    
static	void 
mxvolume(void) 
{ 
	ulong sp; 
                 
	sp = splhi(); 
1995/0214    
	ilock(&blaster); 
1995/0119    
	mxcmds(0x30, audio.left.master); 
	mxcmds(0x31, audio.right.master); 
 
1995/0119/sys/src/9/port/devaudio.c:249,2551995/0214/sys/src/9/port/devaudio.c:262,268
1995/0119    
	mxcmd(0x3c, audio.oswitch); 
	mxcmd(0x3d, audio.left.iswitch); 
	mxcmd(0x3e, audio.right.iswitch); 
	splx(sp); 
1995/0214    
	iunlock(&blaster); 
1995/0119    
} 
 
static	Buf* 
1995/0119/sys/src/9/port/devaudio.c:287,2931995/0214/sys/src/9/port/devaudio.c:300,305
1995/0119    
contindma(void) 
{ 
	Buf *b; 
	ulong count, addr; 
 
	if(!audio.active) 
		goto shutdown; 
1995/0119/sys/src/9/port/devaudio.c:306,3291995/0214/sys/src/9/port/devaudio.c:318,328
1995/0119    
	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 */ 
                 
1995/0214    
	dmasetup(Dma, b->virt, Bufsize, audio.amode == Aread); 
1995/0119    
	return; 
 
shutdown: 
	outb(DMA2_WRMASK, 4|(Dma&3));	/* disable dma */ 
1995/0214    
	dmaend(Dma); 
1995/0119    
	sbcmd(0xd9);				/* exit at end of count */ 
	sbcmd(0xd5);				/* pause */ 
	audio.curcount = 0; 
1995/0119/sys/src/9/port/devaudio.c:339,3521995/0214/sys/src/9/port/devaudio.c:338,349
1995/0119    
{ 
	ulong count; 
 
	outb(DMA2_WRMASK, 4|(Dma&3));	/* disable dma */ 
	if(audio.amode == Aread) { 
		outb(DMA2_WRMODE, 0x44 | (Dma&3));	/* set mode */ 
1995/0214    
	ilock(&blaster); 
	dmaend(Dma); 
	if(audio.amode == Aread) 
1995/0119    
		sbcmd(0x42);			/* input sampling rate */ 
	} else { 
		outb(DMA2_WRMODE, 0x48 | (Dma&3));	/* set mode */ 
1995/0214    
	else 
1995/0119    
		sbcmd(0x41);			/* output sampling rate */ 
	} 
	sbcmd(audio.speed>>8); 
	sbcmd(audio.speed); 
 
1995/0119/sys/src/9/port/devaudio.c:361,3661995/0214/sys/src/9/port/devaudio.c:358,364
1995/0119    
 
	audio.active = 1; 
	contindma(); 
1995/0214    
	iunlock(&blaster); 
1995/0119    
} 
 
/* 
1995/0119/sys/src/9/port/devaudio.c:370,3811995/0214/sys/src/9/port/devaudio.c:368,375
1995/0119    
static	void 
pokeaudio(void) 
{ 
	ulong sp; 
                 
	sp = splhi(); 
	if(!audio.active) 
		startdma(); 
	splx(sp); 
} 
 
void 
1995/0119/sys/src/9/port/devaudio.c:387,4021995/0214/sys/src/9/port/devaudio.c:381,398
1995/0119    
	if(stat) { 
		dummy = 0; 
		if(stat & 2) { 
			dummy = inb(PORT_CLRI16); 
1995/0214    
			ilock(&blaster); 
			dummy = inb(blaster.clri16); 
1995/0119    
			contindma(); 
1995/0214    
			iunlock(&blaster); 
1995/0119    
			audio.intr = 1; 
			wakeup(&audio.vous); 
		} 
		if(stat & 1) { 
			dummy = inb(PORT_CLRI8); 
1995/0214    
			dummy = inb(blaster.clri8); 
1995/0119    
		} 
		if(stat & 4) { 
			dummy = inb(PORT_CLRI401); 
1995/0214    
			dummy = inb(blaster.clri401); 
1995/0119    
		} 
		USED(dummy); 
	} 
1995/0119/sys/src/9/port/devaudio.c:403,4081995/0214/sys/src/9/port/devaudio.c:399,412
1995/0119    
} 
 
void 
1995/0214    
pcaudiosbintr(Ureg *ureg, void *rock) 
{ 
	USED(ureg, rock); 
/*	print("sb16 audio interrupt\n");	/**/ 
	audiosbintr(); 
} 
 
void 
1995/0119    
audiodmaintr(void) 
{ 
/*	print("sb16 dma interrupt\n");	/**/ 
1995/0119/sys/src/9/port/devaudio.c:427,4331995/0214/sys/src/9/port/devaudio.c:431,437
1995/0119    
	pokeaudio(); 
	tsleep(&audio.vous, anybuf, 0, 10*1000); 
	if(audio.intr == 0) { 
/*		print("audio timeout\n");	/**/ 
1995/0214    
		print("audio timeout\n");	/**/ 
1995/0119    
		audio.active = 0; 
		pokeaudio(); 
	} 
1995/0119/sys/src/9/port/devaudio.c:452,4571995/0214/sys/src/9/port/devaudio.c:456,462
1995/0119    
{ 
	int i; 
 
1995/0214    
	ilock(&blaster); 
1995/0119    
	audio.empty.first = 0; 
	audio.empty.last = 0; 
	audio.full.first = 0; 
1995/0119/sys/src/9/port/devaudio.c:460,4651995/0214/sys/src/9/port/devaudio.c:465,471
1995/0119    
	audio.filling = 0; 
	for(i=0; i<Nbuf; i++) 
		putbuf(&audio.empty, &audio.buf[i]); 
1995/0214    
	iunlock(&blaster); 
1995/0119    
} 
 
void 
1995/0119/sys/src/9/port/devaudio.c:481,4951995/0214/sys/src/9/port/devaudio.c:487,542
1995/0119    
void 
audioinit(void) 
{ 
1995/0214    
	ISAConf sbconf; 
1995/0119    
	int i; 
 
1995/0214    
	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; 
 
1995/0119    
	seteisadma(Dma, audiodmaintr); 
1995/0214    
	setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0); 
1995/0119    
 
1995/0214    
	audio.amode = Aclosed; 
1995/0119    
	resetlevel(); 
 
	outb(PORT_RESET, 1); 
1995/0214    
	outb(blaster.reset, 1); 
1995/0119    
	delay(1);			/* >3 υs */ 
	outb(PORT_RESET, 0); 
1995/0214    
	outb(blaster.reset, 0); 
1995/0119    
	delay(1); 
 
	i = sbread(); 
1995/0119/sys/src/9/port/devaudio.c:516,5251995/0214/sys/src/9/port/devaudio.c:563,572
1995/0119    
	 * set up irq/dma chans 
	 */ 
	mxcmd(0x80,			/* irq */ 
		(Irq==2)? 1: 
		(Irq==5)? 2: 
		(Irq==7)? 4: 
		(Irq==10)? 8: 
1995/0214    
		(sbconf.irq==2)? 1: 
		(sbconf.irq==5)? 2: 
		(sbconf.irq==7)? 4: 
		(sbconf.irq==10)? 8: 
1995/0119    
		0); 
	mxcmd(0x81, 1<<Dma);	/* dma */ 
} 
1995/0119/sys/src/9/port/devaudio.c:551,5561995/0214/sys/src/9/port/devaudio.c:598,604
1995/0119    
Chan* 
audioopen(Chan *c, int omode) 
{ 
1995/0214    
	int amode; 
1995/0119    
 
	if(audio.major != 4) 
		error(Emajor); 
1995/0119/sys/src/9/port/devaudio.c:565,5811995/0214/sys/src/9/port/devaudio.c:613,634
1995/0119    
		break; 
 
	case Qaudio: 
1995/0214    
		amode = Awrite; 
		if((omode&7) == OREAD) 
			amode = Aread; 
		qlock(&audio); 
		if(audio.amode != Aclosed){ 
			qunlock(&audio); 
			error(Einuse); 
		} 
1995/0119    
		if(audio.bufinit == 0) { 
			audio.bufinit = 1; 
			sbbufinit(); 
		} 
                 
		audio.amode = Awrite; 
		if((omode&7) == OREAD) 
			audio.amode = Aread; 
                 
1995/0214    
		audio.amode = amode; 
1995/0119    
		setempty(); 
		audio.curcount = 0; 
1995/0214    
		qunlock(&audio); 
1995/0119    
		break; 
	} 
	c = devopen(c, omode, audiodir, NPORT, devgen); 
1995/0119/sys/src/9/port/devaudio.c:612,6201995/0214/sys/src/9/port/devaudio.c:665,681
1995/0119    
 
	case Qaudio: 
		if(c->flag & COPEN) { 
1995/0214    
			qlock(&audio); 
			audio.amode = Aclosed; 
			if(waserror()){ 
				qunlock(&audio); 
				nexterror(); 
			} 
1995/0119    
			while(audio.active) 
				waitaudio(); 
			setempty(); 
1995/0214    
			poperror(); 
			qunlock(&audio); 
1995/0119    
		} 
		break; 
	} 
1995/0119/sys/src/9/port/devaudio.c:640,6451995/0214/sys/src/9/port/devaudio.c:701,711
1995/0119    
	case Qaudio: 
		if(audio.amode != Aread) 
			error(Emode); 
1995/0214    
		qlock(&audio); 
		if(waserror()){ 
			qunlock(&audio); 
			nexterror(); 
		} 
1995/0119    
		while(n > 0) { 
			b = audio.filling; 
			if(b == 0) { 
1995/0119/sys/src/9/port/devaudio.c:665,6701995/0214/sys/src/9/port/devaudio.c:731,738
1995/0119    
				putbuf(&audio.empty, b); 
			} 
		} 
1995/0214    
		poperror(); 
		qunlock(&audio); 
1995/0119    
		break; 
 
	case Qvolume: 
1995/0119/sys/src/9/port/devaudio.c:770,7751995/0214/sys/src/9/port/devaudio.c:838,848
1995/0119    
	case Qaudio: 
		if(audio.amode != Awrite) 
			error(Emode); 
1995/0214    
		qlock(&audio); 
		if(waserror()){ 
			qunlock(&audio); 
			nexterror(); 
		} 
1995/0119    
		while(n > 0) { 
			b = audio.filling; 
			if(b == 0) { 
1995/0119/sys/src/9/port/devaudio.c:796,8011995/0214/sys/src/9/port/devaudio.c:869,876
1995/0119    
				putbuf(&audio.full, b); 
			} 
		} 
1995/0214    
		poperror(); 
		qunlock(&audio); 
1995/0119    
		break; 
	} 
	return n0 - n; 
1995/0119/sys/src/9/port/devaudio.c:829,8341995/0214/sys/src/9/port/devaudio.c:904,911
1995/0119    
{ 
	ulong *p, *ep, b; 
 
1995/0214    
	if(!SBswab) 
		return; 
1995/0119    
	p = (ulong*)a; 
	ep = p + (Bufsize>>2); 
	while(p < ep) { 
1995/0214/sys/src/9/port/devaudio.c:81,871995/0215/sys/src/9/port/devaudio.c:81,86 (short | long)
1995/0119    
	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; 
1995/0215/sys/src/9/port/devaudio.c:430,4361995/0216/sys/src/9/port/devaudio.c:430,436 (short | long)
1995/0119    
	pokeaudio(); 
	tsleep(&audio.vous, anybuf, 0, 10*1000); 
	if(audio.intr == 0) { 
1995/0214    
		print("audio timeout\n");	/**/ 
1995/0216    
/*		print("audio timeout\n");	/**/ 
1995/0119    
		audio.active = 0; 
		pokeaudio(); 
	} 
1995/0216/sys/src/9/port/devaudio.c:13,181995/0217/sys/src/9/port/devaudio.c:13,19 (short | long)
1995/0119    
 
#define	NPORT		(sizeof audiodir/sizeof(Dirtab)) 
 
1995/0217    
typedef struct	AQueue	AQueue; 
1995/0119    
typedef struct	Buf	Buf; 
typedef struct	Level	Level; 
 
1995/0216/sys/src/9/port/devaudio.c:58,641995/0217/sys/src/9/port/devaudio.c:59,65
1995/0119    
	ulong	phys; 
	Buf*	next; 
}; 
struct	Queue 
1995/0217    
struct	AQueue 
1995/0119    
{ 
	Lock; 
	Buf*	first; 
1995/0216/sys/src/9/port/devaudio.c:83,901995/0217/sys/src/9/port/devaudio.c:84,91
1995/0119    
	int	minor;		/* SB16 minor version number */ 
 
	Buf	buf[Nbuf];	/* buffers and queues */ 
	Queue	empty; 
	Queue	full; 
1995/0217    
	AQueue	empty; 
	AQueue	full; 
1995/0119    
	Buf*	current; 
	Buf*	filling; 
} audio; 
1995/0216/sys/src/9/port/devaudio.c:265,2711995/0217/sys/src/9/port/devaudio.c:266,272
1995/0119    
} 
 
static	Buf* 
getbuf(Queue *q) 
1995/0217    
getbuf(AQueue *q) 
1995/0119    
{ 
	Buf *b; 
 
1995/0216/sys/src/9/port/devaudio.c:279,2851995/0217/sys/src/9/port/devaudio.c:280,286
1995/0119    
} 
 
static	void 
putbuf(Queue *q, Buf *b) 
1995/0217    
putbuf(AQueue *q, Buf *b) 
1995/0119    
{ 
 
	ilock(q); 
1995/0217/sys/src/9/port/devaudio.c:15,211995/0221/sys/src/9/port/devaudio.c:15,20 (short | long)
1995/0119    
 
1995/0217    
typedef struct	AQueue	AQueue; 
1995/0119    
typedef struct	Buf	Buf; 
typedef struct	Level	Level; 
 
enum 
{ 
1995/0217/sys/src/9/port/devaudio.c:24,341995/0221/sys/src/9/port/devaudio.c:23,46
1995/0119    
	Qvolume, 
 
	Fmono		= 1, 
1995/0221    
	Fin		= 2, 
	Fout		= 4, 
1995/0119    
 
1995/0214    
	Aclosed		= 0, 
	Aread, 
1995/0119    
	Awrite, 
 
1995/0221    
	Vaudio		= 0, 
	Vsynth, 
	Vcd, 
	Vline, 
	Vmic, 
	Vspeaker, 
	Vtreb, 
	Vbass, 
	Vspeed, 
	Nvol, 
 
1995/0119    
	Speed		= 44100, 
	Ncmd		= 50,		/* max volume command words */ 
}; 
1995/0217/sys/src/9/port/devaudio.c:40,581995/0221/sys/src/9/port/devaudio.c:52,57
1995/0119    
	"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; 
1995/0217/sys/src/9/port/devaudio.c:74,851995/0221/sys/src/9/port/devaudio.c:73,82
1995/0119    
	int	active;		/* boolean dma running */ 
	int	intr;		/* boolean an interrupt has happened */ 
1995/0214    
	int	amode;		/* Aclosed/Aread/Awrite for /audio */ 
1995/0119    
	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 */ 
1995/0221    
	int	rivol[Nvol];		/* right/left input/output volumes */ 
	int	livol[Nvol]; 
	int	rovol[Nvol]; 
	int	lovol[Nvol]; 
1995/0119    
	int	major;		/* SB16 major version number (sb 4) */ 
	int	minor;		/* SB16 minor version number */ 
 
1995/0217/sys/src/9/port/devaudio.c:93,1231995/0221/sys/src/9/port/devaudio.c:90,111
1995/0119    
static	struct 
{ 
	char*	name; 
	int*	ptr1; 
	int*	ptr2; 
	int	flag; 
	int	ilval; 
1995/0221    
	int	ilval;		/* initial values */ 
1995/0119    
	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, 
1995/0221    
[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, 
1995/0119    
 
	"treb",		&audio.left.treb,	&audio.right.treb,	0, 	50,	50, 
	"bass",		&audio.left.bass,	&audio.right.bass,	0, 	50,	50, 
1995/0221    
[Vtreb]		"treb",		Fout, 		50,	50, 
[Vbass]		"bass",		Fout, 		50,	50, 
1995/0119    
 
	"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, 
1995/0221    
[Vspeed]		"speed",		Fin|Fout|Fmono,	Speed,	Speed, 
1995/0119    
	0 
}; 
 
1995/0217/sys/src/9/port/devaudio.c:229,2671995/0221/sys/src/9/port/devaudio.c:217,284
1995/0119    
static	void 
mxvolume(void) 
{ 
1995/0221    
	int *left, *right; 
	int source; 
 
	if(audio.amode == Aread){ 
		left = audio.livol; 
		right = audio.rivol; 
	}else{ 
		left = audio.lovol; 
		right = audio.rovol; 
	} 
 
1995/0214    
	ilock(&blaster); 
1995/0119    
	mxcmds(0x30, audio.left.master); 
	mxcmds(0x31, audio.right.master); 
 
	mxcmdt(0x32, audio.left.pcm); 
	mxcmdt(0x33, audio.right.pcm); 
1995/0221    
	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 */ 
1995/0119    
 
	mxcmdt(0x34, audio.left.synth); 
	mxcmdt(0x35, audio.right.synth); 
1995/0221    
	mxcmds(0x32, left[Vaudio]); 
	mxcmds(0x33, right[Vaudio]); 
1995/0119    
 
	mxcmdt(0x36, audio.left.cd); 
	mxcmdt(0x37, audio.right.cd); 
1995/0221    
	mxcmds(0x34, left[Vsynth]); 
	mxcmds(0x35, right[Vsynth]); 
1995/0119    
 
	mxcmdt(0x38, audio.left.line); 
	mxcmdt(0x39, audio.right.line); 
1995/0221    
	mxcmds(0x36, left[Vcd]); 
	mxcmds(0x37, right[Vcd]); 
1995/0119    
 
	mxcmdt(0x3a, audio.mic); 
	mxcmdt(0x3b, audio.speaker); 
1995/0221    
	mxcmds(0x38, left[Vline]); 
	mxcmds(0x39, right[Vline]); 
1995/0119    
 
	mxcmds(0x3f, audio.left.igain); 
	mxcmds(0x40, audio.right.igain); 
	mxcmds(0x41, audio.left.ogain); 
	mxcmds(0x42, audio.right.ogain); 
1995/0221    
	mxcmds(0x3a, left[Vmic]); 
	mxcmds(0x3b, left[Vspeaker]); 
1995/0119    
 
	mxcmdu(0x44, audio.left.treb); 
	mxcmdu(0x45, audio.right.treb); 
1995/0221    
	mxcmdu(0x44, left[Vtreb]); 
	mxcmdu(0x45, right[Vtreb]); 
1995/0119    
 
	mxcmdu(0x46, audio.left.bass); 
	mxcmdu(0x47, audio.right.bass); 
1995/0221    
	mxcmdu(0x46, left[Vbass]); 
	mxcmdu(0x47, right[Vbass]); 
1995/0119    
 
	mxcmd(0x3c, audio.oswitch); 
	mxcmd(0x3d, audio.left.iswitch); 
	mxcmd(0x3e, audio.right.iswitch); 
1995/0221    
	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 */ 
1995/0214    
	iunlock(&blaster); 
1995/0119    
} 
 
1995/0217/sys/src/9/port/devaudio.c:337,3511995/0221/sys/src/9/port/devaudio.c:354,372
1995/0119    
startdma(void) 
{ 
	ulong count; 
1995/0221    
	int speed; 
1995/0119    
 
1995/0214    
	ilock(&blaster); 
	dmaend(Dma); 
	if(audio.amode == Aread) 
1995/0221    
	if(audio.amode == Aread) { 
1995/0119    
		sbcmd(0x42);			/* input sampling rate */ 
1995/0214    
	else 
1995/0221    
		speed = audio.livol[Vspeed]; 
	} else { 
1995/0119    
		sbcmd(0x41);			/* output sampling rate */ 
	sbcmd(audio.speed>>8); 
	sbcmd(audio.speed); 
1995/0221    
		speed = audio.lovol[Vspeed]; 
	} 
	sbcmd(speed>>8); 
	sbcmd(speed); 
1995/0119    
 
	count = (Bufsize >> 1) - 1; 
	if(audio.amode == Aread) 
1995/0217/sys/src/9/port/devaudio.c:479,4861995/0221/sys/src/9/port/devaudio.c:500,509
1995/0119    
	int i; 
 
	for(i=0; volumes[i].name; i++) { 
		*volumes[i].ptr1 = volumes[i].ilval; 
		*volumes[i].ptr2 = volumes[i].irval; 
1995/0221    
		audio.lovol[i] = volumes[i].ilval; 
		audio.rovol[i] = volumes[i].irval; 
		audio.livol[i] = volumes[i].ilval; 
		audio.rivol[i] = volumes[i].irval; 
1995/0119    
	} 
} 
 
1995/0217/sys/src/9/port/devaudio.c:629,6341995/0221/sys/src/9/port/devaudio.c:652,658
1995/0119    
		setempty(); 
		audio.curcount = 0; 
1995/0214    
		qunlock(&audio); 
1995/0221    
		mxvolume(); 
1995/0119    
		break; 
	} 
	c = devopen(c, omode, audiodir, NPORT, devgen); 
1995/0217/sys/src/9/port/devaudio.c:684,6911995/0221/sys/src/9/port/devaudio.c:708,716
1995/0119    
long 
audioread(Chan *c, char *a, long n, ulong offset) 
{ 
	long m, o, n0, bn; 
	char buf[256]; 
1995/0221    
	int liv, riv, lov, rov; 
	long m, n0; 
	char buf[300]; 
1995/0119    
	Buf *b; 
	int j; 
 
1995/0217/sys/src/9/port/devaudio.c:737,7541995/0221/sys/src/9/port/devaudio.c:762,797
1995/0119    
 
	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); 
1995/0221    
		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); 
				} 
1995/0119    
			} 
1995/0221    
			j += snprint(buf+j, sizeof(buf)-j, "\n"); 
1995/0119    
		} 
 
		return readstr(offset, a, n, buf); 
1995/0217/sys/src/9/port/devaudio.c:766,7721995/0221/sys/src/9/port/devaudio.c:809,815
1995/0119    
audiowrite(Chan *c, char *a, long n, ulong offset) 
{ 
	long m, n0; 
	int i, nf, v, left, right; 
1995/0221    
	int i, nf, v, left, right, in, out; 
1995/0119    
	char buf[255], *field[Ncmd]; 
	Buf *b; 
 
1995/0217/sys/src/9/port/devaudio.c:779,7871995/0221/sys/src/9/port/devaudio.c:822,832
1995/0119    
		break; 
 
	case Qvolume: 
		v = 0; 
1995/0221    
		v = Vaudio; 
1995/0119    
		left = 1; 
		right = 1; 
1995/0221    
		in = 1; 
		out = 1; 
1995/0119    
		if(n > sizeof(buf)-1) 
			n = sizeof(buf)-1; 
		memmove(buf, a, n); 
1995/0217/sys/src/9/port/devaudio.c:794,8031995/0221/sys/src/9/port/devaudio.c:839,852
1995/0119    
			 */ 
			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; 
1995/0221    
				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; 
1995/0119    
				mxvolume(); 
				goto cont0; 
			} 
1995/0217/sys/src/9/port/devaudio.c:805,8101995/0221/sys/src/9/port/devaudio.c:854,863
1995/0119    
			for(m=0; volumes[m].name; m++) { 
				if(strcmp(field[i], volumes[m].name) == 0) { 
					v = m; 
1995/0221    
					in = 1; 
					out = 1; 
					left = 1; 
					right = 1; 
1995/0119    
					goto cont0; 
				} 
			} 
1995/0217/sys/src/9/port/devaudio.c:814,8191995/0221/sys/src/9/port/devaudio.c:867,882
1995/0119    
				mxvolume(); 
				goto cont0; 
			} 
1995/0221    
			if(strcmp(field[i], "in") == 0) { 
				in = 1; 
				out = 0; 
				goto cont0; 
			} 
			if(strcmp(field[i], "out") == 0) { 
				in = 0; 
				out = 1; 
				goto cont0; 
			} 
1995/0119    
			if(strcmp(field[i], "left") == 0) { 
				left = 1; 
				right = 0; 
1995/0217/sys/src/9/port/devaudio.c:821,8311995/0221/sys/src/9/port/devaudio.c:884,889
1995/0119    
			} 
			if(strcmp(field[i], "right") == 0) { 
				left = 0; 
				right = 1; 
				goto cont0; 
			} 
			if(strcmp(field[i], "both") == 0) { 
				left = 1; 
				right = 1; 
				goto cont0; 
			} 
1995/0221/sys/src/9/port/devaudio.c:420,4281995/0804/sys/src/9/port/devaudio.c:420,427 (short | long)
1995/0119    
} 
 
void 
1995/0214    
pcaudiosbintr(Ureg *ureg, void *rock) 
1995/0804    
pcaudiosbintr(Ureg*, void*) 
1995/0214    
{ 
	USED(ureg, rock); 
/*	print("sb16 audio interrupt\n");	/**/ 
	audiosbintr(); 
} 
1995/0221/sys/src/9/port/devaudio.c:434,4421995/0804/sys/src/9/port/devaudio.c:433,440
1995/0119    
} 
 
static int 
anybuf(void *p) 
1995/0804    
anybuf(void*) 
1995/0119    
{ 
	USED(p); 
	return audio.intr; 
} 
 
1995/0221/sys/src/9/port/devaudio.c:664,6761995/0804/sys/src/9/port/devaudio.c:662,669
1995/0119    
} 
 
void 
audiocreate(Chan *c, char *name, int omode, ulong perm) 
1995/0804    
audiocreate(Chan*, char*, int, ulong) 
1995/0119    
{ 
	USED(c); 
	USED(name); 
	USED(omode); 
	USED(perm); 
                 
	error(Eperm); 
} 
 
1995/0221/sys/src/9/port/devaudio.c:806,8121995/0804/sys/src/9/port/devaudio.c:799,805
1995/0119    
} 
 
long 
audiowrite(Chan *c, char *a, long n, ulong offset) 
1995/0804    
audiowrite(Chan *c, char *a, long n, ulong) 
1995/0119    
{ 
	long m, n0; 
1995/0221    
	int i, nf, v, left, right, in, out; 
1995/0221/sys/src/9/port/devaudio.c:813,8201995/0804/sys/src/9/port/devaudio.c:806,811
1995/0119    
	char buf[255], *field[Ncmd]; 
	Buf *b; 
 
	USED(offset); 
                 
	n0 = n; 
	switch(c->qid.path & ~CHDIR) { 
	default: 
1995/0221/sys/src/9/port/devaudio.c:941,9591995/0804/sys/src/9/port/devaudio.c:932,945
1995/0119    
} 
 
void 
audioremove(Chan *c) 
1995/0804    
audioremove(Chan*) 
1995/0119    
{ 
	USED(c); 
                 
	error(Eperm); 
} 
 
void 
audiowstat(Chan *c, char *dp) 
1995/0804    
audiowstat(Chan*, char*) 
1995/0119    
{ 
	USED(c); 
	USED(dp); 
                 
	error(Eperm); 
} 
 
1995/0804/sys/src/9/port/devaudio.c:7,131996/0223/sys/src/9/port/devaudio.c:7,12 (short | long)
1995/0119    
#include	"dat.h" 
#include	"fns.h" 
#include	"../port/error.h" 
#include	"devtab.h" 
#include	"io.h" 
#include	"audio.h" 
 
1996/0223/sys/src/9/port/devaudio.c:822,8281996/0315/sys/src/9/port/devaudio.c:822,828 (short | long)
1995/0119    
		memmove(buf, a, n); 
		buf[n] = '\0'; 
 
		nf = getfields(buf, field, Ncmd, " \t\n"); 
1996/0315    
		nf = parsefields(buf, field, Ncmd, " \t\n"); 
1995/0119    
		for(i = 0; i < nf; i++){ 
			/* 
			 * a number is volume 
1996/0315/sys/src/9/port/devaudio.c:121,1311996/1024/sys/src/9/port/devaudio.c:121,132 (short | long)
1995/0214    
	int	clri8; 
	int	clri16; 
	int	clri401; 
1996/1024    
	int	dma; 
1995/0214    
} blaster; 
 
1995/0119    
static	void	swab(uchar*); 
 
1995/0214    
static	char	Emajor[]	= "SoundBlaster version too old"; 
1996/1024    
static	char	Emajor[]	= "soundblaster not responding/wrong version"; 
1995/0119    
static	char	Emode[]		= "illegal open mode"; 
static	char	Evolume[]	= "illegal volume specifier"; 
 
1996/0315/sys/src/9/port/devaudio.c:334,3441996/1024/sys/src/9/port/devaudio.c:335,345
1995/0119    
	if(b == 0) 
		goto shutdown; 
 
1995/0214    
	dmasetup(Dma, b->virt, Bufsize, audio.amode == Aread); 
1996/1024    
	dmasetup(blaster.dma, b->virt, Bufsize, audio.amode == Aread); 
1995/0119    
	return; 
 
shutdown: 
1995/0214    
	dmaend(Dma); 
1996/1024    
	dmaend(blaster.dma); 
1995/0119    
	sbcmd(0xd9);				/* exit at end of count */ 
	sbcmd(0xd5);				/* pause */ 
	audio.curcount = 0; 
1996/0315/sys/src/9/port/devaudio.c:356,3621996/1024/sys/src/9/port/devaudio.c:357,363
1995/0221    
	int speed; 
1995/0119    
 
1995/0214    
	ilock(&blaster); 
	dmaend(Dma); 
1996/1024    
	dmaend(blaster.dma); 
1995/0221    
	if(audio.amode == Aread) { 
1995/0119    
		sbcmd(0x42);			/* input sampling rate */ 
1995/0221    
		speed = audio.livol[Vspeed]; 
1996/0315/sys/src/9/port/devaudio.c:511,5161996/1024/sys/src/9/port/devaudio.c:512,518
1995/0119    
	int i; 
 
1995/0214    
	sbconf.port = 0x220; 
1996/1024    
	sbconf.dma = 5; 
1995/0214    
	sbconf.irq = 7; 
	if(isaconfig("audio", 0, &sbconf) == 0) 
		return; 
1996/0315/sys/src/9/port/devaudio.c:523,5291996/1024/sys/src/9/port/devaudio.c:525,531
1995/0214    
	case 0x280: 
		break; 
	default: 
		print("bad sb16 port 0x%x\n", sbconf.port); 
1996/1024    
		print("devaudio: bad sb16 port 0x%x\n", sbconf.port); 
1995/0214    
		return; 
	} 
	switch(sbconf.irq){ 
1996/0315/sys/src/9/port/devaudio.c:533,5421996/1024/sys/src/9/port/devaudio.c:535,546
1995/0214    
	case 10: 
		break; 
	default: 
		print("bad sb16 irq %d\n", sbconf.irq); 
1996/1024    
		print("devaudio: bad sb16 irq %d\n", sbconf.irq); 
1995/0214    
		return; 
	} 
 
1996/1024    
	blaster.dma = sbconf.dma; 
 
1995/0214    
	blaster.reset = sbconf.port + 0x6; 
	blaster.read = sbconf.port + 0xa; 
	blaster.write = sbconf.port + 0xc; 
1996/0315/sys/src/9/port/devaudio.c:548,5541996/1024/sys/src/9/port/devaudio.c:552,558
1995/0214    
	blaster.clri16 = sbconf.port + 0xf; 
	blaster.clri401 = sbconf.port + 0x100; 
 
1995/0119    
	seteisadma(Dma, audiodmaintr); 
1996/1024    
	seteisadma(blaster.dma, audiodmaintr); 
1995/0214    
	setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0); 
1995/0119    
 
1995/0214    
	audio.amode = Aclosed; 
1996/0315/sys/src/9/port/devaudio.c:570,5761996/1024/sys/src/9/port/devaudio.c:574,580
1995/0119    
	audio.minor = sbread(); 
 
	if(audio.major != 4) { 
		print("bad soundblaster model #%.2x #.2x\n", audio.major, audio.minor); 
1996/1024    
		print("bad soundblaster model #%.2x #%.2x; not SB 16\n", audio.major, audio.minor); 
1995/0119    
		return; 
	} 
	/* 
1996/0315/sys/src/9/port/devaudio.c:588,5941996/1024/sys/src/9/port/devaudio.c:592,598
1995/0214    
		(sbconf.irq==7)? 4: 
		(sbconf.irq==10)? 8: 
1995/0119    
		0); 
	mxcmd(0x81, 1<<Dma);	/* dma */ 
1996/1024    
	mxcmd(0x81, 1<<blaster.dma);	/* dma */ 
1995/0119    
} 
 
Chan* 
1996/1024/sys/src/9/port/devaudio.c:512,5181996/1025/sys/src/9/port/devaudio.c:512,518 (short | long)
1995/0119    
	int i; 
 
1995/0214    
	sbconf.port = 0x220; 
1996/1024    
	sbconf.dma = 5; 
1996/1025    
	sbconf.dma = Dma; 
1995/0214    
	sbconf.irq = 7; 
	if(isaconfig("audio", 0, &sbconf) == 0) 
		return; 
1996/1025/sys/src/9/port/devaudio.c:10,171997/0327/sys/src/9/port/devaudio.c:10,15 (short | long)
1995/0119    
#include	"io.h" 
#include	"audio.h" 
 
#define	NPORT		(sizeof audiodir/sizeof(Dirtab)) 
                 
1995/0217    
typedef struct	AQueue	AQueue; 
1995/0119    
typedef struct	Buf	Buf; 
 
1996/1025/sys/src/9/port/devaudio.c:94,1031997/0327/sys/src/9/port/devaudio.c:92,101
1995/0119    
	int	irval; 
} volumes[] = 
{ 
1995/0221    
[Vaudio]		"audio",		Fout, 		50,	50, 
[Vsynth]		"synth",		Fin|Fout,		0,	0, 
[Vcd]		"cd",		Fin|Fout,		0,	0, 
[Vline]		"line",		Fin|Fout,		0,	0, 
1997/0327    
[Vaudio]	"audio",	Fout, 		50,	50, 
[Vsynth]	"synth",	Fin|Fout,	0,	0, 
[Vcd]		"cd",		Fin|Fout,	0,	0, 
[Vline]		"line",		Fin|Fout,	0,	0, 
1995/0221    
[Vmic]		"mic",		Fin|Fout|Fmono,	0,	0, 
[Vspeaker]	"speaker",	Fout|Fmono,	0,	0, 
1995/0119    
 
1996/1025/sys/src/9/port/devaudio.c:104,1111997/0327/sys/src/9/port/devaudio.c:102,109
1995/0221    
[Vtreb]		"treb",		Fout, 		50,	50, 
[Vbass]		"bass",		Fout, 		50,	50, 
1995/0119    
 
1995/0221    
[Vspeed]		"speed",		Fin|Fout|Fmono,	Speed,	Speed, 
1995/0119    
	0 
1997/0327    
[Vspeed]	"speed",	Fin|Fout|Fmono,	Speed,	Speed, 
		0 
1995/0119    
}; 
 
1995/0214    
static struct 
1996/1025/sys/src/9/port/devaudio.c:142,1481997/0327/sys/src/9/port/devaudio.c:140,146
1995/0119    
			return 0; 
		} 
	} 
/*	print("SB16 sbcmd (#%.2x) timeout\n", val);	/**/ 
1997/0327    
/*	print("#A: sbcmd (#%.2x) timeout\n", val);	/**/ 
1995/0119    
	return 1; 
} 
 
1996/1025/sys/src/9/port/devaudio.c:157,1631997/0327/sys/src/9/port/devaudio.c:155,161
1995/0214    
			return inb(blaster.read); 
1995/0119    
		} 
	} 
/*	print("SB16 sbread did not respond\n");	/**/ 
1997/0327    
/*	print("#A: sbread did not respond\n");	/**/ 
1995/0119    
	return 0xbb; 
} 
 
1996/1025/sys/src/9/port/devaudio.c:422,4281997/0327/sys/src/9/port/devaudio.c:420,426
1995/0119    
void 
1995/0804    
pcaudiosbintr(Ureg*, void*) 
1995/0214    
{ 
/*	print("sb16 audio interrupt\n");	/**/ 
1997/0327    
/*	print("#A: audio interrupt\n");	/**/ 
1995/0214    
	audiosbintr(); 
} 
 
1996/1025/sys/src/9/port/devaudio.c:429,4351997/0327/sys/src/9/port/devaudio.c:427,433
1995/0214    
void 
1995/0119    
audiodmaintr(void) 
{ 
/*	print("sb16 dma interrupt\n");	/**/ 
1997/0327    
/*	print("#A: dma interrupt\n");	/**/ 
1995/0119    
} 
 
static int 
1996/1025/sys/src/9/port/devaudio.c:450,4561997/0327/sys/src/9/port/devaudio.c:448,454
1995/0119    
	pokeaudio(); 
	tsleep(&audio.vous, anybuf, 0, 10*1000); 
	if(audio.intr == 0) { 
1995/0216    
/*		print("audio timeout\n");	/**/ 
1997/0327    
/*		print("#A: audio timeout\n");	/**/ 
1995/0119    
		audio.active = 0; 
		pokeaudio(); 
	} 
1996/1025/sys/src/9/port/devaudio.c:487,4971997/0327/sys/src/9/port/devaudio.c:485,490
1995/0214    
	iunlock(&blaster); 
1995/0119    
} 
 
void 
audioreset(void) 
{ 
} 
                 
static	void 
resetlevel(void) 
{ 
1996/1025/sys/src/9/port/devaudio.c:505,5111997/0327/sys/src/9/port/devaudio.c:498,504
1995/0119    
	} 
} 
 
void 
1997/0327    
static void 
1995/0119    
audioinit(void) 
{ 
1995/0214    
	ISAConf sbconf; 
1996/1025/sys/src/9/port/devaudio.c:525,5311997/0327/sys/src/9/port/devaudio.c:518,524
1995/0214    
	case 0x280: 
		break; 
	default: 
1996/1024    
		print("devaudio: bad sb16 port 0x%x\n", sbconf.port); 
1997/0327    
		print("#A: bad port 0x%x\n", sbconf.port); 
1995/0214    
		return; 
	} 
	switch(sbconf.irq){ 
1996/1025/sys/src/9/port/devaudio.c:535,5461997/0327/sys/src/9/port/devaudio.c:528,537
1995/0214    
	case 10: 
		break; 
	default: 
1996/1024    
		print("devaudio: bad sb16 irq %d\n", sbconf.irq); 
1997/0327    
		print("#A: bad irq %d\n", sbconf.irq); 
1995/0214    
		return; 
	} 
 
1996/1024    
	blaster.dma = sbconf.dma; 
                 
1995/0214    
	blaster.reset = sbconf.port + 0x6; 
	blaster.read = sbconf.port + 0xa; 
	blaster.write = sbconf.port + 0xc; 
1996/1025/sys/src/9/port/devaudio.c:551,5561997/0327/sys/src/9/port/devaudio.c:542,548
1995/0214    
	blaster.clri8 = sbconf.port + 0xe; 
	blaster.clri16 = sbconf.port + 0xf; 
	blaster.clri401 = sbconf.port + 0x100; 
1997/0327    
	blaster.dma = sbconf.dma; 
1995/0214    
 
1996/1024    
	seteisadma(blaster.dma, audiodmaintr); 
1995/0214    
	setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0); 
1996/1025/sys/src/9/port/devaudio.c:565,5711997/0327/sys/src/9/port/devaudio.c:557,563
1995/0119    
 
	i = sbread(); 
	if(i != 0xaa) { 
		print("sound blaster didnt respond #%.2x\n", i); 
1997/0327    
		print("#A: no response #%.2x\n", i); 
1995/0119    
		return; 
	} 
 
1996/1025/sys/src/9/port/devaudio.c:574,5801997/0327/sys/src/9/port/devaudio.c:566,572
1995/0119    
	audio.minor = sbread(); 
 
	if(audio.major != 4) { 
1996/1024    
		print("bad soundblaster model #%.2x #%.2x; not SB 16\n", audio.major, audio.minor); 
1997/0327    
		print("#A: model #%.2x #%.2x; not SB 16\n", audio.major, audio.minor); 
1995/0119    
		return; 
	} 
	/* 
1996/1025/sys/src/9/port/devaudio.c:595,6251997/0327/sys/src/9/port/devaudio.c:587,611
1996/1024    
	mxcmd(0x81, 1<<blaster.dma);	/* dma */ 
1995/0119    
} 
 
Chan* 
1997/0327    
static Chan* 
1995/0119    
audioattach(char *param) 
{ 
	return devattach('A', param); 
} 
 
Chan* 
audioclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
                 
int 
1997/0327    
static int 
1995/0119    
audiowalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, audiodir, NPORT, devgen); 
1997/0327    
	return devwalk(c, name, audiodir, nelem(audiodir), devgen); 
1995/0119    
} 
 
void 
1997/0327    
static void 
1995/0119    
audiostat(Chan *c, char *db) 
{ 
	devstat(c, db, audiodir, NPORT, devgen); 
1997/0327    
	devstat(c, db, audiodir, nelem(audiodir), devgen); 
1995/0119    
} 
 
Chan* 
1997/0327    
static Chan* 
1995/0119    
audioopen(Chan *c, int omode) 
{ 
1995/0214    
	int amode; 
1996/1025/sys/src/9/port/devaudio.c:656,6621997/0327/sys/src/9/port/devaudio.c:642,648
1995/0221    
		mxvolume(); 
1995/0119    
		break; 
	} 
	c = devopen(c, omode, audiodir, NPORT, devgen); 
1997/0327    
	c = devopen(c, omode, audiodir, nelem(audiodir), devgen); 
1995/0119    
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
1996/1025/sys/src/9/port/devaudio.c:664,6761997/0327/sys/src/9/port/devaudio.c:650,656
1995/0119    
	return c; 
} 
 
void 
1995/0804    
audiocreate(Chan*, char*, int, ulong) 
1995/0119    
{ 
	error(Eperm); 
} 
                 
void 
1997/0327    
static void 
1995/0119    
audioclose(Chan *c) 
{ 
 
1996/1025/sys/src/9/port/devaudio.c:701,7071997/0327/sys/src/9/port/devaudio.c:681,687
1995/0119    
	} 
} 
 
long 
1997/0327    
static long 
1995/0119    
audioread(Chan *c, char *a, long n, ulong offset) 
{ 
1995/0221    
	int liv, riv, lov, rov; 
1996/1025/sys/src/9/port/devaudio.c:717,7231997/0327/sys/src/9/port/devaudio.c:697,703
1995/0119    
		break; 
 
	case Qdir: 
		return devdirread(c, a, n, audiodir, NPORT, devgen); 
1997/0327    
		return devdirread(c, a, n, audiodir, nelem(audiodir), devgen); 
1995/0119    
 
	case Qaudio: 
		if(audio.amode != Aread) 
1996/1025/sys/src/9/port/devaudio.c:795,8071997/0327/sys/src/9/port/devaudio.c:775,781
1995/0119    
	return n0-n; 
} 
 
Block* 
audiobread(Chan *c, long n, ulong offset) 
{ 
	return devbread(c, n, offset); 
} 
                 
long 
1997/0327    
static long 
1995/0804    
audiowrite(Chan *c, char *a, long n, ulong) 
1995/0119    
{ 
	long m, n0; 
1996/1025/sys/src/9/port/devaudio.c:928,9511997/0327/sys/src/9/port/devaudio.c:902,907
1995/0119    
	return n0 - n; 
} 
 
long 
audiobwrite(Chan *c, Block *bp, ulong offset) 
{ 
	return devbwrite(c, bp, offset); 
} 
                 
void 
1995/0804    
audioremove(Chan*) 
1995/0119    
{ 
	error(Eperm); 
} 
                 
void 
1995/0804    
audiowstat(Chan*, char*) 
1995/0119    
{ 
	error(Eperm); 
} 
                 
static	void 
swab(uchar *a) 
{ 
1996/1025/sys/src/9/port/devaudio.c:963,9651997/0327/sys/src/9/port/devaudio.c:919,939
1995/0119    
		*p++ = b; 
	} 
} 
1997/0327    
 
Dev audiodevtab = { 
	devreset, 
	audioinit, 
	audioattach, 
	devclone, 
	audiowalk, 
	audiostat, 
	audioopen, 
	devcreate, 
	audioclose, 
	audioread, 
	devbread, 
	audiowrite, 
	devbwrite, 
	devremove, 
	devwstat, 
}; 
1997/0327/sys/src/9/port/devaudio.c:921,9261997/0408/sys/src/9/port/devaudio.c:921,929 (short | long)
1995/0119    
} 
1997/0327    
 
Dev audiodevtab = { 
1997/0408    
	'A', 
	"audio", 
 
1997/0327    
	devreset, 
	audioinit, 
	audioattach, 
1997/0408/sys/src/9/port/devaudio.c:120,1251998/0317/sys/src/9/port/devaudio.c:120,128 (short | long)
1995/0214    
	int	clri16; 
	int	clri401; 
1996/1024    
	int	dma; 
1998/0317    
 
	void	(*startdma)(void); 
	void	(*intr)(void); 
1995/0214    
} blaster; 
 
1995/0119    
static	void	swab(uchar*); 
1997/0408/sys/src/9/port/devaudio.c:140,1461998/0317/sys/src/9/port/devaudio.c:143,149
1995/0119    
			return 0; 
		} 
	} 
1997/0327    
/*	print("#A: sbcmd (#%.2x) timeout\n", val);	/**/ 
1998/0317    
/*	print("#A: sbcmd (0x%.2x) timeout\n", val);	/**/ 
1995/0119    
	return 1; 
} 
 
1997/0408/sys/src/9/port/devaudio.c:156,1641998/0317/sys/src/9/port/devaudio.c:159,185
1995/0119    
		} 
	} 
1997/0327    
/*	print("#A: sbread did not respond\n");	/**/ 
1995/0119    
	return 0xbb; 
1998/0317    
	return -1; 
1995/0119    
} 
 
1998/0317    
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(); 
} 
 
1995/0119    
static	int 
mxcmd(int addr, int val) 
{ 
1997/0408/sys/src/9/port/devaudio.c:321,3311998/0317/sys/src/9/port/devaudio.c:342,352
1995/0119    
 
	b = audio.current; 
	if(audio.amode == Aread) { 
		if(b)	/* shouldnt happen */ 
1998/0317    
		if(b)	/* shouldn't happen */ 
1995/0119    
			putbuf(&audio.full, b); 
		b = getbuf(&audio.empty); 
	} else { 
		if(b)	/* shouldnt happen */ 
1998/0317    
		if(b)	/* shouldn't happen */ 
1995/0119    
			putbuf(&audio.empty, b); 
		b = getbuf(&audio.full); 
	} 
1997/0408/sys/src/9/port/devaudio.c:333,3401998/0317/sys/src/9/port/devaudio.c:354,363
1995/0119    
	if(b == 0) 
		goto shutdown; 
 
1996/1024    
	dmasetup(blaster.dma, b->virt, Bufsize, audio.amode == Aread); 
1995/0119    
	return; 
1998/0317    
	if(dmasetup(blaster.dma, b->virt, Bufsize, audio.amode == Aread) >= 0) 
		return; 
	print("#A: dmasetup fail\n"); 
	putbuf(&audio.empty, b); 
1995/0119    
 
shutdown: 
1996/1024    
	dmaend(blaster.dma); 
1997/0408/sys/src/9/port/devaudio.c:349,3551998/0317/sys/src/9/port/devaudio.c:372,378
1995/0119    
 * start first dma 
 */ 
static	void 
startdma(void) 
1998/0317    
sb16startdma(void) 
1995/0119    
{ 
	ulong count; 
1995/0221    
	int speed; 
1997/0408/sys/src/9/port/devaudio.c:380,3851998/0317/sys/src/9/port/devaudio.c:403,499
1995/0214    
	iunlock(&blaster); 
1995/0119    
} 
 
1998/0317    
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); 
} 
 
1995/0119    
/* 
 * if audio is stopped, 
 * start it up again. 
1997/0408/sys/src/9/port/devaudio.c:388,3981998/0317/sys/src/9/port/devaudio.c:502,512
1995/0119    
pokeaudio(void) 
{ 
	if(!audio.active) 
		startdma(); 
1998/0317    
		blaster.startdma(); 
1995/0119    
} 
 
void 
audiosbintr(void) 
1998/0317    
static void 
sb16intr(void) 
1995/0119    
{ 
	int stat, dummy; 
 
1997/0408/sys/src/9/port/devaudio.c:417,4271998/0317/sys/src/9/port/devaudio.c:531,570
1995/0119    
	} 
} 
 
1998/0317    
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"); 
} 
 
1995/0119    
void 
1998/0317    
audiosbintr(void) 
{ 
	/* 
	 * Carrera interrupt interface. 
	 */ 
	blaster.intr(); 
} 
 
static void 
1995/0804    
pcaudiosbintr(Ureg*, void*) 
1995/0214    
{ 
1997/0327    
/*	print("#A: audio interrupt\n");	/**/ 
1995/0214    
	audiosbintr(); 
1998/0317    
	/* 
	 * x86 interrupt interface. 
	 */ 
	blaster.intr(); 
1995/0214    
} 
 
void 
1997/0408/sys/src/9/port/devaudio.c:498,5031998/0317/sys/src/9/port/devaudio.c:641,708
1995/0119    
	} 
} 
 
1998/0317    
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; 
} 
 
1997/0327    
static void 
1995/0119    
audioinit(void) 
{ 
1997/0408/sys/src/9/port/devaudio.c:509,5151998/0317/sys/src/9/port/devaudio.c:714,720
1995/0214    
	sbconf.irq = 7; 
	if(isaconfig("audio", 0, &sbconf) == 0) 
		return; 
	if(strcmp(sbconf.type, "sb16") != 0) 
1998/0317    
	if(cistrcmp(sbconf.type, "sb16") != 0 && cistrcmp(sbconf.type, "ess1688") != 0) 
1995/0214    
		return; 
	switch(sbconf.port){ 
	case 0x220: 
1997/0408/sys/src/9/port/devaudio.c:544,5491998/0317/sys/src/9/port/devaudio.c:749,757
1995/0214    
	blaster.clri401 = sbconf.port + 0x100; 
1997/0327    
	blaster.dma = sbconf.dma; 
1995/0214    
 
1998/0317    
	blaster.startdma = sb16startdma; 
	blaster.intr = sb16intr; 
 
1996/1024    
	seteisadma(blaster.dma, audiodmaintr); 
1995/0214    
	setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0); 
1995/0119    
 
1997/0408/sys/src/9/port/devaudio.c:566,5741998/0317/sys/src/9/port/devaudio.c:774,787
1995/0119    
	audio.minor = sbread(); 
 
	if(audio.major != 4) { 
1997/0327    
		print("#A: model #%.2x #%.2x; not SB 16\n", audio.major, audio.minor); 
1995/0119    
		return; 
1998/0317    
		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; 
1995/0119    
	} 
1998/0317    
	 
1995/0119    
	/* 
	 * initialize the mixer 
	 */ 
1998/0317/sys/src/9/port/devaudio.c:895,9011998/0319/sys/src/9/port/devaudio.c:895,901 (short | long)
Change dev read and write to use vlong offset.
rsc Fri Mar 4 12:44:25 2005
1995/0119    
} 
 
1997/0327    
static long 
1995/0119    
audioread(Chan *c, char *a, long n, ulong offset) 
1998/0319    
audioread(Chan *c, char *a, long n, vlong off) 
1995/0119    
{ 
1995/0221    
	int liv, riv, lov, rov; 
	long m, n0; 
1998/0317/sys/src/9/port/devaudio.c:902,9071998/0319/sys/src/9/port/devaudio.c:902,908
1995/0221    
	char buf[300]; 
1995/0119    
	Buf *b; 
	int j; 
1998/0319    
	ulong offset = off; 
1995/0119    
 
	n0 = n; 
	switch(c->qid.path & ~CHDIR) { 
1998/0317/sys/src/9/port/devaudio.c:989,9951998/0319/sys/src/9/port/devaudio.c:990,996
1995/0119    
} 
 
1997/0327    
static long 
1995/0804    
audiowrite(Chan *c, char *a, long n, ulong) 
1998/0319    
audiowrite(Chan *c, char *a, long n, vlong) 
1995/0119    
{ 
	long m, n0; 
1995/0221    
	int i, nf, v, left, right, in, out; 
1998/0319/sys/src/9/port/devaudio.c:964,9831998/0327/sys/src/9/port/devaudio.c:964,989 (short | long)
Formatting edits.
rsc Fri Mar 4 12:44:25 2005
1995/0221    
					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); 
1998/0327    
						j += snprint(buf+j, sizeof(buf)-j, 
						" in %d", liv); 
1995/0221    
					if(volumes[m].flag & Fout) 
						j += snprint(buf+j, sizeof(buf)-j, " out %d", lov); 
1998/0327    
						j += snprint(buf+j, sizeof(buf)-j, 
						" out %d", lov); 
1995/0221    
				} 
			}else{ 
				if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov && riv==rov) 
					j += snprint(buf+j, sizeof(buf)-j, " left %d right %d", 
1998/0327    
				if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && 
				    liv==lov && riv==rov) 
					j += snprint(buf+j, sizeof(buf)-j, 
						" left %d right %d", 
1995/0221    
						liv, riv); 
				else{ 
					if(volumes[m].flag & Fin) 
						j += snprint(buf+j, sizeof(buf)-j, " in left %d right %d", 
1998/0327    
						j += snprint(buf+j, sizeof(buf)-j, 
							" in left %d right %d", 
1995/0221    
							liv, riv); 
					if(volumes[m].flag & Fout) 
						j += snprint(buf+j, sizeof(buf)-j, " out left %d right %d", 
1998/0327    
						j += snprint(buf+j, sizeof(buf)-j, 
							" out left %d right %d", 
1995/0221    
							lov, rov); 
				} 
1995/0119    
			} 
1998/0327/sys/src/9/port/devaudio.c:965,9741998/0331/sys/src/9/port/devaudio.c:965,974 (short | long)
Whitespace edit.
rsc Fri Mar 4 12:44:25 2005
1995/0221    
				else{ 
					if(volumes[m].flag & Fin) 
1998/0327    
						j += snprint(buf+j, sizeof(buf)-j, 
						" in %d", liv); 
1998/0331    
							" in %d", liv); 
1995/0221    
					if(volumes[m].flag & Fout) 
1998/0327    
						j += snprint(buf+j, sizeof(buf)-j, 
						" out %d", lov); 
1998/0331    
							" out %d", lov); 
1995/0221    
				} 
			}else{ 
1998/0327    
				if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && 
1998/0331/sys/src/9/port/devaudio.c:781,7871998/0512/sys/src/9/port/devaudio.c:781,787 (short | long)
Whitespace edit.
rsc Fri Mar 4 12:44:25 2005
1998/0317    
		} 
		audio.major = 4; 
1995/0119    
	} 
1998/0317    
	                 
1998/0512    
 
1995/0119    
	/* 
	 * initialize the mixer 
	 */ 
1998/0512/sys/src/9/port/devaudio.c:879,8841998/0603/sys/src/9/port/devaudio.c:879,896 (short | long)
Bug fix: flush final partial buffer on close of write fd.
rsc Fri Mar 4 12:44:25 2005
1995/0119    
	case Qaudio: 
		if(c->flag & COPEN) { 
1995/0214    
			qlock(&audio); 
1998/0603    
			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(); 
			} 
1995/0214    
			audio.amode = Aclosed; 
			if(waserror()){ 
				qunlock(&audio); 
1998/0603/sys/src/9/port/devaudio.c:866,8711998/0624/sys/src/9/port/devaudio.c:866,872 (short | long)
Formatting edit.
rsc Fri Mar 4 12:44:25 2005
1997/0327    
static void 
1995/0119    
audioclose(Chan *c) 
{ 
1998/0624    
	Buf *b; 
1995/0119    
 
	switch(c->qid.path & ~CHDIR) { 
	default: 
1998/0603/sys/src/9/port/devaudio.c:879,8941998/0624/sys/src/9/port/devaudio.c:880,895
1995/0119    
	case Qaudio: 
		if(c->flag & COPEN) { 
1995/0214    
			qlock(&audio); 
1998/0603    
			if (audio.amode == Awrite) { 
1998/0624    
			if(audio.amode == Awrite) { 
1998/0603    
				/* flush out last partial buffer */ 
				Buf *b = audio.filling; 
				if (b) { 
1998/0624    
				b = audio.filling; 
				if(b) { 
1998/0603    
					audio.filling = 0; 
					memset(b->virt, 0, Bufsize-audio.curcount); 
					swab(b->virt); 
					putbuf(&audio.full, b); 
				} 
				if (!audio.active && audio.full.first) 
1998/0624    
				if(!audio.active && audio.full.first) 
1998/0603    
					pokeaudio(); 
			} 
1995/0214    
			audio.amode = Aclosed; 
1998/0624/sys/src/9/port/devaudio.c:674,6801998/0825/sys/src/9/port/devaudio.c:674,680 (short | long)
Bug fix: print format.
rsc Fri Mar 4 12:44:25 2005
1998/0317    
		i = 0x50|(3<<2); 
		break; 
	default: 
		print("#A: bad ESS1688 irq %d\n", sbconf->irq); 
1998/0825    
		print("#A: bad ESS1688 irq %lud\n", sbconf->irq); 
1998/0317    
		return 1; 
	} 
	ess1688w(0xB1, i); 
1998/0624/sys/src/9/port/devaudio.c:690,6961998/0825/sys/src/9/port/devaudio.c:690,696
1998/0317    
		i = 0x50|(3<<2); 
		break; 
	default: 
		print("#A: bad ESS1688 dma %d\n", sbconf->dma); 
1998/0825    
		print("#A: bad ESS1688 dma %lud\n", sbconf->dma); 
1998/0317    
		return 1; 
	} 
	ess1688w(0xB2, i); 
1998/0624/sys/src/9/port/devaudio.c:723,7291998/0825/sys/src/9/port/devaudio.c:723,729
1995/0214    
	case 0x280: 
		break; 
	default: 
1997/0327    
		print("#A: bad port 0x%x\n", sbconf.port); 
1998/0825    
		print("#A: bad port 0x%lux\n", sbconf.port); 
1995/0214    
		return; 
	} 
	switch(sbconf.irq){ 
1998/0624/sys/src/9/port/devaudio.c:733,7391998/0825/sys/src/9/port/devaudio.c:733,739
1995/0214    
	case 10: 
		break; 
	default: 
1997/0327    
		print("#A: bad irq %d\n", sbconf.irq); 
1998/0825    
		print("#A: bad irq %lud\n", sbconf.irq); 
1995/0214    
		return; 
	} 
 
1998/0825/sys/src/9/port/devaudio.c:885,8911999/0219/sys/src/9/port/devaudio.c:885,891 (short | long)
1998/0624    
				b = audio.filling; 
				if(b) { 
1998/0603    
					audio.filling = 0; 
					memset(b->virt, 0, Bufsize-audio.curcount); 
1999/0219    
					memset(b->virt+audio.curcount, 0, Bufsize-audio.curcount); 
1998/0603    
					swab(b->virt); 
					putbuf(&audio.full, b); 
				} 
1999/0219/sys/src/9/port/devaudio.c:908,9141999/0320/sys/src/9/port/devaudio.c:908,914 (short | long)
1995/0119    
} 
 
1997/0327    
static long 
1998/0319    
audioread(Chan *c, char *a, long n, vlong off) 
1999/0320    
audioread(Chan *c, void *v, long n, vlong off) 
1995/0119    
{ 
1995/0221    
	int liv, riv, lov, rov; 
	long m, n0; 
1999/0219/sys/src/9/port/devaudio.c:916,9231999/0320/sys/src/9/port/devaudio.c:916,925
1995/0119    
	Buf *b; 
	int j; 
1998/0319    
	ulong offset = off; 
1999/0320    
	char *a; 
1995/0119    
 
	n0 = n; 
1999/0320    
	a = v; 
1995/0119    
	switch(c->qid.path & ~CHDIR) { 
	default: 
		error(Eperm); 
1999/0219/sys/src/9/port/devaudio.c:1009,10211999/0320/sys/src/9/port/devaudio.c:1011,1025
1995/0119    
} 
 
1997/0327    
static long 
1998/0319    
audiowrite(Chan *c, char *a, long n, vlong) 
1999/0320    
audiowrite(Chan *c, void *vp, long n, vlong) 
1995/0119    
{ 
	long m, n0; 
1995/0221    
	int i, nf, v, left, right, in, out; 
1995/0119    
	char buf[255], *field[Ncmd]; 
	Buf *b; 
1999/0320    
	char *a; 
1995/0119    
 
1999/0320    
	a = vp; 
1995/0119    
	n0 = n; 
	switch(c->qid.path & ~CHDIR) { 
	default: 
1999/0320/sys/src/9/port/devaudio.c:711,7171999/0504/sys/src/9/port/devaudio.c:711,717 (short | long)
1995/0119    
 
1995/0214    
	sbconf.port = 0x220; 
1996/1025    
	sbconf.dma = Dma; 
1995/0214    
	sbconf.irq = 7; 
1999/0504    
	sbconf.irq = IrqAUDIO; 
1995/0214    
	if(isaconfig("audio", 0, &sbconf) == 0) 
		return; 
1998/0317    
	if(cistrcmp(sbconf.type, "sb16") != 0 && cistrcmp(sbconf.type, "ess1688") != 0) 
1999/0504/sys/src/9/port/devaudio.c:18,231999/1005/sys/src/9/port/devaudio.c:18,24 (short | long)
1995/0119    
	Qdir		= 0, 
	Qaudio, 
	Qvolume, 
1999/1005    
	Qstatus, 
1995/0119    
 
	Fmono		= 1, 
1995/0221    
	Fin		= 2, 
1999/0504/sys/src/9/port/devaudio.c:47,521999/1005/sys/src/9/port/devaudio.c:48,54
1995/0119    
{ 
	"audio",	{Qaudio},		0,	0666, 
	"volume",	{Qvolume},		0,	0666, 
1999/1005    
	"audiostat",{Qstatus},		0,	0444, 
1995/0119    
}; 
 
struct	Buf 
1999/0504/sys/src/9/port/devaudio.c:76,811999/1005/sys/src/9/port/devaudio.c:78,85
1995/0221    
	int	lovol[Nvol]; 
1995/0119    
	int	major;		/* SB16 major version number (sb 4) */ 
	int	minor;		/* SB16 minor version number */ 
1999/1005    
	ulong	totcount;	/* how many bytes processed since open */ 
	vlong	tottime;	/* time at which totcount bytes were processed */ 
1995/0119    
 
	Buf	buf[Nbuf];	/* buffers and queues */ 
1995/0217    
	AQueue	empty; 
1999/0504/sys/src/9/port/devaudio.c:399,4041999/1005/sys/src/9/port/devaudio.c:403,409
1995/0119    
	sbcmd(count>>8); 
 
	audio.active = 1; 
1999/1005    
	audio.tottime = todget(nil); 
1995/0119    
	contindma(); 
1995/0214    
	iunlock(&blaster); 
1995/0119    
} 
1999/0504/sys/src/9/port/devaudio.c:490,4951999/1005/sys/src/9/port/devaudio.c:495,501
1998/0317    
	ess1688w(0xB8, x|0x05); 
 
	audio.active = 1; 
1999/1005    
	audio.tottime = todget(nil); 
1998/0317    
	contindma(); 
	iunlock(&blaster); 
} 
1999/0504/sys/src/9/port/devaudio.c:516,5211999/1005/sys/src/9/port/devaudio.c:522,529
1995/0119    
		if(stat & 2) { 
1995/0214    
			ilock(&blaster); 
			dummy = inb(blaster.clri16); 
1999/1005    
			audio.totcount += Bufsize; 
			audio.tottime = todget(nil); 
1995/0119    
			contindma(); 
1995/0214    
			iunlock(&blaster); 
1995/0119    
			audio.intr = 1; 
1999/0504/sys/src/9/port/devaudio.c:538,5431999/1005/sys/src/9/port/devaudio.c:546,553
1998/0317    
 
	if(audio.active){ 
		ilock(&blaster); 
1999/1005    
		audio.totcount += Bufsize; 
		audio.tottime = todget(nil); 
1998/0317    
		contindma(); 
		dummy = inb(blaster.clri8); 
		iunlock(&blaster); 
1999/0504/sys/src/9/port/devaudio.c:625,6301999/1005/sys/src/9/port/devaudio.c:635,642
1995/0119    
	audio.filling = 0; 
	for(i=0; i<Nbuf; i++) 
		putbuf(&audio.empty, &audio.buf[i]); 
1999/1005    
	audio.totcount = 0; 
	audio.tottime = 0LL; 
1995/0214    
	iunlock(&blaster); 
1995/0119    
} 
 
1999/0504/sys/src/9/port/devaudio.c:707,7131999/1005/sys/src/9/port/devaudio.c:719,726
1995/0119    
audioinit(void) 
{ 
1995/0214    
	ISAConf sbconf; 
1995/0119    
	int i; 
1999/1005    
	int i, x; 
	static int irq[] = {2,5,7,10}; 
1995/0119    
 
1995/0214    
	sbconf.port = 0x220; 
1996/1025    
	sbconf.dma = Dma; 
1999/0504/sys/src/9/port/devaudio.c:752,7601999/1005/sys/src/9/port/devaudio.c:765,770
1998/0317    
	blaster.startdma = sb16startdma; 
	blaster.intr = sb16intr; 
 
1996/1024    
	seteisadma(blaster.dma, audiodmaintr); 
1995/0214    
	setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0); 
1995/0119    
                 
1995/0214    
	audio.amode = Aclosed; 
1995/0119    
	resetlevel(); 
 
1999/0504/sys/src/9/port/devaudio.c:789,7951999/1005/sys/src/9/port/devaudio.c:799,811
1995/0119    
	mxvolume(); 
 
	/* 
	 * set up irq/dma chans 
1999/1005    
	 * 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. 
1995/0119    
	 */ 
	mxcmd(0x80,			/* irq */ 
1995/0214    
		(sbconf.irq==2)? 1: 
1999/0504/sys/src/9/port/devaudio.c:798,8031999/1005/sys/src/9/port/devaudio.c:814,836
1995/0214    
		(sbconf.irq==10)? 8: 
1995/0119    
		0); 
1996/1024    
	mxcmd(0x81, 1<<blaster.dma);	/* dma */ 
1999/1005    
 
	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); 
1995/0119    
} 
 
1997/0327    
static Chan* 
1999/0504/sys/src/9/port/devaudio.c:831,8361999/1005/sys/src/9/port/devaudio.c:864,872
1995/0119    
		error(Eperm); 
		break; 
 
1999/1005    
	case Qstatus: 
		if((omode&7) != OREAD) 
			error(Eperm); 
1995/0119    
	case Qvolume: 
	case Qdir: 
		break; 
1999/0504/sys/src/9/port/devaudio.c:875,8801999/1005/sys/src/9/port/devaudio.c:911,917
1995/0119    
 
	case Qdir: 
	case Qvolume: 
1999/1005    
	case Qstatus: 
1995/0119    
		break; 
 
	case Qaudio: 
1999/0504/sys/src/9/port/devaudio.c:965,9701999/1005/sys/src/9/port/devaudio.c:1002,1013
1995/0214    
		qunlock(&audio); 
1995/0119    
		break; 
 
1999/1005    
	case Qstatus: 
		buf[0] = 0; 
		snprint(buf, sizeof(buf), "bytes %lud\ntime %lld\n", 
			audio.totcount, audio.tottime); 
		return readstr(offset, a, n, buf); 
 
1995/0119    
	case Qvolume: 
		j = 0; 
1995/0221    
		buf[0] = 0; 
1999/0504/sys/src/9/port/devaudio.c:1004,10101999/1005/sys/src/9/port/devaudio.c:1047,1052
1995/0119    
			} 
1995/0221    
			j += snprint(buf+j, sizeof(buf)-j, "\n"); 
1995/0119    
		} 
                 
		return readstr(offset, a, n, buf); 
	} 
	return n0-n; 
1999/1005/sys/src/9/port/devaudio.c:743,7481999/1015/sys/src/9/port/devaudio.c:743,749 (short | long)
1995/0214    
	case 2: 
	case 5: 
	case 7: 
1999/1015    
	case 9: 
1995/0214    
	case 10: 
		break; 
	default: 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)