⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devaudio.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
	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	voidsetempty(void){	int i;	ilock(&blaster);	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]);	audio.totcount = 0;	audio.tottime = 0LL;	iunlock(&blaster);}static	voidresetlevel(void){	int i;	for(i=0; volumes[i].name; i++) {		audio.lovol[i] = volumes[i].ilval;		audio.rovol[i] = volumes[i].irval;		audio.livol[i] = volumes[i].ilval;		audio.rivol[i] = volumes[i].irval;	}}static intess1688(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 %lud\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 %lud\n", sbconf->dma);		return 1;	}	ess1688w(0xB2, i);	ess1688reset();	blaster.startdma = ess1688startdma;	blaster.intr = ess1688intr;	return 0;}static voidaudioinit(void){	ISAConf sbconf;	int i, x;	static int irq[] = {2,5,7,10};	sbconf.port = 0x220;	sbconf.dma = Dma;	sbconf.irq = IrqAUDIO;	if(isaconfig("audio", 0, &sbconf) == 0)		return;	if(cistrcmp(sbconf.type, "sb16") != 0 && cistrcmp(sbconf.type, "ess1688") != 0)		return;	switch(sbconf.port){	case 0x220:	case 0x240:	case 0x260:	case 0x280:		break;	default:		print("#A: bad port 0x%lux\n", sbconf.port);		return;	}	switch(sbconf.irq){	case 2:	case 5:	case 7:	case 9:	case 10:		break;	default:		print("#A: bad irq %lud\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;	blaster.dma = sbconf.dma;	blaster.startdma = sb16startdma;	blaster.intr = sb16intr;	audio.amode = Aclosed;	resetlevel();	outb(blaster.reset, 1);	delay(1);			/* >3 υs */	outb(blaster.reset, 0);	delay(1);	i = sbread();	if(i != 0xaa) {		print("#A: no response #%.2x\n", i);		return;	}	sbcmd(0xe1);			/* get version */	audio.major = sbread();	audio.minor = sbread();	if(audio.major != 4) {		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;	}	/*	 * initialize the mixer	 */	mxcmd(0x00, 0);			/* Reset mixer */	mxvolume();	/*	 * 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.	 */	mxcmd(0x80,			/* irq */		(sbconf.irq==2)? 1:		(sbconf.irq==5)? 2:		(sbconf.irq==7)? 4:		(sbconf.irq==9)? 1:		(sbconf.irq==10)? 8:		0);	mxcmd(0x81, 1<<blaster.dma);	/* dma */	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);}static Chan*audioattach(char *param){	return devattach('A', param);}static intaudiowalk(Chan *c, char *name){	return devwalk(c, name, audiodir, nelem(audiodir), devgen);}static voidaudiostat(Chan *c, char *db){	devstat(c, db, audiodir, nelem(audiodir), devgen);}static Chan*audioopen(Chan *c, int omode){	int amode;	if(audio.major != 4)		error(Emajor);	switch(c->qid.path & ~CHDIR) {	default:		error(Eperm);		break;	case Qstatus:		if((omode&7) != OREAD)			error(Eperm);	case Qvolume:	case Qdir:		break;	case Qaudio:		amode = Awrite;		if((omode&7) == OREAD)			amode = Aread;		qlock(&audio);		if(audio.amode != Aclosed){			qunlock(&audio);			error(Einuse);		}		if(audio.bufinit == 0) {			audio.bufinit = 1;			sbbufinit();		}		audio.amode = amode;		setempty();		audio.curcount = 0;		qunlock(&audio);		mxvolume();		break;	}	c = devopen(c, omode, audiodir, nelem(audiodir), devgen);	c->mode = openmode(omode);	c->flag |= COPEN;	c->offset = 0;	return c;}static voidaudioclose(Chan *c){	Buf *b;	switch(c->qid.path & ~CHDIR) {	default:		error(Eperm);		break;	case Qdir:	case Qvolume:	case Qstatus:		break;	case Qaudio:		if(c->flag & COPEN) {			qlock(&audio);			if(audio.amode == Awrite) {				/* flush out last partial buffer */				b = audio.filling;				if(b) {					audio.filling = 0;					memset(b->virt+audio.curcount, 0, Bufsize-audio.curcount);					swab(b->virt);					putbuf(&audio.full, b);				}				if(!audio.active && audio.full.first)					pokeaudio();			}			audio.amode = Aclosed;			if(waserror()){				qunlock(&audio);				nexterror();			}			while(audio.active)				waitaudio();			setempty();			poperror();			qunlock(&audio);		}		break;	}}static longaudioread(Chan *c, void *v, long n, vlong off){	int liv, riv, lov, rov;	long m, n0;	char buf[300];	Buf *b;	int j;	ulong offset = off;	char *a;	n0 = n;	a = v;	switch(c->qid.path & ~CHDIR) {	default:		error(Eperm);		break;	case Qdir:		return devdirread(c, a, n, audiodir, nelem(audiodir), devgen);	case Qaudio:		if(audio.amode != Aread)			error(Emode);		qlock(&audio);		if(waserror()){			qunlock(&audio);			nexterror();		}		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);			}		}		poperror();		qunlock(&audio);		break;	case Qstatus:		buf[0] = 0;		snprint(buf, sizeof(buf), "bytes %lud\ntime %lld\n",			audio.totcount, audio.tottime);		return readstr(offset, a, n, buf);	case Qvolume:		j = 0;		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);				}			}			j += snprint(buf+j, sizeof(buf)-j, "\n");		}		return readstr(offset, a, n, buf);	}	return n0-n;}static longaudiowrite(Chan *c, void *vp, long n, vlong){	long m, n0;	int i, nf, v, left, right, in, out;	char buf[255], *field[Ncmd];	Buf *b;	char *a;	a = vp;	n0 = n;	switch(c->qid.path & ~CHDIR) {	default:		error(Eperm);		break;	case Qvolume:		v = Vaudio;		left = 1;		right = 1;		in = 1;		out = 1;		if(n > sizeof(buf)-1)			n = sizeof(buf)-1;		memmove(buf, a, n);		buf[n] = '\0';		nf = getfields(buf, field, Ncmd, 1, " \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 && 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;				mxvolume();				goto cont0;			}			for(m=0; volumes[m].name; m++) {				if(strcmp(field[i], volumes[m].name) == 0) {					v = m;					in = 1;					out = 1;					left = 1;					right = 1;					goto cont0;				}			}			if(strcmp(field[i], "reset") == 0) {				resetlevel();				mxvolume();				goto cont0;			}			if(strcmp(field[i], "in") == 0) {				in = 1;				out = 0;				goto cont0;			}			if(strcmp(field[i], "out") == 0) {				in = 0;				out = 1;				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;			}			error(Evolume);			break;		cont0:;		}		break;	case Qaudio:		if(audio.amode != Awrite)			error(Emode);		qlock(&audio);		if(waserror()){			qunlock(&audio);			nexterror();		}		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);			}		}		poperror();		qunlock(&audio);		break;	}	return n0 - n;}static	voidswab(uchar *a){	ulong *p, *ep, b;	if(!SBswab){		USED(a);		return;	}	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;	}}Dev audiodevtab = {	'A',	"audio",	devreset,	audioinit,	audioattach,	devclone,	audiowalk,	audiostat,	audioopen,	devcreate,	audioclose,	audioread,	devbread,	audiowrite,	devbwrite,	devremove,	devwstat,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -