Add XHCI.reset()

This commit is contained in:
Josh Holtrop 2024-02-20 11:23:12 -05:00
parent 699f53ac15
commit a02df12924

View File

@ -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)