mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
pci: pci_setcommand and pci_mapbar
This commit is contained in:
@@ -1,27 +1,34 @@
|
||||
#ifndef _PCI_H
|
||||
#define _PCI_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// 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
|
||||
|
||||
+23
-2
@@ -2,6 +2,7 @@
|
||||
#include <arch/pci.h>
|
||||
#include <kernel/pci.h>
|
||||
#include <kernel/alloc.h>
|
||||
#include <kernel/vmm.h>
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user