~kris/9p

9hist

280fe23479ee62fef9c77291f860dc799baa07f5 — David du Colombier 28 years ago 7ab5fa8
Plan 9 from Bell Labs 1998-03-17
2 files changed, 239 insertions(+), 20 deletions(-)

M pc/devi82365.c
M port/devaudio.c
M pc/devi82365.c => pc/devi82365.c +11 -5
@@ 569,8 569,6 @@ i82386probe(int x, int d, int dev)
		outb(d, c & ~0xC0);
	}

	print("#y%d: %d slot %s\n", ncontroller, cp->nslot, chipname[cp->type]);

	/* low power mode */
	outb(x, Rmisc2 + (dev<<7));
	c = inb(d);


@@ 602,14 600,20 @@ static void
i82365reset(void)
{
	static int already;
	int i, j;
	int i, j, vector;
	I82365 *cp;
	Slot *pp;
	ISAConf isa;

	if(already)
		return;
	already = 1;

	memset(&isa, 0, sizeof(ISAConf));
	vector = VectorPCMCIA;
	if(isaconfig("pcmcia", 0, &isa) && isa.irq)
		vector = VectorPIC+isa.irq;

	/* look for controllers */
	i82386probe(0x3E0, 0x3E1, 0);
	i82386probe(0x3E0, 0x3E1, 1);


@@ 623,6 627,8 @@ i82365reset(void)
	lastslot = slot;
	for(i = 0; i < ncontroller; i++){
		cp = controller[i];
		print("#y%d: %d slot %s: port 0x%uX irq %d\n",
			i, cp->nslot, chipname[cp->type], cp->xreg, vector-VectorPIC);
		for(j = 0; j < cp->nslot; j++){
			pp = lastslot++;
			pp->slotno = pp - slot;


@@ 632,14 638,14 @@ i82365reset(void)
			slotdis(pp);

			/* interrupt on status change */
			wrreg(pp, Rcscic, ((VectorPCMCIA-VectorPIC)<<4) | Fchangeena);
			wrreg(pp, Rcscic, ((vector-VectorPIC)<<4) | Fchangeena);
			rdreg(pp, Rcsc);
		}
	}

	/* for card management interrupts */
	if(ncontroller)
		intrenable(VectorPCMCIA, i82365intr, 0, BUSUNKNOWN);
		intrenable(vector, i82365intr, 0, BUSUNKNOWN);
}

static Chan*

M port/devaudio.c => port/devaudio.c +228 -15
@@ 120,6 120,9 @@ static struct
	int	clri16;
	int	clri401;
	int	dma;

	void	(*startdma)(void);
	void	(*intr)(void);
} blaster;

static	void	swab(uchar*);


@@ 140,7 143,7 @@ sbcmd(int val)
			return 0;
		}
	}
/*	print("#A: sbcmd (#%.2x) timeout\n", val);	/**/
/*	print("#A: sbcmd (0x%.2x) timeout\n", val);	/**/
	return 1;
}



@@ 156,7 159,25 @@ sbread(void)
		}
	}
/*	print("#A: sbread did not respond\n");	/**/
	return 0xbb;
	return -1;
}

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();
}

static	int


@@ 321,11 342,11 @@ contindma(void)

	b = audio.current;
	if(audio.amode == Aread) {
		if(b)	/* shouldnt happen */
		if(b)	/* shouldn't happen */
			putbuf(&audio.full, b);
		b = getbuf(&audio.empty);
	} else {
		if(b)	/* shouldnt happen */
		if(b)	/* shouldn't happen */
			putbuf(&audio.empty, b);
		b = getbuf(&audio.full);
	}


@@ 333,8 354,10 @@ contindma(void)
	if(b == 0)
		goto shutdown;

	dmasetup(blaster.dma, b->virt, Bufsize, audio.amode == Aread);
	return;
	if(dmasetup(blaster.dma, b->virt, Bufsize, audio.amode == Aread) >= 0)
		return;
	print("#A: dmasetup fail\n");
	putbuf(&audio.empty, b);

shutdown:
	dmaend(blaster.dma);


@@ 349,7 372,7 @@ shutdown:
 * start first dma
 */
static	void
startdma(void)
sb16startdma(void)
{
	ulong count;
	int speed;


@@ 380,6 403,97 @@ startdma(void)
	iunlock(&blaster);
}

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);
}

/*
 * if audio is stopped,
 * start it up again.


@@ 388,11 502,11 @@ static	void
pokeaudio(void)
{
	if(!audio.active)
		startdma();
		blaster.startdma();
}

void
audiosbintr(void)
static void
sb16intr(void)
{
	int stat, dummy;



@@ 417,11 531,40 @@ audiosbintr(void)
	}
}

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");
}

void
audiosbintr(void)
{
	/*
	 * Carrera interrupt interface.
	 */
	blaster.intr();
}

static void
pcaudiosbintr(Ureg*, void*)
{
/*	print("#A: audio interrupt\n");	/**/
	audiosbintr();
	/*
	 * x86 interrupt interface.
	 */
	blaster.intr();
}

void


@@ 498,6 641,68 @@ resetlevel(void)
	}
}

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;
}

static void
audioinit(void)
{


@@ 509,7 714,7 @@ audioinit(void)
	sbconf.irq = 7;
	if(isaconfig("audio", 0, &sbconf) == 0)
		return;
	if(strcmp(sbconf.type, "sb16") != 0)
	if(cistrcmp(sbconf.type, "sb16") != 0 && cistrcmp(sbconf.type, "ess1688") != 0)
		return;
	switch(sbconf.port){
	case 0x220:


@@ 544,6 749,9 @@ audioinit(void)
	blaster.clri401 = sbconf.port + 0x100;
	blaster.dma = sbconf.dma;

	blaster.startdma = sb16startdma;
	blaster.intr = sb16intr;

	seteisadma(blaster.dma, audiodmaintr);
	setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0);



@@ 566,9 774,14 @@ audioinit(void)
	audio.minor = sbread();

	if(audio.major != 4) {
		print("#A: model #%.2x #%.2x; not SB 16\n", audio.major, audio.minor);
		return;
		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
	 */