devlml.c 7.5 KB

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