WdfDmaTransactionStopSystemTransfer 函数 (wdfdmatransaction.h)

[仅适用于 KMDF]

WdfDmaTransactionStopSystemTransfer 方法尝试在框架调用 EvtProgramDma 后停止系统模式 DMA 传输。

语法

void WdfDmaTransactionStopSystemTransfer(
  [in] WDFDMATRANSACTION DmaTransaction
);

参数

[in] DmaTransaction

初始化的 DMA 事务对象的句柄。

返回值

备注

只有使用系统模式 DMA 的驱动程序应调用 WdfDmaTransactionStopSystemTransfer

使用总线主控 DMA 的驱动程序负责对自己的专用 DMA 控制器进行编程。 如果出现请求取消、超时或设备错误,驱动程序可以对 DMA 控制器进行编程以停止传输数据。

相比之下,使用系统模式 DMA 的驱动程序必须依赖于硬件抽象层 (HAL) 来对共享 DMA 控制器进行编程。 当驱动程序调用 WdfDmaTransactionStopSystemTransfer 时,框架会通知 HAL 传输必须停止并立即返回。

框架接下来调用驱动程序的 EvtDmaTransactionDmaTransferComplete 回调函数(如果驱动程序已提供)。 否则,当驱动程序下一次调用 WdfDmaTransactionDmaCompleted 时,框架将返回 FALSE。

如果驱动程序在早于 Windows 8 的操作系统上调用此方法,框架的验证程序将报告错误。

有关系统模式 DMA 的详细信息,请参阅 支持 System-Mode DMA

有关取消 DMA 事务的详细信息,请参阅 取消 DMA 事务

示例

下面的代码示例演示驱动程序如何从 EvtTimerFunc 事件回调函数调用 WdfDmaTransactionStopSystemTransfer,该回调函数在 I/O 请求超时时要调用该函数。

VOID
MyTimerFunc(
    __in WDFTIMER Timer
    )
{
    WDFREQUEST request = (WDFREQUEST) WdfTimerGetParentObject(Timer);
    PREQUEST_CONTEXT requestContext = GetRequestContext(request);

    //
    // Begin the completion process.  If we're the first to get here 
    // then stop the DMA transfer.  The dma completion routine will
    // take care of running down cancellation.
    //
    if (BeginCompletion(requestContext, STATUS_IO_TIMEOUT, false)) {
        WdfDmaTransactionStopSystemTransfer(requestContext->DmaTransaction);
    }
    
    AttemptRequestCompletion(requestContext, false);
}

bool
BeginCompletion(
    __in PREQUEST_CONTEXT  RequestContext,
    __in NTSTATUS          CompletionStatus,
    __in bool              ForceStatusUpdate
    )
{
    bool completionStarted;

    //
    // Grab the object lock and mark the beginning of 
    // completion.
    //
    WdfSpinLockAcquire(RequestContext->Lock);

    completionStarted = RequestContext->CompletionStarted;
    RequestContext->CompletionStarted = true;

    if ((completionStarted == false) || 
        (ForceStatusUpdate == true)) {
        RequestContext->CompletionStatus = CompletionStatus;
    }

    WdfSpinLockRelease(RequestContext->Lock);

    return !completionStarted;
}

VOID
AttemptRequestCompletion(
    __in PREQUEST_CONTEXT RequestContext,
    __in bool TransferComplete
    )
{
    LONG refCount;

    NT_ASSERTMSG("No thread has begun completion", 
                 RequestContext->CompletionStarted == true);

    if (TransferComplete) {
        //
        // Unmark the request cancelable.  If that succeeds then drop the cancel reference
        //
        if (WdfRequestUnmarkCancelable(RequestContext->Request) == STATUS_SUCCESS) {
            refCount = InterlockedDecrement(&(RequestContext->CompletionRefCount));
            NT_ASSERTMSGW(L"Reference count should not have gone to zero yet",
                          refCount != 0);
        }
                
        //
        // Stop the timer if it's been started.
        //
        if (RequestContext->TimerStarted == true) {
            if (WdfTimerStop(RequestContext->Timer, FALSE) == TRUE) {
                //
                // The timer was queued but won't ever run.  Drop its 
                // reference count.
                //
                refCount = InterlockedDecrement(&RequestContext->CompletionRefCount);
                NT_ASSERTMSG("Completion reference count should not reach zero until "
                             L"this routine calls AttemptRequestCompletion",
                             refCount > 0);
            }
        }
    }

    //
    // Drop this caller's reference.  If that was the last one then 
    // complete the request.
    //
    refCount = InterlockedDecrement(&(RequestContext->CompletionRefCount));

    if (refCount == 0) {
        NT_ASSERTMSGW(L"Execution reference was released, but execution "
                      L"path did not set a completion status for the "
                      L"request",
                      RequestContext->CompletionStatus != STATUS_PENDING);
        
        
        //
        // Timers are disposed of at passive level.  If we leave it attached to 
        // the request then we can hit a verifier issue, since the request 
        // needs to be immediately disposable at dispatch-level.
        //
        // Delete the timer now so that we can complete the request safely.
        // At this point the timer has either expired or been successfully 
        // cancelled so there's no race with the timer routine.
        //
        if (RequestContext->Timer != NULL) {
            WdfObjectDelete(RequestContext->Timer);
            RequestContext->Timer = NULL;
        }

        WdfRequestComplete(RequestContext->Request, 
                           RequestContext->CompletionStatus);
    }
}

下面的代码示例演示驱动程序如何从 EvtRequestCancel 回调函数调用 WdfDmaTransactionStopSystemTransfer。 驱动程序以前从其 I/O 请求处理程序调用 WdfRequestMarkCancelableEx 来注册回调。

VOID
MyRequestCancel(
    __in WDFREQUEST Request
    )
{
    PREQUEST_CONTEXT requestContext = GetRequestContext(Request);
    LONG oldValue;

    //
    // Start completion
    //

    if (BeginCompletion(requestContext, STATUS_CANCELLED, false)) {
        
        //
        // Cancel the DMA transaction.
        //
        if (WdfDmaTransactionCancel(requestContext->DmaTransaction) == TRUE) {
            //
            // The transaction was stopped before EvtProgramDma could be 
            // called.  Drop the I/O reference.
            // 
            oldValue = InterlockedDecrement(&requestContext->CompletionRefCount);
            NT_ASSERTMSG("Completion reference count should not reach zero until "
                         L"this routine calls AttemptRequestCompletion",
                         oldValue > 0);
            NT_ASSERTMSG("Completion status should be cancelled", 
                         requestContext->CompletionStatus == STATUS_CANCELLED);
        }
        else {
            //
            // The transaction couldn't be stopped before EvtProgramDma.
            // Stop any running system DMA transfer.
            //
            WdfDmaTransactionStopSystemTransfer(requestContext->DmaTransaction);
        }
    }

    AttemptRequestCompletion(requestContext, false);
}

要求

要求
最低受支持的客户端 Windows 8
目标平台 通用
最低 KMDF 版本 1.11
标头 wdfdmatransaction.h (包括 Wdf.h)
Library Wdf01000.sys (请参阅框架库版本控制.)
IRQL <=DISPATCH_LEVEL
DDI 符合性规则 DriverCreate (kmdf)

另请参阅

WdfDmaTransactionCancel

WdfDmaTransactionCreate