PCI XHCI allocate only necessary pages
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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[];
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user