322 lines · 4.5 KB · C
RawDownload
#include	"all.h" /* from ../pc/8250.c */extern int uartcons; staticstruct{	Lock;	uchar	buf[4000];	uchar	*in;	uchar	*out;	int	printing;} printq; staticstruct{	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 voidputs(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;} voidprintinit(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. */voidputstrn(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 */intconschar(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 */extern void trapstats(void);#define Ctl(x)	(x-0100) voidkbdchar(int c){	int s;	uchar *p;	uchar ch; 	switch(c){	case Ctl('T'):		dotrace(0);		return;	case Ctl('I'):		trapstats();		return;	case Ctl('S'):		if(u)			dumpstack(u);		return;	} 	s = splhi();	lock(&readq);	if(readq.reading)		goto out;	if(c == Ctl('U')){		if(echo)			putstrn("^U\n", 3);		readq.in = readq.out;		goto out;	}	if(c == '\r')		c = '\n';	ch = c;	if(echo)		putstrn((char*)&ch, 1);	p = readq.in;	*p++ = c;	if(p >= readq.buf+sizeof(readq.buf))		p = readq.buf;	readq.in = p;	if(c == '\n' || c == Ctl('D')) {		readq.reading = 1;		wakeup(&readq);	}out:	unlock(&readq);	splx(s);} intrawchar(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;} intreading(void*){	return readq.reading;}  /* * get a character from the console * this is the high level routine with * a queue to the interrupt handler */intgetc(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;} intprint(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);	if(predawn && conf.uartonly){		for(int i = 0; i < n; i++)			uartputc(buf[i]);	}else		putstrn(buf, n);	return n;} voidpanic(char *fmt, ...){	int n;	va_list arg;	char buf[PRINTSIZE]; 	lights(Lpanic, 1);	/* if the only console is vga, conserve it */	if(uartcons)		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();} voidprflush(void){	int i; 	if(predawn || !uartcons)		return;	for(i=0; i<50; i++) {		if(!printq.printing)			break;		delay(100);	}}