vcore.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. /*
  7. * Mailbox interface with videocore gpu
  8. */
  9. #define MAILBOX (VIRTIO+0xB880)
  10. typedef struct Prophdr Prophdr;
  11. typedef struct Fbinfo Fbinfo;
  12. enum {
  13. Read = 0x00>>2,
  14. Write = 0x00>>2,
  15. Peek = 0x10>>2,
  16. Sender = 0x14>>2,
  17. Status = 0x18>>2,
  18. Full = 1<<31,
  19. Empty = 1<<30,
  20. Config = 0x1C>>2,
  21. NRegs = 0x20>>2,
  22. ChanMask = 0xF,
  23. ChanProps = 8,
  24. ChanFb = 1,
  25. Req = 0x0,
  26. RspOk = 0x80000000,
  27. TagResp = 1<<31,
  28. TagGetfwrev = 0x00000001,
  29. TagGetmac = 0x00010003,
  30. TagGetram = 0x00010005,
  31. TagGetpower = 0x00020001,
  32. TagSetpower = 0x00028001,
  33. Powerwait = 1<<1,
  34. TagGetclkspd= 0x00030002,
  35. TagFballoc = 0x00040001,
  36. TagFbfree = 0x00048001,
  37. TagFbblank = 0x00040002,
  38. TagGetres = 0x00040003,
  39. TagSetres = 0x00048003,
  40. TagGetvres = 0x00040004,
  41. TagSetvres = 0x00048004,
  42. TagGetdepth = 0x00040005,
  43. TagSetdepth = 0x00048005,
  44. TagGetrgb = 0x00044006,
  45. TagSetrgb = 0x00048006,
  46. };
  47. struct Fbinfo {
  48. u32int xres;
  49. u32int yres;
  50. u32int xresvirtual;
  51. u32int yresvirtual;
  52. u32int pitch; /* returned by gpu */
  53. u32int bpp;
  54. u32int xoffset;
  55. u32int yoffset;
  56. u32int base; /* returned by gpu */
  57. u32int screensize; /* returned by gpu */
  58. };
  59. struct Prophdr {
  60. u32int len;
  61. u32int req;
  62. u32int tag;
  63. u32int tagbuflen;
  64. u32int taglen;
  65. u32int data[1];
  66. };
  67. static void
  68. vcwrite(uint chan, int val)
  69. {
  70. u32int *r;
  71. r = (u32int*)MAILBOX + NRegs;
  72. val &= ~ChanMask;
  73. while(r[Status]&Full)
  74. ;
  75. coherence();
  76. r[Write] = val | chan;
  77. }
  78. static int
  79. vcread(uint chan)
  80. {
  81. u32int *r;
  82. int x;
  83. r = (u32int*)MAILBOX;
  84. do{
  85. while(r[Status]&Empty)
  86. ;
  87. coherence();
  88. x = r[Read];
  89. }while((x&ChanMask) != chan);
  90. return x & ~ChanMask;
  91. }
  92. /*
  93. * Property interface
  94. */
  95. static int
  96. vcreq(int tag, void *buf, int vallen, int rsplen)
  97. {
  98. uintptr r;
  99. int n;
  100. Prophdr *prop;
  101. static uintptr base = BUSDRAM;
  102. if(rsplen < vallen)
  103. rsplen = vallen;
  104. rsplen = (rsplen+3) & ~3;
  105. prop = (Prophdr*)(VCBUFFER);
  106. n = sizeof(Prophdr) + rsplen + 8;
  107. memset(prop, 0, n);
  108. prop->len = n;
  109. prop->req = Req;
  110. prop->tag = tag;
  111. prop->tagbuflen = rsplen;
  112. prop->taglen = vallen;
  113. if(vallen > 0)
  114. memmove(prop->data, buf, vallen);
  115. cachedwbinvse(prop, prop->len);
  116. for(;;){
  117. vcwrite(ChanProps, PADDR(prop) + base);
  118. r = vcread(ChanProps);
  119. if(r == PADDR(prop) + base)
  120. break;
  121. if(base == 0)
  122. return -1;
  123. base = 0;
  124. }
  125. if(prop->req == RspOk &&
  126. prop->tag == tag &&
  127. (prop->taglen&TagResp)) {
  128. if((n = prop->taglen & ~TagResp) < rsplen)
  129. rsplen = n;
  130. memmove(buf, prop->data, rsplen);
  131. }else
  132. rsplen = -1;
  133. return rsplen;
  134. }
  135. /*
  136. * Framebuffer
  137. */
  138. static int
  139. fbdefault(int *width, int *height, int *depth)
  140. {
  141. u32int buf[3];
  142. if(vcreq(TagGetres, &buf[0], 0, 2*4) != 2*4 ||
  143. vcreq(TagGetdepth, &buf[2], 0, 4) != 4)
  144. return -1;
  145. *width = buf[0];
  146. *height = buf[1];
  147. *depth = buf[2];
  148. return 0;
  149. }
  150. void*
  151. fbinit(int set, int *width, int *height, int *depth)
  152. {
  153. Fbinfo *fi;
  154. uintptr va;
  155. if(!set)
  156. fbdefault(width, height, depth);
  157. /* Screen width must be a multiple of 16 */
  158. *width &= ~0xF;
  159. fi = (Fbinfo*)(VCBUFFER);
  160. memset(fi, 0, sizeof(*fi));
  161. fi->xres = fi->xresvirtual = *width;
  162. fi->yres = fi->yresvirtual = *height;
  163. fi->bpp = *depth;
  164. cachedwbinvse(fi, sizeof(*fi));
  165. vcwrite(ChanFb, DMAADDR(fi));
  166. if(vcread(ChanFb) != 0)
  167. return 0;
  168. va = mmukmap(FRAMEBUFFER, PADDR(fi->base), fi->screensize);
  169. if(va)
  170. memset((char*)va, 0x7F, fi->screensize);
  171. return (void*)va;
  172. }
  173. int
  174. fbblank(int blank)
  175. {
  176. u32int buf[1];
  177. buf[0] = blank;
  178. if(vcreq(TagFbblank, buf, sizeof buf, sizeof buf) != sizeof buf)
  179. return -1;
  180. return buf[0] & 1;
  181. }
  182. /*
  183. * Power management
  184. */
  185. void
  186. setpower(int dev, int on)
  187. {
  188. u32int buf[2];
  189. buf[0] = dev;
  190. buf[1] = Powerwait | (on? 1 : 0);
  191. vcreq(TagSetpower, buf, sizeof buf, sizeof buf);
  192. }
  193. int
  194. getpower(int dev)
  195. {
  196. u32int buf[2];
  197. buf[0] = dev;
  198. buf[1] = 0;
  199. if(vcreq(TagGetpower, buf, sizeof buf[0], sizeof buf) != sizeof buf)
  200. return -1;
  201. return buf[0] & 1;
  202. }
  203. /*
  204. * Get ethernet address (as hex string)
  205. * [not reentrant]
  206. */
  207. char *
  208. getethermac(void)
  209. {
  210. uchar ea[8];
  211. char *p;
  212. int i;
  213. static char buf[16];
  214. memset(ea, 0, sizeof ea);
  215. vcreq(TagGetmac, ea, 0, sizeof ea);
  216. p = buf;
  217. for(i = 0; i < 6; i++)
  218. p += sprint(p, "%.2x", ea[i]);
  219. return buf;
  220. }
  221. /*
  222. * Get firmware revision
  223. */
  224. uint
  225. getfirmware(void)
  226. {
  227. u32int buf[1];
  228. if(vcreq(TagGetfwrev, buf, 0, sizeof buf) != sizeof buf)
  229. return 0;
  230. return buf[0];
  231. }
  232. /*
  233. * Get ARM ram
  234. */
  235. void
  236. getramsize(Confmem *mem)
  237. {
  238. u32int buf[2];
  239. if(vcreq(TagGetram, buf, 0, sizeof buf) != sizeof buf)
  240. return;
  241. mem->base = buf[0];
  242. mem->limit = buf[1];
  243. }
  244. /*
  245. * Get clock rate
  246. */
  247. ulong
  248. getclkrate(int clkid)
  249. {
  250. u32int buf[2];
  251. buf[0] = clkid;
  252. if(vcreq(TagGetclkspd, buf, sizeof(buf[0]), sizeof(buf)) != sizeof buf)
  253. return 0;
  254. return buf[1];
  255. }