From 4a7f582881d219b23c1f3411a7def0beebcd89e9 Mon Sep 17 00:00:00 2001 From: quackerd Date: Mon, 4 Nov 2024 05:11:18 -0500 Subject: [PATCH] pci enumeration --- sys/arm64/include/pci.h | 3 ++ sys/arm64/machine.c | 19 ++++++---- sys/arm64/pci.c | 84 +++++++++++++++++++++++++---------------- sys/arm64/pmap.c | 6 ++- sys/dev/ahci.c | 2 +- sys/dev/pci.c | 29 +++++++------- sys/include/kassert.h | 4 +- sys/include/ktime.h | 1 + sys/include/ktimer.h | 1 + sys/include/pci.h | 80 +++++++++++++++++++++++++++++---------- sys/kern/thread.c | 10 ++++- 11 files changed, 158 insertions(+), 81 deletions(-) create mode 100644 sys/arm64/include/pci.h diff --git a/sys/arm64/include/pci.h b/sys/arm64/include/pci.h new file mode 100644 index 0000000..8bb9ecb --- /dev/null +++ b/sys/arm64/include/pci.h @@ -0,0 +1,3 @@ +#pragma once + +int PCI_Discover(void); diff --git a/sys/arm64/machine.c b/sys/arm64/machine.c index 9dedb1a..a3d4269 100644 --- a/sys/arm64/machine.c +++ b/sys/arm64/machine.c @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include #include #include @@ -25,10 +28,8 @@ #include #include #include +#include -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 */ diff --git a/sys/arm64/pci.c b/sys/arm64/pci.c index 2c26047..c2dc267 100644 --- a/sys/arm64/pci.c +++ b/sys/arm64/pci.c @@ -3,75 +3,93 @@ #include #include +#include +#include +#include #include #include +#include +#include -#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; +} diff --git a/sys/arm64/pmap.c b/sys/arm64/pmap.c index 0f2b786..9e7f71c 100644 --- a/sys/arm64/pmap.c +++ b/sys/arm64/pmap.c @@ -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; } diff --git a/sys/dev/ahci.c b/sys/dev/ahci.c index f2ae805..e4393bd 100644 --- a/sys/dev/ahci.c +++ b/sys/dev/ahci.c @@ -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); diff --git a/sys/dev/pci.c b/sys/dev/pci.c index 6688104..db206d6 100644 --- a/sys/dev/pci.c +++ b/sys/dev/pci.c @@ -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)); } diff --git a/sys/include/kassert.h b/sys/include/kassert.h index 0007a4b..1170565 100644 --- a/sys/include/kassert.h +++ b/sys/include/kassert.h @@ -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, ...); diff --git a/sys/include/ktime.h b/sys/include/ktime.h index be146f1..5c29e82 100644 --- a/sys/include/ktime.h +++ b/sys/include/ktime.h @@ -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); diff --git a/sys/include/ktimer.h b/sys/include/ktimer.h index 7d452a5..ea53ea6 100644 --- a/sys/include/ktimer.h +++ b/sys/include/ktimer.h @@ -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); diff --git a/sys/include/pci.h b/sys/include/pci.h index 03e58ee..48844b1 100644 --- a/sys/include/pci.h +++ b/sys/include/pci.h @@ -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 -#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); diff --git a/sys/kern/thread.c b/sys/kern/thread.c index c812621..07f0438 100644 --- a/sys/kern/thread.c +++ b/sys/kern/thread.c @@ -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