console.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /*****************************************************************
  2. * console.c
  3. * adapted from MIT xv6 by Zhiyi Huang, [email protected]
  4. * University of Otago
  5. *
  6. ********************************************************************/
  7. #include "types.h"
  8. #include "defs.h"
  9. #include "param.h"
  10. #include "traps.h"
  11. #include "spinlock.h"
  12. #include "fs.h"
  13. #include "file.h"
  14. #include "memlayout.h"
  15. #include "mmu.h"
  16. #include "proc.h"
  17. #include "arm.h"
  18. #define BACKSPACE 0x100
  19. static int panicked = 0;
  20. static struct {
  21. struct spinlock lock;
  22. int locking;
  23. } cons;
  24. uint cursor_x=0, cursor_y=0;
  25. uint frameheight=768, framewidth=1024, framecolors=16;
  26. uint fontheight=16, fontwidth=8;
  27. FBI fbinfo __attribute__ ((aligned (16), nocommon));
  28. extern u8 font[];
  29. static uint gpucolour=0xffff;
  30. void setgpucolour(u16 c)
  31. {
  32. gpucolour = c;
  33. }
  34. uint initframebuf(uint width, uint height, uint depth)
  35. {
  36. fbinfo.width = width;
  37. fbinfo.height = height;
  38. fbinfo.v_width = width;
  39. fbinfo.v_height = height;
  40. fbinfo.pitch = 0;
  41. fbinfo.depth = depth;
  42. fbinfo.x = 0;
  43. fbinfo.y = 0;
  44. fbinfo.fbp = 0;
  45. fbinfo.fbs = 0;
  46. writemailbox((uint *)&fbinfo, 1);
  47. return readmailbox(1);
  48. }
  49. #define INPUT_BUF 128
  50. struct {
  51. struct spinlock lock;
  52. char buf[INPUT_BUF];
  53. uint r; // Read index
  54. uint w; // Write index
  55. uint e; // Edit index
  56. } input;
  57. int
  58. consolewrite(struct inode *ip, char *buf, int n)
  59. {
  60. int i;
  61. // cprintf("consolewrite is called: ip=%x buf=%x, n=%x", ip, buf, n);
  62. iunlock(ip);
  63. acquire(&cons.lock);
  64. for(i = 0; i < n; i++){
  65. gpuputc(buf[i] & 0xff);
  66. uartputc(buf[i] & 0xff);
  67. }
  68. release(&cons.lock);
  69. ilock(ip);
  70. return n;
  71. }
  72. void drawpixel(uint x, uint y)
  73. {
  74. u16 *addr;
  75. if(x >= framewidth || y >= frameheight) return;
  76. addr = (u16 *) fbinfo.fbp;
  77. // addr = (u16 *) ((FBI *)FrameBufferInfo)->fbp;
  78. addr += y*1024 + x;
  79. *addr = gpucolour;
  80. return;
  81. }
  82. void drawcursor(uint x, uint y)
  83. {
  84. u8 row, bit;
  85. for(row=0; row<15; row++)
  86. for(bit=0; bit<8; bit++)
  87. drawpixel(x+bit, y+row);
  88. }
  89. void drawcharacter(u8 c, uint x, uint y)
  90. {
  91. u8 *faddr;
  92. u8 row, bit, bits;
  93. uint tv;
  94. if(c > 127) return;
  95. tv = ((uint)c) << 4;
  96. faddr = font + tv;
  97. for(row=0; row<15; row++){
  98. bits = *(faddr+row);
  99. for(bit=0; bit<8; bit++){
  100. if((bits>>bit) & 1) drawpixel(x+bit, y+row);
  101. }
  102. }
  103. }
  104. //static void
  105. void
  106. gpuputc(uint c)
  107. {
  108. if(c=='\n'){
  109. cursor_x = 0;
  110. cursor_y += fontheight;
  111. if(cursor_y >= frameheight) {
  112. memmove((u8 *)fbinfo.fbp, (u8 *)fbinfo.fbp+framewidth*fontheight*2, (frameheight - fontheight)*framewidth*2);
  113. cursor_y = frameheight - fontheight;
  114. setgpucolour(0);
  115. while(cursor_x < framewidth) {
  116. drawcursor(cursor_x, cursor_y);
  117. cursor_x = cursor_x + fontwidth;
  118. }
  119. setgpucolour(0xffff);
  120. cursor_x = 0;
  121. }
  122. } else if(c == BACKSPACE) {
  123. if (cursor_x > 0) {
  124. cursor_x -= fontwidth;
  125. setgpucolour(0);
  126. drawcursor(cursor_x, cursor_y);
  127. setgpucolour(0xffff);
  128. }
  129. } else {
  130. setgpucolour(0);
  131. drawcursor(cursor_x, cursor_y);
  132. setgpucolour(0xffff);
  133. if(c!=' ') drawcharacter(c, cursor_x, cursor_y);
  134. cursor_x = cursor_x + fontwidth;
  135. if(cursor_x >= framewidth) {
  136. cursor_x = 0;
  137. cursor_y += fontheight;
  138. if(cursor_y >= frameheight) {
  139. memmove((u8 *)fbinfo.fbp, (u8 *)fbinfo.fbp+framewidth*fontheight*2, (frameheight - fontheight)*framewidth*2);
  140. cursor_y = frameheight - fontheight;
  141. setgpucolour(0);
  142. while(cursor_x < framewidth) {
  143. drawcursor(cursor_x, cursor_y);
  144. cursor_x = cursor_x + fontwidth;
  145. }
  146. setgpucolour(0xffff);
  147. cursor_x = 0;
  148. }
  149. }
  150. }
  151. }
  152. static void
  153. printint(int xx, int base, int sign)
  154. {
  155. static u8 digits[] = "0123456789abcdef";
  156. u8 buf[16];
  157. int i;
  158. uint x, y, b;
  159. if(sign && (sign = xx < 0))
  160. x = -xx;
  161. else
  162. x = xx;
  163. b = base;
  164. i = 0;
  165. do{
  166. y = div(x, b);
  167. buf[i++] = digits[x - y * b];
  168. }while((x = y) != 0);
  169. if(sign)
  170. buf[i++] = '-';
  171. while(--i >= 0){
  172. gpuputc(buf[i]);
  173. uartputc(buf[i]);
  174. }
  175. }
  176. // Print to the console. only understands %d, %x, %p, %s.
  177. void
  178. cprintf(char *fmt, ...)
  179. {
  180. int i, c;
  181. int locking;
  182. uint *argp;
  183. char *s;
  184. locking = cons.locking;
  185. if(locking)
  186. acquire(&cons.lock);
  187. if (fmt == 0)
  188. panic("null fmt");
  189. argp = (uint *)(void*)(&fmt + 1);
  190. for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
  191. if(c != '%'){
  192. gpuputc(c);
  193. uartputc(c);
  194. continue;
  195. }
  196. c = fmt[++i] & 0xff;
  197. if(c == 0)
  198. break;
  199. switch(c){
  200. case 'd':
  201. printint(*argp++, 10, 1);
  202. break;
  203. case 'x':
  204. case 'p':
  205. printint(*argp++, 16, 0);
  206. break;
  207. case 's':
  208. if((s = (char*)*argp++) == 0)
  209. s = "(null)";
  210. for(; *s; s++){
  211. gpuputc(*s);
  212. uartputc(*s);
  213. }
  214. break;
  215. case '%':
  216. gpuputc('%');
  217. uartputc('%');
  218. break;
  219. default:
  220. // Print unknown % sequence to draw attention.
  221. gpuputc('%');
  222. uartputc('%');
  223. gpuputc(c);
  224. uartputc(c);
  225. break;
  226. }
  227. }
  228. if(locking)
  229. release(&cons.lock);
  230. }
  231. void
  232. panic(char *s)
  233. {
  234. int i;
  235. uint pcs[10];
  236. cprintf("cpu%d: panic: ", 0);
  237. cprintf(s);
  238. cprintf("\n");
  239. getcallerpcs(&s, pcs);
  240. for(i=0; i<10; i++)
  241. cprintf(" %p", pcs[i]);
  242. panicked = 1; // freeze other CPU
  243. for(;;)
  244. ;
  245. }
  246. #define C(x) ((x)-'@') // Control-x
  247. void
  248. consputc(int c)
  249. {
  250. if(panicked){
  251. cli();
  252. for(;;)
  253. ;
  254. }
  255. if(c == BACKSPACE){
  256. gpuputc('\b'); gpuputc(' '); gpuputc('\b');
  257. uartputc('\b'); uartputc(' '); uartputc('\b');
  258. } else if(c == C('D')) {
  259. gpuputc('^'); gpuputc('D');
  260. uartputc('^'); uartputc('D');
  261. } else {
  262. gpuputc(c);
  263. uartputc(c);
  264. }
  265. }
  266. void
  267. consoleintr(int (*getc)(void))
  268. {
  269. int c;
  270. acquire(&input.lock);
  271. while((c = getc()) >= 0){
  272. switch(c){
  273. case C('P'): // Process listing.
  274. procdump();
  275. break;
  276. case C('U'): // Kill line.
  277. while(input.e != input.w &&
  278. input.buf[(input.e-1) % INPUT_BUF] != '\n'){
  279. input.e--;
  280. consputc(BACKSPACE);
  281. }
  282. break;
  283. case C('H'): case '\x7f': // Backspace
  284. if(input.e != input.w){
  285. input.e--;
  286. consputc(BACKSPACE);
  287. }
  288. break;
  289. default:
  290. if(c != 0 && input.e-input.r < INPUT_BUF){
  291. if(c == 0xa) break;
  292. c = (c == 0xd) ? '\n' : c;
  293. input.buf[input.e++ % INPUT_BUF] = c;
  294. consputc(c);
  295. if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){
  296. input.w = input.e;
  297. wakeup(&input.r);
  298. }
  299. }
  300. break;
  301. }
  302. }
  303. release(&input.lock);
  304. }
  305. int
  306. consoleread(struct inode *ip, char *dst, int n)
  307. {
  308. uint target;
  309. int c;
  310. //cprintf("inside consoleread\n");
  311. iunlock(ip);
  312. target = n;
  313. acquire(&input.lock);
  314. while(n > 0){
  315. while(input.r == input.w){
  316. if(curr_proc->killed){
  317. release(&input.lock);
  318. ilock(ip);
  319. return -1;
  320. }
  321. sleep(&input.r, &input.lock);
  322. }
  323. c = input.buf[input.r++ % INPUT_BUF];
  324. if(c == C('D')){ // EOF
  325. if(n < target){
  326. // Save ^D for next time, to make sure
  327. // caller gets a 0-byte result.
  328. input.r--;
  329. }
  330. break;
  331. }
  332. *dst++ = c;
  333. --n;
  334. if(c == '\n')
  335. break;
  336. }
  337. release(&input.lock);
  338. ilock(ip);
  339. return target - n;
  340. }
  341. void consoleinit(void)
  342. {
  343. uint fbinfoaddr;
  344. fbinfoaddr = initframebuf(framewidth, frameheight, framecolors);
  345. if(fbinfoaddr != 0) NotOkLoop();
  346. initlock(&cons.lock, "console");
  347. memset(&input, 0, sizeof(input));
  348. initlock(&input.lock, "input");
  349. memset(devsw, 0, sizeof(struct devsw)*NDEV);
  350. devsw[CONSOLE].write = consolewrite;
  351. devsw[CONSOLE].read = consoleread;
  352. cons.locking = 1;
  353. panicked = 0; // must initialize in code since the compiler does not
  354. cursor_x=cursor_y=0;
  355. }