1 /*
2 *
3 * Patrick Rudolph 2017 <[email protected]>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <libpayload-config.h>
30 #include <libpayload.h>
31 #include <stdbool.h>
32 #include <stddef.h>
33
34 #include "i8042.h"
35
36 /* Overflowing FIFO implementation */
37
38 struct fifo {
39 u8 *buf;
40 size_t tx;
41 size_t rx;
42 size_t len;
43 };
44
45 /** Initialize a new fifo queue.
46 * Initialize a new fifo with length @len.
47 * @len: Length of new fifo
48 * Returns NULL on error.
49 */
fifo_init(size_t len)50 static struct fifo *fifo_init(size_t len)
51 {
52 struct fifo *ret;
53
54 ret = malloc(sizeof(*ret));
55 if (!ret)
56 return NULL;
57
58 memset(ret, 0, sizeof(*ret));
59
60 ret->buf = malloc(len);
61 if (!ret->buf) {
62 free(ret);
63 return NULL;
64 }
65
66 ret->len = len;
67
68 return ret;
69 }
70
71 /** Push object onto fifo queue.
72 * Pushes a new object onto the fifo. In case the fifo
73 * is full the oldest object is overwritten.
74 * @fifo: Fifo to use
75 * @c: Element to push
76 */
fifo_push(struct fifo * fifo,u8 c)77 static void fifo_push(struct fifo *fifo, u8 c)
78 {
79 fifo->buf[fifo->tx++] = c;
80 fifo->tx = fifo->tx % fifo->len;
81 if (fifo->tx == fifo->rx)
82 fifo->rx++;
83 fifo->rx = fifo->rx % fifo->len;
84 }
85
86 /** Test fifo queue element count.
87 * Returns 1 if fifo is empty.
88 * @fifo: Fifo to use
89 */
fifo_is_empty(struct fifo * fifo)90 static int fifo_is_empty(struct fifo *fifo)
91 {
92 if (!fifo)
93 return 1;
94 return fifo->tx == fifo->rx;
95 }
96
97 /** Pop element from fifo queue.
98 * Returns the oldest object from queue if any.
99 * In case the queue is empty 0 is returned.
100 * @fifo: Fifo to use
101 */
fifo_pop(struct fifo * fifo)102 static u8 fifo_pop(struct fifo *fifo)
103 {
104 u8 ret;
105
106 if (fifo_is_empty(fifo))
107 return 0;
108
109 ret = fifo->buf[fifo->rx++];
110 fifo->rx = fifo->rx % fifo->len;
111
112 return ret;
113 }
114
115 /** Peek on the head of fifo queue.
116 * Returns the oldest object on the queue if any.
117 * In case the queue is empty 0 is returned.
118 * @fifo: Fifo to use
119 */
fifo_peek(struct fifo * fifo)120 static u8 fifo_peek(struct fifo *fifo)
121 {
122 if (fifo_is_empty(fifo))
123 return 0;
124
125 return fifo->buf[fifo->rx];
126 }
127
128 /** Destroys a fifo queue.
129 * @fifo: Fifo to use
130 */
fifo_destroy(struct fifo * fifo)131 static void fifo_destroy(struct fifo *fifo)
132 {
133 if (fifo && fifo->buf)
134 free(fifo->buf);
135 if (fifo)
136 free(fifo);
137 }
138
139 /* i8042 keyboard controller implementation */
140
read_status(void)141 static inline u8 read_status(void) { return inb(0x64); }
read_data(void)142 static inline u8 read_data(void) { return inb(0x60); }
write_cmd(u8 cmd)143 static inline void write_cmd(u8 cmd) { outb(cmd, 0x64); }
write_data(u8 data)144 static inline void write_data(u8 data) { outb(data, 0x60); }
145
146 #define OBF 1
147 #define IBF 2
148
149 /* Keyboard controller methods */
150 static int initialized = 0;
151 static int kbc_init = 0;
152 static struct fifo *aux_fifo = NULL;
153 static struct fifo *ps2_fifo = NULL;
154
155 static int i8042_cmd_with_response(u8 cmd);
156
157 /** Wait for command ready.
158 * Wait for the keyboard controller to accept a new command.
159 * Returns: 0 on timeout
160 */
i8042_wait_cmd_rdy(void)161 static u8 i8042_wait_cmd_rdy(void)
162 {
163 int retries = 10000;
164 while (retries-- && (read_status() & IBF))
165 udelay(50);
166
167 return retries > 0;
168 }
169
170 /** Wait for data ready.
171 * Wait for the keyboard controller to accept new data.
172 * Returns: 0 on timeout
173 */
i8042_wait_data_rdy(void)174 static u8 i8042_wait_data_rdy(void)
175 {
176 int retries = 30000;
177 while (retries-- && !(read_status() & OBF))
178 udelay(50);
179
180 return retries > 0;
181 }
182
183 /** Keyboard controller has a ps2 port.
184 * Returns if ps2 port is available.
185 */
i8042_has_ps2(void)186 size_t i8042_has_ps2(void)
187 {
188 return !!ps2_fifo;
189 }
190
191 /** Keyboard controller has an aux port.
192 * Returns if aux port is available.
193 */
i8042_has_aux(void)194 size_t i8042_has_aux(void)
195 {
196 return !!aux_fifo;
197 }
198
199 /**
200 * Probe for keyboard controller
201 * Returns: 1 for success, 0 for failure
202 */
i8042_probe(void)203 u8 i8042_probe(void)
204 {
205 if (initialized)
206 return 1;
207
208 aux_fifo = NULL;
209 ps2_fifo = NULL;
210
211 /* If 0x64 returns 0xff, then we have no keyboard
212 * controller */
213 if (read_status() == 0xFF) {
214 printf("ERROR: No keyboard controller found!\n");
215 return 0;
216 }
217
218 if (!i8042_wait_cmd_rdy()) {
219 printf("ERROR: i8042_wait_cmd_rdy failed!\n");
220 return 0;
221 }
222
223 kbc_init = 1;
224
225 /* Disable first device */
226 if (i8042_cmd(I8042_CMD_DIS_KB) != 0) {
227 kbc_init = 0;
228 printf("ERROR: i8042_cmd I8042_CMD_DIS_KB failed!\n");
229 return 0;
230 }
231
232 /* Disable second device */
233 if (i8042_cmd(I8042_CMD_DIS_AUX) != 0) {
234 kbc_init = 0;
235 printf("ERROR: i8042_cmd I8042_CMD_DIS_AUX failed!\n");
236 return 0;
237 }
238
239 /* Flush buffer */
240 while (read_status() & OBF)
241 read_data();
242
243 /* Self test. */
244 if (i8042_cmd_with_response(I8042_CMD_SELF_TEST)
245 != I8042_SELF_TEST_RSP) {
246 kbc_init = 0;
247 printf("ERROR: i8042_cmd I8042_CMD_SELF_TEST failed!\n");
248 return 0;
249 }
250
251 /* Test secondary port */
252 if (CONFIG(LP_PC_MOUSE)) {
253 if (i8042_cmd_with_response(I8042_CMD_AUX_TEST) == 0)
254 aux_fifo = fifo_init(4 * 32);
255 }
256
257 /* Test first PS/2 port */
258 if (i8042_cmd_with_response(I8042_CMD_KB_TEST) == 0)
259 ps2_fifo = fifo_init(2 * 16);
260
261 kbc_init = 0;
262
263 initialized = aux_fifo || ps2_fifo;
264
265 return initialized;
266 }
267
268 /* Close the keyboard controller */
i8042_close(void)269 void i8042_close(void)
270 {
271 if (!initialized)
272 return;
273
274 fifo_destroy(aux_fifo);
275 fifo_destroy(ps2_fifo);
276
277 initialized = 0;
278 aux_fifo = NULL;
279 ps2_fifo = NULL;
280 }
281
282 /** Send command to keyboard controller.
283 * @param cmd: The command to be send.
284 * returns: 0 on success, -1 on failure.
285 */
i8042_cmd(u8 cmd)286 int i8042_cmd(u8 cmd)
287 {
288 if (!initialized && !kbc_init)
289 return -1;
290
291 if (!i8042_wait_cmd_rdy())
292 return -1;
293
294 write_cmd(cmd);
295
296 if (!i8042_wait_cmd_rdy())
297 return -1;
298
299 return 0;
300 }
301
302 /** Send command to keyboard controller.
303 * @param cmd: The command to be send.
304 * returns: Response on success, -1 on failure.
305 */
i8042_cmd_with_response(u8 cmd)306 static int i8042_cmd_with_response(u8 cmd)
307 {
308 const int ret = i8042_cmd(cmd);
309 if (ret != 0)
310 return ret;
311
312 if (!i8042_wait_data_rdy())
313 return -1;
314
315 return read_data();
316 }
317
318 /** Send additional data to keyboard controller.
319 * @param data The data to be send.
320 */
i8042_write_data(u8 data)321 void i8042_write_data(u8 data)
322 {
323 if (!initialized)
324 return;
325
326 if (!i8042_wait_cmd_rdy())
327 return;
328
329 write_data(data);
330
331 if (!i8042_wait_cmd_rdy())
332 return;
333 }
334
335 /**
336 * Send command & data to keyboard controller.
337 *
338 * @param cmd: The command to be sent.
339 * @param data: The data to be sent.
340 * Returns 0 on success, -1 on failure.
341 */
i8042_cmd_with_data(const u8 cmd,const u8 data)342 static int i8042_cmd_with_data(const u8 cmd, const u8 data)
343 {
344 const int ret = i8042_cmd(cmd);
345 if (ret != 0)
346 return ret;
347
348 i8042_write_data(data);
349
350 return ret;
351 }
352
353 /**
354 * Probe for keyboard controller data and queue it.
355 */
i8042_data_poll(void)356 static void i8042_data_poll(void)
357 {
358 u8 c;
359
360 if (!initialized)
361 return;
362
363 c = read_status();
364 while ((c != 0xFF) && (c & OBF)) {
365 const u8 in = read_data();
366 /* Assume "second PS/2 port output buffer full" flag works */
367 struct fifo *const fifo = (c & 0x20) ? aux_fifo : ps2_fifo;
368 if (fifo)
369 fifo_push(fifo, in);
370
371 c = read_status();
372 }
373 }
374
375 /** Keyboard controller data ready status.
376 * Signals that keyboard data is ready for reading.
377 */
i8042_data_ready_ps2(void)378 u8 i8042_data_ready_ps2(void)
379 {
380 if (!initialized)
381 return 0;
382 i8042_data_poll();
383 return !fifo_is_empty(ps2_fifo);
384 }
385
386 /** Keyboard controller data ready status.
387 * Signals that mouse data is ready for reading.
388 */
i8042_data_ready_aux(void)389 u8 i8042_data_ready_aux(void)
390 {
391 if (!initialized)
392 return 0;
393 i8042_data_poll();
394 return !fifo_is_empty(aux_fifo);
395 }
396
397 /**
398 * Returns available keyboard data, if any.
399 */
i8042_read_data_ps2(void)400 u8 i8042_read_data_ps2(void)
401 {
402 i8042_data_poll();
403 return fifo_pop(ps2_fifo);
404 }
405
406 /**
407 * Returns available keyboard data without advancing the queue.
408 */
i8042_peek_data_ps2(void)409 u8 i8042_peek_data_ps2(void)
410 {
411 return fifo_peek(ps2_fifo);
412 }
413
414 /**
415 * Returns available mouse data, if any.
416 */
i8042_read_data_aux(void)417 u8 i8042_read_data_aux(void)
418 {
419 i8042_data_poll();
420 return fifo_pop(aux_fifo);
421 }
422
423 /**
424 * Waits for keyboard data.
425 * Waits for up to 500msec to receive data.
426 * Returns: -1 on timeout, data received otherwise
427 */
i8042_wait_read_ps2(void)428 int i8042_wait_read_ps2(void)
429 {
430 int retries = 10000;
431
432 while (retries-- && !i8042_data_ready_ps2())
433 udelay(50);
434
435 return (retries <= 0) ? -1 : i8042_read_data_ps2();
436 }
437
438 /** Waits for mouse data.
439 * Waits for up to 500msec to receive data.
440 * Returns: -1 on timeout, data received otherwise
441 */
i8042_wait_read_aux(void)442 int i8042_wait_read_aux(void)
443 {
444 int retries = 10000;
445
446 while (retries-- && !i8042_data_ready_aux())
447 udelay(50);
448
449 return (retries <= 0) ? -1 : i8042_read_data_aux();
450 }
451
452 /**
453 * Get the keyboard scancode translation state.
454 *
455 * Returns: -1 on timeout, 1 if the controller translates
456 * scancode set #2 to #1, and 0 if not.
457 */
i8042_get_kbd_translation(void)458 int i8042_get_kbd_translation(void)
459 {
460 const int cfg = i8042_cmd_with_response(I8042_CMD_RD_CMD_BYTE);
461 if (cfg < 0)
462 return cfg;
463
464 return !!(cfg & I8042_CMD_BYTE_XLATE);
465 }
466
467 /**
468 * Sets the keyboard scancode translation state.
469 *
470 * Returns: -1 on timeout, 0 otherwise.
471 */
i8042_set_kbd_translation(const bool xlate)472 int i8042_set_kbd_translation(const bool xlate)
473 {
474 int cfg = i8042_cmd_with_response(I8042_CMD_RD_CMD_BYTE);
475 if (cfg < 0)
476 return cfg;
477
478 if (xlate)
479 cfg |= I8042_CMD_BYTE_XLATE;
480 else
481 cfg &= ~I8042_CMD_BYTE_XLATE;
482 return i8042_cmd_with_data(I8042_CMD_WR_CMD_BYTE, cfg);
483 }
484