1
2 #include <stdbool.h>
3 #include <stdint.h>
4 #include <stdlib.h>
5
6 #include <sys/kassert.h>
7 #include <sys/kdebug.h>
8 #include <sys/irq.h>
9
10 #include <machine/amd64.h>
11 #include <machine/amd64op.h>
12
13 #include "../console.h"
14 #include "ps2.h"
15
16 // Status/Command Port (Input/Output)
17 #define PS2_STATUS_PORT 0x64
18 #define PS2_COMMAND_PORT 0x64
19 #define PS2_DATA_PORT 0x60
20
21 // Controller Status
22 #define PS2_STATUS_OBS 0x01 /* Input Buffer Ready */
23 #define PS2_STATUS_IBS 0x02 /* Output Buffer Full */
24
25 // Controller Commands
26 #define PS2_COMMAND_AUXDISABLE 0xA7 /* Disable Auxiliary */
27 #define PS2_COMMAND_AUXENABLE 0xA8 /* Enable Auxiliary */
28 #define PS2_COMMAND_SELFTEST 0xAA /* Test Controller */
29 #define PS2_COMMAND_KBDDISABLE 0xAD /* Disable Keyboard */
30 #define PS2_COMMAND_KBDENABLE 0xAE /* Enable Keyboard */
31
32 // Keyboard Commands
33 #define PS2_KBD_RESET 0xFF /* Reset */
34 #define PS2_KBD_SETLED 0xED /* Set LED */
35
36 // Keyboard Response
37 #define PS2_KBD_RESETDONE 0xAA /* Reset Done */
38
39 static IRQHandler kbdHandler;
40 static IRQHandler psmHandler;
41
42 // Key state flags
43 #define KS_SHIFT 0x01
44 #define KS_ALT 0x02
45 #define KS_CONTROL 0x04
46 #define KS_CAPSLOCK 0x08
47 #define KS_NUMLOCK 0x10
48 #define KS_SCROLLLOCK 0x20
49 #define KS_E0ESCAPE 0x30
50 static uint32_t keyState;
51
52 static uint8_t keyMap[256] = {
53 0x00, 0x1B, '1', '2', '3', '4', '5', '6',
54 '7', '8', '9', '0', '-', '=', 0x08, 0x09,
55 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
56 'o', 'p', '[', ']', 0x0A, 0x00, 'a', 's',
57 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
58 '\'', '`', 0x00, '\\', 'z', 'x', 'c', 'v',
59 'b', 'n', 'm', ',', '.', '/', 0x00, '*',
60 0x00, ' ', KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
61
62 KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, 0x00, 0x00, '7',
63 '8', '9', '-', '4', '5', '6', '+', '1',
64 '2', '3', '0', '.', 0x00, 0x00, 0x00, KEY_F11,
65 KEY_F12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 };
89
90 static uint8_t shiftKeyMap[256] = {
91 0x00, 0x1B, '!', '@', '#', '$', '%', '^',
92 '&', '*', '(', ')', '_', '+', 0x08, 0x09,
93 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
94 'O', 'P', '{', '}', 0x0A, 0x00, 'A', 'S',
95 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
96 '"', '~', 0x00, '|', 'Z', 'X', 'C', 'V',
97 'B', 'N', 'M', '<', '>', '?', 0x00, '*',
98 0x00, ' ', KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
99
100 KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, 0x00, 0x00, '7',
101 '8', '9', '-', '4', '5', '6', '+', '1',
102 '2', '3', '0', '.', 0x00, 0x00, 0x00, KEY_F11,
103 KEY_F12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 };
127
128 static uint8_t controlKeyMap[256] = {
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 };
165
166 static void
PS2_KeyboardIntr(void * arg)167 PS2_KeyboardIntr(void *arg)
168 {
169 uint8_t status;
170 uint8_t data;
171 uint8_t key;
172
173 while (1) {
174 status = inb(PS2_STATUS_PORT);
175 if ((status & PS2_STATUS_OBS) == 0)
176 return;
177
178 data = inb(PS2_DATA_PORT);
179
180 // E0 escape sequence
181 if (data == 0xE0) {
182 keyState |= KS_E0ESCAPE;
183 continue;
184 }
185
186 // Check for release of shift, alt, control
187 if (data & 0x80) {
188 if (data == 0xAA || data == 0xB6)
189 keyState &= ~KS_SHIFT;
190 if (data == 0x9D)
191 keyState &= ~KS_CONTROL;
192 if (data == 0x38)
193 keyState &= ~KS_ALT;
194
195 // Other key release
196 continue;
197 }
198
199 // Check for shift, alt, control
200 if (data == 0x2A || data == 0x36)
201 keyState |= KS_SHIFT;
202 if (data == 0x1D)
203 keyState |= KS_CONTROL;
204 if (data == 0x38)
205 keyState |= KS_ALT;
206
207 // Check for numlock, capslock, scrolllock
208 if (data == 0x3A)
209 keyState ^= KS_CAPSLOCK;
210 if (data == 0x45)
211 keyState ^= KS_NUMLOCK;
212 if (data == 0x46)
213 keyState ^= KS_SCROLLLOCK;
214
215 // Decode character
216 if (keyState & KS_E0ESCAPE) {
217 keyState &= ~KS_E0ESCAPE;
218
219 // Escape sequences
220 continue;
221 }
222
223 // Debugger sequences
224 if ((keyState & (KS_ALT | KS_CONTROL)) == (KS_ALT | KS_CONTROL)) {
225 // Debugger: Alt-Control-Backspace
226 if (data == 0x0E)
227 breakpoint();
228
229 // Reboot: Alt-Control-Delete
230 }
231
232 int isShift = 0;
233 if (keyState & KS_SHIFT)
234 isShift = 1;
235 if (keyState & KS_CAPSLOCK)
236 isShift ^= 1;
237
238 if (keyState & KS_CONTROL) {
239 key = controlKeyMap[data];
240 } else if (isShift) {
241 key = shiftKeyMap[data];
242 } else {
243 key = keyMap[data];
244 }
245
246 if (key == 0x00)
247 continue;
248
249 //kprintf("Key Press: %02X\n", key);
250 Console_EnqueueKey(key);
251
252 continue;
253 }
254 }
255
256 static void
PS2_MouseIntr(void * arg)257 PS2_MouseIntr(void *arg)
258 {
259 }
260
261 void
PS2Wait()262 PS2Wait()
263 {
264 uint8_t status;
265
266 while (1) {
267 status = inb(PS2_STATUS_PORT);
268 if ((status & PS2_STATUS_OBS) != 0)
269 return;
270 }
271 }
272
273 void
PS2_Init()274 PS2_Init()
275 {
276 uint8_t status, data;
277
278 keyState = 0;
279
280 outb(PS2_COMMAND_PORT, PS2_COMMAND_KBDDISABLE);
281
282 while (1) {
283 status = inb(PS2_STATUS_PORT);
284 if ((status & PS2_STATUS_OBS) == 0)
285 break;
286
287 data = inb(PS2_DATA_PORT);
288 }
289
290 // Self test
291 outb(PS2_COMMAND_PORT, PS2_COMMAND_SELFTEST);
292 PS2Wait();
293 data = inb(PS2_DATA_PORT);
294 if (data != 0x55)
295 kprintf("PS2: Controller test failed\n");
296
297 outb(PS2_COMMAND_PORT, PS2_COMMAND_KBDENABLE);
298
299 kbdHandler.irq = 1;
300 kbdHandler.cb = &PS2_KeyboardIntr;
301 kbdHandler.arg = NULL;
302 psmHandler.irq = 12;
303 psmHandler.cb = &PS2_MouseIntr;
304 psmHandler.arg = NULL;
305
306 IRQ_Register(1, &kbdHandler);
307 IRQ_Register(12, &psmHandler);
308 }
309
310