ControllerControl 例程要求

顾名思义, ControllerControl 例程与控制器对象相关联。 执行 ControllerControl 例程时,控制器对象表示的硬件是免费的,控制器扩展通常不会由另一个驱动程序例程访问,除非控制器扩展包含与驱动程序的 ISR 共享的上下文。

通常, ControllerControl 例程至少执行以下作:

  1. 更新或初始化驱动程序在目标设备对象的设备扩展和控制器扩展中维护的任何上下文

    如果驱动程序使用 DMA,则其 ControllerControl 例程通常负责确定给定传输请求是否必须拆分为部分传输,因为每个 DMA 传输的大小存在任何系统施加的限制或设备施加的限制。 在这些情况下,如果驱动程序具有 AdapterControl 例程,ControllerControl 例程还负责调用 AllocateAdapterChannel

    如果驱动程序使用PIO,并且硬件需要的话,其ControllerControl例程还负责将传输请求拆分为部分传输范围,并用Irp->MdlAddress上的MDL调用MmGetSystemAddressForMdlSafe

  2. 为请求的I/O操作编程其硬件

    如果可以从 ISR 访问设备或控制器扩展,则 ControllerControl 例程必须通过调用 KeSynchronizeExecution 来调用 SynchCritSection 例程。 有关详细信息,请参阅 使用关键节

如果驱动程序具有 Cancel 例程,则其 ControllerControl 例程还必须检查 Irp-Cancel> 字段,以确定是否应取消当前 IRP,并执行下列作之一:

如果 Irp-Cancel> 设置为 TRUEControllerControl 例程必须执行以下操作:

  1. 状态 设置 STATUS_CANCELLED, 为 信息 设置 0,在 IRP 的 I/O 状态块中。

  2. 调用 IoFreeController 释放控制器对象,以便可以立即启动下一个设备作。

  3. 如果驱动程序管理自己的队列,请调用 IoStartNextPacket 或出队下一个 IRP。

  4. 使用 IoCompleteRequest 完成取消的 IRP 并返回控件。

如果未将 Irp-Cancel> 设置为 TRUE,ControllerControl 例程必须执行以下作:

  1. 调用 IoSetCancelRoutine 将 IRP 的 Cancel 例程入口点重置为 NULL。 如果驱动程序在设备对象中使用 I/O 管理器提供的设备队列,则获取此调用的取消旋转锁。

  2. 使用通过调用 KeSynchronizeExecutionSynchCritSection 例程为请求的 I/O 操作编程硬件。 有关详细信息,请参阅 “使用临界区”

有关处理可取消 IRP 的详细信息,请参阅 “取消 IRP”。

对于大多数中断驱动的 I/O操作,除了在附加到物理控制器/适配器的不同设备上的重叠操作外,ControllerControl 例程应返回 KeepObject,因为 DpcForIsrCustomDpc 例程完成操作和 IRP。

一旦 I/O作满足当前请求,完成 IRP 的例程应调用 IoFreeControllerIoStartNextPacket ,以便尽快处理下一个请求。

如果ControllerControl例程本身完成了IRP,或者如果它可以为一个目标设备对象(例如磁盘)设置操作(如磁盘查找),而该操作可能与另一个设备对象的操作重叠,那么ControllerControl例程应返回DeallocateObject