comparison src/console.c @ 0:83c23a36980d

Init
author Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
date Fri, 26 May 2017 23:11:05 +0900
parents
children 36bd61f5c847
comparison
equal deleted inserted replaced
-1:000000000000 0:83c23a36980d
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 static void consputc (int);
16
17 static int panicked = 0;
18
19 static struct {
20 struct spinlock lock;
21 int locking;
22 } cons;
23
24 static void printint (int xx, int base, int sign)
25 {
26 static char digits[] = "0123456789abcdef";
27 char buf[16];
28 int i;
29 uint x;
30
31 if (sign && (sign = xx < 0)) {
32 x = -xx;
33 } else {
34 x = xx;
35 }
36
37 i = 0;
38
39 do {
40 buf[i++] = digits[x % base];
41 } while ((x /= base) != 0);
42
43 if (sign) {
44 buf[i++] = '-';
45 }
46
47 while (--i >= 0) {
48 consputc(buf[i]);
49 }
50 }
51 //PAGEBREAK: 50
52
53 // Print to the console. only understands %d, %x, %p, %s.
54 void cprintf (char *fmt, ...)
55 {
56 int i, c, locking;
57 uint *argp;
58 char *s;
59
60 locking = cons.locking;
61
62 if (locking) {
63 acquire(&cons.lock);
64 }
65
66 if (fmt == 0) {
67 panic("null fmt");
68 }
69
70 argp = (uint*) (void*) (&fmt + 1);
71
72 for (i = 0; (c = fmt[i] & 0xff) != 0; i++) {
73 if (c != '%') {
74 consputc(c);
75 continue;
76 }
77
78 c = fmt[++i] & 0xff;
79
80 if (c == 0) {
81 break;
82 }
83
84 switch (c) {
85 case 'd':
86 printint(*argp++, 10, 1);
87 break;
88
89 case 'x':
90 case 'p':
91 printint(*argp++, 16, 0);
92 break;
93
94 case 's':
95 if ((s = (char*) *argp++) == 0) {
96 s = "(null)";
97 }
98
99 for (; *s; s++) {
100 consputc(*s);
101 }
102 break;
103
104 case '%':
105 consputc('%');
106 break;
107
108 default:
109 // Print unknown % sequence to draw attention.
110 consputc('%');
111 consputc(c);
112 break;
113 }
114 }
115
116 if (locking) {
117 release(&cons.lock);
118 }
119 }
120
121 void panic (char *s)
122 {
123 cli();
124
125 cons.locking = 0;
126
127 cprintf("cpu%d: panic: ", cpu->id);
128
129 show_callstk(s);
130 panicked = 1; // freeze other CPU
131
132 while (1)
133 ;
134 }
135
136 //PAGEBREAK: 50
137 #define BACKSPACE 0x100
138 #define CRTPORT 0x3d4
139
140 void consputc (int c)
141 {
142 if (panicked) {
143 cli();
144 while (1)
145 ;
146 }
147
148 if (c == BACKSPACE) {
149 uartputc('\b');
150 uartputc(' ');
151 uartputc('\b');
152 } else {
153 uartputc(c);
154 }
155
156 // cgaputc(c);
157 }
158
159 #define INPUT_BUF 512
160 struct {
161 struct spinlock lock;
162 char buf[INPUT_BUF];
163 uint r; // Read index
164 uint w; // Write index
165 uint e; // Edit index
166 } input;
167
168 #define C(x) ((x)-'@') // Control-x
169 void consoleintr (int (*getc) (void))
170 {
171 int c;
172
173 acquire(&input.lock);
174
175 while ((c = getc()) >= 0) {
176 switch (c) {
177 case C('P'): // Process listing.
178 procdump();
179 break;
180
181 case C('U'): // Kill line.
182 while ((input.e != input.w) && (input.buf[(input.e - 1) % INPUT_BUF] != '\n')) {
183 input.e--;
184 consputc(BACKSPACE);
185 }
186
187 break;
188
189 case C('H'):
190 case '\x7f': // Backspace
191 if (input.e != input.w) {
192 input.e--;
193 consputc(BACKSPACE);
194 }
195
196 break;
197
198 default:
199 if ((c != 0) && (input.e - input.r < INPUT_BUF)) {
200 c = (c == '\r') ? '\n' : c;
201
202 input.buf[input.e++ % INPUT_BUF] = c;
203 consputc(c);
204
205 if (c == '\n' || c == C('D') || input.e == input.r + INPUT_BUF) {
206 input.w = input.e;
207 wakeup(&input.r);
208 }
209 }
210
211 break;
212 }
213 }
214
215 release(&input.lock);
216 }
217
218 int consoleread (struct inode *ip, char *dst, int n)
219 {
220 uint target;
221 int c;
222
223 iunlock(ip);
224
225 target = n;
226 acquire(&input.lock);
227
228 while (n > 0) {
229 while (input.r == input.w) {
230 if (proc->killed) {
231 release(&input.lock);
232 ilock(ip);
233 return -1;
234 }
235
236 sleep(&input.r, &input.lock);
237 }
238
239 c = input.buf[input.r++ % INPUT_BUF];
240
241 if (c == C('D')) { // EOF
242 if (n < target) {
243 // Save ^D for next time, to make sure
244 // caller gets a 0-byte result.
245 input.r--;
246 }
247
248 break;
249 }
250
251 *dst++ = c;
252 --n;
253
254 if (c == '\n') {
255 break;
256 }
257 }
258
259 release(&input.lock);
260 ilock(ip);
261
262 return target - n;
263 }
264
265 int consolewrite (struct inode *ip, char *buf, int n)
266 {
267 int i;
268
269 iunlock(ip);
270
271 acquire(&cons.lock);
272
273 for (i = 0; i < n; i++) {
274 consputc(buf[i] & 0xff);
275 }
276
277 release(&cons.lock);
278
279 ilock(ip);
280
281 return n;
282 }
283
284 void consoleinit (void)
285 {
286 initlock(&cons.lock, "console");
287 initlock(&input.lock, "input");
288
289 devsw[CONSOLE].write = consolewrite;
290 devsw[CONSOLE].read = consoleread;
291
292 cons.locking = 1;
293 }
294