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:
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user