The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pc/devlml.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Lml 22 driver
    3  */
    4 #include        "u.h"
    5 #include        "../port/lib.h"
    6 #include        "mem.h"
    7 #include        "dat.h"
    8 #include        "fns.h"
    9 #include        "../port/error.h"
   10 #include        "io.h"
   11 
   12 #include        "devlml.h"
   13 
   14 #define DBGREAD 0x01
   15 #define DBGWRIT 0x02
   16 #define DBGINTR 0x04
   17 #define DBGINTS 0x08
   18 
   19 int debug = 0;
   20 
   21 enum{
   22         Qdir,
   23         Qctl0,
   24         Qjpg0,
   25         Qraw0,
   26         Qctl1,
   27         Qjpg1,
   28         Qraw1,
   29 };
   30 
   31 #define QID(q)          ((ulong)(q).path)
   32 #define QIDLML(q)       ((((ulong)(q).path)-1)>>1)
   33 
   34 static Dirtab lmldir[] = {
   35         ".",            {Qdir, 0, QTDIR},       0,      DMDIR|0555,
   36         "lml0ctl",      {Qctl0},                0,      0666,
   37         "lml0jpg",      {Qjpg0},                0,      0444,
   38         "lml0raw",      {Qraw0},                0,      0444,
   39         "lml1ctl",      {Qctl1},                0,      0666,
   40         "lml1jpg",      {Qjpg1},                0,      0444,
   41         "lml1raw",      {Qraw1},                0,      0444,
   42 };
   43 
   44 typedef struct LML LML;
   45 
   46 struct LML {
   47         /* Hardware */
   48         Pcidev  *pcidev;
   49         ulong   pciBaseAddr;
   50 
   51         /* Allocated memory */
   52         CodeData *codedata;
   53 
   54         /* Software state */
   55         ulong   jpgframeno;
   56         int     frameNo;
   57         Rendez  sleepjpg;
   58         int     jpgopens;
   59 } lmls[NLML];
   60 
   61 int nlml;
   62 
   63 static FrameHeader jpgheader = {
   64         MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8,
   65         { 'L', 'M', 'L', '\0'},
   66         -1, 0, 0,  0
   67 };
   68 
   69 #define writel(v, a) *(ulong *)(a) = (v)
   70 #define readl(a) *(ulong*)(a)
   71 
   72 static int
   73 getbuffer(void *x)
   74 {
   75         static last = NBUF-1;
   76         int l = last;
   77         LML *lml;
   78 
   79         lml = x;
   80         for (;;) {
   81                 last = (last+1) % NBUF;
   82                 if (lml->codedata->statCom[last] & STAT_BIT)
   83                         return last + 1;
   84                 if (last == l)
   85                         return 0;
   86         }
   87         return 0;
   88 }
   89 
   90 static long
   91 jpgread(LML *lml, void *va, long nbytes, vlong, int dosleep)
   92 {
   93         int bufno;
   94         FrameHeader *jpgheader;
   95 
   96         /*
   97          * reads should be of size 1 or sizeof(FrameHeader).
   98          * Frameno is the number of the buffer containing the data.
   99          */
  100         while ((bufno = getbuffer(lml)) == 0 && dosleep)
  101                 sleep(&lml->sleepjpg, getbuffer, lml);
  102         if (--bufno < 0)
  103                 return 0;
  104 
  105         jpgheader = (FrameHeader*)(lml->codedata->frag[bufno].hdr+2);
  106         if (nbytes == sizeof(FrameHeader)) {
  107                 memmove(va, jpgheader, sizeof(FrameHeader));
  108                 return sizeof(FrameHeader);
  109         }
  110         if (nbytes == 1) {
  111                 *(char *)va = bufno;
  112                 return 1;
  113         }
  114         return 0;
  115 }
  116 
  117 static void lmlintr(Ureg *, void *);
  118 
  119 static void
  120 prepbuf(LML *lml)
  121 {
  122         int i;
  123         CodeData *cd;
  124 
  125         cd = lml->codedata;
  126         for (i = 0; i < NBUF; i++) {
  127                 cd->statCom[i] = PADDR(&(cd->fragdesc[i]));
  128                 cd->fragdesc[i].addr = PADDR(cd->frag[i].fb);
  129                 /* Length is in double words, in position 1..20 */
  130                 cd->fragdesc[i].leng = FRAGSIZE >> 1 | FRAGM_FINAL_B;
  131                 memmove(cd->frag[i].hdr+2, &jpgheader, sizeof(FrameHeader)-2);
  132         }
  133 }
  134 
  135 static void
  136 lmlreset(void)
  137 {
  138         ulong regpa;
  139         char name[32];
  140         void *regva;
  141         ISAConf isa;
  142         LML *lml;
  143         Pcidev *pcidev;
  144         Physseg segbuf;
  145 
  146         pcidev = nil;
  147 
  148         for (nlml = 0; nlml < NLML && (pcidev = pcimatch(pcidev, VENDOR_ZORAN,
  149             ZORAN_36067)); nlml++){
  150                 if(isaconfig("lml", nlml, &isa) == 0) {
  151                         if (debug) print("lml %d not in plan9.ini\n", nlml);
  152                         break;
  153                 }
  154                 lml = &lmls[nlml];
  155                 lml->pcidev = pcidev;
  156                 lml->codedata = (CodeData*)(((ulong)xalloc(Codedatasize+ BY2PG)
  157                         + BY2PG-1) & ~(BY2PG-1));
  158                 if (lml->codedata == nil) {
  159                         print("devlml: xalloc(%ux, %ux, 0)\n", Codedatasize, BY2PG);
  160                         return;
  161                 }
  162 
  163                 print("Installing Motion JPEG driver %s, irq %d\n",
  164                         MJPG_VERSION, pcidev->intl);
  165                 print("MJPG buffer at 0x%.8lux, size 0x%.8ux\n", lml->codedata,
  166                         Codedatasize);
  167 
  168                 /* Get access to DMA memory buffer */
  169                 lml->codedata->pamjpg = PADDR(lml->codedata->statCom);
  170 
  171                 prepbuf(lml);
  172 
  173                 print("zr36067 found at 0x%.8lux", pcidev->mem[0].bar & ~0x0F);
  174 
  175                 regpa = pcidev->mem[0].bar & ~0x0F;
  176                 regva = vmap(regpa, pcidev->mem[0].size);
  177                 if (regva == 0) {
  178                         print("lml: failed to map registers\n");
  179                         return;
  180                 }
  181                 lml->pciBaseAddr = (ulong)regva;
  182                 print(", mapped at 0x%.8lux\n", lml->pciBaseAddr);
  183 
  184                 memset(&segbuf, 0, sizeof(segbuf));
  185                 segbuf.attr = SG_PHYSICAL;
  186                 sprint(name, "lml%d.mjpg", nlml);
  187                 kstrdup(&segbuf.name, name);
  188                 segbuf.pa = PADDR(lml->codedata);
  189                 segbuf.size = Codedatasize;
  190                 if (addphysseg(&segbuf) == -1) {
  191                         print("lml: physsegment: %s\n", name);
  192                         return;
  193                 }
  194 
  195                 memset(&segbuf, 0, sizeof(segbuf));
  196                 segbuf.attr = SG_PHYSICAL;
  197                 sprint(name, "lml%d.regs", nlml);
  198                 kstrdup(&segbuf.name, name);
  199                 segbuf.pa = (ulong)regpa;
  200                 segbuf.size = pcidev->mem[0].size;
  201                 if (addphysseg(&segbuf) == -1) {
  202                         print("lml: physsegment: %s\n", name);
  203                         return;
  204                 }
  205 
  206                 /* set up interrupt handler */
  207                 intrenable(pcidev->intl, lmlintr, lml, pcidev->tbdf, "lml");
  208         }
  209 }
  210 
  211 static Chan*
  212 lmlattach(char *spec)
  213 {
  214         return devattach('V', spec);
  215 }
  216 
  217 static Walkqid*
  218 lmlwalk(Chan *c, Chan *nc, char **name, int nname)
  219 {
  220         return devwalk(c, nc, name, nname, lmldir, nelem(lmldir), devgen);
  221 }
  222 
  223 static int
  224 lmlstat(Chan *c, uchar *db, int n)
  225 {
  226         return devstat(c, db, n, lmldir, nelem(lmldir), devgen);
  227 }
  228 
  229 static Chan*
  230 lmlopen(Chan *c, int omode)
  231 {
  232         int i;
  233         LML *lml;
  234 
  235         if (omode != OREAD)
  236                 error(Eperm);
  237         c->aux = 0;
  238         i = 0;
  239         switch((ulong)c->qid.path){
  240         case Qctl1:
  241                 i++;
  242                 /* fall through */
  243         case Qctl0:
  244                 if (i >= nlml)
  245                         error(Eio);
  246                 break;
  247         case Qjpg1:
  248         case Qraw1:
  249                 i++;
  250                 /* fall through */
  251         case Qjpg0:
  252         case Qraw0:
  253                 /* allow one open */
  254                 if (i >= nlml)
  255                         error(Eio);
  256                 lml = lmls+i;
  257                 if (lml->jpgopens)
  258                         error(Einuse);
  259                 lml->jpgopens = 1;
  260                 lml->jpgframeno = 0;
  261                 prepbuf(lml);
  262                 break;
  263         }
  264         return devopen(c, omode, lmldir, nelem(lmldir), devgen);
  265 }
  266 
  267 static void
  268 lmlclose(Chan *c)
  269 {
  270         int i;
  271 
  272         i = 0;
  273         switch((ulong)c->qid.path){
  274         case Qjpg1:
  275         case Qraw1:
  276                 i++;
  277                 /* fall through */
  278         case Qjpg0:
  279         case Qraw0:
  280                 lmls[i].jpgopens = 0;
  281                 break;
  282         }
  283 }
  284 
  285 static long
  286 lmlread(Chan *c, void *va, long n, vlong voff)
  287 {
  288         int i, len;
  289         long off = voff;
  290         uchar *buf = va;
  291         LML *lml;
  292         static char lmlinfo[1024];
  293 
  294         i = 0;
  295         switch((ulong)c->qid.path){
  296         case Qdir:
  297                 return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen);
  298         case Qctl1:
  299                 i++;
  300                 /* fall through */
  301         case Qctl0:
  302                 if (i >= nlml)
  303                         error(Eio);
  304                 lml = lmls+i;
  305                 len = snprint(lmlinfo, sizeof lmlinfo, "lml%djpg        lml%draw\nlml%d.regs    0x%lux  0x%ux\nlml%d.mjpg       0x%lux  0x%ux\n",
  306                         i, i,
  307                         i, lml->pcidev->mem[0].bar & ~0x0F, lml->pcidev->mem[0].size,
  308                         i, PADDR(lml->codedata), Codedatasize);
  309                 if (voff > len)
  310                         return 0;
  311                 if (n > len - voff)
  312                         n = len - voff;
  313                 memmove(va, lmlinfo+voff, n);
  314                 return n;
  315         case Qjpg1:
  316                 i++;
  317                 /* fall through */
  318         case Qjpg0:
  319                 if (i >= nlml)
  320                         error(Eio);
  321                 return jpgread(lmls+i, buf, n, off, 1);
  322         case Qraw1:
  323                 i++;
  324                 /* fall through */
  325         case Qraw0:
  326                 if (i >= nlml)
  327                         error(Eio);
  328                 return jpgread(lmls+i, buf, n, off, 0);
  329         }
  330 }
  331 
  332 static long
  333 lmlwrite(Chan *, void *, long, vlong)
  334 {
  335         error(Eperm);
  336         return 0;
  337 }
  338 
  339 Dev lmldevtab = {
  340         'V',
  341         "video",
  342 
  343         lmlreset,
  344         devinit,
  345         devshutdown,
  346         lmlattach,
  347         lmlwalk,
  348         lmlstat,
  349         lmlopen,
  350         devcreate,
  351         lmlclose,
  352         lmlread,
  353         devbread,
  354         lmlwrite,
  355         devbwrite,
  356         devremove,
  357         devwstat,
  358 };
  359 
  360 static void
  361 lmlintr(Ureg *, void *x)
  362 {
  363         ulong fstart, fno, flags, statcom;
  364         FrameHeader *jpgheader;
  365         LML *lml;
  366 
  367         lml = x;
  368         flags = readl(lml->pciBaseAddr+INTR_STAT);
  369         /* Reset all interrupts from 067 */
  370         writel(0xff000000, lml->pciBaseAddr + INTR_STAT);
  371 
  372         if(flags & INTR_JPEGREP) {
  373 
  374                 if(debug&(DBGINTR))
  375                         print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags);
  376 
  377                 fstart = lml->jpgframeno & 3;
  378                 for (;;) {
  379                         lml->jpgframeno++;
  380                         fno = lml->jpgframeno & 3;
  381                         if (lml->codedata->statCom[fno] & STAT_BIT)
  382                                 break;
  383                         if (fno == fstart) {
  384                                 if (debug & DBGINTR)
  385                                         print("Spurious lml jpg intr?\n");
  386                                 return;
  387                         }
  388                 }
  389                 statcom = lml->codedata->statCom[fno];
  390                 jpgheader = (FrameHeader *)(lml->codedata->frag[fno].hdr + 2);
  391                 jpgheader->frameNo = lml->jpgframeno;
  392                 jpgheader->ftime  = todget(nil);
  393                 jpgheader->frameSize = (statcom & 0x00ffffff) >> 1;
  394                 jpgheader->frameSeqNo = statcom >> 24;
  395                 wakeup(&lml->sleepjpg);
  396         }
  397 }

Cache object: a8f9906997ea716c79fcf8a71e97114c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.