Files
Deshab-OS/CODE/DKM/pci/pci.c
T
xyou f1a2a110d7 Record networking and DMA development progress
Add the current OS source tree, build scripts, system image layout, and development notes covering DMA page allocation, e1000 bring-up, net API dispatch, and DHCP work in progress.
2026-07-02 16:17:09 +08:00

252 lines
7.5 KiB
C

/* DKM PCI Driver — PCI bus enumeration via config space (0xCF8/0xCFC)
* Stage 0, required, depends on "irq", provides "pci".
* No IRQ needed for enumeration. Scans all buses/devices/functions.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci_api;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
/* ---------------------------------------------------------------
* PCI constants
* --------------------------------------------------------------- */
#define PCI_CFG_ADDR 0xCF8
#define PCI_CFG_DATA 0xCFC
#define PCI_VENDOR_ID 0x00
#define PCI_DEVICE_ID 0x02
#define PCI_COMMAND 0x04
#define PCI_STATUS 0x06
#define PCI_CLASS 0x0B /* class code */
#define PCI_SUBCLASS 0x0A /* subclass */
#define PCI_PROG_IF 0x09 /* prog IF */
#define PCI_HEADER_TYPE 0x0E
#define PCI_BAR0 0x10
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_depends[] = { "irq" };
static const char *const g_provides[] = { "pci" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "pci",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 2, /* DKM_CLASS_BUS */
.stage = 0,
.flags = 1, /* DKM_F_REQUIRED */
.priority = 0,
.depends = g_depends,
.depends_count = 1,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* I/O helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static __inline__ void outl(u16 port, u32 value) {
__asm__ volatile ("outl %0, %1" :: "a"(value), "Nd"(port));
}
static __inline__ u32 inl(u16 port) {
u32 value;
__asm__ volatile ("inl %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
/* ---------------------------------------------------------------
* PCI config access
* --------------------------------------------------------------- */
static u32 pci_cfg_read(u8 bus, u8 dev, u8 func, u8 reg) {
u32 addr = (u32)((1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC));
outl(PCI_CFG_ADDR, addr);
return inl(PCI_CFG_DATA);
}
static void pci_cfg_write(u8 bus, u8 dev, u8 func, u8 reg, u32 val) {
u32 addr = (u32)((1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC));
outl(PCI_CFG_ADDR, addr);
outl(PCI_CFG_DATA, val);
}
/* ---------------------------------------------------------------
* Log helpers
* --------------------------------------------------------------- */
static void log_hex(const char *prefix, u64 val) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0'; buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(val >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
static const char *pci_class_name(u8 base, u8 sub) {
switch (base) {
case 0x00: return "Legacy";
case 0x01: return "Storage";
case 0x02: return "Network";
case 0x03: return "Display";
case 0x04: return "Multimedia";
case 0x05: return "Memory";
case 0x06: return "Bridge";
case 0x07: return "SimpleComm";
case 0x08: return "BasePeriph";
case 0x09: return "Input";
case 0x0A: return "Docking";
case 0x0B: return "CPU";
case 0x0C: return "SerialBus";
case 0x0D: return "Wireless";
case 0x0E: return "IntelligentIO";
case 0x0F: return "Satellite";
case 0x10: return "Crypto";
case 0x11: return "SignalProc";
case 0x12: return "Accelerator";
default: return "Unknown";
}
(void)sub;
}
/* ---------------------------------------------------------------
* Enumeration
* --------------------------------------------------------------- */
static void pci_scan_bus(u8 bus) {
for (u8 dev = 0; dev < 32; dev++) {
u32 vid_dev = pci_cfg_read(bus, dev, 0, PCI_VENDOR_ID);
u16 vendor = (u16)(vid_dev & 0xffff);
if (vendor == 0xffff) continue;
u8 header_type = (u8)(pci_cfg_read(bus, dev, 0, PCI_HEADER_TYPE) >> 16);
int multi_func = (header_type & 0x80) != 0;
u8 func_count = multi_func ? 8 : 1;
for (u8 func = 0; func < func_count; func++) {
u32 vid_dev2 = pci_cfg_read(bus, dev, func, PCI_VENDOR_ID);
u16 vendor2 = (u16)(vid_dev2 & 0xffff);
if (vendor2 == 0xffff) continue;
u16 device = (u16)(vid_dev2 >> 16);
u32 cc = pci_cfg_read(bus, dev, func, PCI_CLASS);
u8 class_code = (u8)(cc >> 24);
u8 subclass = (u8)((cc >> 16) & 0xff);
g_log->info("[pci]");
log_hex("[pci] bus=", bus);
log_hex("[pci] dev=", dev);
log_hex("[pci] func=", func);
log_hex("[pci] vendor=", vendor2);
log_hex("[pci] device=", device);
g_log->info("[pci] class");
g_log->info(pci_class_name(class_code, subclass));
log_hex("[pci] class_hex=", class_code);
log_hex("[pci] subclass=", subclass);
}
}
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
g_log->info("[pci] scanning PCI bus");
pci_scan_bus(0);
g_log->info("[pci] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}