cga.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. enum {
  15. Black = 0x00,
  16. Blue = 0x01,
  17. Green = 0x02,
  18. Cyan = 0x03,
  19. Red = 0x04,
  20. Magenta = 0x05,
  21. Brown = 0x06,
  22. Grey = 0x07,
  23. Bright = 0x08,
  24. Blinking = 0x80,
  25. Attr = (Black<<4)|Grey, /* (background<<4)|foreground */
  26. };
  27. enum {
  28. Index = 0x3d4,
  29. Data = Index+1,
  30. Width = 80*2,
  31. Height = 25,
  32. Poststrlen = 0,
  33. Postcodelen = 2,
  34. Postlen = Poststrlen+Postcodelen,
  35. Cgasize = 16384,
  36. };
  37. #define CGA (BIOSSEG(0xb800))
  38. static Lock cgalock;
  39. static int cgapos;
  40. static int cgainitdone;
  41. static int
  42. cgaregr(int index)
  43. {
  44. outb(Index, index);
  45. return inb(Data) & 0xff;
  46. }
  47. static void
  48. cgaregw(int index, int data)
  49. {
  50. outb(Index, index);
  51. outb(Data, data);
  52. }
  53. static void
  54. cgablinkoff(void)
  55. {
  56. cgaregw(0x0a, 1<<5);
  57. }
  58. static void
  59. cgacursor(void)
  60. {
  61. uint8_t *cga;
  62. cgaregw(0x0e, (cgapos/2>>8) & 0xff);
  63. cgaregw(0x0f, cgapos/2 & 0xff);
  64. cga = CGA;
  65. cga[cgapos+1] = Attr;
  66. }
  67. /*
  68. * extern, so we could use it to debug things like
  69. * lock() if necessary.
  70. */
  71. void
  72. cgaputc(int c)
  73. {
  74. int i;
  75. uint8_t *cga, *p;
  76. cga = CGA;
  77. if(c == '\n'){
  78. cgapos = cgapos/Width;
  79. cgapos = (cgapos+1)*Width;
  80. }
  81. else if(c == '\t'){
  82. i = 8 - ((cgapos/2)&7);
  83. while(i-- > 0)
  84. cgaputc(' ');
  85. }
  86. else if(c == '\b'){
  87. if(cgapos >= 2)
  88. cgapos -= 2;
  89. cgaputc(' ');
  90. cgapos -= 2;
  91. }
  92. else{
  93. cga[cgapos++] = c;
  94. cga[cgapos++] = Attr;
  95. }
  96. if(cgapos >= (Width*Height)-Postlen*2){
  97. memmove(cga, &cga[Width], Width*(Height-1));
  98. p = &cga[Width*(Height-1)-Postlen*2];
  99. for(i = 0; i < Width/2; i++){
  100. *p++ = ' ';
  101. *p++ = Attr;
  102. }
  103. cgapos -= Width;
  104. }
  105. cgacursor();
  106. }
  107. int
  108. cgaprint(int off, char *fmt, ...)
  109. {
  110. va_list va;
  111. char buf[128];
  112. uint8_t *cga;
  113. int i, n;
  114. va_start(va, fmt);
  115. n = vsnprint(buf, sizeof buf, fmt, va);
  116. va_end(va);
  117. cga = CGA;
  118. for(i = 0; (2*(i+off))+1 < Cgasize && i < n; i++){
  119. cga[2*(i+off)+0] = buf[i];
  120. cga[2*(i+off)+1] = Attr;
  121. }
  122. return n;
  123. }
  124. int
  125. cgaclearln(int off, int c)
  126. {
  127. uint8_t *cga;
  128. int i;
  129. cga = CGA;
  130. for(i = off; (2*i)+1 < Cgasize && i%80 != 0; i++){
  131. cga[2*i+0] = c;
  132. cga[2*i+1] = Attr;
  133. }
  134. return i-off;
  135. }
  136. /*
  137. * debug
  138. */
  139. void
  140. cgaprinthex(uintptr_t x)
  141. {
  142. char str[30];
  143. char *s;
  144. static char dig[] = "0123456789abcdef";
  145. str[29] = 0;
  146. s = &str[29];
  147. while(x != 0){
  148. *--s = dig[x&0xF];
  149. x >>= 4;
  150. }
  151. while(*s != 0)
  152. cgaputc(*s++);
  153. cgaputc('\n');
  154. }
  155. void
  156. cgaconsputs(char* s, int n)
  157. {
  158. ilock(&cgalock);
  159. while(n-- > 0)
  160. cgaputc(*s++);
  161. iunlock(&cgalock);
  162. }
  163. void
  164. cgapost(int code)
  165. {
  166. uint8_t *cga;
  167. static char hex[] = "0123456789ABCDEF";
  168. cga = CGA;
  169. cga[Width*Height-Postcodelen*2] = hex[(code>>4) & 0x0f];
  170. cga[Width*Height-Postcodelen*2+1] = Attr;
  171. cga[Width*Height-Postcodelen*2+2] = hex[code & 0x0f];
  172. cga[Width*Height-Postcodelen*2+3] = Attr;
  173. }
  174. static int32_t
  175. cgaread(Chan* c, void *vbuf, int32_t len, int64_t off)
  176. {
  177. uint8_t *cga;
  178. extern int panicking;
  179. if(panicking)
  180. error("cgaread: kernel panic");
  181. if(off < 0 || off > Cgasize)
  182. error("cgaread: offset out of bounds");
  183. if(off+len > Cgasize)
  184. len = Cgasize - off;
  185. cga = CGA;
  186. memmove(vbuf, cga + off, len);
  187. return len;
  188. }
  189. static int32_t
  190. cgawrite(Chan* c, void *vbuf, int32_t len, int64_t off)
  191. {
  192. uint8_t *cga;
  193. extern int panicking;
  194. if(panicking)
  195. error("cgawrite: kernel panic");
  196. if(off < 0 || off > Cgasize)
  197. error("cgawrite: offset out of bounds");
  198. if(off+len > Cgasize)
  199. len = Cgasize - off;
  200. cga = CGA;
  201. memmove(cga + off, vbuf, len);
  202. return len;
  203. }
  204. void
  205. cgainit(void)
  206. {
  207. ilock(&cgalock);
  208. cgapos = cgaregr(0x0e)<<8;
  209. cgapos |= cgaregr(0x0f);
  210. cgapos *= 2;
  211. cgablinkoff();
  212. cgainitdone = 1;
  213. iunlock(&cgalock);
  214. addarchfile("cgamem", 0666, cgaread, cgawrite);
  215. }