diff options
author | Liav A <liavalb@gmail.com> | 2022-12-22 03:46:22 +0200 |
---|---|---|
committer | Jelle Raaijmakers <jelle@gmta.nl> | 2023-01-06 11:09:56 +0100 |
commit | 0f7cc468b2221d54ea79523922a2f21790c02645 (patch) | |
tree | c4925082a1d18b26e3367839a01536daa5792abc /Kernel/Arch/x86_64/ISABus | |
parent | fc5bcd84764d60ae18a74a3918d3d0ee6d6a913e (diff) | |
download | serenity-0f7cc468b2221d54ea79523922a2f21790c02645.zip |
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.
Diffstat (limited to 'Kernel/Arch/x86_64/ISABus')
-rw-r--r-- | Kernel/Arch/x86_64/ISABus/I8042Controller.cpp | 19 |
1 files changed, 6 insertions, 13 deletions
diff --git a/Kernel/Arch/x86_64/ISABus/I8042Controller.cpp b/Kernel/Arch/x86_64/ISABus/I8042Controller.cpp index 096ba932b0..f4ceeea04e 100644 --- a/Kernel/Arch/x86_64/ISABus/I8042Controller.cpp +++ b/Kernel/Arch/x86_64/ISABus/I8042Controller.cpp @@ -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)); |