corebootscreen.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * Simple coreboot framebuffer screen inspired by the omap code.
  11. * coreboot gives us an x by y screen with 24 bpp, 8 of rgb, always.
  12. * Note that in the coreboot case, this is architecture-independent code.
  13. */
  14. #include "u.h"
  15. #include "../port/lib.h"
  16. #include "mem.h"
  17. #include "dat.h"
  18. #include "fns.h"
  19. #include "io.h"
  20. #include "ureg.h"
  21. #include "../port/error.h"
  22. #define Image IMAGE
  23. #include <draw.h>
  24. #include <memdraw.h>
  25. #include <cursor.h>
  26. #include <coreboot.h>
  27. #include "screen.h"
  28. #include "corebootscreen.h"
  29. enum {
  30. Tabstop = 4, /* should be 8 */
  31. Scroll = 8, /* lines to scroll at one time */
  32. };
  33. extern struct sysinfo_t cbinfo;
  34. int drawdebug = 1;
  35. Point ZP = {0, 0};
  36. Cursor arrow = {
  37. { -1, -1 },
  38. { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
  39. 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
  40. 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
  41. 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
  42. },
  43. { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
  44. 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
  45. 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
  46. 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
  47. },
  48. };
  49. static Memdata xgdata;
  50. static Memimage xgscreen =
  51. {
  52. { 0, 0, 1024, 768 }, /* r */
  53. { 0, 0, 1024, 768 }, /* clipr */
  54. 24, /* depth */
  55. 3, /* nchan */
  56. RGB24, /* chan */
  57. nil, /* cmap */
  58. &xgdata, /* data */
  59. 0, /* zero */
  60. 1024*768, /* width in words of a single scan line */
  61. 0, /* layer */
  62. 0, /* flags */
  63. };
  64. Memimage *gscreen;
  65. static CorebootScreen Cbscreen;
  66. static Memimage *conscol;
  67. static Memimage *back;
  68. static Corebootfb framebuf;
  69. static Memsubfont *memdefont;
  70. //static Lock screenlock;
  71. static Point curpos;
  72. static int h, w;
  73. static int landscape = 0; /* screen orientation, default is 0: portrait */
  74. //static uint32_t *vscreen; /* virtual screen */
  75. static Rectangle window;
  76. static struct VGAdev cbvgadev = {
  77. .name = "coreboot",
  78. /*
  79. void (*enable)(VGAscr*);
  80. void (*disable)(VGAscr*);
  81. void (*page)(VGAscr*, int);
  82. void (*linear)(VGAscr*, int, int);
  83. void (*drawinit)(VGAscr*);
  84. int (*fill)(VGAscr*, Rectangle, uint32_t);
  85. void (*ovlctl)(VGAscr*, Chan*, void*, int);
  86. int (*ovlwrite)(VGAscr*, void*, int, int64_t);
  87. void (*flush)(VGAscr*, Rectangle);
  88. */
  89. };
  90. struct VGAcur cbvgacur = {
  91. "coreboot",
  92. /*
  93. void (*enable)(VGAscr*);
  94. void (*disable)(VGAscr*);
  95. void (*load)(VGAscr*, Cursor*);
  96. int (*move)(VGAscr*, Point);
  97. int doespanning;
  98. */
  99. };
  100. static int scroll(VGAscr*, Rectangle, Rectangle);
  101. // for devdraw
  102. VGAscr vgascreen[1] = {
  103. {
  104. .dev = &cbvgadev,
  105. .cur = &cbvgacur,
  106. .gscreen = &xgscreen,
  107. // .memdefont = memdefont,
  108. .scroll = scroll,
  109. },
  110. };
  111. //static void corebootscreenputs(char *s, int n);
  112. //static uint32_t rep(uint32_t, int);
  113. //static void screenputc(char *buf);
  114. static void screenwin(void);
  115. /*
  116. * Software cursor.
  117. */
  118. int swvisible; /* is the cursor visible? */
  119. int swenabled; /* is the cursor supposed to be on the screen? */
  120. Memimage* swback; /* screen under cursor */
  121. Memimage* swimg; /* cursor image */
  122. Memimage* swmask; /* cursor mask */
  123. Memimage* swimg1;
  124. Memimage* swmask1;
  125. Point swoffset;
  126. Rectangle swrect; /* screen rectangle in swback */
  127. Point swpt; /* desired cursor location */
  128. Point swvispt; /* actual cursor location */
  129. int swvers; /* incremented each time cursor image changes */
  130. int swvisvers; /* the version on the screen */
  131. static void
  132. lcdoff(void)
  133. {
  134. print("LCD OFF\n");
  135. delay(20); /* worst case for 1 frame, 50Hz */
  136. }
  137. static void
  138. lcdon(int enable)
  139. {
  140. print("%s\n", __func__);
  141. print("LCD ON\n");
  142. delay(10);
  143. }
  144. static void
  145. lcdstop(void)
  146. {
  147. print("%s\n", __func__);
  148. lcdoff();
  149. print("lcdstop\n");
  150. }
  151. static void
  152. lcdinit(void)
  153. {
  154. print("%s\n", __func__);
  155. print("lcdinit\n");
  156. lcdstop();
  157. }
  158. /* Paint the image data with blue pixels */
  159. void
  160. screentest(void)
  161. {
  162. int i;
  163. print("%s\n", __func__);
  164. for (i = sizeof(framebuf.pixel)/sizeof(framebuf.pixel[0]) - 1; i >= 0; i--)
  165. framebuf.pixel[i] = 0x1f; /* blue */
  166. // memset(framebuf.pixel, ~0, sizeof framebuf.pixel); /* white */
  167. }
  168. void
  169. screenpower(int on)
  170. {
  171. print("%s\n", __func__);
  172. blankscreen(on == 0);
  173. }
  174. /*
  175. * called with drawlock locked for us, most of the time.
  176. * kernel prints at inopportune times might mean we don't
  177. * hold the lock, but memimagedraw is now reentrant so
  178. * that should be okay: worst case we get cursor droppings.
  179. */
  180. void
  181. swcursorhide(void)
  182. {
  183. print("%s\n", __func__);
  184. if(swvisible == 0)
  185. return;
  186. if(swback == nil)
  187. return;
  188. swvisible = 0;
  189. memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
  190. flushmemscreen(swrect);
  191. }
  192. void
  193. swcursoravoid(Rectangle r)
  194. {
  195. print("%s\n", __func__);
  196. if(swvisible && rectXrect(r, swrect))
  197. swcursorhide();
  198. }
  199. void
  200. swcursordraw(void)
  201. {
  202. print("%s\n", __func__);
  203. if(swvisible)
  204. return;
  205. if(swenabled == 0)
  206. return;
  207. if(swback == nil || swimg1 == nil || swmask1 == nil)
  208. return;
  209. // assert(!canqlock(&drawlock)); // assertion fails on omap
  210. swvispt = swpt;
  211. swvisvers = swvers;
  212. swrect = rectaddpt(Rect(0,0,16,16), swvispt);
  213. memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
  214. memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
  215. flushmemscreen(swrect);
  216. swvisible = 1;
  217. }
  218. int
  219. cursoron(int dolock)
  220. {
  221. print("%s\n", __func__);
  222. if (dolock)
  223. lock(&Cbscreen.l);
  224. cursoroff(0);
  225. swcursordraw();
  226. if (dolock)
  227. unlock(&Cbscreen.l);
  228. return 0;
  229. }
  230. void
  231. cursoroff(int dolock)
  232. {
  233. if (dolock)
  234. lock(&Cbscreen.l);
  235. swcursorhide();
  236. if (dolock)
  237. unlock(&Cbscreen.l);
  238. }
  239. void
  240. swload(Cursor *curs)
  241. {
  242. print("%s\n", __func__);
  243. uint8_t *ip, *mp;
  244. int i, j, set, clr;
  245. if(!swimg || !swmask || !swimg1 || !swmask1)
  246. return;
  247. /*
  248. * Build cursor image and mask.
  249. * Image is just the usual cursor image
  250. * but mask is a transparent alpha mask.
  251. *
  252. * The 16x16x8 memimages do not have
  253. * padding at the end of their scan lines.
  254. */
  255. ip = byteaddr(swimg, ZP);
  256. mp = byteaddr(swmask, ZP);
  257. for(i=0; i<32; i++){
  258. set = curs->set[i];
  259. clr = curs->clr[i];
  260. for(j=0x80; j; j>>=1){
  261. *ip++ = set&j ? 0x00 : 0xFF;
  262. *mp++ = (clr|set)&j ? 0xFF : 0x00;
  263. }
  264. }
  265. swoffset = curs->offset;
  266. swvers++;
  267. memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
  268. memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
  269. }
  270. /* called from devmouse */
  271. void
  272. setcursor(Cursor* curs)
  273. {
  274. print("%s\n", __func__);
  275. cursoroff(1);
  276. Cbscreen.Cursor = *curs;
  277. swload(curs);
  278. cursoron(1);
  279. }
  280. int
  281. swmove(Point p)
  282. {
  283. print("%s\n", __func__);
  284. swpt = addpt(p, swoffset);
  285. return 0;
  286. }
  287. void
  288. swcursorclock(void)
  289. {
  290. print("%s\n", __func__);
  291. int x;
  292. if(!swenabled)
  293. return;
  294. swmove(mousexy());
  295. if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)
  296. return;
  297. x = splhi();
  298. if(swenabled)
  299. if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)
  300. if(canqlock(&drawlock)){
  301. swcursorhide();
  302. swcursordraw();
  303. qunlock(&drawlock);
  304. }
  305. splx(x);
  306. }
  307. void
  308. swcursorinit(void)
  309. {
  310. print("%s\n", __func__);
  311. static int init;
  312. if(!init){
  313. init = 1;
  314. addclock0link(swcursorclock, 10);
  315. }
  316. if(swback){
  317. freememimage(swback);
  318. freememimage(swmask);
  319. freememimage(swmask1);
  320. freememimage(swimg);
  321. freememimage(swimg1);
  322. }
  323. swback = allocmemimage(Rect(0,0,32,32), gscreen->chan);
  324. swmask = allocmemimage(Rect(0,0,16,16), GREY8);
  325. swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
  326. swimg = allocmemimage(Rect(0,0,16,16), GREY8);
  327. swimg1 = allocmemimage(Rect(0,0,16,16), GREY1);
  328. if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){
  329. print("software cursor: allocmemimage fails\n");
  330. return;
  331. }
  332. memfillcolor(swmask, DOpaque);
  333. memfillcolor(swmask1, DOpaque);
  334. memfillcolor(swimg, DBlack);
  335. memfillcolor(swimg1, DBlack);
  336. }
  337. int
  338. screeninit(void)
  339. {
  340. print("%s\n", __func__);
  341. static int first = 1;
  342. struct cb_framebuffer *fb;
  343. print("%s: fb is %p\n", __func__, cbinfo.framebuffer);
  344. if (!cbinfo.framebuffer)
  345. return -1;
  346. fb = KADDR((uintptr_t)cbinfo.framebuffer);
  347. framebuf.pixel = KADDR(fb->physical_address);
  348. /* should not happen but ...*/
  349. if (!framebuf.pixel)
  350. return -1;
  351. print("%s: pixels are %p\n", __func__, fb->physical_address);
  352. if (first) {
  353. iprint("screeninit...");
  354. lcdstop();
  355. }
  356. lcdinit();
  357. lcdon(1);
  358. if (first) {
  359. memimageinit();
  360. memdefont = getmemdefont();
  361. screentest();
  362. }
  363. xgdata.ref = 1;
  364. xgdata.bdata = (uint8_t *)framebuf.pixel;
  365. gscreen = &xgscreen;
  366. gscreen->r = Rect(0, 0, Wid, Ht);
  367. gscreen->clipr = gscreen->r;
  368. /* width, in words, of a single scan line */
  369. gscreen->width = Wid * (Depth / BI2BY) / BY2WD;
  370. flushmemscreen(gscreen->r);
  371. blanktime = 3; /* minutes */
  372. if (first) {
  373. iprint("on: blue for 3 seconds...");
  374. delay(3*1000);
  375. iprint("\n");
  376. screenwin(); /* draw border & top orange bar */
  377. // ? screenputs = corebootcreenputs;
  378. iprint("screen: frame buffer at %#p for %dx%d\n",
  379. framebuf.pixel, Cbscreen.wid, Cbscreen.ht);
  380. swenabled = 1;
  381. swcursorinit(); /* needs gscreen set */
  382. setcursor(&arrow);
  383. first = 0;
  384. }
  385. return 0;
  386. }
  387. /* flushmemscreen should change buffer? */
  388. void
  389. flushmemscreen(Rectangle r)
  390. {
  391. print("%s\n", __func__);
  392. uintptr_t start, end;
  393. if (r.min.x < 0)
  394. r.min.x = 0;
  395. if (r.max.x > Wid)
  396. r.max.x = Wid;
  397. if (r.min.y < 0)
  398. r.min.y = 0;
  399. if (r.max.y > Ht)
  400. r.max.y = Ht;
  401. if (rectclip(&r, gscreen->r) == 0)
  402. return;
  403. start = (uintptr_t)&framebuf.pixel[r.min.y*Wid + r.min.x];
  404. end = (uintptr_t)&framebuf.pixel[(r.max.y - 1)*Wid + r.max.x -1];
  405. print("Flushmemscreen %p %p\n", start, end);
  406. // for now. Don't think we need it. cachedwbse((uint32_t *)start, end - start);
  407. coherence();
  408. }
  409. /*
  410. * export screen to devdraw
  411. */
  412. uint8_t*
  413. attachscreen(Rectangle *r, uint32_t *chan, int *d, int *width, int *softscreen)
  414. {
  415. print("%s\n", __func__);
  416. if (screeninit() < 0)
  417. return nil;
  418. *r = gscreen->r;
  419. *d = gscreen->depth;
  420. *chan = gscreen->chan;
  421. *width = gscreen->width;
  422. *softscreen = (landscape == 0);
  423. return (uint8_t *)gscreen->data->bdata;
  424. }
  425. void
  426. getcolor(uint32_t p, uint32_t *pr, uint32_t *pg, uint32_t *pb)
  427. {
  428. print("%s\n", __func__);
  429. //USED(p, pr, pg, pb);
  430. }
  431. int
  432. setcolor(uint32_t p, uint32_t r, uint32_t g, uint32_t b)
  433. {
  434. print("%s\n", __func__);
  435. //USED(p, r, g, b);
  436. return 0;
  437. }
  438. void
  439. blankscreen(int blank)
  440. {
  441. print("%s\n", __func__);
  442. if (blank)
  443. lcdon(0);
  444. else {
  445. lcdinit();
  446. lcdon(1);
  447. }
  448. }
  449. /* Not sure if we ever need this ... */
  450. #if 0
  451. void
  452. corebootscreenputs(char *s, int n)
  453. {
  454. print("%s\n", __func__);
  455. int i;
  456. Rune r;
  457. char buf[4];
  458. if (!islo()) {
  459. /* don't deadlock trying to print in interrupt */
  460. if (!canlock(&screenlock))
  461. return; /* discard s */
  462. } else
  463. lock(&screenlock);
  464. while (n > 0) {
  465. i = chartorune(&r, s);
  466. if (i == 0) {
  467. s++;
  468. --n;
  469. continue;
  470. }
  471. memmove(buf, s, i);
  472. buf[i] = 0;
  473. n -= i;
  474. s += i;
  475. screenputc(buf);
  476. }
  477. unlock(&screenlock);
  478. }
  479. #endif
  480. static void
  481. screenwin(void)
  482. {
  483. print("%s\n", __func__);
  484. char *greet;
  485. Memimage *orange;
  486. Point p; //, q;
  487. Rectangle r;
  488. memsetchan(gscreen, RGB16);
  489. back = memwhite;
  490. conscol = memblack;
  491. orange = allocmemimage(Rect(0, 0, 1, 1), RGB16);
  492. orange->flags |= Frepl;
  493. orange->clipr = gscreen->r;
  494. orange->data->bdata[0] = 0x40; /* magic: colour? */
  495. orange->data->bdata[1] = 0xfd; /* magic: colour? */
  496. w = memdefont->info[' '].width;
  497. h = memdefont->height;
  498. r = insetrect(gscreen->r, 4);
  499. memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
  500. window = insetrect(r, 4);
  501. memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
  502. memimagedraw(gscreen, Rect(window.min.x, window.min.y,
  503. window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S);
  504. freememimage(orange);
  505. window = insetrect(window, 5);
  506. greet = " Plan 9 Console ";
  507. p = addpt(window.min, Pt(10, 0));
  508. //q = memsubfontwidth(memdefont, greet);
  509. memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
  510. flushmemscreen(r);
  511. window.min.y += h + 6;
  512. curpos = window.min;
  513. window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
  514. }
  515. static int
  516. scroll(VGAscr* _1, Rectangle _2, Rectangle _3)
  517. {
  518. print("%s\n", __func__);
  519. int o;
  520. Point p;
  521. Rectangle r;
  522. /* move window contents up Scroll text lines */
  523. o = Scroll * h;
  524. r = Rpt(window.min, Pt(window.max.x, window.max.y - o));
  525. p = Pt(window.min.x, window.min.y + o);
  526. memimagedraw(gscreen, r, gscreen, p, nil, p, S);
  527. flushmemscreen(r);
  528. /* clear the bottom Scroll text lines */
  529. r = Rpt(Pt(window.min.x, window.max.y - o), window.max);
  530. memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
  531. flushmemscreen(r);
  532. curpos.y -= o;
  533. return 0;
  534. }
  535. #if 0
  536. void
  537. screenputc(char *buf)
  538. {
  539. print("%s\n", __func__);
  540. int w;
  541. uint pos;
  542. Point p;
  543. Rectangle r;
  544. static int *xp;
  545. static int xbuf[256];
  546. if (xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
  547. xp = xbuf;
  548. switch (buf[0]) {
  549. case '\n':
  550. if (curpos.y + h >= window.max.y)
  551. scroll();
  552. curpos.y += h;
  553. screenputc("\r");
  554. break;
  555. case '\r':
  556. xp = xbuf;
  557. curpos.x = window.min.x;
  558. break;
  559. case '\t':
  560. p = memsubfontwidth(memdefont, " ");
  561. w = p.x;
  562. if (curpos.x >= window.max.x - Tabstop * w)
  563. screenputc("\n");
  564. pos = (curpos.x - window.min.x) / w;
  565. pos = Tabstop - pos % Tabstop;
  566. *xp++ = curpos.x;
  567. r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
  568. memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
  569. flushmemscreen(r);
  570. curpos.x += pos * w;
  571. break;
  572. case '\b':
  573. if (xp <= xbuf)
  574. break;
  575. xp--;
  576. r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
  577. memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
  578. flushmemscreen(r);
  579. curpos.x = *xp;
  580. break;
  581. case '\0':
  582. break;
  583. default:
  584. p = memsubfontwidth(memdefont, buf);
  585. w = p.x;
  586. if (curpos.x >= window.max.x - w)
  587. screenputc("\n");
  588. *xp++ = curpos.x;
  589. r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
  590. memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
  591. memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
  592. flushmemscreen(r);
  593. curpos.x += w;
  594. }
  595. }
  596. #endif