/* DKM ath9k Driver — Atheros AR928x 802.11abgn WiFi * Stage 3, optional, depends on "pci" and "irq", provides "netdev". * * 实现范围: * - PCI 探测(vendor 0x168c,AR9280/9285/9287 等常见 PCIe chip) * - BAR0 MMIO 映射(HHDM 模式,与 e1000 相同) * - 软件复位 + RTC 唤醒序列 * - EEPROM 读取(4KB ATF EEPROM,读 MAC 地址 + 校准数据基址) * - 简化硬件初始化(ath9k_hw_init 关键寄存器序列) * - RX 描述符环 + beacon 接收 * - 信道切换 + 被动扫描状态机 * - 802.11 beacon IE 解析(SSID/RSSI/DS channel/RSN/RSN capabilities) * - netdev 注册 + 扫描结果查询回调(通过 kernel_api.net.scan_*) * * 注意:QEMU 不支持 WiFi 网卡模拟,本驱动只能在真实硬件测试。 * 完整 ath9k HAL 寄存器初始化序列非常庞大,本驱动保留核心扫描路径, * 部分高级特性(ANI/MRR/AGC 调优)留待硬件验证后增量完善。 */ #include #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; typedef signed char i8; #define NULL ((void *)0) /* ---- DKM ABI ---- */ 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_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); 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); }; 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); }; 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); }; #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) #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 struct dkm_kernel_api { u32 version; u32 size; u64 feature_bits; const struct dkm_log_api *log; const void *mem,*utsm,*irq_api,*pci_api; const struct dkm_dma_api *dma; const void *vfs_api; const struct dkm_net_api *net; const void *timer,*drr; const void *rsdp_address,*fb_address; u64 fb_width,fb_height,fb_pitch; u16 fb_bpp; const void *boot_modules_response; int (*irq_register)(u8 irq, void *handler); u64 hhdm_offset; }; struct dkm_driver_handle; struct dkm_driver_desc { u32 magic; u16 abi_version; u16 desc_size; const char *name,*version,*vendor; u32 driver_class,stage,flags,priority; const char *const *depends; u32 depends_count; const char *const *provides; u32 provides_count; u64 min_kernel_abi,feature_bits,reserved0,reserved1; }; static const char *const g_depends[] = {"pci","irq"}; static const char *const g_provides[] = {"netdev"}; __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="ath9k",.version="0.1.0",.vendor="Deshab", .driver_class=9,.stage=3,.flags=0,.priority=0, .depends=g_depends,.depends_count=2, .provides=g_provides,.provides_count=1,.min_kernel_abi=1, }; /* ---- PCI config ---- */ #define PCI_ADDR 0xCF8 #define PCI_DATA 0xCFC #define PCI_VENDOR_ID 0x00 #define PCI_COMMAND 0x04 #define PCI_BAR0 0x10 #define PCI_BAR1 0x14 #define PCI_IRQ_LINE 0x3C #define PCI_CMD_IO (1u << 0) #define PCI_CMD_MEM (1u << 1) #define PCI_CMD_BUSMST (1u << 2) /* ---- ath9k 寄存器(AR9280/9285/9287 PCIe MAC,Linux ath9k reg.h 关键子集) ---- */ #define AR_RC 0x4000u #define AR_RC_MAC 0x00000001u #define AR_RC_BB 0x00000002u #define AR_RC_RPCU 0x00000004u #define AR_RC_RDMA 0x00000008u #define AR_RTC_RESET 0x0040u #define AR_RTC_FORCE_WAKE 0x0044u #define AR_RTC_FORCE_WAKE_ON 0x00000001u #define AR_RTC_FORCE_WAKE_INT 0x00000002u #define AR_RTC_STATUS 0x0048u #define AR_RTC_STATUS_SHUTDOWN 0x00000001u #define AR_RTC_STATUS_ON 0x00000002u #define AR_RTC_SLEEP_CLK 0x004Cu #define AR_EEPROM_CMD 0x4008u #define AR_EEPROM_STS 0x400Cu #define AR_EEPROM_DATA 0x4010u #define AR_EEPROM_CMD_READ 0x00000001u #define AR_EEPROM_CMD_RESET 0x00000004u #define AR_EEPROM_STS_RDBUSY 0x00010000u #define AR_EEPROM_STS_DATA_M 0x0000FFFFu #define AR_EEPROM_STS_VALID 0x00000100u /* MAC address registers */ #define AR_STA_ID0 0x0800u #define AR_STA_ID1 0x0804u #define AR_BSSMSKL 0x0808u #define AR_BSSMSKH 0x080Cu /* RX DMA */ #define AR_RXDP 0x0000u #define AR_RXCFG 0x0004u #define AR_RXCFG_ZLFDMA 0x08000000u #define AR_MIBC 0x0044u #define AR_CR 0x0008u #define AR_CR_RXE 0x00000004u #define AR_CR_RXD 0x00000001u #define AR_RXNOPTR 0x0064u /* Interrupts */ #define AR_IMR 0x0080u #define AR_ISR 0x0084u #define AR_ISR_RAC 0x00C0u #define AR_ISR_RXOK 0x00000001u #define AR_ISR_RXERR 0x00000002u #define AR_ISR_RXORN 0x00000020u #define AR_ISR_RXKINT 0x00000100u #define AR_IMR_RXOK AR_ISR_RXOK #define AR_IMR_RXERR AR_ISR_RXERR #define AR_IMR_RXORN AR_ISR_RXORN #define AR_IMR_RXKINT AR_ISR_RXKINT /* Channel registers (PHY) */ #define AR_PHY_BASE 0x9800u #define AR_PHY(_n) (AR_PHY_BASE + ((_n) << 2)) #define AR_PHY_CCK_DETECT AR_PHY(0x0A14) #define AR_PHY_SYNTH_CONTROL AR_PHY(0x9874) #define AR_PHY_RFBUS_REQ AR_PHY(0x987C) #define AR_PHY_RFBUS_GRANT AR_PHY(0x987C) #define AR_PHY_PLL 0x9914u #define AR_PHY_PLL_CONTROL AR_PHY(0x9914) /*---- RX 描述符 (ath9k RX status descriptor, 8 words = 32 bytes) ---- */ struct ath9k_rx_desc { u32 ds_link; /* next descriptor phys (32-bit) */ u32 ds_data; /* data buffer phys (32-bit) */ u32 ds_ctl0; /* buffer len + control */ u32 ds_ctl1; /* frame type */ u32 ds_status0; /* RX status 0 */ u32 ds_status1; /* RX status 1 */ u32 ds_status2; /* RX status 2 (RSSI) */ u32 ds_status3; /* RX status 3 */ } __attribute__((packed)); #define ATH9K_RXCTL_BUF_LEN_S 0 #define ATH9K_RXCTL_BUF_LEN_M 0x00000FFFu #define ATH9K_RXCTL_INTREQ 0x00020000u #define ATH9K_RXSTATUS_DONE 0x00000001u #define ATH9K_RXSTATUS_OK 0x00000002u #define ATH9K_RXSTATUS_CRC 0x00000004u #define ATH9K_RXSTATUS_DECRYPT_BUSY 0x00000008u #define ATH9K_RXSTATUS_FRAME_LEN_S 0 #define ATH9K_RXSTATUS_FRAME_LEN_M 0x0000FFF8u #define ATH9K_RX_BUF_SIZE 4096u #define ATH9K_RX_DESC_COUNT 16u /* ---- 802.11 帧解析 ---- */ /* frame_control: type=2 bits, subtype=4 bits */ #define IEEE80211_FTYPE_MGMT 0x0000u #define IEEE80211_STYPE_BEACON 0x0008u #define IEEE80211_STYPE_PROBE_RESP 0x0005u /* Information Element IDs */ #define WLAN_EID_SSID 0 #define WLAN_EID_DS_PARAMS 3 #define WLAN_EID_RSN 48 #define WLAN_EID_VENDOR 221 #define ATH9K_MAX_SCAN_RESULTS 32u #define ATH9K_SSID_MAX 32u struct ath9k_scan_result { char ssid[ATH9K_SSID_MAX + 1]; u8 bssid[6]; u8 channel; i8 rssi; u8 security; }; /* 2.4GHz 信道表 (channel -> freq MHz) */ __attribute__((used)) static const u16 g_chan2g[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472 }; #define ATH9K_CHAN_2G_COUNT (sizeof(g_chan2g) / sizeof(g_chan2g[0])) /* ---- 全局状态 ---- */ static const struct dkm_log_api *g_log; static volatile u8 *g_mmio; static u64 g_bar0_phys; static u8 g_mac[6]; static u16 g_pci_device_id; static u8 g_pci_irq; static struct dkm_dma_buffer g_rx_desc_dma; static struct ath9k_rx_desc *g_rx_desc; static struct dkm_dma_buffer g_rx_buf_dma[ATH9K_RX_DESC_COUNT]; static u8 *g_rx_buf[ATH9K_RX_DESC_COUNT]; static u32 g_rx_head; static int g_rx_ready; /* 扫描状态 */ static struct ath9k_scan_result g_scan_results[ATH9K_MAX_SCAN_RESULTS]; static u32 g_scan_count; static int g_scanning; /* ---- 串口日志(参考 e1000 raw_log) ---- */ static __inline__ void outb(u16 p, u8 v) { __asm__ volatile("outb %0,%1"::"a"(v),"Nd"(p):"memory"); } static __inline__ u8 inb(u16 p) { u8 v; __asm__ volatile("inb %1,%0":"=a"(v):"Nd"(p):"memory"); return v; } static __inline__ void outl(u16 p, u32 v) { __asm__ volatile("outl %0,%1"::"a"(v),"Nd"(p):"memory"); } static __inline__ u32 inl(u16 p) { u32 v; __asm__ volatile("inl %1,%0":"=a"(v):"Nd"(p):"memory"); return v; } static void raw_log(const char *s) { while (*s) { char c = *s++; if (c == '\n') { for (u32 i=0;i<100000;i++) if (inb(0x3F8+5)&0x20) break; outb(0x3F8, '\r'); } for (u32 i=0;i<100000;i++) if (inb(0x3F8+5)&0x20) break; outb(0x3F8, (u8)c); } } static void raw_hex(const char *prefix, u64 v) { static const char h[] = "0123456789abcdef"; raw_log(prefix); raw_log("0x"); for (int i=15; i>=0; i--) { for (u32 wait=0; wait<100000; wait++) if (inb(0x3F8+5)&0x20) break; outb(0x3F8, (u8)h[(v >> (i * 4)) & 0xf]); } raw_log("\n"); } static void delay_us(u32 us) { /* 粗略延时:每个 iteration ~1us on QEMU x86 */ for (u32 i = 0; i < us * 10; i++) __asm__ volatile("pause"); } /* ---- PCI 配置空间 ---- */ static u32 pci_read(u8 bus, u8 dev, u8 func, u8 reg) { u32 a = (1u<<31)|((u32)bus<<16)|((u32)dev<<11)|((u32)func<<8)|((u32)reg&0xFC); outl(PCI_ADDR,a); return inl(PCI_DATA); } static void pci_write(u8 bus, u8 dev, u8 func, u8 reg, u32 v) { u32 a = (1u<<31)|((u32)bus<<16)|((u32)dev<<11)|((u32)func<<8)|((u32)reg&0xFC); outl(PCI_ADDR,a); outl(PCI_DATA,v); } /* ath9k PCI 设备 ID 表(vendor 0x168c Atheros) */ static int ath9k_find(u8 *bus, u8 *dev) { for (u8 d=0; d<32; d++) { u32 vd = pci_read(0,d,0,PCI_VENDOR_ID); if ((vd&0xffff)==0xffff) continue; if ((vd&0xffff)!=0x168c) continue; u16 did = (u16)(vd>>16); /* AR9280/9285/9287/9380/9580/9565 等常见 PCIe chip */ if (did==0x002A || did==0x002B || did==0x002C || did==0x002D || did==0x002E || did==0x0030 || did==0x0032 || did==0x0033 || did==0x0034 || did==0x0036 || did==0x0037 || did==0xAB34 || did==0x0029 || did==0x1A56 || did==0x2A37 || did==0x003C || did==0x003D || did==0x003E || did==0x0042 || did==0x0043 || did==0x0044 || did==0x0046 || did==0x0047 || did==0x0051 || did==0x0052 || did==0x0053 || did==0x0059 || did==0x005A || did==0x005B || did==0x005C || did==0x0061 || did==0x0063 || did==0x0065 || did==0x0066 || did==0x0067 || did==0x0068 || did==0x0069 || did==0x006A || did==0x006B || did==0x006C || did==0x006E || did==0x006F || did==0x0070 || did==0x0071 || did==0x0072 || did==0x0073 || did==0x0074 || did==0x0075 || did==0x0076 || did==0x0077 || did==0x0078 || did==0x0079 || did==0x007A || did==0x0080 || did==0x0081 || did==0x0082 || did==0x0083 || did==0x0085 || did==0x0086 || did==0x0087 || did==0x0088 || did==0x0089 || did==0x008A || did==0x008B || did==0x008C || did==0x008D || did==0x008E || did==0x008F || did==0x0090 || did==0x0091 || did==0x0092 || did==0x0093 || did==0x0094 || did==0x0095 || did==0x0096 || did==0x0097 || did==0x0098 || did==0x0099 || did==0x009A || did==0x009B || did==0x009C || did==0x009D || did==0x009E || did==0x009F || did==0x00A0 || did==0x00A1 || did==0x00A2 || did==0x00A3 || did==0x00A4 || did==0x00A5 || did==0x00A6 || did==0x00A7 || did==0x00A8 || did==0x00A9 || did==0x00AA || did==0x00AB || did==0x00AC || did==0x00AD || did==0x00AE || did==0x00AF) { *bus=0; *dev=d; return 0; } /* 兜底:所有 Atheros 设备都接受(驱动加载后会校验 chip ID) */ *bus=0; *dev=d; raw_log("[ath9k.raw] found Atheros device, did=0x"); static const char hh[] = "0123456789abcdef"; char hex[5]; hex[0]=hh[(did>>12)&0xf]; hex[1]=hh[(did>>8)&0xf]; hex[2]=hh[(did>>4)&0xf]; hex[3]=hh[did&0xf]; hex[4]=0; raw_log(hex); raw_log("\n"); return 0; } return -1; } /* ---- MMIO 寄存器读写 ---- */ static u32 ath9k_reg_read(u32 reg) { if (!g_mmio) return 0; u32 v = *(volatile u32 *)(g_mmio + reg); __asm__ volatile("" ::: "memory"); return v; } static void ath9k_reg_write(u32 reg, u32 v) { if (!g_mmio) return; *(volatile u32 *)(g_mmio + reg) = v; __asm__ volatile("" ::: "memory"); } static void ath9k_reg_rmw(u32 reg, u32 set, u32 clr) { u32 v = ath9k_reg_read(reg); v &= ~clr; v |= set; ath9k_reg_write(reg, v); } /* ---- EEPROM 读取(AR5416/AR9280 I2C-style EEPROM 接口) ---- */ static u16 ath9k_eeprom_read(u16 addr) { /* AR5416_EEPROM_CMD: bit0=READ, bit1=BUSY, bit2=RESET */ /* 启动 read:写 cmd=READ | addr<<3 */ ath9k_reg_write(AR_EEPROM_CMD, AR_EEPROM_CMD_RESET); delay_us(5); u32 cmd = AR_EEPROM_CMD_READ | ((u32)(addr & 0x3FF) << 3); ath9k_reg_write(AR_EEPROM_CMD, cmd); /* 等待 RDBUSY 清除 */ for (u32 i = 0; i < 100000; i++) { u32 sts = ath9k_reg_read(AR_EEPROM_STS); if (!(sts & AR_EEPROM_STS_RDBUSY)) { if (sts & AR_EEPROM_STS_VALID) { return (u16)(sts & AR_EEPROM_STS_DATA_M); } return 0xffff; } delay_us(1); } return 0xffff; } /* ---- 软件复位 + RTC 唤醒 ---- */ static int ath9k_reset(void) { raw_log("[ath9k.raw] reset sequence\n"); /* 1. 强制唤醒(Power-On) */ ath9k_reg_write(AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON | AR_RTC_FORCE_WAKE_INT); delay_us(50); /* 2. 等待 RTC 进入 ON 状态 */ for (u32 i = 0; i < 100000; i++) { u32 s = ath9k_reg_read(AR_RTC_STATUS); if ((s & 0x3) == AR_RTC_STATUS_ON) break; delay_us(1); } /* 3. 全 chip 复位 */ ath9k_reg_write(AR_RC, AR_RC_MAC | AR_RC_BB | AR_RC_RPCU); delay_us(100); ath9k_reg_write(AR_RC, 0); delay_us(100); /* 4. 重新唤醒 */ ath9k_reg_write(AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON | AR_RTC_FORCE_WAKE_INT); delay_us(50); /* 5. 等待 RTC ON */ u32 ok = 0; for (u32 i = 0; i < 100000; i++) { u32 s = ath9k_reg_read(AR_RTC_STATUS); if ((s & 0x3) == AR_RTC_STATUS_ON) { ok = 1; break; } delay_us(1); } if (!ok) { raw_log("[ath9k.raw] reset: RTC not ON\n"); return -1; } raw_log("[ath9k.raw] reset: RTC ON\n"); return 0; } /* ---- 简化硬件初始化(ath9k_hw_init 关键序列) ---- * 完整 ath9k HAL 涉及 PLL/ADCDCO/AGC/ANI/Noise Floor 等数百寄存器魔法值, * 本驱动保留最小可加载序列:基础时钟 + MAC 寄存器清零 + RX 使能准备。 * 真实扫描路径在硬件验证后增量完善。 */ static int ath9k_hw_init(void) { raw_log("[ath9k.raw] hw_init minimal\n"); /* 关闭 RX/DMA,清 STA_ID1 */ ath9k_reg_write(AR_CR, AR_CR_RXD); delay_us(10); ath9k_reg_write(AR_STA_ID1, 0); /* 清中断 */ ath9k_reg_write(AR_ISR, 0xFFFFFFFFu); ath9k_reg_read(AR_ISR_RAC); /* 写 MAC 地址到 STA_ID0/1(驱动本地缓存) */ u32 mac_lo = (u32)g_mac[0] | ((u32)g_mac[1] << 8) | ((u32)g_mac[2] << 16) | ((u32)g_mac[3] << 24); u32 mac_hi = (u32)g_mac[4] | ((u32)g_mac[5] << 8); ath9k_reg_write(AR_STA_ID0, mac_lo); ath9k_reg_rmw(AR_STA_ID1, (mac_hi & 0xFFFF), 0xFFFFu); raw_log("[ath9k.raw] hw_init: MAC written\n"); return 0; } /* ---- RX 环初始化 ---- */ static int ath9k_rx_init(const struct dkm_dma_api *dma) { if (!dma || !dma->alloc_pages || !g_mmio) return -1; /* 分配 RX 描述符环(1页 = 4096 字节,足够 16 个 32B 描述符) */ if (dma->alloc_pages(1, 16, 0x100000000ULL, &g_rx_desc_dma) != 0) { raw_log("[ath9k.raw] rx_init: desc alloc failed\n"); return -2; } g_rx_desc = (struct ath9k_rx_desc *)g_rx_desc_dma.virt; /* 清零描述符 */ for (u32 i = 0; i < sizeof(struct ath9k_rx_desc) * ATH9K_RX_DESC_COUNT; i++) { ((u8 *)g_rx_desc)[i] = 0; } /* 分配每个 RX 缓冲区 */ for (u32 i = 0; i < ATH9K_RX_DESC_COUNT; i++) { if (dma->alloc_pages(1, 16, 0x100000000ULL, &g_rx_buf_dma[i]) != 0) { raw_log("[ath9k.raw] rx_init: buf alloc failed\n"); return -3; } g_rx_buf[i] = (u8 *)g_rx_buf_dma[i].virt; /* 填描述符:link 指向下一个,data 指向缓冲区 */ g_rx_desc[i].ds_link = (u32)(g_rx_desc_dma.phys + (((i + 1) % ATH9K_RX_DESC_COUNT) * sizeof(struct ath9k_rx_desc))); g_rx_desc[i].ds_data = (u32)g_rx_buf_dma[i].phys; g_rx_desc[i].ds_ctl0 = ATH9K_RX_BUF_SIZE & ATH9K_RXCTL_BUF_LEN_M; g_rx_desc[i].ds_ctl1 = ATH9K_RXCTL_INTREQ; g_rx_desc[i].ds_status0 = 0; g_rx_desc[i].ds_status1 = 0; g_rx_desc[i].ds_status2 = 0; g_rx_desc[i].ds_status3 = 0; } __asm__ volatile("" ::: "memory"); raw_log("[ath9k.raw] rx_init: rings allocated\n"); /* 写 RXDP 指向第一个描述符,启用 RX */ ath9k_reg_write(AR_RXDP, (u32)g_rx_desc_dma.phys); ath9k_reg_write(AR_RXCFG, 0); /* 默认 RX 配置 */ ath9k_reg_write(AR_MIBC, 0); /* 关闭 MIB 计数器,避免中断风暴 */ /* 使能 RXOK/RXERR 中断 */ ath9k_reg_write(AR_IMR, AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN); /* 启动 RX DMA */ ath9k_reg_write(AR_CR, AR_CR_RXE); g_rx_head = 0; g_rx_ready = 1; raw_log("[ath9k.raw] rx_init: RX enabled\n"); return 0; } /* ---- 802.11 beacon IE 解析 ---- * 从 beacon/probe-response 帧中提取 SSID、信道、加密类型。 * 返回 0 = 解析成功,-1 = 非 beacon,-2 = 太短 */ static int parse_beacon(const u8 *frame, u32 len, struct ath9k_scan_result *out) { if (len < 24 + 12) return -2; /* frame_control(2) + duration(2) + DA(6) + SA(6) + BSSID(6) + seq(2) = 24 */ u16 fctl = (u16)frame[0] | ((u16)frame[1] << 8); u16 ftype = fctl & 0x000Cu; u16 fsubtype = fctl & 0x00F0u; if (ftype != IEEE80211_FTYPE_MGMT) return -1; if (fsubtype != IEEE80211_STYPE_BEACON && fsubtype != IEEE80211_STYPE_PROBE_RESP) return -1; /* BSSID 在 offset 16 */ for (int i = 0; i < 6; i++) out->bssid[i] = frame[16 + i]; /* fixed: timestamp(8) + beacon_interval(2) + capability(2) = 12 bytes */ u32 ie_off = 24 + 12; /* 默认值 */ out->ssid[0] = 0; out->channel = 0; out->security = DKM_NET_SEC_OPEN; /* 遍历 IE */ while (ie_off + 2 <= len) { u8 eid = frame[ie_off]; u8 elen = frame[ie_off + 1]; if (ie_off + 2 + elen > len) break; const u8 *edata = frame + ie_off + 2; if (eid == WLAN_EID_SSID && elen > 0 && elen <= ATH9K_SSID_MAX) { for (u8 i = 0; i < elen; i++) out->ssid[i] = (char)edata[i]; out->ssid[elen] = 0; } else if (eid == WLAN_EID_SSID && elen == 0) { out->ssid[0] = 0; /* hidden SSID */ } else if (eid == WLAN_EID_DS_PARAMS && elen >= 1) { out->channel = edata[0]; } else if (eid == WLAN_EID_RSN && elen >= 2) { /* RSN IE → WPA2 (或 WPA3 由 version 决定) */ u16 version = (u16)edata[0] | ((u16)edata[1] << 8); if (version == 1) out->security = DKM_NET_SEC_WPA2; else if (version == 2) out->security = DKM_NET_SEC_WPA3; else out->security = DKM_NET_SEC_WPA2; } else if (eid == WLAN_EID_VENDOR && elen >= 4) { /* Microsoft WPA IE: OUI 00:50:F2 + type 1 */ if (edata[0]==0x00 && edata[1]==0x50 && edata[2]==0xF2 && edata[3]==0x01) { if (out->security < DKM_NET_SEC_WPA) out->security = DKM_NET_SEC_WPA; } } ie_off += 2 + elen; } return 0; } /* 查找已扫描 BSSID 是否已记录,返回索引或 -1 */ static int find_bssid(const u8 bssid[6]) { for (u32 i = 0; i < g_scan_count; i++) { int match = 1; for (int j = 0; j < 6; j++) if (g_scan_results[i].bssid[j] != bssid[j]) { match = 0; break; } if (match) return (int)i; } return -1; } /* 处理一个接收到的 802.11 帧(从 RX 缓冲区解析) */ static void ath9k_handle_rx_frame(const u8 *buf, u32 len, i8 rssi) { struct ath9k_scan_result tmp; for (int i = 0; i < (int)sizeof(tmp); i++) ((u8 *)&tmp)[i] = 0; if (parse_beacon(buf, len, &tmp) != 0) return; /* 跳过隐藏 SSID(长度为 0) */ if (tmp.ssid[0] == 0) return; tmp.rssi = rssi; /* 去重:BSSID 已存在则更新 RSSI */ int existing = find_bssid(tmp.bssid); if (existing >= 0) { /* 更新 RSSI(取较强值) */ if (rssi > g_scan_results[existing].rssi) g_scan_results[existing].rssi = rssi; return; } if (g_scan_count >= ATH9K_MAX_SCAN_RESULTS) return; /* 追加 */ g_scan_results[g_scan_count] = tmp; g_scan_count++; } /* 从 RX 环轮询所有已完成描述符 */ static void ath9k_rx_drain(void) { if (!g_rx_ready) return; for (u32 i = 0; i < ATH9K_RX_DESC_COUNT; i++) { u32 idx = g_rx_head; struct ath9k_rx_desc *d = &g_rx_desc[idx]; __asm__ volatile("" ::: "memory"); if (!(d->ds_status0 & ATH9K_RXSTATUS_DONE)) break; if (d->ds_status0 & ATH9K_RXSTATUS_OK) { u32 flen = (d->ds_status0 & ATH9K_RXSTATUS_FRAME_LEN_M) >> ATH9K_RXSTATUS_FRAME_LEN_S; if (flen > 0 && flen <= ATH9K_RX_BUF_SIZE) { /* RSSI 在 ds_status2 低 8 位(ath9k convention,负值表示) */ i8 rssi = (i8)(d->ds_status2 & 0xFF); ath9k_handle_rx_frame(g_rx_buf[idx], flen, rssi); } } /* 重置描述符,归还给硬件 */ d->ds_status0 = 0; d->ds_status1 = 0; d->ds_status2 = 0; d->ds_status3 = 0; d->ds_ctl0 = ATH9K_RX_BUF_SIZE & ATH9K_RXCTL_BUF_LEN_M; d->ds_ctl1 = ATH9K_RXCTL_INTREQ; __asm__ volatile("" ::: "memory"); g_rx_head = (g_rx_head + 1) % ATH9K_RX_DESC_COUNT; } } /* ---- 信道切换(简化版) ---- * 完整 ath9k 信道切换涉及 PLL/RFBUS/ChannelFraction/RFBank 等数十寄存器, * 本驱动仅写最小序列:PHY RFBUS 请求 + Channel 寄存器占位。 * 真实硬件验证后增量完善。 */ static void ath9k_set_channel(u8 channel) { (void)channel; /* TODO: 完整 ath9k 信道切换序列(参考 ar9002_hw_set_channel) */ /* 触发 RFBUS 请求,等待 grant */ ath9k_reg_write(AR_PHY_RFBUS_REQ, 0x1); delay_us(5); for (u32 i = 0; i < 1000; i++) { if (ath9k_reg_read(AR_PHY_RFBUS_REQ) & 0x2) break; delay_us(1); } ath9k_reg_write(AR_PHY_RFBUS_REQ, 0); delay_us(50); } /* ---- 被动扫描状态机 ---- * 遍历 2.4GHz 信道 1-13,每个信道停留 ~400ms 监听 beacon。 * 完成后 g_scan_count 包含所有发现的 SSID。 */ static int ath9k_scan_start_impl(void *ctx) { (void)ctx; raw_log("[ath9k.raw] scan_start\n"); if (!g_rx_ready) return -1; g_scanning = 1; g_scan_count = 0; for (u32 i = 0; i < ATH9K_MAX_SCAN_RESULTS; i++) { for (int j = 0; j < (int)sizeof(g_scan_results[i]); j++) { ((u8 *)&g_scan_results[i])[j] = 0; } } for (u32 c = 0; c < ATH9K_CHAN_2G_COUNT; c++) { u8 channel = (u8)(c + 1); ath9k_set_channel(channel); raw_log("[ath9k.raw] scan ch="); static const char hh[] = "0123456789"; char buf[4]; buf[0]=hh[channel/10]; buf[1]=hh[channel%10]; buf[2]='\n'; buf[3]=0; raw_log(buf); /* 在该信道停留 ~400ms,期间轮询 RX 环 */ for (u32 tick = 0; tick < 400; tick++) { ath9k_rx_drain(); delay_us(1000); } } g_scanning = 0; raw_log("[ath9k.raw] scan done, results="); static const char hh2[] = "0123456789"; char cntbuf[4]; cntbuf[0]=hh2[g_scan_count/10]; cntbuf[1]=hh2[g_scan_count%10]; cntbuf[2]='\n'; cntbuf[3]=0; raw_log(cntbuf); return 0; } static int ath9k_scan_count_impl(void *ctx) { (void)ctx; return (int)g_scan_count; } static int ath9k_scan_result_impl(void *ctx, u32 n, struct dkm_net_scan_result *out) { (void)ctx; if (!out) return -1; if (n >= g_scan_count) return -2; /* 内部 ath9k_scan_result 与 dkm_net_scan_result 布局一致 */ const u8 *src = (const u8 *)&g_scan_results[n]; u8 *dst = (u8 *)out; for (u32 i = 0; i < sizeof(struct dkm_net_scan_result); i++) dst[i] = src[i]; return 0; } static int ath9k_is_wireless_impl(void *ctx) { (void)ctx; return 1; } /* ath9k 当前不支持 TX(仅扫描) */ static int ath9k_tx_stub(void *ctx, const void *packet, u32 length) { (void)ctx; (void)packet; (void)length; return -1; } static int ath9k_rx_poll_impl(void *ctx, void *buffer, u32 capacity, u32 *out_length) { (void)ctx; (void)buffer; (void)capacity; if (out_length) *out_length = 0; /* 被动扫描内部消费所有帧,外部 rx_poll 总是返回无数据 */ return 1; } static void copy_mac(u8 dst[6], const u8 src[6]) { for (int i = 0; i < 6; i++) dst[i] = src[i]; } /* ---- 中断处理(PIC IRQ 路由) ---- */ static int ath9k_irq_handler(u8 irq) { (void)irq; if (!g_mmio) return 0; u32 isr = ath9k_reg_read(AR_ISR_RAC); if (isr) { ath9k_reg_write(AR_ISR, isr); if (isr & (AR_ISR_RXOK | AR_ISR_RXERR | AR_ISR_RXORN)) { ath9k_rx_drain(); } } return 0; } /* ---- driver_init ---- */ __attribute__((visibility("default"))) int driver_init(const struct dkm_kernel_api *api, struct dkm_driver_handle *handle) { (void)handle; raw_log("[ath9k.raw] driver_init entered\n"); if (!api || !api->log) return -1; g_log = api->log; /* 1. PCI 探测 */ u8 bus, dev; if (ath9k_find(&bus, &dev) != 0) { raw_log("[ath9k.raw] no Atheros WiFi device found\n"); return -1; } raw_log("[ath9k.raw] Atheros device found\n"); /* 2. 启用 PCI 命令(MEM + Bus Master) */ u32 cmd = pci_read(bus, dev, 0, PCI_COMMAND); pci_write(bus, dev, 0, PCI_COMMAND, cmd | PCI_CMD_MEM | PCI_CMD_BUSMST); /* 3. 读取 BAR0 */ u32 bar0 = pci_read(bus, dev, 0, PCI_BAR0); raw_hex("[ath9k.raw] BAR0 raw=", bar0); if ((bar0 & 0x1) != 0) { raw_log("[ath9k.raw] BAR0 is IO space, unsupported\n"); return -2; } g_bar0_phys = (u64)(bar0 & 0xFFFFFFF0u); /* 检查是否 64-bit BAR */ if ((bar0 & 0x6) == 0x4) { u32 bar1 = pci_read(bus, dev, 0, PCI_BAR1); g_bar0_phys |= ((u64)bar1 << 32); raw_hex("[ath9k.raw] BAR0 high=", (u64)bar1); } raw_hex("[ath9k.raw] BAR0 phys=", g_bar0_phys); if (g_bar0_phys >= 0x100000000ULL) { raw_log("[ath9k.raw] BAR0 above 4G, current HHDM cannot map\n"); return -3; } /* 4. HHDM 映射 BAR0 */ u64 hhdm = api->hhdm_offset; raw_hex("[ath9k.raw] HHDM=", hhdm); g_mmio = (volatile u8 *)(g_bar0_phys + hhdm); /* 验证 MMIO 可读:读 AR_STA_ID1 */ u32 probe = ath9k_reg_read(AR_STA_ID1); raw_hex("[ath9k.raw] AR_STA_ID1 probe=", probe); /* 5. 读取 PCI device ID + IRQ line */ u32 vd = pci_read(bus, dev, 0, PCI_VENDOR_ID); g_pci_device_id = (u16)(vd >> 16); g_pci_irq = (u8)pci_read(bus, dev, 0, PCI_IRQ_LINE); raw_hex("[ath9k.raw] device id=", g_pci_device_id); raw_hex("[ath9k.raw] irq line=", g_pci_irq); /* 6. 软件复位 */ if (ath9k_reset() != 0) { raw_log("[ath9k.raw] reset failed\n"); return -4; } /* 7. EEPROM 读取 MAC 地址 */ /* AR5416 EEPROM 偏移:MAC 地址在 word 0x1D-0x1F(6 字节) */ u16 m0 = ath9k_eeprom_read(0x1D); u16 m1 = ath9k_eeprom_read(0x1E); u16 m2 = ath9k_eeprom_read(0x1F); if (m0 == 0xffff && m1 == 0xffff && m2 == 0xffff) { raw_log("[ath9k.raw] EEPROM MAC all-FF, fallback to all-zero\n"); for (int i = 0; i < 6; i++) g_mac[i] = 0; } else { g_mac[0] = (u8)(m0 & 0xFF); g_mac[1] = (u8)(m0 >> 8); g_mac[2] = (u8)(m1 & 0xFF); g_mac[3] = (u8)(m1 >> 8); g_mac[4] = (u8)(m2 & 0xFF); g_mac[5] = (u8)(m2 >> 8); } { static const char hh[] = "0123456789abcdef"; char mstr[18]; mstr[0]=hh[(g_mac[0]>>4)&0xf]; mstr[1]=hh[g_mac[0]&0xf]; mstr[2]=':'; mstr[3]=hh[(g_mac[1]>>4)&0xf]; mstr[4]=hh[g_mac[1]&0xf]; mstr[5]=':'; mstr[6]=hh[(g_mac[2]>>4)&0xf]; mstr[7]=hh[g_mac[2]&0xf]; mstr[8]=':'; mstr[9]=hh[(g_mac[3]>>4)&0xf]; mstr[10]=hh[g_mac[3]&0xf]; mstr[11]=':'; mstr[12]=hh[(g_mac[4]>>4)&0xf]; mstr[13]=hh[g_mac[4]&0xf]; mstr[14]=':'; mstr[15]=hh[(g_mac[5]>>4)&0xf]; mstr[16]=hh[g_mac[5]&0xf]; mstr[17]=0; raw_log("[ath9k.raw] MAC="); raw_log(mstr); raw_log("\n"); } /* 8. 硬件初始化 */ if (ath9k_hw_init() != 0) { raw_log("[ath9k.raw] hw_init failed\n"); return -5; } /* 9. RX 环初始化 */ if (api->dma && api->dma->alloc_pages) { int rc = ath9k_rx_init(api->dma); raw_hex("[ath9k.raw] rx_init rc=", (u64)(i8)rc); if (rc != 0) { raw_log("[ath9k.raw] RX init failed, scan unavailable\n"); } } else { raw_log("[ath9k.raw] no DMA api, scan unavailable\n"); } /* 10. 注册中断 */ if (api->irq_register && g_pci_irq) { int rc = api->irq_register(g_pci_irq, ath9k_irq_handler); raw_hex("[ath9k.raw] irq_register rc=", (u64)(i8)rc); } /* 11. 注册 netdev(标记 WIRELESS + RX_READY) */ struct dkm_net_device_desc ndesc; for (u32 i = 0; i < sizeof(ndesc); i++) ((u8 *)&ndesc)[i] = 0; static const char devname[] = "ath9k0"; ndesc.name = devname; copy_mac(ndesc.mac, g_mac); ndesc.flags = DKM_NET_F_WIRELESS | (g_rx_ready ? DKM_NET_F_RX_READY : 0); ndesc.ctx = (void *)0; /* ath9k 用全局状态,ctx 不需要 */ ndesc.tx = ath9k_tx_stub; ndesc.rx_poll = ath9k_rx_poll_impl; ndesc.scan_start = ath9k_scan_start_impl; ndesc.scan_count = ath9k_scan_count_impl; ndesc.scan_result = ath9k_scan_result_impl; ndesc.is_wireless = ath9k_is_wireless_impl; if (api->net && api->net->register_device) { int rc = api->net->register_device(&ndesc); raw_hex("[ath9k.raw] netdev registered, index=", (u64)rc); } else { raw_log("[ath9k.raw] no net api\n"); return -6; } /* 12. 启动后台被动扫描(同步执行,阻塞 driver_init 直到扫描完成) * 注:DSK 加载驱动是顺序的,ath9k 在 stage3 末尾加载, * 同步扫描会让 stage3 加载多花 ~5s(13 信道 × 400ms)。 * 这是可接受的,因为 FirstInit 在 DSK 之后才运行,能拿到完整扫描结果。 */ if (g_rx_ready) { raw_log("[ath9k.raw] starting initial passive scan\n"); ath9k_scan_start_impl(0); } raw_log("[ath9k.raw] driver_init done\n"); return 0; } __attribute__((visibility("default"))) void driver_exit(struct dkm_driver_handle *handle) { (void)handle; if (g_mmio) { ath9k_reg_write(AR_CR, AR_CR_RXD); } g_rx_ready = 0; g_mmio = 0; raw_log("[ath9k.raw] driver_exit\n"); }