WDF-SDHC框架选型:从Storport到KMDF的架构移植

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
// WDF: O2SDHCEvtDevicePrepareHardware (O2SDHC.C:842)
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);
// 传递给 sdstor_legacy 复用层
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 初始化 (sdhc_init.c:187-288)
WDF_DMA_ENABLER_CONFIG_INIT(&dmaConfig,
WdfDmaProfileScatterGather, 1024*1024);
dmaConfig.WdmDmaVersionOverride = 3; // DMA v3 支持 IOMMU
WdfDmaEnablerCreate(DevExt->WdfDevice, &dmaConfig, ...);

// Common Buffer 用于 ADMA2 描述符表
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 中断创建 (sdhc_isr.c:34-90)
WDF_INTERRUPT_CONFIG_INIT(&InterruptConfig,
SDHCEvtInterruptIsr, // DIRQL: 读状态、清中断、判断来源
SDHCEvtInterruptDpc); // DISPATCH: card_init、创建 Child PDO
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
// WDF 层注入 (O2SDHCEvtDevicePrepareHardware)
devExt->pdx.host.pci_dev.membase = devExt->RegsBase[0]; // BAR0 映射地址

// sdstor_legacy 层使用 (host.c)
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
// WDF 层分配 Common Buffer 并注入到复用层
pdev_ext->dma_buff.va = WdfCommonBufferGetAlignedVirtualAddress(DevExt->dmadescbuf);
pdev_ext->dma_buff.pa = WdfCommonBufferGetAlignedLogicalAddress(DevExt->dmadescbuf);
pdev_ext->dma_buff.len = 4096;

// sdstor_legacy/transhandler.c 使用 dma_buff 构建 ADMA2 描述符

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
// o2sdhc: 创建 Child PDO (O2SDHC.C:1965)
O2SDHCEvtChildListCreateDevice(...) {
SDHCCreatePdo(ParentDevice, ChildInit);
WdfDeviceCreateDeviceInterface(..., &GUID_DEVINTERFACE_STORAGEPORT, ...);
}

// sdhcstor: Attach 到 Child PDO 上方 (sdhcstor.c:19)
SDHCSTOR_AddDevice(DriverObject, PhysicalDeviceObject) {
IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION), ..., &DeviceObject);
// PhysicalDeviceObject = o2sdhc 创建的 Child PDO
DeviceExtension->LowerDeviceObject =
IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
}

5.4 sdhcstor 具体解决什么问题

核心问题:Windows 存储子系统(Disk.sys、PartMgr.sys、NTFS)只通过 SCSI 协议 跟磁盘通信。SD 卡不是 SCSI 设备,必须有人伪装成一个。

sdhcstor 做两件具体的事:

① 设备身份声明 — 让 Windows 认为 SD 卡是一个磁盘

1
2
3
4
// disk.c — 响应 IOCTL_STORAGE_QUERY_PROPERTY ("你是什么设备?")
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
// disk.c:260 — 接收 Disk.sys 发来的 IRP_MJ_SCSI
SDHCSTOR_HandleInternalDeviceControl(DeviceObject, Irp) {
// 从 IRP 中取出 SCSI Request Block (SRB)
Request = IoStack->Parameters.Others.Argument1;

switch (srbEx->SrbFunction) {
case SRB_FUNCTION_EXECUTE_SCSI:
// 从 SRB 中解包 CDB (SCSI Command Descriptor Block)
// CDB 里面才是真正的命令: READ(10), WRITE(10), INQUIRY...
GetSrbScsiData(srbEx, &CdbLength8, ...);
// 入队串行处理
SDHCSTOR_QueueAddIrp(DeviceObject, Irp);
return STATUS_PENDING;
case SRB_FUNCTION_CLAIM_DEVICE:
// Disk.sys 说:"这个设备归我管了"
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 移植步骤

  1. 搭建 KMDF 骨架:基于 PCIDRV 示例,实现 DriverEntry → EvtDeviceAdd → PrepareHardware
  2. 注入复用层:将 sdstor_legacy 目录整体引入,通过 membase 指针桥接
  3. 实现 I/O 路径:Sequential Queue → DMA Transaction → 复用层 card_adma2_rw_data
  4. 实现中断:ISR 读状态/清中断,DPC 处理卡插拔和传输完成
  5. 自建存储层:sdhcstor WDM 驱动处理 SCSI 命令
  6. 电源管理: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 功能

移植后获得的收益:

  1. Win11 兼容性:WDF DMA API 原生支持 IOMMU/DMA-Remapping
  2. 代码简化:消除 thread_main + Tag Queue + SpinLock 复杂同步
  3. 电源管理:WDF Power Policy 框架原生支持 RTD3
  4. 可维护性:WDF 对象生命周期自动管理,减少资源泄漏风险