diff --git a/kernel/include/kernel/USB/XHCI/Controller.h b/kernel/include/kernel/USB/XHCI/Controller.h index aa7582f1..3eac91c5 100644 --- a/kernel/include/kernel/USB/XHCI/Controller.h +++ b/kernel/include/kernel/USB/XHCI/Controller.h @@ -51,6 +51,7 @@ namespace Kernel BAN::ErrorOr initialize_impl(); BAN::ErrorOr initialize_ports(); BAN::ErrorOr initialize_primary_interrupter(); + BAN::ErrorOr initialize_scratchpad(); BAN::ErrorOr reset_controller(); @@ -91,6 +92,9 @@ namespace Kernel 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 }; diff --git a/kernel/kernel/USB/XHCI/Controller.cpp b/kernel/kernel/USB/XHCI/Controller.cpp index 02691ddb..cf3ac24a 100644 --- a/kernel/kernel/USB/XHCI/Controller.cpp +++ b/kernel/kernel/USB/XHCI/Controller.cpp @@ -18,6 +18,10 @@ namespace Kernel { if (m_port_updater) m_port_updater->exit(0, SIGKILL); + + for (auto paddr : m_scratchpad_buffers) + if (paddr) + Heap::get().release_page(paddr); } BAN::ErrorOr XHCIController::take_ownership(PCI::Device& pci_device) @@ -123,6 +127,8 @@ namespace Kernel TRY(initialize_primary_interrupter()); + TRY(initialize_scratchpad()); + // enable the controller operational.usbcmd.run_stop = 1; while (operational.usbsts & XHCI::USBSTS::HCHalted) @@ -238,6 +244,33 @@ namespace Kernel return {}; } + BAN::ErrorOr XHCIController::initialize_scratchpad() + { + auto& capabilities = capability_regs(); + + const uint32_t max_scratchpads = (capabilities.hcsparams2.max_scratchpad_buffers_hi << 5) | capabilities.hcsparams2.max_scratchpad_buffers_lo; + if (max_scratchpads == 0) + return {}; + + m_scratchpad_buffer_array = TRY(DMARegion::create(max_scratchpads * sizeof(uint64_t))); + TRY(m_scratchpad_buffers.resize(max_scratchpads)); + + auto* scratchpad_buffer_array = reinterpret_cast(m_scratchpad_buffer_array->vaddr()); + for (size_t i = 0; i < max_scratchpads; i++) + { + const paddr_t paddr = Heap::get().take_free_page(); + if (paddr == 0) + return BAN::Error::from_errno(ENOMEM); + m_scratchpad_buffers[i] = paddr; + scratchpad_buffer_array[i] = paddr; + } + + ASSERT(m_dcbaa_region); + *reinterpret_cast(m_dcbaa_region->vaddr()) = m_scratchpad_buffer_array->paddr(); + + return {}; + } + static Mutex s_port_mutex; void XHCIController::port_updater_task()