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

1998/0317/port/devaudio.c (diff list | history)

1997/0408/sys/src/9/port/devaudio.c:120,1251998/0317/sys/src/9/port/devaudio.c:120,128 (short | long | prev | next)
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 
	 */ 


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