#pragma once #include #include #include namespace Kernel { class AHCIDevice final : public detail::ATABaseDevice { public: static BAN::ErrorOr> create(BAN::RefPtr, volatile HBAPortMemorySpace*); ~AHCIDevice() = default; private: AHCIDevice(BAN::RefPtr controller, volatile HBAPortMemorySpace* port) : m_controller(controller) , m_port(port) { } BAN::ErrorOr initialize(); BAN::ErrorOr allocate_buffers(); BAN::ErrorOr rebase(); BAN::ErrorOr read_identify_data(); virtual BAN::ErrorOr read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan) override; virtual BAN::ErrorOr write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan) override; BAN::ErrorOr send_command_and_block(uint64_t lba, uint64_t sector_count, Command command); BAN::Optional find_free_command_slot(); void handle_irq(); BAN::ErrorOr block_until_command_completed(uint32_t command_slot); private: BAN::RefPtr m_controller; volatile HBAPortMemorySpace* const m_port; BAN::UniqPtr m_dma_region; // Intermediate read/write buffer // TODO: can we read straight to user buffer? BAN::UniqPtr m_data_dma_region; friend class AHCIController; }; }