Storport SD Controller架构(二):工作线程与Storport请求交互机制

Storport SD Controller 架构(二):工作线程与 Storport 请求交互机制

日期: 2026-03-21
系列: Storport SD Controller 架构解析
适用: Windows 驱动开发者、存储系统工程师


1. 概述

1.1 工作线程设计理念

BHTSDDR 驱动的核心设计之一是多工作线程架构

  • 主工作线程 (thread_main): 卡初始化、事件处理、电源管理
  • 标签队列线程: 高效处理并发 I/O 请求
  • 线程间同步: 使用事件对象和 DPC 实现异步通信

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
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
┌─────────────────────────────────────────────────────────────────────┐
│ 工作线程层次架构 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Windows Kernel (NTOS) │ │
│ │ │ │
│ │ 系统工作线程 (ExpWorkerThread) │ │
│ │ │ │ │
│ │ └── PnP Device Action Worker │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Storport.sys (Windows Storage Framework) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ I/O Request Flow: │ │ │
│ │ │ │ │ │
│ │ │ 文件系统 → Class Driver → Storage Stack → Storport │ │ │
│ │ │ │ │ │ │
│ │ │ ▼ │ │ │
│ │ │ SRB (SCSI Request Block) │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ BHTSDDR Miniport Driver │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ HwStartIo() ★ 主入口 │ │ │
│ │ │ │ │ │ │
│ │ │ ▼ │ │ │
│ │ │ scsi_execute() → req_tag_io_add() │ │ │
│ │ │ │ │ │ │
│ │ │ ▼ │ │ │
│ │ │ tagqueue_add() → DPC 调度 │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ Work Threads (工作线程) │ │ │
│ │ │ │ │ │
│ │ │ thread_main() ←─── 主工作线程 │ │ │
│ │ │ │ │ │ │
│ │ │ ├── card_init_thread() ←─── 卡初始化线程 │ │ │
│ │ │ └── card_event_thread() ←─── 卡事件线程 │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

2. 主工作线程 (thread_main)

2.1 线程创建

1
2
3
4
5
6
// winscsientry.c:444
// 在 StorHwPassiveInitialize 的最后创建工作线程
os_create_thread(pdx, &pdx->os.thread[0], pdx, thread_main);

// thread 0 用于主工作线程
// 可配置多个线程: MAX_THREAD_COUNT

2.2 线程入口函数

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
// main/thread.c
void thread_main(void *param)
{
bht_dev_ext_t *pdx = (bht_dev_ext_t *)param;

DbgInfo(MODULE_OS_ENTRY, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"thread_main start\n");

// 设置线程优先级
os_set_thread_priority(pdx, THREAD_PRIORITY_NORMAL);

// 主循环
while(!os_thread_should_terminate(pdx))
{
// 等待事件发生
e_event_t event = os_wait_event(pdx, &pdx->os);

switch(event)
{
case EVENT_TASK_OCCUR:
// 处理任务
thread_handle_task(pdx);
break;

default:
// 睡眠避免 CPU 占用过高
os_sleep(pdx, 10);
break;
}
}

DbgInfo(MODULE_OS_ENTRY, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"thread_main exit\n");
}

2.3 线程事件类型

1
2
3
4
5
6
7
8
9
10
// osapi.h
typedef enum {
EVENT_NONE = 0,
EVENT_TASK_OCCUR, // 有任务需要处理
EVENT_CARD_INIT, // 卡初始化请求
EVENT_CARD_REMOVE, // 卡移除请求
EVENT_RTD3_REQUEST, // Runtime D3 请求
EVENT_RTD3_COMPLETE, // Runtime D3 完成
// ... 更多事件类型
} e_event_t;

3. 标签队列 (Tag Queue) 机制

3.1 Tag Queue 设计理念

为什么需要 Tag Queue?

  • SD Host Controller 有硬件队列深度限制 (通常 32 或 64)
  • Storport 可能有多个并发 I/O 请求
  • Tag Queue 负责请求分发资源管理

3.2 标签队列结构

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
// basic.h
typedef struct tag_queue_s {
// 队列配置
u32 max_queue_depth; // 最大队列深度

// 队列状态
volatile u32 used_cnt; // 已使用的标签数
volatile u32 pending_cnt; // 等待中的请求数

// 标签数组 (硬件队列)
node_t *nodes[MAX_TAG]; // 标签节点数组

// 空闲标签管理
node_t *free_head; // 空闲链表头
node_t *free_tail; // 空闲链表尾

// 同步对象
os_lock_t lock; // 队列锁
os_event_t queue_event; // 队列完成事件
} tag_queue_t;

// 标签节点结构
typedef struct node_s {
u16 tag; // 标签 ID (0-31)
u8 status; // 状态
u8 reserved;

srb_ext_t *srb_ext; // 关联的 SRB 扩展

// DMA 相关
dma_buf_t data_buf; // 数据缓冲区
trans_context_t trans_ctx; // 传输上下文

// 链表指针
struct node_s *next;
} node_t;

3.3 标签状态机

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
┌─────────────────────────────────────────────────────────────────────┐
│ Tag 状态机 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ tag_alloc() │
│ │ │
│ ▼ │
│ ┌─────────┐ tag_build_io() ┌─────────────┐ tag_start_io() │
│ │ FREE │ ────────────────────► │ BUILT │ ──────────────► │
│ │ (空闲) │ │ (已构建) │ │
│ └─────────┘ └─────────────┘ │
│ ▲ │ │
│ │ │ │
│ │ tag_free() tag_complete() │
│ │ │ │
│ │ ┌────────────────────────┘ │
│ │ ▼ │
│ │ ┌─────────────┐ tag_cleanup() │
│ └──│ COMPLETED │ ◄────────────────────────────────────── │
│ │ (已完成) │ │
│ └─────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 状态说明: │ │
│ │ │ │
│ │ FREE ← 空闲状态,可分配给新请求 │ │
│ │ BUILT ← 已构建 DMA 传输,硬件可处理 │ │
│ │ EXECUTING ← 正在执行 │ │
│ │ COMPLETED ← 传输完成,待释放 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

4. SRB 到 Tag Queue 的请求流程

4.1 请求入口: scsi_execute()

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
// winscsientry.c
// scsi_HwStartIO() 调用此函数处理 SCSI 命令
static BOOLEAN scsi_execute(
bht_dev_ext_t *pdx,
PSCSI_REQUEST_BLOCK Srb,
bool *pending_io
)
{
srb_ext_t *srb_ext = (srb_ext_t *)Srb->SrbExtension;

DbgInfo(MODULE_OS_ENTRY, FEATURE_SCSICMD_TRACE, NOT_TO_RAM,
"scsi_execute: CDB[0]=0x%02X LBA=%lld Len=%d\n",
Srb->Cdb[0],
get_lba_from_cdb(Srb),
get_len_from_cdb(Srb));

// 解析 CDB 并构建请求
switch(Srb->Cdb[0])
{
case SCSIOP_READ:
case SCSIOP_WRITE:
// 读/写请求 → 添加到 Tag Queue
return req_tag_io_add(pdx, srb_ext, Srb, pending_io);

case SCSIOP_INQUIRY:
// 查询请求 → 直接处理
return scsi_inquiry(pdx, srb_ext, Srb);

case SCSIOP_TEST_UNIT_READY:
// 测试单元就绪 → 直接处理
return scsi_test_unit_ready(pdx, srb_ext, Srb);

case SCSIOP_REQUEST_SENSE:
// 请求感知数据 → 直接处理
return scsi_request_sense(pdx, srb_ext, Srb);

default:
// 其他命令 → 失败
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
return TRUE; // 同步完成
}
}

4.2 请求添加到 Tag Queue

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
// main/reqmng.c
e_req_result req_tag_io_add(
bht_dev_ext_t *pdx,
srb_ext_t *srb_ext,
PSCSI_REQUEST_BLOCK Srb,
bool *pending_io
)
{
e_req_result result = REQ_SUCCESS;

// 1. 获取标签 (从空闲队列分配)
node_t *node = tag_alloc(&pdx->tag_queue);
if(node == NULL)
{
DbgErr("tag_alloc failed!\n");
Srb->SrbStatus = SRB_STATUS_BUSY;
*pending_io = FALSE;
return REQ_TAG_FULL;
}

// 2. 初始化节点
node_init(node, srb_ext);

// 3. 设置 SRB 关联
srb_ext->node = node;
node->srb_ext = srb_ext;

// 4. 检查设备状态
if(!IS_DEVICE_READY(pdx))
{
// 设备未就绪 → 排队等待
os_set_event(pdx, &pdx->os, EVENT_CARD_INIT);
tag_free(&pdx->tag_queue, node);
Srb->SrbStatus = SRB_STATUS_BUSY;
*pending_io = TRUE;
return REQ_DEVICE_NOT_READY;
}

// 5. 构建 DMA 传输
result = tag_build_io(pdx, node);
if(result != REQ_SUCCESS)
{
tag_free(&pdx->tag_queue, node);
Srb->SrbStatus = SRB_STATUS_ERROR;
return result;
}

// 6. 启动 DMA 传输
result = tag_start_io(pdx, node);
if(result == REQ_PENDING)
{
*pending_io = TRUE; // 异步处理
}
else if(result == REQ_SUCCESS)
{
// 同步完成
*pending_io = FALSE;
}

return result;
}

4.3 请求处理时序图

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
┌─────────────────────────────────────────────────────────────────────┐
│ SRB → Tag Queue 请求处理时序 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ [Storport] [HwStartIO] [req_tag_io_add] [tagqueue] │
│ │ │ │ │ │
│ │ SRB下发 │ │ │ │
│ │──────────────►│ │ │ │
│ │ │ │ │ │
│ │ │ scsi_execute() │ │ │
│ │ │───────────────►│ │ │
│ │ │ │ │ │
│ │ │ │ tag_alloc() │ │
│ │ │ │───────────────►│ │
│ │ │ │ │ │
│ │ │ │ │ ◄─ 分配空闲 Tag │
│ │ │ │ │ │
│ │ │ │◄──────────────│ │
│ │ │ │ │ │
│ │ │ │ tag_build_io() │ │
│ │ │ │───────────────►│ │
│ │ │ │ │ │
│ │ │ │ │ ◄─ 构建DMA描述符 │
│ │ │ │ │ │
│ │ │ │◄──────────────│ │
│ │ │ │ │ │
│ │ │ │ tag_start_io() │ │
│ │ │ │───────────────►│ │
│ │ │ │ │ │
│ │ │ │ │ ◄─ 启动DMA传输 │
│ │ │ │ │ │
│ │ │ │◄──────────────│ │
│ │ │◄──────────────│ │ │
│ │ │ │ │ │
│ │ SRB_PENDING │ │ │ │
│ │◄──────────────│ │ │ │
│ │ │ │ │ │
│ │ │ [中断处理] │ │ │
│ │ │ │ │ │ │
│ │ │◄──────│───────│ │ │
│ │ │ │ │ │ │
│ │ │ ▼ │ │ │
│ │ │ tag_complete()│ │ │
│ │ │───────────────►│ │ │
│ │ │ │ │ │
│ │ │ │ tag_free() │ │
│ │ │ │───────────────►│ │
│ │ │ │ │ │
│ │ │ │◄──────────────│ │
│ │ │ │ │ │
│ │ SRB完成通知 │ │ │ │
│ │◄──────────────│ │ │ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ │
└─────────────────────────────────────────────────────────────────────┘

5. 中断与 DPC 处理

5.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
// winscsientry.c:837
BOOLEAN scsi_HwInterrupt(IN PVOID DeviceExtension)
{
return sdhci_irq((bht_dev_ext_t *)DeviceExtension);
}

// host/irqhandler.c
BOOLEAN sdhci_irq(bht_dev_ext_t *pdx)
{
u32 int_status = sdhci_readl(&pdx->host, SDHCI_INT_STATUS);
u32 int_enable = sdhci_readl(&pdx->host, SDHCI_INT_ENABLE);

// 清除中断标志
sdhci_writel(&pdx->host, SDHCI_INT_STATUS, int_status);

// 检查传输完成中断
if(int_status & SDHCI_INT_TRANSFER_COMPLETE)
{
// 调度 DPC 完成传输
os_issue_dpc(pdx, trans_done_dpc, NULL);
return TRUE;
}

// 检查命令完成中断
if(int_status & SDHCI_INT_CMD_COMPLETE)
{
os_issue_dpc(pdx, cmd_done_dpc, NULL);
return TRUE;
}

// 检查错误中断
if(int_status & (SDHCI_INT_ERROR | SDHCI_INT_CMD_TIMEOUT))
{
os_issue_dpc(pdx, error_dpc, NULL);
return TRUE;
}

return FALSE; // 不是本设备的中断
}

5.2 DPC (Deferred Procedure Call) 完成处理

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
// host/transhandler.c
void trans_done_dpc(
bht_dev_ext_t *pdx,
PVOID DeviceExtension,
PVOID SystemArgument1,
PVOID SystemArgument2
)
{
node_t *node = (node_t *)SystemArgument1;

DbgInfo(MODULE_OS_ENTRY, FEATURE_TRANS_TRACE, NOT_TO_RAM,
"trans_done_dpc: tag=%d\n", node->tag);

// 1. 标记传输完成
tag_complete(&pdx->tag_queue, node);

// 2. 复制数据 (如果需要)
if(node->trans_dir == DATA_DIR_IN)
{
// DMA → SRB Buffer
copy_data_to_srb(pdx, node);
}

// 3. 更新状态
node->status = NODE_STATUS_COMPLETED;

// 4. 完成 SRB
complete_srb(pdx, node->srb_ext, SRB_STATUS_SUCCESS);

// 5. 释放 Tag
tag_free(&pdx->tag_queue, node);
}

5.3 SRB 完成通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 驱动使用 Storport 提供的 API 完成 SRB
void complete_srb(
bht_dev_ext_t *pdx,
srb_ext_t *srb_ext,
UCHAR SrbStatus
)
{
PSCSI_REQUEST_BLOCK Srb = srb_ext->psrb;

// 设置状态
Srb->SrbStatus = SrbStatus;

// 设置感知数据 (如果有错误)
if(SrbStatus != SRB_STATUS_SUCCESS)
{
srb_ext->sense_data.Valid = TRUE;
srb_ext->sense_data.SenseKey = ...;
srb_ext->sense_data.AddSenseCode = ...;
}

// ★ 关键: 通知 Storport 请求完成
StorPortNotification(RequestComplete, pdx, Srb);
}

6. 传输模式 (SDMA / ADMA2 / ADMA3)

6.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
// tagqueue/tqpolicy.c
e_trans_type select_transfer_mode(
bht_dev_ext_t *pdx,
srb_ext_t *srb_ext
)
{
// 1. 检查设备能力
if(!pdx->host.feature.adma2_supp)
return TRANS_SDMA;

// 2. 检查请求长度
u32 len = srb_ext->req.tag_req_t.sec_cnt * 512;
if(len > MAX_SDMA_LENGTH)
return TRANS_ADMA2;

// 3. 检查 Scatter-Gather
if(srb_ext->req.srb_sg_len == 1)
return TRANS_ADMA2;
else
return TRANS_SDMA;

// 4. 检查电源状态
if(pdx->pm_state.current_state == PM_STATE_D3)
return TRANS_PIO; // 低功耗模式只能 PIO
}

6.2 传输模式对比

模式 描述 优点 缺点 适用场景
SDMA 单次 DMA,直接指定数据地址 简单,低延迟 需要连续物理内存 小块传输 (<4KB)
ADMA2 高级 DMA,使用描述符表 支持 Scatter-Gather 描述符需要 IOVA 中等大小传输
ADMA3 ADMA2 增强,支持双缓冲区 高性能,低功耗 配置复杂 大块传输
PIO 程序化 I/O,CPU 直接访问 兼容性好 CPU 占用高 低功耗/错误恢复

6.3 ADMA2 描述符表

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
┌─────────────────────────────────────────────────────────────────────┐
│ ADMA2 描述符表格式 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Descriptor Entry (64-bit) │ │
│ │ ┌────────────────┬────────────────┬───────┬───────┐ │ │
│ │ │ Address [63:32] │ Length [15:0] │ Type │ Attr │ │ │
│ │ └────────────────┴────────────────┴───────┴───────┘ │ │
│ │ │ │
│ │ Type: │ │
│ │ - 00b: FDS (Fetch Descriptor) │ │
│ │ - 01b: Tran (Data Transfer) │ │
│ │ - 10b: Link (Link to next descriptor table) │ │
│ │ - 11b: Nop (No Operation) │ │
│ │ │ │
│ │ Attr: │ │
│ │ - Valid: 描述符有效 │ │
│ │ - End: 描述符链结束 │ │
│ │ - Int: 产生中断 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 示例: 传输 3 个非连续数据块 │ │
│ │ │ │
│ │ ┌─────────┬──────┬────┬─────┐ │ │
│ │ │ Addr0 │ Len0 │ 01 │ V │ ───► Data Block 0 │ │
│ │ ├─────────┼──────┼────┼─────┤ │ │
│ │ │ Addr1 │ Len1 │ 01 │ V │ ───► Data Block 1 │ │
│ │ ├─────────┼──────┼────┼─────┤ │ │
│ │ │ Addr2 │ Len2 │ 01 │ VE │ ───► Data Block 2 (End) │ │
│ │ └─────────┴──────┴────┴─────┘ │ │
│ │ V=Valid, VE=Valid+End │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

7. 工作线程与请求的同步机制

7.1 事件同步对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// winapi.h
typedef struct {
// Storport 事件对象
PSTOR_EVENT pStorEvent;

// 事件状态
volatile BOOLEAN signaled;
} win_evt_t;

// 事件管理器
typedef struct {
u32 evt_cnt;
PVOID pevt_array[MAX_EVENTS];
} evt_mgr_t;

7.2 线程等待模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// winapi.c
e_event_t os_wait_event(void *pdx, os_struct *os)
{
evt_mgr_t *mgr = &os->evt_mgr;
NTSTATUS ret;

// ★ 关键: 使用 StorPortWaitForSingleObject 等待
// 这会挂起线程直到某个事件被设置
ret = StorPortWaitForSingleObject(
(bht_dev_ext_t*)pdx,
mgr->pevt_array[EVENT_TASK_OCCUR], // 等待任务事件
FALSE, // 不可警报
NULL // 无超时
);

if(ret == STATUS_SUCCESS)
return EVENT_TASK_OCCUR;

return EVENT_NONE;
}

7.3 跨线程通信

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
┌─────────────────────────────────────────────────────────────────────┐
│ 跨线程通信机制 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ [HwStartIO 上下文] [工作线程上下文] │
│ │ │ │
│ │ │ os_wait_event() │
│ │ │ ◄── 阻塞等待 ── │
│ │ │ │
│ │ tag_build_io() │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ os_set_event() │ │
│ │ │ │ │
│ │ │ 唤醒 │ │
│ │ ├────────────────────►│ │
│ │ │ │ │
│ │ │ │ thread_handle_task() │
│ │ │ │ │ │
│ │ │ │ ▼ │
│ │ │ │ 处理工作项 │
│ │ │ │ │ │
│ │ │ │ ▼ │
│ │ │ │ 返回等待状态 │
│ │ │ │
│ ▼ ▼ │
│ │
│ 同步点: │
│ - Tag Queue 锁保护共享数据 │
│ - 事件对象协调线程唤醒 │
│ - DPC 串行化中断处理 │
│ │
└─────────────────────────────────────────────────────────────────────┘

8. 卡初始化线程

8.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
// main/thread.c
void card_init_thread(void *param)
{
bht_dev_ext_t *pdx = (bht_dev_ext_t *)param;
card_init_result_t result;

DbgInfo(MODULE_OS_ENTRY, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"card_init_thread start\n");

while(!os_thread_should_terminate(pdx))
{
// 等待初始化请求
os_wait_for_event(&pdx->os.evt_card_init);

// 检查设备就绪
if(IS_DEVICE_REMOVED(pdx))
{
DbgInfo(..., "card removed, skip init\n");
continue;
}

// 执行卡初始化
result = card_init_full(&pdx->card, 3); // 重试 3 次

if(result == CARD_INIT_SUCCESS)
{
DbgInfo(..., "card init success\n");
// 通知上层卡就绪
StorPortNotification(BusChangeDetected, pdx);
}
else
{
DbgErr("card init failed: %d\n", result);
}
}
}

8.2 卡初始化状态机

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
┌─────────────────────────────────────────────────────────────────────┐
│ 卡初始化状态机 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ │ NO_CARD │ ←─── 卡物理移除 │
│ │ (无卡) │ │
│ └──────────────┘ │
│ │ │
│ │ card_inserted() │
│ ▼ │
│ ┌──────────────┐ │
│ │ INIT_START │ ←─── 收到卡插入中断 │
│ │ (开始初始化) │ │
│ └──────────────┘ │
│ │ │
│ │ card_identify() │
│ ▼ │
│ ┌──────────────┐ │
│ │ IDENTIFY │ ←─── 识别卡类型 │
│ │ (识别中) │ (SD/MMC/UHS2) │
│ └──────────────┘ │
│ │ │
│ │ card_init_csd() │
│ ▼ │
│ ┌──────────────┐ │
│ │ INIT_CSD │ ←─── 读取 CSD 寄存器 │
│ │ (读取参数) │ │
│ └──────────────┘ │
│ │ │
│ │ card_switch() │
│ ▼ │
│ ┌──────────────┐ │
│ │ SWITCH │ ←─── 切换到高速模式 │
│ │ (模式切换) │ (UHS-I / HS200 / HS400) │
│ └──────────────┘ │
│ │ │
│ │ card_ready() │
│ ▼ │
│ ┌──────────────┐ │
│ │ READY ★ │ ←─── 卡就绪,可接受读写 │
│ │ (就绪) │ │
│ └──────────────┘ │
│ │
│ 错误路径: │
│ INIT_START ──timeout──► ERROR ──card_remove──► NO_CARD │
│ │
└─────────────────────────────────────────────────────────────────────┘

9. 电源状态与请求处理

9.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
// main/pmfunc.c
e_req_result req_check_power_state(
bht_dev_ext_t *pdx,
srb_ext_t *srb_ext
)
{
// 检查当前电源状态
switch(pdx->pm_state.current_state)
{
case PM_STATE_D0:
// 完全工作状态 → 正常处理
return REQ_SUCCESS;

case PM_STATE_RTD3:
// Runtime D3 → 检查唤醒条件
if(IS_WAKE_REQUEST(srb_ext))
return REQ_SUCCESS;
else
return REQ_PENDING;

case PM_STATE_D3:
// D3 状态 → 请求必须等待
return REQ_PENDING;

default:
return REQ_ERROR;
}
}

9.2 D3 进入流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// main/pmfunc.c
void req_enter_d3(bht_dev_ext_t *pdx)
{
DbgInfo(MODULE_OS_ENTRY, FEATURE_PM_TRACE, NOT_TO_RAM,
"req_enter_d3 enter\n");

// 1. 标记进入 D3
pdx->pm_state.current_state = PM_STATE_D3;
pdx->pm_state.d3_entered = TRUE;

// 2. 取消所有待处理的请求
req_cancel_all_io(pdx);

// 3. 停止卡时钟
host_set_clock(&pdx->host, 0);

// 4. 关闭卡电源
card_power_off(&pdx->card, TRUE);

DbgInfo(MODULE_OS_ENTRY, FEATURE_PM_TRACE, NOT_TO_RAM,
"req_enter_d3 exit\n");
}

10. 总结

10.1 请求处理关键路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SRB 到达 → scsi_execute() → req_tag_io_add()


tag_alloc() (分配 Tag)


tag_build_io() (构建 DMA)


tag_start_io() (启动传输)

┌─────────────────┴─────────────────┐
│ │
同步完成 异步完成
│ │
▼ ▼
StorPortNotification() 中断触发
(RequestComplete) │
│ ▼
│ DPC: trans_done_dpc()
│ │
▼ ▼
SRB 完成 tag_complete()

10.2 设计要点

要点 实现
Tag 管理 静态数组 + 空闲链表
异步处理 DPC + 事件同步
错误处理 错误恢复流程 + SRB Sense Data
电源管理 状态检查 + 请求拦截
并发控制 自旋锁 + 原子操作

文档生成日期: 2026-03-21
驱动版本: BHTSDDR