存储类驱动程序的 BuildRequest 例程

与所有更高级别的内核模式驱动程序一样,存储类驱动程序在 处理对存储外围设备的请求时,必须为下一个较低的驱动程序设置 IRP 的 I/O 堆栈位置。 在类驱动程序为系统提供的端口驱动程序设置包含 SRBs 的 IRP 中,端口驱动程序的 I/O 堆栈位置设置如下:

  • MajorFunction 包含IRP_MJ_SCSI

  • Parameters.Scsi.Srb 包含指向 SRB 的指针

每个类驱动程序都负责为 SRB 分配内存,并配置 CDB 以用于底层存储端口驱动程序。 类驱动程序可以使用 ExInitializeNPageLookasideList 为其 SRB 设置旁视列表,或者为非分页内存调用 ExAllocatePool。 有关使用 Lookaside 列表和非分页池的详细信息,请参阅“使用 Lookaside 列表”。

无论是从池中分配内存还是从驱动程序创建的旁视列表分配内存,每个存储类驱动程序都负责释放为 SRB 分配的内存。 存储类驱动程序的 IoCompletion 例程,在 存储类驱动程序的 IoCompletion 例程 中描述,通常会将分配给 SRBs 的内存释放回旁视列表。

类驱动程序的 BuildRequest 例程必须在 SRB 成员中设置适当的值,包括它设置为与其设备通信的 CDB 的长度。 对于返回请求感知信息和/或驱动程序可能需要重试的请求,它会在 IRP 中设置 IoCompletion 例程。 对于读取或写入请求,它将SrbFlags与相应的传输方向标志(SRB_FLAGS_DATA_IN 或 SRB_FLAGS_DATA_OUT)进行逻辑或运算。

BuildRequest 例程可能与 SendSrbSynchronousSendSrbAsynchronous 例程共同承担设置 SRB 的责任。 也就是说, BuildRequest 例程可以设置通常为所有请求设置的 SRB 成员,而 SendSrbXxx 例程则每个设置的 SRB 值仅与每种类型的请求相关。 从 SendSrbAsynchronous 例程将 IRP 向下传递到端口驱动程序时,必须使用驱动程序提供的 IoCompletion 例程设置 IRP。

加载类驱动程序后,它会设置大多数 SRB,并将 Function 成员设置为SRB_FUNCTION_EXECUTE_SCSI,以指示通过总线发送设备 I/O 请求。

有关系统定义的 SRB 成员及其值的详细信息,请参阅 SCSI_REQUEST_BLOCK

设置请求感知的 SRB

当目标控制器返回检查条件时,类驱动程序可以请求端口驱动程序返回 SCSI 请求感知或等效信息。 为此,类驱动程序在 SRB 中设置 SenseInfoBuffer 指针和 SenseInfoBufferLength ,以便端口驱动程序可以在检查条件发生时返回请求感知信息。 端口驱动程序通过在返回 IRP 时使用 SRB_STATUS_AUTOSENSE_VALID 设置 SrbStatus 成员,来指示它返回了请求感知信息。 有关 InterpretSenseInfo 例程的详细信息,请参阅 存储类驱动程序的 InterpretRequestSense 例程

重试

存储类驱动程序负责重试由于目标/控制器错误、总线重置或请求超时而失败的请求。 因此,许多类驱动程序在 IRP 的自己的 I/O 堆栈位置维护重试计数。 此类驱动程序的 BuildRequest 例程也可能在设置 IoCompletion 例程并将 IRP 发送到端口驱动程序之前初始化给定请求的重试限制。 有关 RetryRequest 例程的详细信息,请参阅 存储类驱动程序的 RetryRequest 例程