WDF-SDHC存储驱动框架设计:初始化、I/O流水与电源管理

WDF-SDHC存储驱动框架设计:初始化、I/O流水与电源管理

概述

本文从 WDF SD Host Controller 驱动的三条核心主线出发,梳理驱动与硬件 SD Host 资源及 OS 上下游的完整调用流水:

  1. 初始化路径:从 PnP 枚举到 SD 卡就绪
  2. I/O 数据路径:从用户读写请求到 SDHCI 寄存器操作
  3. 电源状态管理:D-state 转换与硬件上下文保存/恢复

1. 驱动分层架构总览

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
38
39
┌─────────────────────────────────────────────────────────────────────────┐
│ WDF-sdhcstor 完整驱动栈 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ OS 上游: File System (NTFS/exFAT) → Disk.sys → PartMgr.sys │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ IRP_MJ_SCSI (SRB: READ/WRITE/INQUIRY/READ_CAPACITY) │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ sdhcstor/ (自建 WDM Port Driver) │ │
│ │ SCSI 命令解析 → 转换为扇区地址 + 块数 │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ Read/Write Request (sector_addr, sector_cnt, direction) │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ o2sdhc/ (KMDF Storage Driver) │ │
│ │ ┌─────────────┐ ┌──────────────┐ ┌────────────────────┐ │ │
│ │ │ sdhc_queue.c│ │ sdhc_isr.c │ │ sdhc_init.c │ │ │
│ │ │ I/O Queue │ │ ISR + DPC │ │ DMA + Queue Init │ │ │
│ │ └─────────────┘ └──────────────┘ └────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ SD 命令 + DMA 描述符 │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ sdstor_legacy/ (SD 协议栈复用层) │ │
│ │ ┌──────────┐ ┌──────────────┐ ┌──────────────────────┐ │ │
│ │ │ host.c │ │ cmdhandler.c │ │ transhandler.c │ │ │
│ │ │ 寄存器IO │ │ SD命令生成 │ │ ADMA2描述符构建 │ │ │
│ │ └──────────┘ └──────────────┘ └──────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ MMIO: READ_REGISTER / WRITE_REGISTER │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Hardware: PCIe SD Host Controller (Bayhub GG8) │ │
│ │ BAR0: SDHCI 标准寄存器 (0x00-0x7F) │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘

2. 初始化路径:从 PnP 枚举到 SD 卡就绪

2.1 完整初始化时序

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
PnP Manager                    WDF Framework                 o2sdhc Driver
│ │ │
│ IRP_MN_START_DEVICE │ │
├─────────────────────────────►│ │
│ │ EvtDevicePrepareHardware │
│ ├─────────────────────────────►│
│ │ │ ① 映射BAR0寄存器
│ │ │ ② 初始化Host能力
│ │ │ ③ 初始化Card结构
│ │ │ ④ 配置Host寄存器
│ │◄─────────────────────────────┤
│ │ │
│ │ (框架连接中断) │
│ │ │
│ │ EvtDeviceD0Entry │
│ ├─────────────────────────────►│
│ │ │ ⑤ 设备进入D0
│ │◄─────────────────────────────┤
│ │ │
│ │ (框架使能中断) │
│ │ │
│ │ EvtDeviceSelfManagedIoInit │
│ ├─────────────────────────────►│
│ │ │ ⑥ 检测卡是否在位
│ │ │ ⑦ card_init (SD协议)
│ │ │ ⑧ MediaReadCapacity
│ │ │ ⑨ 创建Child PDO
│ │◄─────────────────────────────┤
│ │ │
│ PnP枚举子设备 │ │
│◄─────────────────────────────┤ │
│ │ │

2.2 各阶段详解

① EvtDevicePrepareHardware — 硬件资源映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// O2SDHC.C:842 — 遍历 PCI 资源,映射 BAR0
for (Index = 0; Index < ResourceCount; Index++) {
Descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, Index);
if (Descriptor->Type == CmResourceTypeMemory) {
// 映射 SDHCI 寄存器空间到内核虚拟地址
devExt->pdx.host.pci_dev.membase = LocalMmMapIoSpace(
Descriptor->u.Memory.Start, Descriptor->u.Memory.Length);
devExt->RegsBase[BAR0] = devExt->pdx.host.pci_dev.membase;
}
}
// 初始化 Host 控制器能力(读 CAPABILITIES 寄存器)
host_init_capbility(&devExt->pdx.host);
// 初始化 Card 数据结构
card_stuct_init(&devExt->pdx);
// 配置 Host 寄存器(时钟、电源、中断使能)
host_init(&devExt->pdx.host);

与硬件的交互

操作 SDHCI 寄存器 偏移 说明
读取能力 CAPABILITIES 0x40 获取 ADMA2/HS/8bit 等支持标志
软复位 SOFTWARE_RESET 0x2F 复位 Host 控制器
时钟配置 CLOCK_CONTROL 0x2C 设置初始 400KHz 时钟
电源配置 POWER_CONTROL 0x29 设置 3.3V/1.8V 供电
中断使能 INT_ENABLE 0x34 使能卡插入/移除中断
信号使能 SIGNAL_ENABLE 0x38 使能中断信号到 PCIe

② EvtDeviceSelfManagedIoInit — SD 卡初始化

1
2
3
4
5
6
7
8
// O2SDHC.C:1033 — 中断已连接后执行
reg32 = SDHCReadRegULong(devExt, BAR0, SDHCI_PRESENT_STATE);
if (reg32 & SDHCI_CARD_PRESENT) {
card_init(&devExt->pdx.card, 1, 1); // 完整 SD 协议初始化
MediaReadCapacity(Device); // 读取卡容量
// 创建 Child PDO,触发 PnP 枚举子设备
WdfChildListAddOrUpdateChildDescriptionAsPresent(list, &Description.Header, NULL);
}

card_init 内部 SD 协议流程

1
2
3
4
5
6
7
8
9
10
11
12
card_init()

├── CMD0 (GO_IDLE_STATE) ← 复位卡到 Idle 状态
├── CMD8 (SEND_IF_COND) ← 检测 SD 2.0+ 电压兼容
├── ACMD41 (SD_SEND_OP_COND) ← 获取 OCR,等待卡上电完成
├── CMD2 (ALL_SEND_CID) ← 获取卡唯一标识
├── CMD3 (SEND_RELATIVE_ADDR) ← 获取 RCA 地址
├── CMD9 (SEND_CSD) ← 获取卡参数(容量、速度等级)
├── CMD7 (SELECT_CARD) ← 选中卡,进入 Transfer 状态
├── ACMD6 (SET_BUS_WIDTH) ← 切换 4-bit 总线宽度
└── CMD6 (SWITCH_FUNC) ← 协商速度模式 (HS/SDR50/SDR104)
└── Tuning (CMD19) ← SDR50/SDR104 需要执行调谐

3. I/O 数据路径:从用户请求到硬件传输

3.1 完整 I/O 流水线

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
┌─────────────────────────────────────────────────────────────────────────┐
│ I/O 请求完整流水线 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 用户进程 ReadFile/WriteFile │
│ │ │
│ ▼ │
│ NTFS → Disk.sys → sdhcstor (SCSI→扇区转换) │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ SequentialQueueEvtIoReadWrite (sdhc_queue.c:185) │ │
│ │ • 提取 DeviceOffset → sec_addr │ │
│ │ • 提取 Length → sec_cnt │ │
│ │ • 判断方向: Read=1, Write=2 │ │
│ └──────────────────────────────┬──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ WdfDmaTransactionInitializeUsingRequest │ │
│ │ → WdfDmaTransactionExecute │ │
│ │ → 框架构建 Scatter-Gather List │ │
│ └──────────────────────────────┬──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ SDEvtProgramDmaFunction (sdhc_queue.c:117) │ │
│ │ • 接收 SCATTER_GATHER_LIST │ │
│ │ • 调用 card_adma2_rw_data (复用层) │ │
│ │ └── build_adma2_desc: 构建 ADMA2 描述符表 │ │
│ │ └── cmd_generate_reg: 生成 SDHCI 命令寄存器值 │ │
│ │ └── cmd_execute_sync: 写入寄存器,等待完成 │ │
│ └──────────────────────────────┬──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ SDHCI 寄存器写入序列 (硬件操作) │ │
│ │ 1. SDHCI_DMA_ADDRESS (0x00) ← ADMA2 描述符表物理地址 │ │
│ │ 2. SDHCI_BLOCK_SIZE (0x04) ← 512 bytes │ │
│ │ 3. SDHCI_BLOCK_COUNT (0x06) ← sec_cnt │ │
│ │ 4. SDHCI_ARGUMENT (0x08) ← sec_addr │ │
│ │ 5. SDHCI_TRANSFER_MODE(0x0C) ← DMA_EN|BLK_CNT_EN|DIR|MULTI │ │
│ │ 6. SDHCI_COMMAND (0x0E) ← CMD18/CMD25 + 响应类型 │ │
│ └──────────────────────────────┬──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 硬件执行 DMA 传输 │ │
│ │ SD Host Controller 按 ADMA2 描述符自动搬运数据 │ │
│ │ 完成后产生 Transfer Complete 中断 │ │
│ └──────────────────────────────┬──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ SDHCEvtInterruptIsr (sdhc_isr.c:93) │ │
│ │ • 读 SDHCI_INT_STATUS (0x30) │ │
│ │ • 写回清除中断位 │ │
│ │ • WdfInterruptQueueDpcForIsr → 调度 DPC │ │
│ └──────────────────────────────┬──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ SDHCEvtInterruptDpc (sdhc_isr.c:168) │ │
│ │ • WdfDmaTransactionDmaCompletedFinal │ │
│ │ • RequestCompletion(request, STATUS_SUCCESS, Length) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘

3.2 ADMA2 描述符格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ADMA2 描述符表 (每项 8 字节):
┌───────────────────────────────────────────────────────────────┐
│ Word 0 (Low 32-bit): │
│ [31:16] Transfer Length (0 = 65536 bytes) │
│ [15:6] Reserved │
│ [5:4] Act: 00=Nop, 01=Reserved, 10=Tran, 11=Link │
│ [3] Int (中断使能) │
│ [2] End (最后一项) │
│ [1] Valid │
│ [0] Reserved │
├───────────────────────────────────────────────────────────────┤
│ Word 1 (High 32-bit): │
│ [31:0] Physical Address (数据缓冲区物理地址) │
└───────────────────────────────────────────────────────────────┘

示例: 读取 4 个扇区 (2048 bytes) 的描述符:
┌──────────────────────────────────────┐
│ Entry 0: Len=2048, Act=Tran, End=1 │
│ Addr=0x12345000 │
└──────────────────────────────────────┘

3.3 ADMA2 描述符中的两块内存:描述符表 vs 数据缓冲区

ADMA2 传输涉及两块独立的物理内存,容易混淆:

内存 分配时机 分配者 物理地址写到哪 用途
描述符表 (4KB) 驱动初始化时 WdfCommonBufferCreate SDHCI_DMA_ADDRESS (0x00) 存放 ADMA2 描述符条目
数据缓冲区 每次 I/O 请求时 用户进程 (ReadFile 的 buffer) ADMA2 描述符的 Address 字段 SD 卡数据的实际搬运目标/来源

描述符表在初始化时一次性分配:

1
2
3
4
// sdhc_init.c:246 — 4KB Common Buffer 用于存放 ADMA2 描述符表
WdfCommonBufferCreate(DevExt->DmaEnabler, 4096, ..., &DevExt->dmadescbuf);
pdev_ext->dma_buff.va = WdfCommonBufferGetAlignedVirtualAddress(...); // CPU 写描述符用
pdev_ext->dma_buff.pa = WdfCommonBufferGetAlignedLogicalAddress(...); // 告诉硬件表在哪

数据缓冲区的物理地址则是每次 I/O 请求时动态获取的,来源是用户进程的 buffer:

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
38
39
40
41
42
43
44
45
46
47
48
用户进程: ReadFile(hFile, userBuffer, 4096, ...)

│ userBuffer 是用户态虚拟地址 (如 0x7FF6`12340000)

┌─────────────────────────────────────────────────────────────────┐
│ NT I/O Manager │
│ │
│ 因为 o2sdhc 设置了 Direct I/O (O2SDHC.C:435): │
│ ioConfig.ReadWriteIoType = WdfDeviceIoDirect; │
│ │
│ I/O Manager 做两件事: │
│ 1. MmProbeAndLockPages — 把用户虚拟页锁定到物理内存 │
│ 2. 创建 MDL (Memory Descriptor List) — 记录虚拟页→物理页帧映射 │
└──────────────────────────────┬──────────────────────────────────┘
│ IRP + MDL

┌─────────────────────────────────────────────────────────────────┐
│ WdfDmaTransactionExecute │
│ │
│ WDF 框架调用 HAL DMA Adapter: │
│ - 从 MDL 的物理页帧号 (PFN) 计算物理地址 │
│ - 如果有 IOMMU,做 PA → Bus Address 映射 │
│ - 生成 SCATTER_GATHER_LIST: │
│ Elements[0] = { Address: 0x1A340000, Length: 4096 } │
│ Elements[1] = { Address: 0x2B780000, Length: 4096 } │
│ (用户 buffer 在物理上可能不连续,所以是 scatter-gather) │
└──────────────────────────────┬──────────────────────────────────┘
│ PSCATTER_GATHER_LIST

┌─────────────────────────────────────────────────────────────────┐
│ SDEvtProgramDmaFunction → card_adma2_rw_data │
│ │
│ // 遍历 SGL,把每个物理地址写入 ADMA2 描述符表 │
│ pTable = pdx->dma_buff.va; // 描述符表的虚拟地址(CPU写入用) │
│ │
│ for (i = 0; i < lbuffer->NumberOfElements; i++) { │
│ itemTotalLen = lbuffer->Elements[i].Length; │
│ itemAddrHdr = lbuffer->Elements[i].Address.LowPart; │
│ ↑ 用户 buffer 对应的物理地址 │
│ │
│ *(pTable++) = gen_adma2_desc_low_32bit(itemTotalLen, TRAN); │
│ *(pTable++) = (u32)itemAddrHdr; // ★ 写入描述符 │
│ } │
│ │
│ // 最后告诉硬件描述符表的物理地址 │
│ sd_data.data_mng.sys_addr = pdx->dma_buff.pa; │
│ // → 写入 SDHCI_DMA_ADDRESS (0x00) 寄存器 │
└─────────────────────────────────────────────────────────────────┘

硬件执行时的读取顺序

1
2
3
4
5
6
7
8
SD Host Controller:
1. 从 SDHCI_DMA_ADDRESS (0x00) 读到描述符表物理地址 → 0xABC00000
2. 从物理地址 0xABC00000 读取第一个描述符条目:
- Length = 4096, Address = 0x1A340000
3. 把 SD 卡数据 DMA 搬运到物理地址 0x1A340000
(这就是用户 ReadFile buffer 的第一个物理页)
4. 读取下一个描述符条目,继续搬运...
5. 遇到 End=1 的描述符,产生 Transfer Complete 中断

总结:用户 ReadFile 的 buffer 虚拟地址 → I/O Manager 锁页生成 MDL → WDF/HAL 翻译为物理地址 SGL → 驱动填入 ADMA2 描述符 → 硬件按描述符 DMA 搬运数据到用户 buffer 的物理页。整个过程中数据零拷贝,直接从 SD 卡搬到用户内存。

3.4 PIO 传输模式(备选路径)

当 ADMA2 不可用时,使用 PIO 模式通过 CPU 逐字搬运:

1
2
3
4
5
6
7
8
9
// cardcommon.c — PIO 读数据
for (block = 0; block < sec_cnt; block++) {
// 等待 Buffer Read Ready
while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_DATA_AVAILABLE));
// 从 SDHCI_BUFFER (0x20) 逐 32-bit 读取
for (i = 0; i < 512/4; i++) {
*buf++ = sdhci_readl(host, SDHCI_BUFFER);
}
}

4. 电源状态管理

4.1 WDF 电源状态机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌─────────────────────────────────────────────────────────────────────────┐
│ WDF 电源状态转换 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ ┌─────────│ D0 (Working)│─────────┐ │
│ │ └──────────────┘ │ │
│ │EvtDeviceD0Entry EvtDeviceD0Exit│ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ └─────────│ Dx (Sleep) │◄────────┘ │
│ └──────────────┘ │
│ │
│ PrepareHardware ──► D0Entry ──► SelfManagedIoInit ──► 正常工作 │
│ │
│ 正常工作 ──► D0Exit ──► Dx (休眠/待机) │
│ │
│ Dx ──► D0Entry ──► 恢复工作 │
│ │
│ SelfManagedIoCleanup ──► ReleaseHardware ──► 设备移除 │
│ │
└─────────────────────────────────────────────────────────────────────────┘

4.2 各回调的硬件操作

回调 方向 硬件操作
EvtDevicePrepareHardware 首次启动 映射 BAR0,初始化 Host 寄存器,配置时钟/电源
EvtDeviceD0Entry Dx → D0 恢复 Host 寄存器状态,重新使能时钟和中断
EvtDeviceSelfManagedIoInit 首次 D0 后 检测卡、执行 card_init、创建 Child PDO
EvtDeviceD0Exit D0 → Dx 保存寄存器上下文,关闭时钟,禁用中断
EvtDeviceReleaseHardware 设备移除 取消映射 BAR0,释放 DMA 资源

4.3 框架自动管理的中断生命周期

1
2
3
4
5
6
7
D0Entry 完成后:
→ 框架自动调用 EvtInterruptEnable (使能 SDHCI 中断)
→ 中断已连接,可以响应卡插拔

D0Exit 之前:
→ 框架自动调用 EvtInterruptDisable (禁用 SDHCI 中断)
→ 框架自动断开中断连接
1
2
3
4
5
6
7
8
9
10
// sdhc_isr.c — 中断使能回调
NTSTATUS SDHCEvtInterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE Device) {
PDEVICE_EXTENSION devExt = GetDeviceContext(Device);
// 使能卡插入/移除 + 传输完成中断
SDHCWriteRegULong(devExt, BAR0, SDHCI_INT_ENABLE,
SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
SDHCI_INT_CMD_COMP | SDHCI_INT_TRANSFER_COMP);
SDHCWriteRegULong(devExt, BAR0, SDHCI_SIGNAL_ENABLE, ...);
return STATUS_SUCCESS;
}

4.4 Power Policy 配置

1
2
3
// O2SDHCEvtDeviceAdd (O2SDHC.C:415)
// 声明本驱动不是 Power Policy Owner(存储栈中由 Port Driver 管理)
WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE);

在存储驱动栈中,Power Policy Owner 通常是 Port Driver(sdhcstor),它决定何时进入低功耗状态。o2sdhc 作为 Function Driver 响应电源 IRP 但不主动发起。


5. WDF 对象模型与设备上下文

5.1 对象层次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
WDFDRIVER (O2SDHC)

└── WDFDEVICE (SD Host Controller FDO)

├── WDFINTERRUPT ─── ISR + DPC 回调

├── WDFQUEUE (Sequential) ─── EvtIoRead/Write/DeviceControl

├── WDFDMAENABLER
│ ├── WDFCOMMONBUFFER (4KB, ADMA2 描述符表)
│ ├── WDFDMATRANSACTION (Read)
│ └── WDFDMATRANSACTION (Write)

└── WDFCHILDLIST
└── Child PDO (SD Card) ─── 触发 sdhcstor 加载

5.2 DEVICE_EXTENSION 核心字段

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
typedef struct _DEVICE_EXTENSION {
// WDF 对象句柄
WDFDEVICE WdfDevice;
WDFINTERRUPT WdfInterrupt;
WDFQUEUE WdfQueue;
WDFDMAENABLER DmaEnabler;
WDFDMATRANSACTION ReadDmaTransaction;
WDFDMATRANSACTION WriteDmaTransaction;

// 硬件资源
PUCHAR RegsBase[2]; // BAR0/BAR1 映射地址
ULONG RegsLength[2];

// SD 协议栈 (sdstor_legacy 复用层)
bht_dev_ext_t pdx; // 内含 sd_host_t + sd_card_t

// I/O 状态 (Queue 回调 → DMA 回调 传递)
u8 dir; // 1=Read, 2=Write
u32 sec_addr; // 起始扇区
u16 sec_cnt; // 扇区数

// 卡状态
BOOLEAN CardPresentState;
DISK_GEOMETRY DiskGeometry;
LARGE_INTEGER PartitionLength;
} DEVICE_EXTENSION;

6. SDHCI 关键寄存器映射

偏移 名称 宽度 初始化使用 I/O使用 电源使用
0x00 DMA_ADDRESS 32 ✅ ADMA2表地址
0x04 BLOCK_SIZE 16 ✅ 512
0x06 BLOCK_COUNT 16 ✅ sec_cnt
0x08 ARGUMENT 32 ✅ sec_addr
0x0C TRANSFER_MODE 16 ✅ DMA/方向/多块
0x0E COMMAND 16 ✅ CMD18/CMD25
0x10 RESPONSE 128 ✅ CID/CSD ✅ 命令响应
0x20 BUFFER 32 ✅ PIO数据
0x24 PRESENT_STATE 32 ✅ 卡检测 ✅ 忙等待
0x28 HOST_CONTROL 8 ✅ 总线宽度
0x29 POWER_CONTROL 8 ✅ 电压设置 ✅ 开/关电源
0x2C CLOCK_CONTROL 16 ✅ 时钟频率 ✅ 开/关时钟
0x2F SOFTWARE_RESET 8 ✅ 复位
0x30 INT_STATUS 32 ✅ ISR读取
0x34 INT_ENABLE 32 ✅ 使能中断 ✅ 禁用中断
0x38 SIGNAL_ENABLE 32 ✅ 使能信号 ✅ 禁用信号
0x3E HOST_CONTROL2 16 ✅ UHS模式
0x40 CAPABILITIES 64 ✅ 读取能力

7. 总结

WDF SD Host Controller 驱动的核心职责可归纳为三条主线:

主线 触发条件 核心操作 涉及硬件
初始化 PnP 枚举 BAR映射 → Host配置 → Card识别 → PDO创建 CAPABILITIES, CLOCK, POWER, CMD寄存器
I/O 传输 用户读写 Queue接收 → DMA事务 → ADMA2描述符 → SD命令 → 中断完成 DMA_ADDR, BLOCK, COMMAND, INT_STATUS
电源管理 系统休眠/唤醒 保存/恢复寄存器 → 开关时钟 → 开关中断 CLOCK, POWER, INT_ENABLE

三条主线共享同一套 sdstor_legacy 协议栈,通过 devExt->pdx.host.pci_dev.membase 统一访问硬件寄存器。