devlml.c 7.4 KB

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