~kris/9p

9hist

40a802559879af09848114f3b41817513934a23e — David du Colombier 25 years ago 3f34ec0
Plan 9 from Bell Labs 2000-11-15
5 files changed, 98 insertions(+), 71 deletions(-)

M bitsy/devuda1341.c
M bitsy/sa1110dma.c
M bitsy/sa1110dma.h
M pc/devi82365.c
M port/latin1.h
M bitsy/devuda1341.c => bitsy/devuda1341.c +40 -18
@@ 132,6 132,7 @@ struct	Buf
struct	IOstate
{
	QLock;
	Lock			ilock;
	Rendez			vous;
	Chan			*chan;			/* chan of open */
	int				dma;			/* dma chan, alloc on open, free on close */


@@ 435,15 436,17 @@ audioenable(void)
	L3_init();

	/* Setup the uarts */
    ppcregs->assignment &= ~(1<<18);	/* Could be the other way round! */
    ppcregs->assignment &= (1<<18);	/* Could be the other way round! */

    gpioregs->altfunc &= ~(GPIO_SSP_TXD_o | GPIO_SSP_RXD_i | GPIO_SSP_SCLK_o | GPIO_SSP_SFRM_o);
	gpioregs->altfunc |= (GPIO_SSP_CLK_i);
	gpioregs->direction &= ~(GPIO_SSP_CLK_i);

	sspregs->control0 = 0x10<<0 | 0x1<<4 | 1<<7 | 0x8<<8;
	sspregs->control0 = 0xf<<0 | 0x1<<4 | 0x3<<8;
	sspregs->control1 = 0<<3 + 0<<4 + 1<<5;

	sspregs->control0 |= 1<<7;	/* enable */

	/* Enable the audio power */
	audiopower(1);
	amplifierpower(1);


@@ 458,12 461,14 @@ audioenable(void)
	delay(100);
    print("Ser4SSSR=0x%lux\n", sspregs->status);

    gpioregs->clear = EGPIO_codec_reset;
    gpioregs->set = EGPIO_codec_reset;

	/* Reset the chip */
	data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */ | 1<<6 /* reset */;
	L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1 );

    gpioregs->clear = EGPIO_codec_reset;
    gpioregs->set = EGPIO_codec_reset;
	delay(10);

	data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */;
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_STATUS, data, 1 );


@@ 496,22 501,38 @@ audioenable(void)
	data[1] = 0xe0 | 0<<2 | 3;	/* agc time constant and output level */
	L3_write(UDA1341_L3Addr<<2 | UDA1341_DATA0, data, 2 );

	/* Reset the chip */
	data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */ | 1<<6 /* reset */;
	L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1 );

	delay(10);

	data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */;
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_STATUS, data, 1 );
	/* Reset done */

	if (debug) print("#A: audio enabled\n");
}

static void
sendaudio(IOstate *b) {
	/* call this with lock held */
	if (debug) print("#A: sendaudio\n");
	/* interrupt routine calls this too */
	if (debug > 1) print("#A: sendaudio\n");
	ilock(&b->ilock);
	while (b->next != b->filling) {
		assert(b->next->nbytes);
		if (dmastart(b->dma, b->next->virt, b->next->nbytes) == 0)
			break;
		incref(&b->active);
		if (dmastart(b->dma, b->next->virt, b->next->nbytes) == 0) {
			decref(&b->active);
			break;
		}
		if (debug > 1) print("#A: dmastart @%p\n", b->next);
		b->next->nbytes = 0;
		b->next++;
		if (b->next == &b->buf[Nbuf])
			b->next = &b->buf[0];
	}
	iunlock(&b->ilock);
}

static void


@@ 519,16 540,13 @@ audiointr(void *x, ulong) {
	IOstate *s = x;

	if (s == &audio.o) {
		decref(&s->active);
		/* Only interrupt routine touches s->current */
		s->current->nbytes = 0;
		if (debug > 1) iprint("#A: audio interrupt @%p\n", s->current);
		s->current++;
		if (s->current == &s->buf[Nbuf])
			s->current = &s->buf[0];
		if (canlock((Lock*)s)) {
			sendaudio(s);
			unlock((Lock*)s);
		}
		decref(&s->active);
		sendaudio(s);
	}
	wakeup(&s->vous);
}


@@ 598,8 616,8 @@ audioopen(Chan *c, int omode)
			audio.o.chan = c;
			audio.o.dma = dmaalloc(0, 0, 8, 2, SSPXmitDMA, Port4SSP, audiointr, (void*)&audio.o);
		}
		qunlock(&audio);
//		mxvolume();
		qunlock(&audio);
		if (debug) print("#A: open done\n");
		break;
	}


@@ 626,6 644,7 @@ audioclose(Chan *c)
		break;

	case Qaudio:
		if (debug > 1) print("#A: close\n");
		if(c->flag & COPEN) {
			qlock(&audio);
			qlock(&audio.o);


@@ 638,7 657,7 @@ audioclose(Chan *c)
				/* closing the write end */
				audio.amode &= ~Awrite;

				while (audio.o.filling->nbytes) {
				if (audio.o.filling->nbytes) {
					audio.o.filling++;
					if (audio.o.filling == &audio.o.buf[Nbuf])
						audio.o.filling = &audio.o.buf[0];


@@ 827,7 846,7 @@ audiowrite(Chan *c, void *vp, long n, vlong)
		break;

	case Qaudio:
		if (debug) print("#A: write %ld\n", n);
		if (debug > 1) print("#A: write %ld\n", n);
		if((audio.amode & Awrite) == 0)
			error(Emode);
		a = &audio.o;


@@ 838,8 857,10 @@ audiowrite(Chan *c, void *vp, long n, vlong)
		}
		while(n > 0) {
			/* wait if dma in progress */
			while (a->active.ref && a->filling == a->current)
			while (a->active.ref && a->filling == a->current) {
				if (debug > 1) print("#A: sleep\n");
				sleep(&a->vous, audioqnotfull, a);
			}

			m = Bufsize - a->filling->nbytes;
			if(m > n)


@@ 850,6 871,7 @@ audiowrite(Chan *c, void *vp, long n, vlong)
			n -= m;
			p += m;
			if(a->filling->nbytes >= Bufsize) {
				if (debug > 1) print("#A: filled @%p\n", a->filling);
				a->filling++;
				if (a->filling == &a->buf[Nbuf])
					a->filling = a->buf;

M bitsy/sa1110dma.c => bitsy/sa1110dma.c +50 -46
@@ 41,7 41,8 @@ enum {
};

typedef struct DMAchan {
	int		inuse;
	int		allocated;
	Ref		active;
	Rendez	r;
	void	(*intr)(void*, ulong);
	void	*param;


@@ 71,6 72,8 @@ dmainit(void) {

	/* map the lcd regs into the kernel's virtual space */
	dmaregs = (struct dmaregs*)mapspecial(DMAREGS, NDMA*sizeof(struct dmaregs));;
	if (debug) print("dma: dmaalloc registers 0x%ux mapped at 0x%p\n",
		DMAREGS, dmaregs);
	for (i = 0; i < NDMA; i++) {
		intrenable(IRQdma0+i, dmaintr, &dmaregs[i], "DMA");
	}


@@ 79,23 82,26 @@ dmainit(void) {
int
dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, ulong port, void (*intr)(void*, ulong), void *param) {
	int i;
	ulong ddar;

	if (debug) print("dma: dmaalloc\n");
	lock(&dma);
	for (i = 0; i < NDMA; i++) {
		if (dma.chan[i].inuse)
		if (dma.chan[i].allocated)
			continue;
		dma.chan[i].inuse++;
		dma.chan[i].allocated++;
		unlock(&dma);
		dmaregs[i].ddar =
		ddar =
			(rd?1:0)<<RW |
			(bigendian?1:0)<<E |
			((burstsize==8)?1:0)<<BS |
			((datumsize==2)?1:0)<<DW |
			device<<DS |
			0x80000000 | ((ulong)port << 6);
		dmaregs[i].ddar = ddar;
		if (debug) print("dma: dmaalloc: 0x%lux\n", ddar);
		dma.chan[i].intr = intr;
		dma.chan[i].param = param;
		dmaregs[i].dcsr_clr = 0xff;
		return i;
	}
	unlock(&dma);


@@ 104,68 110,58 @@ dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, ulong 

void
dmafree(int i) {
	dma.chan[i].inuse = 0;
	dma.chan[i].allocated = 0;
	dma.chan[i].intr = nil;
}

static int
dmaready(void *dcsr) {
	return *(int*)dcsr & ((1<<DONEA)|(1<<DONEB));
}

ulong
dmastart(int chan, void *addr, int count) {
	ulong status;

	if (debug) print("dma: dmastart\n");
	if (((status = dmaregs[chan].dcsr_rd) & ((1<<DONEA)|(1<<DONEB))) == 0)
	status = dmaregs[chan].dcsr_rd;
	if (debug > 1) print("dma: dmastart 0x%lux\n", status);

	if (dma.chan[chan].active.ref >= 2) {
		if (debug > 1) print("\n");
		return 0;
	}

	if ((status & (1<<DONEA|1<<DONEB|1<<RUN)) == 1<<RUN)
		panic("dmastart called while busy");

	cachewbregion((ulong)addr, count);
	if ((status & (1<<BIU | 1<<STRTB)) == (1<<BIU | 1<<STRTB) ||
				(status & (1<<BIU | 1<<STRTA)) == (1<<STRTA)) {
		dmaregs[chan].dcsr_clr |= 1<<DONEA | 1<<STRTA;
		(status & (1<<BIU | 1<<STRTA)) == 0) {
		dmaregs[chan].dcsr_clr = 1<<DONEA | 1<<STRTA;
		dmaregs[chan].dstrtA = addr;
		dmaregs[chan].dxcntA = count-1;
		dmaregs[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STRTA;
		incref(&dma.chan[chan].active);
		dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTA;
		return 1<<DONEA;
	} else {
		dmaregs[chan].dcsr_clr |= 1<<DONEB | 1<<STRTB;
		dmaregs[chan].dcsr_clr = 1<<DONEB | 1<<STRTB;
		dmaregs[chan].dstrtB = addr;
		dmaregs[chan].dxcntB = count-1;
		dmaregs[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STRTB;
		incref(&dma.chan[chan].active);
		dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTB;
		return 1<<DONEB;
	}
}

ulong
dmadone(int chan, ulong op) {
	ulong dcsr;

	dcsr = dmaregs[chan].dcsr_rd;
	if (dcsr & 1<<ERROR)
		pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
	return dcsr & (op | 1<<ERROR);
}

int
dmaidle(int chan) {
	ulong dcsr;
	return dma.chan[chan].active.ref == 0;
}

	dcsr = dmaregs[chan].dcsr_rd;
	if (dcsr & 1<<ERROR)
		pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
	return (dcsr & (1<<DONEA | 1<<DONEB)) == (1<<DONEA | 1<<DONEB);
static int
_dmaidle(void* chan) {
	return dma.chan[(int)chan].active.ref == 0;
}

void
dmawait(int chan, ulong op) {
	ulong dcsr;

	while (((dcsr = dmaregs[chan].dcsr_rd) & (op | 1<<ERROR)) == 0)
		sleep(&dma.chan[chan].r, dmaready, &dmaregs[chan].dcsr_rd);
	if (dcsr & 1<<ERROR)
		pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
dmawait(int chan) {
	while (dma.chan[chan].active.ref)
		sleep(&dma.chan[chan].r, _dmaidle, (void*)chan);
}

/*


@@ 176,14 172,22 @@ dmaintr(Ureg*, void *x)
{
	int i;
	struct dmaregs *regs = x;
	ulong dcsr;
	ulong dcsr, donebit;

	if (debug) print("dma: interrupt\n");
	i = regs - dmaregs;
	if ((dcsr = regs->dcsr_rd) & (1<<DONEA | 1<<DONEB | 1<<ERROR)) {
		wakeup(&dma.chan[i].r);
	dcsr = regs->dcsr_rd;
	if (debug > 1)
		iprint("dma: interrupt channel %d, status 0x%lux\n", i, dcsr);
	if (dcsr & 1<<ERROR)
		iprint("error, channel %d, status 0x%lux\n", i, dcsr);
	donebit = 1<<((dcsr&1<<BIU)?DONEA:DONEB);
	if (dcsr & donebit) {
		regs->dcsr_clr |= donebit;
		if (dma.chan[i].intr)
			(*dma.chan[i].intr)(dma.chan[i].param, dcsr);
			(*dma.chan[i].intr)(dma.chan[i].param, 3-dma.chan[i].active.ref);
		/* must call interrupt routine before calling decref */
		decref(&dma.chan[i].active);
		wakeup(&dma.chan[i].r);
	} else
		print("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
		iprint("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
}

M bitsy/sa1110dma.h => bitsy/sa1110dma.h +4 -3
@@ 10,7 10,8 @@ enum {
void	dmainit(void);
int		dmaalloc(int, int, int, int, int, ulong, void (*)(void*, ulong), void*);
void	dmafree(int);

ulong	dmastart(int, void *, int);
ulong	dmadone(int, ulong);
void	dmawait(int, ulong);
int		dmaidle(int chan);

void	dmawait(int);
int		dmaidle(int);

M pc/devi82365.c => pc/devi82365.c +2 -2
@@ 661,14 661,14 @@ i82365reset(void)

	/* look for controllers if the ports aren't already taken */
	if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){
		i82365probe(0x3E0, 0x3E1, 0);
		i82365probe(0x3E0, 0x3E1, 0) ||
		i82365probe(0x3E0, 0x3E1, 1);
		if(ncontroller == 0)
			iofree(0x3E0);
	}
	if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){
		i = ncontroller;
		i82365probe(0x3E2, 0x3E3, 0);
		i82365probe(0x3E2, 0x3E3, 0) ||
		i82365probe(0x3E2, 0x3E3, 1);
		if(ncontroller == i)
			iofree(0x3E2);

M port/latin1.h => port/latin1.h +2 -2
@@ 57,7 57,7 @@
	"P", "P",	L"ℙ",
	"Q", "Q",	L"ℚ",
	"R", "R",	L"ℝ",
	"S", "S",	L"§",
	"S", "123S",	L"¹²³§",
	"T", "-u",	L"Ŧ⊨",
	"V", "=",	L"⇐",
	"Y", "R",	L"Ʀ",


@@ 85,7 85,7 @@
	"o", "AOUaeiu",	L"Å⊚Ůåœƣů",
	"p", "Odgrt",	L"℗∂¶∏∝",
	"r", "\"\'O",	L"”’®",
	"s", "()+-0123456789=abnoprstu",	L"⁽⁾⁺⁻⁰¹²³⁴⁵⁶⁷⁸⁹⁼ª⊂ⁿº⊃√ß∍∑",
	"s", "()+-0123456789=abnoprstu",	L"⁽⁾⁺⁻⁰ⁱ⁲⁳⁴⁵⁶⁷⁸⁹⁼ª⊂ⁿº⊃√ß∍∑",
	"t", "-efmsu",	L"ŧ∃∴™ς⊢",
	"u", "-AEGIOUaegiou",	L"ʉĂĔĞĬŎŬ↑ĕğĭŏŭ",
	"v\"", "Uu",	L"Ǚǚ",