comparison src/console.cbc @ 41:087d7b61c86b

cbc cmake version
author kono
date Sat, 02 Mar 2019 19:01:03 +0900
parents src/console.c@a7144583914c
children
comparison
equal deleted inserted replaced
40:162d92edbb0a 41:087d7b61c86b
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 "spinlock.h"
9 #include "fs.h"
10 #include "file.h"
11 #include "memlayout.h"
12 #include "mmu.h"
13 #include "proc.h"
14
15 __code cbc_consoleread1 ();
16 __code cbc_consoleread2 ();
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 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
40 i = 0;
41
42 do {
43 buf[i++] = digits[x % base];
44 } while ((x /= base) != 0);
45
46 if (sign) {
47 buf[i++] = '-';
48 }
49
50 while (--i >= 0) {
51 consputc(buf[i]);
52 }
53 }
54 //PAGEBREAK: 50
55
56 // Print to the console. only understands %d, %x, %p, %s.
57 void cprintf (char *fmt, ...)
58 {
59 int i, c, locking;
60 uint *argp;
61 char *s;
62
63 locking = cons.locking;
64
65 if (locking) {
66 acquire(&cons.lock);
67 }
68
69 if (fmt == 0) {
70 panic("null fmt");
71 }
72
73 argp = (uint*) (void*) (&fmt + 1);
74
75 for (i = 0; (c = fmt[i] & 0xff) != 0; i++) {
76 if (c != '%') {
77 consputc(c);
78 continue;
79 }
80
81 c = fmt[++i] & 0xff;
82
83 if (c == 0) {
84 break;
85 }
86
87 switch (c) {
88 case 'd':
89 printint(*argp++, 10, 1);
90 break;
91
92 case 'x':
93 case 'p':
94 printint(*argp++, 16, 0);
95 break;
96
97 case 's':
98 if ((s = (char*) *argp++) == 0) {
99 s = "(null)";
100 }
101
102 for (; *s; s++) {
103 consputc(*s);
104 }
105 break;
106
107 case '%':
108 consputc('%');
109 break;
110
111 default:
112 // Print unknown % sequence to draw attention.
113 consputc('%');
114 consputc(c);
115 break;
116 }
117 }
118
119 if (locking) {
120 release(&cons.lock);
121 }
122 }
123
124 __code cbc_panic (char *s)
125 {
126 cli();
127
128 cons.locking = 0;
129
130 cprintf("cpu%d: panic: ", cpu->id);
131
132 show_callstk(s);
133 panicked = 1; // freeze other CPU
134
135 while (1)
136 ;
137 }
138
139 void panic (char *s)
140 {
141 cli();
142
143 cons.locking = 0;
144
145 cprintf("cpu%d: panic: ", cpu->id);
146
147 show_callstk(s);
148 panicked = 1; // freeze other CPU
149
150 while (1)
151 ;
152 }
153
154 //PAGEBREAK: 50
155 #define BACKSPACE 0x100
156 #define CRTPORT 0x3d4
157
158 void consputc (int c)
159 {
160 if (panicked) {
161 cli();
162 while (1)
163 ;
164 }
165
166 if (c == BACKSPACE) {
167 uartputc('\b');
168 uartputc(' ');
169 uartputc('\b');
170 } else {
171 uartputc(c);
172 }
173
174 // cgaputc(c);
175 }
176
177 #define INPUT_BUF 512
178 struct {
179 struct spinlock lock;
180 char buf[INPUT_BUF];
181 uint r; // Read index
182 uint w; // Write index
183 uint e; // Edit index
184 } input;
185
186 #define C(x) ((x)-'@') // Control-x
187 void consoleintr (int (*getc) (void))
188 {
189 int c;
190
191 acquire(&input.lock);
192
193 while ((c = getc()) >= 0) {
194 switch (c) {
195 case C('P'): // Process listing.
196 procdump();
197 break;
198
199 case C('U'): // Kill line.
200 while ((input.e != input.w) && (input.buf[(input.e - 1) % INPUT_BUF] != '\n')) {
201 input.e--;
202 consputc(BACKSPACE);
203 }
204
205 break;
206
207 case C('H'):
208 case '\x7f': // Backspace
209 if (input.e != input.w) {
210 input.e--;
211 consputc(BACKSPACE);
212 }
213
214 break;
215
216 default:
217 if ((c != 0) && (input.e - input.r < INPUT_BUF)) {
218 c = (c == '\r') ? '\n' : c;
219
220 input.buf[input.e++ % INPUT_BUF] = c;
221 consputc(c);
222
223 if (c == '\n' || c == C('D') || input.e == input.r + INPUT_BUF) {
224 input.w = input.e;
225 wakeup(&input.r);
226 }
227 }
228
229 break;
230 }
231 }
232
233 release(&input.lock);
234 }
235
236 __code cbc_consoleread2 ()
237 {
238 struct inode *ip = proc->cbc_arg.cbc_console_arg.ip;
239 __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next;
240 if (input.r == input.w) {
241 if (proc->killed) {
242 release(&input.lock);
243 ilock(ip);
244 goto next(-1);
245 }
246 goto cbc_sleep(&input.r, &input.lock, cbc_consoleread2);
247 }
248 goto cbc_consoleread1();
249 }
250
251 __code cbc_consoleread1 ()
252 {
253 int cont = 1;
254 int n = proc->cbc_arg.cbc_console_arg.n;
255 int target = proc->cbc_arg.cbc_console_arg.target;
256 char* dst = proc->cbc_arg.cbc_console_arg.dst;
257 struct inode *ip = proc->cbc_arg.cbc_console_arg.ip;
258 __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next;
259
260 int c = input.buf[input.r++ % INPUT_BUF];
261
262 if (c == C('D')) { // EOF
263 if (n < target) {
264 // Save ^D for next time, to make sure
265 // caller gets a 0-byte result.
266 input.r--;
267 }
268 cont = 0;
269 }
270
271 *dst++ = c;
272 --n;
273
274 if (c == '\n') {
275 cont = 0;
276 }
277
278 if (cont == 1) {
279 if (n > 0) {
280 proc->cbc_arg.cbc_console_arg.n = n;
281 proc->cbc_arg.cbc_console_arg.target = target;
282 proc->cbc_arg.cbc_console_arg.dst = dst;
283 proc->cbc_arg.cbc_console_arg.ip = ip;
284 proc->cbc_arg.cbc_console_arg.next = next;
285 goto cbc_sleep(&input.r, &input.lock, cbc_consoleread2);
286 }
287 }
288
289 release(&input.lock);
290 ilock(ip);
291
292 goto next(target - n);
293 }
294
295 __code cbc_consoleread (struct inode *ip, char *dst, int n, __code(*next)(int ret))
296 {
297 uint target;
298
299 iunlock(ip);
300
301 target = n;
302 acquire(&input.lock);
303
304 if (n > 0) {
305 proc->cbc_arg.cbc_console_arg.n = n;
306 proc->cbc_arg.cbc_console_arg.target = target;
307 proc->cbc_arg.cbc_console_arg.dst = dst;
308 proc->cbc_arg.cbc_console_arg.ip = ip;
309 proc->cbc_arg.cbc_console_arg.next = next;
310 goto cbc_consoleread2();
311 }
312 goto cbc_consoleread1();
313 }
314
315 int consoleread (struct inode *ip, char *dst, int n)
316 {
317 uint target;
318 int c;
319
320 iunlock(ip);
321
322 target = n;
323 acquire(&input.lock);
324
325 while (n > 0) {
326 while (input.r == input.w) {
327 if (proc->killed) {
328 release(&input.lock);
329 ilock(ip);
330 return -1;
331 }
332
333 sleep(&input.r, &input.lock);
334 }
335
336 c = input.buf[input.r++ % INPUT_BUF];
337
338 if (c == C('D')) { // EOF
339 if (n < target) {
340 // Save ^D for next time, to make sure
341 // caller gets a 0-byte result.
342 input.r--;
343 }
344
345 break;
346 }
347
348 *dst++ = c;
349 --n;
350
351 if (c == '\n') {
352 break;
353 }
354 }
355
356 release(&input.lock);
357 ilock(ip);
358
359 return target - n;
360 }
361
362 int consolewrite (struct inode *ip, char *buf, int n)
363 {
364 int i;
365
366 iunlock(ip);
367
368 acquire(&cons.lock);
369
370 for (i = 0; i < n; i++) {
371 consputc(buf[i] & 0xff);
372 }
373
374 release(&cons.lock);
375
376 ilock(ip);
377
378 return n;
379 }
380
381 void consoleinit (void)
382 {
383 initlock(&cons.lock, "console");
384 initlock(&input.lock, "input");
385
386 devsw[CONSOLE].write = consolewrite;
387 devsw[CONSOLE].read = consoleread;
388 //cbc_devsw[CONSOLE].write = cbc_consolewrite;
389 cbc_devsw[CONSOLE].read = cbc_consoleread;
390
391 cons.locking = 1;
392 }
393