diff options
author | Robert Morris <[email protected]> | 2019-06-11 09:57:14 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-06-11 09:57:14 -0400 |
commit | 5753553213df8f9de851adb68377db43faecb91f (patch) | |
tree | 3b629ff54897fca414146677532cb459a2ed11ba /kernel/console.c | |
parent | 91ba81110acd3163f7de3580b677eece0c57f5e7 (diff) | |
download | xv6-labs-5753553213df8f9de851adb68377db43faecb91f.tar.gz xv6-labs-5753553213df8f9de851adb68377db43faecb91f.tar.bz2 xv6-labs-5753553213df8f9de851adb68377db43faecb91f.zip |
separate source into kernel/ user/ mkfs/
Diffstat (limited to 'kernel/console.c')
-rw-r--r-- | kernel/console.c | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/kernel/console.c b/kernel/console.c new file mode 100644 index 0000000..b20d4a9 --- /dev/null +++ b/kernel/console.c @@ -0,0 +1,271 @@ +// Console input and output. +// Input is from the keyboard or serial port. +// Output is written to the screen and serial port. + +#include <stdarg.h> + +#include "types.h" +#include "param.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "fs.h" +#include "file.h" +#include "memlayout.h" +#include "riscv.h" +#include "defs.h" +#include "proc.h" + +static void consputc(int); + +static volatile int panicked = 0; + +static struct { + struct spinlock lock; + int locking; +} cons; + +static char digits[] = "0123456789abcdef"; + +static void +printint(int xx, int base, int sign) +{ + char buf[16]; + int i; + uint x; + + if(sign && (sign = xx < 0)) + x = -xx; + else + x = xx; + + i = 0; + do{ + buf[i++] = digits[x % base]; + }while((x /= base) != 0); + + if(sign) + buf[i++] = '-'; + + while(--i >= 0) + consputc(buf[i]); +} + +static void +printptr(uint64 x) { + int i; + consputc('0'); + consputc('x'); + for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4) + consputc(digits[x >> (sizeof(uint64) * 8 - 4)]); +} + + +//PAGEBREAK: 50 + +// Print to the console. only understands %d, %x, %p, %s. +void +printf(char *fmt, ...) +{ + va_list ap; + int i, c, locking; + char *s; + + locking = cons.locking; + if(locking) + acquire(&cons.lock); + + if (fmt == 0) + panic("null fmt"); + + va_start(ap, fmt); + for(i = 0; (c = fmt[i] & 0xff) != 0; i++){ + if(c != '%'){ + consputc(c); + continue; + } + c = fmt[++i] & 0xff; + if(c == 0) + break; + switch(c){ + case 'd': + printint(va_arg(ap, int), 10, 1); + break; + case 'x': + printint(va_arg(ap, int), 16, 1); + break; + case 'p': + printptr(va_arg(ap, uint64)); + break; + case 's': + if((s = va_arg(ap, char*)) == 0) + s = "(null)"; + for(; *s; s++) + consputc(*s); + break; + case '%': + consputc('%'); + break; + default: + // Print unknown % sequence to draw attention. + consputc('%'); + consputc(c); + break; + } + } + + if(locking) + release(&cons.lock); +} + +void +panic(char *s) +{ + cons.locking = 0; + printf("panic: "); + printf(s); + printf("\n"); + panicked = 1; // freeze other CPU + for(;;) + ; +} + +#define BACKSPACE 0x100 + +void +consputc(int c) +{ + if(panicked){ + for(;;) + ; + } + + if(c == BACKSPACE){ + uartputc('\b'); uartputc(' '); uartputc('\b'); + } else + uartputc(c); +} + +#define INPUT_BUF 128 +struct { + char buf[INPUT_BUF]; + uint r; // Read index + uint w; // Write index + uint e; // Edit index +} input; + +#define C(x) ((x)-'@') // Contro + +int +consoleread(struct inode *ip, int user_dst, uint64 dst, int n) +{ + uint target; + int c; + char buf[1]; + + iunlock(ip); + target = n; + acquire(&cons.lock); + while(n > 0){ + while(input.r == input.w){ + if(myproc()->killed){ + release(&cons.lock); + ilock(ip); + return -1; + } + sleep(&input.r, &cons.lock); + } + c = input.buf[input.r++ % INPUT_BUF]; + if(c == C('D')){ // EOF + if(n < target){ + // Save ^D for next time, to make sure + // caller gets a 0-byte result. + input.r--; + } + break; + } + buf[0] = c; + if(either_copyout(user_dst, dst, &buf[0], 1) == -1) + break; + dst++; + --n; + if(c == '\n') + break; + } + release(&cons.lock); + ilock(ip); + + return target - n; +} + +int +consolewrite(struct inode *ip, int user_src, uint64 src, int n) +{ + int i; + + iunlock(ip); + acquire(&cons.lock); + for(i = 0; i < n; i++){ + char c; + if(either_copyin(&c, user_src, src+i, 1) == -1) + break; + consputc(c); + } + release(&cons.lock); + ilock(ip); + + return n; +} + +void +consoleintr(int c) +{ + int doprocdump = 0; + + acquire(&cons.lock); + + switch(c){ + case C('P'): // Process list. + // procdump() locks cons.lock indirectly; invoke later + doprocdump = 1; + break; + case C('U'): // Kill line. + while(input.e != input.w && + input.buf[(input.e-1) % INPUT_BUF] != '\n'){ + input.e--; + consputc(BACKSPACE); + } + break; + case C('H'): case '\x7f': // Backspace + if(input.e != input.w){ + input.e--; + consputc(BACKSPACE); + } + break; + default: + if(c != 0 && input.e-input.r < INPUT_BUF){ + c = (c == '\r') ? '\n' : c; + input.buf[input.e++ % INPUT_BUF] = c; + consputc(c); + if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){ + input.w = input.e; + wakeup(&input.r); + } + } + break; + } + + release(&cons.lock); + + if(doprocdump) + procdump(); +} + +void +consoleinit(void) +{ + initlock(&cons.lock, "console"); + + devsw[CONSOLE].write = consolewrite; + devsw[CONSOLE].read = consoleread; + cons.locking = 1; +} |