mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 11:55:24 +00:00
x86/ps2: disable devices during commands
Especially the initial reset ended up with an unusable keyboard in rare cases before. This commit disables keyboard and mouse handling of i8042 during command sequences according to a note from https://www.win.tue.nl/~aeb/linux/kbd/scancodes-12.html
This commit is contained in:
parent
a2b303e95a
commit
a036d2373a
@ -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
|
||||
|
@ -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 <typename FN>
|
||||
void apply_commands(FN const &fn)
|
||||
{
|
||||
_begin_commands();
|
||||
fn();
|
||||
_end_commands();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _SERIAL_INTERFACE_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);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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) };
|
||||
|
Loading…
x
Reference in New Issue
Block a user