~kris/9p

9hist

fa8501367e6fda36ef08a275cc5bf1f91bf410b1 — David du Colombier 25 years ago e43ce1c
Plan 9 from Bell Labs 2001-05-02
6 files changed, 108 insertions(+), 66 deletions(-)

M bitsy/devuda1341.c
M bitsy/main.c
M bitsy/sa1110dma.c
M port/chan.c
M port/devdraw.c
M port/sysfile.c
M bitsy/devuda1341.c => bitsy/devuda1341.c +89 -57
@@ 19,7 19,7 @@
#include	"io.h"
#include	"sa1110dma.h"

static int debug = 2;
static int debug = 0;

/*
 * GPIO based L3 bus support.


@@ 139,15 139,15 @@ struct	IOstate
{
	QLock;
	Lock			ilock;
	Rendez			vous;
	Chan			*chan;			/* chan of open */
	int				dma;			/* dma chan, alloc on open, free on close */
	int				bufinit;		/* boolean, if buffers allocated */
	Buf				buf[Nbuf];		/* buffers and queues */
	Rendez		vous;
	Chan		*chan;		/* chan of open */
	int			dma;			/* dma chan, alloc on open, free on close */
	int			bufinit;		/* boolean, if buffers allocated */
	Buf			buf[Nbuf];		/* buffers and queues */
	volatile Buf	*current;		/* next dma to finish */
	volatile Buf	*next;			/* next candidate for dma */
	volatile Buf	*next;		/* next candidate for dma */
	volatile Buf	*filling;		/* buffer being filled */
/* just be be cute (and to have defines like linux, a real operating system) */
/* to have defines just like linux — there's a real operating system */
#define emptying filling
};



@@ 166,6 166,9 @@ static	struct
	IOstate	o;
} audio;

Buf	zeroes;
int	zerodma;	/* dma buffer used for sending zero */

static struct
{
	ulong	bytes;


@@ 173,6 176,7 @@ static struct
	ulong	idledma;
	ulong	faildma;
	ulong	samedma;
	ulong	empties;
} iostats;

static	struct


@@ 183,14 187,14 @@ static	struct
	int	irval;
} volumes[] =
{
[Vaudio]	{"audio",	Fout|Fmono,	 80,	 80},
[Vmic]		{"mic",		Fin|Fmono,	  0,	  0},
[Vtreb]		{"treb",	Fout|Fmono,	 50,	 50},
[Vbass]		{"bass",	Fout|Fmono, 	 50,	 50},
[Vaudio]	{"audio",	Fout|Fmono,	 	80,		80},
[Vmic]	{"mic",	Fin|Fmono,		  0,		  0},
[Vtreb]	{"treb",	Fout|Fmono,		50,		50},
[Vbass]	{"bass",	Fout|Fmono, 		50,		50},
[Vspeed]	{"speed",	Fin|Fout|Fmono,	Speed,	Speed},
[Vfilter]	{"filter",	Fout|Fmono,	  0,	  0},
[Vinvert]	{"invert",	Fin|Fout|Fmono,	  0,	  0},
[Nvol]		{0}
[Vfilter]	{"filter",	Fout|Fmono,		  0,		  0},
[Vinvert]	{"invert",	Fin|Fout|Fmono,	  0,		  0},
[Nvol]	{0}
};

static void	setreg(char *name, int val, int n);


@@ 397,8 401,15 @@ bufinit(IOstate *b)
	for (i = 0; i < Nbuf; i++) {
		b->buf[i].virt = xalloc(Bufsize);
		b->buf[i].phys = PADDR(b->buf[i].virt);
		memset(b->buf[i].virt, 0xAA, Bufsize);
	}
	b->bufinit = 1;

	if (b == &audio.o) {
		zeroes.virt = xalloc(Bufsize);
		zeroes.phys = PADDR(b->buf[i].virt);
		memset(zeroes.virt, 0, Bufsize);
	}
};

static void


@@ 681,6 692,15 @@ sendaudio(IOstate *s) {

	if (debug > 1) print("#A: sendaudio\n");
	ilock(&s->ilock);
	if ((audio.amode &  Aread) && s->next == s->filling && dmaidle(s->dma)) {
		// send an empty buffer to provide an input clock
		zerodma |= dmastart(s->dma, zeroes.phys, Bufsize) & 0xff;
		if (zerodma == 0)
			if (debug) print("emptyfail\n");
		iostats.empties++;
		iunlock(&s->ilock);
		return;
	}
	while (s->next != s->filling) {
		assert(s->next->nbytes);
		if ((n = dmastart(s->dma, s->next->phys, s->next->nbytes)) == 0) {


@@ 688,7 708,7 @@ sendaudio(IOstate *s) {
			break;
		}
		iostats.totaldma++;
		switch (n) {
		switch (n >> 8) {
		case 1:
			iostats.idledma++;
			break;


@@ 724,7 744,7 @@ recvaudio(IOstate *s) {
			break;
		}
		iostats.totaldma++;
		switch (n) {
		switch (n >> 8) {
		case 1:
			iostats.idledma++;
			break;


@@ 791,14 811,20 @@ audiointr(void *x, ulong ndma) {
		else
			iprint("-");
	}
	/* Only interrupt routine touches s->current */
	s->current++;
	if (s->current == &s->buf[Nbuf])
		s->current = &s->buf[0];
	if (ndma > 0) {
		if (s == &audio.o)
	if (s == &audio.i || (ndma & ~zerodma)) {
		/* A dma, not of a zero buffer completed, update current
		 * Only interrupt routine touches s->current
		 */
		s->current->nbytes = (s == &audio.i)? Bufsize: 0;
		s->current++;
		if (s->current == &s->buf[Nbuf])
			s->current = &s->buf[0];
	}
	if (ndma) {
		if (s == &audio.o) {
			zerodma &= ~ndma;
			sendaudio(s);
		else if (s == &audio.i)
		} else if (s == &audio.i)
			recvaudio(s);
	}
	wakeup(&s->vous);


@@ 862,19 888,23 @@ audioopen(Chan *c, int mode)
			s->dma = dmaalloc(1, 0, 4, 2, SSPRecvDMA, Port4SSP, audiointr, (void*)s);
			audio.amode |= Aread;
		}
		if (omode & Awrite) {
			outenable();
		if (omode & (Aread|Awrite) && (audio.amode & Awrite) == 0) {
			s = &audio.o;
			audio.amode |= Awrite;
			if(s->bufinit == 0)
				bufinit(s);
			setempty(s);
			s->chan = c;
			s->dma = dmaalloc(0, 0, 4, 2, SSPXmitDMA, Port4SSP, audiointr, (void*)s);
		}	
		if (omode & Awrite) {
			audio.amode |= Awrite;
			outenable();
		}
		mxvolume();
		qunlock(&audio);
		if (audio.amode == Aread)
			sendaudio(&audio.o);
			
		if (debug) print("open done\n");
		break;
	}


@@ 905,19 935,34 @@ audioclose(Chan *c)
		if (debug > 1) print("#A: close\n");
		if(c->flag & COPEN) {
			qlock(&audio);
			if(waserror()){
				qunlock(&audio);
				nexterror();
			if (audio.i.chan == c) {
				/* closing the read end */
				audio.amode &= ~Aread;
				s = &audio.i;
				qlock(s);
				indisable();
				setempty(s);
				dmafree(s->dma);
				qunlock(s);
				if ((audio.amode & Awrite) == 0) {
					s = &audio.o;
					qlock(s);
					while(waserror()) {
						dmawait(s->dma);
						if (dmaidle(s->dma))
							break;
					}
					outdisable();
					setempty(s);
					dmafree(s->dma);
					qunlock(s);
				}
			}
			if (audio.o.chan == c) {
				/* closing the write end */
				audio.amode &= ~Awrite;
				s = &audio.o;
				qlock(s);
				if(waserror()){
					qunlock(s);
					nexterror();
				}
				if (s->filling->nbytes) {
					/* send remaining partial buffer */
					s->filling++;


@@ 925,34 970,22 @@ audioclose(Chan *c)
						s->filling = &s->buf[0];
					sendaudio(s);
				}
				dmawait(s->dma);
				outdisable();
				setempty(s);
				dmafree(s->dma);
				qunlock(s);
				poperror();
			}
			if (audio.i.chan == c) {
				/* closing the read end */
				audio.amode &= ~Aread;
				s = &audio.i;
				qlock(s);
				if(waserror()){
					qunlock(s);
					nexterror();
				while(waserror()) {
					dmawait(s->dma);
					if (dmaidle(s->dma))
						break;
				}
				indisable();
				outdisable();
				setempty(s);
				dmafree(s->dma);
				if ((audio.amode & Aread) == 0)
					dmafree(s->dma);
				qunlock(s);
				poperror();
			}
			if (audio.amode == 0) {
				/* turn audio off */
				egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 0);
			}
			qunlock(&audio);
			poperror();
			if (debug) {
				print("total dmas: %lud\n", iostats.totaldma);
				print("dmas while idle: %lud\n", iostats.idledma);


@@ 1009,10 1042,9 @@ audioread(Chan *c, void *v, long n, vlong off)
				sleep(&s->vous, audioqnotempty, s);
			}

			m = Bufsize - s->emptying->nbytes;
			if(m > n)
				m = n;
			memmove(p, s->emptying->virt + s->emptying->nbytes, m);
			m = (s->emptying->nbytes > n)? n: s->emptying->nbytes;
			memmove(p, s->emptying->virt + Bufsize - 
					  s->emptying->nbytes, m);

			s->emptying->nbytes -= m;
			n -= m;

M bitsy/main.c => bitsy/main.c +1 -1
@@ 381,7 381,7 @@ machinit(void)
	gpioregs->altfunc |= 
		GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
		|GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o
		|GPIO_SSP_CLK_i|GPIO_SSP_RXD_i;
		|GPIO_SSP_CLK_i;

	/* map in special H3650 io pins */
	egpioreg = mapspecial(EGPIOREGS, 4);

M bitsy/sa1110dma.c => bitsy/sa1110dma.c +6 -4
@@ 7,7 7,7 @@
#include	"../port/error.h"
#include	"sa1110dma.h"

static int debug = 2;
static int debug = 0;

/*
 *	DMA helper routines


@@ 140,26 140,28 @@ dmastart(int chan,  ulong addr, int count) {
		return 0;
	}
	cachewbregion(addr, count);
	n = 1;
	n = 0x100;
	if ((status & (1<<BIU | 1<<STRTB)) == (1<<BIU | 1<<STRTB) ||
		(status & (1<<BIU | 1<<STRTA)) == 0) {
		if (status & 1<<STRTA)
			iprint("writing busy dma entry 0x%lux\n", status);
		if (status & 1<<STRTB)
			n = (last == 1)?2:3;
			n = (last == 1)?0x200:0x300;
		last = 2;
		dmaregs[chan].dstrtA = addr;
		dmaregs[chan].dxcntA = count;
		dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTA;
		n |= 1<<DONEA;
	} else {
		if (status & 1<<STRTB)
			iprint("writing busy dma entry 0x%lux\n", status);
		if (status & 1<<STRTA)
			n = (last == 2)?2:3;
			n = (last == 2)?0x200:0x300;
		last = 1;
		dmaregs[chan].dstrtB = addr;
		dmaregs[chan].dxcntB = count;
		dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTB;
		n |= 1<<DONEB;
	}
	return n;
}

M port/chan.c => port/chan.c +5 -3
@@ 194,12 194,14 @@ cclose(Chan *c)
	if(decref(c))
		return;

	if(!waserror()) {
		devtab[c->type]->close(c);
		poperror();
	if(waserror()){
		print("cclose error: type %C; error %s\n", devtab[c->type]->dc, up!=nil? up->error : "no user"); //BUG
		return;
	}

	devtab[c->type]->close(c);
	chanfree(c);
	poperror();
}

int

M port/devdraw.c => port/devdraw.c +1 -1
@@ 959,7 959,7 @@ drawclose(Chan *c)
	Client *cl;
	Refresh *r;

	if(c->qid.path & CHDIR)
	if(QID(c->qid) < Qcolormap)	/* Qtopdir, Qnew, Q3rd, Q2nd have no client */
		return;
	qlock(&sdraw);
	if(waserror()){

M port/sysfile.c => port/sysfile.c +6 -0
@@ 455,6 455,9 @@ syspread(ulong *arg)
		ulong u[2];
	} o;

	if(arg[3] == ~0UL && arg[4] == ~0UL)
		return sysread(arg);

	n = arg[2];
	validaddr(arg[1], n, 1);
	c = fdtochan(arg[0], OREAD, 1, 1);


@@ 557,6 560,9 @@ syspwrite(ulong *arg)
		ulong u[2];
	} o;

	if(arg[3] == ~0UL && arg[4] == ~0UL)
		return syswrite(arg);

	validaddr(arg[1], arg[2], 0);
	n = arg[2];
	c = fdtochan(arg[0], OWRITE, 1, 1);