Xv6 with picoc & Linkage editor
v1.0
The project delineate mutual cohesion between c library, linkage editor ( linker), interpreter and operating system by porting the same on xv6 kernel
|
00001 // Console input and output. 00002 // Input is from the keyboard or serial port. 00003 // Output is written to the screen and serial port. 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 "memlayout.h" 00013 #include "mmu.h" 00014 #include "proc.h" 00015 #include "x86.h" 00016 00017 static void consputc(int); 00018 00019 static int panicked = 0; 00020 00021 static struct { 00022 struct spinlock lock; 00023 int locking; 00024 } cons; 00025 00026 static void 00027 printint(int xx, int base, int sign) 00028 { 00029 static char digits[] = "0123456789abcdef"; 00030 char buf[16]; 00031 int i; 00032 uint x; 00033 00034 if(sign && (sign = xx < 0)) 00035 x = -xx; 00036 else 00037 x = xx; 00038 00039 i = 0; 00040 do{ 00041 buf[i++] = digits[x % base]; 00042 }while((x /= base) != 0); 00043 00044 if(sign) 00045 buf[i++] = '-'; 00046 00047 while(--i >= 0) 00048 consputc(buf[i]); 00049 } 00050 //PAGEBREAK: 50 00051 00052 // Print to the console. only understands %d, %x, %p, %s. 00053 void 00054 cprintf(char *fmt, ...) 00055 { 00056 int i, c, locking; 00057 uint *argp; 00058 char *s; 00059 00060 locking = cons.locking; 00061 if(locking) 00062 acquire(&cons.lock); 00063 00064 if (fmt == 0) 00065 panic("null fmt"); 00066 00067 argp = (uint*)(void*)(&fmt + 1); 00068 for(i = 0; (c = fmt[i] & 0xff) != 0; i++){ 00069 if(c != '%'){ 00070 consputc(c); 00071 continue; 00072 } 00073 c = fmt[++i] & 0xff; 00074 if(c == 0) 00075 break; 00076 switch(c){ 00077 case 'd': 00078 printint(*argp++, 10, 1); 00079 break; 00080 case 'x': 00081 case 'p': 00082 printint(*argp++, 16, 0); 00083 break; 00084 case 's': 00085 if((s = (char*)*argp++) == 0) 00086 s = "(null)"; 00087 for(; *s; s++) 00088 consputc(*s); 00089 break; 00090 case '%': 00091 consputc('%'); 00092 break; 00093 default: 00094 // Print unknown % sequence to draw attention. 00095 consputc('%'); 00096 consputc(c); 00097 break; 00098 } 00099 } 00100 00101 if(locking) 00102 release(&cons.lock); 00103 } 00104 00105 void 00106 panic(char *s) 00107 { 00108 int i; 00109 uint pcs[10]; 00110 00111 cli(); 00112 cons.locking = 0; 00113 cprintf("cpu%d: panic: ", cpu->id); 00114 cprintf(s); 00115 cprintf("\n"); 00116 getcallerpcs(&s, pcs); 00117 for(i=0; i<10; i++) 00118 cprintf(" %p", pcs[i]); 00119 panicked = 1; // freeze other CPU 00120 for(;;) 00121 ; 00122 } 00123 00124 //PAGEBREAK: 50 00125 #define BACKSPACE 0x100 00126 #define CRTPORT 0x3d4 00127 static ushort *crt = (ushort*)P2V(0xb8000); // CGA memory 00128 00129 static void 00130 cgaputc(int c) 00131 { 00132 int pos; 00133 00134 // Cursor position: col + 80*row. 00135 outb(CRTPORT, 14); 00136 pos = inb(CRTPORT+1) << 8; 00137 outb(CRTPORT, 15); 00138 pos |= inb(CRTPORT+1); 00139 00140 if(c == '\n') 00141 pos += 80 - pos%80; 00142 else if(c == BACKSPACE){ 00143 if(pos > 0) --pos; 00144 } else 00145 crt[pos++] = (c&0xff) | 0x0700; // black on white 00146 00147 if((pos/80) >= 24){ // Scroll up. 00148 memmove(crt, crt+80, sizeof(crt[0])*23*80); 00149 pos -= 80; 00150 memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos)); 00151 } 00152 00153 outb(CRTPORT, 14); 00154 outb(CRTPORT+1, pos>>8); 00155 outb(CRTPORT, 15); 00156 outb(CRTPORT+1, pos); 00157 crt[pos] = ' ' | 0x0700; 00158 } 00159 00160 void 00161 consputc(int c) 00162 { 00163 if(panicked){ 00164 cli(); 00165 for(;;) 00166 ; 00167 } 00168 00169 if(c == BACKSPACE){ 00170 uartputc('\b'); uartputc(' '); uartputc('\b'); 00171 } else 00172 uartputc(c); 00173 cgaputc(c); 00174 } 00175 00176 #define INPUT_BUF 128 00177 struct { 00178 struct spinlock lock; 00179 char buf[INPUT_BUF]; 00180 uint r; // Read index 00181 uint w; // Write index 00182 uint e; // Edit index 00183 } input; 00184 00185 #define C(x) ((x)-'@') // Control-x 00186 00187 void 00188 consoleintr(int (*getc)(void)) 00189 { 00190 int c; 00191 00192 acquire(&input.lock); 00193 while((c = getc()) >= 0){ 00194 switch(c){ 00195 case C('P'): // Process listing. 00196 procdump(); 00197 break; 00198 case C('U'): // Kill line. 00199 while(input.e != input.w && 00200 input.buf[(input.e-1) % INPUT_BUF] != '\n'){ 00201 input.e--; 00202 consputc(BACKSPACE); 00203 } 00204 break; 00205 case C('H'): case '\x7f': // Backspace 00206 if(input.e != input.w){ 00207 input.e--; 00208 consputc(BACKSPACE); 00209 } 00210 break; 00211 default: 00212 if(c != 0 && input.e-input.r < INPUT_BUF){ 00213 c = (c == '\r') ? '\n' : c; 00214 input.buf[input.e++ % INPUT_BUF] = c; 00215 consputc(c); 00216 if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){ 00217 input.w = input.e; 00218 wakeup(&input.r); 00219 } 00220 } 00221 break; 00222 } 00223 } 00224 release(&input.lock); 00225 } 00226 00227 int 00228 consoleread(struct inode *ip, char *dst, int n) 00229 { 00230 uint target; 00231 int c; 00232 00233 iunlock(ip); 00234 target = n; 00235 acquire(&input.lock); 00236 while(n > 0){ 00237 while(input.r == input.w){ 00238 if(proc->killed){ 00239 release(&input.lock); 00240 ilock(ip); 00241 return -1; 00242 } 00243 sleep(&input.r, &input.lock); 00244 } 00245 c = input.buf[input.r++ % INPUT_BUF]; 00246 if(c == C('D')){ // EOF 00247 if(n < target){ 00248 // Save ^D for next time, to make sure 00249 // caller gets a 0-byte result. 00250 input.r--; 00251 } 00252 break; 00253 } 00254 *dst++ = c; 00255 --n; 00256 if(c == '\n') 00257 break; 00258 } 00259 release(&input.lock); 00260 ilock(ip); 00261 00262 return target - n; 00263 } 00264 00265 int 00266 consolewrite(struct inode *ip, char *buf, int n) 00267 { 00268 int i; 00269 00270 iunlock(ip); 00271 acquire(&cons.lock); 00272 for(i = 0; i < n; i++) 00273 consputc(buf[i] & 0xff); 00274 release(&cons.lock); 00275 ilock(ip); 00276 00277 return n; 00278 } 00279 00280 void 00281 consoleinit(void) 00282 { 00283 initlock(&cons.lock, "console"); 00284 initlock(&input.lock, "input"); 00285 00286 devsw[CONSOLE].write = consolewrite; 00287 devsw[CONSOLE].read = consoleread; 00288 cons.locking = 1; 00289 00290 picenable(IRQ_KBD); 00291 ioapicenable(IRQ_KBD, 0); 00292 } 00293