From f31071371b6de75d4733f6c892dd013c7f455911 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 16 Jul 2023 21:44:02 -0300 Subject: [PATCH] pci: pci_setcommand and pci_mapbar --- kernel-src/include/kernel/pci.h | 28 +++++++++++++++++++--------- kernel-src/io/pci.c | 25 +++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/kernel-src/include/kernel/pci.h b/kernel-src/include/kernel/pci.h index 1a458d22..cc15a95b 100644 --- a/kernel-src/include/kernel/pci.h +++ b/kernel-src/include/kernel/pci.h @@ -1,27 +1,34 @@ #ifndef _PCI_H #define _PCI_H +#include +#include +#include + // 2 byte fields #define PCI_CONFIG_VENDOR 0x0 #define PCI_CONFIG_DEVICEID 0x2 +#define PCI_CONFIG_COMMAND 0x4 + #define PCI_COMMAND_IO 0x1 + #define PCI_COMMAND_MMIO 0x2 + #define PCI_COMMAND_IRQ 0x400 #define PCI_CONFIG_STATUS 0x6 -#define PCI_STATUS_HASCAP 0x10 + #define PCI_STATUS_HASCAP 0x10 // 1 byte fields #define PCI_CONFIG_REVISION 0x8 #define PCI_CONFIG_PROGIF 0x9 #define PCI_CONFIG_SUBCLASS 0xa + #define PCI_SUBCLASS_STORAGE_NVM 0x8 #define PCI_CONFIG_CLASS 0xb + #define PCI_CLASS_STORAGE 0x1 #define PCI_CONFIG_HEADERTYPE 0xe - -#define PCI_HEADERTYPE_MULTIFUNCTION_MASK 0x80 -#define PCI_HEADERTYPE_MASK 0x7f -#define PCI_HEADERTYPE_STANDARD 0 - + #define PCI_HEADERTYPE_MULTIFUNCTION_MASK 0x80 + #define PCI_HEADERTYPE_MASK 0x7f + #define PCI_HEADERTYPE_STANDARD 0 #define PCI_CONFIG_CAP 0x34 - -#define PCI_CAP_MSI 0x5 -#define PCI_CAP_MSIX 0x11 + #define PCI_CAP_MSI 0x5 + #define PCI_CAP_MSIX 0x11 typedef struct { bool exists; @@ -48,6 +55,7 @@ typedef struct { uintptr_t address; size_t length; bool mmio; + bool prefetchable; } pcibar_t; uint8_t pci_read8(int bus, int device, int function, uint32_t offset); @@ -59,6 +67,8 @@ void pci_write32(int bus, int device, int function, uint32_t offset, uint32_t va pcienum_t *pci_getenum(int class, int subclass, int progif, int vendor, int deviceid, int revision, int n); int pci_getcapoffset(pcienum_t *e, int cap, int n); pcibar_t pci_getbar(pcienum_t *e, int bar); +void *pci_mapbar(pcibar_t bar); +void pci_setcommand(pcienum_t *e, int mask, int v); void pci_init(); #endif diff --git a/kernel-src/io/pci.c b/kernel-src/io/pci.c index 0710a261..d9c1f70d 100644 --- a/kernel-src/io/pci.c +++ b/kernel-src/io/pci.c @@ -2,6 +2,7 @@ #include #include #include +#include uint8_t pci_read8(int bus, int device, int function, uint32_t offset) { return (pci_archread32(bus, device, function, offset) >> ((offset & 0b11) * 8)) & 0xff; @@ -52,28 +53,48 @@ int pci_getcapoffset(pcienum_t *e, int cap, int n) { return offset; } +void pci_setcommand(pcienum_t *e, int mask, int v) { + uint16_t current = pci_read16(e->bus, e->device, e->function, PCI_CONFIG_COMMAND); + + if (v) + current |= mask; + else + current &= ~mask; + + pci_write16(e->bus, e->device, e->function, PCI_CONFIG_COMMAND, current); +} + +#define BAR_MAP_FLAGS (ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_NOEXEC) + +void *pci_mapbar(pcibar_t bar) { + __assert(bar.mmio); + return vmm_map(NULL, bar.length, VMM_FLAGS_PHYSICAL, BAR_MAP_FLAGS | (bar.prefetchable ? ARCH_MMU_FLAGS_WT : ARCH_MMU_FLAGS_UC), (void *)bar.address); +} + #define BAR_IO 1 #define BAR_TYPE_MASK 0x6 #define BAR_TYPE_64BIT 0x4 +#define BAR_PREFETCHABLE 0x8 pcibar_t pci_getbar(pcienum_t *e, int n) { - // TODO map bars (also taking in count the prefetchable flag) pcibar_t ret; int offset = 0x10 + n * 4; uint32_t bar = pci_read32(e->bus, e->device, e->function, offset); if (bar & BAR_IO) { ret.mmio = false; + ret.prefetchable = false; ret.address = bar & 0xfffffffc; pci_write32(e->bus, e->device, e->function, offset, -1); ret.length = ~(pci_read32(e->bus, e->device, e->function, offset) & 0xfffffffc) + 1; pci_write32(e->bus, e->device, e->function, offset, bar); } else { ret.mmio = true; + ret.prefetchable = bar & BAR_PREFETCHABLE; ret.address = bar & 0xfffffff0; ret.length = -1; if ((bar & BAR_TYPE_MASK) == BAR_TYPE_64BIT) - ret.address = (uint64_t)pci_read32(e->bus, e->device, e->function, offset + 4) << 32; + ret.address += (uint64_t)pci_read32(e->bus, e->device, e->function, offset + 4) << 32; pci_write32(e->bus, e->device, e->function, offset, -1); ret.length = ~(pci_read32(e->bus, e->device, e->function, offset) & 0xfffffff0) + 1;