1 /* See COPYRIGHT for copyright information. */
5 #include <inc/kbdreg.h>
6 #include <inc/string.h>
7 #include <inc/assert.h>
9 #include <kern/console.h>
12 void cons_intr(int (*proc
)(void));
15 /***** Serial I/O code *****/
24 serial_proc_data(void)
26 if (!(inb(COM1
+COMSTATUS
) & COMDATA
))
28 return inb(COM1
+COMREAD
);
34 cons_intr(serial_proc_data
);
44 /***** Parallel port output code *****/
45 // For information on PC parallel port programming, see:
47 // Stupid I/O delay routine necessitated by historical PC design flaws
62 for (i
=0; !(inb(0x378+1)&0x80) && i
<12800; i
++)
65 outb(0x378+2, 0x08|0x01);
72 /***** Text-mode CGA/VGA display output *****/
74 static unsigned addr_6845
;
75 static u_short
*crt_buf
;
85 cp
= (short *) (KERNBASE
+ CGA_BUF
);
87 *cp
= (u_short
) 0xA55A;
89 cp
= (short *) (KERNBASE
+ MONO_BUF
);
90 addr_6845
= MONO_BASE
;
96 /* Extract cursor location */
98 pos
= inb(addr_6845
+1) << 8;
100 pos
|= inb(addr_6845
+1);
102 crt_buf
= (u_short
*)cp
;
110 /* if no attribute given, then use black on white */
111 if (!(c
& ~0xff)) c
|= 0x0700;
117 crt_buf
[crt_pos
] = (c
&~0xff) | ' ';
124 crt_pos
-= (crt_pos
% CRT_COLS
);
134 crt_buf
[crt_pos
++] = c
; /* write the character */
138 /* scroll if necessary */
139 if (crt_pos
>= CRT_SIZE
) {
141 memcpy(crt_buf
, crt_buf
+ CRT_COLS
, CRT_SIZE
<< 1);
142 for (i
= CRT_SIZE
- CRT_COLS
; i
< CRT_SIZE
; i
++)
143 crt_buf
[i
] = 0x0700 | ' ';
147 /* move that little blinky thing */
149 outb(addr_6845
+1, crt_pos
>> 8);
151 outb(addr_6845
+1, crt_pos
);
156 /***** Keyboard input code *****/
164 #define CAPSLOCK (1<<3)
165 #define NUMLOCK (1<<4)
166 #define SCROLLOCK (1<<5)
168 static int shiftcode
[256] =
176 static int togglecode
[256] =
183 static char normalmap
[256] =
185 NO
, 033, '1', '2', '3', '4', '5', '6',
186 '7', '8', '9', '0', '-', '=', '\b', '\t',
187 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
188 'o', 'p', '[', ']', '\n', NO
, 'a', 's',
189 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
190 '\'', '`', NO
, '\\', 'z', 'x', 'c', 'v',
191 'b', 'n', 'm', ',', '.', '/', NO
, '*',
192 NO
, ' ', NO
, NO
, NO
, NO
, NO
, NO
,
193 NO
, NO
, NO
, NO
, NO
, NO
, NO
, '7',
194 '8', '9', '-', '4', '5', '6', '+', '1',
198 static char shiftmap
[256] =
200 NO
, 033, '!', '@', '#', '$', '%', '^',
201 '&', '*', '(', ')', '_', '+', '\b', '\t',
202 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
203 'O', 'P', '{', '}', '\n', NO
, 'A', 'S',
204 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';',
205 '"', '~', NO
, '|', 'Z', 'X', 'C', 'V',
206 'B', 'N', 'M', '<', '>', '?', NO
, '*',
207 NO
, ' ', NO
, NO
, NO
, NO
, NO
, NO
,
208 NO
, NO
, NO
, NO
, NO
, NO
, NO
, '7',
209 '8', '9', '-', '4', '5', '6', '+', '1',
215 static char ctlmap
[256] =
217 NO
, NO
, NO
, NO
, NO
, NO
, NO
, NO
,
218 NO
, NO
, NO
, NO
, NO
, NO
, NO
, NO
,
219 C('Q'), C('W'), C('E'), C('R'), C('T'), C('Y'), C('U'), C('I'),
220 C('O'), C('P'), NO
, NO
, '\r', NO
, C('A'), C('S'),
221 C('D'), C('F'), C('G'), C('H'), C('J'), C('K'), C('L'), NO
,
222 NO
, NO
, NO
, C('\\'), C('Z'), C('X'), C('C'), C('V'),
223 C('B'), C('N'), C('M'), NO
, NO
, C('/'), NO
, NO
,
226 static char *charcode
[4] = {
234 * Get data from the keyboard. If we finish a character, return it. Else 0.
235 * Return -1 if no data.
244 if ((inb(KBSTATP
) & KBS_DIB
) == 0)
251 shift
&= ~shiftcode
[data
&~0x80];
256 shift
|= shiftcode
[data
];
257 shift
^= togglecode
[data
];
258 c
= charcode
[shift
&(CTL
|SHIFT
)][data
];
260 if (shift
&CAPSLOCK
) {
261 if ('a' <= c
&& c
<= 'z')
263 else if ('A' <= c
&& c
<= 'Z')
273 cons_intr(kbd_proc_data
);
283 /***** General device-independent console code *****/
284 // Here we manage the console input buffer,
285 // where we stash characters received from the keyboard or serial port
286 // whenever the corresponding interrupt occurs.
296 // called by device interrupt routines to feed input characters
297 // into the circular console input buffer.
299 cons_intr(int (*proc
)(void))
303 while ((c
= (*proc
)()) != -1) {
306 cons
.buf
[cons
.wpos
++] = c
;
307 if (cons
.wpos
== BY2CONS
)
312 // return the next input character from the console, or 0 if none waiting
318 // poll for any pending input characters,
319 // so that this function works even when interrupts are disabled
320 // (e.g., when called from the kernel monitor).
324 // grab the next character from the input buffer.
325 if (cons
.rpos
!= cons
.wpos
) {
326 c
= cons
.buf
[cons
.rpos
++];
327 if (cons
.rpos
== BY2CONS
)
334 // output a character to the console
342 // initialize the console devices
353 // `High'-level console I/O. Used by readline and printf.
366 while ((c
= cons_getc()) == 0)