~kris/9p

9hist

602fc1003b1173c4d4ffc04f819159a3959fd6f7 — David du Colombier 25 years ago bafa3d1
Plan 9 from Bell Labs 2000-11-22
M bitsy/dat.h => bitsy/dat.h +1 -1
@@ 316,7 316,7 @@ struct Cisdat
 */
struct PCMslot
{
	Ref;
	Ref	ref;

	long	memlen;		/* memory length */
	uchar	slotno;		/* slot number */

M bitsy/devpcmcia.c => bitsy/devpcmcia.c +16 -8
@@ 86,6 86,9 @@ pcmciareset(void)
	/* set timing to the default, 300 */
	slottiming(0, 300, 300, 300, 0);
	slottiming(1, 300, 300, 300, 0);

	/* interrupt on card insertion */
	gpiointrenable(
}

static Chan*


@@ 286,7 289,7 @@ Dev pcmciadevtab = {

/* see what's there */
static void
slotinfo(void)
slotinfo(Ureg*, void*)
{
	ulong x = gpioregs->level;



@@ 295,8 298,14 @@ slotinfo(void)
		slot[0].occupied = 0;
		slot[1].occupied = 0;
	} else {
		slot[0].occupied = (x & GPIO_CARD_IND0_i) == 0;
		slot[1].occupied = (x & GPIO_CARD_IND1_i) == 0;
		if(!slot[0].occupied && (x & GPIO_CARD_IND0_i)){
			slot[0].occupied = 1;
			slot[0].cisread = 0;
		}
		if(!slot[1].occupied && (x & GPIO_CARD_IND1_i)){
			slot[1].occupied = 1;
			slot[0].cisread = 0;
		}
	}
}



@@ 304,21 313,20 @@ slotinfo(void)
static void
increfp(PCMslot *pp)
{
	slotinfo(nil, nil);
	if(incref(&pcmcia) == 1){
		egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 1);
		egpiobits(EGPIO_pcmcia_reset, 0);
		delay(100);	/* time to power up */
		delay(200);	/* time to power up */
	}

	incref(pp);

	slotinfo();
	if(pp->occupied && pp->cisread == 0)
		pcmcisread(pp);
}

static void
decrefp(PCMslot *pp)
{
	slotinfo();
	decref(pp);
	if(decref(&pcmcia) == 0)
		egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);

M bitsy/devuda1341.c => bitsy/devuda1341.c +85 -37
@@ 19,7 19,7 @@
#include	"io.h"
#include	"sa1110dma.h"

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

/*
 * GPIO based L3 bus support.


@@ 382,6 382,12 @@ L3_read(uchar addr, uchar *data, int len)
	return bytes;
}

void
audiomute(int on)
{
	egpiobits(EGPIO_audio_mute, on);
}

static	char	Emode[]		= "illegal open mode";
static	char	Evolume[]	= "illegal volume specifier";



@@ 390,7 396,7 @@ bufinit(IOstate *b)
{
	int i;

	if (debug) print("#A: bufinit\n");
	if (debug) print("bufinit\n");
	for (i = 0; i < Nbuf; i++) {
		b->buf[i].virt = xalloc(Bufsize);
		b->buf[i].phys = PADDR(b->buf[i].virt);


@@ 403,7 409,7 @@ setempty(IOstate *b)
{
	int i;

	if (debug) print("#A: setempty\n");
	if (debug) print("setempty\n");
	for (i = 0; i < Nbuf; i++) {
		b->buf[i].nbytes = 0;
	}


@@ 470,7 476,7 @@ enable(void)
	sspregs->control0 = 0x039f;	/* enable */

	/* Enable the audio power */
	audiopower(1);
	egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 1);

	/* external clock configured for 44100 samples/sec */
	gpioregs->set	= GPIO_CLK_SET0_o;


@@ 492,15 498,14 @@ enable(void)
	L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data0e6, 2 );

	if (debug) {
		print("uchar	status0	= 0x%2.2ux\n", status0);
		print("uchar	status1	= 0x%2.2ux\n", status1);
		print("uchar	data02	= 0x%2.2ux\n", data02);
		print("ushort	data0e2	= 0x%4.4ux\n", data0e2);
		print("ushort	data0e4	= 0x%4.4ux\n", data0e4);
		print("ushort	data0e6	= 0x%4.4ux\n", data0e6);
		print("#A: audio enabled\n");
		print("\tsspregs->control0 = 0x%lux\n", sspregs->control0);
		print("\tsspregs->control1 = 0x%lux\n", sspregs->control1);
		print("enable:	status0	= 0x%2.2ux\n", status0);
		print("enable:	status1	= 0x%2.2ux\n", status1);
		print("enable:	data02	= 0x%2.2ux\n", data02);
		print("enable:	data0e2	= 0x%4.4ux\n", data0e2);
		print("enable:	data0e4	= 0x%4.4ux\n", data0e4);
		print("enable:	data0e6	= 0x%4.4ux\n", data0e6);
		print("enable:	sspregs->control0 = 0x%lux\n", sspregs->control0);
		print("enable:	sspregs->control1 = 0x%lux\n", sspregs->control1);
	}
}



@@ 521,7 526,6 @@ static void
mxvolume(void) {
	int *left, *right;

	if (debug) print("mxvolume\n");
	if(audio.amode & Aread){
		left = audio.livol;
		right = audio.rivol;


@@ 540,7 544,16 @@ mxvolume(void) {
			L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data0e4, 2 );
			L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data0e5, 2 );
		}
		
		if (left[Vinvert]+right[Vinvert] == 0)
			status1 &= ~0x04;
		else
			status1 |= 0x04;
		L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1);
		if (debug) {
			print("mxvolume:	status1	= 0x%2.2ux\n", status1);
			print("mxvolume:	data0e4	= 0x%4.4ux\n", data0e4);
			print("mxvolume:	data0e5	= 0x%4.4ux\n", data0e5);
		}
	}
	if(audio.amode & Awrite){
		left = audio.lovol;


@@ 562,27 575,26 @@ mxvolume(void) {
		else
			data02 |= 0x10;
		if (left[Vinvert]+right[Vinvert] == 0)
			status1 &= ~0x14;
			status1 &= ~0x10;
		else
			status1 |= 0x14;
			status1 |= 0x10;
		L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1);
		L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data00, 1);
		L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data01, 1);
		L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data02, 1);
		if (debug) {
			print("uchar	status1	= 0x%2.2ux;\n", status1);
			print("uchar	data00	= 0x%2.2ux; /* audio out */\n", data00);
			print("uchar	data01	= 0x%2.2ux; /* bass&treb */\n", data01);
			print("uchar	data02	= 0x%2.2ux; /* mode */\n", data02);
			print("mxvolume:	status1	= 0x%2.2ux\n", status1);
			print("mxvolume:	data00	= 0x%2.2ux\n", data00);
			print("mxvolume:	data01	= 0x%2.2ux\n", data01);
			print("mxvolume:	data02	= 0x%2.2ux\n", data02);
		}
	}

}

static void
outenable(void) {
	/* turn on DAC, set output gain switch */
	amplifierpower(1);
	egpiobits(EGPIO_audio_power, 1);
	audiomute(0);
	status1 |= 0x41;
	L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1);


@@ 590,40 602,62 @@ outenable(void) {
	data00 |= 0xf;
	L3_write(UDA1341_L3Addr | UDA1341_DATA0, (uchar*)&data00, 1);
	if (debug) {
		print("uchar	status1	= 0x%2.2ux\n", status1);
		print("uchar	data00	= 0x%2.2ux\n", data00);
		print("outenable:	status1	= 0x%2.2ux\n", status1);
		print("outenable:	data00	= 0x%2.2ux\n", data00);
	}
}

static void
outdisable(void) {
	dmastop(audio.o.dma);
	/* turn off DAC, clear output gain switch */
	audiomute(1);
	amplifierpower(0);
	egpiobits(EGPIO_audio_power, 0);
	status1 &= ~0x41;
	L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1);
	if (debug) {
		print("uchar	status1	= 0x%2.2ux\n", status1);
		print("outdisable:	status1	= 0x%2.2ux\n", status1);
	}
	egpiobits(EGPIO_audio_power, 0);
}

static void
inenable(void) {
	/* turn on ADC, set input gain switch */
//	egpiobits(EGPIO_audio_power, 1);
//	audiomute(0);
	status1 |= 0x22;
	L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1);
	if (debug) {
		print("uchar	status1	= 0x%2.2ux\n", status1);
		print("inenable:	status1	= 0x%2.2ux\n", status1);
	}
}

static void
indisable(void) {
	dmastop(audio.i.dma);
	/* turn off ADC, clear input gain switch */
	status1 &= ~0x22;
	L3_write(UDA1341_L3Addr | UDA1341_STATUS, (uchar*)&status1, 1);
	if (debug) {
		print("uchar	status1	= 0x%2.2ux\n", status1);
		print("indisable:	status1	= 0x%2.2ux\n", status1);
	}
}

static void
disable(void) {
	egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 0);
}

static void
audiopower(int flag) {
	if (flag) {
		egpiobits(EGPIO_audio_power, 1);
		egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 1);
	} else {
		/* power off */
		egpiobits(EGPIO_audio_power, 0);
		egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 0);
	}
}



@@ 649,7 683,12 @@ sendaudio(IOstate *s) {
			iostats.faildma++;
			break;
		}
		if (debug > 1) print("#A: dmastart @%p\n", s->next);
		if (debug) {
			if (debug > 1)
				print("dmastart @%p\n", s->next);
			else
				iprint("+");
		}
		s->next->nbytes = 0;
		s->next++;
		if (s->next == &s->buf[Nbuf])


@@ 680,7 719,12 @@ recvaudio(IOstate *s) {
			iostats.faildma++;
			break;
		}
		if (debug > 1) print("#A: dmastart @%p\n", s->next);
		if (debug) {
			if (debug > 1)
				print("dmastart @%p\n", s->next);
			else
				iprint("+");
		}
		s->next++;
		if (s->next == &s->buf[Nbuf])
			s->next = &s->buf[0];


@@ 692,7 736,12 @@ static void
audiointr(void *x, ulong ndma) {
	IOstate *s = x;

	if (debug > 1) iprint("#A: audio interrupt @%p\n", s->current);
	if (debug) {
		if (debug > 1)
			iprint("#A: audio interrupt @%p\n", s->current);
		else
			iprint("-");
	}
	/* Only interrupt routine touches s->current */
	s->current++;
	if (s->current == &s->buf[Nbuf])


@@ 762,7 811,7 @@ audioopen(Chan *c, int mode)
			setempty(s);
			s->emptying = &s->buf[Nbuf-1];
			s->chan = c;
			s->dma = dmaalloc(0, 0, 4, 2, SSPRecvDMA, Port4SSP, audiointr, (void*)s);
			s->dma = dmaalloc(1, 0, 4, 2, SSPRecvDMA, Port4SSP, audiointr, (void*)s);
		}
		if (omode & Awrite) {
			outenable();


@@ 777,7 826,7 @@ audioopen(Chan *c, int mode)
		resetlevel();
		mxvolume();
		qunlock(&audio);
		if (debug) print("#A: open done\n");
		if (debug) print("open done\n");
		break;
	}
	c = devopen(c, mode, audiodir, nelem(audiodir), devgen);


@@ 829,7 878,6 @@ audioclose(Chan *c)
				}
				dmawait(s->dma);
				outdisable();
				amplifierpower(0);
				setempty(s);
				dmafree(s->dma);
				qunlock(s);


@@ 844,7 892,6 @@ audioclose(Chan *c)
					qunlock(s);
					nexterror();
				}
				dmawait(s->dma);
				indisable();
				setempty(s);
				dmafree(s->dma);


@@ 853,7 900,7 @@ audioclose(Chan *c)
			}
			if (audio.amode == 0) {
				/* turn audio off */
				audiopower(0);
				egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 0);
			}
			qunlock(&audio);
			poperror();


@@ 1127,4 1174,5 @@ Dev uda1341devtab = {
	devbwrite,
	devremove,
	devwstat,
	audiopower,
};

M bitsy/fns.h => bitsy/fns.h +1 -0
@@ 25,6 25,7 @@ char*	getconf(char*);
ulong	getfar(void);
ulong	getfsr(void);
#define	getpgcolor(a)	0
void	gpiointrenable(ulong, int, void (*)(Ureg*, void*), void*, char*)
void	h3650uartsetup(void);
void	icacheinvalidate(void);
void	idle(void);

M bitsy/io.h => bitsy/io.h +10 -0
@@ 109,6 109,16 @@ enum
	GPIO_32_768kHz_o=	1<<27,	/* 32.768 kHz clock (O, RTC) */
};

/*
 *  edge argument for gpiointrenable
 */
enum
{
	GPIOrising,
	GPIOfalling,
	GPIOboth,
};

/* hardware registers */
typedef struct Uartregs Uartregs;
struct Uartregs

M bitsy/main.c => bitsy/main.c +0 -18
@@ 426,24 426,6 @@ lcdpower(int on)
}

void
audiopower(int on)
{
	egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, on);
}

void
amplifierpower(int on)
{
	egpiobits(EGPIO_audio_power, on);
}

void
audiomute(int on)
{
	egpiobits(EGPIO_audio_mute, on);
}

void
flashprogpower(int on)
{
	egpiobits(EGPIO_prog_flash, on);

A bitsy/power.c => bitsy/power.c +26 -0
@@ 0,0 1,26 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"ureg.h"
#include	"init.h"
#include	"pool.h"

/* Power management for the bitsy */

static void
powerintr(Ureg*, void *x)
{
	/* Power button interrupt */
	int i;

	/* debounce, 50 ms*/
	for (i = 0; i < 50; i++) {
		delay(1);
		if ((gpioregs->level & GPIO_PWR_ON_i) == 0)
			return;	/* bounced */
	}
	rs232power(0);
}

M bitsy/sa1110dma.c => bitsy/sa1110dma.c +15 -1
@@ 115,6 115,11 @@ dmafree(int i) {
	dma.chan[i].intr = nil;
}

void
dmastop(int i) {
	dmaregs[i].dcsr_clr = 0xff;
}

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


@@ 194,12 199,21 @@ dmaintr(Ureg*, void *x)
		iprint("error, channel %d, status 0x%lux\n", i, dcsr);
	donebit = 1<<((dcsr&1<<BIU)?DONEA:DONEB);
	if (dcsr & donebit) {
		regs->dcsr_clr = donebit;
		regs->dcsr_clr = 1<<DONEA|1<<DONEB;
		if (dma.chan[i].intr) {
			(*dma.chan[i].intr)(dma.chan[i].param, dcsr & (1<<DONEA|1<<DONEB));
		}
		wakeup(&dma.chan[i].r);
		return;
	}
	if (dcsr & 1<<ERROR) {
		regs->dcsr_clr = ERROR;
		iprint("DMA error, channel %d, status 0x%lux\n", i, dcsr);
		if (dma.chan[i].intr) {
			(*dma.chan[i].intr)(dma.chan[i].param, 0);
		}
		wakeup(&dma.chan[i].r);
		return;
	}
	iprint("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
}

M bitsy/sa1110dma.h => bitsy/sa1110dma.h +1 -0
@@ 14,4 14,5 @@ void	dmafree(int);
ulong	dmastart(int, ulong, int);

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

M bitsy/trap.c => bitsy/trap.c +42 -0
@@ 128,6 128,44 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
}

/*
 *  enable an interrupt on gpio line.  edge is encoded as follows
 */
void
gpiointrenable(ulong bit, int edge, void (*f)(Ureg*, void*), void* a, char *name)
{
	int irq;

	/* figure out which interrupt */
	for(irq = 0; irq < 28; irq++)
		if((1<<irq) & bit)
			break;
	if(irq >= 28)
		panic("gpiointrenable %lux", bit);
	if(irq > 11)
		irq = 11;

	/* it had better be input */
	if(bit & gpioregs->direction)
		panic(""gpiointrenable %lux of output pin", bit);

	/* set edge register */
	switch(edge){
	case GPIOboth:
		gpioregs->rising |= bit;
		gpioregs->falling |= bit;
		break;
	case GPIOfalling:
		gpioregs->falling |= bit;
		break;
	case GPIOrising:
		gpioregs->rising |= bit;
		break;
	}

	intrenable(irq, f, a, name);
}

/*
 *  called by trap to handle access faults
 */
static void


@@ 196,6 234,10 @@ trap(Ureg *ureg)
	if(ureg->type == PsrMirq){
		found = 0;
		va = intrregs->icip;

		/* clear any gpio edge interrupt */
		gpioregs->irqbit = va & 0xFFF;

		for(v = vctl; v != nil; v = v->next){
			if(v->irqbit & va){
				v->f(ureg, v->a);

M port/portdat.h => port/portdat.h +1 -0
@@ 193,6 193,7 @@ struct Dev
	long	(*bwrite)(Chan*, Block*, ulong);
	void	(*remove)(Chan*);
	void	(*wstat)(Chan*, char*);
	void	(*power)(int);	/* power mgt: power(1) → on, power (0) → off */
};

struct Dirtab