diff options
author | rsc <rsc> | 2007-08-28 03:28:13 +0000 |
---|---|---|
committer | rsc <rsc> | 2007-08-28 03:28:13 +0000 |
commit | f0d11fea8251ef959cf1197b62e523922855df3a (patch) | |
tree | c1ac5b50ec8cffb2e46636a6b5569f758dcaf8ae | |
parent | c1bfbfa2f7b995ee38ef138ca3250274213dc010 (diff) | |
download | xv6-labs-f0d11fea8251ef959cf1197b62e523922855df3a.tar.gz xv6-labs-f0d11fea8251ef959cf1197b62e523922855df3a.tar.bz2 xv6-labs-f0d11fea8251ef959cf1197b62e523922855df3a.zip |
Move keyboard code into kbd.c; add backspace handling.
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | console.c | 236 | ||||
-rw-r--r-- | defs.h | 5 | ||||
-rw-r--r-- | kbd.c | 51 |
4 files changed, 164 insertions, 129 deletions
@@ -23,6 +23,7 @@ OBJS = \ fs.o\ exec.o\ 8253pit.o\ + kbd.o\ # Cross-compiling (e.g., on Mac OS X) #TOOLPREFIX = i386-jos-elf- @@ -11,6 +11,8 @@ #define CRTPORT 0x3d4 #define LPTPORT 0x378 +#define BACKSPACE 0x100 + static ushort *crt = (ushort*)0xb8000; // CGA memory static struct spinlock console_lock; @@ -27,16 +29,48 @@ lpt_putc(int c) for(i = 0; !(inb(LPTPORT+1) & 0x80) && i < 12800; i++) ; + if(c == BACKSPACE) + c = '\b'; outb(LPTPORT+0, c); outb(LPTPORT+2, 0x08|0x04|0x01); outb(LPTPORT+2, 0x08); } static void -cons_putc(int c) +cga_putc(int c) { - int ind; + int pos; + + // Cursor position: col + 80*row. + outb(CRTPORT, 14); + pos = inb(CRTPORT+1) << 8; + outb(CRTPORT, 15); + pos |= inb(CRTPORT+1); + + if(c == '\n') + pos += 80 - pos%80; + else if(c == BACKSPACE){ + if(pos > 0) + crt[--pos] = ' ' | 0x0700; + }else + crt[pos++] = (c&0xff) | 0x0700; // black on white + + if((pos/80) >= 24){ // Scroll up. + memmove(crt, crt+80, sizeof(crt[0])*23*80); + pos -= 80; + memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos)); + } + + outb(CRTPORT, 14); + outb(CRTPORT+1, pos>>8); + outb(CRTPORT, 15); + outb(CRTPORT+1, pos); + crt[pos] = ' ' | 0x0700; +} +static void +cons_putc(int c) +{ if(panicked){ cli(); for(;;) @@ -44,34 +78,7 @@ cons_putc(int c) } lpt_putc(c); - - // cursor position, 16 bits, col + 80*row - outb(CRTPORT, 14); - ind = inb(CRTPORT + 1) << 8; - outb(CRTPORT, 15); - ind |= inb(CRTPORT + 1); - - c &= 0xff; - if(c == '\n'){ - ind -= (ind % 80); - ind += 80; - } else { - c |= 0x0700; // black on white - crt[ind] = c; - ind++; - } - - if((ind / 80) >= 24){ - // scroll up - memmove(crt, crt + 80, sizeof(crt[0]) * (23 * 80)); - ind -= 80; - memset(crt + ind, 0, sizeof(crt[0]) * ((24 * 80) - ind)); - } - - outb(CRTPORT, 14); - outb(CRTPORT + 1, ind >> 8); - outb(CRTPORT, 15); - outb(CRTPORT + 1, ind); + cga_putc(c); } void @@ -99,7 +106,7 @@ printint(int xx, int base, int sgn) cons_putc(buf[i]); } -// Print to the console. only understands %d, %x, %p, %s. +// Print to the input. only understands %d, %x, %p, %s. void cprintf(char *fmt, ...) { @@ -157,25 +164,6 @@ cprintf(char *fmt, ...) release(&console_lock); } -void -panic(char *s) -{ - int i; - uint pcs[10]; - - __asm __volatile("cli"); - use_console_lock = 0; - cprintf("panic (%d): ", cpu()); - cprintf(s, 0); - cprintf("\n", 0); - getcallerpcs(&s, pcs); - for(i=0; i<10; i++) - cprintf(" %p", pcs[i]); - panicked = 1; // freeze other CPU - for(;;) - ; -} - int console_write(int minor, char *buf, int n) { @@ -189,86 +177,57 @@ console_write(int minor, char *buf, int n) return n; } -#define KBD_BUF 64 +#define INPUT_BUF 128 struct { - uchar buf[KBD_BUF]; - int r; - int w; struct spinlock lock; -} kbd; + char buf[INPUT_BUF]; + int r; // Read index + int w; // Write index + int e; // Edit index +} input; void -kbd_intr(void) +console_intr(int (*getc)(void)) { - static uint shift; - static uchar *charcode[4] = { - normalmap, - shiftmap, - ctlmap, - ctlmap - }; - uint st, data, c; - - acquire(&kbd.lock); - - st = inb(KBSTATP); - if((st & KBS_DIB) == 0) - goto out; - data = inb(KBDATAP); - - if(data == 0xE0) { - shift |= E0ESC; - goto out; - } else if(data & 0x80) { - // Key released - data = (shift & E0ESC ? data : data & 0x7F); - shift &= ~(shiftcode[data] | E0ESC); - goto out; - } else if(shift & E0ESC) { - // Last character was an E0 escape; or with 0x80 - data |= 0x80; - shift &= ~E0ESC; - } - - shift |= shiftcode[data]; - shift ^= togglecode[data]; - - c = charcode[shift & (CTL | SHIFT)][data]; - if(shift & CAPSLOCK) { - if('a' <= c && c <= 'z') - c += 'A' - 'a'; - else if('A' <= c && c <= 'Z') - c += 'a' - 'A'; - } + int c; - switch(c){ - case 0: - // Ignore unknown keystrokes. - break; + acquire(&input.lock); + while((c = getc()) >= 0){ + switch(c){ + case C('P'): // Process listing. + procdump(); + break; + + case C('U'): // Kill line. + while(input.e > input.w && + input.buf[(input.e-1) % INPUT_BUF] != '\n'){ + input.e--; + cons_putc(BACKSPACE); + } + break; - case C('T'): - cprintf("#"); // Let user know we're still alive. - break; + case C('H'): // Backspace + if(input.e > input.w){ + input.e--; + cons_putc(BACKSPACE); + } + break; - case C('P'): - procdump(); - break; - - default: - if(((kbd.w + 1) % KBD_BUF) != kbd.r){ - kbd.buf[kbd.w++] = c; - if(kbd.w >= KBD_BUF) - kbd.w = 0; - wakeup(&kbd.r); + default: + if(c != 0 && input.e < input.r+INPUT_BUF){ + input.buf[input.e++] = c; + cons_putc(c); + if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){ + input.w = input.e; + wakeup(&input.r); + } + } + break; } - break; } - -out: - release(&kbd.lock); + release(&input.lock); } -//PAGEBREAK: 25 int console_read(int minor, char *dst, int n) { @@ -276,31 +235,33 @@ console_read(int minor, char *dst, int n) int c; target = n; - acquire(&kbd.lock); + acquire(&input.lock); while(n > 0){ - while(kbd.r == kbd.w){ + while(input.r == input.w){ if(cp->killed){ - release(&kbd.lock); + release(&input.lock); return -1; } - sleep(&kbd.r, &kbd.lock); + sleep(&input.r, &input.lock); } - c = kbd.buf[kbd.r++]; + c = input.buf[input.r++]; if(c == C('D')){ // EOF if(n < target){ // Save ^D for next time, to make sure // caller gets a 0-byte result. - kbd.r--; + input.r--; } break; } *dst++ = c; cons_putc(c); --n; - if(kbd.r >= KBD_BUF) - kbd.r = 0; + if(c == '\n') + break; + if(input.r >= INPUT_BUF) + input.r = 0; } - release(&kbd.lock); + release(&input.lock); return target - n; } @@ -309,7 +270,7 @@ void console_init(void) { initlock(&console_lock, "console"); - initlock(&kbd.lock, "kbd"); + initlock(&input.lock, "console input"); devsw[CONSOLE].write = console_write; devsw[CONSOLE].read = console_read; @@ -319,3 +280,22 @@ console_init(void) ioapic_enable(IRQ_KBD, 0); } +void +panic(char *s) +{ + int i; + uint pcs[10]; + + __asm __volatile("cli"); + use_console_lock = 0; + cprintf("panic (%d): ", cpu()); + cprintf(s, 0); + cprintf("\n", 0); + getcallerpcs(&s, pcs); + for(i=0; i<10; i++) + cprintf(" %p", pcs[i]); + panicked = 1; // freeze other CPU + for(;;) + ; +} + @@ -19,7 +19,7 @@ void bwrite(struct buf*); // console.c void console_init(void); void cprintf(char*, ...); -void kbd_intr(void); +void console_intr(int(*)(void)); void panic(char*) __attribute__((noreturn)); // exec.c @@ -67,6 +67,9 @@ char* kalloc(int); void kfree(char*, int); void kinit(void); +// kbd.c +void kbd_intr(void); + // lapic.c int cpu(void); extern volatile uint* lapic; @@ -0,0 +1,51 @@ +#include "types.h" +#include "x86.h" +#include "defs.h" +#include "kbd.h" + +int +kbd_getc(void) +{ + static uint shift; + static uchar *charcode[4] = { + normalmap, shiftmap, ctlmap, ctlmap + }; + uint st, data, c; + + st = inb(KBSTATP); + if((st & KBS_DIB) == 0) + return -1; + data = inb(KBDATAP); + + if(data == 0xE0) { + shift |= E0ESC; + return 0; + } else if(data & 0x80) { + // Key released + data = (shift & E0ESC ? data : data & 0x7F); + shift &= ~(shiftcode[data] | E0ESC); + return 0; + } else if(shift & E0ESC) { + // Last character was an E0 escape; or with 0x80 + data |= 0x80; + shift &= ~E0ESC; + } + + shift |= shiftcode[data]; + shift ^= togglecode[data]; + c = charcode[shift & (CTL | SHIFT)][data]; + if(shift & CAPSLOCK) { + if('a' <= c && c <= 'z') + c += 'A' - 'a'; + else if('A' <= c && c <= 'Z') + c += 'a' - 'A'; + } + return c; +} + +void +kbd_intr(void) +{ + console_intr(kbd_getc); +} + |