~kris/9p

9hist

1656551c58c9b264f5f5d416abab6af3c3c06280 — David du Colombier 27 years ago 6d7bced
Plan 9 from Bell Labs 1999-05-13
4 files changed, 139 insertions(+), 70 deletions(-)

M pc/devlml.c
M pc/devlml.h
M pc/ns16552.h
M port/devns16552.c
M pc/devlml.c => pc/devlml.c +57 -45
@@ 11,33 11,34 @@
// Lml 22 driver

enum{
	Qdir,
	Q819,
	Q856,
	Qreg,
	Qvideo,
	Qjvideo,
	Qjframe,
};

static Dirtab viddir[]={
//	 name,		 qid,	  size,		mode
	"vid819",	{Q819},		0,		0644,
	"vid856",	{Q856},		0,		0644,
	"vidreg",	{Qreg},		0,		0644,
	"video",	{Qvideo},	0,		0666,
static Dirtab lmldir[]={
//	 name,		 qid,		size,		mode
	"lml819",	{Q819},		0,		0644,
	"lml856",	{Q856},		0,		0644,
	"lmlreg",	{Qreg},		0,		0644,
	"jvideo",	{Qjvideo},	0,		0666,
	"jframe",	{Qjframe},	0,		0666,
};

CodeData *	codeData;

int			currentBuffer;
int			currentBufferLength;
int		currentBuffer;
int		currentBufferLength;
void *		currentBufferPtr;
int			frameNo;
int		frameNo;
Rendez		sleeper;
int			singleFrame;
int			bufferPrepared;
int			hdrPos;
int			nopens;
int		singleFrame;
int		bufferPrepared;
int		hdrPos;
int		nopens;
uchar		q856[3];

static FrameHeader frameHeader = {


@@ 455,14 456,13 @@ vwrite(Chan *, void *va, long count, vlong pos) {
static void lmlintr(Ureg *, void *);

static void
vidreset(void)
lmlreset(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);


@@ 472,7 472,7 @@ vidreset(void)
	}

	print("Installing Motion JPEG driver %s\n", MJPG_VERSION); 
	print("Buffer size %ux\n", sizeof(CodeData)); 
	print("Buffer at 0x%.8lux, size 0x%.8ux\n", codeData, sizeof(CodeData)); 

	// Get access to DMA memory buffer
	memset(codeData, 0xAA, sizeof(CodeData));


@@ 491,7 491,7 @@ vidreset(void)

	pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F);

	print("zr36067 found at %lux\n", pciPhysBaseAddr);
	print("zr36067 found at 0x%.8lux", pciPhysBaseAddr);

	regpa = upamalloc(pcidev->mem[0].bar & ~0x0F, pcidev->mem[0].size, 0);
	if (regpa == 0) {


@@ 499,6 499,7 @@ vidreset(void)
		return;
	}
	pciBaseAddr = (ulong)KADDR(regpa);
	print(", mapped at 0x%.8lux\n", pciBaseAddr);

	// make sure the device will respond to mem accesses
	// (pcicmd_master | pcicmd_memory) -- probably superfluous


@@ 510,30 511,29 @@ vidreset(void)
	// Interrupt handler
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf);

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

static Chan*
vidattach(char *spec)
lmlattach(char *spec)
{
	return devattach('V', spec);
}

static int
vidwalk(Chan *c, char *name)
lmlwalk(Chan *c, char *name)
{
	return devwalk(c, name, viddir, nelem(viddir), devgen);
	return devwalk(c, name, lmldir, nelem(lmldir), devgen);
}

static void
vidstat(Chan *c, char *dp)
lmlstat(Chan *c, char *dp)
{
	devstat(c, dp, viddir, nelem(viddir), devgen);
	devstat(c, dp, lmldir, nelem(lmldir), devgen);
}

static Chan*
vidopen(Chan *c, int omode)
lmlopen(Chan *c, int omode)
{
	c->aux = 0;
	switch(c->qid.path){


@@ 541,7 541,7 @@ vidopen(Chan *c, int omode)
	case Q856:
	case Qreg:
		break;
	case Qvideo:
	case Qjvideo:
	case Qjframe:
		if (nopens)
			error(Einuse);


@@ 556,28 556,34 @@ vidopen(Chan *c, int omode)
		// allow one open total for these two
		break;
	}
	return devopen(c, omode, viddir, nelem(viddir), devgen);
	return devopen(c, omode, lmldir, nelem(lmldir), devgen);
}

static void
vidclose(Chan *c)
lmlclose(Chan *c)
{
	switch(c->qid.path){
	case Q819:
	case Q856:
	case Qreg:
	case Qvideo:
	case Qjvideo:
	case Qjframe:
		authclose(c);
	}
}

static long
vidread(Chan *c, void *va, long n, vlong off) {
lmlread(Chan *c, void *va, long n, vlong voff) {
	int i, d;
	uchar *buf = va;
	long off = voff;
	long v;

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

	case Qdir:
		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen);

	switch(c->qid.path){
	case Q819:
		if (off < 0 || off + n > 0x20)
			return 0;


@@ 621,24 627,30 @@ vidread(Chan *c, void *va, long n, vlong off) {
			break;
		case 4:
			if (off & (n-1)) return 0;
			*(long *)buf = readl(pciBaseAddr + off);
			v = readl(pciBaseAddr + off);
			*(long *)buf = v;
print("reading %lux at %lux (%lux)\n", v, pciBaseAddr + off, off);
			break;
		default:
			return 0;
		}
		return n;
	case Qvideo:
	case Qjvideo:
	case Qjframe:
		return vread(c, buf, n, off);
	}
}

static long
vidwrite(Chan *c, void *va, long n, vlong off) {
lmlwrite(Chan *c, void *va, long n, vlong off) {
	int i;
	uchar *buf = va;

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

	case Qdir:
		error(Eperm);

	case Q819:
		if (off < 0 || off + n > 0x20)
			return 0;


@@ 680,28 692,28 @@ vidwrite(Chan *c, void *va, long n, vlong off) {
			return 0;
		}
		return n;
	case Qvideo:
	case Qjvideo:
	case Qjframe:
		return vwrite(c, buf, n, off);
	}
}

Dev viddevtab = {
Dev lmldevtab = {
	'V',
	"video",

	vidreset,
	lmlreset,
	devinit,
	vidattach,
	lmlattach,
	devclone,
	vidwalk,
	vidstat,
	vidopen,
	lmlwalk,
	lmlstat,
	lmlopen,
	devcreate,
	vidclose,
	vidread,
	lmlclose,
	lmlread,
	devbread,
	vidwrite,
	lmlwrite,
	devbwrite,
	devremove,
	devwstat,

M pc/devlml.h => pc/devlml.h +4 -4
@@ 12,7 12,7 @@
// driver.

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

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


@@ 89,9 89,9 @@ 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 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))

M pc/ns16552.h => pc/ns16552.h +25 -5
@@ 14,7 14,7 @@ enum
#define uartwrreg(u,r,v)	outb((u)->port + r, (u)->sticky[r] | (v))
#define uartrdreg(u,r)		inb((u)->port + r)

void	ns16552setup(ulong, ulong, char*);
void	ns16552setup(ulong, ulong, char*, int);
void	ns16552special(int, int, Queue**, Queue**, int (*)(Queue*, int));
void	uartclock(void);
/*


@@ 93,9 93,9 @@ ns16552install(void)
	already = 1;

	/* first two ports are always there and always the normal frequency */
	ns16552setup(0x3F8, UartFREQ, "eia0");
	ns16552setup(0x3F8, UartFREQ, "eia0", Ns550);
	intrenable(IrqUART0, ns16552intrx, (void*)0, BUSUNKNOWN);
	ns16552setup(0x2F8, UartFREQ, "eia1");
	ns16552setup(0x2F8, UartFREQ, "eia1", Ns550);
	intrenable(IrqUART1, ns16552intrx, (void*)1, BUSUNKNOWN);
	addclock0link(uartclock);



@@ 133,9 133,29 @@ ns16552install(void)
			port = sc->port;
			for(j=0; j < sc->size; j++){
				sprint(name, "eia%d%2.2d", nscard, j);
				ns16552setup(port, sc->freq, name);
				ns16552setup(port, sc->freq, name, Ns550);
				port += 8;
			}
		} else if(cistrcmp(sc->type, "turbo650") == 0){
			/*
			 *  port gives base port address for the uart
			 *  irq is interrupt
			 *  freq is the baud rate generator frequency
			 */
			if(sc->freq == 0)
				sc->freq = UartFREQ*4;
			sprint(name, "eia%d00", nscard);
			ns16552setup(sc->port, sc->freq, name, Ns650);

			/*
			 *  multiply clock speed by 4
			 */
			if(sc->mem == 0)
				outb(0x2c8, 0);
			else
				outb(sc->mem, 0);

			intrenable(sc->irq, ns16552intrx, (void*)(nuart-1), BUSUNKNOWN);
		} else if(cistrcmp(sc->type, "com") == 0 && sc->port != 0x3F8 && sc->port != 0x2F8){
			/*
			 *  port gives base port address for the uart


@@ 145,7 165,7 @@ ns16552install(void)
			if(sc->freq == 0)
				sc->freq = UartFREQ;
			sprint(name, "eia%d00", nscard);
			ns16552setup(sc->port, sc->freq, name);
			ns16552setup(sc->port, sc->freq, name, Ns550);
			intrenable(sc->irq, ns16552intrx, (void*)(nuart-1), BUSUNKNOWN);
		}
		nscard++;

M port/devns16552.c => port/devns16552.c +53 -16
@@ 22,11 22,17 @@ enum
	 Ixmt=	(1<<1),		/*  for xmit buffer empty */
	 Irstat=(1<<2),		/*  for change in rcv'er status */
	 Imstat=(1<<3),		/*  for change in modem status */
	 Isleep=(1<<4),		/*  put in sleep mode; 16C650 */
	 Ixoff=	(1<<5),		/*  for xoff received; 16C650 */
	 Irts=	(1<<6),		/*  for !rts asserted in auto mode; 16C650 */
	 Icts=	(1<<7),		/*  for !cts asserted in auto mode; 16C650 */
	Istat=	2,		/* interrupt flag (read) */
	 Fenabd=(3<<6),		/*  on if fifo's enabled */
	 Irctsd=(1<<4),		/*  auto rts or cts changed state */
	Fifoctl=2,		/* fifo control (write) */
	 Fena=	(1<<0),		/*  enable xmit/rcv fifos */
	 Ftrig=	(1<<6),		/*  trigger after 4 input characters */
	 Ftrig4=	(1<<6),		/*  trigger after 4 input characters */
	 Ftrig24=	(2<<6),		/*  trigger after 24 input characters */
	 Fclear=(3<<1),		/*  clear xmit & rcv fifos */
	Format=	3,		/* byte format */
	 Bits8=	(3<<0),		/*  8 bits/byte */


@@ 36,12 42,16 @@ enum
	 Pforce=(1<<5),		/*  force parity */
	 Break=	(1<<6),		/*  generate a break */
	 Dra=	(1<<7),		/*  address the divisor */
	 Ers=	0xbf,		/*  enable enhaced register set on 16C650 */
	Mctl=	4,		/* modem control */
	 Dtr=	(1<<0),		/*  data terminal ready */
	 Rts=	(1<<1),		/*  request to send */
	 Ri=	(1<<2),		/*  ring */
	 Inton=	(1<<3),		/*  turn on interrupts */
	 Loop=	(1<<4),		/*  loop back */
	 Intsel=(1<<5),		/*  NO! open source interrupts; 16C650 */
	 Irda=	(1<<6),		/*  infrared interface; 16C650 */
	 Cdiv=	(1<<7),		/*  divide clock by four; 16C650 */
	Lstat=	5,		/* line status */
	 Inready=(1<<0),	/*  receive buffer full */
	 Oerror=(1<<1),		/*  receiver overrun */


@@ 60,12 70,20 @@ enum
	Scratch=7,		/* scratchpad */
	Dlsb=	0,		/* divisor lsb */
	Dmsb=	1,		/* divisor msb */
	Efr=	2,		/* enhanced features for 16C650 */
	 Eena=	(1<<4),		/* enable enhanced bits in normal registers */
	 Arts=	(1<<6),		/* auto rts */
	 Acts=	(1<<7),		/* auto cts */

	CTLS= 023,
	CTLQ= 021,

	Stagesize= 1024,
	Nuart=	32,		/* max per machine */

	Ns450=	0,
	Ns550,
	Ns650,
};

typedef struct Uart Uart;


@@ 79,7 97,7 @@ struct Uart
	char	name[NAMELEN];

	uchar	sticky[8];		/* sticky write register values */
	ulong	port;
	ulong	port;			/* io ports */
	ulong	freq;			/* clock frequency */
	uchar	mask;			/* bits/char */
	int	dev;


@@ 96,7 114,7 @@ struct Uart

	Lock	flock;			/* fifo */
	uchar	fifoon;			/* fifo's enabled */
	uchar	nofifo;			/* earlier chip version with nofifo */
	uchar	type;			/* chip version */

	Lock	rlock;			/* receive */
	uchar	istage[Stagesize];


@@ 207,7 225,6 @@ ns16552bits(Uart *p, int bits)
	uartwrreg(p, Format, 0);
}


/*
 *  toggle DTR
 */


@@ 255,7 272,7 @@ ns16552fifoon(Uart *p)
{
	ulong i, x;

	if(p->nofifo)
	if(p->type < Ns550)
		return;

	x = splhi();


@@ 273,11 290,14 @@ ns16552fifoon(Uart *p)

	/* turn on fifo */
	p->fifoon = 1;
	uartwrreg(p, Fifoctl, Fena|Ftrig);
	if(p->type == Ns650)
		uartwrreg(p, Fifoctl, Fena|Ftrig24);
	else
		uartwrreg(p, Fifoctl, Fena|Ftrig4);

	if((p->istat & Fenabd) == 0){
		/* didn't work, must be an earlier chip type */
		p->nofifo = 1;
		p->type = Ns450;
	}

	splx(x);


@@ 289,16 309,32 @@ ns16552fifoon(Uart *p)
static void
ns16552mflow(Uart *p, int n)
{


	ilock(&p->tlock);
	if(n){
		p->sticky[Iena] |= Imstat;
		uartwrreg(p, Iena, 0);
		p->modem = 1;
		p->cts = uartrdreg(p, Mstat) & Cts;
print("mflow type %d\n", p->type);
		if(p->type == Ns650){
			outb(p->port + Format, 0xbf);
			outb(p->port + Efr, Eena|Arts|Acts);
			uartwrreg(p, Format, 0);
			p->cts = 1;
		} else {
			p->sticky[Iena] |= Imstat;
			uartwrreg(p, Iena, 0);
			p->modem = 1;
			p->cts = uartrdreg(p, Mstat) & Cts;
		}
	} else {
		p->sticky[Iena] &= ~Imstat;
		uartwrreg(p, Iena, 0);
		p->modem = 0;
		if(p->type == Ns650){
			outb(p->port + Format, 0xbf);
			outb(p->port + Efr, Eena|Arts|Acts);
			uartwrreg(p, Format, 0);
		} else {
			p->sticky[Iena] &= ~Imstat;
			uartwrreg(p, Iena, 0);
			p->modem = 0;
		}
		p->cts = 1;
	}
	iunlock(&p->tlock);


@@ 521,7 557,7 @@ ns16552setup0(Uart *p)
 *  called by main() to create a new duart
 */
void
ns16552setup(ulong port, ulong freq, char *name)
ns16552setup(ulong port, ulong freq, char *name, int type)
{
	Uart *p;



@@ 535,6 571,7 @@ ns16552setup(ulong port, ulong freq, char *name)
	nuart++;
	p->port = port;
	p->freq = freq;
	p->type = type;
	ns16552setup0(p);
}



@@ 990,7 1027,7 @@ ns16552write(Chan *c, void *buf, long n, vlong)
	 *  It must be something I don't understand. -- presotto
	 */
	lock(&p->flock);
	if((p->istat & Fenabd) == 0 && p->fifoon && p->nofifo == 0)
	if((p->istat & Fenabd) == 0 && p->fifoon && p->type < Ns550)
		ns16552fifoon(p);
	unlock(&p->flock);