]> Devi Nivas Git - cs3210-lab1.git/commitdiff
Move keyboard code into kbd.c; add backspace handling.
authorrsc <rsc>
Tue, 28 Aug 2007 03:28:13 +0000 (03:28 +0000)
committerrsc <rsc>
Tue, 28 Aug 2007 03:28:13 +0000 (03:28 +0000)
Makefile
console.c
defs.h
kbd.c [new file with mode: 0644]

index cde81e59f907fc330ad7132cfc7c068392e20315..7e05cfcad2de2a47bc4c67fe407744af31cd3d1b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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-
index 3e45e3ef94a53befbe969b4abc5934c32b436c76..b7fd56ea6edb9ff439c0f8a10d60c65989a6ccfb 100644 (file)
--- a/console.c
+++ b/console.c
@@ -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(;;)
+    ;
+}
+
diff --git a/defs.h b/defs.h
index 7ed89efeb48f9701e376026a19190a80e5908de7..40f34b16ba996a91407914d4f1526d70056b395c 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -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;
diff --git a/kbd.c b/kbd.c
new file mode 100644 (file)
index 0000000..a4dd381
--- /dev/null
+++ b/kbd.c
@@ -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);
+}
+