[仅适用于 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) |
图书馆 | Wdf01000.sys(请参阅框架库版本控制。 |
IRQL | <=DISPATCH_LEVEL |
DDI 符合性规则 | DriverCreate(kmdf) |