#pragma once #include #include #include #include #include #include #include namespace Kernel { class XHCIDevice; class XHCIController : public USBController, public Interruptable { BAN_NON_COPYABLE(XHCIController); BAN_NON_MOVABLE(XHCIController); public: struct Port { uint8_t revision_major { 0 }; uint8_t revision_minor { 0 }; uint8_t slot_type { 0 }; uint8_t slot_id { 0 }; }; public: static BAN::ErrorOr take_ownership(PCI::Device&); static BAN::ErrorOr> create(PCI::Device&); void handle_irq() final override; private: XHCIController(PCI::Device& pci_device); ~XHCIController(); BAN::ErrorOr initialize_impl(); BAN::ErrorOr initialize_ports(); BAN::ErrorOr initialize_primary_interrupter(); BAN::ErrorOr initialize_scratchpad(); BAN::ErrorOr reset_controller(); void port_updater_task(); BAN::ErrorOr initialize_slot(int port_index); BAN::ErrorOr send_command(const XHCI::TRB&); void advance_command_enqueue(); bool context_size_set() { return capability_regs().hccparams1.context_size; } const Port& port(uint32_t port_id) const { return m_ports[port_id - 1]; } volatile XHCI::CapabilityRegs& capability_regs(); volatile XHCI::OperationalRegs& operational_regs(); volatile XHCI::RuntimeRegs& runtime_regs(); volatile uint32_t& doorbell_reg(uint32_t slot_id); volatile uint64_t& dcbaa_reg(uint32_t slot_id); const volatile XHCI::TRB& current_event_trb(); uint8_t speed_class_to_id(USB::SpeedClass speed_class) const; USB::SpeedClass speed_id_to_class(uint8_t) const; private: static constexpr uint32_t m_command_ring_trb_count = 256; static constexpr uint32_t m_event_ring_trb_count = 252; Mutex m_mutex; Process* m_port_updater { nullptr }; ThreadBlocker m_port_thread_blocker; BAN::Atomic m_port_changed { false }; PCI::Device& m_pci_device; BAN::UniqPtr m_configuration_bar; BAN::UniqPtr m_dcbaa_region; BAN::UniqPtr m_command_ring_region; uint32_t m_command_enqueue { 0 }; bool m_command_cycle { 1 }; BAN::UniqPtr m_scratchpad_buffer_array; BAN::Vector m_scratchpad_buffers; BAN::UniqPtr m_event_ring_region; uint32_t m_event_dequeue { 0 }; bool m_event_cycle { 1 }; BAN::Vector m_command_completions; BAN::Vector m_ports; BAN::Vector> m_slots; friend class XHCIDevice; friend class BAN::UniqPtr; }; }