PCI XHCI allocate only necessary pages
All checks were successful
Build ISO image / build-and-deploy (push) Successful in 3m6s
Build documentation / build-and-deploy (push) Successful in 2m54s

This commit is contained in:
2026-03-26 00:29:42 +01:00
parent 99712af7dd
commit bcdd769967
5 changed files with 63 additions and 2 deletions

View File

@@ -14,6 +14,7 @@
#define AMD64_PG_PRESENT (1 << 0) #define AMD64_PG_PRESENT (1 << 0)
#define AMD64_PG_RW (1 << 1) #define AMD64_PG_RW (1 << 1)
#define AMD64_PG_USER (1 << 2) #define AMD64_PG_USER (1 << 2)
#define AMD64_PG_PWT (1 << 3)
#define AMD64_PG_PCD (1 << 4) #define AMD64_PG_PCD (1 << 4)
#define AMD64_PG_HUGE (1 << 7) #define AMD64_PG_HUGE (1 << 7)
@@ -98,7 +99,7 @@ static uint64_t mm_resolve_flags (uint32_t generic) {
flags |= ((generic & MM_PG_PRESENT) ? AMD64_PG_PRESENT : 0); flags |= ((generic & MM_PG_PRESENT) ? AMD64_PG_PRESENT : 0);
flags |= ((generic & MM_PG_RW) ? AMD64_PG_RW : 0); flags |= ((generic & MM_PG_RW) ? AMD64_PG_RW : 0);
flags |= ((generic & MM_PG_USER) ? AMD64_PG_USER : 0); flags |= ((generic & MM_PG_USER) ? AMD64_PG_USER : 0);
flags |= ((generic & MM_PG_NOCACHE ? AMD64_PG_PCD : 0)); flags |= ((generic & MM_PG_NOCACHE ? (AMD64_PG_PCD | AMD64_PG_PWT) : 0));
return flags; return flags;
} }

View File

@@ -128,6 +128,38 @@ uint8_t pci_find_cap (uint8_t bus, uint8_t slot, uint8_t func, uint8_t cap_id) {
return 0; return 0;
} }
uint64_t pci_get_bar_size (uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) {
uint32_t bar = pci_read32 (bus, slot, func, offset);
pci_write32 (bus, slot, func, offset, 0xFFFFFFFF);
uint32_t mask = pci_read32 (bus, slot, func, offset);
pci_write32 (bus, slot, func, offset, bar);
if (mask == 0)
return 0;
uint64_t full_mask;
if ((bar & PCI_BAR_MEM32) || (bar & PCI_BAR_MEM64)) {
full_mask = mask & ~0xF;
if ((bar & PCI_BAR_MEM64)) {
uint32_t bar_hi = pci_read32 (bus, slot, func, offset + 4);
pci_write32 (bus, slot, func, offset + 4, 0xFFFFFFFF);
uint32_t mask_hi = pci_read32 (bus, slot, func, offset + 4);
pci_write32 (bus, slot, func, offset + 4, bar_hi);
full_mask |= ((uint64_t)mask_hi << 32);
}
} else {
full_mask = mask & ~0x3;
full_mask |= 0xFFFFFFFF00000000ULL;
}
return (~full_mask) + 1;
}
bool pci_msi_init (uint8_t bus, uint8_t slot, uint8_t func, uint8_t vec, uint32_t lapic_id) { bool pci_msi_init (uint8_t bus, uint8_t slot, uint8_t func, uint8_t vec, uint32_t lapic_id) {
struct limine_hhdm_response* hhdm = limine_hhdm_request.response; struct limine_hhdm_response* hhdm = limine_hhdm_request.response;

View File

@@ -82,6 +82,8 @@ uint8_t pci_find_cap (uint8_t bus, uint8_t slot, uint8_t func, uint8_t cap_id);
bool pci_msi_init (uint8_t bus, uint8_t slot, uint8_t func, uint8_t vec, uint32_t lapic_id); bool pci_msi_init (uint8_t bus, uint8_t slot, uint8_t func, uint8_t vec, uint32_t lapic_id);
uint64_t pci_get_bar_size (uint8_t bus, uint8_t slot, uint8_t func, uint8_t bar_offset);
extern const struct pci_vendor pci_vendors[]; extern const struct pci_vendor pci_vendors[];
extern const struct pci_device_id pci_device_names[]; extern const struct pci_device_id pci_device_names[];

View File

@@ -42,8 +42,11 @@ bool pci_xhci_init (struct proc* proc, struct reschedule_ctx* rctx, struct pci_i
} }
uintptr_t xhci_phys = 0; uintptr_t xhci_phys = 0;
size_t map_pages = 0;
uint32_t bar0 = pci_read32 (pci_info.bus, pci_info.slot, pci_info.func, PCI_BAR0); uint32_t bar0 = pci_read32 (pci_info.bus, pci_info.slot, pci_info.func, PCI_BAR0);
map_pages = pci_get_bar_size (pci_info.bus, pci_info.slot, pci_info.func, PCI_BAR0);
map_pages = div_align_up (map_pages, PAGE_SIZE);
if ((bar0 & PCI_BAR_MEM64)) { if ((bar0 & PCI_BAR_MEM64)) {
uint32_t bar1 = pci_read32 (pci_info.bus, pci_info.slot, pci_info.func, PCI_BAR1); uint32_t bar1 = pci_read32 (pci_info.bus, pci_info.slot, pci_info.func, PCI_BAR1);
@@ -61,7 +64,9 @@ bool pci_xhci_init (struct proc* proc, struct reschedule_ctx* rctx, struct pci_i
uintptr_t xhci_base = xhci_phys + (uintptr_t)hhdm->offset; uintptr_t xhci_base = xhci_phys + (uintptr_t)hhdm->offset;
for (size_t page = 0; page < 8; page++) { DEBUG ("BAR size = %zu pages\n", map_pages);
for (size_t page = 0; page < map_pages; page++) {
mm_map_kernel_page (xhci_phys + page * PAGE_SIZE, xhci_base + page * PAGE_SIZE, mm_map_kernel_page (xhci_phys + page * PAGE_SIZE, xhci_base + page * PAGE_SIZE,
MM_PG_RW | MM_PG_PRESENT | MM_PG_NOCACHE); MM_PG_RW | MM_PG_PRESENT | MM_PG_NOCACHE);
} }

View File

@@ -188,6 +188,27 @@ static void xhci_event_dispatch (struct xhci* xhci, struct xhci_trb* event, uint
DEBUG ("cmd completion: code=%u,slot=%u\n", cmpl_code, slot_id); DEBUG ("cmd completion: code=%u,slot=%u\n", cmpl_code, slot_id);
} break; } break;
case XHCI_TRB_PORT_STS_CHNG: {
uint8_t port = ((event->param >> 24) & 0xFF) - 1;
uint32_t portsc = xhci_portsc_read (xhci, port);
DEBUG ("Status change on port %u: 0x%08x\n", port, portsc);
/* ack. PED + PR */
portsc &= ~((1 << 1) | (1 << 4));
xhci_portsc_write (xhci, port, portsc);
if ((portsc & (1 << 17))) {
if ((portsc & (1 << 0)))
DEBUG ("Device attached to port %u!\n", port);
else
DEBUG ("Device detached from port %u!\n", port);
}
if ((portsc & (1 << 21)))
DEBUG ("Port %u reset done\n", port);
} break;
default: default:
DEBUG ("Unhandled event type %u at %u\n", type, xhci->event_ring_idx); DEBUG ("Unhandled event type %u at %u\n", type, xhci->event_ring_idx);
break; break;