存储类驱动程序的 BuildRequest 例程

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

  • MajorFunction 包含IRP_MJ_SCSI

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

每个类驱动程序负责为 SRB 分配内存,并为基础存储端口驱动程序使用 CDB 进行设置。 类驱动程序可以使用 ExInitializeNPageLookasideList 为其 SRB 设置查找列表,也可以调用 ExAllocatePool 以获取非分页内存。 有关 使用查看列表 和非分页池的详细信息,请参阅使用 Lookaside 列表。

无论是从池中分配内存还是从驱动程序创建的查看列表中分配内存,每个存储类驱动程序都负责释放它为 SRB 分配的内存。 存储类驱动程序的 IoCompletion 例程( 如存储类驱动程序的 IoCompletion 例程中所述)通常会将分配给 SRB 的内存释放回查看列表。

类驱动程序的 BuildRequest 例程必须在 SRB 成员中设置适当的值,包括它为与其设备通信而设置的 CDB 的长度。 对于返回请求感知信息和/或驱动程序可能需要重试的请求,它会在 IRP 中设置 IoCompletion 例程。 对于读取或写入请求,它分别使用适当的传输方向(SRB_FLAGS_DATA_IN或SRB_FLAGS_DATA_OUT)来设置 SrbFlag

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 例程