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
目標平台 Universal
最小 KMDF 版本 1.11
標頭 wdfdmatransaction.h (包含 Wdf.h)
程式庫 Wdf01000.sys (請參閱 Framework Library Versioning.)
IRQL <=DISPATCH_LEVEL
DDI 合規性規則 DriverCreate (kmdf)

另請參閱

WdfDmaTransactionCancel

WdfDmaTransactionCreate