/* * Copyright (c) 2021, Pankaj R * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Kernel { class NVMeController : public PCI::Device , public StorageController { public: static ErrorOr> try_initialize(PCI::DeviceIdentifier const&, bool is_queue_polled); ErrorOr initialize(bool is_queue_polled); LockRefPtr device(u32 index) const override; size_t devices_count() const override; virtual StringView device_name() const override { return "NVMeController"sv; } protected: ErrorOr reset() override; ErrorOr shutdown() override; void complete_current_request(AsyncDeviceRequest::RequestResult result) override; public: ErrorOr reset_controller(); ErrorOr start_controller(); u32 get_admin_q_dept(); u16 submit_admin_command(NVMeSubmission& sub, bool sync = false) { // First queue is always the admin queue if (sync) { return m_admin_queue->submit_sync_sqe(sub); } m_admin_queue->submit_sqe(sub); return 0; } bool is_admin_queue_ready() { return m_admin_queue_ready; } void set_admin_queue_ready_flag() { m_admin_queue_ready = true; } private: NVMeController(PCI::DeviceIdentifier const&, u32 hardware_relative_controller_id); ErrorOr identify_and_init_namespaces(); ErrorOr identify_and_init_controller(); Tuple get_ns_features(IdentifyNamespace& identify_data_struct); ErrorOr create_admin_queue(QueueType queue_type); ErrorOr create_io_queue(u8 qid, QueueType queue_type); void calculate_doorbell_stride() { m_dbl_stride = (m_controller_regs->cap >> CAP_DBL_SHIFT) & CAP_DBL_MASK; } bool wait_for_ready(bool); private: LockRefPtr m_admin_queue; Vector> m_queues; Vector> m_namespaces; Memory::TypedMapping m_controller_regs; RefPtr m_dbbuf_shadow_page; RefPtr m_dbbuf_eventidx_page; bool m_admin_queue_ready { false }; size_t m_device_count { 0 }; AK::Duration m_ready_timeout; PhysicalAddress m_bar { 0 }; u8 m_dbl_stride { 0 }; PCI::InterruptType m_irq_type; QueueType m_queue_type { QueueType::IRQ }; static Atomic s_controller_id; }; }