Kernel: Enable PS2 keyboard scan code translation if not already enabled

On the QEMU microvm machine type, it became apparent that the BIOS was
not setting the i8042 controller to function as expected. To ensure that
the controller is always outputting correct scan codes, set it to scan
code 2 and enable first port translation to ensure all scan codes are
translated to scan code set 1. This is the expected behavior when using
SeaBIOS, but on qboot (the BIOS for the QEMU microvm machine type), the
firmware doesn't take care of this so we need to do this ourselves.
This commit is contained in:
Liav A 2022-04-15 11:20:11 +03:00 committed by Idan Horowitz
parent 04763c4a12
commit 063ea0088e
Notes: sideshowbarker 2024-07-18 22:57:59 +09:00
2 changed files with 11 additions and 0 deletions

View file

@ -109,7 +109,17 @@ UNMAP_AFTER_INIT ErrorOr<void> I8042Controller::detect_devices()
TRY(do_wait_then_write(I8042Port::Command, I8042Command::WriteConfiguration));
configuration &= ~I8042ConfigurationFlag::FirstPS2PortInterrupt;
configuration &= ~I8042ConfigurationFlag::SecondPS2PortInterrupt;
// Note: The default BIOS on the QEMU microvm machine type (qboot) doesn't
// behave like SeaBIOS, which means it doesn't set first port scan code translation.
// Howerver we rely on compatbility feature of the i8042 to send scan codes of set 1.
// To ensure that the controller is always outputting correct scan codes, set it
// to scan code 2 (because SeaBIOS on regular QEMU machine does this for us) and enable
// first port translation to ensure all scan codes are translated to scan code set 1.
configuration |= I8042ConfigurationFlag::FirstPS2PortTranslation;
TRY(do_wait_then_write(I8042Port::Buffer, configuration));
TRY(do_wait_then_write(I8042Port::Buffer, I8042Command::SetScanCodeSet));
TRY(do_wait_then_write(I8042Port::Buffer, 0x2));
m_is_dual_channel = (configuration & I8042ConfigurationFlag::SecondPS2PortClock) != 0;
dbgln("I8042: {} channel controller", m_is_dual_channel ? "Dual" : "Single");

View file

@ -30,6 +30,7 @@ enum I8042Command : u8 {
DisableFirstPS2Port = 0xAD,
EnableFirstPS2Port = 0xAE,
WriteSecondPS2PortInputBuffer = 0xD4,
SetScanCodeSet = 0xF0,
GetDeviceID = 0xF2,
SetSampleRate = 0xF3,
EnablePacketStreaming = 0xF4,