Request的取消

什么时候需要取消?

如果驱动调用者(caller)向驱动程序发送Request,需要从硬件读取数据,而读取完成不是一个同步操作时,那么该Request必须是可以被取消的。比如数据传输完成以中断方式通知时。

取消流程

  1. Request Handlers调用WdfRequestMarkCancelableor WdfRequestMarkCancelableEx注册一个取消例程,该例程将在IRQL: <=DISPATCH_LEVEL被Framework调用。另外在Device Context里保存Request
  2. 当caller取消该Request时,就会调用取消例程,在取消历程内部调用WdfRequestComplete,一般以STATUS_CANCELLED方式完成Request 。另外把Device Context里的Request设置为NULL
  3. 当取消例程得到调用时,IRQL: <=DISPATCH_LEVEL。也就是说ISR和DPC可以打断取消例程。
    • 如果取消例程完成了Request,并且DeviceContext->InProcessRequest=NULL都已执行,DPC只要判断DeviceContext->InProcessRequest是否为NULL,如果是NULL就不用完成Request。
    • 如果取消例程完成了Request,并且DeviceContext->InProcessRequest=NULL没有执行,DPC将得到DeviceContext->InProcessRequest,而该Request已经被取消,DPC调用WdfRequestUnmarkCancelable将返回STATUS_CANCELLED,此时不要完成Request
    • 如果取消例程没有完成Request,DPC调用WdfRequestUnmarkCancelable将返回STATUS_CANCELLED,表示该Request将要被取消,此时也不要完成Request.
    • DPC是不能被取消例程打断的,所以取消例程只要完成就可以了
    • 取消例程必须把InProcessRequest设置为NULL,否则DPC中的WdfRequestUnmarkCancelable会发生BugCheck

 

DMA取消

如果驱动程序中包含DMA操作,那么取消工作要复杂一些

  1. 如果DMA基于CommBuffer,DPC从WdfRequestUnmarkCancelable得到STATUS_CANCELLED状态就不用拷贝数据到虚拟Buffer了
  2. 如果DMA基于Packet,必须硬件支持DMA取消(比如写寄存器,或者复位),因为DMA控制器无法知道目的地址是否还是有效的。取消DMA在取消例程中做就行了,这也就是为什么Framework提供这么一个取消例程的原因。如果不是这个原因,取消例程完全可以做到Framework里。

posted on 2010-09-20 20:52  devcfei  阅读(801)  评论(0编辑  收藏  举报