devlml.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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. ISAConf isa;
  110. char name[32];
  111. Pcidev *pcidev;
  112. LML *lml;
  113. pcidev = nil;
  114. for (nlml = 0; nlml < NLML && (pcidev = pcimatch(pcidev, VENDOR_ZORAN, ZORAN_36067)); nlml++){
  115. if(isaconfig("lml", nlml, &isa) == 0) {
  116. if (debug) print("lml %d not in plan9.ini\n", nlml);
  117. break;
  118. }
  119. lml = &lmls[nlml];
  120. lml->pcidev = pcidev;
  121. lml->codedata = (CodeData*)(((ulong)xalloc(Codedatasize+ BY2PG) + BY2PG-1) & ~(BY2PG-1));
  122. if (lml->codedata == nil) {
  123. print("devlml: xalloc(%ux, %ux, 0)\n", Codedatasize, BY2PG);
  124. return;
  125. }
  126. print("Installing Motion JPEG driver %s, irq %d\n", MJPG_VERSION, pcidev->intl);
  127. print("MJPG buffer at 0x%.8lux, size 0x%.8ux\n", lml->codedata, Codedatasize);
  128. // Get access to DMA memory buffer
  129. lml->codedata->pamjpg = PADDR(lml->codedata->statCom);
  130. prepbuf(lml);
  131. print("zr36067 found at 0x%.8lux", pcidev->mem[0].bar & ~0x0F);
  132. regpa = upamalloc(pcidev->mem[0].bar & ~0x0F, pcidev->mem[0].size, 0);
  133. if (regpa == 0) {
  134. print("lml: failed to map registers\n");
  135. return;
  136. }
  137. lml->pciBaseAddr = (ulong)KADDR(regpa);
  138. print(", mapped at 0x%.8lux\n", lml->pciBaseAddr);
  139. memset(&segbuf, 0, sizeof(segbuf));
  140. segbuf.attr = SG_PHYSICAL;
  141. sprint(name, "lml%d.mjpg", nlml);
  142. kstrdup(&segbuf.name, name);
  143. segbuf.pa = PADDR(lml->codedata);
  144. segbuf.size = Codedatasize;
  145. if (addphysseg(&segbuf) == -1) {
  146. print("lml: physsegment: %s\n", name);
  147. return;
  148. }
  149. memset(&segbuf, 0, sizeof(segbuf));
  150. segbuf.attr = SG_PHYSICAL;
  151. sprint(name, "lml%d.regs", nlml);
  152. kstrdup(&segbuf.name, name);
  153. segbuf.pa = (ulong)regpa;
  154. segbuf.size = pcidev->mem[0].size;
  155. if (addphysseg(&segbuf) == -1) {
  156. print("lml: physsegment: %s\n", name);
  157. return;
  158. }
  159. // Interrupt handler
  160. intrenable(pcidev->intl, lmlintr, lml, pcidev->tbdf, "lml");
  161. }
  162. return;
  163. }
  164. static Chan*
  165. lmlattach(char *spec)
  166. {
  167. return devattach('V', spec);
  168. }
  169. static Walkqid*
  170. lmlwalk(Chan *c, Chan *nc, char **name, int nname)
  171. {
  172. return devwalk(c, nc, name, nname, lmldir, nelem(lmldir), devgen);
  173. }
  174. static int
  175. lmlstat(Chan *c, uchar *db, int n)
  176. {
  177. return devstat(c, db, n, lmldir, nelem(lmldir), devgen);
  178. }
  179. static Chan*
  180. lmlopen(Chan *c, int omode) {
  181. int i;
  182. LML *lml;
  183. if (omode != OREAD)
  184. error(Eperm);
  185. c->aux = 0;
  186. i = 0;
  187. switch((ulong)c->qid.path){
  188. case Qctl1:
  189. i++;
  190. case Qctl0:
  191. if (i >= nlml)
  192. error(Eio);
  193. break;
  194. case Qjpg1:
  195. case Qraw1:
  196. i++;
  197. case Qjpg0:
  198. case Qraw0:
  199. // allow one open
  200. if (i >= nlml)
  201. error(Eio);
  202. lml = lmls+i;
  203. if (lml->jpgopens)
  204. error(Einuse);
  205. lml->jpgopens = 1;
  206. lml->jpgframeno = 0;
  207. prepbuf(lml);
  208. break;
  209. }
  210. return devopen(c, omode, lmldir, nelem(lmldir), devgen);
  211. }
  212. static void
  213. lmlclose(Chan *c) {
  214. int i;
  215. i = 0;
  216. switch((ulong)c->qid.path){
  217. case Qjpg1:
  218. case Qraw1:
  219. i++;
  220. case Qjpg0:
  221. case Qraw0:
  222. lmls[i].jpgopens = 0;
  223. break;
  224. }
  225. }
  226. static long
  227. lmlread(Chan *c, void *va, long n, vlong voff) {
  228. int i;
  229. uchar *buf = va;
  230. long off = voff;
  231. LML *lml;
  232. static char lmlinfo[1024];
  233. int len;
  234. i = 0;
  235. switch((ulong)c->qid.path){
  236. case Qdir:
  237. return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen);
  238. case Qctl1:
  239. i++;
  240. case Qctl0:
  241. if (i >= nlml)
  242. error(Eio);
  243. lml = lmls+i;
  244. len = snprint(lmlinfo, sizeof lmlinfo, "lml%djpg lml%draw\nlml%d.regs 0x%lux 0x%ux\nlml%d.mjpg 0x%lux 0x%ux\n",
  245. i, i,
  246. i, lml->pcidev->mem[0].bar & ~0x0F, lml->pcidev->mem[0].size,
  247. i, PADDR(lml->codedata), Codedatasize);
  248. if (voff > len)
  249. return 0;
  250. if (n > len - voff)
  251. n = len - voff;
  252. memmove(va, lmlinfo+voff, n);
  253. return n;
  254. case Qjpg1:
  255. i++;
  256. case Qjpg0:
  257. if (i >= nlml)
  258. error(Eio);
  259. return jpgread(lmls+i, buf, n, off, 1);
  260. case Qraw1:
  261. i++;
  262. case Qraw0:
  263. if (i >= nlml)
  264. error(Eio);
  265. return jpgread(lmls+i, buf, n, off, 0);
  266. }
  267. }
  268. static long
  269. lmlwrite(Chan *, void *, long, vlong) {
  270. error(Eperm);
  271. return 0;
  272. }
  273. Dev lmldevtab = {
  274. 'V',
  275. "video",
  276. lmlreset,
  277. devinit,
  278. devshutdown,
  279. lmlattach,
  280. lmlwalk,
  281. lmlstat,
  282. lmlopen,
  283. devcreate,
  284. lmlclose,
  285. lmlread,
  286. devbread,
  287. lmlwrite,
  288. devbwrite,
  289. devremove,
  290. devwstat,
  291. };
  292. static void
  293. lmlintr(Ureg *, void *x) {
  294. FrameHeader *jpgheader;
  295. ulong fstart, fno, flags, statcom;
  296. LML *lml;
  297. lml = x;
  298. flags = readl(lml->pciBaseAddr+INTR_STAT);
  299. // Reset all interrupts from 067
  300. writel(0xff000000, lml->pciBaseAddr + INTR_STAT);
  301. if(flags & INTR_JPEGREP) {
  302. if(debug&(DBGINTR))
  303. print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags);
  304. fstart = lml->jpgframeno & 0x00000003;
  305. for (;;) {
  306. lml->jpgframeno++;
  307. fno = lml->jpgframeno & 0x00000003;
  308. if (lml->codedata->statCom[fno] & STAT_BIT)
  309. break;
  310. if (fno == fstart) {
  311. if (debug & DBGINTR)
  312. print("Spurious lml jpg intr?\n");
  313. return;
  314. }
  315. }
  316. statcom = lml->codedata->statCom[fno];
  317. jpgheader = (FrameHeader *)(lml->codedata->frag[fno].hdr+2);
  318. jpgheader->frameNo = lml->jpgframeno;
  319. jpgheader->ftime = todget(nil);
  320. jpgheader->frameSize = (statcom & 0x00ffffff) >> 1;
  321. jpgheader->frameSeqNo = statcom >> 24;
  322. wakeup(&lml->sleepjpg);
  323. }
  324. return;
  325. }