/* * Copyright (c) 2021-2022, Liav A. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include namespace Kernel { class AsyncBlockDeviceRequest; class AHCIInterruptHandler; class AHCIPort; class AHCIController final : public ATAController , public PCI::Device { friend class AHCIInterruptHandler; public: static ErrorOr> initialize(PCI::DeviceIdentifier const& pci_device_identifier); virtual ~AHCIController() override; virtual StringView device_name() const override { return "AHCI"sv; } virtual LockRefPtr device(u32 index) const override; virtual ErrorOr reset() override; virtual ErrorOr shutdown() override; virtual size_t devices_count() const override; virtual void start_request(ATADevice const&, AsyncBlockDeviceRequest&) override; virtual void complete_current_request(AsyncDeviceRequest::RequestResult) override; void handle_interrupt_for_port(Badge, u32 port_index) const; private: void disable_global_interrupts() const; void enable_global_interrupts() const; explicit AHCIController(PCI::DeviceIdentifier const&); ErrorOr initialize_hba(PCI::DeviceIdentifier const&); AHCI::HBADefinedCapabilities capabilities() const; LockRefPtr device_by_port(u32 index) const; volatile AHCI::PortRegisters& port(size_t port_number) const; ErrorOr> map_default_hba_region(PCI::DeviceIdentifier const&); volatile AHCI::HBA& hba() const; Array, 32> m_ports; Memory::TypedMapping m_hba_mapping; AHCI::HBADefinedCapabilities m_hba_capabilities; // FIXME: There could be multiple IRQ (MSI) handlers for AHCI. Find a way to use all of them. OwnPtr m_irq_handler; // Note: This lock is intended to be locked when doing changes to HBA registers // that affect its core functionality in a manner that controls all attached storage devices // to the HBA SATA ports. mutable Spinlock m_hba_control_lock {}; }; }