* more re-work
[mascara-docs.git] / i386 / junos / ucla / src / lab4 / kern / console.c
blob24bff351eeae81068bcc9c149543ddaa0df54bd2
1 /* See COPYRIGHT for copyright information. */
3 #include <inc/x86.h>
4 #include <inc/memlayout.h>
5 #include <inc/kbdreg.h>
6 #include <inc/string.h>
7 #include <inc/assert.h>
9 #include <kern/console.h>
10 #include <kern/picirq.h>
12 static void cons_intr(int (*proc)(void));
13 static void cons_putc(int c);
15 // Stupid I/O delay routine necessitated by historical PC design flaws
16 static void
17 delay(void)
19 inb(0x84);
20 inb(0x84);
21 inb(0x84);
22 inb(0x84);
25 /***** Serial I/O code *****/
27 #define COM1 0x3F8
29 #define COM_RX 0 // In: Receive buffer (DLAB=0)
30 #define COM_TX 0 // Out: Transmit buffer (DLAB=0)
31 #define COM_DLL 0 // Out: Divisor Latch Low (DLAB=1)
32 #define COM_DLM 1 // Out: Divisor Latch High (DLAB=1)
33 #define COM_IER 1 // Out: Interrupt Enable Register
34 #define COM_IER_RDI 0x01 // Enable receiver data interrupt
35 #define COM_IIR 2 // In: Interrupt ID Register
36 #define COM_FCR 2 // Out: FIFO Control Register
37 #define COM_LCR 3 // Out: Line Control Register
38 #define COM_LCR_DLAB 0x80 // Divisor latch access bit
39 #define COM_LCR_WLEN8 0x03 // Wordlength: 8 bits
40 #define COM_MCR 4 // Out: Modem Control Register
41 #define COM_MCR_RTS 0x02 // RTS complement
42 #define COM_MCR_DTR 0x01 // DTR complement
43 #define COM_MCR_OUT2 0x08 // Out2 complement
44 #define COM_LSR 5 // In: Line Status Register
45 #define COM_LSR_DATA 0x01 // Data available
46 #define COM_LSR_TXRDY 0x20 // Transmit buffer avail
47 #define COM_LSR_TSRE 0x40 // Transmitter off
49 static bool serial_exists;
51 static int
52 serial_proc_data(void)
54 if (!(inb(COM1+COM_LSR) & COM_LSR_DATA))
55 return -1;
56 return inb(COM1+COM_RX);
59 void
60 serial_intr(void)
62 if (serial_exists)
63 cons_intr(serial_proc_data);
66 static void
67 serial_putc(int c)
69 int i;
71 for (i = 0;
72 !(inb(COM1 + COM_LSR) & COM_LSR_TXRDY) && i < 12800;
73 i++)
74 delay();
76 outb(COM1 + COM_TX, c);
79 static void
80 serial_init(void)
82 // Turn off the FIFO
83 outb(COM1+COM_FCR, 0);
85 // Set speed; requires DLAB latch
86 outb(COM1+COM_LCR, COM_LCR_DLAB);
87 outb(COM1+COM_DLL, (uint8_t) (115200 / 9600));
88 outb(COM1+COM_DLM, 0);
90 // 8 data bits, 1 stop bit, parity off; turn off DLAB latch
91 outb(COM1+COM_LCR, COM_LCR_WLEN8 & ~COM_LCR_DLAB);
93 // No modem controls
94 outb(COM1+COM_MCR, 0);
95 // Enable rcv interrupts
96 outb(COM1+COM_IER, COM_IER_RDI);
98 // Clear any preexisting overrun indications and interrupts
99 // Serial port doesn't exist if COM_LSR returns 0xFF
100 serial_exists = (inb(COM1+COM_LSR) != 0xFF);
101 (void) inb(COM1+COM_IIR);
102 (void) inb(COM1+COM_RX);
108 /***** Parallel port output code *****/
109 // For information on PC parallel port programming, see the class References
110 // page.
112 static void
113 lpt_putc(int c)
115 int i;
117 for (i = 0; !(inb(0x378+1) & 0x80) && i < 12800; i++)
118 delay();
119 outb(0x378+0, c);
120 outb(0x378+2, 0x08|0x04|0x01);
121 outb(0x378+2, 0x08);
127 /***** Text-mode CGA/VGA display output *****/
129 static unsigned addr_6845;
130 static uint16_t *crt_buf;
131 static uint16_t crt_pos;
133 // Scrollback support
134 #define CRT_SAVEROWS 128
136 #if CRT_SAVEROWS > 0
137 static uint16_t crtsave_buf[CRT_SAVEROWS * CRT_COLS];
138 static uint16_t crtsave_pos;
139 static int16_t crtsave_backscroll;
140 static uint16_t crtsave_size;
141 #endif
143 static void
144 cga_init(void)
146 volatile uint16_t *cp;
147 uint16_t was;
148 unsigned pos;
150 cp = (uint16_t*) (KERNBASE + CGA_BUF);
151 was = *cp;
152 *cp = (uint16_t) 0xA55A;
153 if (*cp != 0xA55A) {
154 cp = (uint16_t*) (KERNBASE + MONO_BUF);
155 addr_6845 = MONO_BASE;
156 } else {
157 *cp = was;
158 addr_6845 = CGA_BASE;
161 /* Extract cursor location */
162 outb(addr_6845, 14);
163 pos = inb(addr_6845 + 1) << 8;
164 outb(addr_6845, 15);
165 pos |= inb(addr_6845 + 1);
167 crt_buf = (uint16_t*) cp;
168 crt_pos = pos;
172 #if CRT_SAVEROWS > 0
173 // Copy one screen's worth of data to or from the save buffer,
174 // starting at line 'first_line'.
175 static void
176 cga_savebuf_copy(int first_line, bool to_screen)
178 uint16_t *pos;
179 uint16_t *end;
180 uint16_t *trueend;
182 // Calculate the beginning & end of the save buffer area.
183 pos = crtsave_buf + (first_line % CRT_SAVEROWS) * CRT_COLS;
184 end = pos + CRT_ROWS * CRT_COLS;
185 // Check for wraparound.
186 trueend = MIN(end, crtsave_buf + CRT_SAVEROWS * CRT_COLS);
188 // Copy the initial portion.
189 if (to_screen)
190 memmove(crt_buf, pos, (trueend - pos) * sizeof(uint16_t));
191 else
192 memmove(pos, crt_buf, (trueend - pos) * sizeof(uint16_t));
194 // If there was wraparound, copy the second part of the screen.
195 if (end == trueend)
196 /* do nothing */;
197 else if (to_screen)
198 memmove(crt_buf + (trueend - pos), crtsave_buf, (end - trueend) * sizeof(uint16_t));
199 else
200 memmove(crtsave_buf, crt_buf + (trueend - pos), (end - trueend) * sizeof(uint16_t));
203 #endif
205 static void
206 cga_putc(int c)
208 #if CRT_SAVEROWS > 0
209 // unscroll if necessary
210 if (crtsave_backscroll > 0) {
211 cga_savebuf_copy(crtsave_pos + crtsave_size, 1);
212 crtsave_backscroll = 0;
215 #endif
216 // if no attribute given, then use black on white
217 if (!(c & ~0xFF))
218 c |= 0x0700;
220 switch (c & 0xff) {
221 case '\b':
222 if (crt_pos > 0) {
223 crt_pos--;
224 crt_buf[crt_pos] = (c & ~0xff) | ' ';
226 break;
227 case '\n':
228 crt_pos += CRT_COLS;
229 /* fallthru */
230 case '\r':
231 crt_pos -= (crt_pos % CRT_COLS);
232 break;
233 case '\t':
234 cons_putc(' ');
235 cons_putc(' ');
236 cons_putc(' ');
237 cons_putc(' ');
238 cons_putc(' ');
239 break;
240 default:
241 crt_buf[crt_pos++] = c; /* write the character */
242 break;
245 // What is the purpose of this?
246 if (crt_pos >= CRT_SIZE) {
247 int i;
249 #if CRT_SAVEROWS > 0
250 // Save the scrolled-back row
251 if (crtsave_size == CRT_SAVEROWS - CRT_ROWS)
252 crtsave_pos = (crtsave_pos + 1) % CRT_SAVEROWS;
253 else
254 crtsave_size++;
255 memmove(crtsave_buf + ((crtsave_pos + crtsave_size - 1) % CRT_SAVEROWS) * CRT_COLS, crt_buf, CRT_COLS * sizeof(uint16_t));
257 #endif
258 memmove(crt_buf, crt_buf + CRT_COLS, (CRT_SIZE - CRT_COLS) * sizeof(uint16_t));
259 for (i = CRT_SIZE - CRT_COLS; i < CRT_SIZE; i++)
260 crt_buf[i] = 0x0700 | ' ';
261 crt_pos -= CRT_COLS;
264 /* move that little blinky thing */
265 outb(addr_6845, 14);
266 outb(addr_6845 + 1, crt_pos >> 8);
267 outb(addr_6845, 15);
268 outb(addr_6845 + 1, crt_pos);
271 #if CRT_SAVEROWS > 0
272 static void
273 cga_scroll(int delta)
275 int new_backscroll = MAX(MIN(crtsave_backscroll - delta, crtsave_size), 0);
277 if (new_backscroll == crtsave_backscroll)
278 return;
279 if (crtsave_backscroll == 0)
280 // save current screen
281 cga_savebuf_copy(crtsave_pos + crtsave_size, 0);
283 crtsave_backscroll = new_backscroll;
284 cga_savebuf_copy(crtsave_pos + crtsave_size - crtsave_backscroll, 1);
287 #endif
289 /***** Keyboard input code *****/
291 #define NO 0
293 #define SHIFT (1<<0)
294 #define CTL (1<<1)
295 #define ALT (1<<2)
297 #define CAPSLOCK (1<<3)
298 #define NUMLOCK (1<<4)
299 #define SCROLLLOCK (1<<5)
301 #define E0ESC (1<<6)
303 // Synonyms of other keys for the numeric keypad
304 #define KEY_KP_ENTER '\n'
305 #define KEY_KP_DIV '/'
307 static const uint8_t shiftcode[256] =
309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00
310 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CTL, 0, 0, // 0x10
311 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SHIFT, 0, 0, 0, 0, 0, // 0x20
312 0, 0, 0, 0, 0, 0, SHIFT, 0, ALT, 0, 0, 0, 0, 0, 0, 0, // 0x30
313 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
314 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x50
315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70
317 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80
318 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CTL, 0, 0, // 0x90
319 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0
320 0, 0, 0, 0, 0, 0, 0, 0, ALT, 0, 0, 0, 0, 0, 0, 0, // 0xB0
321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0
322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xD0
323 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0
324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF0
327 static const uint8_t togglecode[256] =
329 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00
330 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10
331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20
332 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CAPSLOCK, 0, 0, 0, 0, 0, // 0x30
333 0, 0, 0, 0, 0, NUMLOCK, SCROLLLOCK, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x50
335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
336 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70
337 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80
338 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90
339 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0
340 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xB0
341 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0
342 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xD0
343 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0
344 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF0
347 static const uint8_t normalmap[256] =
349 0, 0x1B, '1', '2', '3', '4', '5', '6', // 0x00
350 '7', '8', '9', '0', '-', '=', '\b', '\t',
351 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', // 0x10
352 'o', 'p', '[', ']', '\n', 0, 'a', 's',
353 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', // 0x20
354 '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',
355 'b', 'n', 'm', ',', '.', '/', 0, '*', // 0x30
356 0, ' ', 0, 0, 0, 0, 0, 0,
357 0, 0, 0, 0, 0, 0, 0, '7', // 0x40
358 '8', '9', '-', '4', '5', '6', '+', '1',
359 '2', '3', '0', '.', 0, 0, 0, 0, // 0x50
360 0, 0, 0, 0, 0, 0, 0, 0,
361 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
362 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70
363 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80
364 0, 0, 0, 0, 0, 0, 0, 0, // 0x90
365 0, 0, 0, 0, KEY_KP_ENTER, 0, 0, 0,
366 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0
367 0, 0, 0, 0, 0, KEY_KP_DIV, 0, 0, // 0xB0
368 0, 0, 0, 0, 0, 0, 0, 0,
369 0, 0, 0, 0, 0, 0, 0, KEY_HOME, // 0xC0
370 KEY_UP, KEY_PGUP, 0, KEY_LF, 0, KEY_RT, 0, KEY_END,
371 KEY_DN, KEY_PGDN, KEY_INS, KEY_DEL, 0, 0, 0, 0, // 0xD0
372 0, 0, 0, 0, 0, 0, 0, 0,
373 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0
374 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF0
377 static const uint8_t shiftmap[256] =
379 0, 033, '!', '@', '#', '$', '%', '^', // 0x00
380 '&', '*', '(', ')', '_', '+', '\b', '\t',
381 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', // 0x10
382 'O', 'P', '{', '}', '\n', 0, 'A', 'S',
383 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', // 0x20
384 '"', '~', 0, '|', 'Z', 'X', 'C', 'V',
385 'B', 'N', 'M', '<', '>', '?', 0, '*', // 0x30
386 0, ' ', 0, 0, 0, 0, 0, 0,
387 0, 0, 0, 0, 0, 0, 0, '7', // 0x40
388 '8', '9', '-', '4', '5', '6', '+', '1',
389 '2', '3', '0', '.', 0, 0, 0, 0, // 0x50
390 0, 0, 0, 0, 0, 0, 0, 0,
391 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70
393 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80
394 0, 0, 0, 0, 0, 0, 0, KEY_HOME, // 0x90
395 0, 0, 0, 0, KEY_KP_ENTER, 0, 0, 0,
396 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0
397 0, 0, 0, 0, 0, KEY_KP_DIV, 0, 0, // 0xB0
398 0, 0, 0, 0, 0, 0, 0, 0,
399 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0
400 KEY_UP, KEY_PGUP, 0, KEY_LF, 0, KEY_RT, 0, KEY_END,
401 KEY_DN, KEY_PGDN, KEY_INS, KEY_DEL, 0, 0, 0, 0, // 0xD0
402 0, 0, 0, 0, 0, 0, 0, 0,
403 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0
404 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF0
407 #define C(x) (x - '@')
409 static const uint8_t ctlmap[256] =
411 0, 0, 0, 0, 0, 0, 0, 0, // 0x00
412 0, 0, 0, 0, 0, 0, 0, 0,
413 C('Q'), C('W'), C('E'), C('R'), C('T'), C('Y'), C('U'), C('I'), // 0x10
414 C('O'), C('P'), 0, 0, '\r', 0, C('A'), C('S'),
415 C('D'), C('F'), C('G'), C('H'), C('J'), C('K'), C('L'), 0, // 0x20
416 0, 0, 0, C('\\'), C('Z'), C('X'), C('C'), C('V'),
417 C('B'), C('N'), C('M'), 0, 0, C('/'), 0, 0, // 0x30
418 0, 0, 0, 0, 0, 0, 0, 0,
419 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
420 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x50
421 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
422 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70
423 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80
424 0, 0, 0, 0, 0, 0, 0, KEY_HOME, // 0x90
425 0, 0, 0, 0, 0, 0, 0, 0,
426 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0
427 0, 0, 0, 0, 0, C('/'), 0, 0, // 0xB0
428 0, 0, 0, 0, 0, 0, 0, 0,
429 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0
430 KEY_UP, KEY_PGUP, 0, KEY_LF, 0, KEY_RT, 0, KEY_END,
431 KEY_DN, KEY_PGDN, KEY_INS, KEY_DEL, 0, 0, 0, 0, // 0xD0
432 0, 0, 0, 0, 0, 0, 0, 0,
433 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0
434 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF0
437 static const uint8_t * const charcode[4] = {
438 normalmap,
439 shiftmap,
440 ctlmap,
441 ctlmap
445 * Get data from the keyboard. If we finish a character, return it. Else 0.
446 * Return -1 if no data.
448 static int
449 kbd_proc_data(void)
451 int c;
452 uint8_t data;
453 static uint32_t shift;
455 if ((inb(KBSTATP) & KBS_DIB) == 0)
456 return -1;
458 data = inb(KBDATAP);
460 if (data == 0xE0) {
461 // E0 escape character
462 shift |= E0ESC;
463 return 0;
464 } else if (data & 0x80) {
465 // Key released
466 data = (shift & E0ESC ? data : data & 0x7F);
467 shift &= ~(shiftcode[data] | E0ESC);
468 return 0;
469 } else if (shift & E0ESC) {
470 // Last character was an E0 escape; or with 0x80
471 data |= 0x80;
472 shift &= ~E0ESC;
475 shift |= shiftcode[data];
476 shift ^= togglecode[data];
478 c = charcode[shift & (CTL | SHIFT)][data];
479 if (shift & CAPSLOCK) {
480 if ('a' <= c && c <= 'z')
481 c += 'A' - 'a';
482 else if ('A' <= c && c <= 'Z')
483 c += 'a' - 'A';
486 // Process special keys
487 #if CRT_SAVEROWS > 0
488 // Shift-PageUp and Shift-PageDown: scroll console
489 if ((shift & (CTL | SHIFT)) && (c == KEY_PGUP || c == KEY_PGDN)) {
490 cga_scroll(c == KEY_PGUP ? -CRT_ROWS : CRT_ROWS);
491 return 0;
493 #endif
494 // Ctrl-Alt-Del: reboot
495 if (!(~shift & (CTL | ALT)) && c == KEY_DEL) {
496 cprintf("Rebooting!\n");
497 outb(0x92, 0x3); // courtesy of Chris Frost
500 return c;
503 void
504 kbd_intr(void)
506 cons_intr(kbd_proc_data);
509 static void
510 kbd_init(void)
512 // Drain the kbd buffer so that Bochs generates interrupts.
513 kbd_intr();
514 irq_setmask_8259A(irq_mask_8259A & ~(1<<1));
519 /***** General device-independent console code *****/
520 // Here we manage the console input buffer,
521 // where we stash characters received from the keyboard or serial port
522 // whenever the corresponding interrupt occurs.
524 #define CONSBUFSIZE 512
526 static struct {
527 uint8_t buf[CONSBUFSIZE];
528 uint32_t rpos;
529 uint32_t wpos;
530 } cons;
532 // called by device interrupt routines to feed input characters
533 // into the circular console input buffer.
534 static void
535 cons_intr(int (*proc)(void))
537 int c;
539 while ((c = (*proc)()) != -1) {
540 if (c == 0)
541 continue;
542 cons.buf[cons.wpos++] = c;
543 if (cons.wpos == CONSBUFSIZE)
544 cons.wpos = 0;
548 // return the next input character from the console, or 0 if none waiting
550 cons_getc(void)
552 int c;
554 // poll for any pending input characters,
555 // so that this function works even when interrupts are disabled
556 // (e.g., when called from the kernel monitor).
557 serial_intr();
558 kbd_intr();
560 // grab the next character from the input buffer.
561 if (cons.rpos != cons.wpos) {
562 c = cons.buf[cons.rpos++];
563 if (cons.rpos == CONSBUFSIZE)
564 cons.rpos = 0;
565 return c;
567 return 0;
570 // output a character to the console
571 static void
572 cons_putc(int c)
574 serial_putc(c);
575 lpt_putc(c);
576 cga_putc(c);
579 // initialize the console devices
580 void
581 cons_init(void)
583 cga_init();
584 kbd_init();
585 serial_init();
587 if (!serial_exists)
588 cprintf("Serial port does not exist!\n");
592 // `High'-level console I/O. Used by readline and cprintf.
594 void
595 cputchar(int c)
597 cons_putc(c);
601 getchar(void)
603 int c;
605 while ((c = cons_getc()) == 0)
606 /* do nothing */;
607 return c;
611 iscons(int fdnum)
613 // used by readline
614 return 1;