diff --git a/repos/os/src/drivers/input/spec/ps2/ps2_keyboard.h b/repos/os/src/drivers/input/spec/ps2/ps2_keyboard.h index 8136f64902..08ef773a5e 100644 --- a/repos/os/src/drivers/input/spec/ps2/ps2_keyboard.h +++ b/repos/os/src/drivers/input/spec/ps2/ps2_keyboard.h @@ -382,17 +382,19 @@ class Ps2::Keyboard : public Input_driver void _set_leds(bool capslock, bool numlock, bool scrlock) { - _kbd.write(0xed); - if (_kbd.read() != ACK) { - Genode::warning("setting of mode indicators failed (0xed)"); - return; - } + _kbd.apply_commands([&]() { + _kbd.write(0xed); + if (_kbd.read() != ACK) { + Genode::warning("setting of mode indicators failed (0xed)"); + return; + } - _kbd.write((capslock ? 4:0) | (numlock ? 2:0) | (scrlock ? 1:0)); - if (_kbd.read() != ACK) { - Genode::warning("setting of mode indicators failed"); - return; - } + _kbd.write((capslock ? 4:0) | (numlock ? 2:0) | (scrlock ? 1:0)); + if (_kbd.read() != ACK) { + Genode::warning("setting of mode indicators failed"); + return; + } + }); } void _update_leds() @@ -468,17 +470,19 @@ class Ps2::Keyboard : public Input_driver if (_xlate_mode) return; - /* try to enable scan-code set 2 */ - _kbd.write(0xf0); - if (_kbd.read() != ACK) { - Genode::warning("scan code setting not supported"); - return; - } - _kbd.write(SCAN_CODE_SET_2); - if (_kbd.read() != ACK) { - Genode::warning("scan code 2 not supported"); - return; - } + _kbd.apply_commands([&]() { + /* try to enable scan-code set 2 */ + _kbd.write(0xf0); + if (_kbd.read() != ACK) { + Genode::warning("scan code setting not supported"); + return; + } + _kbd.write(SCAN_CODE_SET_2); + if (_kbd.read() != ACK) { + Genode::warning("scan code 2 not supported"); + return; + } + }); /* * If configuration of scan-code set 2 was successful, select diff --git a/repos/os/src/drivers/input/spec/ps2/serial_interface.h b/repos/os/src/drivers/input/spec/ps2/serial_interface.h index da35e1639f..ab5225a5bd 100644 --- a/repos/os/src/drivers/input/spec/ps2/serial_interface.h +++ b/repos/os/src/drivers/input/spec/ps2/serial_interface.h @@ -27,6 +27,24 @@ struct Serial_interface : Genode::Interface * (Re-)enable device interrupt */ virtual void enable_irq() { } + + protected: + + virtual void _begin_commands() { } + virtual void _end_commands() { } + + public: + + /** + * Don't interfere with incoming events on command sequence + */ + template + void apply_commands(FN const &fn) + { + _begin_commands(); + fn(); + _end_commands(); + } }; #endif /* _SERIAL_INTERFACE_H_ */ diff --git a/repos/os/src/drivers/input/spec/ps2/x86/i8042.h b/repos/os/src/drivers/input/spec/ps2/x86/i8042.h index a1bc5080cf..f336f56e25 100644 --- a/repos/os/src/drivers/input/spec/ps2/x86/i8042.h +++ b/repos/os/src/drivers/input/spec/ps2/x86/i8042.h @@ -156,6 +156,23 @@ class I8042 flush_read(); return !empty(); } + + void _begin_commands() override + { + /* disable keyboard and mouse */ + _i8042._command(CMD_KBD_DISABLE); + _i8042._command(CMD_AUX_DISABLE); + + /* flush remaining data in controller */ + while (_i8042._output_buffer_full()) _i8042._data(); + } + + void _end_commands() override + { + /* enable keyboard and mouse */ + _i8042._command(CMD_KBD_ENABLE); + _i8042._command(CMD_AUX_ENABLE); + } }; private: @@ -266,46 +283,37 @@ class I8042 unsigned char configuration; unsigned char ret; - /* disable keyboard and mouse */ - _command(CMD_KBD_DISABLE); - _command(CMD_AUX_DISABLE); + _kbd_interface.apply_commands([&]() { + /* get configuration (can change during the self tests) */ + _command(CMD_READ); + configuration = _wait_data(); + /* query xlate bit */ + _kbd_xlate = !!(configuration & CTRL_XLATE); - /* read remaining data in controller */ - while (_output_buffer_full()) _data(); + /* run self tests */ + _command(CMD_TEST); + if ((ret = _wait_data()) != RET_TEST_OK) { + Genode::log("i8042: self test failed (", Genode::Hex(ret), ")"); + return; + } - /* get configuration (can change during the self tests) */ - _command(CMD_READ); - configuration = _wait_data(); - /* query xlate bit */ - _kbd_xlate = !!(configuration & CTRL_XLATE); + _command(CMD_KBD_TEST); + if ((ret = _wait_data()) != RET_KBD_TEST_OK) { + Genode::log("i8042: kbd test failed (", Genode::Hex(ret), ")"); + return; + } - /* run self tests */ - _command(CMD_TEST); - if ((ret = _wait_data()) != RET_TEST_OK) { - Genode::log("i8042: self test failed (", Genode::Hex(ret), ")"); - return; - } + _command(CMD_AUX_TEST); + if ((ret = _wait_data()) != RET_AUX_TEST_OK) { + Genode::log("I8042: aux test failed (", Genode::Hex(ret), ")"); + return; + } - _command(CMD_KBD_TEST); - if ((ret = _wait_data()) != RET_KBD_TEST_OK) { - Genode::log("i8042: kbd test failed (", Genode::Hex(ret), ")"); - return; - } - - _command(CMD_AUX_TEST); - if ((ret = _wait_data()) != RET_AUX_TEST_OK) { - Genode::log("I8042: aux test failed (", Genode::Hex(ret), ")"); - return; - } - - /* enable interrupts for keyboard and mouse at the controller */ - configuration |= CTRL_KBD_INT | CTRL_AUX_INT; - _command(CMD_WRITE); - _data(configuration); - - /* enable keyboard and mouse */ - _command(CMD_KBD_ENABLE); - _command(CMD_AUX_ENABLE); + /* enable interrupts for keyboard and mouse at the controller */ + configuration |= CTRL_KBD_INT | CTRL_AUX_INT; + _command(CMD_WRITE); + _data(configuration); + }); } /** diff --git a/repos/os/src/drivers/input/spec/ps2/x86/main.cc b/repos/os/src/drivers/input/spec/ps2/x86/main.cc index 3960fa257d..a2c8f13f3c 100644 --- a/repos/os/src/drivers/input/spec/ps2/x86/main.cc +++ b/repos/os/src/drivers/input/spec/ps2/x86/main.cc @@ -52,7 +52,7 @@ struct Ps2::Main Platform::Device_client _device_ps2 { _ps2_device_cap() }; - enum { REG_IOPORT_DATA = 0, REG_IOPORT_STATUS }; + enum { REG_IOPORT_DATA = 0, REG_IOPORT_STATUS = 1 }; I8042 _i8042 { _device_ps2.io_port(REG_IOPORT_DATA), _device_ps2.io_port(REG_IOPORT_STATUS) };