PCI enumeration

This commit is contained in:
Matheus
2022-08-06 21:34:52 -03:00
parent dee3fe16db
commit a69310a03c
5 changed files with 219 additions and 2 deletions
+15
View File
@@ -45,6 +45,21 @@ typedef struct {
uint32_t flags;
} __attribute__((packed)) madt_t;
typedef struct {
uint64_t address;
uint16_t segmentgroup;
uint8_t startbus;
uint8_t endbus;
uint32_t reserved;
} __attribute__((packed)) mcfgentry;
typedef struct {
sdt_t header;
uint64_t reserved;
mcfgentry entries[];
} __attribute__((packed)) mcfg_t;
void* acpi_gettable(char* sig, size_t n);
void acpi_init();
bool acpi_checksumok(sdt_t* table);
+12 -2
View File
@@ -1,13 +1,23 @@
#ifndef _IO_H_INCLUDE
#define _IO_H_INCLUDE
static inline void outd(uint16_t port, uint32_t data){
asm volatile("out %%eax, %%dx" : : "a"(data), "d"(port));
}
static inline uint32_t ind(uint16_t port){
uint32_t ret;
asm volatile("in %%dx, %%eax" : "=a"(ret) : "d"(port));
return ret;
}
static inline void outb(uint16_t port, uint8_t data){
asm("out %%al, %%dx" : : "a"(data), "d"(port));
asm volatile("out %%al, %%dx" : : "a"(data), "d"(port));
}
static inline uint8_t inb(uint16_t port){
uint8_t ret;
asm("in %%dx, %%al" : "=a"(ret) : "d"(port));
asm volatile ("in %%dx, %%al" : "=a"(ret) : "d"(port));
return ret;
}
+56
View File
@@ -0,0 +1,56 @@
#ifndef _PCI_H_INCLUDE
#define _PCI_H_INCLUDE
#include <stdint.h>
#include <stddef.h>
#define PCI_DEV_HEADER 0
#define PCI_BRIDGE_HEADER 1
#define PCI_CARDBUS_HEADER 2
#define PCI_CARDBUS_HEADERSIZE 0x48
#define PCI_OTHER_HEADERSIZE 0x40
typedef struct{
uint16_t vendor;
uint16_t device;
uint16_t command;
uint16_t status;
uint8_t revision;
uint8_t progif;
uint8_t subclass;
uint8_t class;
uint8_t cachesize;
uint8_t latencytimer;
uint8_t type;
uint8_t bist;
} __attribute__((packed)) pci_common;
typedef struct{
pci_common common;
uint32_t BAR[6];
uint32_t cardbuscis;
uint16_t subsystemvendor;
uint16_t subsystem;
uint32_t rombase;
uint8_t capabilities;
uint8_t r[3];
uint32_t reserved;
uint8_t interruptline;
uint8_t interruptpin;
uint8_t mingrant;
uint8_t maxgrant;
} __attribute__((packed)) pci_deviceheader;
typedef struct _pci_enumeration{
struct pci_enumeration* next;
uint8_t bus;
uint8_t device;
uint8_t function;
pci_common* header;
} pci_enumeration;
void pci_enumerate();
#endif
+2
View File
@@ -65,6 +65,8 @@ void kmain(){
apic_init();
apic_lapicinit();
pci_enumerate();
smp_init();
+134
View File
@@ -0,0 +1,134 @@
#include <arch/pci.h>
#include <arch/acpi.h>
#include <arch/io.h>
#include <kernel/alloc.h>
#include <stdio.h>
pci_enumeration* enumerations;
#define CONFIG_ADDRESS 0xCF8
#define CONFIG_DATA 0xCFC
uint32_t legacy_readdata(int bus, int device, int func, int reg){
uint32_t address = reg << 2;
address |= (func & 0b111) << 8;
address |= (device & 0b11111) << 11;
address |= (bus & 0xFF) << 16;
address |= 1 << 31;
outd(CONFIG_ADDRESS, address);
return ind(CONFIG_DATA);
}
static inline bool legacy_exists(int bus, int device, int func){
return legacy_readdata(bus, device, func, 0) != 0xFFFFFFFF;
}
static pci_enumeration* allocnewenum(){
pci_enumeration* enumeration;
if(!enumerations){
enumeration = alloc(sizeof(pci_enumeration));
}
else{
while(enumeration->next != NULL)
enumeration = enumeration->next;
enumeration->next = alloc(sizeof(pci_enumeration));
enumeration = enumeration->next;
}
return enumeration;
}
static void legacy_copyheader(pci_enumeration* dev, size_t size){
size_t count = size / 4;
uint32_t* where = (uint32_t*)dev->header;
for(size_t i = 0; i < count; ++i)
*where++ = legacy_readdata(dev->bus, dev->device, dev->function, i);
}
static size_t legacy_getcapabilityoffset(size_t id, pci_enumeration* enumeration){
// does this device have a capability list
if(enumeration->header->status & (1 << 4) == 0) return 0;
size_t offset = ((pci_deviceheader*)enumeration->header)->capabilities>> 2;
while(offset){
uint32_t word = legacy_readdata(enumeration->bus, enumeration->device, enumeration->function, offset);
size_t targetid = word & 0xFF;
if(targetid == id)
return offset;
offset = (word >> 8) & 0xFF;
offset >>= 2;
}
return 0;
}
static void legacy_enumeratedevice(int bus, int device){
// if the device is multifunction, scan and enumerate all 8. else, only one
size_t functioncount = ((legacy_readdata(bus, device, 0, 3) >> 16) & 0xFF) != 0 ? 8 : 1;
for(size_t function = 0; function < functioncount; ++function){
if(!legacy_exists(bus, device, function))
continue;
pci_enumeration* enumeration = allocnewenum();
enumeration->bus = bus;
enumeration->device = device;
enumeration->function = function;
// type with multifunction masked off
size_t type = (legacy_readdata(bus, device, function, 3) >> 16) & 0x7F;
size_t headersize = type == PCI_CARDBUS_HEADER ? PCI_CARDBUS_HEADERSIZE : PCI_OTHER_HEADERSIZE;
enumeration->header = alloc(headersize);
legacy_copyheader(enumeration, headersize);
printf("PCI: %02x:%02x.%x %02x%02x: %04x:%04x (rev %2x) \n", bus, device, function, enumeration->header->class, enumeration->header->subclass, enumeration->header->vendor, enumeration->header->device, enumeration->header->revision);
}
}
static void legacy_enumeration(){
for(size_t bus = 0; bus < 1; ++bus){
for(size_t device = 0; device < 32; ++device){
if(legacy_exists(bus, device, 0))
legacy_enumeratedevice(bus, device);
}
}
}
void pci_enumerate(){
// TODO PCIe enumeration
legacy_enumeration();
}