123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- #include "all.h"
- static
- struct
- {
- Lock;
- uchar buf[4000];
- uchar *in;
- uchar *out;
- int printing;
- } printq;
- static
- struct
- {
- Lock;
- Rendez;
- uchar buf[500];
- uchar *in;
- uchar *out;
- int reading;
- } readq;
- int (*consgetc)(void);
- void (*consputc)(int);
- void (*consputs)(char*, int);
- /*
- * Put a string on the console.
- * n bytes of s are guaranteed to fit in the buffer and is ready to print.
- * Must be called splhi() and with printq locked.
- * If early in booting (predawn) poll output.
- * This is the interrupt driven routine used for non- screen-based systems.
- */
- static void
- puts(char *s, int n)
- {
- if(predawn) {
- while(n > 0) {
- (*consputc)(*s++ & 0xFF);
- delay(5);
- n--;
- }
- return;
- }
- if(!printq.printing){
- printq.printing = 1;
- consstart(*s++ & 0xFF);
- n--;
- }
- memmove(printq.in, s, n);
- printq.in += n;
- if(printq.in >= printq.buf+sizeof(printq.buf))
- printq.in = printq.buf;
- }
- void
- printinit(void)
- {
- lock(&printq); /* allocate lock */
- printq.in = printq.buf;
- printq.out = printq.buf;
- unlock(&printq);
- lock(&readq); /* allocate lock */
- readq.in = readq.buf;
- readq.out = readq.buf;
- unlock(&readq);
- consinit(puts);
- }
- /*
- * Print a string on the console. This is the high level routine
- * with a queue to the interrupt handler. BUG: There is no check against
- * overflow.
- */
- void
- putstrn(char *str, int n)
- {
- int s, m;
- char *t;
- s = splhi();
- lock(&printq);
- while(n > 0){
- if(*str == '\n')
- (*consputs)("\r", 1);
- m = printq.buf+sizeof(printq.buf) - printq.in;
- if(n < m)
- m = n;
- t = memchr(str+1, '\n', m-1);
- if(t)
- if(t-str < m)
- m = t - str;
- (*consputs)(str, m);
- n -= m;
- str += m;
- }
- unlock(&printq);
- splx(s);
- }
- /*
- * get character to print at interrupt time
- * always called splhi from proc 0
- */
- int
- conschar(void)
- {
- uchar *p;
- int c, s;
- s = splhi();
- lock(&printq);
- p = printq.out;
- if(p == printq.in) {
- printq.printing = 0;
- c = -1;
- } else {
- c = *p++;
- if(p >= printq.buf+sizeof(printq.buf))
- p = printq.buf;
- printq.out = p;
- }
- unlock(&printq);
- splx(s);
- return c;
- }
- /*
- * dispose of input character at interrupt time
- * always called splhi from proc 0
- */
- void
- kbdchar(int c)
- {
- int s;
- uchar *p;
- uchar ch;
- if(c == ('T' - '@')) /* ^t */
- dotrace(0);
- s = splhi();
- lock(&readq);
- if(readq.reading)
- goto out;
- if(c == ('U' - '@')) {
- if(echo)
- putstrn("^U\n", 3); /* echo */
- readq.in = readq.out;
- goto out;
- }
- if(c == '\r')
- c = '\n';
- ch = c;
- if(echo)
- putstrn((char*)&ch, 1); /* echo */
- p = readq.in;
- *p++ = c;
- if(p >= readq.buf+sizeof(readq.buf))
- p = readq.buf;
- readq.in = p;
- if(c == '\n' || c == ('D' - '@')) {
- readq.reading = 1;
- wakeup(&readq);
- }
- out:
- unlock(&readq);
- splx(s);
- }
- int
- rawchar(int seconds)
- {
- int c;
- ulong s;
- if(seconds != 0)
- seconds += toytime();
- for(;;) {
- c = (*consgetc)();
- if(c) {
- if(c == '\r')
- c = '\n';
- if(c == '\n') {
- (*consputc)('\r');
- delay(10);
- }
- (*consputc)(c);
- return c;
- }
- if(seconds) {
- /* Allow MACHP(0)->ticks to run */
- s = spllo();
- if(toytime() > seconds) {
- splx(s);
- break;
- }
- splx(s);
- }
- delay(1);
- }
- return 0;
- }
- int
- reading(void*)
- {
- return readq.reading;
- }
- /*
- * get a character from the console
- * this is the high level routine with
- * a queue to the interrupt handler
- */
- int
- getc(void)
- {
- int c, s;
- uchar *p;
- c = 0;
- loop:
- sleep(&readq, reading, 0);
- s = splhi();
- lock(&readq);
- p = readq.out;
- if(readq.in == p) {
- readq.reading = 0;
- unlock(&readq);
- splx(s);
- goto loop;
- }
- if(readq.in != p) {
- c = *p++;
- if(p == readq.buf+sizeof(readq.buf))
- p = readq.buf;
- readq.out = p;
- }
- unlock(&readq);
- splx(s);
- return c;
- }
- int
- print(char *fmt, ...)
- {
- int n;
- va_list arg;
- char buf[PRINTSIZE];
- va_start(arg, fmt);
- n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
- va_end(arg);
- putstrn(buf, n);
- return n;
- }
- void
- panic(char *fmt, ...)
- {
- int n;
- va_list arg;
- char buf[PRINTSIZE];
- lights(Lpanic, 1);
- dumpstack(u);
- strcpy(buf, "panic: ");
- va_start(arg, fmt);
- n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
- va_end(arg);
- buf[n] = '\n';
- putstrn(buf, n+1);
- if(!predawn){
- spllo();
- prflush();
- }
- exit();
- }
- void
- prflush(void)
- {
- int i;
- if(predawn)
- return;
- for(i=0; i<50; i++) {
- if(!printq.printing)
- break;
- delay(100);
- }
- }
|