pci enumeration

This commit is contained in:
quackerd 2024-11-04 05:11:18 -05:00
parent b5ac633a9e
commit 4a7f582881
11 changed files with 158 additions and 81 deletions

3
sys/arm64/include/pci.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
int PCI_Discover(void);

View File

@ -7,6 +7,9 @@
#include <sys/mp.h>
#include <sys/irq.h>
#include <sys/spinlock.h>
#include <sys/pci.h>
#include <sys/ktime.h>
#include <sys/ktimer.h>
#include <machine/cpu.h>
#include <machine/trap.h>
@ -25,10 +28,8 @@
#include <machine/mrt.h>
#include <machine/pdcache.h>
#include <machine/timer.h>
#include <machine/pci.h>
extern void KTime_Init();
extern void KTimer_Init();
extern void PCI_Init();
extern void MachineBoot_AddMem();
extern void Loader_LoadInit();
extern void PAlloc_LateInit();
@ -113,11 +114,6 @@ void Machine_Init()
KTimer_Init();
enable_interrupts();
while(1){
hlt();
}
// GICv3
Thread_Init();
/*
@ -128,9 +124,16 @@ void Machine_Init()
/*
* Initialize Basic Devices
*/
int ret;
if ((ret = PCI_Discover()) != 0) {
Panic("Failed to detect PCIe host controller: %d.\n", ret);
}
PCI_Init(); // PCI BUS
BufCache_Init();
while(1){
hlt();
}
/*
* Open the primary disk and mount the root file system
*/

View File

@ -3,75 +3,93 @@
#include <sys/kassert.h>
#include <sys/pci.h>
#include <sys/contrib/libfdt/libfdt.h>
#include <errno.h>
#include <machine/bootinfo.h>
#include <machine/cpu.h>
#include <machine/cpuop.h>
#include <machine/pmap.h>
#include <machine/pci.h>
#define PCI_PORT_ADDR 0xCF8
#define PCI_PORT_DATABASE 0xCFC
static void * pci_conf_space;
static UNUSED size_t pci_conf_size;
static inline uint32_t
static inline volatile void *
PCIGetAddr(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
{
ASSERT(bus < 256 && slot < 64 && func < 8 && reg < 256);
return (1 << 31) | (bus << 16) | (slot << 11) | (func << 8) | (reg & 0x00fc);
return pci_conf_space + ((bus << 20) | (slot << 15) | (func << 12) | (reg & 0xff));
}
uint8_t
PCICfgRead8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
{
UNUSED uint32_t addr = PCIGetAddr(bus, slot, func, reg);
UNUSED uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
return 0;
volatile uint8_t * ret = PCIGetAddr(bus, slot, func, reg);
return * ret;
}
uint16_t
PCICfgRead16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
{
UNUSED uint32_t addr = PCIGetAddr(bus, slot, func, reg);
UNUSED uint16_t port = PCI_PORT_DATABASE + (reg & 0x2);
ASSERT((reg & 0x1) == 0);
return 0;
volatile uint16_t * ret = PCIGetAddr(bus, slot, func, reg);
return * ret;
}
uint32_t
PCICfgRead32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
{
UNUSED uint32_t addr = PCIGetAddr(bus, slot, func, reg);
UNUSED uint16_t port = PCI_PORT_DATABASE;
ASSERT((reg & 0x3) == 0);
return 0;
volatile uint32_t * ret = PCIGetAddr(bus, slot, func, reg);
return * ret;
}
void
PCICfgWrite8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
UNUSED uint8_t data)
PCICfgWrite8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg, uint8_t data)
{
UNUSED uint32_t addr = PCIGetAddr(bus, slot, func, reg);
UNUSED uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
volatile uint8_t * ret = PCIGetAddr(bus, slot, func, reg);
*ret = data;
}
void
PCICfgWrite16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
UNUSED uint16_t data)
uint16_t data)
{
UNUSED uint32_t addr = PCIGetAddr(bus, slot, func, reg);
UNUSED uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
volatile uint16_t * ret = PCIGetAddr(bus, slot, func, reg);
*ret = data;
}
void
PCICfgWrite32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
UNUSED uint32_t data)
uint32_t data)
{
UNUSED uint32_t addr = PCIGetAddr(bus, slot, func, reg);
UNUSED uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
volatile uint32_t * ret = PCIGetAddr(bus, slot, func, reg);
*ret = data;
}
int
PCI_Discover(void)
{
const void * dtb = kbootinfo.dtb_addr;
const int offset = fdt_node_offset_by_compatible(dtb, -1, "pci-host-ecam-generic");
if (offset < 0) {
return ENOENT;
}
int lenp;
const struct fdt_property * prop = fdt_get_property(dtb, offset, "reg", &lenp);
if (prop == NULL || lenp != 4 * sizeof(uint32_t)) {
return EINVAL;
}
const uint32_t * ptr = (const uint32_t *)prop->data;
const uint64_t conf_base = fdt32_to_cpu(ptr[1]) | ((uint64_t)fdt32_to_cpu(ptr[0]) << 32);
const uint64_t limit = fdt32_to_cpu(ptr[3]) | ((uint64_t)fdt32_to_cpu(ptr[2]) << 32);
pci_conf_space = (void *)DEVPA2VA(conf_base);
pci_conf_size = limit;
kprintf("PCI conf space = 0x%p, size = 0x%lx.\n", pci_conf_space, pci_conf_size);
return 0;
}

View File

@ -136,9 +136,12 @@ PMap_DestroyAS(AS *space)
{
// free usertables
UNUSED struct vmpt * pt = space->user_tbl;
// release space itself
PAlloc_Release(space);
// XXX: release all pdcaches
NOT_IMPLEMENTED();
}
/**
@ -393,6 +396,7 @@ PMap_SystemUnmap(UNUSED uint64_t virt, UNUSED uint64_t pages)
void
PMap_Dump(UNUSED AS *space)
{
NOT_IMPLEMENTED();
return;
}

View File

@ -192,7 +192,7 @@ AHCI_Init(uint32_t bus, uint32_t slot, uint32_t func)
uint32_t device = dev.vendor << 16 | dev.device;
uint8_t progif = PCI_CfgRead8(&dev, PCI_OFFSET_PROGIF);
uint8_t progif = PCI_CfgRead8(&dev, PCI_OFFSET_PROG_INTERFACE);
if (progif != 0x01)
{
kprintf("Unsupported SATA Controller PROGIF=%02x\n", progif);

View File

@ -34,31 +34,31 @@ PCI_Init()
uint16_t
PCIGetDeviceID(uint32_t bus, uint32_t device, uint32_t func)
{
return PCICfgRead16(bus, device, func, PCI_OFFSET_DEVICEID);
return PCICfgRead16(bus, device, func, PCI_OFFSET_DEVICE_ID);
}
uint16_t
PCIGetVendorID(uint32_t bus, uint32_t device, uint32_t func)
{
return PCICfgRead16(bus, device, func, PCI_OFFSET_VENDORID);
return PCICfgRead16(bus, device, func, PCI_OFFSET_VENDOR_ID);
}
uint8_t
PCIGetBaseClass(uint32_t bus, uint32_t device, uint32_t func)
{
return PCICfgRead8(bus, device, func, PCI_OFFSET_CLASS);
return PCICfgRead8(bus, device, func, PCI_OFFSET_BASE_CLASS_CODE);
}
uint8_t
PCIGetSubClass(uint32_t bus, uint32_t device, uint32_t func)
{
return PCICfgRead8(bus, device, func, PCI_OFFSET_SUBCLASS);
return PCICfgRead8(bus, device, func, PCI_OFFSET_SUB_CLASS_CODE);
}
uint8_t
PCIGetHeaderType(uint32_t bus, uint32_t device, uint32_t func)
{
return PCICfgRead8(bus, device, func, PCI_OFFSET_HEADERTYPE);
return PCICfgRead8(bus, device, func, PCI_OFFSET_HEADER_TYPE);
}
uint8_t
@ -100,31 +100,31 @@ PCI_CfgWrite32(PCIDevice *dev, uint32_t reg, uint32_t data)
uint16_t
PCI_GetDeviceID(PCIDevice *dev)
{
return PCI_CfgRead16(dev, PCI_OFFSET_DEVICEID);
return PCI_CfgRead16(dev, PCI_OFFSET_DEVICE_ID);
}
uint16_t
PCI_GetVendorID(PCIDevice *dev)
{
return PCI_CfgRead16(dev, PCI_OFFSET_VENDORID);
return PCI_CfgRead16(dev, PCI_OFFSET_VENDOR_ID);
}
uint8_t
PCI_GetBaseClass(PCIDevice *dev)
{
return PCI_CfgRead8(dev, PCI_OFFSET_CLASS);
return PCI_CfgRead8(dev, PCI_OFFSET_BASE_CLASS_CODE);
}
uint8_t
PCI_GetSubClass(PCIDevice *dev)
{
return PCI_CfgRead8(dev, PCI_OFFSET_SUBCLASS);
return PCI_CfgRead8(dev, PCI_OFFSET_SUB_CLASS_CODE);
}
uint8_t
PCI_GetHeaderType(PCIDevice *dev)
{
return PCI_CfgRead8(dev, PCI_OFFSET_HEADERTYPE);
return PCI_CfgRead8(dev, PCI_OFFSET_HEADER_TYPE);
}
/*
@ -250,10 +250,10 @@ PCI_Configure(PCIDevice *dev)
{
int bar;
dev->irq = PCI_CfgRead8(dev, PCI_OFFSET_IRQLINE);
dev->irq = PCI_CfgRead8(dev, PCI0_INTERRUPT_LINE);
PCI_CfgWrite16(dev, PCI_OFFSET_COMMAND,
PCI_COMMAND_IOENABLE | PCI_COMMAND_MEMENABLE | PCI_COMMAND_BUSMASTER);
PCI_CMD_IOSE | PCI_CMD_BME | PCI_CMD_MSE);
for (bar = 0; bar < PCI_MAX_BARS; bar++)
{
@ -264,7 +264,7 @@ PCI_Configure(PCIDevice *dev)
for (bar = 0; bar < PCI_MAX_BARS; bar++)
{
uint32_t barReg = PCI_OFFSET_BARFIRST + 4 * bar;
uint32_t barReg = PCI0_BASE_ADDR0 + 4 * bar;
uint32_t base, size;
uint32_t origValue = PCI_CfgRead32(dev, barReg);
@ -410,12 +410,11 @@ Debug_PCIDump(int argc, const char *argv[])
kprintf("Device ID: %04x\n", PCIGetDeviceID(bus, device, func));
kprintf("Class: %d\n", PCIGetBaseClass(bus, device, func));
kprintf("Subclass: %d\n", PCIGetSubClass(bus, device, func));
kprintf("ProgIf: %02x\n", PCICfgRead8(bus, device, func, PCI_OFFSET_PROGIF));
kprintf("Header Type: %d\n", PCIGetHeaderType(bus, device, func));
for (bar = 0; bar < PCI_MAX_BARS; bar++)
{
uint32_t barReg = PCI_OFFSET_BARFIRST + 4 * bar;
uint32_t barReg = PCI0_BASE_ADDR0 + 4 * bar;
kprintf("BAR%d: %016x\n", bar, PCICfgRead32(bus, device, func, barReg));
}

View File

@ -17,7 +17,7 @@
__FUNCTION__, __FILE__, __LINE__); \
}
NO_RETURN void Panic(const char *str, ...);
NO_RETURN PRINTF_LIKE void Panic(const char *str, ...);
#if defined(__aarch64__)
NO_RETURN extern void
@ -30,7 +30,7 @@ Halt(void)
}
#endif
int kprintf(const char *fmt, ...);
PRINTF_LIKE int kprintf(const char *fmt, ...);
int kvprintf(const char *fmt, va_list ap);
NO_RETURN void Debug_Assert(const char *fmt, ...);

View File

@ -20,6 +20,7 @@ typedef struct KTime {
typedef uint64_t UnixEpoch;
typedef uint64_t UnixEpochNS;
void KTime_Init(void);
void KTime_Fixup(KTime *tm);
UnixEpoch KTime_ToEpoch(const KTime *tm);
void KTime_FromEpoch(UnixEpoch time, KTime *tm);

View File

@ -14,6 +14,7 @@ typedef struct KTimerEvent {
LIST_ENTRY(KTimerEvent) timerQueue;
} KTimerEvent;
void KTimer_Init(void);
KTimerEvent *KTimer_Create(uint64_t timeout, KTimerCB cb, void *arg);
void KTimer_Retain(KTimerEvent *evt);
void KTimer_Release(KTimerEvent *evt);

View File

@ -1,25 +1,67 @@
#pragma once
#define PCI_OFFSET_VENDORID 0x00
#define PCI_OFFSET_DEVICEID 0x02
#define PCI_OFFSET_COMMAND 0x04
#define PCI_OFFSET_STATUS 0x06
#define PCI_OFFSET_REVISIONID 0x08
#define PCI_OFFSET_PROGIF 0x09
#define PCI_OFFSET_SUBCLASS 0x0A
#define PCI_OFFSET_CLASS 0x0B
#define PCI_OFFSET_CACHELINE 0x0C
#define PCI_OFFSET_LATENCYTMR 0x0D
#define PCI_OFFSET_HEADERTYPE 0x0E
#define PCI_OFFSET_BIST 0x0F
#include <stdint.h>
#define PCI_OFFSET_BARFIRST 0x10
#define PCI_OFFSET_BARLAST 0x24
#define PCI_OFFSET_VENDOR_ID 0x00 // Vendor ID ro
#define PCI_OFFSET_DEVICE_ID 0x02 // Device ID ro
#define PCI_OFFSET_COMMAND 0x04 // Command rw
#define PCI_OFFSET_STATUS 0x06 // Status rw
#define PCI_OFFSET_REVISION_ID 0x08 // Revision ID ro
#define PCI_OFFSET_CLASS_CODE 0x09 // Class Code ro
#define PCI_OFFSET_PROG_INTERFACE (PCI_OFFSET_CLASS_CODE) // Programming Interface ro
#define PCI_OFFSET_SUB_CLASS_CODE 0x0A // Sub Class Code ro
#define PCI_OFFSET_BASE_CLASS_CODE 0x0B // Base Class Code ro
#define PCI_OFFSET_CACHE_LINE_SIZE 0x0C // Cache Line Size ro+
#define PCI_OFFSET_LATENCY_TIMER 0x0D // Latency Timer ro+
#define PCI_OFFSET_HEADER_TYPE 0x0E // Header Type ro
#define PCI_OFFSET_BIST 0x0F // Built in self test rw
#define PCI_OFFSET_IRQLINE 0x3C
// Type 0 PCI offsets
#define PCI0_BASE_ADDR0 0x10 // Base Address 0 rw
#define PCI0_BASE_ADDR1 0x14 // Base Address 1 rw
#define PCI0_BASE_ADDR2 0x18 // Base Address 2 rw
#define PCI0_BASE_ADDR3 0x1C // Base Address 3 rw
#define PCI0_BASE_ADDR4 0x20 // Base Address 4 rw
#define PCI0_BASE_ADDR5 0x24 // Base Address 5 rw
#define PCI0_CIS 0x28 // CardBus CIS Pointer ro
#define PCI0_SUB_VENDOR_ID 0x2C // Sub-Vendor ID ro
#define PCI0_SUB_SYSTEM_ID 0x2E // Sub-System ID ro
#define PCI0_ROM_BASE_ADDR 0x30 // Expansion ROM Base Address rw
#define PCI0_CAP_PTR 0x34 // Capability list pointer ro
#define PCI0_RESERVED 0x35
#define PCI0_INTERRUPT_LINE 0x3C // Interrupt Line rw
#define PCI0_INTERRUPT_PIN 0x3D // Interrupt Pin ro
#define PCI0_MINIMUM_GRANT 0x3E // Maximum Grant ro
#define PCI0_MAXIMUM_LATENCY 0x3F // Maximum Latency ro
#define PCI_COMMAND_IOENABLE 0x0001
#define PCI_COMMAND_MEMENABLE 0x0002
#define PCI_COMMAND_BUSMASTER 0x0004
// Type 1 PCI offsets
#define PCI1_BASE_ADDR0 0x10 // Base Address 0 rw
#define PCI1_BASE_ADDR1 0x14 // Base Address 1 rw
#define PCI1_PRI_BUS_NUM 0x18 // Primary Bus Number rw
#define PCI1_SEC_BUS_NUM 0x19 // Secondary Bus Number rw
#define PCI1_SUB_BUS_NUM 0x1A // Subordinate Bus Number rw
#define PCI1_SEC_LAT_TIMER 0x1B // Secondary Latency Timer ro+
#define PCI1_IO_BASE 0x1C // I/O Base rw
#define PCI1_IO_LIMIT 0x1D // I/O Limit rw
#define PCI1_SECONDARY_STATUS 0x1E // Secondary Status rw
#define PCI1_MEM_BASE 0x20 // Memory Base rw
#define PCI1_MEM_LIMIT 0x22 // Memory Limit rw
#define PCI1_PRF_MEM_BASE 0x24 // Prefetchable Memory Base rw
#define PCI1_PRF_MEM_LIMIT 0x26 // Prefetchable Memory Limit rw
#define PCI1_PRF_BASE_UPPER 0x28 // Prefetchable Base Upper 32 rw
#define PCI1_PRF_LIMIT_UPPER 0x2C // Prefetchable Limit Upper 32 rw
#define PCI1_IO_BASE_UPPER 0x30 // I/O Base Upper 16 bits rw
#define PCI1_IO_LIMIT_UPPER 0x32 // I/O Limit Upper 16 bits rw
#define PCI1_RESERVED 0x34 // Reserved ro
#define PCI1_ROM_BASE_ADDR 0x38 // Expansion ROM Base Address rw
#define PCI1_INTR_LINE 0x3C // Interrupt Line rw
#define PCI1_INTR_PIN 0x3D // Interrupt Pin ro
#define PCI1_BRIDGE_CTRL 0x3E // Bridge Control rw
// some pci command reg bitfields
#define PCI_CMD_BME 0x04 // Bus master function enable
#define PCI_CMD_MSE 0x02 // Memory Space Access enable
#define PCI_CMD_IOSE 0x01 // I/O space enable
#define PCI_MAX_BARS 6
@ -66,7 +108,7 @@ typedef struct PCIDevice
PCIBAR bars[PCI_MAX_BARS];
} PCIDevice;
void PCI_Init();
void PCI_Init(void);
uint8_t PCI_CfgRead8(PCIDevice *dev, uint32_t reg);
uint16_t PCI_CfgRead16(PCIDevice *dev, uint32_t reg);

View File

@ -70,11 +70,17 @@ Thread_Init()
// Kernel Process
kernelProcess = Process_Create(NULL, "kernel");
if (!kernelProcess) {
Panic("Failed to create kernel process.\n");
}
// Create an thread object for current context
Process *proc = Process_Create(NULL, "init");
curProc[0] = Thread_Create(proc);
curProc[0]->schedState = SCHED_STATE_RUNNING;
if (!proc) {
Panic("Failed to create init process.\n");
}
curProc[CPU()] = Thread_Create(proc);
curProc[CPU()]->schedState = SCHED_STATE_RUNNING;
}
void