ControllerControl 例程要求
顾名思义, ControllerControl 例程与控制器对象相关联。 执行 ControllerControl 例程时,控制器对象表示的硬件是免费的,并且控制器扩展通常不会由另一个驱动程序例程访问,除非控制器扩展包含与驱动程序的 ISR 共享的上下文。
通常, ControllerControl 例程至少执行以下操作:
汇报或初始化驱动程序在目标设备对象的设备扩展和控制器扩展中维护的任何上下文
如果驱动程序使用 DMA,则其 ControllerControl 例程通常负责确定给定传输请求是否必须拆分为部分传输,因为系统对每个 DMA 传输的大小施加或设备施加的任何限制。 在这些情况下,如果驱动程序具有 AdapterControl 例程,ControllerControl 例程还负责调用 AllocateAdapterChannel。
如果驱动程序使用 PIO,则其 ControllerControl 例程还负责将传输请求拆分为部分传输范围,并在 Irp-MdlAddress> 中使用 MDL 调用 MmGetSystemAddressForMdlSafe。
针对请求的 I/O 操作对硬件进行程序
如果可以从 ISR 访问设备或控制器扩展,则 ControllerControl 例程必须使用通过调用 KeSynchronizeExecution 调用的 SynchCritSection 例程。 有关详细信息,请参阅 使用关键部分。
如果驱动程序具有 Cancel 例程,则其 ControllerControl 例程还必须检查 Irp-Cancel> 字段来确定是否应取消当前 IRP,并执行以下操作之一:
如果 Irp-Cancel> 设置为 TRUE,则 ControllerControl 例程必须执行以下操作:
在 IRP 的 I/O 状态块中为 “状态 ”设置“STATUS_CANCELLED”,为 “信息 ”设置零。
调用 IoFreeController 释放控制器对象,以便可以立即启动下一个设备操作。
如果驱动程序管理自己的队列,请调用 IoStartNextPacket 或取消下一个 IRP 排队。
使用 IoCompleteRequest 完成已取消的 IRP 并返回控件。
如果未将 Irp-Cancel> 设置为 TRUE,则 ControllerControl 例程必须执行以下操作:
调用 IoSetCancelRoutine 将 IRP 的 Cancel 例程入口点重置为 NULL。 如果驱动程序在设备对象中使用 I/O 管理器提供的设备队列,请获取此调用的取消旋转锁。
使用通过调用 KeSynchronizeExecution 调用的 SynchCritSection 例程为请求的 I/O 操作编写硬件。 有关详细信息,请参阅 使用关键部分
有关处理可取消 IRP 的详细信息,请参阅 取消 IRP。
对于大多数中断驱动的 I/O 操作,除了附加到物理控制器/适配器的不同设备上的重叠操作外, ControllerControl 例程应返回 KeepObject, 因为 DpcForIsr 或 CustomDpc 例程完成操作和 IRP。
完成 I/O 操作 () 以满足当前请求后,将完成 IRP 的例程应调用 IoFreeController 和 IoStartNextPacket ,以便可以尽快处理下一个请求。
如果 ControllerControl 例程本身完成了一个 IRP,或者如果它可以为一个目标设备对象设置一个操作(如磁盘查找), (磁盘) 可能会与另一个设备对象的操作重叠, 则 ControllerControl 例程应返回 DeallocateObject。