vga.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "io.h"
  15. #include "../port/error.h"
  16. #define Image IMAGE
  17. #include <draw.h>
  18. #include <memdraw.h>
  19. #include <cursor.h>
  20. #include "screen.h"
  21. static Memimage *back;
  22. static Memimage *conscol;
  23. static Point curpos;
  24. static Rectangle window;
  25. static int *xp;
  26. static int xbuf[256];
  27. Lock vgascreenlock;
  28. int drawdebug;
  29. void
  30. vgaimageinit(u32 chan)
  31. {
  32. if(back == nil){
  33. back = allocmemimage(Rect(0, 0, 1, 1), chan); /* RSC BUG */
  34. if(back == nil)
  35. panic("back alloc"); /* RSC BUG */
  36. back->flags |= Frepl;
  37. back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
  38. memfillcolor(back, DBlack);
  39. }
  40. if(conscol == nil){
  41. conscol = allocmemimage(Rect(0, 0, 1, 1), chan); /* RSC BUG */
  42. if(conscol == nil)
  43. panic("conscol alloc"); /* RSC BUG */
  44. conscol->flags |= Frepl;
  45. conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
  46. memfillcolor(conscol, DWhite);
  47. }
  48. }
  49. static void
  50. vgascroll(VGAscr *scr)
  51. {
  52. int h, o;
  53. Point p;
  54. Rectangle r;
  55. h = scr->memdefont->height;
  56. o = 8 * h;
  57. r = Rpt(window.min, Pt(window.max.x, window.max.y - o));
  58. p = Pt(window.min.x, window.min.y + o);
  59. memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S);
  60. r = Rpt(Pt(window.min.x, window.max.y - o), window.max);
  61. memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S);
  62. curpos.y -= o;
  63. }
  64. static void
  65. vgascreenputc(VGAscr *scr, char *buf, Rectangle *flushr)
  66. {
  67. Point p;
  68. int h, w, pos;
  69. Rectangle r;
  70. // drawdebug = 1;
  71. if(xp < xbuf || xp >= &xbuf[nelem(xbuf) - 1])
  72. xp = xbuf;
  73. h = scr->memdefont->height;
  74. switch(buf[0]){
  75. case '\n':
  76. if(curpos.y + h >= window.max.y){
  77. vgascroll(scr);
  78. *flushr = window;
  79. }
  80. curpos.y += h;
  81. vgascreenputc(scr, "\r", flushr);
  82. break;
  83. case '\r':
  84. xp = xbuf;
  85. curpos.x = window.min.x;
  86. break;
  87. case '\t':
  88. p = memsubfontwidth(scr->memdefont, " ");
  89. w = p.x;
  90. if(curpos.x >= window.max.x - 4 * w)
  91. vgascreenputc(scr, "\n", flushr);
  92. pos = (curpos.x - window.min.x) / w;
  93. pos = 4 - (pos % 4);
  94. *xp++ = curpos.x;
  95. r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
  96. memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
  97. curpos.x += pos * w;
  98. break;
  99. case '\b':
  100. if(xp <= xbuf)
  101. break;
  102. xp--;
  103. r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
  104. memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S);
  105. combinerect(flushr, r);
  106. curpos.x = *xp;
  107. break;
  108. case '\0':
  109. break;
  110. default:
  111. p = memsubfontwidth(scr->memdefont, buf);
  112. w = p.x;
  113. if(curpos.x >= window.max.x - w)
  114. vgascreenputc(scr, "\n", flushr);
  115. *xp++ = curpos.x;
  116. r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
  117. memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
  118. memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf);
  119. combinerect(flushr, r);
  120. curpos.x += w;
  121. }
  122. // drawdebug = 0;
  123. }
  124. static void
  125. vgascreenputs(char *s, int n)
  126. {
  127. int i, gotdraw;
  128. Rune r;
  129. char buf[4];
  130. VGAscr *scr;
  131. Rectangle flushr;
  132. scr = &vgascreen[0];
  133. if(!islo()){
  134. /*
  135. * Don't deadlock trying to
  136. * print in an interrupt.
  137. */
  138. if(!canlock(&vgascreenlock))
  139. return;
  140. } else
  141. lock(&vgascreenlock);
  142. /*
  143. * Be nice to hold this, but not going to deadlock
  144. * waiting for it. Just try and see.
  145. */
  146. gotdraw = canqlock(&drawlock);
  147. flushr = Rect(10000, 10000, -10000, -10000);
  148. while(n > 0){
  149. i = chartorune(&r, s);
  150. if(i == 0){
  151. s++;
  152. --n;
  153. continue;
  154. }
  155. memmove(buf, s, i);
  156. buf[i] = 0;
  157. n -= i;
  158. s += i;
  159. vgascreenputc(scr, buf, &flushr);
  160. }
  161. flushmemscreen(flushr);
  162. if(gotdraw)
  163. qunlock(&drawlock);
  164. unlock(&vgascreenlock);
  165. }
  166. void
  167. vgascreenwin(VGAscr *scr)
  168. {
  169. int h, w;
  170. if(!scr)
  171. error("vgascreenwin: no scr");
  172. if(!scr->memdefont)
  173. error("vgascreenwin: no scr->memdefont");
  174. if(!scr->memdefont->info)
  175. error("vgascreenwin: no memdefont info");
  176. h = scr->memdefont->height;
  177. if(h == 0){
  178. print("vgascreenwin: height is 0");
  179. error("vgascreenwin: height is 0");
  180. }
  181. w = scr->memdefont->info[' '].width;
  182. if(w == 0){
  183. error("vgascreenwin: width is 0");
  184. print("vgascreenwin: width is 0");
  185. }
  186. window = insetrect(scr->gscreen->r, 48);
  187. window.max.x = window.min.x + ((window.max.x - window.min.x) / w) * w;
  188. window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
  189. curpos = window.min;
  190. consputs = vgascreenputs;
  191. }
  192. /*
  193. * Supposedly this is the way to turn DPMS
  194. * monitors off using just the VGA registers.
  195. * Unfortunately, it seems to mess up the video mode
  196. * on the cards I've tried.
  197. */
  198. void
  199. vgablank(VGAscr *scr, int blank)
  200. {
  201. unsigned char seq1, crtc17;
  202. if(blank){
  203. seq1 = 0x00;
  204. crtc17 = 0x80;
  205. } else {
  206. seq1 = 0x20;
  207. crtc17 = 0x00;
  208. }
  209. outs(Seqx, 0x0100); /* synchronous reset */
  210. seq1 |= vgaxi(Seqx, 1) & ~0x20;
  211. vgaxo(Seqx, 1, seq1);
  212. crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
  213. delay(10);
  214. vgaxo(Crtx, 0x17, crtc17);
  215. outs(Crtx, 0x0300); /* end synchronous reset */
  216. }
  217. void
  218. addvgaseg(char *name, u32 pa, u32 size)
  219. {
  220. Physseg seg;
  221. memset(&seg, 0, sizeof seg);
  222. seg.attr = SG_PHYSICAL | SG_READ | SG_WRITE;
  223. seg.name = name;
  224. seg.pa = pa;
  225. seg.size = size;
  226. seg.pgszi = -1; // Default page size
  227. addphysseg(&seg);
  228. }
  229. void
  230. cornerstring(char *s)
  231. {
  232. int h, w;
  233. VGAscr *scr;
  234. Rectangle r;
  235. Point p;
  236. scr = &vgascreen[0];
  237. if(scr->vaddr == nil || consputs != vgascreenputs)
  238. return;
  239. p = memsubfontwidth(scr->memdefont, s);
  240. w = p.x;
  241. h = scr->memdefont->height;
  242. r = Rect(0, 0, w, h);
  243. memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
  244. memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s);
  245. // flushmemscreen(r);
  246. }