~kris/9p

9hist

2105602d9855c19fcf7bef0e710ebb4774906cbc — David du Colombier 27 years ago eb7f309
Plan 9 from Bell Labs 1999-06-01
3 files changed, 61 insertions(+), 265 deletions(-)

M pc/devlml.c
M pc/trap.c
M port/devns16552.c
M pc/devlml.c => pc/devlml.c +8 -224
@@ 23,40 23,20 @@ int debug = 0;

enum{
	Qdir,
	Qjvideo,
	Qjframe,
	Qjcount,
};

static Dirtab lmldir[]={
//	 name,		 qid,		size,		mode
	"jvideo",	{Qjvideo},	0,		0666,
	"jframe",	{Qjframe},	0,		0666,
	"jcount",	{Qjcount},	0,		0444,
};

CodeData *	codeData;

typedef enum {
	New,
	Header,
	Body,
	Error,
} State;

int		frameNo;
Rendez		sleeper;
int		singleFrame;
int		nopens;
uchar		q856[3];
State		state = New;

static FrameHeader frameHeader = {
	MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8,
	{ 'L', 'M', 'L', '\0'},
	-1, 0, 0, 0, 0
};


#define writel(v, a) *(ulong *)(a) = (v)
#define readl(a) *(ulong*)(a)


@@ 86,177 66,6 @@ vcount(Chan *, void *va, long nbytes, vlong) {
	return 1;
}

static long
vread(Chan *, void *va, long nbytes, vlong) {
	static int bufpos;
	static char *bufptr;
	static int curbuf;
	static int fragsize;
	static int frameno;
	static int frameprev;
	char *p;
	long count = nbytes;
	int i;
	vlong thetime;

	p = (char *)va;
	while (count > 0) {
		switch (state) {
		case New:
			curbuf = getbuffer();
			frameNo = codeData->statCom[curbuf] >> 24;
			fragsize = (codeData->statCom[curbuf] & 0x00ffffff)>>1;
			if (debug & DBGREAD)
				pprint("devlml: got read buf %d, fr %d, size %d\n",
					curbuf, frameNo, fragsize);
			if (!singleFrame && frameno != (frameprev + 1) % 256)
				pprint("Frame out of sequence: %d %d\n",
					frameprev, frameno);
			frameprev = frameno;
			if (fragsize <= 0 || fragsize > sizeof(Fragment)) {
				pprint("Wrong sized fragment, %d (ignored)\n",
					fragsize);
				codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf]));
				break;
			}
			// Fill in APP marker fields here
			thetime = todget(nil);
			frameHeader.sec = (ulong)(thetime / 1000000000LL);
			frameHeader.usec = (ulong)(thetime % 1000000000LL) / 1000;
			frameHeader.frameSize = fragsize - 2 + sizeof(FrameHeader);
			frameHeader.frameSeqNo++;
			frameHeader.frameNo = frameno;
			bufpos = 0;
			state = Header;
			bufptr = (char *)(&frameHeader);
			// Fall through
		case Header:
			i = sizeof(FrameHeader) - bufpos;
			if (count <= i) {
				memmove(p, bufptr, count);
				bufptr += count;
				bufpos += count;
				return nbytes;
			}
			memmove(p, bufptr, i);
			count -= i;
			p += i;
			bufpos = 2;
			bufptr = codeData->frag[curbuf].fb + 2;
			state = Body;
			// Fall through
		case Body:
			i = fragsize - bufpos;
			if (count < i) {
				memmove(p, bufptr, count);
				bufptr += count;
				bufpos += count;
				return nbytes;
			}
			memmove(p, bufptr, i);
			count -= i;
			p += i;

			// Allow reuse of current buffer
			codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf]));
			state = New;
			if (singleFrame) {
				state = Error;
				return nbytes - count;
			}
			break;
		case Error:
			return 0;
		}
	}
}

static long
vwrite(Chan *, void *va, long nbytes, vlong) {
	static int bufpos;
	static char *bufptr;
	static int curbuf;
	static int fragsize;
	char *p;
	long count = nbytes;
	int i;

	p = (char *)va;
	while (count > 0) {
		switch (state) {
		case New:
			curbuf = getbuffer();
			if (debug&DBGWRIT)
				pprint("current buffer %d\n", curbuf);
			bufptr = codeData->frag[curbuf].fb;
			bufpos = 0;
			state = Header;
			// Fall through
		case Header:
			if (count < sizeof(FrameHeader) - bufpos) {
				memmove(bufptr, p, count);
				bufptr += count;
				bufpos += count;
				return nbytes;
			}
			// Fill remainder of header
			i = sizeof(FrameHeader) - bufpos;
			memmove(bufptr, p, i);
			bufptr += i;
			bufpos += i;
			p += i;
			count -= i;
			// verify header
			if (codeData->frag[curbuf].fh.mrkSOI != MRK_SOI
			 || codeData->frag[curbuf].fh.mrkAPP3 != MRK_APP3
			 || strcmp(codeData->frag[curbuf].fh.nm, APP_NAME)) {
				// Header is bad
				pprint("devlml: header error: 0x%.4ux, 0x%.4ux, `%.4s'\n",
					codeData->frag[curbuf].fh.mrkSOI,
					codeData->frag[curbuf].fh.mrkAPP3,
					codeData->frag[curbuf].fh.nm);
				state = Error;
				return nbytes - count;
			}
			fragsize = codeData->frag[curbuf].fh.frameSize;
			if (fragsize <= sizeof(FrameHeader)
			 || fragsize  > sizeof(Fragment)) {
				pprint("devlml: frame size error: 0x%.8ux\n",
					fragsize);
				state = Error;
				return nbytes - count;
			}
			state = Body;
			// Fall through
		case Body:
			i = fragsize - bufpos;
			if (count < i) {
				memmove(bufptr, p, count);
				bufptr += count;
				bufpos += count;
				return nbytes;
			}
			memmove(bufptr, p, i);
			bufptr += i;
			bufpos += i;
			p += i;
			count -= i;
			// We have written the frame, time to display it
			codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf]));
			if (debug&DBGWRIT)
				pprint("Sending buffer %d\n", curbuf);
			if (singleFrame) {
				state = Error;
				return nbytes - count;
			}
			state = New;
			break;
		case Error:
			return 0;
		}
	}
}

static void lmlintr(Ureg *, void *);

static void


@@ 289,14 98,11 @@ lmlreset(void)
		return;
	}

	memset(grabbuf, 0x33, grablen);

	print("Installing Motion JPEG driver %s\n", MJPG_VERSION); 
	print("MJPG buffer at 0x%.8lux, size 0x%.8lux\n", codeData, cdsize); 
	print("Grab buffer at 0x%.8lux, size 0x%.8lux\n", grabbuf, grablen); 

	// Get access to DMA memory buffer
	memset(codeData, 0xAA, sizeof(CodeData));
	codeData->pamjpg = PADDR(codeData->statCom);
	codeData->pagrab = PADDR(grabbuf);
	for (i = 0; i < NBUF; i++) {


@@ 306,8 112,6 @@ lmlreset(void)
		codeData->fragdesc[i].leng = ((sizeof codeData->frag[i]) >> 1) | FRAGM_FINAL_B;
	}

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

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

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


@@ 320,9 124,6 @@ lmlreset(void)
	pciBaseAddr = (ulong)KADDR(regpa);
	print(", mapped at 0x%.8lux\n", pciBaseAddr);

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

	memset(&segbuf, 0, sizeof(segbuf));
	segbuf.attr = SG_PHYSICAL;
	segbuf.name = smalloc(NAMELEN);


@@ 355,6 156,10 @@ lmlreset(void)
		print("lml: physsegment: lmlgrab\n");
		return;
	}

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

	return;
}



@@ 378,22 183,14 @@ lmlstat(Chan *c, char *dp)

static Chan*
lmlopen(Chan *c, int omode) {
	int i;

	c->aux = 0;
	switch(c->qid.path){
	case Qjframe:
	case Qjvideo:
	case Qjcount:
		// allow one open
		if (nopens)
			error(Einuse);
		nopens = 1;
		singleFrame = (c->qid.path == Qjframe) ? 1 : 0;;
		state = New;
		for (i = 0; i < NBUF; i++)
			codeData->statCom[i] = PADDR(&(codeData->fragdesc[i]));

		// allow one open total for these two
		break;
	}
	return devopen(c, omode, lmldir, nelem(lmldir), devgen);


@@ 403,8 200,6 @@ static void
lmlclose(Chan *c) {

	switch(c->qid.path){
	case Qjvideo:
	case Qjframe:
	case Qjcount:
		nopens = 0;
		authclose(c);


@@ 420,27 215,16 @@ lmlread(Chan *c, void *va, long n, vlong voff) {

	case Qdir:
		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen);
	case Qjvideo:
	case Qjframe:
		return vread(c, buf, n, off);
	case Qjcount:
		return vcount(c, buf, n, off);
	}
}

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

	switch(c->qid.path & ~CHDIR){
	case Qdir:
	case Qjcount:
		error(Eperm);
	case Qjvideo:
	case Qjframe:
		return vwrite(c, buf, n, off);
	}
	error(Eperm);
	return 0;
}

Dev lmldevtab = {

M pc/trap.c => pc/trap.c +2 -40
@@ 15,16 15,8 @@ static void fault386(Ureg*, void*);
static Lock vctllock;
static Vctl *vctl[256];

/* interrupt timestamps, l.s knows fills intrts each interupt */
	uvlong	intrts;
static	struct {
	Lock;
	int	vno;		/* vector to save timestamps for */
	int	n;		/* number of valid timestamps in ts[] */
	uvlong	ts[128];	/* time stamps */
} tsalloc;

static void	savets(void);
/* interrupt timestamps, l.s fills intrts each interupt */
uvlong	intrts;

void
intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf)


@@ 41,8 33,6 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf)

	ilock(&vctllock);
	vno = arch->intrenable(v);
	if(irq == IrqUART0)
		tsalloc.vno = vno;
	if(vno == -1){
		iunlock(&vctllock);
		print("intrenable: couldn't enable irq %d, tbdf 0x%uX\n",


@@ 192,8 182,6 @@ trap(Ureg* ureg)
	}

	vno = ureg->trap;
	if(vno == tsalloc.vno)
		savets();
	if(ctl = vctl[vno]){
		if(ctl->isintr){
			m->intr++;


@@ 752,29 740,3 @@ dbgpc(Proc *p)

	return ureg->pc;
}

/* called with interrupts off */
static void
savets(void)
{
	lock(&tsalloc);
	if(tsalloc.n < nelem(tsalloc.ts))
		tsalloc.ts[tsalloc.n++] = intrts;
	unlock(&tsalloc);
}

/* read interrupt timestamps */
long
readintrts(void *buf, int n)
{
	n /= sizeof(uvlong);
	if(n <= 0)
		return 0;
	ilock(&tsalloc);
	if(n > tsalloc.n)
		n = tsalloc.n;
	memmove(buf, tsalloc.ts, n*sizeof(uvlong));
	tsalloc.n = 0;
	iunlock(&tsalloc);
	return n*sizeof(uvlong);
}

M port/devns16552.c => port/devns16552.c +51 -1
@@ 131,7 131,7 @@ struct Uart
	int	modem;			/* hardware flow control on */
	int	xonoff;			/* software flow control on */
	int	blocked;
	int	cts, dsr, dcd;		/* keep track of modem status */ 
	int	cts, dsr, dcd, dcdts;		/* keep track of modem status */ 
	int	ctsbackoff;
	int	hup_dsr, hup_dcd;	/* send hangup upstream? */
	int	dohup;


@@ 149,6 149,41 @@ struct Uartalloc {

void ns16552intr(int);

/* interrupt timestamps, l.s fills intrts each interupt */
uvlong	intrts;
static	struct {
	Lock;
	int	vno;		/* vector to save timestamps for */
	int	n;		/* number of valid timestamps in ts[] */
	uvlong	ts[128];	/* time stamps */
} tsalloc;

/* called with interrupts off by interrupt routine */
static void
savets(void)
{
	lock(&tsalloc);
	if(tsalloc.n < nelem(tsalloc.ts))
		tsalloc.ts[tsalloc.n++] = intrts;
	unlock(&tsalloc);
}

/* read interrupt timestamps */
long
readintrts(void *buf, int n)
{
	n /= sizeof(uvlong);
	if(n <= 0)
		return 0;
	ilock(&tsalloc);
	if(n > tsalloc.n)
		n = tsalloc.n;
	memmove(buf, tsalloc.ts, n*sizeof(uvlong));
	tsalloc.n = 0;
	iunlock(&tsalloc);
	return n*sizeof(uvlong);
}

/*
 *  pick up architecture specific routines and definitions
 */


@@ 254,6 289,15 @@ ns16552rts(Uart *p, int n)
}

/*
 *  save dcd timestamps for gps clock
 */
static void
ns16552dcdts(Uart *p, int n)
{
	p->dcdts = n;
}

/*
 *  send break
 */
static void


@@ 669,6 713,8 @@ ns16552intr(int dev)
			}
	 		if (ch & Dcdc) {
				l = ch & Dcd;
				if(l == 0 && p->dcd != 0 && p->dcdts)
					savets();
				if(p->hup_dcd && p->dcd && !l){
					ilock(&p->rlock);
					p->dohup = 1;


@@ 997,6 1043,10 @@ ns16552ctl(Uart *p, char *cmd)
		qsetlimit(p->iq, n);
		qsetlimit(p->oq, n);
		break;
	case 'T':
	case 't':
		ns16552dcdts(p, n);
		break;
	case 'W':
	case 'w':
		/* obsolete */