Kernel: Do a big rewrite of PS/2 code

Command sending+response reading is now synchronized. This allows
bochs to properly initialize both mouse and keyboard simultaneously.

Also status register is checked EVERY time read/write to other IO
ports is performed.
This commit is contained in:
2024-01-07 17:25:06 +02:00
parent 2fec718590
commit d760239748
9 changed files with 264 additions and 124 deletions

View File

@@ -11,10 +11,6 @@ namespace Kernel
ACPI_NoRootSDT,
ACPI_NoSuchHeader,
ACPI_RootInvalid,
PS2_Timeout,
PS2_SelfTest,
PS2_Reset,
PS2_UnsupportedDevice,
Ext2_Invalid,
Ext2_Corrupted,
Ext2_NoInodes,

View File

@@ -14,8 +14,8 @@ namespace Kernel::Input::PS2
enum Status : uint8_t
{
OUTPUT_FULL = (1 << 0),
INPUT_FULL = (1 << 1),
OUTPUT_STATUS = (1 << 0),
INPUT_STATUS = (1 << 1),
SYSTEM = (1 << 2),
DEVICE_OR_CONTROLLER = (1 << 3),
TIMEOUT_ERROR = (1 << 6),

View File

@@ -1,8 +1,10 @@
#pragma once
#include <BAN/CircularQueue.h>
#include <BAN/UniqPtr.h>
#include <kernel/Device/Device.h>
#include <kernel/Input/PS2/Config.h>
#include <kernel/InterruptController.h>
#include <kernel/SpinLock.h>
namespace Kernel::Input
{
@@ -15,7 +17,10 @@ namespace Kernel::Input
static BAN::ErrorOr<void> initialize();
static PS2Controller& get();
void send_byte(const PS2Device*, uint8_t);
BAN::ErrorOr<void> device_send_byte(PS2Device* device, uint8_t byte);
[[nodiscard]] bool lock_command(PS2Device*);
void unlock_command(PS2Device*);
private:
PS2Controller() = default;
@@ -25,8 +30,21 @@ namespace Kernel::Input
BAN::ErrorOr<void> reset_device(uint8_t);
BAN::ErrorOr<void> set_scanning(uint8_t, bool);
BAN::ErrorOr<uint8_t> read_byte();
BAN::ErrorOr<void> send_byte(uint16_t port, uint8_t byte);
BAN::ErrorOr<void> send_command(PS2::Command command);
BAN::ErrorOr<void> send_command(PS2::Command command, uint8_t data);
BAN::ErrorOr<void> device_send_byte(uint8_t device_index, uint8_t byte);
BAN::ErrorOr<void> device_read_ack(uint8_t device_index);
private:
PS2Device* m_devices[2] { nullptr, nullptr };
BAN::RefPtr<PS2Device> m_devices[2];
RecursiveSpinLock m_lock;
PS2Device* m_executing_device { nullptr };
PS2Device* m_pending_device { nullptr };
};
}

View File

@@ -1,6 +1,8 @@
#pragma once
#include <BAN/CircularQueue.h>
#include <kernel/Input/PS2/Controller.h>
#include <kernel/InterruptController.h>
namespace Kernel::Input
{
@@ -13,8 +15,8 @@ namespace Kernel::Input
virtual void send_initialize() = 0;
bool append_command_queue(uint8_t command);
bool append_command_queue(uint8_t command, uint8_t data);
bool append_command_queue(uint8_t command, uint8_t response_size);
bool append_command_queue(uint8_t command, uint8_t data, uint8_t response_size);
virtual void handle_irq() final override;
virtual void handle_byte(uint8_t) = 0;
@@ -24,13 +26,22 @@ namespace Kernel::Input
virtual dev_t rdev() const final override { return m_rdev; }
private:
void update();
void update_command();
private:
enum class State
{
Normal,
WaitingAck,
WaitingResponse,
};
struct Command
{
uint8_t out_data[2];
uint8_t out_count;
uint8_t in_count;
uint8_t send_index;
};
private:
@@ -39,7 +50,9 @@ namespace Kernel::Input
PS2Controller& m_controller;
State m_state = State::Normal;
BAN::CircularQueue<uint8_t, 10> m_command_queue;
BAN::CircularQueue<Command, 10> m_command_queue;
friend class PS2Controller;
};
}