diff --git a/src/arch/x86_64/include/arch/pci.h b/src/arch/x86_64/include/arch/pci.h index 2dac70f1..7952812f 100644 --- a/src/arch/x86_64/include/arch/pci.h +++ b/src/arch/x86_64/include/arch/pci.h @@ -3,6 +3,7 @@ #include #include +#include #define PCI_DEV_HEADER 0 #define PCI_BRIDGE_HEADER 1 @@ -85,6 +86,11 @@ static inline void* getbarmemaddr(pci_deviceheader* e, int bar){ #define PCI_COMMAND_MEMORY 2 #define PCI_COMMAND_MASTER 4 +bool pci_msisupport(pci_enumeration* e); +void pci_msienable(pci_enumeration* e, bool enable); +void pci_msimask(pci_enumeration* e, int which, int val); +void pci_msimaskall(pci_enumeration* e, int val); + void pci_setcommand(pci_enumeration* e, int which, int val); pci_enumeration* pci_getdevicecs(int class, int subclass, int n); pci_enumeration* pci_getdevicecsp(int class, int subclass, int progif, int n); diff --git a/src/arch/x86_64/pci.c b/src/arch/x86_64/pci.c index 09f28ea5..f4be4551 100644 --- a/src/arch/x86_64/pci.c +++ b/src/arch/x86_64/pci.c @@ -10,6 +10,7 @@ pci_enumeration* enumerations; #define CONFIG_DATA 0xCFC #define COMMAND_REG 1 +#define CAP_MSI 5 pci_enumeration* pci_getdevicecs(int class, int subclass, int n){ @@ -178,6 +179,79 @@ static size_t legacy_getcapabilityoffset(size_t id, pci_enumeration* enumeration } +bool pci_msisupport(pci_enumeration* e){ + if(!legacy_getcapabilityoffset(CAP_MSI, e)) + return false; + + return true; +} + +void pci_msienable(pci_enumeration* e, bool enable){ + + int offset = legacy_getcapabilityoffset(CAP_MSI, e); + + if(!offset) + return; + + uint32_t currval = legacy_readdata(e->bus, e->device, e->function, offset); + + if((currval & 1 << 23) == 0) + _panic("32 bit MSI not supported!"); + + if(enable){ + currval |= 1 << 16; + } + else{ + currval &= ~(1 << 16); + } + + legacy_writedata(e->bus, e->device, e->function, offset, currval); + +} + +void pci_msimask(pci_enumeration* e, int which, int val){ + int offset = legacy_getcapabilityoffset(CAP_MSI, e); + + if(!offset) + return; + + offset += 2; + + uint32_t currval = legacy_readdata(e->bus, e->device, e->function, offset); + + if(val){ + currval |= 1 << which; + } + else{ + currval &= ~(1 << which); + } + + legacy_writedata(e->bus, e->device, e->function, offset, currval); + +} + +void pci_msimaskall(pci_enumeration* e, int val){ + + int offset = legacy_getcapabilityoffset(CAP_MSI, e); + + if(!offset) + return; + + offset += 2; + + uint32_t currval = legacy_readdata(e->bus, e->device, e->function, offset); + + if(val){ + currval = 0xFFFFFFFF; + } + else{ + currval = 0; + } + + legacy_writedata(e->bus, e->device, e->function, offset, currval); + +} + static void legacy_enumeratedevice(int bus, int device){ // if the device is multifunction, scan and enumerate all 8. else, only one diff --git a/src/sys/block/nvme.c b/src/sys/block/nvme.c index 29e1ad5c..b5c5832e 100644 --- a/src/sys/block/nvme.c +++ b/src/sys/block/nvme.c @@ -99,7 +99,15 @@ void nvme_initctlr(pci_enumeration* pci){ printf("Controller minimum page size is bigger than the system page size\n"); return; } + + // set relevant command stuff in the pci config space + pci_setcommand(pci, PCI_COMMAND_MEMORY, 1); + pci_setcommand(pci, PCI_COMMAND_MASTER, 1); + + pci_msienable(pci, true); // msi is always supported by nvme + pci_msimaskall(pci, 1); + // reset controller uint32_t cc = bar0->cc; @@ -126,7 +134,7 @@ void nvme_initctlr(pci_enumeration* pci){ bar0->cc = cc; // enable - + bar0->cc |= 1; while((bar0->csts & 3) == 0);