From f86bba3059c813bd6c28ec53c56760318d2ea653 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Fri, 12 Apr 2024 15:57:27 +0200 Subject: [PATCH] ps2: probe for working i8042 If no working controller is detected the driver just enters sleep forever. Issue #5174 --- repos/os/src/drivers/ps2/x86/i8042.h | 39 +++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/repos/os/src/drivers/ps2/x86/i8042.h b/repos/os/src/drivers/ps2/x86/i8042.h index 3105684d7f..315bedf7ca 100644 --- a/repos/os/src/drivers/ps2/x86/i8042.h +++ b/repos/os/src/drivers/ps2/x86/i8042.h @@ -16,6 +16,7 @@ #include #include +#include #include "serial_interface.h" @@ -219,6 +220,24 @@ class I8042 bool _input_buffer_full() { return _status() & STAT_IBF; } bool _aux_data_pending() { return _status() & STAT_AUX_DATA; } + /** + * Probe controller by flushing limited amount of available data + * + * If there's no controller we'll infinitely read 0xff from status + * port. + */ + bool _probe_controller() + { + unsigned attempts = 32; /* artificial maximum controller buffer size */ + + while (_output_buffer_full() && attempts > 0) { + (void)_data(); + attempts--; + } + + return attempts > 0; + } + /** * Wait for data and read */ @@ -229,10 +248,8 @@ class I8042 while (!_output_buffer_full() && attempts > 0) attempts--; - if (attempts == 0) { - Genode::error("no data available"); + if (attempts == 0) return RET_INVALID; - } return _data(); } @@ -273,14 +290,11 @@ class I8042 _kbd_interface(*this, false), _aux_interface(*this, true) { - reset(); - } + if (!_probe_controller()) { + Genode::log("i8042: no controller detected"); + Genode::sleep_forever(); + } - /** - * Test and initialize controller - */ - void reset() - { unsigned char configuration; unsigned char ret; @@ -295,18 +309,19 @@ class I8042 _command(CMD_TEST); if ((ret = _wait_data()) != RET_TEST_OK) { Genode::log("i8042: self test failed (", Genode::Hex(ret), ")"); - return; + Genode::sleep_forever(); } _command(CMD_KBD_TEST); if ((ret = _wait_data()) != RET_KBD_TEST_OK) { Genode::log("i8042: kbd test failed (", Genode::Hex(ret), ")"); - return; + Genode::sleep_forever(); } _command(CMD_AUX_TEST); if ((ret = _wait_data()) != RET_AUX_TEST_OK) { Genode::log("I8042: aux test failed (", Genode::Hex(ret), ")"); + /* don't sleep forever as keyboard may work */ return; }