5 #include "../port/lib.h"
9 #include "../port/error.h"
20 int debug = DBGREAD|DBGWRIT|DBGFS;
32 static Dirtab lmldir[] = {
33 ".", {Qdir, 0, QTDIR}, 0, 0555,
34 "lml0ctl", {Qctl0}, 0, 0666,
35 "lml0jpg", {Qjpg0}, 0, 0444,
36 "lml0raw", {Qraw0}, 0, 0444,
37 "lml1ctl", {Qctl1}, 0, 0666,
38 "lml1jpg", {Qjpg1}, 0, 0444,
39 "lml1raw", {Qraw1}, 0, 0444,
42 typedef struct LML LML;
49 /* Allocated memory */
61 static FrameHeader jpgheader = {
62 MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8,
63 { 'L', 'M', 'L', '\0'},
67 #define writel(v, a) *(ulong *)(a) = (v)
68 #define readl(a) *(ulong*)(a)
79 last = (last+1) % NBUF;
80 if(lml->codedata->statCom[last] & STAT_BIT)
88 jpgread(LML *lml, void *va, long nbytes, vlong, int dosleep)
91 FrameHeader *jpgheader;
94 * reads should be of size 1 or sizeof(FrameHeader).
95 * Frameno is the number of the buffer containing the data.
97 while((bufno = getbuffer(lml)) == 0 && dosleep)
98 sleep(&lml->sleepjpg, getbuffer, lml);
102 jpgheader = (FrameHeader*)(lml->codedata->frag[bufno].hdr+2);
103 if(nbytes == sizeof(FrameHeader)){
104 memmove(va, jpgheader, sizeof(FrameHeader));
105 return sizeof(FrameHeader);
114 static void lmlintr(Ureg *, void *);
123 for(i = 0; i < NBUF; i++){
124 cd->statCom[i] = PADDR(&(cd->fragdesc[i]));
125 cd->fragdesc[i].addr = PADDR(cd->frag[i].fb);
126 /* Length is in double words, in position 1..20 */
127 cd->fragdesc[i].leng = FRAGSIZE >> 1 | FRAGM_FINAL_B;
128 memmove(cd->frag[i].hdr+2, &jpgheader, sizeof(FrameHeader)-2);
144 for(nlml = 0; nlml < NLML && (pcidev = pcimatch(pcidev, VENDOR_ZORAN,
145 ZORAN_36067)); nlml++){
147 lml->pcidev = pcidev;
148 lml->codedata = (CodeData*)(((ulong)xalloc(Codedatasize+ BY2PG)
149 + BY2PG-1) & ~(BY2PG-1));
150 if(lml->codedata == nil){
151 print("devlml: xalloc(%ux, %ux, 0)\n", Codedatasize, BY2PG);
155 print("Installing Motion JPEG driver %s, irq %d\n",
156 MJPG_VERSION, pcidev->intl);
157 print("MJPG buffer at 0x%.8p, size 0x%.8ux\n", lml->codedata,
160 /* Get access to DMA memory buffer */
161 lml->codedata->pamjpg = PADDR(lml->codedata->statCom);
165 print("zr36067 found at 0x%.8lux", pcidev->mem[0].bar & ~0x0F);
167 regpa = pcidev->mem[0].bar & ~0x0F;
168 regva = vmap(regpa, pcidev->mem[0].size);
170 print("lml: failed to map registers\n");
173 lml->pciBaseAddr = (ulong)regva;
174 print(", mapped at 0x%.8lux\n", lml->pciBaseAddr);
176 memset(&segbuf, 0, sizeof(segbuf));
177 segbuf.attr = SG_PHYSICAL;
178 sprint(name, "lml%d.mjpg", nlml);
179 kstrdup(&segbuf.name, name);
180 segbuf.pa = PADDR(lml->codedata);
181 segbuf.size = Codedatasize;
182 if(addphysseg(&segbuf) == -1){
183 print("lml: physsegment: %s\n", name);
187 memset(&segbuf, 0, sizeof(segbuf));
188 segbuf.attr = SG_PHYSICAL;
189 sprint(name, "lml%d.regs", nlml);
190 kstrdup(&segbuf.name, name);
191 segbuf.pa = (ulong)regpa;
192 segbuf.size = pcidev->mem[0].size;
193 if(addphysseg(&segbuf) == -1){
194 print("lml: physsegment: %s\n", name);
198 /* set up interrupt handler */
199 intrenable(pcidev->intl, lmlintr, lml, pcidev->tbdf, "lml");
204 lmlattach(char *spec)
207 print("lmlattach\n");
208 return devattach(L'Λ', spec);
212 lmlwalk(Chan *c, Chan *nc, char **name, int nname)
216 return devwalk(c, nc, name, nname, lmldir, 3*nlml+1, devgen);
220 lmlstat(Chan *c, uchar *db, int n)
224 return devstat(c, db, n, lmldir, 3*nlml+1, devgen);
228 lmlopen(Chan *c, int omode)
239 switch((ulong)c->qid.path){
264 return devopen(c, omode, lmldir, 3*nlml+1, devgen);
275 switch((ulong)c->qid.path){
282 lmls[i].jpgopens = 0;
288 lmlread(Chan *c, void *va, long n, vlong voff)
294 static char lmlinfo[1024];
297 switch((ulong)c->qid.path){
299 n = devdirread(c, (char *)buf, n, lmldir, 3*nlml+1, devgen);
300 if(debug&(DBGFS|DBGREAD))
301 print("lmlread %ld\n", n);
310 len = snprint(lmlinfo, sizeof lmlinfo, "lml%djpg lml%draw\nlml%d.regs 0x%lux 0x%ux\nlml%d.mjpg 0x%lux 0x%ux\n",
312 i, lml->pcidev->mem[0].bar & ~0x0F, lml->pcidev->mem[0].size,
313 i, PADDR(lml->codedata), Codedatasize);
318 memmove(va, lmlinfo+voff, n);
326 return jpgread(lmls+i, buf, n, off, 1);
333 return jpgread(lmls+i, buf, n, off, 0);
339 lmlwrite(Chan *, void *, long, vlong)
367 lmlintr(Ureg *, void *x)
369 ulong fstart, fno, flags, statcom;
370 FrameHeader *jpgheader;
374 flags = readl(lml->pciBaseAddr+INTR_STAT);
375 /* Reset all interrupts from 067 */
376 writel(0xff000000, lml->pciBaseAddr + INTR_STAT);
378 if(flags & INTR_JPEGREP){
381 print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags);
383 fstart = lml->jpgframeno & 3;
386 fno = lml->jpgframeno & 3;
387 if(lml->codedata->statCom[fno] & STAT_BIT)
391 print("Spurious lml jpg intr?\n");
395 statcom = lml->codedata->statCom[fno];
396 jpgheader = (FrameHeader *)(lml->codedata->frag[fno].hdr + 2);
397 jpgheader->frameNo = lml->jpgframeno;
398 jpgheader->ftime = todget(nil);
399 jpgheader->frameSize = (statcom & 0x00ffffff) >> 1;
400 jpgheader->frameSeqNo = statcom >> 24;
401 wakeup(&lml->sleepjpg);