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