AIC8800M80 是一款常见的 USB WiFi 6 / 蓝牙二合一网卡芯片(2.4/5GHz 双频、802.11ax、WPA3),但它没有进入 Linux 内核主线,只能依赖厂商外流、社区维护的开源驱动。本作品是社区仓库 ronnyf/AIC8800-Linux-Driver 的 fork,目标只有一个:让这块网卡在 StarFive VisionFive 2(昉星光 2,JH7110 RISC-V SoC,内核 6.12.5-starfive)上真正用起来。
适配结果已在真机验证:固件下载成功 → 生成 wlan0 → NetworkManager 自动关联并联网正常。相对上游的改动极小——3 个文件、7 行,无任何功能变更,分支保持干净,随时可以向上游回馈。
这块网卡的“三段变身“
AIC8800M80 插上电脑后不是一张现成的网卡,而是一台会变身的设备,USB ID 随状态流转:
| 阶段 | VID:PID | 状态 |
|---|---|---|
| 插入瞬间 | a69c:5721 | 伪装成 U 盘(存放 Windows 驱动安装包) |
| eject 之后 | a69c:8d80 | ROM 引导模式,等待主机下载固件 |
| 固件就绪 | a69c:8d83 | 真正的 WiFi 工作模式 |
所以驱动加载前必须先对设备执行 eject(注意不是 usb_modeswitch),把 U 盘“弹出“成固件下载模式。这一步用一条 udev 规则即可自动化。蓝牙部分则无需操心,固件就绪后由内核自带的 btusb 接管。
核心难题:320KB 的固件下载窗口
适配过程中最耗时的不是写代码,而是定位一个隐蔽的硬件限制。最初的现象是驱动日志卡在 bin upload fail: 170400,随后芯片彻底失去响应。
排查一度误入歧途——因为问题只在这块 RISC-V 开发板上出现,很容易怀疑是 JH7110 平台的 USB 兼容性缺陷。直到在 Deepin x86 PC 上完整复现了同样的故障,才推翻平台假设(教训:疑似平台问题,应尽早做跨平台对照实验)。
真正的根因是:AIC8800M80 的 boot ROM 为固件下载预留的 RAM 窗口只有 320KB,写入超过偏移 0x170000 会确定性挂死 ROM。而社区流传的 D80 固件体积在 347~358KB,全部超窗,没有一个能用。
最终在上游仓库的 fw/aic8800D80/ 目录里找到了 fmacfw_8800d80_u02.bin(324720 字节,md5 01acfbebdfb15755e3fe853e7bc95c7d)——这是目前已知唯一在 320KB 窗口之内的公开固件。换上它之后,固件一次下载成功。
内核 6.12 编译修复:3 文件 7 行
上游驱动的 cfg80211 API 版本门控有 3 处判断错误——它误以为某些 API 在内核 6.0 就已引入,实际上它们分别落地于 6.13 和 6.15,导致在 6.12 上编译失败。修复全部是预处理条件的版本号校正:
| 文件 | 修改 |
|---|---|
drivers/aic8800/aic8800_fdrv/rwnx_main.h | rwnx_cfg80211_set_monitor_channel_() 声明门控改为 >= 6.13 |
rwnx_compat.h | cfg80211_rx_spurious_frame 宏门控 6.0 → 6.13 |
rwnx_main.c | set_tx_power 的 parent 参数门控 6.0 → 6.15 |
交叉编译(对已编译的 RISC-V 内核源码树):
# 先编固件加载模块,再编主驱动(依赖前者的符号表)
make -C $K M=$SRC/aic_load_fw ARCH=riscv CROSS_COMPILE=$CROSS KBUILD_MODPOST_WARN=1 modules
make -C $K M=$SRC/aic8800_fdrv ARCH=riscv CROSS_COMPILE=$CROSS \
KBUILD_EXTRA_SYMBOLS=$SRC/aic_load_fw/Module.symvers KBUILD_MODPOST_WARN=1 modules
部署时两个 .ko 拷入模块目录后 depmod -a,固件放入 /lib/firmware/aic8800D80/,加载顺序固定为先 modprobe aic_load_fw,再 modprobe aic8800_fdrv。
开箱即用的自动化
fork 仓库附带一套已在 VisionFive 2 上验证的开机自动化链条:
- udev 规则
99-aic8800.rules:插入网卡自动 eject,触发身份切换; - systemd 服务
aic8800-load.service:按序加载两个内核模块; - NetworkManager autoconnect +
wifi-setup命令行工具:首次配置后开机自动联网。
整个流程从插卡到联网无需人工干预。
过程中的两个教训
- rmmod 会死锁:在网卡仍处于绑定状态时卸载驱动模块,会导致引用计数错乱(-1)并卡死内核——调试期间因此搞挂过两次设备。正确顺序是先解除绑定再卸载。
- 不要试图从 Windows 驱动里抠固件:曾尝试从 Windows
.sys文件中提取固件,因边界错位得到损坏镜像,白费功夫;公开仓库里的固件才是正路。
分支与开源
- 默认分支
starfive-visionfive2-k6.12:适配版,README 为中文,含 VisionFive 2 专属的英文适配文档STARFIVE_VISIONFIVE2.md; main分支保留上游原版(x86 原生编译可参考它);- 编译产物(.ko/.o)未入库,diff 干净,遵循上游原许可证。