xref: /aosp_15_r20/external/coreboot/payloads/libpayload/drivers/i8042/i8042.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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