#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int xhci_counter = 0; bool pci_xhci_init (struct proc* proc, struct reschedule_ctx* rctx, struct pci_info pci_info) { struct limine_hhdm_response* hhdm = limine_hhdm_request.response; uint8_t progif = pci_read8 (pci_info.bus, pci_info.slot, pci_info.func, PCI_PROG_IF); /* not an XHCI controller */ if (progif != 0x30) { return true; } uint16_t pci_cmd = pci_read16 (pci_info.bus, pci_info.slot, pci_info.func, PCI_COMMAND); uint16_t new_cmd = (pci_cmd | (1 << 1) | (1 << 2)); if (pci_cmd != new_cmd) { pci_write16 (pci_info.bus, pci_info.slot, pci_info.func, PCI_COMMAND, new_cmd); } uintptr_t xhci_phys = 0; uint32_t bar0 = pci_read32 (pci_info.bus, pci_info.slot, pci_info.func, PCI_BAR0); if ((bar0 & PCI_BAR_MEM64)) { uint32_t bar1 = pci_read32 (pci_info.bus, pci_info.slot, pci_info.func, PCI_BAR1); xhci_phys = ((uint64_t)bar1 << 32) | (bar0 & ~0xF); DEBUG ("XHCI phys base addr=%p (64 bit)\n", xhci_phys); } else { xhci_phys = (bar0 & ~0xF); DEBUG ("XHCI phys base addr=%p (32 bit)\n", xhci_phys); } if (xhci_phys == 0) { DEBUG ("WARNING xhci_phys is NULL!\n"); return false; } uintptr_t xhci_base = xhci_phys + (uintptr_t)hhdm->offset; /* 2 pages should cover the mmio space */ mm_map_kernel_page (xhci_phys, xhci_base, MM_PG_RW | MM_PG_PRESENT); mm_map_kernel_page (xhci_phys + PAGE_SIZE, xhci_base + PAGE_SIZE, MM_PG_RW | MM_PG_PRESENT); char key[32]; snprintf (key, sizeof (key), "xhci%d", xhci_counter++); struct xhci_init init = {.xhci_mmio_base = xhci_base}; device_op_func_t ops[] = {0}; struct device* xhci = device_create (key, ops, lengthof (ops), &xhci_init, &xhci_fini, &init, proc, rctx); return true; }