Kernel: Take ownership of xHCI controller from bios
This commit is contained in:
parent
baa4e6475a
commit
86e9d92ecb
|
@ -38,7 +38,8 @@ namespace Kernel
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<XHCIController>> initialize(PCI::Device&);
|
static BAN::ErrorOr<void> take_ownership(PCI::Device&);
|
||||||
|
static BAN::ErrorOr<BAN::UniqPtr<XHCIController>> create(PCI::Device&);
|
||||||
|
|
||||||
void handle_irq() final override;
|
void handle_irq() final override;
|
||||||
|
|
||||||
|
|
|
@ -409,6 +409,17 @@ namespace Kernel::XHCI
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ExtendedCap) == 4);
|
static_assert(sizeof(ExtendedCap) == 4);
|
||||||
|
|
||||||
|
struct USBLegacySupportCap
|
||||||
|
{
|
||||||
|
uint32_t capability_id : 8;
|
||||||
|
uint32_t next_capability : 8;
|
||||||
|
uint32_t hc_bios_owned_semaphore : 1;
|
||||||
|
uint32_t : 7;
|
||||||
|
uint32_t hc_os_owned_semaphore : 1;
|
||||||
|
uint32_t : 7;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(USBLegacySupportCap) == 4);
|
||||||
|
|
||||||
struct SupportedPrococolCap
|
struct SupportedPrococolCap
|
||||||
{
|
{
|
||||||
uint32_t capability_id : 8;
|
uint32_t capability_id : 8;
|
||||||
|
|
|
@ -241,8 +241,6 @@ namespace Kernel::Input
|
||||||
|
|
||||||
BAN::ErrorOr<void> PS2Controller::initialize_impl()
|
BAN::ErrorOr<void> PS2Controller::initialize_impl()
|
||||||
{
|
{
|
||||||
// FIXME: Initialise USB Controllers
|
|
||||||
|
|
||||||
// Determine if the PS/2 Controller Exists
|
// Determine if the PS/2 Controller Exists
|
||||||
auto* fadt = static_cast<const ACPI::FADT*>(ACPI::ACPI::get().get_header("FACP"_sv, 0));
|
auto* fadt = static_cast<const ACPI::FADT*>(ACPI::ACPI::get().get_header("FACP"_sv, 0));
|
||||||
if (fadt && fadt->revision > 1 && !(fadt->iapc_boot_arch & (1 << 1)))
|
if (fadt && fadt->revision > 1 && !(fadt->iapc_boot_arch & (1 << 1)))
|
||||||
|
|
|
@ -13,6 +13,36 @@ namespace Kernel
|
||||||
ASSERT(!s_instance);
|
ASSERT(!s_instance);
|
||||||
auto manager = TRY(BAN::UniqPtr<USBManager>::create());
|
auto manager = TRY(BAN::UniqPtr<USBManager>::create());
|
||||||
s_instance = BAN::move(manager);
|
s_instance = BAN::move(manager);
|
||||||
|
|
||||||
|
PCI::PCIManager::get().for_each_device(
|
||||||
|
[](PCI::Device& pci_device)
|
||||||
|
{
|
||||||
|
if (pci_device.class_code() != 0x0C || pci_device.subclass() != 0x03)
|
||||||
|
return;
|
||||||
|
switch (pci_device.prog_if())
|
||||||
|
{
|
||||||
|
case 0x00:
|
||||||
|
dprintln("Unsupported UHCI controller");
|
||||||
|
break;
|
||||||
|
case 0x10:
|
||||||
|
dprintln("Unsupported OHCI controller");
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
dprintln("Unsupported EHCI controller");
|
||||||
|
break;
|
||||||
|
case 0x30:
|
||||||
|
if (auto ret = XHCIController::take_ownership(pci_device); ret.is_error())
|
||||||
|
dprintln("Could not take ownership of xHCI controller: {}", ret.error());
|
||||||
|
else
|
||||||
|
dprintln("Took ownership of xHCI controller");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dprintln("Unsupported USB controller, prog if {2H}", pci_device.prog_if());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,12 +70,13 @@ namespace Kernel
|
||||||
dprintln("Unsupported EHCI controller");
|
dprintln("Unsupported EHCI controller");
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
case 0x30:
|
case 0x30:
|
||||||
if (auto ret = XHCIController::initialize(pci_device); ret.is_error())
|
if (auto ret = XHCIController::create(pci_device); ret.is_error())
|
||||||
dprintln("Could not initialize XHCI controller: {}", ret.error());
|
dprintln("Could not initialize XHCI controller: {}", ret.error());
|
||||||
else
|
else
|
||||||
controller = ret.release_value();
|
controller = ret.release_value();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
dprintln("Unsupported USB controller, prog if {2H}", pci_device.prog_if());
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,51 @@ namespace Kernel
|
||||||
m_port_updater->exit(0, SIGKILL);
|
m_port_updater->exit(0, SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<XHCIController>> XHCIController::initialize(PCI::Device& pci_device)
|
BAN::ErrorOr<void> XHCIController::take_ownership(PCI::Device& pci_device)
|
||||||
|
{
|
||||||
|
auto bar = TRY(pci_device.allocate_bar_region(0));
|
||||||
|
if (bar->type() != PCI::BarType::MEM)
|
||||||
|
{
|
||||||
|
dwarnln("XHCI controller with non-memory configuration space");
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& capabilities = *reinterpret_cast<volatile XHCI::CapabilityRegs*>(bar->vaddr());
|
||||||
|
const uint16_t ext_offset = capabilities.hccparams1.xhci_extended_capabilities_pointer;
|
||||||
|
if (ext_offset == 0)
|
||||||
|
{
|
||||||
|
dwarnln("XHCI controller does not have extended capabilities");
|
||||||
|
return BAN::Error::from_errno(EFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
vaddr_t ext_addr = bar->vaddr() + ext_offset * 4;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto& ext_cap = *reinterpret_cast<volatile XHCI::ExtendedCap*>(ext_addr);
|
||||||
|
|
||||||
|
if (ext_cap.capability_id == XHCI::ExtendedCapabilityID::USBLegacySupport)
|
||||||
|
{
|
||||||
|
auto& legacy = *reinterpret_cast<volatile XHCI::USBLegacySupportCap*>(ext_addr);
|
||||||
|
if (!legacy.hc_bios_owned_semaphore)
|
||||||
|
return {};
|
||||||
|
legacy.hc_os_owned_semaphore = 1;
|
||||||
|
|
||||||
|
const uint64_t timeout_ms = SystemTimer::get().ms_since_boot() + 1000;
|
||||||
|
while (legacy.hc_bios_owned_semaphore)
|
||||||
|
if (SystemTimer::get().ms_since_boot() > timeout_ms)
|
||||||
|
return BAN::Error::from_errno(ETIMEDOUT);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ext_cap.next_capability == 0)
|
||||||
|
break;
|
||||||
|
ext_addr += ext_cap.next_capability * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::UniqPtr<XHCIController>> XHCIController::create(PCI::Device& pci_device)
|
||||||
{
|
{
|
||||||
auto controller = TRY(BAN::UniqPtr<XHCIController>::create(pci_device));
|
auto controller = TRY(BAN::UniqPtr<XHCIController>::create(pci_device));
|
||||||
TRY(controller->initialize_impl());
|
TRY(controller->initialize_impl());
|
||||||
|
|
|
@ -189,6 +189,9 @@ static void init2(void*)
|
||||||
PCI::PCIManager::initialize();
|
PCI::PCIManager::initialize();
|
||||||
dprintln("PCI initialized");
|
dprintln("PCI initialized");
|
||||||
|
|
||||||
|
MUST(USBManager::initialize());
|
||||||
|
dprintln("USBManager initialized");
|
||||||
|
|
||||||
if (ACPI::ACPI::get().enter_acpi_mode(InterruptController::get().is_using_apic()).is_error())
|
if (ACPI::ACPI::get().enter_acpi_mode(InterruptController::get().is_using_apic()).is_error())
|
||||||
dprintln("Failed to enter ACPI mode");
|
dprintln("Failed to enter ACPI mode");
|
||||||
|
|
||||||
|
@ -202,14 +205,12 @@ static void init2(void*)
|
||||||
// Initialize empty keymap
|
// Initialize empty keymap
|
||||||
MUST(LibInput::KeyboardLayout::initialize());
|
MUST(LibInput::KeyboardLayout::initialize());
|
||||||
|
|
||||||
// FIXME: initialize PS/2 after USB
|
// FIXME: implement device hot plugging, so multiple devices is possible
|
||||||
//if (auto res = PS2Controller::initialize(); res.is_error())
|
//if (auto res = PS2Controller::initialize(); res.is_error())
|
||||||
// dprintln("{}", res.error());
|
// dprintln("{}", res.error());
|
||||||
|
|
||||||
MUST(NetworkManager::initialize());
|
MUST(NetworkManager::initialize());
|
||||||
|
|
||||||
MUST(USBManager::initialize());
|
|
||||||
|
|
||||||
// NOTE: PCI devices are the last ones to be initialized
|
// NOTE: PCI devices are the last ones to be initialized
|
||||||
// so other devices can reserve predefined interrupts
|
// so other devices can reserve predefined interrupts
|
||||||
PCI::PCIManager::get().initialize_devices();
|
PCI::PCIManager::get().initialize_devices();
|
||||||
|
|
Loading…
Reference in New Issue