Kernel: Add support for ACPI Embedded Controllers

This commit is contained in:
2025-08-11 20:32:24 +03:00
parent 8ed5a71c45
commit 58ad839136
7 changed files with 696 additions and 94 deletions

View File

@@ -2,6 +2,7 @@
#include <BAN/Vector.h>
#include <kernel/ACPI/AML/Namespace.h>
#include <kernel/ACPI/EmbeddedController.h>
#include <kernel/ACPI/Headers.h>
#include <kernel/Memory/Types.h>
#include <kernel/ThreadBlocker.h>
@@ -35,8 +36,12 @@ namespace Kernel::ACPI
BAN::ErrorOr<void> poweroff();
BAN::ErrorOr<void> reset();
BAN::ErrorOr<void> register_gpe_handler(uint8_t gpe, void (*callback)(void*), void* argument);
void handle_irq() override;
BAN::Span<BAN::UniqPtr<EmbeddedController>> embedded_controllers() { return m_embedded_controllers.span(); }
private:
ACPI() = default;
BAN::ErrorOr<void> initialize_impl();
@@ -50,6 +55,12 @@ namespace Kernel::ACPI
BAN::ErrorOr<void> route_interrupt_link_device(const AML::Scope& device, uint64_t& routed_irq_mask);
BAN::ErrorOr<void> initialize_embedded_controller(const AML::Scope& embedded_controller);
BAN::ErrorOr<void> initialize_embedded_controllers();
BAN::Optional<GAS> find_gpe_block(size_t index);
bool enable_gpe(uint8_t gpe);
private:
paddr_t m_header_table_paddr = 0;
vaddr_t m_header_table_vaddr = 0;
@@ -68,8 +79,23 @@ namespace Kernel::ACPI
ThreadBlocker m_event_thread_blocker;
BAN::Vector<BAN::UniqPtr<EmbeddedController>> m_embedded_controllers;
struct GPEHandler
{
bool has_callback { false };
union {
AML::Reference* method;
struct
{
void (*callback)(void*);
void* argument;
};
};
};
bool m_has_any_gpes { false };
AML::Scope m_gpe_scope;
BAN::Array<AML::Reference*, 0xFF> m_gpe_methods { nullptr };
BAN::Array<GPEHandler, 0xFF> m_gpe_methods;
bool m_hardware_reduced { false };
AML::Namespace* m_namespace { nullptr };

View File

@@ -0,0 +1,69 @@
#pragma once
#include <BAN/Atomic.h>
#include <BAN/UniqPtr.h>
#include <kernel/ACPI/AML/Scope.h>
#include <kernel/Lock/Mutex.h>
#include <kernel/Thread.h>
namespace Kernel::ACPI
{
class EmbeddedController
{
public:
static BAN::ErrorOr<BAN::UniqPtr<EmbeddedController>> create(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, BAN::Optional<uint8_t> gpe);
~EmbeddedController();
BAN::ErrorOr<uint8_t> read_byte(uint8_t offset);
BAN::ErrorOr<void> write_byte(uint8_t offset, uint8_t value);
const AML::Scope& scope() const { return m_scope; }
private:
EmbeddedController(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, bool has_gpe)
: m_scope(BAN::move(scope))
, m_command_port(command_port)
, m_data_port(data_port)
, m_has_gpe(has_gpe)
{ }
private:
void wait_status_bit(uint8_t bit, uint8_t value);
uint8_t read_one(uint16_t port);
void write_one(uint16_t port, uint8_t value);
static void handle_gpe_wrapper(void*);
void handle_gpe();
BAN::ErrorOr<void> call_query_method(uint8_t notification);
void thread_task();
struct Command
{
uint8_t command;
BAN::Optional<uint8_t> data1;
BAN::Optional<uint8_t> data2;
uint8_t* response;
BAN::Atomic<bool> done;
};
BAN::ErrorOr<void> send_command(Command& command);
private:
const AML::Scope m_scope;
const uint16_t m_command_port;
const uint16_t m_data_port;
const bool m_has_gpe;
Mutex m_mutex;
ThreadBlocker m_thread_blocker;
BAN::Optional<Command*> m_queued_command;
Thread* m_thread { nullptr };
};
}