Move keyboard code into kbd.c; add backspace handling.
This commit is contained in:
		
							parent
							
								
									c1bfbfa2f7
								
							
						
					
					
						commit
						f0d11fea82
					
				
					 4 changed files with 210 additions and 175 deletions
				
			
		
							
								
								
									
										1
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								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-
 | ||||
|  |  | |||
							
								
								
									
										328
									
								
								console.c
									
										
									
									
									
								
							
							
						
						
									
										328
									
								
								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 | ||||
| cga_putc(int c) | ||||
| { | ||||
|   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) | ||||
| { | ||||
|   int ind; | ||||
| 
 | ||||
|   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,6 +164,122 @@ cprintf(char *fmt, ...) | |||
|     release(&console_lock); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| console_write(int minor, char *buf, int n) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   acquire(&console_lock); | ||||
|   for(i = 0; i < n; i++) | ||||
|     cons_putc(buf[i] & 0xff); | ||||
|   release(&console_lock); | ||||
| 
 | ||||
|   return n; | ||||
| } | ||||
| 
 | ||||
| #define INPUT_BUF 128 | ||||
| struct { | ||||
|   struct spinlock lock; | ||||
|   char buf[INPUT_BUF]; | ||||
|   int r;  // Read index
 | ||||
|   int w;  // Write index
 | ||||
|   int e;  // Edit index
 | ||||
| } input; | ||||
| 
 | ||||
| void | ||||
| console_intr(int (*getc)(void)) | ||||
| { | ||||
|   int c; | ||||
| 
 | ||||
|   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('H'):  // Backspace
 | ||||
|       if(input.e > input.w){ | ||||
|         input.e--; | ||||
|         cons_putc(BACKSPACE); | ||||
|       } | ||||
|       break; | ||||
|    | ||||
|     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; | ||||
|     } | ||||
|   } | ||||
|   release(&input.lock); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| console_read(int minor, char *dst, int n) | ||||
| { | ||||
|   uint target; | ||||
|   int c; | ||||
| 
 | ||||
|   target = n; | ||||
|   acquire(&input.lock); | ||||
|   while(n > 0){ | ||||
|     while(input.r == input.w){ | ||||
|       if(cp->killed){ | ||||
|         release(&input.lock); | ||||
|         return -1; | ||||
|       } | ||||
|       sleep(&input.r, &input.lock); | ||||
|     } | ||||
|     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.
 | ||||
|         input.r--; | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|     *dst++ = c; | ||||
|     cons_putc(c); | ||||
|     --n; | ||||
|     if(c == '\n') | ||||
|       break; | ||||
|     if(input.r >= INPUT_BUF) | ||||
|       input.r = 0; | ||||
|   } | ||||
|   release(&input.lock); | ||||
| 
 | ||||
|   return target - n; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| console_init(void) | ||||
| { | ||||
|   initlock(&console_lock, "console"); | ||||
|   initlock(&input.lock, "console input"); | ||||
| 
 | ||||
|   devsw[CONSOLE].write = console_write; | ||||
|   devsw[CONSOLE].read = console_read; | ||||
|   use_console_lock = 1; | ||||
| 
 | ||||
|   irq_enable(IRQ_KBD); | ||||
|   ioapic_enable(IRQ_KBD, 0); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| panic(char *s) | ||||
| { | ||||
|  | @ -176,146 +299,3 @@ panic(char *s) | |||
|     ; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| console_write(int minor, char *buf, int n) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   acquire(&console_lock); | ||||
|   for(i = 0; i < n; i++) | ||||
|     cons_putc(buf[i] & 0xff); | ||||
|   release(&console_lock); | ||||
| 
 | ||||
|   return n; | ||||
| } | ||||
| 
 | ||||
| #define KBD_BUF 64 | ||||
| struct { | ||||
|   uchar buf[KBD_BUF]; | ||||
|   int r; | ||||
|   int w; | ||||
|   struct spinlock lock; | ||||
| } kbd; | ||||
| 
 | ||||
| void | ||||
| kbd_intr(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'; | ||||
|   } | ||||
| 
 | ||||
|   switch(c){ | ||||
|   case 0: | ||||
|     // Ignore unknown keystrokes.
 | ||||
|     break; | ||||
|    | ||||
|   case C('T'): | ||||
|     cprintf("#");  // Let user know we're still alive.
 | ||||
|     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); | ||||
|     } | ||||
|     break; | ||||
|   } | ||||
| 
 | ||||
| out: | ||||
|   release(&kbd.lock); | ||||
| } | ||||
| 
 | ||||
| //PAGEBREAK: 25
 | ||||
| int | ||||
| console_read(int minor, char *dst, int n) | ||||
| { | ||||
|   uint target; | ||||
|   int c; | ||||
| 
 | ||||
|   target = n; | ||||
|   acquire(&kbd.lock); | ||||
|   while(n > 0){ | ||||
|     while(kbd.r == kbd.w){ | ||||
|       if(cp->killed){ | ||||
|         release(&kbd.lock); | ||||
|         return -1; | ||||
|       } | ||||
|       sleep(&kbd.r, &kbd.lock); | ||||
|     } | ||||
|     c = kbd.buf[kbd.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--; | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|     *dst++ = c; | ||||
|     cons_putc(c); | ||||
|     --n; | ||||
|     if(kbd.r >= KBD_BUF) | ||||
|       kbd.r = 0; | ||||
|   } | ||||
|   release(&kbd.lock); | ||||
| 
 | ||||
|   return target - n; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| console_init(void) | ||||
| { | ||||
|   initlock(&console_lock, "console"); | ||||
|   initlock(&kbd.lock, "kbd"); | ||||
| 
 | ||||
|   devsw[CONSOLE].write = console_write; | ||||
|   devsw[CONSOLE].read = console_read; | ||||
|   use_console_lock = 1; | ||||
| 
 | ||||
|   irq_enable(IRQ_KBD); | ||||
|   ioapic_enable(IRQ_KBD, 0); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										5
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								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; | ||||
|  |  | |||
							
								
								
									
										51
									
								
								kbd.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								kbd.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -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); | ||||
| } | ||||
| 
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 rsc
						rsc