vga.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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(uint32_t 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[sizeof(xbuf)])
  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. }
  141. else
  142. lock(&vgascreenlock);
  143. /*
  144. * Be nice to hold this, but not going to deadlock
  145. * waiting for it. Just try and see.
  146. */
  147. gotdraw = canqlock(&drawlock);
  148. flushr = Rect(10000, 10000, -10000, -10000);
  149. while(n > 0){
  150. i = chartorune(&r, s);
  151. if(i == 0){
  152. s++;
  153. --n;
  154. continue;
  155. }
  156. memmove(buf, s, i);
  157. buf[i] = 0;
  158. n -= i;
  159. s += i;
  160. vgascreenputc(scr, buf, &flushr);
  161. }
  162. flushmemscreen(flushr);
  163. if(gotdraw)
  164. qunlock(&drawlock);
  165. unlock(&vgascreenlock);
  166. }
  167. void
  168. vgascreenwin(VGAscr* scr)
  169. {
  170. int h, w;
  171. h = scr->memdefont->height;
  172. w = scr->memdefont->info[' '].width;
  173. window = insetrect(scr->gscreen->r, 48);
  174. window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w;
  175. window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
  176. curpos = window.min;
  177. consputs = vgascreenputs;
  178. }
  179. /*
  180. * Supposedly this is the way to turn DPMS
  181. * monitors off using just the VGA registers.
  182. * Unfortunately, it seems to mess up the video mode
  183. * on the cards I've tried.
  184. */
  185. void
  186. vgablank(VGAscr *scr, int blank)
  187. {
  188. unsigned char seq1, crtc17;
  189. if(blank) {
  190. seq1 = 0x00;
  191. crtc17 = 0x80;
  192. } else {
  193. seq1 = 0x20;
  194. crtc17 = 0x00;
  195. }
  196. outs(Seqx, 0x0100); /* synchronous reset */
  197. seq1 |= vgaxi(Seqx, 1) & ~0x20;
  198. vgaxo(Seqx, 1, seq1);
  199. crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
  200. delay(10);
  201. vgaxo(Crtx, 0x17, crtc17);
  202. outs(Crtx, 0x0300); /* end synchronous reset */
  203. }
  204. void
  205. addvgaseg(char *name, uint32_t pa, uint32_t size)
  206. {
  207. Physseg seg;
  208. memset(&seg, 0, sizeof seg);
  209. seg.attr = SG_PHYSICAL;
  210. seg.name = name;
  211. seg.pa = pa;
  212. seg.size = size;
  213. addphysseg(&seg);
  214. }
  215. void
  216. cornerstring(char *s)
  217. {
  218. int h, w;
  219. VGAscr *scr;
  220. Rectangle r;
  221. Point p;
  222. scr = &vgascreen[0];
  223. if(scr->vaddr == nil || consputs != vgascreenputs)
  224. return;
  225. p = memsubfontwidth(scr->memdefont, s);
  226. w = p.x;
  227. h = scr->memdefont->height;
  228. r = Rect(0, 0, w, h);
  229. memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
  230. memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s);
  231. // flushmemscreen(r);
  232. }