mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:57:46 +00:00
Kernel: Make i8042 controller initialization sequence more robust
The setting of scan code set sequence is removed, as it's buggy and could lead the controller to fail immediately when doing self-test afterwards. We will restore it when we understand how to do so safely. Allow the user to determine a preferred detection path with a new kernel command line argument. The defualt option is to check i8042 presence with an ACPI check and if necessary - an "aggressive" test to determine i8042 existence in the system. Also, keep the i8042 controller pointer on the stack, so don't assign m_i8042_controller member pointer if it does not exist.
This commit is contained in:
parent
fc5bcd8476
commit
0f7cc468b2
6 changed files with 62 additions and 34 deletions
|
@ -107,23 +107,12 @@ UNMAP_AFTER_INIT ErrorOr<void> I8042Controller::detect_devices()
|
|||
|
||||
TRY(do_wait_then_write(I8042Port::Command, I8042Command::ReadConfiguration));
|
||||
configuration = TRY(do_wait_then_read(I8042Port::Buffer));
|
||||
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.
|
||||
// However we rely on compatibility 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");
|
||||
TRY(do_wait_then_write(I8042Port::Command, I8042Command::WriteConfiguration));
|
||||
TRY(do_wait_then_write(I8042Port::Buffer, configuration));
|
||||
|
||||
// Perform controller self-test
|
||||
TRY(do_wait_then_write(I8042Port::Command, I8042Command::TestPS2Controller));
|
||||
|
@ -134,8 +123,12 @@ UNMAP_AFTER_INIT ErrorOr<void> I8042Controller::detect_devices()
|
|||
TRY(do_wait_then_write(I8042Port::Buffer, configuration));
|
||||
} else {
|
||||
dbgln("I8042: Controller self test failed");
|
||||
return Error::from_errno(EIO);
|
||||
}
|
||||
|
||||
m_is_dual_channel = (configuration & I8042ConfigurationFlag::SecondPS2PortClock) != 0;
|
||||
dbgln("I8042: {} channel controller", m_is_dual_channel ? "Dual" : "Single");
|
||||
|
||||
// Test ports and enable them if available
|
||||
TRY(do_wait_then_write(I8042Port::Command, I8042Command::TestFirstPS2Port));
|
||||
auto first_port_test_result = TRY(do_wait_then_read(I8042Port::Buffer));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue