root/console.c

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

/* [previous][next][first][last][top][bottom][index][help]  */