devlml.c 7.3 KB

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