mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-29 05:38:21 +00:00
PCI enumeration
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -65,6 +65,8 @@ void kmain(){
|
||||
apic_init();
|
||||
|
||||
apic_lapicinit();
|
||||
|
||||
pci_enumerate();
|
||||
|
||||
smp_init();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user