00001
00002
00003
00004
00005 #include "types.h"
00006 #include "defs.h"
00007 #include "param.h"
00008 #include "traps.h"
00009 #include "spinlock.h"
00010 #include "fs.h"
00011 #include "file.h"
00012 #include "mmu.h"
00013 #include "proc.h"
00014 #include "x86.h"
00015
00016 static void consputc(int);
00017
00018 static int panicked = 0;
00019
00020 static struct {
00021 struct spinlock lock;
00022 int locking;
00023 } cons;
00024
00025 static void
00026 printint(int xx, int base, int sgn)
00027 {
00028 static char digits[] = "0123456789abcdef";
00029 char buf[16];
00030 int i = 0, neg = 0;
00031 uint x;
00032
00033 if(sgn && xx < 0){
00034 neg = 1;
00035 x = -xx;
00036 } else
00037 x = xx;
00038
00039 do{
00040 buf[i++] = digits[x % base];
00041 }while((x /= base) != 0);
00042 if(neg)
00043 buf[i++] = '-';
00044
00045 while(--i >= 0)
00046 consputc(buf[i]);
00047 }
00048
00049
00050 void
00051 cprintf(char *fmt, ...)
00052 {
00053 int i, c, state, locking;
00054 uint *argp;
00055 char *s;
00056
00057 locking = cons.locking;
00058 if(locking)
00059 acquire(&cons.lock);
00060
00061 argp = (uint*)(void*)(&fmt + 1);
00062 state = 0;
00063 for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
00064 if(c != '%'){
00065 consputc(c);
00066 continue;
00067 }
00068 c = fmt[++i] & 0xff;
00069 if(c == 0)
00070 break;
00071 switch(c){
00072 case 'd':
00073 printint(*argp++, 10, 1);
00074 break;
00075 case 'x':
00076 case 'p':
00077 printint(*argp++, 16, 0);
00078 break;
00079 case 's':
00080 if((s = (char*)*argp++) == 0)
00081 s = "(null)";
00082 for(; *s; s++)
00083 consputc(*s);
00084 break;
00085 case '%':
00086 consputc('%');
00087 break;
00088 default:
00089
00090 consputc('%');
00091 consputc(c);
00092 break;
00093 }
00094 }
00095
00096 if(locking)
00097 release(&cons.lock);
00098 }
00099
00100 void
00101 panic(char *s)
00102 {
00103 int i;
00104 uint pcs[10];
00105
00106 cli();
00107 cons.locking = 0;
00108 cprintf("cpu%d: panic: ", cpu->id);
00109 cprintf(s);
00110 cprintf("\n");
00111 getcallerpcs(&s, pcs);
00112 for(i=0; i<10; i++)
00113 cprintf(" %p", pcs[i]);
00114 panicked = 1;
00115 for(;;)
00116 ;
00117 }
00118
00119 #define BACKSPACE 0x100
00120 #define CRTPORT 0x3d4
00121 static ushort *crt = (ushort*)0xb8000;
00122
00123 static void
00124 cgaputc(int c)
00125 {
00126 int pos;
00127
00128
00129 outb(CRTPORT, 14);
00130 pos = inb(CRTPORT+1) << 8;
00131 outb(CRTPORT, 15);
00132 pos |= inb(CRTPORT+1);
00133
00134 if(c == '\n')
00135 pos += 80 - pos%80;
00136 else if(c == BACKSPACE){
00137 if(pos > 0)
00138 crt[--pos] = ' ' | 0x0700;
00139 } else
00140 crt[pos++] = (c&0xff) | 0x0700;
00141
00142 if((pos/80) >= 24){
00143 memmove(crt, crt+80, sizeof(crt[0])*23*80);
00144 pos -= 80;
00145 memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos));
00146 }
00147
00148 outb(CRTPORT, 14);
00149 outb(CRTPORT+1, pos>>8);
00150 outb(CRTPORT, 15);
00151 outb(CRTPORT+1, pos);
00152 crt[pos] = ' ' | 0x0700;
00153 }
00154
00155 void
00156 consputc(int c)
00157 {
00158 if(panicked){
00159 cli();
00160 for(;;)
00161 ;
00162 }
00163
00164 uartputc(c);
00165 cgaputc(c);
00166 }
00167
00168 #define INPUT_BUF 128
00169 struct {
00170 struct spinlock lock;
00171 char buf[INPUT_BUF];
00172 uint r;
00173 uint w;
00174 uint e;
00175 } input;
00176
00177 #define C(x) ((x)-'@') // Control-x
00178
00179 void
00180 consoleintr(int (*getc)(void))
00181 {
00182 int c;
00183
00184 acquire(&input.lock);
00185 while((c = getc()) >= 0){
00186 switch(c){
00187 case C('P'):
00188 procdump();
00189 break;
00190 case C('U'):
00191 while(input.e != input.w &&
00192 input.buf[(input.e-1) % INPUT_BUF] != '\n'){
00193 input.e--;
00194 consputc(BACKSPACE);
00195 }
00196 break;
00197 case C('H'):
00198 if(input.e != input.w){
00199 input.e--;
00200 consputc(BACKSPACE);
00201 }
00202 break;
00203 default:
00204 if(c != 0 && input.e-input.r < INPUT_BUF){
00205 input.buf[input.e++ % INPUT_BUF] = c;
00206 consputc(c);
00207 if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){
00208 input.w = input.e;
00209 wakeup(&input.r);
00210 }
00211 }
00212 break;
00213 }
00214 }
00215 release(&input.lock);
00216 }
00217
00218 int
00219 consoleread(struct inode *ip, char *dst, int n)
00220 {
00221 uint target;
00222 int c;
00223
00224 iunlock(ip);
00225 target = n;
00226 acquire(&input.lock);
00227 while(n > 0){
00228 while(input.r == input.w){
00229 if(proc->killed){
00230 release(&input.lock);
00231 ilock(ip);
00232 return -1;
00233 }
00234 sleep(&input.r, &input.lock);
00235 }
00236 c = input.buf[input.r++ % INPUT_BUF];
00237 if(c == C('D')){
00238 if(n < target){
00239
00240
00241 input.r--;
00242 }
00243 break;
00244 }
00245 *dst++ = c;
00246 --n;
00247 if(c == '\n')
00248 break;
00249 }
00250 release(&input.lock);
00251 ilock(ip);
00252
00253 return target - n;
00254 }
00255
00256 int
00257 consolewrite(struct inode *ip, char *buf, int n)
00258 {
00259 int i;
00260
00261 iunlock(ip);
00262 acquire(&cons.lock);
00263 for(i = 0; i < n; i++)
00264 consputc(buf[i] & 0xff);
00265 release(&cons.lock);
00266 ilock(ip);
00267
00268 return n;
00269 }
00270
00271 void
00272 consoleinit(void)
00273 {
00274 initlock(&cons.lock, "console");
00275 initlock(&input.lock, "input");
00276
00277 devsw[CONSOLE].write = consolewrite;
00278 devsw[CONSOLE].read = consoleread;
00279 cons.locking = 1;
00280
00281 picenable(IRQ_KBD);
00282 ioapicenable(IRQ_KBD, 0);
00283 }
00284