devcons.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #include "all.h"
  2. /* from ../pc/8250.c */
  3. extern int uartcons;
  4. static
  5. struct
  6. {
  7. Lock;
  8. uchar buf[4000];
  9. uchar *in;
  10. uchar *out;
  11. int printing;
  12. } printq;
  13. static
  14. struct
  15. {
  16. Lock;
  17. Rendez;
  18. uchar buf[500];
  19. uchar *in;
  20. uchar *out;
  21. int reading;
  22. } readq;
  23. int (*consgetc)(void);
  24. void (*consputc)(int);
  25. void (*consputs)(char*, int);
  26. /*
  27. * Put a string on the console.
  28. * n bytes of s are guaranteed to fit in the buffer and is ready to print.
  29. * Must be called splhi() and with printq locked.
  30. * If early in booting (predawn) poll output.
  31. * This is the interrupt driven routine used for non- screen-based systems.
  32. */
  33. static void
  34. puts(char *s, int n)
  35. {
  36. if(predawn) {
  37. while(n > 0) {
  38. (*consputc)(*s++ & 0xFF);
  39. delay(5);
  40. n--;
  41. }
  42. return;
  43. }
  44. if(!printq.printing){
  45. printq.printing = 1;
  46. consstart(*s++ & 0xFF);
  47. n--;
  48. }
  49. memmove(printq.in, s, n);
  50. printq.in += n;
  51. if(printq.in >= printq.buf+sizeof(printq.buf))
  52. printq.in = printq.buf;
  53. }
  54. void
  55. printinit(void)
  56. {
  57. lock(&printq); /* allocate lock */
  58. printq.in = printq.buf;
  59. printq.out = printq.buf;
  60. unlock(&printq);
  61. lock(&readq); /* allocate lock */
  62. readq.in = readq.buf;
  63. readq.out = readq.buf;
  64. unlock(&readq);
  65. consinit(puts);
  66. }
  67. /*
  68. * Print a string on the console. This is the high level routine
  69. * with a queue to the interrupt handler. BUG: There is no check against
  70. * overflow.
  71. */
  72. void
  73. putstrn(char *str, int n)
  74. {
  75. int s, m;
  76. char *t;
  77. s = splhi();
  78. lock(&printq);
  79. while(n > 0){
  80. if(*str == '\n')
  81. (*consputs)("\r", 1);
  82. m = printq.buf+sizeof(printq.buf) - printq.in;
  83. if(n < m)
  84. m = n;
  85. t = memchr(str+1, '\n', m-1);
  86. if(t)
  87. if(t-str < m)
  88. m = t - str;
  89. (*consputs)(str, m);
  90. n -= m;
  91. str += m;
  92. }
  93. unlock(&printq);
  94. splx(s);
  95. }
  96. /*
  97. * get character to print at interrupt time
  98. * always called splhi from proc 0
  99. */
  100. int
  101. conschar(void)
  102. {
  103. uchar *p;
  104. int c, s;
  105. s = splhi();
  106. lock(&printq);
  107. p = printq.out;
  108. if(p == printq.in) {
  109. printq.printing = 0;
  110. c = -1;
  111. } else {
  112. c = *p++;
  113. if(p >= printq.buf+sizeof(printq.buf))
  114. p = printq.buf;
  115. printq.out = p;
  116. }
  117. unlock(&printq);
  118. splx(s);
  119. return c;
  120. }
  121. #define ctl(c) ((c) & 037)
  122. /*
  123. * dispose of input character at interrupt time
  124. * always called splhi from proc 0
  125. */
  126. void
  127. kbdchar(int c)
  128. {
  129. int s;
  130. uchar *p;
  131. uchar ch;
  132. char uparrow[2];
  133. if(c == ctl('t'))
  134. dotrace(0);
  135. s = splhi();
  136. lock(&readq);
  137. if(readq.reading)
  138. goto out;
  139. if(c == ctl('u')) {
  140. if(echo)
  141. putstrn("^U\n", 3); /* echo */
  142. readq.in = readq.out;
  143. goto out;
  144. }
  145. if(c == '\r')
  146. c = '\n';
  147. ch = c;
  148. if(echo)
  149. /*
  150. * cga mode (for example) does a poor job of showing control
  151. * chars, so echo them as ^X. this will mess up subsequent
  152. * backspace erasures, alas. it also doesn't cope with utf.
  153. */
  154. if (ch >= ' ' || ch == '\n' || ch == '\t' || ch == '\b')
  155. putstrn((char*)&ch, 1); /* echo */
  156. else {
  157. uparrow[0] = '^';
  158. uparrow[1] = ch + '@'; /* ctrl -> upper case */
  159. putstrn(uparrow, 2);
  160. }
  161. p = readq.in;
  162. *p++ = c;
  163. if(p >= readq.buf+sizeof(readq.buf))
  164. p = readq.buf;
  165. readq.in = p;
  166. if(c == '\n' || c == ctl('d')) {
  167. readq.reading = 1;
  168. wakeup(&readq);
  169. }
  170. out:
  171. unlock(&readq);
  172. splx(s);
  173. }
  174. int
  175. rawchar(int seconds)
  176. {
  177. int c;
  178. ulong s;
  179. if(seconds != 0)
  180. seconds += toytime();
  181. for(;;) {
  182. c = (*consgetc)();
  183. if(c) {
  184. if(c == '\r')
  185. c = '\n';
  186. /* ugh! yet another place that does echoing */
  187. if(c == '\n') {
  188. (*consputc)('\r');
  189. delay(10);
  190. }
  191. (*consputc)(c);
  192. return c;
  193. }
  194. if(seconds) {
  195. /* Allow MACHP(0)->ticks to run */
  196. s = spllo();
  197. if(toytime() > seconds) {
  198. splx(s);
  199. break;
  200. }
  201. splx(s);
  202. }
  203. delay(1);
  204. }
  205. return 0;
  206. }
  207. int
  208. reading(void*)
  209. {
  210. return readq.reading;
  211. }
  212. /*
  213. * get a character from the console
  214. * this is the high level routine with
  215. * a queue to the interrupt handler
  216. */
  217. int
  218. getc(void)
  219. {
  220. int c, s;
  221. uchar *p;
  222. c = 0;
  223. loop:
  224. sleep(&readq, reading, 0);
  225. s = splhi();
  226. lock(&readq);
  227. p = readq.out;
  228. if(readq.in == p) {
  229. readq.reading = 0;
  230. unlock(&readq);
  231. splx(s);
  232. goto loop;
  233. }
  234. if(readq.in != p) {
  235. c = *p++;
  236. if(p == readq.buf+sizeof(readq.buf))
  237. p = readq.buf;
  238. readq.out = p;
  239. }
  240. unlock(&readq);
  241. splx(s);
  242. return c;
  243. }
  244. int
  245. print(char *fmt, ...)
  246. {
  247. int n;
  248. va_list arg;
  249. char buf[PRINTSIZE];
  250. va_start(arg, fmt);
  251. n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
  252. va_end(arg);
  253. putstrn(buf, n);
  254. return n;
  255. }
  256. void
  257. panic(char *fmt, ...)
  258. {
  259. int n;
  260. va_list arg;
  261. char buf[PRINTSIZE];
  262. lights(Lpanic, 1);
  263. /* if the only console is vga, conserve it */
  264. if (uartcons)
  265. dumpstack(u);
  266. strcpy(buf, "panic: ");
  267. va_start(arg, fmt);
  268. n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
  269. va_end(arg);
  270. buf[n] = '\n';
  271. putstrn(buf, n+1);
  272. if(!predawn){
  273. spllo();
  274. prflush();
  275. }
  276. exit();
  277. }
  278. void
  279. prflush(void)
  280. {
  281. int i;
  282. if(predawn || !uartcons)
  283. return;
  284. for(i=0; i<50; i++) {
  285. if(!printq.printing)
  286. break;
  287. delay(100);
  288. }
  289. }