1 /* Minimal polling PC keyboard driver
2  * - No interrupt
3  * - No LED
4  * - No special keys
5  *
6  * still Enough For Me to type a filename.
7  *
8  * 2003-07 by SONE Takesh
9  * 2004-04 moved by LYH From filo to Etherboot
10  *		yhlu@tyan.com
11  */
12 
13 #include <ipxe/io.h>
14 #include <ipxe/console.h>
15 
16 static char key_map[][128] = {
17     {
18 	"\0\x1b""1234567890-=\b\t"
19 	"qwertyuiop[]\r\0as"
20 	"dfghjkl;'`\0\\zxcv"
21 	"bnm,./\0*\0 \0\0\0\0\0\0"
22 	"\0\0\0\0\0\0\0""789-456+1"
23 	"230."
24     },{
25 	"\0\x1b""!@#$%^&*()_+\b\t"
26 	"QWERTYUIOP{}\r\0AS"
27 	"DFGHJKL:\"~\0|ZXCV"
28 	"BNM<>?\0\0\0 \0\0\0\0\0\0"
29 	"\0\0\0\0\0\0\0""789-456+1"
30 	"230."
31     }
32 };
33 
34 static int cur_scan;
35 static unsigned int shift_state;
36 #define SHIFT 1
37 #define CONTROL 2
38 #define CAPS 4
39 
get_scancode(void)40 static int get_scancode(void)
41 {
42     int scan;
43 
44     if ((inb(0x64) & 1) == 0)
45 	return 0;
46     scan = inb(0x60);
47 
48     switch (scan) {
49     case 0x2a:
50     case 0x36:
51 	shift_state |= SHIFT;
52 	break;
53     case 0xaa:
54     case 0xb6:
55 	shift_state &= ~SHIFT;
56 	break;
57     case 0x1d:
58 	shift_state |= CONTROL;
59 	break;
60     case 0x9d:
61 	shift_state &= ~CONTROL;
62 	break;
63     case 0x3a:
64 	shift_state ^= CAPS;
65 	break;
66     }
67 
68     if (scan & 0x80)
69 	return 0; /* ignore break code or 0xe0 etc! */
70     return scan;
71 }
72 
kbd_havekey(void)73 static int kbd_havekey(void)
74 {
75     if (!cur_scan)
76 	cur_scan = get_scancode();
77     return cur_scan != 0;
78 }
79 
kbd_ischar(void)80 static int kbd_ischar(void)
81 {
82     if (!kbd_havekey())
83 	return 0;
84     if (!key_map[shift_state & SHIFT][cur_scan]) {
85 	cur_scan = 0;
86 	return 0;
87     }
88     return 1;
89 }
90 
kbd_getc(void)91 static int kbd_getc(void)
92 {
93     int c;
94 
95     while (!kbd_ischar())
96 	;
97     c = key_map[shift_state & SHIFT][cur_scan];
98     if (shift_state & (CONTROL | CAPS)) {
99 	if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
100 	    if (shift_state & CONTROL)
101 		c &= 0x1f;
102 	    else if (shift_state & CAPS)
103 		c ^= ('A' ^ 'a');
104 	}
105     }
106     cur_scan = 0;
107     return c;
108 }
109 
110 struct console_driver pc_kbd_console __console_driver = {
111 	.getchar = kbd_getc,
112 };
113