diff options
| -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); +} + | 
