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

1995/0214/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 | prev | next)
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) { 


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