Fungsi WdfDmaTransactionStopSystemTransfer (wdfdmatransaction.h)
[Hanya berlaku untuk KMDF]
Metode WdfDmaTransactionStopSystemTransfer mencoba menghentikan transfer DMA mode sistem setelah kerangka kerja disebut EvtProgramDma.
Sintaks
void WdfDmaTransactionStopSystemTransfer(
[in] WDFDMATRANSACTION DmaTransaction
);
Parameter
[in] DmaTransaction
Handel ke objek transaksi DMA yang diinisialisasi.
Nilai kembali
Tidak ada
Keterangan
Hanya driver yang menggunakan DMA mode sistem yang harus memanggil WdfDmaTransactionStopSystemTransfer.
Pengemudi yang menggunakan DMA yang menguasai bus bertanggung jawab untuk memprogram pengontrol DMA khususnya sendiri. Jika terjadi pembatalan permintaan, waktu habis, atau kesalahan perangkat, driver dapat memprogram pengontrol DMA untuk berhenti mentransfer data.
Sebaliknya, driver yang menggunakan DMA mode sistem harus mengandalkan lapisan abstraksi perangkat keras (HAL) untuk memprogram pengontrol DMA bersama. Ketika driver memanggil WdfDmaTransactionStopSystemTransfer, kerangka kerja memberi tahu HAL bahwa transfer harus segera dihentikan dan dikembalikan.
Kerangka kerja berikutnya memanggil fungsi panggilan balik EvtDmaTransactionDmaTransferComplete driver, jika driver telah menyediakannya. Jika tidak, kerangka kerja mengembalikan FALSE saat driver berikutnya memanggil WdfDmaTransactionDmaCompleted.
Jika driver Anda memanggil metode ini pada sistem operasi yang lebih awal dari Windows 8, pemverifikasi kerangka kerja melaporkan kesalahan.
Untuk informasi selengkapnya tentang DMA mode sistem, lihat Mendukung System-Mode DMA.
Untuk informasi selengkapnya tentang membatalkan transaksi DMA, lihat Membatalkan Transaksi DMA.
Contoh
Contoh kode berikut menunjukkan bagaimana driver mungkin memanggil WdfDmaTransactionStopSystemTransfer dari fungsi panggilan balik peristiwa EvtTimerFunc yang terdaftar untuk dipanggil jika waktu permintaan I/O habis.
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);
}
}
Contoh kode berikut menunjukkan bagaimana driver mungkin memanggil WdfDmaTransactionStopSystemTransfer dari fungsi panggilan balik EvtRequestCancel . Driver yang sebelumnya disebut WdfRequestMarkCancelableEx dari handler permintaan I/O-nya untuk mendaftarkan panggilan balik.
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);
}
Persyaratan
Persyaratan | Nilai |
---|---|
Klien minimum yang didukung | Windows 8 |
Target Platform | Universal |
Versi KMDF minimum | 1.11 |
Header | wdfdmatransaction.h (termasuk Wdf.h) |
Pustaka | Wdf01000.sys (lihat Penerapan Versi Pustaka Kerangka Kerja.) |
IRQL | <=DISPATCH_LEVEL |
Aturan kepatuhan DDI | DriverCreate(kmdf) |
Lihat juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk