console.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include "u.h"
  2. #include "lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. IOQ consiq;
  8. IOQ consoq;
  9. static int useuart;
  10. int debug = 0;
  11. void
  12. kbdchar(int c)
  13. {
  14. c &= 0x7F;
  15. if(c == 0x10)
  16. warp86("\n^P\n", 0);
  17. if(c == 0x12) /* control-r? */
  18. debug = !debug;
  19. consiq.putc(&consiq, c);
  20. }
  21. static int
  22. consputc(void)
  23. {
  24. return consoq.getc(&consoq);
  25. }
  26. void
  27. kbdinit(void)
  28. {
  29. i8042init();
  30. qinit(&consiq);
  31. }
  32. void
  33. consinit(char* name, char* speed)
  34. {
  35. int baud, port;
  36. if(name == nil || cistrcmp(name, "cga") == 0)
  37. return;
  38. port = strtoul(name, 0, 0);
  39. if(port < 0 || port > 1)
  40. return;
  41. if(speed == nil || (baud = strtoul(speed, 0, 0)) == 0)
  42. baud = 9600;
  43. qinit(&consoq);
  44. uartspecial(port, kbdchar, consputc, baud);
  45. useuart = 1;
  46. uartputs(&consoq, "\n", 1);
  47. }
  48. void
  49. consdrain(void)
  50. {
  51. if(useuart)
  52. uartdrain();
  53. }
  54. void
  55. consputs(char* s, int n)
  56. {
  57. cgascreenputs(s, n);
  58. if(useuart)
  59. uartputs(&consoq, s, n);
  60. }
  61. void
  62. warp86(char* s, ulong)
  63. {
  64. if(s != nil)
  65. print(s);
  66. spllo();
  67. consdrain();
  68. i8042reset();
  69. /*
  70. * Often the BIOS hangs during restart if a conventional 8042
  71. * warm-boot sequence is tried. The following is Intel specific and
  72. * seems to perform a cold-boot, but at least it comes back.
  73. * And sometimes there is no keyboard...
  74. *
  75. * The reset register (0xcf9) is usually in one of the bridge
  76. * chips. The actual location and sequence could be extracted from
  77. * ACPI but why bother, this is the end of the line anyway.
  78. */
  79. print("Takes a licking and keeps on ticking...\n");
  80. *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */
  81. outb(0xcf9, 0x02);
  82. outb(0xcf9, 0x06);
  83. for(;;)
  84. idle();
  85. }
  86. static int
  87. getline(char *buf, int size, int timeout)
  88. {
  89. int c, i=0;
  90. ulong start;
  91. char echo;
  92. for (;;) {
  93. start = m->ticks;
  94. do{
  95. /* timeout seconds to first char */
  96. if(timeout && ((m->ticks - start) > timeout*HZ))
  97. return -2;
  98. c = consiq.getc(&consiq);
  99. }while(c == -1);
  100. timeout = 0;
  101. if(c == '\r')
  102. c = '\n'; /* turn carriage return into newline */
  103. if(c == '\177')
  104. c = '\010'; /* turn delete into backspace */
  105. if(c == '\025')
  106. echo = '\n'; /* echo ^U as a newline */
  107. else
  108. echo = c;
  109. consputs(&echo, 1);
  110. if(c == '\010'){
  111. if(i > 0)
  112. i--; /* bs deletes last character */
  113. continue;
  114. }
  115. /* a newline ends a line */
  116. if (c == '\n')
  117. break;
  118. /* ^U wipes out the line */
  119. if (c =='\025')
  120. return -1;
  121. if(i == size)
  122. return size;
  123. buf[i++] = c;
  124. }
  125. buf[i] = 0;
  126. return i;
  127. }
  128. int
  129. getstr(char *prompt, char *buf, int size, char *def, int timeout)
  130. {
  131. int len, isdefault;
  132. char pbuf[PRINTSIZE];
  133. buf[0] = 0;
  134. isdefault = (def && *def);
  135. if(isdefault == 0){
  136. timeout = 0;
  137. sprint(pbuf, "%s: ", prompt);
  138. }
  139. else if(timeout)
  140. sprint(pbuf, "%s[default==%s (%ds timeout)]: ", prompt, def, timeout);
  141. else
  142. sprint(pbuf, "%s[default==%s]: ", prompt, def);
  143. for (;;) {
  144. print(pbuf);
  145. consdrain();
  146. len = getline(buf, size, timeout);
  147. switch(len){
  148. case 0:
  149. /* RETURN */
  150. if(isdefault)
  151. break;
  152. continue;
  153. case -1:
  154. /* ^U typed */
  155. continue;
  156. case -2:
  157. /* timeout, use default */
  158. consputs("\n", 1);
  159. len = 0;
  160. break;
  161. default:
  162. break;
  163. }
  164. if(len >= size){
  165. print("line too long\n");
  166. continue;
  167. }
  168. break;
  169. }
  170. if(len == 0 && isdefault)
  171. strcpy(buf, def);
  172. return 0;
  173. }
  174. int
  175. print(char *fmt, ...)
  176. {
  177. int n;
  178. va_list arg;
  179. char buf[PRINTSIZE];
  180. va_start(arg, fmt);
  181. n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
  182. va_end(arg);
  183. consputs(buf, n);
  184. return n;
  185. }
  186. void
  187. panic(char *fmt, ...)
  188. {
  189. int n;
  190. va_list arg;
  191. char buf[PRINTSIZE];
  192. strcpy(buf, "panic: ");
  193. va_start(arg, fmt);
  194. n = vseprint(buf+7, buf+sizeof(buf), fmt, arg) - buf;
  195. va_end(arg);
  196. buf[n] = '\n';
  197. consputs(buf, n+1);
  198. //floppymemwrite();
  199. //splhi(); for(;;);
  200. if(etherdetach)
  201. etherdetach();
  202. if(sddetach)
  203. sddetach();
  204. consputs("\nPress almost any key to reset...", 32);
  205. spllo();
  206. while(consiq.getc(&consiq) == -1)
  207. ;
  208. warp86(nil, 0);
  209. }