devcons.c 4.2 KB

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