2026-07-26 21:07:36 +08:00
|
|
|
|
/* DKM 共享头文件 — 消除各驱动重复的结构体/宏/PCI/TSC 代码
|
|
|
|
|
|
*
|
|
|
|
|
|
* 设计要点:
|
|
|
|
|
|
* - 结构体定义与 UTSM/include/utsm/dkm.h 保持布局一致 (canonical)
|
|
|
|
|
|
* - PCI I/O 函数使用 static __inline__, 每个 .drv 文件获得独立副本, 避免链接冲突
|
|
|
|
|
|
* - TSC 校准函数使用 static __inline__, 每个 .drv 文件获得自己的 dkm_tsc_per_ms
|
|
|
|
|
|
* - 驱动源文件只需 #include "../dkm_shared.h", 保留各自的 driver_desc 和 driver_init
|
|
|
|
|
|
*
|
|
|
|
|
|
* 使用约定:
|
|
|
|
|
|
* 1. 在 driver_init 开头调用 dkm_tsc_calibrate() 完成校准
|
|
|
|
|
|
* 2. 时序等待使用 dkm_delay_ms() / dkm_delay_us()
|
|
|
|
|
|
* 3. 串口发送等待使用 dkm_serial_wait_tx(COM1)
|
|
|
|
|
|
* 4. MMIO 寄存器读取等待使用 dkm_rdtsc() + dkm_tsc_per_ms 直接计算 deadline
|
|
|
|
|
|
*/
|
|
|
|
|
|
#ifndef DKM_SHARED_H
|
|
|
|
|
|
#define DKM_SHARED_H
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 基本类型 (与 UTSM/types.h 一致) ---- */
|
|
|
|
|
|
typedef unsigned char u8;
|
|
|
|
|
|
typedef unsigned short u16;
|
|
|
|
|
|
typedef unsigned int u32;
|
|
|
|
|
|
typedef unsigned long long u64;
|
|
|
|
|
|
typedef signed char i8;
|
|
|
|
|
|
typedef short i16;
|
|
|
|
|
|
typedef int i32;
|
|
|
|
|
|
typedef long long i64;
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef NULL
|
|
|
|
|
|
#define NULL ((void *)0)
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- DKM magic / ABI 版本 ---- */
|
|
|
|
|
|
#define DKM_DRIVER_MAGIC 0x444B4D31u
|
|
|
|
|
|
#define DKM_ABI_VERSION 1u
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- DKM 驱动类别 (driver_desc.driver_class) ---- */
|
|
|
|
|
|
#define DKM_CLASS_PLATFORM 1u
|
|
|
|
|
|
#define DKM_CLASS_BUS 2u
|
|
|
|
|
|
#define DKM_CLASS_INTERRUPT 3u
|
|
|
|
|
|
#define DKM_CLASS_TIMER 4u
|
|
|
|
|
|
#define DKM_CLASS_CONSOLE 5u
|
|
|
|
|
|
#define DKM_CLASS_STORAGE 6u
|
|
|
|
|
|
#define DKM_CLASS_FS 7u
|
|
|
|
|
|
#define DKM_CLASS_NET 8u
|
|
|
|
|
|
#define DKM_CLASS_INPUT 9u
|
|
|
|
|
|
#define DKM_CLASS_GPU 10u
|
|
|
|
|
|
#define DKM_CLASS_MISC 11u
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- DKM 驱动标志 (driver_desc.flags) ---- */
|
|
|
|
|
|
#define DKM_F_REQUIRED (1u << 0)
|
|
|
|
|
|
#define DKM_F_BOOT_MODULE (1u << 1)
|
|
|
|
|
|
#define DKM_F_NO_UNLOAD (1u << 2)
|
|
|
|
|
|
#define DKM_F_STRONG_RECOVERY (1u << 3)
|
|
|
|
|
|
#define DKM_F_DMA_REQUIRED (1u << 4)
|
|
|
|
|
|
#define DKM_F_EARLY_LOG (1u << 5)
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 网卡链路/能力标志 ---- */
|
|
|
|
|
|
#define DKM_NET_F_LINK_UP (1u << 0)
|
|
|
|
|
|
#define DKM_NET_F_TX_READY (1u << 1)
|
|
|
|
|
|
#define DKM_NET_F_RX_READY (1u << 2)
|
|
|
|
|
|
#define DKM_NET_F_WIRELESS (1u << 3)
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- WiFi 扫描加密类型 ---- */
|
|
|
|
|
|
#define DKM_NET_SEC_OPEN 0u
|
|
|
|
|
|
#define DKM_NET_SEC_WEP 1u
|
|
|
|
|
|
#define DKM_NET_SEC_WPA 2u
|
|
|
|
|
|
#define DKM_NET_SEC_WPA2 3u
|
|
|
|
|
|
#define DKM_NET_SEC_WPA3 4u
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- DKM 结构体定义 (与 UTSM/include/utsm/dkm.h 布局一致) ---- */
|
|
|
|
|
|
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_dma_buffer {
|
|
|
|
|
|
void *virt;
|
|
|
|
|
|
u64 phys;
|
|
|
|
|
|
u64 size;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct dkm_dma_api {
|
|
|
|
|
|
int (*alloc_pages)(u64 page_count, u64 alignment, u64 max_phys, struct dkm_dma_buffer *out);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct dkm_net_scan_result {
|
|
|
|
|
|
char ssid[33];
|
|
|
|
|
|
u8 bssid[6];
|
|
|
|
|
|
u8 channel;
|
|
|
|
|
|
i8 rssi;
|
|
|
|
|
|
u8 security;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct dkm_net_device_desc {
|
|
|
|
|
|
const char *name;
|
|
|
|
|
|
u8 mac[6];
|
|
|
|
|
|
u32 flags;
|
|
|
|
|
|
void *ctx;
|
|
|
|
|
|
int (*tx)(void *ctx, const void *packet, u32 length);
|
|
|
|
|
|
int (*rx_poll)(void *ctx, void *buffer, u32 capacity, u32 *out_length);
|
|
|
|
|
|
/* 无线扩展回调(有线驱动置 NULL,向后兼容)。 */
|
|
|
|
|
|
int (*scan_start)(void *ctx);
|
|
|
|
|
|
int (*scan_count)(void *ctx);
|
|
|
|
|
|
int (*scan_result)(void *ctx, u32 n, struct dkm_net_scan_result *out);
|
|
|
|
|
|
int (*is_wireless)(void *ctx);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-31 13:53:49 +08:00
|
|
|
|
struct dkm_net_stats {
|
|
|
|
|
|
u64 tx_ok;
|
|
|
|
|
|
u64 tx_err;
|
|
|
|
|
|
u64 rx_ok;
|
|
|
|
|
|
u64 rx_err;
|
|
|
|
|
|
u64 rx_overflow;
|
|
|
|
|
|
u64 link_changes;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-26 21:07:36 +08:00
|
|
|
|
struct dkm_net_api {
|
|
|
|
|
|
int (*register_device)(const struct dkm_net_device_desc *desc);
|
|
|
|
|
|
u32 (*device_count)(void);
|
|
|
|
|
|
int (*device_info)(u32 index, void *out);
|
|
|
|
|
|
int (*tx)(u32 index, const void *packet, u32 length);
|
|
|
|
|
|
int (*rx_poll)(u32 index, void *buffer, u32 capacity, u32 *out_length);
|
|
|
|
|
|
int (*scan_start)(u32 index);
|
|
|
|
|
|
int (*scan_count)(u32 index);
|
|
|
|
|
|
int (*scan_result)(u32 index, u32 n, struct dkm_net_scan_result *out);
|
|
|
|
|
|
int (*is_wireless)(u32 index);
|
2026-07-31 13:53:49 +08:00
|
|
|
|
int (*device_stats)(u32 index, struct dkm_net_stats *out);
|
2026-07-26 21:07:36 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
typedef int (*dkm_block_read_fn)(void *ctx, u64 lba, u32 count, void *buffer);
|
|
|
|
|
|
typedef int (*dkm_block_write_fn)(void *ctx, u64 lba, u32 count, const void *buffer);
|
|
|
|
|
|
|
|
|
|
|
|
struct dkm_block_device_desc {
|
|
|
|
|
|
const char *name;
|
|
|
|
|
|
u64 sector_size;
|
|
|
|
|
|
u64 sector_count;
|
|
|
|
|
|
void *ctx;
|
|
|
|
|
|
int (*read)(void *ctx, u64 lba, u32 count, void *buffer);
|
|
|
|
|
|
int (*write)(void *ctx, u64 lba, u32 count, const void *buffer);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct dkm_block_api {
|
|
|
|
|
|
int (*register_device)(const struct dkm_block_device_desc *desc);
|
|
|
|
|
|
u32 (*device_count)(void);
|
|
|
|
|
|
int (*read)(u32 index, u64 lba, u32 count, void *buffer);
|
|
|
|
|
|
int (*write)(u32 index, u64 lba, u32 count, const void *buffer);
|
|
|
|
|
|
u64 (*sector_size)(u32 index);
|
|
|
|
|
|
const char *(*device_name)(u32 index);
|
|
|
|
|
|
int (*set_write_fn)(u32 index, dkm_block_write_fn fn);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-31 13:53:49 +08:00
|
|
|
|
/* 与 UTSM/include/utsm/paging.h 中的 dkm_mmio_api 布局一致 */
|
|
|
|
|
|
struct dkm_mmio_api {
|
|
|
|
|
|
/* 四级页表 walk。返回 0=未映射;1=4K PTE;2=2M PDE;3=1G PDPTE */
|
|
|
|
|
|
int (*is_mapped)(u64 vaddr);
|
|
|
|
|
|
/* 把物理区间映射到 hhdm_offset + phys(4KiB UC 页),返回 0 成功 */
|
|
|
|
|
|
int (*map_mmio)(u64 phys, u64 size);
|
|
|
|
|
|
/* 当前 CR3 物理地址(诊断用) */
|
|
|
|
|
|
u64 (*cr3)(void);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-26 21:07:36 +08:00
|
|
|
|
/* 与 UTSM/include/utsm/dkm.h 中的 dkm_kernel_api 布局完全一致.
|
|
|
|
|
|
* 字段顺序/类型不可调整 — UTSM 端按此偏移填充. */
|
|
|
|
|
|
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;
|
|
|
|
|
|
const struct dkm_dma_api *dma;
|
|
|
|
|
|
const void *vfs;
|
|
|
|
|
|
const struct dkm_net_api *net;
|
|
|
|
|
|
const void *timer;
|
|
|
|
|
|
const void *drr;
|
|
|
|
|
|
const void *rsdp_address;
|
|
|
|
|
|
const void *fb_address;
|
|
|
|
|
|
u64 fb_width;
|
|
|
|
|
|
u64 fb_height;
|
|
|
|
|
|
u64 fb_pitch;
|
|
|
|
|
|
u16 fb_bpp;
|
|
|
|
|
|
const void *boot_modules_response;
|
|
|
|
|
|
int (*irq_register)(u8 irq, void *handler);
|
|
|
|
|
|
u64 hhdm_offset;
|
2026-07-31 13:53:49 +08:00
|
|
|
|
const struct dkm_block_api *block; /* 不使用 block 的驱动可不访问 */
|
|
|
|
|
|
const struct dkm_mmio_api *mmio; /* 页表/高位 MMIO 映射服务(HHDM 空洞原地补映射) */
|
|
|
|
|
|
/* —— 新增字段只允许追加在末尾(DSK 以 api+0xA8 硬偏移读取 block) —— */
|
|
|
|
|
|
void *(*mm_map_mmio)(u64 phys, u64 size); /* MMIO 独立窗口映射(PCD|PWT),返回虚拟地址,失败返回 0 */
|
|
|
|
|
|
void (*mm_unmap_mmio)(void *virt, u64 size); /* 解除 MMIO 独立窗口映射 */
|
2026-07-26 21:07:36 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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 配置空间常量 ---- */
|
|
|
|
|
|
#define PCI_ADDR 0xCF8
|
|
|
|
|
|
#define PCI_DATA 0xCFC
|
|
|
|
|
|
#define PCI_VENDOR_ID 0x00
|
|
|
|
|
|
#define PCI_DEVICE_ID 0x02
|
|
|
|
|
|
#define PCI_COMMAND 0x04
|
|
|
|
|
|
#define PCI_PROG_IF 0x09
|
|
|
|
|
|
#define PCI_SUBCLASS 0x0A
|
|
|
|
|
|
#define PCI_CLASS 0x0B
|
|
|
|
|
|
#define PCI_HEADER 0x0E
|
|
|
|
|
|
#define PCI_CAP_PTR 0x34
|
|
|
|
|
|
#define PCI_IRQ_LINE 0x3C
|
|
|
|
|
|
#define PCI_BAR0 0x10
|
|
|
|
|
|
#define PCI_BAR1 0x14
|
|
|
|
|
|
#define PCI_BAR2 0x18
|
|
|
|
|
|
#define PCI_BAR3 0x1C
|
|
|
|
|
|
#define PCI_BAR4 0x20
|
|
|
|
|
|
#define PCI_BAR5 0x24
|
|
|
|
|
|
|
|
|
|
|
|
#define PCI_CMD_IO (1u << 0)
|
|
|
|
|
|
#define PCI_CMD_MEM (1u << 1)
|
|
|
|
|
|
#define PCI_CMD_BUSM (1u << 2)
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- PCI I/O 端口内联函数 (每个 .drv 获得独立副本) ---- */
|
|
|
|
|
|
static __inline__ void dkm_outl(u16 port, u32 value) {
|
|
|
|
|
|
__asm__ volatile ("outl %0, %1" :: "a"(value), "Nd"(port));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ u32 dkm_inl(u16 port) {
|
|
|
|
|
|
u32 value;
|
|
|
|
|
|
__asm__ volatile ("inl %1, %0" : "=a"(value) : "Nd"(port));
|
|
|
|
|
|
return value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ void dkm_outb(u16 port, u8 value) {
|
|
|
|
|
|
__asm__ volatile ("outb %0, %1" :: "a"(value), "Nd"(port));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ u8 dkm_inb(u16 port) {
|
|
|
|
|
|
u8 value;
|
|
|
|
|
|
__asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
|
|
|
|
|
|
return value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ u32 dkm_pci_read(u8 bus, u8 dev, u8 func, u8 reg) {
|
|
|
|
|
|
u32 addr = (1u << 31)
|
|
|
|
|
|
| ((u32)bus << 16)
|
|
|
|
|
|
| ((u32)dev << 11)
|
|
|
|
|
|
| ((u32)func << 8)
|
|
|
|
|
|
| ((u32)reg & 0xFC);
|
|
|
|
|
|
dkm_outl(PCI_ADDR, addr);
|
|
|
|
|
|
return dkm_inl(PCI_DATA);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ void dkm_pci_write(u8 bus, u8 dev, u8 func, u8 reg, u32 value) {
|
|
|
|
|
|
u32 addr = (1u << 31)
|
|
|
|
|
|
| ((u32)bus << 16)
|
|
|
|
|
|
| ((u32)dev << 11)
|
|
|
|
|
|
| ((u32)func << 8)
|
|
|
|
|
|
| ((u32)reg & 0xFC);
|
|
|
|
|
|
dkm_outl(PCI_ADDR, addr);
|
|
|
|
|
|
dkm_outl(PCI_DATA, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ u8 dkm_pci_read8(u8 bus, u8 dev, u8 func, u8 reg) {
|
|
|
|
|
|
u32 v = dkm_pci_read(bus, dev, func, reg);
|
|
|
|
|
|
return (u8)((v >> ((reg & 3) * 8)) & 0xff);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- TSC 时序: 实机要求用 CPU 频率计算, 不用循环 ----
|
|
|
|
|
|
* 每个 .drv 包含此头文件后获得自己的 file-local dkm_tsc_per_ms 副本,
|
|
|
|
|
|
* 通过 dkm_tsc_calibrate() 在 driver_init 开头初始化.
|
|
|
|
|
|
*/
|
|
|
|
|
|
static u64 dkm_tsc_per_ms __attribute__((unused)) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ u64 dkm_rdtsc(void) {
|
|
|
|
|
|
u32 lo, hi;
|
|
|
|
|
|
__asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
|
|
|
|
|
|
return ((u64)hi << 32) | lo;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 通过 PIT ch0 + TSC 校准 ~10ms 区间, 推算每毫秒 TSC 周期数. */
|
|
|
|
|
|
static __inline__ void dkm_tsc_calibrate(void) {
|
|
|
|
|
|
dkm_outb(0x43, 0x30); /* ch0, lo+hi, mode 0, binary */
|
|
|
|
|
|
dkm_outb(0x40, 0x7c); /* 11932 low = ~10ms */
|
|
|
|
|
|
dkm_outb(0x40, 0x2e); /* 11932 high */
|
|
|
|
|
|
u64 tsc_start = dkm_rdtsc();
|
|
|
|
|
|
u16 prev = 0; u64 loops = 0;
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
|
dkm_outb(0x43, 0x00);
|
|
|
|
|
|
u16 cur = (u16)dkm_inb(0x40) | ((u16)dkm_inb(0x40) << 8);
|
|
|
|
|
|
if (cur > prev && loops > 10) break;
|
|
|
|
|
|
prev = cur; loops++;
|
|
|
|
|
|
}
|
|
|
|
|
|
u64 tsc_end = dkm_rdtsc();
|
|
|
|
|
|
dkm_tsc_per_ms = (tsc_end - tsc_start) / 10;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ void dkm_delay_ms(u32 ms) {
|
|
|
|
|
|
if (!dkm_tsc_per_ms) {
|
|
|
|
|
|
for (volatile u32 i = 0; i < 100000 * ms; i++) __asm__ volatile("pause");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
u64 target = dkm_tsc_per_ms * ms;
|
|
|
|
|
|
u64 start = dkm_rdtsc();
|
|
|
|
|
|
while (dkm_rdtsc() - start < target) __asm__ volatile("pause");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ void dkm_delay_us(u32 us) {
|
|
|
|
|
|
if (!dkm_tsc_per_ms) {
|
|
|
|
|
|
for (volatile u32 i = 0; i < 100 * us; i++) __asm__ volatile("pause");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
u64 target = dkm_tsc_per_ms * us / 1000;
|
|
|
|
|
|
u64 start = dkm_rdtsc();
|
|
|
|
|
|
while (dkm_rdtsc() - start < target) __asm__ volatile("pause");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 实机: 基于 TSC 的串口发送等待 (100us 超时). com_port = 0x3F8 (COM1). */
|
|
|
|
|
|
static __inline__ void dkm_serial_wait_tx(u16 com_port) {
|
|
|
|
|
|
if (!dkm_tsc_per_ms) {
|
|
|
|
|
|
for (volatile u32 i = 0; i < 100000; i++) {
|
|
|
|
|
|
if (dkm_inb((u16)(com_port + 5)) & 0x20) break;
|
|
|
|
|
|
__asm__ volatile("pause");
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
u64 deadline = dkm_rdtsc() + dkm_tsc_per_ms / 10;
|
|
|
|
|
|
while (dkm_rdtsc() < deadline) {
|
|
|
|
|
|
if (dkm_inb((u16)(com_port + 5)) & 0x20) break;
|
|
|
|
|
|
__asm__ volatile("pause");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* DKM_SHARED_H */
|