root/console.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. printint
  2. cprintf
  3. panic
  4. cgaputc
  5. consputc
  6. consoleintr
  7. consoleread
  8. consolewrite
  9. consoleinit

   1 // Console input and output.
   2 // Input is from the keyboard or serial port.
   3 // Output is written to the screen and serial port.
   4 
   5 #include "types.h"
   6 #include "defs.h"
   7 #include "param.h"
   8 #include "traps.h"
   9 #include "spinlock.h"
  10 #include "fs.h"
  11 #include "file.h"
  12 #include "memlayout.h"
  13 #include "mmu.h"
  14 #include "proc.h"
  15 #include "x86.h"
  16 
  17 static void consputc(int);
  18 
  19 static int panicked = 0;
  20 
  21 static struct {
  22   struct spinlock lock;
  23   int locking;
  24 } cons;
  25 
  26 static void
  27 printint(int xx, int base, int sign)
  28 {
  29   static char digits[] = "0123456789abcdef";
  30   char buf[16];
  31   int i;
  32   uint x;
  33 
  34   if(sign && (sign = xx < 0))
  35     x = -xx;
  36   else
  37     x = xx;
  38 
  39   i = 0;
  40   do{
  41     buf[i++] = digits[x % base];
  42   }while((x /= base) != 0);
  43 
  44   if(sign)
  45     buf[i++] = '-';
  46 
  47   while(--i >= 0)
  48     consputc(buf[i]);
  49 }
  50 //PAGEBREAK: 50
  51 
  52 // Print to the console. only understands %d, %x, %p, %s.
  53 void
  54 cprintf(char *fmt, ...)
  55 {
  56   int i, c, locking;
  57   uint *argp;
  58   char *s;
  59 
  60   locking = cons.locking;
  61   if(locking)
  62     acquire(&cons.lock);
  63 
  64   if (fmt == 0)
  65     panic("null fmt");
  66 
  67   argp = (uint*)(void*)(&fmt + 1);
  68   for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
  69     if(c != '%'){
  70       consputc(c);
  71       continue;
  72     }
  73     c = fmt[++i] & 0xff;
  74     if(c == 0)
  75       break;
  76     switch(c){
  77     case 'd':
  78       printint(*argp++, 10, 1);
  79       break;
  80     case 'x':
  81     case 'p':
  82       printint(*argp++, 16, 0);
  83       break;
  84     case 's':
  85       if((s = (char*)*argp++) == 0)
  86         s = "(null)";
  87       for(; *s; s++)
  88         consputc(*s);
  89       break;
  90     case '%':
  91       consputc('%');
  92       break;
  93     default:
  94       // Print unknown % sequence to draw attention.
  95       consputc('%');
  96       consputc(c);
  97       break;
  98     }
  99   }
 100 
 101   if(locking)
 102     release(&cons.lock);
 103 }
 104 
 105 void
 106 panic(char *s)
 107 {
 108   int i;
 109   uint pcs[10];
 110   
 111   cli();
 112   cons.locking = 0;
 113   cprintf("cpu%d: panic: ", cpu->id);
 114   cprintf(s);
 115   cprintf("\n");
 116   getcallerpcs(&s, pcs);
 117   for(i=0; i<10; i++)
 118     cprintf(" %p", pcs[i]);
 119   panicked = 1; // freeze other CPU
 120   for(;;)
 121     ;
 122 }
 123 
 124 //PAGEBREAK: 50
 125 #define BACKSPACE 0x100
 126 #define CRTPORT 0x3d4
 127 static ushort *crt = (ushort*)P2V(0xb8000);  // CGA memory
 128 
 129 static void
 130 cgaputc(int c)
 131 {
 132   int pos;
 133   
 134   // Cursor position: col + 80*row.
 135   outb(CRTPORT, 14);
 136   pos = inb(CRTPORT+1) << 8;
 137   outb(CRTPORT, 15);
 138   pos |= inb(CRTPORT+1);
 139 
 140   if(c == '\n')
 141     pos += 80 - pos%80;
 142   else if(c == BACKSPACE){
 143     if(pos > 0) --pos;
 144   } else
 145     crt[pos++] = (c&0xff) | 0x0700;  // black on white
 146   
 147   if((pos/80) >= 24){  // Scroll up.
 148     memmove(crt, crt+80, sizeof(crt[0])*23*80);
 149     pos -= 80;
 150     memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos));
 151   }
 152   
 153   outb(CRTPORT, 14);
 154   outb(CRTPORT+1, pos>>8);
 155   outb(CRTPORT, 15);
 156   outb(CRTPORT+1, pos);
 157   crt[pos] = ' ' | 0x0700;
 158 }
 159 
 160 void
 161 consputc(int c)
 162 {
 163   if(panicked){
 164     cli();
 165     for(;;)
 166       ;
 167   }
 168 
 169   if(c == BACKSPACE){
 170     uartputc('\b'); uartputc(' '); uartputc('\b');
 171   } else
 172     uartputc(c);
 173   cgaputc(c);
 174 }
 175 
 176 #define INPUT_BUF 128
 177 struct {
 178   struct spinlock lock;
 179   char buf[INPUT_BUF];
 180   uint r;  // Read index
 181   uint w;  // Write index
 182   uint e;  // Edit index
 183 } input;
 184 
 185 #define C(x)  ((x)-'@')  // Control-x
 186 
 187 void
 188 consoleintr(int (*getc)(void))
 189 {
 190   int c;
 191 
 192   acquire(&input.lock);
 193   while((c = getc()) >= 0){
 194     switch(c){
 195     case C('P'):  // Process listing.
 196       procdump();
 197       break;
 198     case C('U'):  // Kill line.
 199       while(input.e != input.w &&
 200             input.buf[(input.e-1) % INPUT_BUF] != '\n'){
 201         input.e--;
 202         consputc(BACKSPACE);
 203       }
 204       break;
 205     case C('H'): case '\x7f':  // Backspace
 206       if(input.e != input.w){
 207         input.e--;
 208         consputc(BACKSPACE);
 209       }
 210       break;
 211     default:
 212       if(c != 0 && input.e-input.r < INPUT_BUF){
 213         c = (c == '\r') ? '\n' : c;
 214         input.buf[input.e++ % INPUT_BUF] = c;
 215         consputc(c);
 216         if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){
 217           input.w = input.e;
 218           wakeup(&input.r);
 219         }
 220       }
 221       break;
 222     }
 223   }
 224   release(&input.lock);
 225 }
 226 
 227 int
 228 consoleread(struct inode *ip, char *dst, int n)
 229 {
 230   uint target;
 231   int c;
 232 
 233   iunlock(ip);
 234   target = n;
 235   acquire(&input.lock);
 236   while(n > 0){
 237     while(input.r == input.w){
 238       if(proc->killed){
 239         release(&input.lock);
 240         ilock(ip);
 241         return -1;
 242       }
 243       sleep(&input.r, &input.lock);
 244     }
 245     c = input.buf[input.r++ % INPUT_BUF];
 246     if(c == C('D')){  // EOF
 247       if(n < target){
 248         // Save ^D for next time, to make sure
 249         // caller gets a 0-byte result.
 250         input.r--;
 251       }
 252       break;
 253     }
 254     *dst++ = c;
 255     --n;
 256     if(c == '\n')
 257       break;
 258   }
 259   release(&input.lock);
 260   ilock(ip);
 261 
 262   return target - n;
 263 }
 264 
 265 int
 266 consolewrite(struct inode *ip, char *buf, int n)
 267 {
 268   int i;
 269 
 270   iunlock(ip);
 271   acquire(&cons.lock);
 272   for(i = 0; i < n; i++)
 273     consputc(buf[i] & 0xff);
 274   release(&cons.lock);
 275   ilock(ip);
 276 
 277   return n;
 278 }
 279 
 280 void
 281 consoleinit(void)
 282 {
 283   initlock(&cons.lock, "console");
 284   initlock(&input.lock, "input");
 285 
 286   devsw[CONSOLE].write = consolewrite;
 287   devsw[CONSOLE].read = consoleread;
 288   cons.locking = 1;
 289 
 290   picenable(IRQ_KBD);
 291   ioapicenable(IRQ_KBD, 0);
 292 }
 293 

/* [<][>][^][v][top][bottom][index][help] */