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