提交 f0d11fea 创建 作者: rsc's avatar rsc

Move keyboard code into kbd.c; add backspace handling.

上级 c1bfbfa2
...@@ -23,6 +23,7 @@ OBJS = \ ...@@ -23,6 +23,7 @@ OBJS = \
fs.o\ fs.o\
exec.o\ exec.o\
8253pit.o\ 8253pit.o\
kbd.o\
# Cross-compiling (e.g., on Mac OS X) # Cross-compiling (e.g., on Mac OS X)
#TOOLPREFIX = i386-jos-elf- #TOOLPREFIX = i386-jos-elf-
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#define CRTPORT 0x3d4 #define CRTPORT 0x3d4
#define LPTPORT 0x378 #define LPTPORT 0x378
#define BACKSPACE 0x100
static ushort *crt = (ushort*)0xb8000; // CGA memory static ushort *crt = (ushort*)0xb8000; // CGA memory
static struct spinlock console_lock; static struct spinlock console_lock;
...@@ -27,16 +29,48 @@ lpt_putc(int c) ...@@ -27,16 +29,48 @@ lpt_putc(int c)
for(i = 0; !(inb(LPTPORT+1) & 0x80) && i < 12800; i++) for(i = 0; !(inb(LPTPORT+1) & 0x80) && i < 12800; i++)
; ;
if(c == BACKSPACE)
c = '\b';
outb(LPTPORT+0, c); outb(LPTPORT+0, c);
outb(LPTPORT+2, 0x08|0x04|0x01); outb(LPTPORT+2, 0x08|0x04|0x01);
outb(LPTPORT+2, 0x08); outb(LPTPORT+2, 0x08);
} }
static void 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){ if(panicked){
cli(); cli();
for(;;) for(;;)
...@@ -44,34 +78,7 @@ cons_putc(int c) ...@@ -44,34 +78,7 @@ cons_putc(int c)
} }
lpt_putc(c); lpt_putc(c);
cga_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);
} }
void void
...@@ -99,7 +106,7 @@ printint(int xx, int base, int sgn) ...@@ -99,7 +106,7 @@ printint(int xx, int base, int sgn)
cons_putc(buf[i]); 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 void
cprintf(char *fmt, ...) cprintf(char *fmt, ...)
{ {
...@@ -157,25 +164,6 @@ cprintf(char *fmt, ...) ...@@ -157,25 +164,6 @@ cprintf(char *fmt, ...)
release(&console_lock); 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 int
console_write(int minor, char *buf, int n) console_write(int minor, char *buf, int n)
{ {
...@@ -189,86 +177,57 @@ console_write(int minor, char *buf, int n) ...@@ -189,86 +177,57 @@ console_write(int minor, char *buf, int n)
return n; return n;
} }
#define KBD_BUF 64 #define INPUT_BUF 128
struct { struct {
uchar buf[KBD_BUF];
int r;
int w;
struct spinlock lock; struct spinlock lock;
} kbd; char buf[INPUT_BUF];
int r; // Read index
int w; // Write index
int e; // Edit index
} input;
void void
kbd_intr(void) console_intr(int (*getc)(void))
{ {
static uint shift; int c;
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';
}
switch(c){ acquire(&input.lock);
case 0: while((c = getc()) >= 0){
// Ignore unknown keystrokes. switch(c){
break; 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'): case C('H'): // Backspace
cprintf("#"); // Let user know we're still alive. if(input.e > input.w){
break; input.e--;
cons_putc(BACKSPACE);
}
break;
case C('P'): default:
procdump(); if(c != 0 && input.e < input.r+INPUT_BUF){
break; input.buf[input.e++] = c;
cons_putc(c);
default: if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){
if(((kbd.w + 1) % KBD_BUF) != kbd.r){ input.w = input.e;
kbd.buf[kbd.w++] = c; wakeup(&input.r);
if(kbd.w >= KBD_BUF) }
kbd.w = 0; }
wakeup(&kbd.r); break;
} }
break;
} }
release(&input.lock);
out:
release(&kbd.lock);
} }
//PAGEBREAK: 25
int int
console_read(int minor, char *dst, int n) console_read(int minor, char *dst, int n)
{ {
...@@ -276,31 +235,33 @@ console_read(int minor, char *dst, int n) ...@@ -276,31 +235,33 @@ console_read(int minor, char *dst, int n)
int c; int c;
target = n; target = n;
acquire(&kbd.lock); acquire(&input.lock);
while(n > 0){ while(n > 0){
while(kbd.r == kbd.w){ while(input.r == input.w){
if(cp->killed){ if(cp->killed){
release(&kbd.lock); release(&input.lock);
return -1; 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(c == C('D')){ // EOF
if(n < target){ if(n < target){
// Save ^D for next time, to make sure // Save ^D for next time, to make sure
// caller gets a 0-byte result. // caller gets a 0-byte result.
kbd.r--; input.r--;
} }
break; break;
} }
*dst++ = c; *dst++ = c;
cons_putc(c); cons_putc(c);
--n; --n;
if(kbd.r >= KBD_BUF) if(c == '\n')
kbd.r = 0; break;
if(input.r >= INPUT_BUF)
input.r = 0;
} }
release(&kbd.lock); release(&input.lock);
return target - n; return target - n;
} }
...@@ -309,7 +270,7 @@ void ...@@ -309,7 +270,7 @@ void
console_init(void) console_init(void)
{ {
initlock(&console_lock, "console"); initlock(&console_lock, "console");
initlock(&kbd.lock, "kbd"); initlock(&input.lock, "console input");
devsw[CONSOLE].write = console_write; devsw[CONSOLE].write = console_write;
devsw[CONSOLE].read = console_read; devsw[CONSOLE].read = console_read;
...@@ -319,3 +280,22 @@ console_init(void) ...@@ -319,3 +280,22 @@ console_init(void)
ioapic_enable(IRQ_KBD, 0); 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*); ...@@ -19,7 +19,7 @@ void bwrite(struct buf*);
// console.c // console.c
void console_init(void); void console_init(void);
void cprintf(char*, ...); void cprintf(char*, ...);
void kbd_intr(void); void console_intr(int(*)(void));
void panic(char*) __attribute__((noreturn)); void panic(char*) __attribute__((noreturn));
// exec.c // exec.c
...@@ -67,6 +67,9 @@ char* kalloc(int); ...@@ -67,6 +67,9 @@ char* kalloc(int);
void kfree(char*, int); void kfree(char*, int);
void kinit(void); void kinit(void);
// kbd.c
void kbd_intr(void);
// lapic.c // lapic.c
int cpu(void); int cpu(void);
extern volatile uint* lapic; extern volatile uint* lapic;
......
#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);
}
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论