123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- /*
- * Lml 22 driver
- */
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "../port/error.h"
- #include "io.h"
- #include "devlml.h"
- #define DBGREAD 0x01
- #define DBGWRIT 0x02
- #define DBGINTR 0x04
- #define DBGINTS 0x08
- #define DBGFS 0x10
- int debug = DBGREAD|DBGWRIT|DBGFS;
- enum{
- Qdir,
- Qctl0,
- Qjpg0,
- Qraw0,
- Qctl1,
- Qjpg1,
- Qraw1,
- };
- static Dirtab lmldir[] = {
- ".", {Qdir, 0, QTDIR}, 0, 0555,
- "lml0ctl", {Qctl0}, 0, 0666,
- "lml0jpg", {Qjpg0}, 0, 0444,
- "lml0raw", {Qraw0}, 0, 0444,
- "lml1ctl", {Qctl1}, 0, 0666,
- "lml1jpg", {Qjpg1}, 0, 0444,
- "lml1raw", {Qraw1}, 0, 0444,
- };
- typedef struct LML LML;
- struct LML {
- /* Hardware */
- Pcidev *pcidev;
- ulong pciBaseAddr;
- /* Allocated memory */
- CodeData *codedata;
- /* Software state */
- ulong jpgframeno;
- int frameNo;
- Rendez sleepjpg;
- int jpgopens;
- } lmls[NLML];
- int nlml;
- static FrameHeader jpgheader = {
- MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8,
- { 'L', 'M', 'L', '\0'},
- -1, 0, 0, 0
- };
- #define writel(v, a) *(ulong *)(a) = (v)
- #define readl(a) *(ulong*)(a)
- static int
- getbuffer(void *x)
- {
- static last = NBUF-1;
- int l = last;
- LML *lml;
- lml = x;
- for(;;){
- last = (last+1) % NBUF;
- if(lml->codedata->statCom[last] & STAT_BIT)
- return last + 1;
- if(last == l)
- return 0;
- }
- }
- static long
- jpgread(LML *lml, void *va, long nbytes, vlong, int dosleep)
- {
- int bufno;
- FrameHeader *jpgheader;
- /*
- * reads should be of size 1 or sizeof(FrameHeader).
- * Frameno is the number of the buffer containing the data.
- */
- while((bufno = getbuffer(lml)) == 0 && dosleep)
- sleep(&lml->sleepjpg, getbuffer, lml);
- if(--bufno < 0)
- return 0;
- jpgheader = (FrameHeader*)(lml->codedata->frag[bufno].hdr+2);
- if(nbytes == sizeof(FrameHeader)){
- memmove(va, jpgheader, sizeof(FrameHeader));
- return sizeof(FrameHeader);
- }
- if(nbytes == 1){
- *(char *)va = bufno;
- return 1;
- }
- return 0;
- }
- static void lmlintr(Ureg *, void *);
- static void
- prepbuf(LML *lml)
- {
- int i;
- CodeData *cd;
- cd = lml->codedata;
- for(i = 0; i < NBUF; i++){
- cd->statCom[i] = PADDR(&(cd->fragdesc[i]));
- cd->fragdesc[i].addr = PADDR(cd->frag[i].fb);
- /* Length is in double words, in position 1..20 */
- cd->fragdesc[i].leng = FRAGSIZE >> 1 | FRAGM_FINAL_B;
- memmove(cd->frag[i].hdr+2, &jpgheader, sizeof(FrameHeader)-2);
- }
- }
- static void
- lmlreset(void)
- {
- ulong regpa;
- char name[32];
- void *regva;
- LML *lml;
- Pcidev *pcidev;
- Physseg segbuf;
- pcidev = nil;
- for(nlml = 0; nlml < NLML && (pcidev = pcimatch(pcidev, VENDOR_ZORAN,
- ZORAN_36067)); nlml++){
- lml = &lmls[nlml];
- lml->pcidev = pcidev;
- lml->codedata = (CodeData*)(((ulong)xalloc(Codedatasize+ BY2PG)
- + BY2PG-1) & ~(BY2PG-1));
- if(lml->codedata == nil){
- print("devlml: xalloc(%ux, %ux, 0)\n", Codedatasize, BY2PG);
- return;
- }
- print("Installing Motion JPEG driver %s, irq %d\n",
- MJPG_VERSION, pcidev->intl);
- print("MJPG buffer at 0x%.8p, size 0x%.8ux\n", lml->codedata,
- Codedatasize);
- /* Get access to DMA memory buffer */
- lml->codedata->pamjpg = PADDR(lml->codedata->statCom);
- prepbuf(lml);
- print("zr36067 found at 0x%.8lux", pcidev->mem[0].bar & ~0x0F);
- regpa = pcidev->mem[0].bar & ~0x0F;
- regva = vmap(regpa, pcidev->mem[0].size);
- if(regva == 0){
- print("lml: failed to map registers\n");
- return;
- }
- lml->pciBaseAddr = (ulong)regva;
- print(", mapped at 0x%.8lux\n", lml->pciBaseAddr);
- memset(&segbuf, 0, sizeof(segbuf));
- segbuf.attr = SG_PHYSICAL;
- sprint(name, "lml%d.mjpg", nlml);
- kstrdup(&segbuf.name, name);
- segbuf.pa = PADDR(lml->codedata);
- segbuf.size = Codedatasize;
- if(addphysseg(&segbuf) == -1){
- print("lml: physsegment: %s\n", name);
- return;
- }
- memset(&segbuf, 0, sizeof(segbuf));
- segbuf.attr = SG_PHYSICAL;
- sprint(name, "lml%d.regs", nlml);
- kstrdup(&segbuf.name, name);
- segbuf.pa = (ulong)regpa;
- segbuf.size = pcidev->mem[0].size;
- if(addphysseg(&segbuf) == -1){
- print("lml: physsegment: %s\n", name);
- return;
- }
- /* set up interrupt handler */
- intrenable(pcidev->intl, lmlintr, lml, pcidev->tbdf, "lml");
- }
- }
- static Chan*
- lmlattach(char *spec)
- {
- if(debug&DBGFS)
- print("lmlattach\n");
- return devattach(L'Λ', spec);
- }
- static Walkqid*
- lmlwalk(Chan *c, Chan *nc, char **name, int nname)
- {
- if(debug&DBGFS)
- print("lmlwalk\n");
- return devwalk(c, nc, name, nname, lmldir, 3*nlml+1, devgen);
- }
- static int
- lmlstat(Chan *c, uchar *db, int n)
- {
- if(debug&DBGFS)
- print("lmlstat\n");
- return devstat(c, db, n, lmldir, 3*nlml+1, devgen);
- }
- static Chan*
- lmlopen(Chan *c, int omode)
- {
- int i;
- LML *lml;
- if(debug&DBGFS)
- print("lmlopen\n");
- if(omode != OREAD)
- error(Eperm);
- c->aux = 0;
- i = 0;
- switch((ulong)c->qid.path){
- case Qctl1:
- i++;
- /* fall through */
- case Qctl0:
- if(i >= nlml)
- error(Eio);
- break;
- case Qjpg1:
- case Qraw1:
- i++;
- /* fall through */
- case Qjpg0:
- case Qraw0:
- /* allow one open */
- if(i >= nlml)
- error(Eio);
- lml = lmls+i;
- if(lml->jpgopens)
- error(Einuse);
- lml->jpgopens = 1;
- lml->jpgframeno = 0;
- prepbuf(lml);
- break;
- }
- return devopen(c, omode, lmldir, 3*nlml+1, devgen);
- }
- static void
- lmlclose(Chan *c)
- {
- int i;
- if(debug&DBGFS)
- print("lmlclose\n");
- i = 0;
- switch((ulong)c->qid.path){
- case Qjpg1:
- case Qraw1:
- i++;
- /* fall through */
- case Qjpg0:
- case Qraw0:
- lmls[i].jpgopens = 0;
- break;
- }
- }
- static long
- lmlread(Chan *c, void *va, long n, vlong voff)
- {
- int i, len;
- long off = voff;
- uchar *buf = va;
- LML *lml;
- static char lmlinfo[1024];
- i = 0;
- switch((ulong)c->qid.path){
- case Qdir:
- n = devdirread(c, (char *)buf, n, lmldir, 3*nlml+1, devgen);
- if(debug&(DBGFS|DBGREAD))
- print("lmlread %ld\n", n);
- return n;
- case Qctl1:
- i++;
- /* fall through */
- case Qctl0:
- if(i >= nlml)
- error(Eio);
- lml = lmls+i;
- len = snprint(lmlinfo, sizeof lmlinfo, "lml%djpg lml%draw\nlml%d.regs 0x%lux 0x%ux\nlml%d.mjpg 0x%lux 0x%ux\n",
- i, i,
- i, lml->pcidev->mem[0].bar & ~0x0F, lml->pcidev->mem[0].size,
- i, PADDR(lml->codedata), Codedatasize);
- if(voff > len)
- return 0;
- if(n > len - voff)
- n = len - voff;
- memmove(va, lmlinfo+voff, n);
- return n;
- case Qjpg1:
- i++;
- /* fall through */
- case Qjpg0:
- if(i >= nlml)
- error(Eio);
- return jpgread(lmls+i, buf, n, off, 1);
- case Qraw1:
- i++;
- /* fall through */
- case Qraw0:
- if(i >= nlml)
- error(Eio);
- return jpgread(lmls+i, buf, n, off, 0);
- }
- return -1;
- }
- static long
- lmlwrite(Chan *, void *, long, vlong)
- {
- error(Eperm);
- return 0;
- }
- Dev lmldevtab = {
- L'Λ',
- "video",
- lmlreset,
- devinit,
- devshutdown,
- lmlattach,
- lmlwalk,
- lmlstat,
- lmlopen,
- devcreate,
- lmlclose,
- lmlread,
- devbread,
- lmlwrite,
- devbwrite,
- devremove,
- devwstat,
- };
- static void
- lmlintr(Ureg *, void *x)
- {
- ulong fstart, fno, flags, statcom;
- FrameHeader *jpgheader;
- LML *lml;
- lml = x;
- flags = readl(lml->pciBaseAddr+INTR_STAT);
- /* Reset all interrupts from 067 */
- writel(0xff000000, lml->pciBaseAddr + INTR_STAT);
- if(flags & INTR_JPEGREP){
- if(debug&DBGINTR)
- print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags);
- fstart = lml->jpgframeno & 3;
- for(;;){
- lml->jpgframeno++;
- fno = lml->jpgframeno & 3;
- if(lml->codedata->statCom[fno] & STAT_BIT)
- break;
- if(fno == fstart){
- if(debug & DBGINTR)
- print("Spurious lml jpg intr?\n");
- return;
- }
- }
- statcom = lml->codedata->statCom[fno];
- jpgheader = (FrameHeader *)(lml->codedata->frag[fno].hdr + 2);
- jpgheader->frameNo = lml->jpgframeno;
- jpgheader->ftime = todget(nil);
- jpgheader->frameSize = (statcom & 0x00ffffff) >> 1;
- jpgheader->frameSeqNo = statcom >> 24;
- wakeup(&lml->sleepjpg);
- }
- }
|