From a02df12924219b423a68f85acaedeee404c67109 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Tue, 20 Feb 2024 11:23:12 -0500 Subject: [PATCH] Add XHCI.reset() --- src/hulk/usb/xhci.d | 60 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/hulk/usb/xhci.d b/src/hulk/usb/xhci.d index d23f8e1..f012b89 100644 --- a/src/hulk/usb/xhci.d +++ b/src/hulk/usb/xhci.d @@ -11,6 +11,8 @@ module hulk.usb.xhci; import hulk.pci; import hulk.hurl.a1; import hulk.klog; +import hulk.time; +import core.volatile; struct XHCI { @@ -351,6 +353,14 @@ struct XHCI m_runtime_registers = cast(RuntimeRegisters *)(base_address + m_capability_registers.rts_offset); m_doorbell_registers = cast(DoorbellRegister *)(base_address + m_capability_registers.doorbell_offset); dump_extended_capabilities(); + if (reset()) + { + Klog.writefln("XHCI controller initialization successful"); + } + else + { + Klog.writefln("XHCI controller failed to initialize"); + } } private void dump_extended_capabilities() @@ -393,6 +403,56 @@ struct XHCI } } + private bool reset() + { + /* Clear run/stop bit. */ + m_operational_registers.usb_command &= ~0x1u; + + /* Wait for HCHalted bit to be set. */ + enum halt_timeout = 40u; + for (size_t halt_timeout_counter = 0u;;) + { + Time.msleep(1u); + + if ((volatileLoad(&m_operational_registers.usb_status) & 1u) != 0u) + { + break; + } + + halt_timeout_counter++; + if (halt_timeout_counter >= halt_timeout) + { + Klog.writefln("XHCI controller failed to halt"); + return false; + } + } + + /* Set HC reset bit. */ + m_operational_registers.usb_command |= (1u << 1u); + + /* Wait for controller to be ready. */ + enum reset_timeout = 100u; + for (size_t reset_timeout_counter = 0u;;) + { + Time.msleep(1u); + + if (((volatileLoad(&m_operational_registers.usb_command) & (1u << 1u)) == 0u) && + ((volatileLoad(&m_operational_registers.usb_status) & (1u << 11u)) == 0u)) + { + break; + } + + reset_timeout_counter++; + if (reset_timeout_counter >= reset_timeout) + { + Klog.writefln("XHCI controller failed to reset"); + return false; + } + } + + return true; + } + static void build(Pci.Device * pci_device) { if (pci_device.memory_ranges[0].address != null)