diff --git a/kernel/amd64/mm.c b/kernel/amd64/mm.c index 48b070a..3adc750 100644 --- a/kernel/amd64/mm.c +++ b/kernel/amd64/mm.c @@ -14,6 +14,7 @@ #define AMD64_PG_PRESENT (1 << 0) #define AMD64_PG_RW (1 << 1) #define AMD64_PG_USER (1 << 2) +#define AMD64_PG_PWT (1 << 3) #define AMD64_PG_PCD (1 << 4) #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_RW) ? AMD64_PG_RW : 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; } diff --git a/kernel/device/pci.c b/kernel/device/pci.c index 5c9fe56..12503bc 100644 --- a/kernel/device/pci.c +++ b/kernel/device/pci.c @@ -128,6 +128,38 @@ uint8_t pci_find_cap (uint8_t bus, uint8_t slot, uint8_t func, uint8_t cap_id) { 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) { struct limine_hhdm_response* hhdm = limine_hhdm_request.response; diff --git a/kernel/device/pci.h b/kernel/device/pci.h index cdb0318..f43f3dd 100644 --- a/kernel/device/pci.h +++ b/kernel/device/pci.h @@ -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); +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_device_id pci_device_names[]; diff --git a/kernel/device/pci_xhci.c b/kernel/device/pci_xhci.c index ba6dab4..30a9b2f 100644 --- a/kernel/device/pci_xhci.c +++ b/kernel/device/pci_xhci.c @@ -42,8 +42,11 @@ bool pci_xhci_init (struct proc* proc, struct reschedule_ctx* rctx, struct pci_i } 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); + 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)) { 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; - 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_PG_RW | MM_PG_PRESENT | MM_PG_NOCACHE); } diff --git a/kernel/device/xhci.c b/kernel/device/xhci.c index 116f8cd..859c9ce 100644 --- a/kernel/device/xhci.c +++ b/kernel/device/xhci.c @@ -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); } 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: DEBUG ("Unhandled event type %u at %u\n", type, xhci->event_ring_idx); break;