Mercurial > hg > Members > innparusu > xv6-rpi
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 |