~kris/9p

9hist

0ae1ad81d8abfc17b5f227de54b1ac95392e143b — David du Colombier 25 years ago c4587b9
Plan 9 from Bell Labs 2000-11-10
M bitsy/clock.c => bitsy/clock.c +17 -0
@@ 66,3 66,20 @@ delay(int ms)
		}
	}
}

void
µdelay(int µs)
{
	ulong start;
	int i;

	if(clockinited){
		start = timerregs->oscr;
		while(timerregs->oscr - start < µs∗ClockFreq/1000000);
	} else {
		while(µs-- > 0){
			for(i = 0; i < 10; i++)
				;
		}
	}
}

M bitsy/devuda1341.c => bitsy/devuda1341.c +185 -121
@@ 17,6 17,7 @@
#include	"fns.h"
#include	"../port/error.h"
#include	"io.h"
#include	"sa1110dma.h"

/*
 * GPIO based L3 bus support.


@@ 122,7 123,6 @@ audiodir[] =

struct	Buf
{
	int		active;			/* dma running */
	uchar*	virt;
	uint	nbytes;
};


@@ 130,11 130,15 @@ struct	Buf
struct	IOstate
{
	QLock;
	Rendez	vous;
	int		bufinit;		/* boolean, if buffers allocated */
	Buf		buf[Nbuf];		/* buffers and queues */
	Buf		*current;		/* next candidate for dma */
	Buf		*filling;		/* buffer being filled */
	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 */
	int				active;			/* # of dmas in progress */
	volatile Buf	*current;		/* next dma to finish */
	volatile Buf	*next;			/* next candidate for dma */
	volatile Buf	*filling;		/* buffer being filled */
};

static	struct


@@ 177,29 181,32 @@ static	struct
/*
 * Grab control of the IIC/L3 shared pins
 */
static void L3_acquirepins(void)
static void
L3_acquirepins(void)
{
	GPSR = (GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
	GPDR |=  (GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
	gpioregs->set = (GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
	gpioregs->direction |=  (GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
}

/*
 * Release control of the IIC/L3 shared pins
 */
static void L3_releasepins(void)
static void
L3_releasepins(void)
{
	GPDR &= ~(GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
	GPCR = (GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
	gpioregs->direction &= ~(GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
	gpioregs->clear = (GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
}

/*
 * Initialize the interface
 */
static void __init L3_init(void)
static void 
L3_init(void)
{
	GAFR &= ~(GPIO_L3_SDA_io | GPIO_L3_SCLK_o | GPIO_L3_MODE_o);
	GPSR = GPIO_L3_MODE_o;
	GPDR |= GPIO_L3_MODE_o;
	gpioregs->altfunc &= ~(GPIO_L3_SDA_io | GPIO_L3_SCLK_o | GPIO_L3_MODE_o);
	gpioregs->set = GPIO_L3_MODE_o;
	gpioregs->direction |= GPIO_L3_MODE_o;
	L3_releasepins();
}



@@ 207,17 214,18 @@ static void __init L3_init(void)
 * Get a bit. The clock is high on entry and on exit. Data is read after
 * the clock low time has expired.
 */
static int L3_getbit(void)
static int
L3_getbit(void)
{
	int data;

	GPCR = GPIO_L3_SCLK_o;
	udelay(L3_ClockLowTime);
	gpioregs->clear = GPIO_L3_SCLK_o;
	µdelay(L3_ClockLowTime);

	data = (GPLR & GPIO_L3_SDA_io) ? 1 : 0;
	data = (gpioregs->level & GPIO_L3_SDA_io) ? 1 : 0;

 	GPSR = GPIO_L3_SCLK_o;
	udelay(L3_ClockHighTime);
 	gpioregs->set = GPIO_L3_SCLK_o;
	µdelay(L3_ClockHighTime);

	return data;
}


@@ 226,20 234,21 @@ static int L3_getbit(void)
 * Send a bit. The clock is high on entry and on exit. Data is sent only
 * when the clock is low (I2C compatibility).
 */
static void L3_sendbit(int bit)
static void
L3_sendbit(int bit)
{
	GPCR = GPIO_L3_SCLK_o;
	gpioregs->clear = GPIO_L3_SCLK_o;

	if (bit & 1)
		GPSR = GPIO_L3_SDA_io;
		gpioregs->set = GPIO_L3_SDA_io;
	else
		GPCR = GPIO_L3_SDA_io;
		gpioregs->clear = GPIO_L3_SDA_io;

	/* Assumes L3_DataSetupTime < L3_ClockLowTime */
	udelay(L3_ClockLowTime);
	µdelay(L3_ClockLowTime);

	GPSR = GPIO_L3_SCLK_o;
	udelay(L3_ClockHighTime);
	gpioregs->set = GPIO_L3_SCLK_o;
	µdelay(L3_ClockHighTime);
}

/*


@@ 247,34 256,35 @@ static void L3_sendbit(int bit)
 * count. The mode line is high on entry and exit. The mod line is pulsed
 * before the second data byte and before ech byte thereafter.
 */
static void L3_sendbyte(char data, int mode)
static void
L3_sendbyte(char data, int mode)
{
	int i;

	L3_acquirepins();

	switch(mode) {
	    case 0: /* Address mode */
		GPCR = GPIO_L3_MODE_o;
	case 0: /* Address mode */
		gpioregs->clear = GPIO_L3_MODE_o;
		break;
	    case 1: /* First data byte */
	case 1: /* First data byte */
		break;
	    default: /* Subsequent bytes */
		GPCR = GPIO_L3_MODE_o;
		udelay(L3_HaltTime);
		GPSR = GPIO_L3_MODE_o;
	default: /* Subsequent bytes */
		gpioregs->clear = GPIO_L3_MODE_o;
		µdelay(L3_HaltTime);
		gpioregs->set = GPIO_L3_MODE_o;
		break;
	}

	udelay(L3_ModeSetupTime);
	µdelay(L3_ModeSetupTime);

	for (i = 0; i < 8; i++)
		L3_sendbit(data >> i);

	if (mode == 0)  /* Address mode */
		GPSR = GPIO_L3_MODE_o;
		gpioregs->set = GPIO_L3_MODE_o;

	udelay(L3_ModeHoldTime);
	µdelay(L3_ModeHoldTime);

	L3_releasepins();
}


@@ 286,32 296,33 @@ static void L3_sendbyte(char data, int mode)
 * function is never valid with mode == 0 (address cycle) as the address
 * is always sent on the bus, not read.
 */
static char L3_getbyte(int mode)
static char
L3_getbyte(int mode)
{
	char data = 0;
	int i;

	L3_acquirepins();
	GPDR &= ~(GPIO_L3_SDA_io);
	gpioregs->direction &= ~(GPIO_L3_SDA_io);

	switch(mode) {
	    case 0: /* Address mode - never valid */
	case 0: /* Address mode - never valid */
		break;
	    case 1: /* First data byte */
	case 1: /* First data byte */
		break;
	    default: /* Subsequent bytes */
		GPCR = GPIO_L3_MODE_o;
		udelay(L3_HaltTime);
		GPSR = GPIO_L3_MODE_o;
	default: /* Subsequent bytes */
		gpioregs->clear = GPIO_L3_MODE_o;
		µdelay(L3_HaltTime);
		gpioregs->set = GPIO_L3_MODE_o;
		break;
	}

	udelay(L3_ModeSetupTime);
	µdelay(L3_ModeSetupTime);

	for (i = 0; i < 8; i++)
		data |= (L3_getbit() << i);

	udelay(L3_ModeHoldTime);
	µdelay(L3_ModeHoldTime);

	L3_releasepins();



@@ 324,7 335,8 @@ static char L3_getbyte(int mode)
 * is encoded in the address (low two bits are set and device address is
 * in the upper 6 bits).
 */
static int L3_write(char addr, char *data, int len)
static int
L3_write(char addr, char *data, int len)
{
	int mode = 0;
	int bytes = len;


@@ 342,7 354,8 @@ static int L3_write(char addr, char *data, int len)
 * is encoded in the address (low two bits are set and device address is
 * in the upper 6 bits).
 */
static int L3_read(char addr, char * data, int len)
static int
L3_read(char addr, char * data, int len)
{
	int mode = 0;
	int bytes = len;


@@ 378,27 391,70 @@ setempty(IOstate *b)
	}
	b->filling = b->buf;
	b->current = b->buf;
	b->next = b->buf;
}

static int
audioqnotfull(IOstate *s)
{
	/* called with lock */
	return s->active == 0 || s->filling != s->current;
}

static int
audioqnotempty(IOstate *s)
{
	/* called with lock */
	return s->next != s->filling;
}

static int
audioidle(IOstate *s)
{
	/* called with lock */
	return s->active == 0;
}

static void
audioinit(void)
{
	/* do nothing */
}

static void
audioenable(void)
{
	int err;
   
	/* Acquire and initialize DMA */
	if( audio_init_dma( &output_stream, "UDA1341 DMA out" ) ||
	    audio_init_dma( &input_stream, "UDA1341 DMA in" ) ){
		audio_clear_dma( &output_stream );
		audio_clear_dma( &input_stream );
		return -EBUSY;
	}

	L3_init();
	audio_ssp_init();

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

	init_waitqueue_head(&audio_waitq);
    gpioregs->altfunc &= ~(GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM);
	gpioregs->altfunc |= (GPIO_SSP_CLK);
	gpioregs->direction &= ~(GPIO_SSP_CLK);

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

	/* Enable the audio power */
          set_bitsy_egpio(EGPIO_BITSY_CODEC_NRESET|EGPIO_BITSY_AUD_AMP_ON|EGPIO_BITSY_AUD_PWR_ON);
          clr_bitsy_egpio(EGPIO_BITSY_QMUTE);
	  gpioregs->direction |=  (GPIO_BITSY_CLK_SET0|GPIO_BITSY_CLK_SET1);
	  /* external clock configured for 44100 samples/sec */
          GPSR =   GPIO_BITSY_CLK_SET0;
          GPCR =   GPIO_BITSY_CLK_SET1;

 
        printk("gpioregs->altfunc=%08x gpioregs->direction=%08x GPLR=%08x\n", gpioregs->altfunc, gpioregs->direction, GPLR);
        printk("PPDR=%08x PPSR=%08x PPAR=%08x PPFR=%08x\n", PPDR, PPSR, PPAR, PPFR);

	/* Wait for the UDA1341 to wake up */
	mdelay(100);
        printk("Ser4SSSR=%08x\n", Ser4SSSR);

    audio_uda1341_reset();

	/* Set some default mixer values... */
	STATUS_1.DAC_gain = 1;


@@ 416,23 472,42 @@ audioinit(void)
	DATA0_ext6.AGC_level = 3;
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_ext6, 2 );

	/* register devices */
	audio_dev_dsp = register_sound_dsp(&UDA1341_dsp_fops, -1);
	audio_dev_mixer = register_sound_mixer(&UDA1341_mixer_fops, -1);

	printk( AUDIO_NAME_VERBOSE " initialized\n" );
	print("audio enabled\n");

	return 0;
}

static void
sendaudio(IOstat *b) {
	if (dmastart(b->chan, b->current->virt, b->current->nbytes)) {
		b->current->active++;
		b->current++;
	/* call this with lock held */
	while (b->next != b->filling) {
		assert(b->next->nbytes);
		if (dmastart(b->dma, b->next->virt, b->next->nbytes) == 0)
			break;
		incref(&b->active);
		b->next++;
		if (b->next == &b->buf[Nbuf])
			b->next == &b->buf[0];
	}
}

static void
audiointr(void *x, ulong state) {
	IOstate *s = x;

	if (s == &audio.o) {
		decref(&s->active);
		/* Only interrupt routine touches s->current */
		s->current->nbytes = 0;
		s->current++;
		if (b->current == &b->buf[Nbuf])
			b->current == &b->buf[0];
		if (canlock(s)) {
			sendaudio(s);
			unlock(s);
		}
	}
	wakeup(s->vous);
}

static Chan*


@@ 471,26 546,33 @@ audioopen(Chan *c, int omode)

	case Qaudio:
		omode = (omode & 0x7) + 1;
		if (omode & ~(Aread | Awrite))
//		if (omode & ~(Aread | Awrite))
		if (omode & ~(Awrite))
			error(Ebadarg);
		qlock(&audio);
		if(audio.amode & omode){
			qunlock(&audio);
			error(Einuse);
		}
		audiopower(1);
		if (omode & Aread) {
			/* read */
			audio.amode |= Aread;
			if(audio.i.bufinit == 0)
				bufinit(&audio.i);
			audio.i.chan = c;
			setempty(&audio.i);
		}
		if (omode & 0x2) {
			/* write */
			amplifierpower(1);
			audiomute(0);
			audio.amode |= Awrite;
			if(audio.o.bufinit == 0)
				bufinit(&audio.o);
			setempty(&audio.o);
			audio.o.chan = c;
			&audio.o.dma = dmaalloc(0, 0, 8, 2, AudioDMA, void *port, void (*f)(int, ulong))
		}
		qunlock(&audio);
//		mxvolume();


@@ 507,7 589,7 @@ audioopen(Chan *c, int omode)
static void
audioclose(Chan *c)
{
	Buf *b;
	IOstate *b;

	switch(c->qid.path & ~CHDIR) {
	default:


@@ 522,22 604,38 @@ audioclose(Chan *c)
	case Qaudio:
		if(c->flag & COPEN) {
			qlock(&audio);
			if(audio.amode & Awrite) {
				/* flush out last partial buffer */
				b = audio.o.filling;
				if(audio.o.buf[b].count) {
					putbuf(&audio.full, b);
				}
			}
			audio.amode = Aclosed;
			qlock(&audio.o);
			if(waserror()){
				qunlock(&audio.o);
				qunlock(&audio);
				nexterror();
			}
			while(audio.active)
				waitaudio();
			setempty();
			if (audio.o.chan == c) {
				/* closing the write end */
				audio.amode &= ~Awrite;

				while (audio.o.filling->nbytes) {
					audio.o.filling++;
					if (audio.o.filling == &audio.o.buf[Nbuf])
						audio.o.filling = &audio.o.buf[0];
					sendaudio(&audio.o);
				}
				while(!audioidle(&audio.o))
					sleep(&audio.o.vous, audioidle, &audio.o);
				audioamplifier(0);
				setempty(&audio.o);
			}
			if (audio.i.chan == c) {
				/* closing the read end */
				audio.amode &= ~Aread;
				setempty(&audio.i);
			}
			if (audio.amode == 0) {
				/* turn audio off */
				audiopower(0);
			}
			poperror();
			qunlock(&audio.o);
			qunlock(&audio);
		}
		break;


@@ 566,40 664,6 @@ audioread(Chan *c, void *v, long n, vlong off)
		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:


@@ 752,8 816,8 @@ audiowrite(Chan *c, void *vp, long n, vlong)
		}
		while(n > 0) {
			/* wait if dma in progress */
			while (a->filling->active)
				waitaudio(a);
			while (a->active && a->filling == a->current)
				sleep(&a->vous, audioqnotfull, a);

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


@@ 764,10 828,10 @@ audiowrite(Chan *c, void *vp, long n, vlong)
			n -= m;
			p += m;
			if(a->filling->nbytes >= Bufsize) {
				sendaudio(a);
				a->filling++;
				if (a->filling == &a->buf[Nbuf])
					a->filling = a->buf;
				sendaudio(a);
			}
		}
		poperror();

M bitsy/fns.h => bitsy/fns.h +1 -6
@@ 10,12 10,7 @@ int	cistrncmp(char*, char*, int);
void	clockinit(void);
#define	coherence()
void	delay(int);
void	dmainit(void);
int		dmaalloc(int, int, int, int, int, void *);
void	dmafree(int);
ulong	dmastart(int, void *, int);
ulong	dmadone(int, ulong);
void	dmawait(int, ulong);
void	µdelay(int);
void	evenaddr(ulong);
void	flushmmu(void);
int		fpiarm(Ureg *ur);

M bitsy/io.h => bitsy/io.h +23 -0
@@ 199,3 199,26 @@ enum
	EGPIO_lcd_9v=		1<<15,
};
extern ulong *egpioreg;

/* Peripheral pin controller registers */
typedef struct PPCregs PPCregs;
struct PPCregs {
	ulong	direction;
	ulong	state;
	ulong	assignment;
	ulong	sleepdir;
	ulong	flags;
};
extern PPCregs *ppcregs;

/* Synchronous Serial Port controller registers */
typedef struct SSPregs SSPregs;
struct SSPregs {
	ulong	control0;
	ulong	control1;
	ulong	dummy0;
	ulong	data;
	ulong	dummy1;
	ulong	status;
};
extern SSPregs *sspregs;

M bitsy/main.c => bitsy/main.c +46 -0
@@ 36,6 36,8 @@ main(void)
	xinit();
	mmuinit();
	gpioinit();
	ppcinit();
	sspinit();
	trapinit();
	sa1100_uartsetup(1);
	rs232power(1);


@@ 374,6 376,20 @@ gpioinit(void)
	egpioreg = mapspecial(EGPIOREGS, 4);
}

PPCregs *ppcregs;

static void
ppcinit(void) {
	ppcregs = mapspecial(PPCREGS, 32);
}

SSPregs *sspregs;

static void
sspinit(void) {
	sspregs = mapspecial(SSPREGS, 32);
}

static ulong egpiosticky;

void


@@ 405,3 421,33 @@ lcdpower(int on)
		egpiosticky &= ~(EGPIO_lcd_3v|EGPIO_lcd_ic_power|EGPIO_lcd_5v|EGPIO_lcd_9v);
	*egpioreg = egpiosticky;
}

void
audiopower(int on)
{
	if(on)
		egpiosticky |= EGPIO_audio_ic_power | EGPIO_codec_reset;
	else
		egpiosticky &= ~(EGPIO_audio_ic_power | EGPIO_codec_reset);
	*egpioreg = egpiosticky;
}

void
amplifierpower(int on)
{
	if(on)
		egpiosticky |= EGPIO_audio_power;
	else
		egpiosticky &= ~(EGPIO_audio_power);
	*egpioreg = egpiosticky;
}

void
audiomute(int on)
{
	if(on)
		egpiosticky |= EGPIO_audio_mute;
	else
		egpiosticky &= ~(EGPIO_audio_mute);
	*egpioreg = egpiosticky;
}

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

/*
 *	DMA helper routines


@@ 40,7 41,8 @@ enum {
typedef struct Chan {
	int		inuse;
	Rendez	r;
	void	(*f)(void);
	void	(*intr)(int, ulong);
	void	*param;
} Chan;

struct {


@@ 66,7 68,7 @@ dmainit(void) {
}

int
dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, void *port) {
dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, void *port, void (*intr)(int, ulong), void *param) {
	int i;

	lock(&dma);


@@ 82,6 84,8 @@ dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, void *
			((datumsize==2)?1:0)<<DW |
			device<<DS |
			0x80000000 | ((ulong)port << 6);
		dma.chan[i].intr = intr;
		dma.chan[i].param = param;
		return i;
	}
	unlock(&dma);


@@ 91,6 95,7 @@ dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, void *
void
dmafree(int i) {
	dma.chan[i].inuse = 0;
	dma.chan[i].intr = nil;
}

static int


@@ 132,6 137,16 @@ dmadone(int chan, ulong op) {
	return dcsr & (op | 1<<ERROR);
}

int
dmaidle(int chan) {
	ulong dcsr;

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

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


@@ 154,7 169,7 @@ dmaintr(Ureg*, void *x)
	for (i = 0; i < NDMA; i++) {
		if ((dcsr = dmaregs[i].dcsr_rd) & (1<<DONEA | 1<<DONEB | 1<<ERROR))
			wakeup(&dma.chan[i].r);
			if (dma.chan[i].f)
				(*dma.chan[i].f)(dcsr);
			if (dma.chan[i].intr)
				(*dma.chan[i].intr)(dma.chan[i].param, dcsr);
	}
}

A bitsy/sa1110dma.h => bitsy/sa1110dma.h +13 -0
@@ 0,0 1,13 @@

enum {
	Port4MCP		= 0x80060008,
	Port4SSP		= 0x8007006c,
};

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

M pc/devether.c => pc/devether.c +1 -1
@@ 382,7 382,7 @@ etherreset(void)
			snprint(name, sizeof(name), "ether%d", ctlrno);

			/* If ether->irq is less than 0, it is a hack to indicate no interrupt
			 * used for the seocnd logical ethernet for the wavelan card
			 * used for the second logical ethernet for the wavelan card
			 */
			if(ether->irq >= 0)
				intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);

M pc/devi82365.c => pc/devi82365.c +0 -1
@@ 1498,6 1498,5 @@ tvers1(Slot *pp, Cisdat *cis, int )
			break;
		pp->verstr[i] = c;
	}
print("pcmcia: %s\n", pp->verstr);
	pp->verstr[i] = 0;
}