~kris/9p

9hist

1cac83d73c4b20e3f73bb85f3051baf7b8d0704e — David du Colombier 27 years ago 75715a0
Plan 9 from Bell Labs 1999-04-23
M alphapc/arch164.c => alphapc/arch164.c +8 -3
@@ 54,15 54,17 @@ coreinit(void)
	}
	coresave[0] = core[0x140/4];

	/* direct map bottom 2G PCI target space to KZERO in window 1 */
	wind[0x500/4] = KZERO|1;
	wind[0x540/4] = 0x7ff00000;
#ifdef notdef
	/* direct map bottom 1G PCI target space to KZERO in window 1 */
	wind[0x500/4] = PCIWINDOW|1;
	wind[0x540/4] = 0x3ff00000;
	wind[0x580/4] = 0;

	/* disable other windows */
	wind[0x400/4] = 0;
	wind[0x600/4] = 0;
	wind[0x700/4] = 0;
#endif /* notdef */

	/* clear error state */
	core[0x8200/4] = 0x7ff;


@@ 263,6 265,7 @@ outb2117x(int port, int val)
{
	mb();
	*(uchar*)(iobase(port)) = val;
	mb();
}

void


@@ 270,6 273,7 @@ outs2117x(int port, ushort val)
{
	mb();
	*(ushort*)(iobase(port)) = val;
	mb();
}

void


@@ 277,6 281,7 @@ outl2117x(int port, ulong val)
{
	mb();
	*(ulong*)(iobase(port)) = val;
	mb();
}

void

M alphapc/devfloppy.c => alphapc/devfloppy.c +2 -37
@@ 118,10 118,8 @@ Dirtab floppydir[]={
static void
fldump(void)
{
mb();
	DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
		inb(Pdor), inb(Pmsr), inb(Pdir));
mb();
}

/*


@@ 146,8 144,6 @@ floppyreset(void)
	FDrive *dp;
	FType *t;
	ulong maxtsize;

	dmainit(DMAchan);
	
	floppysetup0(&fl);



@@ 163,6 159,8 @@ floppyreset(void)
			maxtsize = t->tsize;
	}

	dmainit(DMAchan, maxtsize);

	/*
	 *  allocate the drive storage
	 */


@@ 174,9 172,7 @@ floppyreset(void)
	 */
	fl.motor = 0;
	delay(10);
mb();
	outb(Pdor, fl.motor | Fintena | Fena);
mb();
	delay(10);

	/*


@@ 267,23 263,15 @@ changed(Chan *c, FDrive *dp)
	/*
	 *  if floppy has changed or first time through
	 */
mb();
	if((inb(Pdir)&Fchange) || dp->vers == 0){
mb();
		DPRINT("changed\n");
		fldump();
		dp->vers++;
		floppysetdef(dp);
		start = dp->t;
		dp->confused = 1;	/* make floppyon recal */
DPRINT("b4 floppyon:\n");
fldump();
		floppyon(dp);
DPRINT("after floppyon:\n");
fldump();
		floppyseek(dp, dp->t->heads*dp->t->tsize);
DPRINT("after floppyseek:\n");
fldump();
		while(waserror()){
			while(++dp->t){
				if(dp->t == &floppytype[nelem(floppytype)])


@@ 486,9 474,7 @@ floppyon(FDrive *dp)
	/* start motor and select drive */
	alreadyon = fl.motor & MOTORBIT(dp->dev);
	fl.motor |= MOTORBIT(dp->dev);
mb();
	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
mb();
	if(!alreadyon){
		/* wait for drive to spin up */
		tsleep(&dp->r, return0, 0, 750);


@@ 500,9 486,7 @@ mb();
	/* set transfer rate */
	if(fl.rate != dp->t->rate){
		fl.rate = dp->t->rate;
mb();
		outb(Pdsr, fl.rate);
mb();
	}

	/* get drive to a known cylinder */


@@ 521,9 505,7 @@ static void
floppyoff(FDrive *dp)
{
	fl.motor &= ~MOTORBIT(dp->dev);
mb();
	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
mb();
}

/*


@@ 538,10 520,8 @@ floppycmd(void)
	fl.nstat = 0;
	for(i = 0; i < fl.ncmd; i++){
		for(tries = 0; ; tries++){
mb();
			if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
				break;
mb();
			if(tries > 1000){
				DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
				fldump();


@@ 552,9 532,7 @@ mb();
			}
			microdelay(8);	/* for machine independence */
		}
mb();
		outb(Pfdata, fl.cmd[i]);
mb();
	}
	return 0;
}


@@ 576,9 554,7 @@ floppyresult(void)
	for(i = 0; i < sizeof(fl.stat); i++){
		/* wait for status byte */
		for(tries = 0; ; tries++){
mb();
			s = inb(Pmsr)&(Ffrom|Fready);
mb();
			if(s == Fready){
				fl.nstat = i;
				return fl.nstat;


@@ 593,10 569,7 @@ mb();
			}
			microdelay(8);	/* for machine independence */
		}
mb();
		fl.stat[i] = inb(Pfdata);
mb();
// print("stat[%d]: %.2ux\n", i, fl.stat[i]);
	}
	fl.nstat = sizeof(fl.stat);
	return fl.nstat;


@@ 686,9 659,7 @@ floppyrecal(FDrive *dp)
		return -1;
	floppywait();
	if(fl.nstat < 2){
mb();
		DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
mb();
		fl.confused = 1;
		return -1;
	}


@@ 729,13 700,9 @@ floppyrevive(void)
		splhi();
		fl.ncmd = 1;
		fl.cmd[0] = 0;
mb();
		outb(Pdor, 0);
mb();
		delay(10);
mb();
		outb(Pdor, Fintena|Fena);
mb();
		delay(10);
		spllo();
		fl.motor = 0;


@@ 747,9 714,7 @@ mb();
			dp->confused = 1;

		/* set rate to a known value */
mb();
		outb(Pdsr, 0);
mb();
		fl.rate = 0;

		DPRINT("floppyrevive out\n");

M alphapc/dma.c => alphapc/dma.c +37 -35
@@ 9,23 9,6 @@ typedef struct DMAport	DMAport;
typedef struct DMA	DMA;
typedef struct DMAxfer	DMAxfer;

enum
{
	/*
	 *  the byte registers for DMA0 are all one byte apart
	 */
	Dma0=		0x00,
	Dma0status=	Dma0+0x8,	/* status port */
	Dma0reset=	Dma0+0xD,	/* reset port */

	/*
	 *  the byte registers for DMA1 are all two bytes apart (why?)
	 */
	Dma1=		0xC0,
	Dma1status=	Dma1+2*0x8,	/* status port */
	Dma1reset=	Dma1+2*0xD,	/* reset port */
};

/*
 *  state of a dma transfer
 */


@@ 33,6 16,7 @@ struct DMAxfer
{
	ulong	bpa;		/* bounce buffer physical address */
	void*	bva;		/* bounce buffer virtual address */
	int	blen;		/* bounce buffer length */
	void*	va;		/* virtual address destination/src */
	long	len;		/* bytes to be transferred */
	int	isread;


@@ 84,29 68,42 @@ DMA dma[2] = {
 *  initialisation routines of any devices which require DMA to ensure
 *  the allocated bounce buffers are below the 16MB limit.
 */
void
dmainit(int chan)
int
dmainit(int chan, int maxtransfer)
{
	DMA *dp;
	DMAxfer *xp;
	ulong v;

	if(maxtransfer > 64*1024)
		maxtransfer = 64*1024;

	dp = &dma[(chan>>2)&1];
	chan = chan & 3;
	xp = &dp->x[chan];
	if(xp->bva != nil)
		return;

	v = (ulong)xalloc(BY2PG+BY2PG);
	if(v == 0 || PADDR(v) >= 16*MB){
		print("dmainit: chan %d: 0x%luX out of range\n", chan, v);
		xfree((void*)v);
		v = 0;
	if(xp->bva != nil){
		if(xp->blen < maxtransfer)
			return 1;
		return 0;
	}
	xp->bva = (void*)ROUND(v, BY2PG);

	xp->bva = xspanalloc(maxtransfer, BY2PG, 64*1024);
	if(xp->bva == nil)
		return 1;
	xp->bpa = PADDR(xp->bva);
	if(xp->bpa >= 16*MB){
		/*
		 * This will panic with the current
		 * implementation of xspanalloc().
		xfree(xp->bva);
		 */
		xp->bva = nil;
		return 1;
	}
	xp->blen = maxtransfer;
	xp->len = 0;
	xp->isread = 0;

	return 0;
}

/*


@@ 133,16 130,17 @@ dmasetup(int chan, void *va, long len, int isread)

	/*
	 *  if this isn't kernel memory or crossing 64k boundary or above 16 meg
	 *  use the allocated low memory page.
	 *  use the bounce buffer.
	 */
#ifdef notdef
	pa = PADDR(va);
	if((((ulong)va)&0xF0000000) != KZERO
	|| (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
	|| pa >= 16*MB) {
		if(xp->bva == nil)
			return -1;
		if(len > BY2PG)
			len = BY2PG;
		if(len > xp->blen)
			len = xp->blen;
		if(!isread)
			memmove(xp->bva, va, len);
		xp->va = va;


@@ 152,17 150,21 @@ dmasetup(int chan, void *va, long len, int isread)
	}
	else
		xp->len = 0;
#else
	pa = PCIWADDR(va);
#endif /* notdef */

	/*
	 * this setup must be atomic
	 */
	ilock(dp);
	mode = (isread ? 0x44 : 0x48) | chan;
	outb(dp->mode, mode);	/* single mode dma (give CPU a chance at mem) */
	outb(dp->page[chan], pa>>16);
	ilock(dp);
	outb(dp->cbp, 0);		/* set count & address to their first byte */
	outb(dp->mode, mode);	/* single mode dma (give CPU a chance at mem) */
	outb(dp->addr[chan], pa>>dp->shift);		/* set address */
	outb(dp->addr[chan], pa>>(8+dp->shift));
	outb(dp->page[chan], pa>>16);
outb(0x400|dp->page[chan], pa>>24);
	outb(dp->count[chan], (len>>dp->shift)-1);		/* set count */
	outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
	outb(dp->sbm, chan);		/* enable the channel */

M alphapc/ether2114x.c => alphapc/ether2114x.c +5 -8
@@ 21,9 21,6 @@

/* nasty PCI DMA hack... */

#undef	PADDR
#define	PADDR(a) ((ulong)(a))

#define DEBUG		0
#define debug		if(DEBUG)print



@@ 380,7 377,7 @@ txstart(Ether* ether)
		ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic;
		des = &ctlr->tdr[ctlr->tdrh];
		des->bp = bp;
		des->addr = PADDR(bp->rp);
		des->addr = PCIWADDR(bp->rp);
		des->control |= control;
		ctlr->ntq++;
		coherence();


@@ 465,7 462,7 @@ interrupt(Ureg*, void* arg)
					des->bp->wp = des->bp->rp+len;
					etheriq(ether, des->bp, 1);
					des->bp = bp;
					des->addr = PADDR(bp->rp);
					des->addr = PCIWADDR(bp->rp);
				}

				des->control &= Er;


@@ 574,17 571,17 @@ ctlrinit(Ether* ether)
		des->bp = allocb(ROUNDUP(sizeof(Etherpkt)+4, 4));
		des->status = Own;
		des->control = ROUNDUP(sizeof(Etherpkt)+4, 4);
		des->addr = PADDR(des->bp->rp);
		des->addr = PCIWADDR(des->bp->rp);
	}
	ctlr->rdr[ctlr->nrdr-1].control |= Er;
	ctlr->rdrx = 0;
	csr32w(ctlr, 3, PADDR(ctlr->rdr));
	csr32w(ctlr, 3, PCIWADDR(ctlr->rdr));

	ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0);
	ctlr->tdr[ctlr->ntdr-1].control |= Er;
	ctlr->tdrh = 0;
	ctlr->tdri = 0;
	csr32w(ctlr, 4, PADDR(ctlr->tdr));
	csr32w(ctlr, 4, PCIWADDR(ctlr->tdr));

	ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;
	csr32w(ctlr, 7, ctlr->mask);

M alphapc/fns.h => alphapc/fns.h +1 -1
@@ 15,7 15,7 @@ void		cserve(ulong, ulong);
int	dmacount(int);
int	dmadone(int);
void	dmaend(int);
void	dmainit(int);
int	dmainit(int, int);
long	dmasetup(int, void*, long, int);
void		evenaddr(ulong);
void		fataltrap(Ureg *, char *);

M alphapc/io.h => alphapc/io.h +3 -0
@@ 202,3 202,6 @@ typedef struct SCSIdev {
	char*	type;
	Scsiio	(*reset)(int, ISAConf*);
} SCSIdev;

#define PCIWINDOW	0x40000000
#define PCIWADDR(va)	(PADDR(va)+PCIWINDOW)

M alphapc/main.c => alphapc/main.c +1 -1
@@ 54,11 54,11 @@ main(void)
	percpu[32] |= (0<<16);		/* default action */
#endif

	pageinit();
	procinit0();
	initseg();
	links();
	chandevreset();
	pageinit();
	swapinit();
	userinit();
	schedinit();

M pc/devlml.c => pc/devlml.c +359 -38
@@ 13,10 13,8 @@
enum{
	Q819,
	Q856,
	Qi22,
	Q060,
	Q067,
	Qstat,
	Qvideo,
	Qjframe,
};


@@ 25,10 23,8 @@ static Dirtab viddir[]={
//	 name,		 qid,	  size,		mode
	"vid819",	{Q819},		0,		0644,
	"vid856",	{Q856},		0,		0644,
	"vidi22",	{Qi22},		0,		0644,
	"vid060",	{Q060},		0,		0644,
	"vid067",	{Q067},		0,		0644,
	"vidstat",	{Qstat},	0,		0444,
	"video",	{Qvideo},	0,		0666,
	"jframe",	{Qjframe},	0,		0666,
};


@@ 36,7 32,318 @@ static Dirtab viddir[]={
CodeData *	codeData;
MjpgDrv *	mjpgDrv;

static void lmlintr(Ureg *ur, void *arg);
static void
lml33_i2c_pause(void) {

	microdelay(I2C_DELAY);
}

static void
lml33_i2c_waitscl(void) {
	int i;
	ulong a;

	for(i=0;;i++) {
		a = readl(pciBaseAddr + ZR36057_I2C_BUS);
		if (a & ZR36057_I2C_SCL) break;
		if (i>I2C_TIMEOUT) error(Eio);
	}
}

static void
lml33_i2c_start(void) {

	writel(ZR36057_I2C_SCL|ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS);
	lml33_i2c_waitscl();
	lml33_i2c_pause();

	writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS);
	lml33_i2c_pause();

	writel(0, pciBaseAddr + ZR36057_I2C_BUS);
	lml33_i2c_pause();
}

static void
lml33_i2c_stop(void) {
	// the clock should already be low, make sure data is
	writel(0, pciBaseAddr + ZR36057_I2C_BUS);
	lml33_i2c_pause();

	// set clock high and wait for device to catch up
	writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS);
	lml33_i2c_waitscl();
	lml33_i2c_pause();

	// set the data high to indicate the stop bit
	writel(ZR36057_I2C_SCL|ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS);
	lml33_i2c_pause();
}

static void lml33_i2c_wrbit(int bit) {
	if (bit){
		writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); // set data
		lml33_i2c_pause();
		writel(ZR36057_I2C_SDA|ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS);
		lml33_i2c_waitscl();
		lml33_i2c_pause();
		writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS);
		lml33_i2c_pause();
	} else {
		writel(0, pciBaseAddr + ZR36057_I2C_BUS); // clr data
		lml33_i2c_pause();
		writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS);
		lml33_i2c_waitscl();
		lml33_i2c_pause();
		writel(0, pciBaseAddr + ZR36057_I2C_BUS);
		lml33_i2c_pause();
	}
}

static int
lml33_i2c_rdbit(void) {
	int bit;
	// the clk line should be low

	// ensure we are not asserting the data line
	writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS);
	lml33_i2c_pause();

	// set the clock high and wait for device to catch up
	writel(ZR36057_I2C_SDA|ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS);
	lml33_i2c_waitscl();
	lml33_i2c_pause();

	// the data line should be a valid bit
	bit = readl(pciBaseAddr+ZR36057_I2C_BUS);
	if (bit & ZR36057_I2C_SDA){
		bit = 1;
	} else {
		bit = 0;
	}

	// set the clock low to indicate end of cycle
	writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS);
	lml33_i2c_pause();

	return bit;
}

static int
lml33_i2c_rdbyte(uchar *v) {
	int i, ack;
	uchar res;

	res = 0;
	for (i=0;i<8;i++){
		res  = res << 1;
		res += lml33_i2c_rdbit();
	}

	ack = lml33_i2c_rdbit();

	*v = res;

	return ack;
}

static int
lml33_i2c_wrbyte(uchar v) {
	int i, ack;

	for (i=0;i<8;i++){
		lml33_i2c_wrbit(v & 0x80);
		v = v << 1;
	}

	ack = lml33_i2c_rdbit();

	return ack;
}

static void
lml33_i2c_write_bytes(uchar addr, uchar sub, uchar *bytes, long num) {
	int ack;
	long i;

	lml33_i2c_start();

	ack = lml33_i2c_wrbyte(addr);
	if (ack == 1) error(Eio);

	ack = lml33_i2c_wrbyte(sub);
	if (ack == 1) error(Eio);

	for(i=0;i<num;i+=1){
		ack = lml33_i2c_wrbyte(bytes[i]);
		if (ack == 1) error(Eio);
	}

	lml33_i2c_stop();
}

static uchar
lml33_i2c_rd8(int addr, int sub)
{
	int ack;
	uchar msb;

	lml33_i2c_start();

	ack = lml33_i2c_wrbyte(addr);
	if (ack == 1){
		lml33_i2c_stop();
		error(Eio);
	}

	ack = lml33_i2c_wrbyte(sub);
	if (ack == 1){
		lml33_i2c_stop();
		error(Eio);
	}

	lml33_i2c_start();

	ack = lml33_i2c_wrbyte(addr+1);
	if (ack == 1){
		lml33_i2c_stop();
		error(Eio);
	}

	ack = lml33_i2c_rdbyte(&msb);
	if (ack == 0){
		lml33_i2c_stop();
		error(Eio);
	}

	lml33_i2c_stop();

	return msb;
}

/*
 * The following mapping applies for the guests in the LML33
 *
 * Guest        Device
 *   0          zr36060
 *              uses subaddress GADR[0..1]
 *   1          zr36060 START#
 *   2          -
 *   3          zr36060 RESET#
 *   4          -
 *   5          -
 *   6          -
 *   7          -
 */

// lml33_post_idle waits for the guest bus to become free
static int
lml33_post_idle(void) {
	ulong a;
	int timeout;

	for(timeout = 0;;timeout += 1){
		a = readl(pciBaseAddr + ZR36057_POST_OFFICE);
		if ((a & ZR36057_POST_PEND) == 0) 
			return a;
		if (timeout == GUEST_TIMEOUT) 
			return -1;
	}
}

// lml33_post_write writes a byte to a guest using postoffice mechanism
static void
lml33_post_write(int guest, int reg, int v) {
	int w;

	// wait for postoffice not busy
	lml33_post_idle();

	// Trim the values, just in case
	guest &= 0x07;
	reg   &= 0x07;
	v     &= 0xFF;

	// write postoffice operation
	w = ZR36057_POST_DIR + (guest<<20) + (reg<<16) + v;
	writel(w, pciBaseAddr + ZR36057_POST_OFFICE);

	// wait for postoffice not busy
	w = lml33_post_idle();

	// decide if write went ok
	if (w == -1) error(Eio);
}

// lml33_post_read reads a byte from a guest using postoffice mechanism
static uchar
lml33_post_read(int guest, int reg) {
	int w;

	// wait for postoffice not busy
	lml33_post_idle();

	// Trim the values, just in case
	guest &= 0x07;
	reg   &= 0x07;

	// write postoffice operation
	w = (guest<<20) + (reg<<16);
	writel(w, pciBaseAddr + ZR36057_POST_OFFICE);

	// wait for postoffice not busy, get result
	w = lml33_post_idle();

	// decide if read went ok
	if (w == -1) error(Eio);

	return (uchar)(w & 0xFF);
}

static void
lml33_zr060_write(int reg, int v) {
	int guest_id;

	guest_id = GID060;

	lml33_post_write(guest_id, 1, reg>>8 & 0x03);
	lml33_post_write(guest_id, 2, reg    & 0xff);
	lml33_post_write(guest_id, 3, v);
}

static uchar
lml33_zr060_read(int reg) {
	int guest_id;

	guest_id = GID060;

	lml33_post_write(guest_id, 1, reg>>8 & 0x03);
	lml33_post_write(guest_id, 2, reg    & 0xff);

	return lml33_post_read(guest_id, 3);
}

long
chipread(long addr, char *buf, long n, long off) {
	long i;

	for (i = 0; i < n; i++) {
		*buf++ = lml33_i2c_rd8(addr, off++);
	}
	return i;
}

long
post060read(char *buf, long n, long off) {
	long i;

	for (i = 0; i < n; i++) {
		*buf++ = lml33_zr060_read(off++);
	}
	return i;
}

static void lmlintr(Ureg *, void *);

static void
vidreset(void)


@@ 44,6 351,11 @@ vidreset(void)
	ulong regpa;
	int i;

	pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067);
	if (pcidev == nil) {
		print("No zr36067 found.\n");
		return;
	}
	codeData = (CodeData*)xspanalloc(sizeof(CodeData), BY2PG, 0);
	if (codeData == nil) {
		print("devlml: xspanalloc(%ux, %ux, 0)\n", sizeof(CodeData), BY2PG);


@@ 61,7 373,7 @@ vidreset(void)
		codeData->statCom[i] = PADDR(&(codeData->fragmDescr[i]));
		codeData->statComInitial[i] = codeData->statCom[i];
		codeData->fragmDescr[i].fragmAddress =
			(H33_Fragment *)PADDR(&(codeData->frag[i]));
			(Fragment *)PADDR(&(codeData->frag[i]));
		// Length is in double words, in position 1..20
		codeData->fragmDescr[i].fragmLength = (FRAGSIZE >> 1) | FRAGM_FINAL_B;
	}


@@ 71,39 383,29 @@ vidreset(void)
		print("LML33: can't allocate dynamic memory for MjpgDrv\n");
		return;
	}
	if((lml33Board = xallocz(sizeof(LML33Board), 0)) == nil) {
		print("LML33: can't allocate dynamic memory for lml33Board\n");
		return;
	}

	print("initializing LML33 board...");

	lml33Board->pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067);
	if (lml33Board->pcidev == nil) {
		print("zr36067 not found. Install aborted.\n");
		return;
	}
	lml33Board->pciPhysBaseAddr =
		(void *)(lml33Board->pcidev->mem[0].bar & ~0x0F);
	pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F);

	print("zr36067 found at %lux\n", lml33Board->pciPhysBaseAddr);
	print("zr36067 found at %lux\n", pciPhysBaseAddr);

	regpa = upamalloc(lml33Board->pcidev->mem[0].bar & ~0x0F, lml33Board->pcidev->mem[0].size, 0);
	regpa = upamalloc(pcidev->mem[0].bar & ~0x0F, pcidev->mem[0].size, 0);
	if (regpa == 0) {
		print("lml: failed to map registers\n");
		return;
	}
	lml33Board->pciBaseAddr = KADDR(regpa);
	pciBaseAddr = (ulong)KADDR(regpa);

	// make sure the device will respond to mem accesses
	// (pcicmd_master | pcicmd_memory) -- probably superfluous
//	pcicfgw32(lml33Board->pcidev, PciPCR, 0x04 | 0x02);
//	pcicfgw32(pcidev, PciPCR, 0x04 | 0x02);

	// set bus latency -- probably superfluous
//	pcicfgw8(lml33Board->pcidev, PciLTR, 64);
//	pcicfgw8(pcidev, PciLTR, 64);

	// Interrupt handler
	intrenable(lml33Board->pcidev->intl, lmlintr, lml33Board, lml33Board->pcidev->tbdf);
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf);

	print("LML33 Installed\n"); 
	return; 


@@ 134,14 436,10 @@ vidopen(Chan *c, int omode)
	switch(c->qid.path){
	case Q819:
	case Q856:
	case Qi22:
	case Q060:
	case Q067:
		// allow one open per file
		break;
	case Qstat:
		// allow many opens
		break;
	case Qvideo:
	case Qjframe:
		// allow one open total for these two


@@ 156,10 454,8 @@ vidclose(Chan *c)
	switch(c->qid.path){
	case Q819:
	case Q856:
	case Qi22:
	case Q060:
	case Q067:
	case Qstat:
	case Qvideo:
	case Qjframe:
		authclose(c);


@@ 167,17 463,23 @@ vidclose(Chan *c)
}

static long
vidread(Chan *c, void *buf, long n, vlong off)
{
vidread(Chan *c, void *buf, long n, vlong off) {

	switch(c->qid.path){
	case Q819:
		if (off < 0 || off + n > 20)
			return 0;
		return chipread(BT819Addr, buf, n, off);
	case Q856:
	case Qi22:
		if (off < 0xda || off + n > 0xe0)
			return 0;
		return chipread(BT856Addr, buf, n, off);
	case Q060:
		return post060read(buf, n, off);
	case Q067:
		return chipread(c, buf, n, off);
	case Qstat:
		return statread(c, buf, n, off);
		if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0;
		*(long *)buf = readl(pciBaseAddr + off);
		return 4;
	case Qvideo:
	case Qjframe:
		return videoread(c, buf, n, off);


@@ 187,6 489,26 @@ vidread(Chan *c, void *buf, long n, vlong off)
static long
vidwrite(Chan *c, void *va, long n, vlong off)
{

	switch(c->qid.path){
	case Q819:
		if (off < 0 || off + n > 20)
			return 0;
		return chipwrite(BT819Addr, buf, n, off);
	case Q856:
		if (off < 0xda || off + n > 0xe0)
			return 0;
		return chipwrite(BT856Addr, buf, n, off);
	case Q060:
		return post060write(buf, n, off);
	case Q067:
		if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0;
		writel(*(long *)buf, pciBaseAddr + off);
		return 4;
	case Qvideo:
	case Qjframe:
		return videowrite(c, buf, n, off);
	}
}

Dev viddevtab = {


@@ 211,9 533,8 @@ Dev viddevtab = {
};

static void
lmlintr(Ureg *ur, void *arg)
lmlintr(Ureg *ur, void *)
{
	LML33Board *lml33Board = (Lml33Board *)arg;

	

}

M pc/devlml.h => pc/devlml.h +47 -218
@@ 11,52 11,56 @@
// The following values can be modified to tune/set default behaviour of the
// driver.

// The number of uS delay in I2C state transitions
#define H33_I2C_DELAY 10
// The number of uS delay in I2C state transitions (probably >= 10)
#define I2C_DELAY 15

// The amount of spinning to do before the I2C bus is timed out
#define H33_I2C_TIMEOUT 10000000
#define I2C_TIMEOUT 10000000

// The amount of spinning to do before the guest bus is timed out
#define H33_GUEST_TIMEOUT 10000000
#define GUEST_TIMEOUT 10000000

// The amount of spinning to do before the polling of the still
// transfer port is aborted.
#define H33_STILL_TIMEOUT 1000000
#define STILL_TIMEOUT 1000000

// The following number is the maximum number of cards permited. Each
// card found is mapped to a device minor number starting from 0.
#define H33_MAX_CARDS 1
#define MAX_CARDS 1

// The following is the number of device types supported.
#define H33_DEVICE_COUNT 2
#define DEVICE_COUNT 2

// The number of 8K pages per buffer, we will allocate four buffers,
// locked into memory whenever the device is open so modify with care.
#define H33_PAGES 32
#define PAGES 32

// The following are the datastructures needed by the device.
#define ZR36057_I2C_BUS		0x044
// which bit of ZR36057_I2C_BUS is which
#define ZR36057_I2C_SCL                 1
#define ZR36057_I2C_SDA                 2

// A H33_Device records the properties of the various card types supported.
// A Device records the properties of the various card types supported.
typedef struct {
	int		number;			// The H33_CARDTYPE_ assigned
	char	*card_name;		// A string name
	int		zr060addr;		// Which guest bus address for the ZR36060
} H33_Device;
} Device;

// An entry in the fragment table
typedef struct {
	ulong	address;		// bus address of page
	int		length;			// length of page
} H33_RingPage;
} RingPage;

// The structure that we will use to tell the '57 about the buffers
// The sizeof(H33_RingData) should not exceed page size
// The sizeof(RingData) should not exceed page size
typedef struct {
	void			*buffer[4];
	ulong			i_stat_com[4];
	H33_RingPage	ring_pages[4][H33_PAGES];
} H33_RingData;
	RingPage		ring_pages[4][PAGES];
} RingData;

typedef struct {
	int		expect;			// the buffer the int routine expects next


@@ 64,7 68,7 @@ typedef struct {
	int		filled;			// the current number of filled buffers
	int		pages;			// the number of complete pages
	int		remainder;		// the number of bytes in incomplete page
} H33_RingPtr;
} RingPtr;

// The remainder of the #defs are constants which should not need changing.



@@ 72,142 76,17 @@ typedef struct {
// these really belong in pci.h
#define PCI_VENDOR_ZORAN				0x11de
#define PCI_DEVICE_ZORAN_36057			0x6057
#define PCI_DEVICE_ZORAN_36067			PCI_DEVICE_ZORAN_36057

// The ZR36057 is mapped into a 4Kbyte block of the address space
// starting at PCI_BASE_ADDRESS_0. Its application specific registers
// are layed out within that space as follows.
#define ZR36057_VFEND_HORCON			0x000
#define ZR36057_VFEND_VERCON			0x004
#define ZR36057_VFEND_SCLPIX			0x008
#define ZR36057_VDISP_TOP				0x00c
#define ZR36057_VDISP_BOT				0x010
#define ZR36057_VSTRD_GRB				0x014
#define ZR36057_VDISP_CONF				0x018
#define ZR36057_MASK_TOP				0x01c
#define ZR36057_MASK_BOT				0x020
#define ZR36057_OVRLY_CTL				0x024
#define ZR36057_SYS_PCI					0x028
#define ZR36057_GPIO_CTL				0x02c
#define ZR36057_MPEG_SRCW				0x030
#define ZR36057_MPEG_CTFR_CTL			0x034
#define ZR36057_MPEG_MEM_PTR			0x038
#define ZR36057_INTR_STAT				0x03c
#define ZR36057_INTR_CTL				0x040
#define ZR36057_I2C_BUS					0x044
#define ZR36057_JPEG_MODE_CTL			0x100
#define ZR36057_JPEG_PROC_CTL			0x104
#define ZR36057_VSYNC_PARM				0x108
#define ZR36057_HSYNC_PARM				0x10c
#define ZR36057_HOR_ACTIVE				0x110
#define ZR36057_VER_ACTIVE				0x114
#define ZR36057_FIELD_PROC				0x118
#define ZR36057_JPEG_CODE_BASE			0x11C
#define ZR36057_JPEG_FIFO_THRHLD		0x120
#define ZR36057_JPEG_GUESTID			0x124
#define ZR36057_GUEST_CTL				0x12c
#define ZR36057_POST_OFFICE				0x200
#define ZR36057_STILL_TRANS				0x300
// The datasheet says that STILL_TRANS is 0x140, but the errata says it's 0x300

// which bits of the ZR36057_INTR... mean something special
#define ZR36057_INTR_GIRQ1              0x40000000
#define ZR36057_INTR_GIRQ0              0x20000000
#define ZR36057_INTR_CODREP             0x10000000
#define ZR36057_INTR_JPEGREP            0x08000000
#define ZR36057_INTR_ENABLE             0x01000000
#define BT819Addr 0x8a
#define BT856Addr 0x88

#define GID060							0

// which bits of ZR36057_I2C_BUS mean something special
#define ZR36057_POST_PEND               0x02000000
#define ZR36057_POST_TIME               0x01000000
#define ZR36057_POST_DIR                0x00800000

// function of the Guest CS outputs
#define ZR36060_GUEST_DATA              0
#define ZR36060_GUEST_START             1
#define ZR36060_GUEST_RESET             3

// the still busy bit in ZR36057_STILL_TRANS
// this assumes we are working in little endian mode
#define ZR36057_STILL_BUSY              0x80000000

// which bit of ZR36057_I2C_BUS is which
#define ZR36057_I2C_SCL                 1
#define ZR36057_I2C_SDA                 2

// The ZR36060 registers
#define ZR36060_LOAD                    0x000
#define ZR36060_FIFO_STAT               0x001
#define ZR36060_INTERFACE               0x002
#define ZR36060_MODE                    0x003
#define ZR36060_ZERO                    0x004
#define ZR36060_MBCV                    0x005
#define ZR36060_MARKERS_EN              0x006
#define ZR36060_INT_MASK                0x007
#define ZR36060_INT_STAT                0x008
#define ZR36060_TCV_NEThi               0x009
#define ZR36060_TCV_NETmh               0x00a
#define ZR36060_TCV_NETml               0x00b
#define ZR36060_TCV_NETlo               0x00c
#define ZR36060_TCV_DATAhi              0x00d
#define ZR36060_TCV_DATAmh              0x00e
#define ZR36060_TCV_DATAml              0x00f
#define ZR36060_TCV_DATAlo              0x010
#define ZR36060_SFhi                    0x011
#define ZR36060_SFlo                    0x012
#define ZR36060_AFhi                    0x013
#define ZR36060_AFme                    0x014
#define ZR36060_AFlo                    0x015
#define ZR36060_ACVhi                   0x016
#define ZR36060_ACVmh                   0x017
#define ZR36060_ACVml                   0x018
#define ZR36060_ACVlo                   0x019
#define ZR36060_ATAhi                   0x01a
#define ZR36060_ATAmh                   0x01b
#define ZR36060_ATAml                   0x01c
#define ZR36060_ATAlo                   0x01d
#define ZR36060_ACV_TRUNhi              0x01e
#define ZR36060_ACV_TRUNmh              0x01f
#define ZR36060_ACV_TRUNml              0x020
#define ZR36060_ACV_TRUNlo              0x021
#define ZR36060_DEV_ID                  0x022
#define ZR36060_DEV_REV                 0x023
#define ZR36060_TEST_1                  0x024
#define ZR36060_TEST_2                  0x025
#define ZR36060_VCR                     0x030
#define ZR36060_VPR                     0x031
#define ZR36060_SCALE                   0x032
#define ZR36060_BKG_CLR_Y               0x033
#define ZR36060_BKG_CLR_U               0x034
#define ZR36060_BKG_CLR_V               0x035
#define ZR36060_SYNC_VTOTALhi           0x036
#define ZR36060_SYNC_VTOTALlo           0x037
#define ZR36060_SYNC_HTOTALhi           0x038
#define ZR36060_SYNC_HTOTALlo           0x039
#define ZR36060_SYNC_VSIZE              0x03a
#define ZR36060_SYNC_HSIZE              0x03b
#define ZR36060_SYNC_BVSTART            0x03c
#define ZR36060_SYNC_BHSTART            0x03d
#define ZR36060_SYNC_BVENDhi            0x03e
#define ZR36060_SYNC_BVENDlo            0x03f
#define ZR36060_SYNC_BHENDhi            0x040
#define ZR36060_SYNC_BHENDlo            0x041
#define ZR36060_AA_VSTARThi             0x042
#define ZR36060_AA_VSTARTlo             0x043
#define ZR36060_AA_VENDhi               0x044
#define ZR36060_AA_VENDlo               0x045
#define ZR36060_AA_HSTARThi             0x046
#define ZR36060_AA_HSTARTlo             0x047
#define ZR36060_AA_HENDhi               0x048
#define ZR36060_AA_HENDlo               0x049
#define ZR36060_SW_VSTARThi             0x04a
#define ZR36060_SW_VSTARTlo             0x04b
#define ZR36060_SW_VENDhi               0x04c
#define ZR36060_SW_VENDlo               0x04d
#define ZR36060_SW_HSTARThi             0x04e
#define ZR36060_SW_HSTARTlo             0x04f
#define ZR36060_SW_HENDhi               0x050
#define ZR36060_SW_HENDlo               0x051
#define ZR36057_POST_OFFICE				0x200
#define ZR36057_POST_PEND				0x02000000
#define ZR36057_POST_TIME				0x01000000
#define ZR36057_POST_DIR				0x00800000

#define MB 0x100000
#define NBUF 4


@@ 215,29 94,36 @@ typedef struct {
#define FRAGM_FINAL_B 1
#define STAT_BIT 1

#define writel(v, a)	*(ulong *)(a) = v
#define writew(v, a)	*(ushort *)(a) = v
#define writeb(v, a)	*(uchar *)(a) = v
#define readl(a)		(*(ulong *)(a))
#define readw(a)		(*(ushort *)(a))
#define readb(a)		(*(uchar *)(a))

typedef struct MjpgDrv				MjpgDrv;
typedef struct H33_Fragment			H33_Fragment;
typedef struct H33_FragmentTable	H33_FragmentTable;
typedef struct Fragment				Fragment;
typedef struct FragmentTable		FragmentTable;
typedef struct CodeData				CodeData;
typedef struct ML33Board			LML33Board;

#define FRAGSIZE (MB/NBUF)

struct H33_Fragment {
struct Fragment {
	uchar	fragbytes[FRAGSIZE];
};

struct H33_FragmentTable {
	H33_Fragment *	fragmAddress;			// Physical address
struct FragmentTable {
	Fragment *		fragmAddress;			// Physical address
	ulong			fragmLength;
};

struct CodeData {
	char				idString[16];
	ulong				statCom[4];			// Physical address
	ulong				statComInitial[4];	// Physical address
	H33_FragmentTable	fragmDescr[4];
	H33_Fragment		frag[4];
	char			idString[16];
	ulong			statCom[4];				// Physical address
	ulong			statComInitial[4];		// Physical address
	FragmentTable	fragmDescr[4];
	Fragment		frag[4];
};

extern char static_MjpgDrv_GPL_Notice[];


@@ 249,71 135,14 @@ struct MjpgDrv {
	struct wait_queue *	intrWaitQ;
};

#define PCI_DEVICE_ZORAN_36067 PCI_DEVICE_ZORAN_36057

struct ML33Board
{
	void *		pciPhysBaseAddr;
	void *		pciBaseAddr;
	Pcidev *	pcidev;
};

extern void *		H33Addr;
extern LML33Board *	lml33Board;
static void *		pciPhysBaseAddr;
static ulong		pciBaseAddr;
static Pcidev *		pcidev;

void	LML33Board_ctor(LML33Board*);
void	LML33Board_dtor(LML33Board*);
int		LML33Board_installInterruptHandler(LML33Board*);
void	LML33Board_initHardware(LML33Board*);
void	LML33Board_mjpegGo(LML33Board*);


// ZR36067 (PCI controller) register memory access
ulong	LML33Board_readL(LML33Board*,int addr);
void	LML33Board_writeL(LML33Board*,int addr,ulong);
ushort	LML33Board_readW(LML33Board*,int addr);
void	LML33Board_writeW(LML33Board*,int addr,ushort);
uchar	LML33Board_readB(LML33Board*,int addr);
void	LML33Board_writeB(LML33Board*,int addr,uchar);
int		LML33Board_getBit(LML33Board*,int addr,int);
void	LML33Board_setBit(LML33Board*,int addr,int,int);

// I2C (video encoder/decoder) manipulation functions
void	h33_i2c_pause(LML33Board*);
int		h33_i2c_waitscl(LML33Board*);
void	h33_i2c_start(LML33Board*);
void	h33_i2c_stop(LML33Board*);
void	h33_i2c_wrbit(LML33Board*,int bit);
int		h33_i2c_rdbit(LML33Board*);
int		h33_i2c_wrbyte(LML33Board*,int value);
int		h33_i2c_rdbyte(LML33Board*,int* value);
int		h33_i2c_probe(LML33Board*,int addr);
int		h33_i2c_wr8(LML33Board*,int addr, int sub, int value);
int		h33_i2c_rd8(LML33Board*,int addr, int sub, int *value);
int		h33_i2c_bt856rd8 (LML33Board*,int addr, int *msb);

// GPIO access
void	gpioSetDirection(int gpIO,int dir);
void	gpioSet(int gpIO,int value);
int		gpioGet(int gpIO);

// PostOffice access functions 
int		h33_post_idle(void);
int		h33_post_write(int guest, int reg, int value);
int		h33_post_read(int guest, int reg);

// ZR36060
void	h33_zr060_write(int reg, int value);
int		h33_zr060_read(int reg);

void	MjpgDrv_ctor(MjpgDrv*);
void	MjpgDrv_dtor(MjpgDrv*);
int		MjpgDrv_open(struct inode *iNode, struct file *filePtr);
void	MjpgDrv_release(struct inode *iNode, struct file *filePtr);
void	MjpgDrv_intrHandler(int irqNo, void *devId, struct pt_regs *ptRegs);

void *	static_CodeData_map(ulong h33PHighMemory,ulong h33BufferSize);
int		CodeData_getReadyBuffer(CodeData*);
int		CodeData_getProcessedBuffer(CodeData*this);
int		CodeData_getBuffer(CodeData *,int bufferNo,void** bufferPtr,ushort* frameNo);
int		CodeData_prepareBuffer(CodeData *, int bufferNo);