xref: /plan9/sys/src/9/pc/devlml.c (revision 7ec5746a5244cc505568e3d45ab9d5421abbdc7d)
141dd6b47SDavid du Colombier /*
241dd6b47SDavid du Colombier  * Lml 22 driver
341dd6b47SDavid du Colombier  */
43ff48bf5SDavid du Colombier #include	"u.h"
53ff48bf5SDavid du Colombier #include	"../port/lib.h"
63ff48bf5SDavid du Colombier #include	"mem.h"
73ff48bf5SDavid du Colombier #include	"dat.h"
83ff48bf5SDavid du Colombier #include	"fns.h"
93ff48bf5SDavid du Colombier #include	"../port/error.h"
103ff48bf5SDavid du Colombier #include	"io.h"
113ff48bf5SDavid du Colombier 
123ff48bf5SDavid du Colombier #include	"devlml.h"
133ff48bf5SDavid du Colombier 
143ff48bf5SDavid du Colombier #define DBGREAD	0x01
153ff48bf5SDavid du Colombier #define DBGWRIT	0x02
163ff48bf5SDavid du Colombier #define DBGINTR	0x04
173ff48bf5SDavid du Colombier #define DBGINTS	0x08
18*7ec5746aSDavid du Colombier #define DBGFS	0x10
193ff48bf5SDavid du Colombier 
20*7ec5746aSDavid du Colombier int debug = DBGREAD|DBGWRIT|DBGFS;
213ff48bf5SDavid du Colombier 
223ff48bf5SDavid du Colombier enum{
233ff48bf5SDavid du Colombier 	Qdir,
243ff48bf5SDavid du Colombier 	Qctl0,
253ff48bf5SDavid du Colombier 	Qjpg0,
263ff48bf5SDavid du Colombier 	Qraw0,
273ff48bf5SDavid du Colombier 	Qctl1,
283ff48bf5SDavid du Colombier 	Qjpg1,
293ff48bf5SDavid du Colombier 	Qraw1,
303ff48bf5SDavid du Colombier };
313ff48bf5SDavid du Colombier 
323ff48bf5SDavid du Colombier static Dirtab lmldir[] = {
33*7ec5746aSDavid du Colombier 	".",		{Qdir, 0, QTDIR},	0,	0555,
343ff48bf5SDavid du Colombier 	"lml0ctl",	{Qctl0},		0,	0666,
353ff48bf5SDavid du Colombier 	"lml0jpg",	{Qjpg0},		0,	0444,
363ff48bf5SDavid du Colombier 	"lml0raw",	{Qraw0},		0,	0444,
373ff48bf5SDavid du Colombier 	"lml1ctl",	{Qctl1},		0,	0666,
383ff48bf5SDavid du Colombier 	"lml1jpg",	{Qjpg1},		0,	0444,
393ff48bf5SDavid du Colombier 	"lml1raw",	{Qraw1},		0,	0444,
403ff48bf5SDavid du Colombier };
413ff48bf5SDavid du Colombier 
423ff48bf5SDavid du Colombier typedef struct LML LML;
433ff48bf5SDavid du Colombier 
443ff48bf5SDavid du Colombier struct LML {
4541dd6b47SDavid du Colombier 	/* Hardware */
463ff48bf5SDavid du Colombier 	Pcidev	*pcidev;
473ff48bf5SDavid du Colombier 	ulong	pciBaseAddr;
4841dd6b47SDavid du Colombier 
4941dd6b47SDavid du Colombier 	/* Allocated memory */
503ff48bf5SDavid du Colombier 	CodeData *codedata;
5141dd6b47SDavid du Colombier 
5241dd6b47SDavid du Colombier 	/* Software state */
533ff48bf5SDavid du Colombier 	ulong	jpgframeno;
543ff48bf5SDavid du Colombier 	int	frameNo;
553ff48bf5SDavid du Colombier 	Rendez	sleepjpg;
563ff48bf5SDavid du Colombier 	int	jpgopens;
573ff48bf5SDavid du Colombier } lmls[NLML];
583ff48bf5SDavid du Colombier 
593ff48bf5SDavid du Colombier int nlml;
603ff48bf5SDavid du Colombier 
613ff48bf5SDavid du Colombier static FrameHeader jpgheader = {
623ff48bf5SDavid du Colombier 	MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8,
633ff48bf5SDavid du Colombier 	{ 'L', 'M', 'L', '\0'},
643ff48bf5SDavid du Colombier 	-1, 0, 0,  0
653ff48bf5SDavid du Colombier };
663ff48bf5SDavid du Colombier 
673ff48bf5SDavid du Colombier #define writel(v, a) *(ulong *)(a) = (v)
683ff48bf5SDavid du Colombier #define readl(a) *(ulong*)(a)
693ff48bf5SDavid du Colombier 
703ff48bf5SDavid du Colombier static int
getbuffer(void * x)7141dd6b47SDavid du Colombier getbuffer(void *x)
7241dd6b47SDavid du Colombier {
733ff48bf5SDavid du Colombier 	static last = NBUF-1;
743ff48bf5SDavid du Colombier 	int l = last;
753ff48bf5SDavid du Colombier 	LML *lml;
763ff48bf5SDavid du Colombier 
773ff48bf5SDavid du Colombier 	lml = x;
783ff48bf5SDavid du Colombier 	for(;;){
793ff48bf5SDavid du Colombier 		last = (last+1) % NBUF;
803ff48bf5SDavid du Colombier 		if(lml->codedata->statCom[last] & STAT_BIT)
813ff48bf5SDavid du Colombier 			return last + 1;
823ff48bf5SDavid du Colombier 		if(last == l)
833ff48bf5SDavid du Colombier 			return 0;
843ff48bf5SDavid du Colombier 	}
853ff48bf5SDavid du Colombier }
863ff48bf5SDavid du Colombier 
873ff48bf5SDavid du Colombier static long
jpgread(LML * lml,void * va,long nbytes,vlong,int dosleep)8841dd6b47SDavid du Colombier jpgread(LML *lml, void *va, long nbytes, vlong, int dosleep)
8941dd6b47SDavid du Colombier {
903ff48bf5SDavid du Colombier 	int bufno;
913ff48bf5SDavid du Colombier 	FrameHeader *jpgheader;
923ff48bf5SDavid du Colombier 
9341dd6b47SDavid du Colombier 	/*
9441dd6b47SDavid du Colombier 	 * reads should be of size 1 or sizeof(FrameHeader).
9541dd6b47SDavid du Colombier 	 * Frameno is the number of the buffer containing the data.
9641dd6b47SDavid du Colombier 	 */
973ff48bf5SDavid du Colombier 	while((bufno = getbuffer(lml)) == 0 && dosleep)
983ff48bf5SDavid du Colombier 		sleep(&lml->sleepjpg, getbuffer, lml);
993ff48bf5SDavid du Colombier 	if(--bufno < 0)
1003ff48bf5SDavid du Colombier 		return 0;
1013ff48bf5SDavid du Colombier 
1023ff48bf5SDavid du Colombier 	jpgheader = (FrameHeader*)(lml->codedata->frag[bufno].hdr+2);
1033ff48bf5SDavid du Colombier 	if(nbytes == sizeof(FrameHeader)){
1043ff48bf5SDavid du Colombier 		memmove(va, jpgheader, sizeof(FrameHeader));
1053ff48bf5SDavid du Colombier 		return sizeof(FrameHeader);
1063ff48bf5SDavid du Colombier 	}
1073ff48bf5SDavid du Colombier 	if(nbytes == 1){
1083ff48bf5SDavid du Colombier 		*(char *)va = bufno;
1093ff48bf5SDavid du Colombier 		return 1;
1103ff48bf5SDavid du Colombier 	}
1113ff48bf5SDavid du Colombier 	return 0;
1123ff48bf5SDavid du Colombier }
1133ff48bf5SDavid du Colombier 
1143ff48bf5SDavid du Colombier static void lmlintr(Ureg *, void *);
1153ff48bf5SDavid du Colombier 
1163ff48bf5SDavid du Colombier static void
prepbuf(LML * lml)11741dd6b47SDavid du Colombier prepbuf(LML *lml)
11841dd6b47SDavid du Colombier {
1193ff48bf5SDavid du Colombier 	int i;
12041dd6b47SDavid du Colombier 	CodeData *cd;
1213ff48bf5SDavid du Colombier 
12241dd6b47SDavid du Colombier 	cd = lml->codedata;
1233ff48bf5SDavid du Colombier 	for(i = 0; i < NBUF; i++){
12441dd6b47SDavid du Colombier 		cd->statCom[i] = PADDR(&(cd->fragdesc[i]));
12541dd6b47SDavid du Colombier 		cd->fragdesc[i].addr = PADDR(cd->frag[i].fb);
12641dd6b47SDavid du Colombier 		/* Length is in double words, in position 1..20 */
12741dd6b47SDavid du Colombier 		cd->fragdesc[i].leng = FRAGSIZE >> 1 | FRAGM_FINAL_B;
12841dd6b47SDavid du Colombier 		memmove(cd->frag[i].hdr+2, &jpgheader, sizeof(FrameHeader)-2);
1293ff48bf5SDavid du Colombier 	}
1303ff48bf5SDavid du Colombier }
1313ff48bf5SDavid du Colombier 
1323ff48bf5SDavid du Colombier static void
lmlreset(void)1333ff48bf5SDavid du Colombier lmlreset(void)
1343ff48bf5SDavid du Colombier {
1353ff48bf5SDavid du Colombier 	ulong regpa;
13641dd6b47SDavid du Colombier 	char name[32];
1374de34a7eSDavid du Colombier 	void *regva;
1383ff48bf5SDavid du Colombier 	LML *lml;
13941dd6b47SDavid du Colombier 	Pcidev *pcidev;
14041dd6b47SDavid du Colombier 	Physseg segbuf;
1413ff48bf5SDavid du Colombier 
1423ff48bf5SDavid du Colombier 	pcidev = nil;
1433ff48bf5SDavid du Colombier 
14441dd6b47SDavid du Colombier 	for(nlml = 0; nlml < NLML && (pcidev = pcimatch(pcidev, VENDOR_ZORAN,
14541dd6b47SDavid du Colombier 	    ZORAN_36067)); nlml++){
1463ff48bf5SDavid du Colombier 		lml = &lmls[nlml];
1473ff48bf5SDavid du Colombier 		lml->pcidev = pcidev;
14841dd6b47SDavid du Colombier 		lml->codedata = (CodeData*)(((ulong)xalloc(Codedatasize+ BY2PG)
14941dd6b47SDavid du Colombier 			+ BY2PG-1) & ~(BY2PG-1));
1503ff48bf5SDavid du Colombier 		if(lml->codedata == nil){
1513ff48bf5SDavid du Colombier 			print("devlml: xalloc(%ux, %ux, 0)\n", Codedatasize, BY2PG);
1523ff48bf5SDavid du Colombier 			return;
1533ff48bf5SDavid du Colombier 		}
1543ff48bf5SDavid du Colombier 
15541dd6b47SDavid du Colombier 		print("Installing Motion JPEG driver %s, irq %d\n",
15641dd6b47SDavid du Colombier 			MJPG_VERSION, pcidev->intl);
157*7ec5746aSDavid du Colombier 		print("MJPG buffer at 0x%.8p, size 0x%.8ux\n", lml->codedata,
15841dd6b47SDavid du Colombier 			Codedatasize);
1593ff48bf5SDavid du Colombier 
16041dd6b47SDavid du Colombier 		/* Get access to DMA memory buffer */
1613ff48bf5SDavid du Colombier 		lml->codedata->pamjpg = PADDR(lml->codedata->statCom);
1623ff48bf5SDavid du Colombier 
1633ff48bf5SDavid du Colombier 		prepbuf(lml);
1643ff48bf5SDavid du Colombier 
1653ff48bf5SDavid du Colombier 		print("zr36067 found at 0x%.8lux", pcidev->mem[0].bar & ~0x0F);
1663ff48bf5SDavid du Colombier 
1674de34a7eSDavid du Colombier 		regpa = pcidev->mem[0].bar & ~0x0F;
16873e742d7SDavid du Colombier 		regva = vmap(regpa, pcidev->mem[0].size);
1694de34a7eSDavid du Colombier 		if(regva == 0){
1703ff48bf5SDavid du Colombier 			print("lml: failed to map registers\n");
1713ff48bf5SDavid du Colombier 			return;
1723ff48bf5SDavid du Colombier 		}
1734de34a7eSDavid du Colombier 		lml->pciBaseAddr = (ulong)regva;
1743ff48bf5SDavid du Colombier 		print(", mapped at 0x%.8lux\n", lml->pciBaseAddr);
1753ff48bf5SDavid du Colombier 
1763ff48bf5SDavid du Colombier 		memset(&segbuf, 0, sizeof(segbuf));
1773ff48bf5SDavid du Colombier 		segbuf.attr = SG_PHYSICAL;
1783ff48bf5SDavid du Colombier 		sprint(name, "lml%d.mjpg", nlml);
1793ff48bf5SDavid du Colombier 		kstrdup(&segbuf.name, name);
1803ff48bf5SDavid du Colombier 		segbuf.pa = PADDR(lml->codedata);
1813ff48bf5SDavid du Colombier 		segbuf.size = Codedatasize;
1823ff48bf5SDavid du Colombier 		if(addphysseg(&segbuf) == -1){
1833ff48bf5SDavid du Colombier 			print("lml: physsegment: %s\n", name);
1843ff48bf5SDavid du Colombier 			return;
1853ff48bf5SDavid du Colombier 		}
1863ff48bf5SDavid du Colombier 
1873ff48bf5SDavid du Colombier 		memset(&segbuf, 0, sizeof(segbuf));
1883ff48bf5SDavid du Colombier 		segbuf.attr = SG_PHYSICAL;
1893ff48bf5SDavid du Colombier 		sprint(name, "lml%d.regs", nlml);
1903ff48bf5SDavid du Colombier 		kstrdup(&segbuf.name, name);
1913ff48bf5SDavid du Colombier 		segbuf.pa = (ulong)regpa;
1923ff48bf5SDavid du Colombier 		segbuf.size = pcidev->mem[0].size;
1933ff48bf5SDavid du Colombier 		if(addphysseg(&segbuf) == -1){
1943ff48bf5SDavid du Colombier 			print("lml: physsegment: %s\n", name);
1953ff48bf5SDavid du Colombier 			return;
1963ff48bf5SDavid du Colombier 		}
1973ff48bf5SDavid du Colombier 
19841dd6b47SDavid du Colombier 		/* set up interrupt handler */
1993ff48bf5SDavid du Colombier 		intrenable(pcidev->intl, lmlintr, lml, pcidev->tbdf, "lml");
2003ff48bf5SDavid du Colombier 	}
2013ff48bf5SDavid du Colombier }
2023ff48bf5SDavid du Colombier 
2033ff48bf5SDavid du Colombier static Chan*
lmlattach(char * spec)2043ff48bf5SDavid du Colombier lmlattach(char *spec)
2053ff48bf5SDavid du Colombier {
206*7ec5746aSDavid du Colombier 	if(debug&DBGFS)
207*7ec5746aSDavid du Colombier 		print("lmlattach\n");
208*7ec5746aSDavid du Colombier 	return devattach(L'Λ', spec);
2093ff48bf5SDavid du Colombier }
2103ff48bf5SDavid du Colombier 
2113ff48bf5SDavid du Colombier static Walkqid*
lmlwalk(Chan * c,Chan * nc,char ** name,int nname)2123ff48bf5SDavid du Colombier lmlwalk(Chan *c, Chan *nc, char **name, int nname)
2133ff48bf5SDavid du Colombier {
214*7ec5746aSDavid du Colombier 	if(debug&DBGFS)
215*7ec5746aSDavid du Colombier 		print("lmlwalk\n");
216*7ec5746aSDavid du Colombier 	return devwalk(c, nc, name, nname, lmldir, 3*nlml+1, devgen);
2173ff48bf5SDavid du Colombier }
2183ff48bf5SDavid du Colombier 
2193ff48bf5SDavid du Colombier static int
lmlstat(Chan * c,uchar * db,int n)2203ff48bf5SDavid du Colombier lmlstat(Chan *c, uchar *db, int n)
2213ff48bf5SDavid du Colombier {
222*7ec5746aSDavid du Colombier 	if(debug&DBGFS)
223*7ec5746aSDavid du Colombier 		print("lmlstat\n");
224*7ec5746aSDavid du Colombier 	return devstat(c, db, n, lmldir, 3*nlml+1, devgen);
2253ff48bf5SDavid du Colombier }
2263ff48bf5SDavid du Colombier 
2273ff48bf5SDavid du Colombier static Chan*
lmlopen(Chan * c,int omode)22841dd6b47SDavid du Colombier lmlopen(Chan *c, int omode)
22941dd6b47SDavid du Colombier {
2303ff48bf5SDavid du Colombier 	int i;
2313ff48bf5SDavid du Colombier 	LML *lml;
2323ff48bf5SDavid du Colombier 
233*7ec5746aSDavid du Colombier 	if(debug&DBGFS)
234*7ec5746aSDavid du Colombier 		print("lmlopen\n");
2353ff48bf5SDavid du Colombier 	if(omode != OREAD)
2363ff48bf5SDavid du Colombier 		error(Eperm);
2373ff48bf5SDavid du Colombier 	c->aux = 0;
2383ff48bf5SDavid du Colombier 	i = 0;
2393ff48bf5SDavid du Colombier 	switch((ulong)c->qid.path){
2403ff48bf5SDavid du Colombier 	case Qctl1:
2413ff48bf5SDavid du Colombier 		i++;
24241dd6b47SDavid du Colombier 		/* fall through */
2433ff48bf5SDavid du Colombier 	case Qctl0:
2443ff48bf5SDavid du Colombier 		if(i >= nlml)
2453ff48bf5SDavid du Colombier 			error(Eio);
2463ff48bf5SDavid du Colombier 		break;
2473ff48bf5SDavid du Colombier 	case Qjpg1:
2483ff48bf5SDavid du Colombier 	case Qraw1:
2493ff48bf5SDavid du Colombier 		i++;
25041dd6b47SDavid du Colombier 		/* fall through */
2513ff48bf5SDavid du Colombier 	case Qjpg0:
2523ff48bf5SDavid du Colombier 	case Qraw0:
25341dd6b47SDavid du Colombier 		/* allow one open */
2543ff48bf5SDavid du Colombier 		if(i >= nlml)
2553ff48bf5SDavid du Colombier 			error(Eio);
2563ff48bf5SDavid du Colombier 		lml = lmls+i;
2573ff48bf5SDavid du Colombier 		if(lml->jpgopens)
2583ff48bf5SDavid du Colombier 			error(Einuse);
2593ff48bf5SDavid du Colombier 		lml->jpgopens = 1;
2603ff48bf5SDavid du Colombier 		lml->jpgframeno = 0;
2613ff48bf5SDavid du Colombier 		prepbuf(lml);
2623ff48bf5SDavid du Colombier 		break;
2633ff48bf5SDavid du Colombier 	}
264*7ec5746aSDavid du Colombier 	return devopen(c, omode, lmldir, 3*nlml+1, devgen);
2653ff48bf5SDavid du Colombier }
2663ff48bf5SDavid du Colombier 
2673ff48bf5SDavid du Colombier static void
lmlclose(Chan * c)26841dd6b47SDavid du Colombier lmlclose(Chan *c)
26941dd6b47SDavid du Colombier {
2703ff48bf5SDavid du Colombier 	int i;
2713ff48bf5SDavid du Colombier 
272*7ec5746aSDavid du Colombier 	if(debug&DBGFS)
273*7ec5746aSDavid du Colombier 		print("lmlclose\n");
2743ff48bf5SDavid du Colombier 	i = 0;
2753ff48bf5SDavid du Colombier 	switch((ulong)c->qid.path){
2763ff48bf5SDavid du Colombier 	case Qjpg1:
2773ff48bf5SDavid du Colombier 	case Qraw1:
2783ff48bf5SDavid du Colombier 		i++;
27941dd6b47SDavid du Colombier 		/* fall through */
2803ff48bf5SDavid du Colombier 	case Qjpg0:
2813ff48bf5SDavid du Colombier 	case Qraw0:
2823ff48bf5SDavid du Colombier 		lmls[i].jpgopens = 0;
2833ff48bf5SDavid du Colombier 		break;
2843ff48bf5SDavid du Colombier 	}
2853ff48bf5SDavid du Colombier }
2863ff48bf5SDavid du Colombier 
2873ff48bf5SDavid du Colombier static long
lmlread(Chan * c,void * va,long n,vlong voff)28841dd6b47SDavid du Colombier lmlread(Chan *c, void *va, long n, vlong voff)
28941dd6b47SDavid du Colombier {
29041dd6b47SDavid du Colombier 	int i, len;
2913ff48bf5SDavid du Colombier 	long off = voff;
29241dd6b47SDavid du Colombier 	uchar *buf = va;
2933ff48bf5SDavid du Colombier 	LML *lml;
2943ff48bf5SDavid du Colombier 	static char lmlinfo[1024];
2953ff48bf5SDavid du Colombier 
2963ff48bf5SDavid du Colombier 	i = 0;
2973ff48bf5SDavid du Colombier 	switch((ulong)c->qid.path){
2983ff48bf5SDavid du Colombier 	case Qdir:
299*7ec5746aSDavid du Colombier 		n = devdirread(c, (char *)buf, n, lmldir, 3*nlml+1, devgen);
300*7ec5746aSDavid du Colombier 		if(debug&(DBGFS|DBGREAD))
301*7ec5746aSDavid du Colombier 			print("lmlread %ld\n", n);
302*7ec5746aSDavid du Colombier 		return n;
3033ff48bf5SDavid du Colombier 	case Qctl1:
3043ff48bf5SDavid du Colombier 		i++;
30541dd6b47SDavid du Colombier 		/* fall through */
3063ff48bf5SDavid du Colombier 	case Qctl0:
3073ff48bf5SDavid du Colombier 		if(i >= nlml)
3083ff48bf5SDavid du Colombier 			error(Eio);
3093ff48bf5SDavid du Colombier 		lml = lmls+i;
3103ff48bf5SDavid du Colombier 		len = snprint(lmlinfo, sizeof lmlinfo, "lml%djpg	lml%draw\nlml%d.regs	0x%lux	0x%ux\nlml%d.mjpg	0x%lux	0x%ux\n",
3113ff48bf5SDavid du Colombier 			i, i,
3123ff48bf5SDavid du Colombier 			i, lml->pcidev->mem[0].bar & ~0x0F, lml->pcidev->mem[0].size,
3133ff48bf5SDavid du Colombier 			i, PADDR(lml->codedata), Codedatasize);
3143ff48bf5SDavid du Colombier 		if(voff > len)
3153ff48bf5SDavid du Colombier 			return 0;
3163ff48bf5SDavid du Colombier 		if(n > len - voff)
3173ff48bf5SDavid du Colombier 			n = len - voff;
3183ff48bf5SDavid du Colombier 		memmove(va, lmlinfo+voff, n);
3193ff48bf5SDavid du Colombier 		return n;
3203ff48bf5SDavid du Colombier 	case Qjpg1:
3213ff48bf5SDavid du Colombier 		i++;
32241dd6b47SDavid du Colombier 		/* fall through */
3233ff48bf5SDavid du Colombier 	case Qjpg0:
3243ff48bf5SDavid du Colombier 		if(i >= nlml)
3253ff48bf5SDavid du Colombier 			error(Eio);
3263ff48bf5SDavid du Colombier 		return jpgread(lmls+i, buf, n, off, 1);
3273ff48bf5SDavid du Colombier 	case Qraw1:
3283ff48bf5SDavid du Colombier 		i++;
32941dd6b47SDavid du Colombier 		/* fall through */
3303ff48bf5SDavid du Colombier 	case Qraw0:
3313ff48bf5SDavid du Colombier 		if(i >= nlml)
3323ff48bf5SDavid du Colombier 			error(Eio);
3333ff48bf5SDavid du Colombier 		return jpgread(lmls+i, buf, n, off, 0);
3343ff48bf5SDavid du Colombier 	}
335*7ec5746aSDavid du Colombier 	return -1;
3363ff48bf5SDavid du Colombier }
3373ff48bf5SDavid du Colombier 
3383ff48bf5SDavid du Colombier static long
lmlwrite(Chan *,void *,long,vlong)33941dd6b47SDavid du Colombier lmlwrite(Chan *, void *, long, vlong)
34041dd6b47SDavid du Colombier {
3413ff48bf5SDavid du Colombier 	error(Eperm);
3423ff48bf5SDavid du Colombier 	return 0;
3433ff48bf5SDavid du Colombier }
3443ff48bf5SDavid du Colombier 
3453ff48bf5SDavid du Colombier Dev lmldevtab = {
346*7ec5746aSDavid du Colombier 	L'Λ',
3473ff48bf5SDavid du Colombier 	"video",
3483ff48bf5SDavid du Colombier 
3493ff48bf5SDavid du Colombier 	lmlreset,
3503ff48bf5SDavid du Colombier 	devinit,
3513ff48bf5SDavid du Colombier 	devshutdown,
3523ff48bf5SDavid du Colombier 	lmlattach,
3533ff48bf5SDavid du Colombier 	lmlwalk,
3543ff48bf5SDavid du Colombier 	lmlstat,
3553ff48bf5SDavid du Colombier 	lmlopen,
3563ff48bf5SDavid du Colombier 	devcreate,
3573ff48bf5SDavid du Colombier 	lmlclose,
3583ff48bf5SDavid du Colombier 	lmlread,
3593ff48bf5SDavid du Colombier 	devbread,
3603ff48bf5SDavid du Colombier 	lmlwrite,
3613ff48bf5SDavid du Colombier 	devbwrite,
3623ff48bf5SDavid du Colombier 	devremove,
3633ff48bf5SDavid du Colombier 	devwstat,
3643ff48bf5SDavid du Colombier };
3653ff48bf5SDavid du Colombier 
3663ff48bf5SDavid du Colombier static void
lmlintr(Ureg *,void * x)36741dd6b47SDavid du Colombier lmlintr(Ureg *, void *x)
36841dd6b47SDavid du Colombier {
3693ff48bf5SDavid du Colombier 	ulong fstart, fno, flags, statcom;
37041dd6b47SDavid du Colombier 	FrameHeader *jpgheader;
3713ff48bf5SDavid du Colombier 	LML *lml;
3723ff48bf5SDavid du Colombier 
3733ff48bf5SDavid du Colombier 	lml = x;
3743ff48bf5SDavid du Colombier 	flags = readl(lml->pciBaseAddr+INTR_STAT);
37541dd6b47SDavid du Colombier 	/* Reset all interrupts from 067 */
3763ff48bf5SDavid du Colombier 	writel(0xff000000, lml->pciBaseAddr + INTR_STAT);
3773ff48bf5SDavid du Colombier 
3783ff48bf5SDavid du Colombier 	if(flags & INTR_JPEGREP){
3793ff48bf5SDavid du Colombier 
380*7ec5746aSDavid du Colombier 		if(debug&DBGINTR)
3813ff48bf5SDavid du Colombier 			print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags);
3823ff48bf5SDavid du Colombier 
38341dd6b47SDavid du Colombier 		fstart = lml->jpgframeno & 3;
3843ff48bf5SDavid du Colombier 		for(;;){
3853ff48bf5SDavid du Colombier 			lml->jpgframeno++;
38641dd6b47SDavid du Colombier 			fno = lml->jpgframeno & 3;
3873ff48bf5SDavid du Colombier 			if(lml->codedata->statCom[fno] & STAT_BIT)
3883ff48bf5SDavid du Colombier 				break;
3893ff48bf5SDavid du Colombier 			if(fno == fstart){
3903ff48bf5SDavid du Colombier 				if(debug & DBGINTR)
3913ff48bf5SDavid du Colombier 					print("Spurious lml jpg intr?\n");
3923ff48bf5SDavid du Colombier 				return;
3933ff48bf5SDavid du Colombier 			}
3943ff48bf5SDavid du Colombier 		}
3953ff48bf5SDavid du Colombier 		statcom = lml->codedata->statCom[fno];
3963ff48bf5SDavid du Colombier 		jpgheader = (FrameHeader *)(lml->codedata->frag[fno].hdr + 2);
3973ff48bf5SDavid du Colombier 		jpgheader->frameNo = lml->jpgframeno;
3983ff48bf5SDavid du Colombier 		jpgheader->ftime  = todget(nil);
3993ff48bf5SDavid du Colombier 		jpgheader->frameSize = (statcom & 0x00ffffff) >> 1;
4003ff48bf5SDavid du Colombier 		jpgheader->frameSeqNo = statcom >> 24;
4013ff48bf5SDavid du Colombier 		wakeup(&lml->sleepjpg);
4023ff48bf5SDavid du Colombier 	}
4033ff48bf5SDavid du Colombier }
404