WDF-SDHC框架选型:从Storport到KMDF的架构移植
概述
本文介绍将O2Micro SD Host Controller驱动从Storport框架移植到WDF(KMDF)的完整过程:移植动机、框架选型决策、逐子系统的接口对标关系、sdstor_legacy复用层设计,以及移植方法论总结。
1. 移植动机
1.1 Storport 框架的架构性缺陷
原项目基于 Storport Miniport 框架,在 Win11 上暴露出以下问题:
| 问题 |
根因 |
影响 |
| DDI 限制 |
Storport 禁止调用大量 WDM DDI(MmMapIoSpace、IoConnectInterrupt 等) |
无法灵活管理硬件资源 |
| DMA-Remapping 不兼容 |
Win11 24H2 强制 DMA 安全限制,Storport 内部 DMA 管理与 IOMMU 冲突 |
驱动加载失败或蓝屏 |
| 线程模型僵化 |
必须自建 thread_main + Tag Queue 管理并发 |
代码复杂度高,竞态问题多 |
| 电源管理受限 |
HwAdapterControl 回调粒度粗,PoFx 集成需大量 workaround |
RTD3 实现困难 |
1.2 移植目标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| ┌─────────────────────────────────────────────────────────────────────────┐ │ Storport 架构 → WDF (KMDF) 架构 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ Storport 架构 WDF 架构 │ │ ┌──────────────────────┐ ┌──────────────────────┐ │ │ │ Storport.sys │ │ WDF Framework │ │ │ │ (Port Driver) │ │ (WdfLdr.sys) │ │ │ ├──────────────────────┤ ├──────────────────────┤ │ │ │ winscsientry.c │ ────► │ O2SDHC.C │ │ │ │ (HW callbacks) │ 重写 │ (WDF callbacks) │ │ │ ├──────────────────────┤ ├──────────────────────┤ │ │ │ tagqueue/ │ ────► │ sdhc_queue.c │ │ │ │ thread_main │ 替代 │ (WDF Queue) │ │ │ ├──────────────────────┤ ├──────────────────────┤ │ │ │ host/ card/ cmd/ │ ════► │ sdstor_legacy/ │ │ │ │ (SD Protocol) │ 直接复用 │ (SD Protocol) │ │ │ ├──────────────────────┤ ├──────────────────────┤ │ │ │ (Storport内置 │ ────► │ sdhcstor/ │ │ │ │ Disk/SCSI层) │ 新增自建 │ (WDM Port Driver) │ │ │ └──────────────────────┘ └──────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘
|
2. 框架选型决策
2.1 候选方案对比
| 特性 |
Inbox Sdbus.sys |
自定义 KMDF |
| 协议栈控制 |
❌ 不可控(黑盒) |
✅ 完全可控 |
| SD Express 支持 |
⚠️ 有限 |
✅ 可定制模式切换 |
| BBR 热插拔模拟 |
❌ 不支持 |
✅ 支持 |
| 调试可见性 |
❌ 黑盒 |
✅ 完全透明 |
| DMA-Remapping 兼容 |
✅ 框架处理 |
✅ WDF DMA API |
| 开发复杂度 |
低 |
中(有 PCIDRV 参考) |
2.2 最终选择:自定义 KMDF
基于微软 PCIDRV 示例,KMDF 提供完整的 PCI 设备驱动能力:
| KMDF 接口 |
PCIDRV 示例 |
WDF-sdhcstor 应用 |
| PnP/Power 事件 |
EvtDeviceAdd, EvtDeviceD0Entry |
✅ 相同 |
| 硬件资源映射 |
EvtDevicePrepareHardware |
✅ BAR0/BAR1 映射 |
| DMA 接口 |
Scatter-Gather DMA |
✅ ADMA2 描述符 |
| 中断处理 |
EvtInterruptIsr + EvtInterruptDpc |
✅ SDHC 中断 |
| I/O 队列 |
WdfIoQueueCreate |
✅ Sequential Queue |
3. 逐子系统移植对标
3.1 驱动入口
1 2 3 4 5 6 7 8 9
| Storport: WDF (KMDF): ───────────────────────────────────────────────────────────────────────── HW_INITIALIZATION_DATA HwInitData; WDF_DRIVER_CONFIG config; HwInitData.HwFindAdapter = ...; WDF_DRIVER_CONFIG_INIT(&config, HwInitData.HwInitialize = ...; O2SDHCEvtDeviceAdd); HwInitData.HwStartIo = ...; WdfDriverCreate(DriverObject, HwInitData.HwInterrupt = ...; RegistryPath, &attrib, StorPortInitialize(DriverObject, &config, &driverObject); RegistryPath, &HwInitData, NULL);
|
关键差异:Storport 在 DriverEntry 中一次性注册所有回调(声明式),WDF 在 EvtDeviceAdd 中分步注册各类回调(命令式、按需组合)。
3.2 设备发现与资源映射
| 阶段 |
Storport |
WDF |
| 设备发现 |
HwFindAdapter — Storport 传入 ConfigInfo |
EvtDevicePrepareHardware — 遍历 ResourcesTranslated |
| BAR 映射 |
StorPortGetDeviceBase(ConfigInfo->AccessRanges[0]) |
MmMapIoSpace(resDesc->u.Memory.Start, Length) |
| 设备扩展 |
Storport 分配 bht_dev_ext_t |
WDF 分配 DEVICE_EXTENSION(内嵌 bht_dev_ext_t pdx) |
| 初始化时机 |
HwInitialize + HwPassiveInitialize |
EvtDeviceSelfManagedIoInit(PASSIVE_LEVEL) |
1 2 3 4 5 6 7 8 9 10 11
| for (i = 0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) { resDesc = WdfCmResourceListGetDescriptor(ResourcesTranslated, i); if (resDesc->Type == CmResourceTypeMemory) { devExt->RegsBase[barIndex] = MmMapIoSpace( resDesc->u.Memory.Start, resDesc->u.Memory.Length, MmNonCached); devExt->pdx.host.pci_dev.membase = devExt->RegsBase[0]; } }
|
3.3 I/O 请求处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| Storport I/O 路径: WDF I/O 路径: ───────────────────────────────────────────────────────────────────────── Storport.sys 收到 SRB WDF Framework 收到 IRP │ │ ▼ ▼ HwBuildIo (DISPATCH_LEVEL) SequentialQueueEvtIoReadWrite │ │ ▼ ▼ HwStartIo (DISPATCH_LEVEL, 串行) 解析 WDF_REQUEST_PARAMETERS │ │ ▼ ▼ thread_main → Tag Queue 入队 WdfDmaTransactionInitialize │ │ ▼ ▼ Tag 状态机: FREE→BUILT→EXECUTING SDEvtProgramDmaFunction │ │ ▼ ▼ card_adma2_rw_data (SD命令) card_adma2_rw_data (复用!) │ │ ▼ ▼ HwInterrupt → DPC → 完成 SRB ISR → DPC → RequestCompletion
|
核心变化:
- Storport 需要自建
thread_main 工作线程 + Tag Queue 状态机管理并发
- WDF 的 Sequential Queue 天然串行化,无需手动线程管理
SynchronizationScopeDevice 确保 Queue 回调和 DPC 不会并发执行
3.4 DMA 传输
| 方面 |
Storport |
WDF |
| SGL 获取 |
StorPortGetScatterGatherList |
EvtProgramDma 回调参数直接提供 |
| ADMA2 描述符 |
自管理(tagqueue/tqadma2.c) |
复用 sdstor_legacy/transhandler.c |
| DMA 缓冲区 |
StorPortGetUncachedExtension |
WdfCommonBufferCreate(4KB) |
| 事务管理 |
手动跟踪 Tag 状态 |
WdfDmaTransaction 对象自动管理 |
| IOMMU 兼容 |
❌ 框架内部冲突 |
✅ WDF DMA API 原生支持 |
1 2 3 4 5 6 7 8 9 10
| WDF_DMA_ENABLER_CONFIG_INIT(&dmaConfig, WdfDmaProfileScatterGather, 1024*1024); dmaConfig.WdmDmaVersionOverride = 3; WdfDmaEnablerCreate(DevExt->WdfDevice, &dmaConfig, ...);
WdfCommonBufferCreate(DevExt->DmaEnabler, 4096, ...); pdev_ext->dma_buff.va = WdfCommonBufferGetAlignedVirtualAddress(...); pdev_ext->dma_buff.pa = WdfCommonBufferGetAlignedLogicalAddress(...);
|
3.5 中断处理
| 方面 |
Storport |
WDF |
| 注册方式 |
HwInitData.HwInterrupt = scsi_HwInterrupt |
WdfInterruptCreate + ISR/DPC 分离 |
| ISR 级别 |
DIRQL,单一回调处理所有逻辑 |
DIRQL ISR + DISPATCH DPC 分层 |
| 同步机制 |
Storport 内置串行化 |
AutomaticSerialization = TRUE |
| 连接/断开 |
手动管理 |
框架自动:D0Entry 后连接,D0Exit 前断开 |
1 2 3 4 5 6
| WDF_INTERRUPT_CONFIG_INIT(&InterruptConfig, SDHCEvtInterruptIsr, SDHCEvtInterruptDpc); InterruptConfig.AutomaticSerialization = TRUE; WdfInterruptCreate(DevExt->WdfDevice, &InterruptConfig, ...);
|
3.6 电源管理
| 方面 |
Storport |
WDF |
| 回调入口 |
HwAdapterControl(ScsiStopAdapter/ScsiRestartAdapter) |
EvtDeviceD0Entry / EvtDeviceD0Exit |
| 状态粒度 |
仅 Stop/Restart 两态 |
D0/D1/D2/D3hot/D3cold 完整状态机 |
| PoFx 集成 |
需手动调用 StorPortInitializePoFxPower |
WDF Power Policy 框架原生支持 |
| RTD3 |
大量 workaround 代码 |
WdfDeviceInitSetPowerPolicyOwnership + Idle 设置 |
3.7 线程模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Storport 线程模型: WDF 线程模型: ───────────────────────────────────────────────────────────────────────── ┌─────────────────────┐ ┌─────────────────────┐ │ thread_main │ │ WDF Sequential │ │ (自建工作线程) │ │ Queue │ │ │ │ (框架管理) │ │ ┌───────────────┐ │ │ │ │ │ Tag Queue │ │ 替代为 │ 请求天然串行分发 │ │ │ FREE→BUILT→ │ │ ──────────► │ 无需手动同步 │ │ │ EXECUTING→ │ │ │ │ │ │ COMPLETED │ │ │ SynchronizationScope│ │ └───────────────┘ │ │ = Device │ │ │ │ (Queue+DPC 互斥) │ │ 手动 SpinLock 同步 │ │ │ └─────────────────────┘ └─────────────────────┘
|
4. sdstor_legacy 复用层
4.1 复用策略
移植的核心原则:框架层重写,协议层复用。SD 协议栈(卡识别、命令发送、数据传输)与框架无关,可直接复用。
4.2 复用模块清单
| 模块 |
文件 |
功能 |
复用方式 |
| Host 寄存器访问 |
host.c |
sdhci_readl/writel/readw/writew |
直接复用,membase 指针传递 |
| SD 卡初始化 |
cardinterface.c |
card_init 完整流程 |
直接复用 |
| SD 命令处理 |
cmdhandler.c |
cmd_generate_reg, cmd_execute_sync |
直接复用 |
| DMA 描述符 |
transhandler.c |
build_adma2_desc, link_adma2_desc |
直接复用 |
| 中断逻辑 |
irqhandler.c |
中断状态解析 |
直接复用 |
| 配置管理 |
cfgmng.c |
INF/注册表配置读取 |
直接复用 |
| SD 协议 |
sd.c |
卡识别、速度切换、tuning |
直接复用 |
| 通用卡操作 |
cardcommon.c |
PIO 读写、命令发送封装 |
直接复用 |
4.3 membase 指针传递机制
复用层通过 sd_host_t.pci_dev.membase 访问硬件寄存器,WDF 层在 PrepareHardware 时注入:
1 2 3 4 5 6 7 8 9 10
| devExt->pdx.host.pci_dev.membase = devExt->RegsBase[0];
static inline u32 sdhci_readl(sd_host_t* host, u32 reg) { return READ_REGISTER_ULONG((PULONG)(host->pci_dev.membase + reg)); } static inline void sdhci_writel(sd_host_t* host, u32 reg, u32 val) { WRITE_REGISTER_ULONG((PULONG)(host->pci_dev.membase + reg), val); }
|
4.4 DMA 缓冲区传递
1 2 3 4 5 6
| pdev_ext->dma_buff.va = WdfCommonBufferGetAlignedVirtualAddress(DevExt->dmadescbuf); pdev_ext->dma_buff.pa = WdfCommonBufferGetAlignedLogicalAddress(DevExt->dmadescbuf); pdev_ext->dma_buff.len = 4096;
|
5. 存储栈分层变化
5.1 Storport 架构(内置 Disk/SCSI)
Storport.sys 自身提供完整的存储栈:Disk.sys 直接发 SRB 给 Storport,Storport 分发给 Miniport。驱动只需实现 HW 回调。
5.2 WDF 架构(需自建存储层)
WDF 是通用框架,不提供存储栈。需要自建 sdhcstor WDM 驱动来承接 Disk.sys 的 SCSI 请求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ┌────────────────────────────────────────────────────────────────────┐ │ Storport 架构 WDF 架构 │ ├────────────────────────────────────────────────────────────────────┤ │ │ │ Disk.sys Disk.sys │ │ │ │ │ │ ▼ ▼ │ │ Storport.sys ◄── 内置 sdhcstor.sys ◄── 自建 WDM │ │ │ SCSI/Disk层 │ SCSI 处理 │ │ ▼ ▼ │ │ Miniport (HW callbacks) o2sdhc.sys (KMDF) │ │ │ │ │ │ ▼ ▼ │ │ SD Host Controller SD Host Controller │ │ │ └────────────────────────────────────────────────────────────────────┘
|
5.3 驱动栈绑定机制
WDF 架构中三层驱动的绑定通过 PnP 枚举 + Child PDO + IoAttachDeviceToDeviceStack 实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| ┌─────────────────────────────────────────────────────────────────────────┐ │ WDF 存储驱动栈绑定过程 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ Step 1: PCI.sys 枚举出 VEN_1217&DEV_8620 │ │ → PnP 加载 o2sdhc.sys 作为 FDO │ │ │ │ Step 2: o2sdhc 检测到 SD 卡在位 │ │ → WdfChildListAddOrUpdateChildDescriptionAsPresent │ │ → 框架回调 O2SDHCEvtChildListCreateDevice │ │ → SDHCCreatePdo 创建 Child PDO (Hardware ID: "SD\\GenDisk") │ │ │ │ Step 3: PnP Manager 匹配 Child PDO 的 Hardware ID │ │ → 加载 sdhcstor.sys,调用 SDHCSTOR_AddDevice │ │ → IoAttachDeviceToDeviceStack(FDO, ChildPDO) │ │ → sdhcstor FDO attach 到 o2sdhc 的 Child PDO 上方 │ │ │ │ Step 4: sdhcstor 创建自己的 Child PDO (磁盘设备) │ │ → Disk.sys 加载并 attach 到 sdhcstor 的 PDO 上方 │ │ │ │ 最终设备栈: │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ Disk.sys FDO │ │ │ │ (发送 IRP_MJ_SCSI: INQUIRY, READ_CAPACITY, READ, WRITE) │ │ │ ├──────────────────────────────────────────────────────────────────┤ │ │ │ sdhcstor.sys FDO ← IoAttachDeviceToDeviceStack │ │ │ │ (SCSI→SD翻译: 解析 SRB → sec_addr + sec_cnt + direction) │ │ │ ├──────────────────────────────────────────────────────────────────┤ │ │ │ o2sdhc Child PDO ← WdfChildList 创建 (代表 SD 卡) │ │ │ ├──────────────────────────────────────────────────────────────────┤ │ │ │ o2sdhc.sys FDO (KMDF) │ │ │ │ (管理 PCIe 硬件: BAR0 映射, DMA, 中断, SDHCI 寄存器) │ │ │ ├──────────────────────────────────────────────────────────────────┤ │ │ │ PCI.sys PDO (PCI 总线枚举 VEN_1217&DEV_8620) │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘
|
关键代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
| O2SDHCEvtChildListCreateDevice(...) { SDHCCreatePdo(ParentDevice, ChildInit); WdfDeviceCreateDeviceInterface(..., &GUID_DEVINTERFACE_STORAGEPORT, ...); }
SDHCSTOR_AddDevice(DriverObject, PhysicalDeviceObject) { IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION), ..., &DeviceObject); DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); }
|
5.4 sdhcstor 具体解决什么问题
核心问题:Windows 存储子系统(Disk.sys、PartMgr.sys、NTFS)只通过 SCSI 协议 跟磁盘通信。SD 卡不是 SCSI 设备,必须有人伪装成一个。
sdhcstor 做两件具体的事:
① 设备身份声明 — 让 Windows 认为 SD 卡是一个磁盘
1 2 3 4
| devdesc->DeviceType = DIRECT_ACCESS_DEVICE; devdesc->RemovableMedia = TRUE; devdesc->CommandQueueing = FALSE;
|
没有这个回答,Disk.sys 根本不会加载到这个设备上,用户在”此电脑”里看不到任何盘符。
② SCSI 命令接收与翻译 — 把 Disk.sys 的请求转为 SD 操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| SDHCSTOR_HandleInternalDeviceControl(DeviceObject, Irp) { Request = IoStack->Parameters.Others.Argument1; switch (srbEx->SrbFunction) { case SRB_FUNCTION_EXECUTE_SCSI: GetSrbScsiData(srbEx, &CdbLength8, ...); SDHCSTOR_QueueAddIrp(DeviceObject, Irp); return STATUS_PENDING; case SRB_FUNCTION_CLAIM_DEVICE: PDODeviceExtension->Claimed = TRUE; break; } }
|
数据请求的完整翻译链路:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| Disk.sys 发送: ┌─────────────────────────────────────────────────────────┐ │ IRP (IRP_MJ_SCSI) │ │ └── SRB (STORAGE_REQUEST_BLOCK) │ │ └── CDB (SCSI READ(10)) │ │ ├── OpCode = 0x28 (READ_10) │ │ ├── LBA = 0x00001000 │ │ └── TransferLength = 8 blocks │ └─────────────────────────────────────────────────────────┘ │ ▼ sdhcstor 解包 SRB → 提取 CDB → 翻译为扇区参数 ┌─────────────────────────────────────────────────────────┐ │ 转发给 o2sdhc 的 I/O Queue: │ │ sec_addr = 0x1000 │ │ sec_cnt = 8 │ │ dir = READ (1) │ └─────────────────────────────────────────────────────────┘ │ ▼ o2sdhc → sdstor_legacy → SDHCI 寄存器 ┌─────────────────────────────────────────────────────────┐ │ SD 命令写入硬件: │ │ ARGUMENT = 0x1000 (扇区地址) │ │ BLOCK_COUNT = 8 │ │ COMMAND = CMD18 (READ_MULTIPLE_BLOCK) │ │ TRANSFER_MODE = DMA_EN | READ | MULTI_BLOCK │ └─────────────────────────────────────────────────────────┘
|
5.5 为什么 o2sdhc 不能自己做 sdhcstor 的事
| 原因 |
说明 |
| SRB 格式复杂 |
SCSI Request Block 有 Legacy SRB 和 STORAGE_REQUEST_BLOCK 两种格式,CDB 有 CDB16/CDB32/CDBVar 三种封装,解包逻辑繁琐 |
| 设备声明协议 |
Disk.sys 加载前需要先 CLAIM_DEVICE,再 QUERY_PROPERTY,还有 INQUIRY 握手——这是完整的存储枚举协议 |
| 请求队列管理 |
SCSI 层需要自己的 IRP 队列、Cancel Routine、Freeze/Release Queue 机制 |
| 职责分离 |
o2sdhc 管硬件(DMA、中断、寄存器),sdhcstor 管协议翻译,各自独立演进 |
| 在 Storport 中免费 |
Storport.sys 自身就实现了以上全部功能(SRB 分发、设备声明、队列管理),Miniport 只需实现 HwStartIo |
一句话总结:sdhcstor = 自建的微型 Storport,专门为 SD 卡定制的最小 SCSI-to-SD 翻译层。
6. 完整子系统对比表
| 子系统 |
Storport 实现 |
WDF 实现 |
变化 |
| 驱动入口 |
HW_INITIALIZATION_DATA + StorPortInitialize |
WDF_DRIVER_CONFIG + WdfDriverCreate |
重写 |
| 设备发现 |
HwFindAdapter(ConfigInfo) |
EvtDevicePrepareHardware(ResourceList) |
重写 |
| I/O 入口 |
HwStartIo + SRB |
Sequential Queue + WDFREQUEST |
重写 |
| 线程模型 |
thread_main + Tag Queue + SpinLock |
WDF Sequential Queue(框架串行化) |
替代 |
| DMA 管理 |
StorPortGetScatterGatherList + 自管理 |
WdfDmaTransaction + EvtProgramDma |
重写 |
| DMA 缓冲 |
StorPortGetUncachedExtension |
WdfCommonBufferCreate |
重写 |
| 中断 |
HwInterrupt(单一回调) |
ISR + DPC 分离 + AutomaticSerialization |
重写 |
| 电源管理 |
HwAdapterControl + 手动 PoFx |
EvtDeviceD0Entry/Exit + Power Policy |
重写 |
| 子设备 |
Storport 内置 LUN 管理 |
WdfChildList + PDO 创建 |
重写 |
| SD 协议栈 |
host.c / card.c / cmdhandler.c / transhandler.c |
sdstor_legacy/(同一套代码) |
复用 |
| 寄存器访问 |
sdhci_readl/writel via membase |
sdhci_readl/writel via membase(相同) |
复用 |
| 配置管理 |
cfgmng.c |
cfgmng.c |
复用 |
| SCSI/Disk 层 |
Storport.sys 内置 |
sdhcstor/(自建 WDM) |
新增 |
7. 移植方法论
7.1 移植步骤
- 搭建 KMDF 骨架:基于 PCIDRV 示例,实现 DriverEntry → EvtDeviceAdd → PrepareHardware
- 注入复用层:将 sdstor_legacy 目录整体引入,通过 membase 指针桥接
- 实现 I/O 路径:Sequential Queue → DMA Transaction → 复用层 card_adma2_rw_data
- 实现中断:ISR 读状态/清中断,DPC 处理卡插拔和传输完成
- 自建存储层:sdhcstor WDM 驱动处理 SCSI 命令
- 电源管理:D0Entry/D0Exit 中保存/恢复 Host 寄存器状态
7.2 复用 vs 重写决策矩阵
| 判断条件 |
决策 |
| 代码依赖 Storport DDI(StorPortXxx) |
重写 |
| 代码依赖自建线程/同步原语 |
替代为 WDF 机制 |
| 代码仅依赖 membase 寄存器访问 |
直接复用 |
| 代码仅依赖 SD 协议规范 |
直接复用 |
| 功能由 Storport.sys 内置提供 |
新增自建 |
7.3 常见移植陷阱
| 陷阱 |
说明 |
解决方案 |
| IRQL 不匹配 |
Storport HwStartIo 在 DISPATCH,WDF Queue 回调可能在 PASSIVE |
确认 WdfExecutionLevelDispatch 设置 |
| DMA 地址宽度 |
Storport 自动处理 32/64-bit,WDF 需显式配置 |
WdmDmaVersionOverride = 3 |
| 中断共享 |
Storport 自动处理,WDF 需在 ISR 中验证中断来源 |
读 INT_STATUS 判断是否为本设备中断 |
| 存储栈缺失 |
Storport 内置 Disk/SCSI,WDF 无此功能 |
自建 sdhcstor WDM 层 |
| Power Policy Owner |
Storport 是 PPO,WDF 默认也是 PPO |
存储栈中需协调,设置 SetPowerPolicyOwnership(FALSE) |
8. 总结
本次架构移植的核心策略:
- 框架层全部重写(约 40% 代码):利用 WDF 对象模型替代 Storport 回调
- 协议层全部复用(约 50% 代码):sdstor_legacy 通过指针注入无缝桥接
- 存储层全新开发(约 10% 代码):sdhcstor 补齐 WDF 缺失的 SCSI/Disk 功能
移植后获得的收益:
- Win11 兼容性:WDF DMA API 原生支持 IOMMU/DMA-Remapping
- 代码简化:消除 thread_main + Tag Queue + SpinLock 复杂同步
- 电源管理:WDF Power Policy 框架原生支持 RTD3
- 可维护性:WDF 对象生命周期自动管理,减少资源泄漏风险