From 26c84967faade6a66305606526b8ee37f50365f7 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Sun, 24 Oct 2021 19:51:00 +0200 Subject: [PATCH] Kernel: Enumify all magic constants for I8042 devices This makes the code much easier to read. --- Kernel/Devices/HID/I8042Controller.cpp | 112 ++++++++++++----------- Kernel/Devices/HID/I8042Controller.h | 55 +++++++++-- Kernel/Devices/HID/PS2KeyboardDevice.cpp | 2 +- Kernel/Devices/HID/PS2MouseDevice.cpp | 28 ++---- 4 files changed, 115 insertions(+), 82 deletions(-) diff --git a/Kernel/Devices/HID/I8042Controller.cpp b/Kernel/Devices/HID/I8042Controller.cpp index f941896b4f3..423b0dc71ae 100644 --- a/Kernel/Devices/HID/I8042Controller.cpp +++ b/Kernel/Devices/HID/I8042Controller.cpp @@ -37,51 +37,51 @@ UNMAP_AFTER_INIT void I8042Controller::detect_devices() { SpinlockLocker lock(m_lock); // Disable devices - do_wait_then_write(I8042_STATUS, 0xad); - do_wait_then_write(I8042_STATUS, 0xa7); // ignored if it doesn't exist + do_wait_then_write(I8042Port::Command, I8042Command::DisableFirstPS2Port); + do_wait_then_write(I8042Port::Command, I8042Command::DisableSecondPS2Port); // ignored if it doesn't exist // Drain buffers do_drain(); - do_wait_then_write(I8042_STATUS, 0x20); - configuration = do_wait_then_read(I8042_BUFFER); - do_wait_then_write(I8042_STATUS, 0x60); - configuration &= ~3; // Disable IRQs for all - do_wait_then_write(I8042_BUFFER, configuration); + do_wait_then_write(I8042Port::Command, I8042Command::ReadConfiguration); + configuration = do_wait_then_read(I8042Port::Buffer); + do_wait_then_write(I8042Port::Command, I8042Command::WriteConfiguration); + configuration &= ~I8042ConfigurationFlag::FirstPS2PortInterrupt; + configuration &= ~I8042ConfigurationFlag::SecondPS2PortInterrupt; + do_wait_then_write(I8042Port::Buffer, configuration); - m_is_dual_channel = (configuration & (1 << 5)) != 0; - dbgln("I8042: {} channel controller", - m_is_dual_channel ? "Dual" : "Single"); + m_is_dual_channel = (configuration & I8042ConfigurationFlag::SecondPS2PortClock) != 0; + dbgln("I8042: {} channel controller", m_is_dual_channel ? "Dual" : "Single"); // Perform controller self-test - do_wait_then_write(I8042_STATUS, 0xaa); - if (do_wait_then_read(I8042_BUFFER) == 0x55) { + do_wait_then_write(I8042Port::Command, I8042Command::TestPS2Controller); + if (do_wait_then_read(I8042Port::Buffer) == I8042Response::ControllerTestPassed) { // Restore configuration in case the controller reset - do_wait_then_write(I8042_STATUS, 0x60); - do_wait_then_write(I8042_BUFFER, configuration); + do_wait_then_write(I8042Port::Command, I8042Command::WriteConfiguration); + do_wait_then_write(I8042Port::Buffer, configuration); } else { dbgln("I8042: Controller self test failed"); } // Test ports and enable them if available - do_wait_then_write(I8042_STATUS, 0xab); // test - m_first_port_available = (do_wait_then_read(I8042_BUFFER) == 0); + do_wait_then_write(I8042Port::Command, I8042Command::TestFirstPS2Port); + m_first_port_available = (do_wait_then_read(I8042Port::Buffer) == 0); if (m_first_port_available) { - do_wait_then_write(I8042_STATUS, 0xae); //enable - configuration |= 1; - configuration &= ~(1 << 4); + do_wait_then_write(I8042Port::Command, I8042Command::EnableFirstPS2Port); + configuration |= I8042ConfigurationFlag::FirstPS2PortInterrupt; + configuration &= ~I8042ConfigurationFlag::FirstPS2PortClock; } else { dbgln("I8042: Keyboard port not available"); } if (m_is_dual_channel) { - do_wait_then_write(I8042_STATUS, 0xa9); // test - m_second_port_available = (do_wait_then_read(I8042_BUFFER) == 0); + do_wait_then_write(I8042Port::Command, I8042Command::TestSecondPS2Port); + m_second_port_available = (do_wait_then_read(I8042Port::Buffer) == 0); if (m_second_port_available) { - do_wait_then_write(I8042_STATUS, 0xa8); // enable - configuration |= 2; - configuration &= ~(1 << 5); + do_wait_then_write(I8042Port::Command, I8042Command::EnableSecondPS2Port); + configuration |= I8042ConfigurationFlag::SecondPS2PortInterrupt; + configuration &= ~I8042ConfigurationFlag::SecondPS2PortClock; } else { dbgln("I8042: Mouse port not available"); } @@ -89,9 +89,10 @@ UNMAP_AFTER_INIT void I8042Controller::detect_devices() // Enable IRQs for the ports that are usable if (m_first_port_available || m_second_port_available) { - configuration &= ~0x30; // renable clocks - do_wait_then_write(I8042_STATUS, 0x60); - do_wait_then_write(I8042_BUFFER, configuration); + configuration &= ~I8042ConfigurationFlag::FirstPS2PortClock; + configuration &= ~I8042ConfigurationFlag::SecondPS2PortClock; + do_wait_then_write(I8042Port::Command, I8042Command::WriteConfiguration); + do_wait_then_write(I8042Port::Buffer, configuration); } } @@ -101,11 +102,11 @@ UNMAP_AFTER_INIT void I8042Controller::detect_devices() if (!m_keyboard_device) { dbgln("I8042: Keyboard device failed to initialize, disable"); m_first_port_available = false; - configuration &= ~1; - configuration |= 1 << 4; + configuration &= ~I8042ConfigurationFlag::FirstPS2PortInterrupt; + configuration |= I8042ConfigurationFlag::FirstPS2PortClock; SpinlockLocker lock(m_lock); - do_wait_then_write(I8042_STATUS, 0x60); - do_wait_then_write(I8042_BUFFER, configuration); + do_wait_then_write(I8042Port::Command, I8042Command::WriteConfiguration); + do_wait_then_write(I8042Port::Buffer, configuration); } } if (m_second_port_available) { @@ -115,10 +116,10 @@ UNMAP_AFTER_INIT void I8042Controller::detect_devices() if (!m_mouse_device) { dbgln("I8042: Mouse device failed to initialize, disable"); m_second_port_available = false; - configuration |= 1 << 5; + configuration |= I8042ConfigurationFlag::SecondPS2PortClock; SpinlockLocker lock(m_lock); - do_wait_then_write(I8042_STATUS, 0x60); - do_wait_then_write(I8042_BUFFER, configuration); + do_wait_then_write(I8042Port::Command, I8042Command::WriteConfiguration); + do_wait_then_write(I8042Port::Buffer, configuration); } } } @@ -134,11 +135,11 @@ bool I8042Controller::irq_process_input_buffer(HIDDevice::Type) { VERIFY(Processor::current_in_irq()); - u8 status = IO::in8(I8042_STATUS); - if (!(status & I8042_BUFFER_FULL)) + u8 status = IO::in8(I8042Port::Status); + if (!(status & I8042StatusFlag::OutputBuffer)) return false; - HIDDevice::Type data_for_device = ((status & I8042_WHICH_BUFFER) == I8042_MOUSE_BUFFER) ? HIDDevice::Type::Mouse : HIDDevice::Type::Keyboard; - u8 byte = IO::in8(I8042_BUFFER); + HIDDevice::Type data_for_device = ((status & I8042StatusFlag::SecondPS2PortOutputBuffer) == 0) ? HIDDevice::Type::Keyboard : HIDDevice::Type::Mouse; + u8 byte = IO::in8(I8042Port::Buffer); if (data_for_device == HIDDevice::Type::Mouse) { VERIFY(m_mouse_device); static_cast(*m_mouse_device).irq_handle_byte_read(byte); @@ -155,10 +156,10 @@ bool I8042Controller::irq_process_input_buffer(HIDDevice::Type) void I8042Controller::do_drain() { for (;;) { - u8 status = IO::in8(I8042_STATUS); - if (!(status & I8042_BUFFER_FULL)) + u8 status = IO::in8(I8042Port::Status); + if (!(status & I8042StatusFlag::OutputBuffer)) return; - IO::in8(I8042_BUFFER); + IO::in8(I8042Port::Buffer); } } @@ -168,10 +169,10 @@ bool I8042Controller::do_reset_device(HIDDevice::Type device) VERIFY(m_lock.is_locked()); VERIFY(!Processor::current_in_irq()); - if (do_send_command(device, 0xff) != I8042_ACK) + if (do_send_command(device, I8042Command::Reset) != I8042Response::Acknowledge) return false; // Wait until we get the self-test result - return do_wait_then_read(I8042_BUFFER) == 0xaa; + return do_wait_then_read(I8042Port::Buffer) == I8042Response::Success; } u8 I8042Controller::do_send_command(HIDDevice::Type device, u8 command) @@ -192,7 +193,7 @@ u8 I8042Controller::do_send_command(HIDDevice::Type device, u8 command, u8 data) VERIFY(!Processor::current_in_irq()); u8 response = do_write_to_device(device, command); - if (response == I8042_ACK) + if (response == I8042Response::Acknowledge) response = do_write_to_device(device, data); return response; } @@ -209,13 +210,13 @@ u8 I8042Controller::do_write_to_device(HIDDevice::Type device, u8 data) do { if (device != HIDDevice::Type::Keyboard) { prepare_for_output(); - IO::out8(I8042_STATUS, 0xd4); + IO::out8(I8042Port::Command, I8042Command::WriteSecondPS2PortInputBuffer); } prepare_for_output(); - IO::out8(I8042_BUFFER, data); + IO::out8(I8042Port::Buffer, data); - response = do_wait_then_read(I8042_BUFFER); - } while (response == I8042_RESEND && ++attempts < 3); + response = do_wait_then_read(I8042Port::Buffer); + } while (response == I8042Response::Resend && ++attempts < 3); if (attempts >= 3) dbgln("Failed to write byte to device, gave up"); return response; @@ -226,16 +227,20 @@ u8 I8042Controller::do_read_from_device(HIDDevice::Type device) VERIFY(device != HIDDevice::Type::Unknown); prepare_for_input(device); - return IO::in8(I8042_BUFFER); + return IO::in8(I8042Port::Buffer); } void I8042Controller::prepare_for_input(HIDDevice::Type device) { VERIFY(m_lock.is_locked()); - const u8 buffer_type = device == HIDDevice::Type::Keyboard ? I8042_KEYBOARD_BUFFER : I8042_MOUSE_BUFFER; + u8 const second_port_flag = device == HIDDevice::Type::Keyboard ? 0 : I8042StatusFlag::SecondPS2PortOutputBuffer; for (;;) { - u8 status = IO::in8(I8042_STATUS); - if ((status & I8042_BUFFER_FULL) && (device == HIDDevice::Type::Unknown || ((status & I8042_WHICH_BUFFER) == buffer_type))) + u8 status = IO::in8(I8042Port::Status); + if (!(status & I8042StatusFlag::OutputBuffer)) + continue; + if (device == HIDDevice::Type::Unknown) + return; + if ((status & I8042StatusFlag::SecondPS2PortOutputBuffer) == second_port_flag) return; } } @@ -244,7 +249,8 @@ void I8042Controller::prepare_for_output() { VERIFY(m_lock.is_locked()); for (;;) { - if (!(IO::in8(I8042_STATUS) & 2)) + u8 status = IO::in8(I8042Port::Status); + if (!(status & I8042StatusFlag::InputBuffer)) return; } } diff --git a/Kernel/Devices/HID/I8042Controller.h b/Kernel/Devices/HID/I8042Controller.h index cc67b636abf..190d5c50449 100644 --- a/Kernel/Devices/HID/I8042Controller.h +++ b/Kernel/Devices/HID/I8042Controller.h @@ -13,16 +13,55 @@ namespace Kernel { -#define I8042_BUFFER 0x60 -#define I8042_STATUS 0x64 -#define I8042_ACK 0xFA -#define I8042_RESEND 0xFE -#define I8042_BUFFER_FULL 0x01 +enum I8042Port : u8 { + Buffer = 0x60, + Command = 0x64, + Status = 0x64, +}; -#define I8042_WHICH_BUFFER 0x20 +enum I8042Command : u8 { + ReadConfiguration = 0x20, + WriteConfiguration = 0x60, + DisableSecondPS2Port = 0xA7, + EnableSecondPS2Port = 0xA8, + TestSecondPS2Port = 0xA9, + TestPS2Controller = 0xAA, + TestFirstPS2Port = 0xAB, + DisableFirstPS2Port = 0xAD, + EnableFirstPS2Port = 0xAE, + WriteSecondPS2PortInputBuffer = 0xD4, + GetDeviceID = 0xF2, + SetSampleRate = 0xF3, + EnablePacketStreaming = 0xF4, + SetDefaults = 0xF6, + Reset = 0xFF, +}; -#define I8042_KEYBOARD_BUFFER 0x00 -#define I8042_MOUSE_BUFFER 0x20 +enum I8042ConfigurationFlag : u8 { + FirstPS2PortInterrupt = 1 << 0, + SecondPS2PortInterrupt = 1 << 1, + SystemFlag = 1 << 2, + FirstPS2PortClock = 1 << 4, + SecondPS2PortClock = 1 << 5, + FirstPS2PortTranslation = 1 << 6, +}; + +enum I8042StatusFlag : u8 { + OutputBuffer = 1 << 0, + InputBuffer = 1 << 1, + System = 1 << 2, + InputType = 1 << 3, + SecondPS2PortOutputBuffer = 1 << 5, + TimeoutError = 1 << 6, + ParityError = 1 << 7, +}; + +enum I8042Response : u8 { + ControllerTestPassed = 0x55, + Success = 0xAA, + Acknowledge = 0xFA, + Resend = 0xFE, +}; class I8042Controller; class I8042Device { diff --git a/Kernel/Devices/HID/PS2KeyboardDevice.cpp b/Kernel/Devices/HID/PS2KeyboardDevice.cpp index 9d2b727616b..47d907198d2 100644 --- a/Kernel/Devices/HID/PS2KeyboardDevice.cpp +++ b/Kernel/Devices/HID/PS2KeyboardDevice.cpp @@ -63,7 +63,7 @@ void PS2KeyboardDevice::irq_handle_byte_read(u8 byte) break; } switch (ch) { - case I8042_ACK: + case I8042Response::Acknowledge: break; default: if ((m_modifiers & Mod_Alt) != 0 && ch >= 2 && ch <= ConsoleManagement::s_max_virtual_consoles + 1) { diff --git a/Kernel/Devices/HID/PS2MouseDevice.cpp b/Kernel/Devices/HID/PS2MouseDevice.cpp index af86416e720..0f2009fa66d 100644 --- a/Kernel/Devices/HID/PS2MouseDevice.cpp +++ b/Kernel/Devices/HID/PS2MouseDevice.cpp @@ -16,17 +16,6 @@ namespace Kernel { #define IRQ_MOUSE 12 -#define PS2MOUSE_SET_RESOLUTION 0xE8 -#define PS2MOUSE_STATUS_REQUEST 0xE9 -#define PS2MOUSE_REQUEST_SINGLE_PACKET 0xEB -#define PS2MOUSE_GET_DEVICE_ID 0xF2 -#define PS2MOUSE_SET_SAMPLE_RATE 0xF3 -#define PS2MOUSE_ENABLE_PACKET_STREAMING 0xF4 -#define PS2MOUSE_DISABLE_PACKET_STREAMING 0xF5 -#define PS2MOUSE_SET_DEFAULTS 0xF6 -#define PS2MOUSE_RESEND 0xFE -#define PS2MOUSE_RESET 0xFF - #define PS2MOUSE_INTELLIMOUSE_ID 0x03 #define PS2MOUSE_INTELLIMOUSE_EXPLORER_ID 0x04 @@ -142,7 +131,7 @@ MousePacket PS2MouseDevice::parse_data_packet(const RawPacket& raw_packet) u8 PS2MouseDevice::get_device_id() { - if (send_command(PS2MOUSE_GET_DEVICE_ID) != I8042_ACK) + if (send_command(I8042Command::GetDeviceID) != I8042Response::Acknowledge) return 0; return read_from_device(); } @@ -155,22 +144,22 @@ u8 PS2MouseDevice::read_from_device() u8 PS2MouseDevice::send_command(u8 command) { u8 response = m_i8042_controller->send_command(instrument_type(), command); - if (response != I8042_ACK) - dbgln("PS2MouseDevice: Command {} got {} but expected ack: {}", command, response, I8042_ACK); + if (response != I8042Response::Acknowledge) + dbgln("PS2MouseDevice: Command {} got {} but expected ack: {}", command, response, static_cast(I8042Response::Acknowledge)); return response; } u8 PS2MouseDevice::send_command(u8 command, u8 data) { u8 response = m_i8042_controller->send_command(instrument_type(), command, data); - if (response != I8042_ACK) - dbgln("PS2MouseDevice: Command {} got {} but expected ack: {}", command, response, I8042_ACK); + if (response != I8042Response::Acknowledge) + dbgln("PS2MouseDevice: Command {} got {} but expected ack: {}", command, response, static_cast(I8042Response::Acknowledge)); return response; } void PS2MouseDevice::set_sample_rate(u8 rate) { - send_command(PS2MOUSE_SET_SAMPLE_RATE, rate); + send_command(I8042Command::SetSampleRate, rate); } UNMAP_AFTER_INIT RefPtr PS2MouseDevice::try_to_initialize(const I8042Controller& ps2_controller) @@ -192,11 +181,10 @@ UNMAP_AFTER_INIT bool PS2MouseDevice::initialize() u8 device_id = read_from_device(); - // Set default settings. - if (send_command(PS2MOUSE_SET_DEFAULTS) != I8042_ACK) + if (send_command(I8042Command::SetDefaults) != I8042Response::Acknowledge) return false; - if (send_command(PS2MOUSE_ENABLE_PACKET_STREAMING) != I8042_ACK) + if (send_command(I8042Command::EnablePacketStreaming) != I8042Response::Acknowledge) return false; if (device_id != PS2MOUSE_INTELLIMOUSE_ID) {