corebootscreen.c 14 KB

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