ReactOS 0.4.16-dev-1946-g52006dd
FxDmaPacketTransaction Class Reference

#include <fxdmatransaction.hpp>

Inheritance diagram for FxDmaPacketTransaction:
Collaboration diagram for FxDmaPacketTransaction:

Public Member Functions

virtual _Must_inspect_result_ NTSTATUS InitializeResources (VOID)
 
_Must_inspect_result_ NTSTATUS ReserveAdapter (__in ULONG NumberOfMapRegisters, __in WDF_DMA_DIRECTION Direction, __in PFN_WDF_RESERVE_DMA Callback, __in_opt PVOID Context)
 
VOID ReleaseAdapter (VOID)
 
virtual _Must_inspect_result_ NTSTATUS StartTransfer (VOID)
 
virtual _Must_inspect_result_ NTSTATUS TransferCompleted (VOID)
 
virtual _Must_inspect_result_ NTSTATUS StageTransfer (VOID)
 
virtual VOID ReleaseResources (__in BOOLEAN ForceRelease)
 
VOID SetDeviceAddressOffset (__in ULONG Offset)
 
- Public Member Functions inherited from FxDmaTransactionBase
 FxDmaTransactionBase (__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in USHORT ObjectSize, __in USHORT ExtraSize, __in FxDmaEnabler *DmaEnabler)
 
virtual BOOLEAN Dispose (VOID)
 
_Must_inspect_result_ NTSTATUS Initialize (__in PFN_WDF_PROGRAM_DMA ProgramDmaFunction, __in WDF_DMA_DIRECTION DmaDirection, __in PMDL Mdl, __in size_t Offset, __in ULONG Length)
 
virtual _Must_inspect_result_ NTSTATUS InitializeResources (VOID)=0
 
_Must_inspect_result_ NTSTATUS Execute (__in PVOID Context)
 
virtual _Must_inspect_result_ NTSTATUS StartTransfer (VOID)=0
 
virtual _Must_inspect_result_ NTSTATUS StageTransfer (VOID)=0
 
BOOLEAN DmaCompleted (__in size_t TransferredLength, __out NTSTATUS *ReturnStatus, __in FxDmaCompletionType CompletionType)
 
virtual _Must_inspect_result_ NTSTATUS TransferCompleted (VOID)=0
 
VOID ReleaseForReuse (__in BOOLEAN ForceRelease)
 
virtual VOID ReleaseResources (__in BOOLEAN ForceRelease)=0
 
VOID GetTransferInfo (__out_opt ULONG *MapRegisterCount, __out_opt ULONG *ScatterGatherElementCount)
 
__forceinline size_t GetBytesTransferred (VOID)
 
__forceinline FxDmaEnablerGetDmaEnabler (VOID)
 
__forceinline FxRequestGetRequest (VOID)
 
__forceinline BOOLEAN IsRequestReferenced (VOID)
 
__forceinline VOID SetRequest (__in FxRequest *Request)
 
__forceinline VOID ReferenceRequest (VOID)
 
__forceinline VOID ReleaseButRetainRequest (VOID)
 
__forceinline VOID ClearRequest (VOID)
 
__forceinline size_t GetMaximumFragmentLength (VOID)
 
__forceinline VOID SetMaximumFragmentLength (size_t MaximumFragmentLength)
 
__forceinline size_t GetCurrentFragmentLength (VOID)
 
__forceinline WDFDMATRANSACTION GetHandle (VOID)
 
PVOID GetTransferContext (VOID)
 
VOID SetImmediateExecution (__in BOOLEAN Value)
 
BOOLEAN CancelResourceAllocation (VOID)
 
FxDmaTransactionState GetTransactionState (VOID)
 
- Public Member Functions inherited from FxNonPagedObject
 FxNonPagedObject (__in WDFTYPE Type, __in USHORT Size, __in PFX_DRIVER_GLOBALS FxDriverGlobals)
 
 FxNonPagedObject (__in WDFTYPE Type, __in USHORT Size, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObjectType ObjectType)
 
virtual ~FxNonPagedObject (VOID)
 
 _Acquires_lock_ (this->m_NPLock.m_Lock) __drv_maxIRQL(DISPATCH_LEVEL) __drv_setsIRQL(DISPATCH_LEVEL) VOID Lock(__out __drv_deref(__drv_savesIRQL) PKIRQL PreviousIrql)
 
 _Releases_lock_ (this->m_NPLock.m_Lock) __drv_requiresIRQL(DISPATCH_LEVEL) __inline VOID Unlock(__in __drv_restoresIRQL KIRQL PreviousIrql)
 
 _Acquires_lock_ (this->m_NPLock.m_Lock) __drv_requiresIRQL(DISPATCH_LEVEL) VOID LockAtDispatch(VOID)
 
 _Requires_lock_held_ (this->m_NPLock.m_Lock) _Releases_lock_(this -> m_NPLock.m_Lock) __drv_requiresIRQL(DISPATCH_LEVEL) __inline VOID UnlockFromDispatch(VOID)
 
- Public Member Functions inherited from FxObject
PVOID GetCOMWrapper ()
 
void SetCOMWrapper (__drv_aliasesMem PVOID Wrapper)
 
 FxObject (__in WDFTYPE Type, __in USHORT Size, __in PFX_DRIVER_GLOBALS FxDriverGlobals)
 
virtual ~FxObject (VOID)
 
PVOID __inline operator new (__in size_t Size, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObjectType Type)
 
PVOID __inline operator new (__in size_t Size, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __in USHORT ExtraSize=0)
 
VOID operator delete (__in PVOID Memory)
 
VOID SetNoContextHeader (VOID)
 
PVOID __inline GetObjectHandle (VOID)
 
__inline FxContextHeaderGetContextHeader (VOID)
 
__inline PFX_DRIVER_GLOBALS GetDriverGlobals (VOID)
 
WDFTYPE GetType (VOID)
 
USHORT GetObjectSize (VOID)
 
LONG GetRefCnt (VOID)
 
FxTagTrackerGetTagTracker (VOID)
 
CfxDeviceGetDevice (VOID)
 
CfxDeviceBaseGetDeviceBase (VOID)
 
VOID SetDeviceBase (__in CfxDeviceBase *DeviceBase)
 
__inline VOID CallCleanup (VOID)
 
ULONG __inline AddRef (__in_opt PVOID Tag=NULL, __in LONG Line=0, __in_opt PSTR File=NULL)
 
virtual ULONG Release (__in_opt PVOID Tag=NULL, __in LONG Line=0, __in_opt PSTR File=NULL)
 
virtual ULONG AddRefOverride (__in WDFOBJECT_OFFSET Offset, __in_opt PVOID Tag=NULL, __in LONG Line=0, __in_opt PSTR File=NULL)
 
virtual ULONG ReleaseOverride (__in WDFOBJECT_OFFSET Offset, __in_opt PVOID Tag=NULL, __in LONG Line=0, __in_opt PSTR File=NULL)
 
virtual _Must_inspect_result_ NTSTATUS QueryInterface (__in FxQueryInterfaceParams *Params)
 
VOID MarkTraceState (VOID)
 
BOOLEAN __inline IsTraceState (VOID)
 
VOID __inline TraceDroppedEvent (__in FxObjectDroppedEvent Event)
 
VOID MarkPassiveDispose (__in FxObjectLockState State=ObjectLock)
 
VOID MarkPassiveCallbacks (__in FxObjectLockState State=ObjectLock)
 
VOID MarkForceDisposeThread (__in FxObjectLockState State=ObjectLock)
 
BOOLEAN IsPassiveCallbacks (__in BOOLEAN AcquireLock=TRUE)
 
BOOLEAN IsPassiveDispose (__in BOOLEAN AcquireLock=TRUE)
 
BOOLEAN IsForceDisposeThread (__in BOOLEAN AcquireLock=TRUE)
 
VOID MarkCommitted (VOID)
 
BOOLEAN IsCommitted (VOID)
 
VOID MarkDisposeOverride (__in FxObjectLockState State=ObjectLock)
 
VOID MarkNoDeleteDDI (__in FxObjectLockState State=ObjectLock)
 
BOOLEAN IsNoDeleteDDI (VOID)
 
_Must_inspect_result_ NTSTATUS Commit (__in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __out_opt WDFOBJECT *ObjectHandle, __in_opt FxObject *Parent=NULL, __in BOOLEAN AssignDriverAsDefaultParent=TRUE)
 
VOID DeleteFromFailedCreate (VOID)
 
VOID ClearEvtCallbacks (VOID)
 
BOOLEAN EarlyDispose (VOID)
 
virtual VOID DeleteObject (VOID)
 
virtual BOOLEAN Dispose (VOID)
 
_Must_inspect_result_ NTSTATUS AssignParentObject (__in FxObject *ParentObject)
 
_Must_inspect_result_ NTSTATUS AddContext (__in FxContextHeader *Header, __in PVOID *Context, __in PWDF_OBJECT_ATTRIBUTES Attributes)
 
_Must_inspect_result_ NTSTATUS RemoveParentAssignment (VOID)
 
_Must_inspect_result_ FxObjectGetParentObjectReferenced (__in PVOID Tag)
 
BOOLEAN IsDisposed (VOID)
 

Static Public Member Functions

static _Must_inspect_result_ NTSTATUS _Create (__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in FxDmaEnabler *DmaEnabler, __out WDFDMATRANSACTION *Transaction)
 
- Static Public Member Functions inherited from FxDmaTransactionBase
static VOID _ComputeNextTransferAddress (__in PMDL CurrentMdl, __in size_t CurrentOffset, __in ULONG Transferred, __deref_out PMDL *NextMdl, __out size_t *NextOffset)
 
static _Must_inspect_result_ NTSTATUS _CalculateRequiredMapRegisters (__in PMDL Mdl, __in size_t CurrentOffset, __in ULONG Length, __in ULONG AvailableMapRegisters, __out_opt PULONG PossibleTransferLength, __out PULONG MapRegistersRequired)
 
- Static Public Member Functions inherited from FxObject
static FxObject_FromDisposeEntry (__in PSINGLE_LIST_ENTRY Entry)
 
static FxObject_GetObjectFromHandle (__in WDFOBJECT Handle, __inout PWDFOBJECT_OFFSET ObjectOffset)
 
static PVOID __inline _ToHandle (__in FxObject *Object)
 
static VOID __inline _ReferenceActual (__in WDFOBJECT Object, __in_opt PVOID Tag, __in LONG Line, __in PSTR File)
 
static VOID __inline _DereferenceActual (__in WDFOBJECT Object, __in_opt PVOID Tag, __in LONG Line, __in PSTR File)
 
static PVOID _GetDebugBase (__in FxObject *Object)
 
static PFX_POOL_HEADER _CleanupPointer (__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObject *Object)
 
static _Must_inspect_result_ NTSTATUS _GetEffectiveLock (__in FxObject *Object, __in_opt IFxHasCallbacks *Callbacks, __in BOOLEAN AutomaticLocking, __in BOOLEAN PassiveCallbacks, __out FxCallbackLock **CallbackLock, __out_opt FxObject **CallbackLockObject)
 
static _Must_inspect_result_ NTSTATUS _ObjectQuery (_In_ FxObject *Object, _In_ CONST GUID *Guid, _In_ ULONG QueryBufferLength, _Out_writes_bytes_(QueryBufferLength) PVOID QueryBuffer)
 

Protected Member Functions

 FxDmaPacketTransaction (__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in USHORT ObjectSize, __in USHORT ExtraSize, __in FxDmaEnabler *DmaEnabler)
 
virtual VOID Reuse (VOID)
 
void SetMapRegisterBase (__in PVOID Value)
 
void ClearMapRegisterBase (VOID)
 
BOOLEAN IsMapRegisterBaseSet (VOID)
 
PVOID GetMapRegisterBase (VOID)
 
virtual IO_ALLOCATION_ACTION GetAdapterControlReturnValue (VOID)
 
virtual BOOLEAN PreMapTransfer (VOID)
 
 _Acquires_lock_ (this) VOID __drv_raisesIRQL(DISPATCH_LEVEL) LockTransferState(__out __drv_deref(__drv_savesIRQL) KIRQL *OldIrql)
 
 _Requires_lock_held_ (this) _Releases_lock_(this) VOID UnlockTransferState(__in __drv_restoresIRQL KIRQL OldIrql)
 
virtual PDMA_COMPLETION_ROUTINE GetTransferCompletionRoutine (VOID)
 
_Must_inspect_result_ NTSTATUS AcquireDevice (VOID)
 
FORCEINLINE VOID ReleaseDevice (VOID)
 
_Must_inspect_result_ NTSTATUS AllocateAdapterChannel (__in BOOLEAN MapRegistersReserved)
 
FORCEINLINE NTSTATUS MapTransfer (__out_bcount_opt(ScatterGatherListCb) PSCATTER_GATHER_LIST ScatterGatherList, __in ULONG ScatterGatherListCb, __in_opt PDMA_COMPLETION_ROUTINE CompletionRoutine, __in_opt PVOID CompletionContext, __out ULONG *TransferLength)
 
FORCEINLINE NTSTATUS FlushAdapterBuffers (VOID)
 
virtual VOID FreeMapRegistersAndAdapter (VOID)
 
virtual VOID CallEvtDmaCompleted (__in DMA_COMPLETION_STATUS)
 
virtual VOID Reuse (VOID)
 
- Protected Member Functions inherited from FxObject
 FxObject (__in WDFTYPE Type, __in USHORT Size, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObjectType ObjectType)
 
FxObjectDebugExtensionGetDebugExtension (VOID)
 
BOOLEAN IsDebug (VOID)
 
VOID AllocateTagTracker (__in WDFTYPE Type)
 
virtual VOID SelfDestruct (VOID)
 
PVOID __inline GetObjectHandleUnchecked (VOID)
 
VOID __inline DestroyChildren (VOID)
 
VOID DeleteEarlyDisposedObject (VOID)
 

Static Protected Member Functions

static IO_ALLOCATION_ACTION NTAPI _AdapterControl (__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PVOID MapRegisterBase, __in PVOID Context)
 
- Static Protected Member Functions inherited from FxDmaTransactionBase
static PVOID GetStartVaFromOffset (__in PMDL Mdl, __in size_t Offset)
 
- Static Protected Member Functions inherited from FxObject
static PVOID _GetBase (__in FxObject *Object)
 

Protected Attributes

ULONG m_MapRegistersNeeded
 
PVOID m_MapRegisterBase
 
BOOLEAN m_MapRegisterBaseSet
 
ULONG m_DeviceAddressOffset
 
ULONG m_MapRegistersReserved
 
struct {
   PKTHREAD   CurrentStagingThread
 
   BOOLEAN   RerunStaging
 
   BOOLEAN   RerunCompletion
 
   DMA_COMPLETION_STATUS   CompletionStatus
 
m_TransferState
 
ULONG m_IsCancelled
 
- Protected Attributes inherited from FxDmaTransactionBase
FxDmaTransactionState m_State
 
WDF_DMA_DIRECTION m_DmaDirection
 
FxDmaEnablerm_DmaEnabler
 
FxDmaDescriptionm_AdapterInfo
 
FxRequestm_EncodedRequest
 
FxDmaTransactionProgramOrReserveDma m_DmaAcquiredFunction
 
PVOID m_DmaAcquiredContext
 
PVOID m_TransferContext
 
PMDL m_StartMdl
 
PMDL m_CurrentFragmentMdl
 
size_t m_StartOffset
 
size_t m_CurrentFragmentOffset
 
size_t m_MaxFragmentLength
 
size_t m_TransactionLength
 
size_t m_Remaining
 
size_t m_Transferred
 
size_t m_CurrentFragmentLength
 
ULONG m_Flags
 
- Protected Attributes inherited from FxObject
union {
   CfxDeviceBase *   m_DeviceBase
 
   CfxDevice *   m_Device
 
}; 
 

Detailed Description

Definition at line 731 of file fxdmatransaction.hpp.

Constructor & Destructor Documentation

◆ FxDmaPacketTransaction()

FxDmaPacketTransaction::FxDmaPacketTransaction ( __in PFX_DRIVER_GLOBALS  FxDriverGlobals,
__in USHORT  ObjectSize,
__in USHORT  ExtraSize,
__in FxDmaEnabler DmaEnabler 
)
protected

Definition at line 1165 of file fxdmatransaction.cpp.

1170 :
1171 FxDmaTransactionBase(FxDriverGlobals, ObjectSize, ExtraSize, DmaEnabler)
1172{
1178
1180
1181 m_TransferState.CurrentStagingThread = NULL;
1182 m_TransferState.RerunStaging = FALSE;
1183 m_TransferState.RerunCompletion = FALSE;
1185}
struct FxDmaPacketTransaction::@4631 m_TransferState
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define UNDEFINED_DMA_COMPLETION_STATUS
_Must_inspect_result_ _In_ WDFDMAENABLER DmaEnabler

Member Function Documentation

◆ _Acquires_lock_()

FxDmaPacketTransaction::_Acquires_lock_ ( this  )
inlineprotected

Definition at line 976 of file fxdmatransaction.hpp.

979 :__WARNING_FAILING_TO_ACQUIRE_MEDIUM_CONFIDENCE, "transferring lock name to 'this->TransferStateLock'")
980#pragma prefast(suppress:__WARNING_FAILING_TO_RELEASE_MEDIUM_CONFIDENCE, "transferring lock name to 'this->TransferStateLock'")
981 LockTransferState(
983 )
984 {
985 Lock(OldIrql);
986 }
__in __drv_restoresIRQL KIRQL OldIrql
Definition: fxobject.hpp:1465
#define __out
Definition: dbghelp.h:62
#define __drv_savesIRQL
Definition: driverspecs.h:326
#define __drv_deref(annotes)
Definition: driverspecs.h:265
UCHAR KIRQL
Definition: env_spec_w32.h:591
boolean suppress
Definition: jpeglib.h:1006
#define __WARNING_FAILING_TO_RELEASE_MEDIUM_CONFIDENCE
Definition: suppress.h:509
#define __WARNING_FAILING_TO_ACQUIRE_MEDIUM_CONFIDENCE
Definition: suppress.h:510
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127

◆ _AdapterControl()

IO_ALLOCATION_ACTION FxDmaPacketTransaction::_AdapterControl ( __in PDEVICE_OBJECT  DeviceObject,
__in PIRP  Irp,
__in PVOID  MapRegisterBase,
__in PVOID  Context 
)
staticprotected

Definition at line 1661 of file fxdmatransaction.cpp.

1667{
1668 FxDmaPacketTransaction * pDmaTransaction;
1672
1675
1676 pDmaTransaction = (FxDmaPacketTransaction*) Context;
1677 ASSERT(pDmaTransaction);
1678
1679 pFxDriverGlobals = pDmaTransaction->GetDriverGlobals();
1680
1681 //
1682 // Cache the return value while we can still touch the transaction
1683 //
1684 action = pDmaTransaction->GetAdapterControlReturnValue();
1685
1686 //
1687 // Save the MapRegister base, unless it was previously set
1688 // during a reserve.
1689 //
1690 if (pDmaTransaction->IsMapRegisterBaseSet() == FALSE) {
1691 pDmaTransaction->SetMapRegisterBase(MapRegisterBase);
1692 }
1693 else {
1694 NT_ASSERTMSG("Caller was expected to use existing map register base",
1695 MapRegisterBase == pDmaTransaction->m_MapRegisterBase);
1696 }
1697
1700 "Map registers for WDFDMATRANSACTION %p allocated "
1701 "(base %p)",
1702 pDmaTransaction->GetHandle(),
1704 }
1705
1706 //
1707 // NOTE: KMDF used to call KeFlushIoBuffers() here to "ensure the
1708 // data buffers were flushed." However KeFlushIoBuffers did
1709 // nothing on x86 & amd64 (which are cache coherent WRT DMA)
1710 // and calling FlushAdapterBuffers() does any necessary
1711 // flushing anyway. Plus on non-cache-coherent architectures
1712 // (such as ARM) the flush operation has to be cache-line aligned
1713 // to avoid cache line tearing. So the flush is not necessary
1714 // and has been removed.
1715
1716 //
1717 // Check the state of the transaction. If it's reserve then call the
1718 // reserve callback and return. Otherwise stage the first fragment.
1719 //
1720 if (pDmaTransaction->m_State == FxDmaTransactionStateReserved)
1721 {
1723
1724 //
1725 // Save off and clear the callback before calling it.
1726 //
1727 callback = pDmaTransaction->m_DmaAcquiredFunction;
1728 pDmaTransaction->m_DmaAcquiredFunction.Clear();
1729
1730 ASSERTMSG("Mismatch between map register counts",
1731 (pDmaTransaction->m_MapRegistersReserved ==
1732 pDmaTransaction->m_MapRegistersNeeded));
1733
1734 //
1735 // Invoke the callback. Note that from here the driver may initialize
1736 // and execute the transaction.
1737 //
1738 callback.InvokeReserveDma(
1739 pDmaTransaction->GetHandle(),
1740 pDmaTransaction->m_DmaAcquiredContext
1741 );
1742 }
1743 else {
1744
1745 //
1746 // Stage next fragment
1747 //
1748 status = pDmaTransaction->StageTransfer();
1749
1750 if (!NT_SUCCESS(status)) {
1751
1752 DMA_COMPLETION_STATUS dmaStatus =
1755
1756 //
1757 // Map transfer failed. There will be no DMA completion callback
1758 // and no call to EvtProgramDma. And we have no way to hand this
1759 // status back directly to the driver. Fake a DMA completion with
1760 // the appropriate status.
1761 //
1762 // This should only happen for system DMA (and there most likely
1763 // only during cancelation, though we leave the possibility that
1764 // the DMA extension may fail the transfer)
1765 //
1766 ASSERTMSG("Unexpected failure of StageTransfer for packet based "
1767 "DMA",
1768 (pDmaTransaction->GetDmaEnabler()->IsBusMaster() == false));
1769
1772 "Invoking DmaCompleted callback %p (context %p) "
1773 "for WDFDMATRANSACTION %p (status %x) "
1774 "due to staging failure (%!STATUS!)",
1777 pDmaTransaction->GetHandle(),
1778 dmaStatus,
1779 status);
1780 }
1781
1782 pDmaTransaction->CallEvtDmaCompleted(
1784 );
1785 }
1786 }
1787
1788 //
1789 // Indicate that MapRegs are to be kept
1790 //
1791 return action;
1792}
LONG NTSTATUS
Definition: precomp.h:26
__inline BOOLEAN IsBusMaster(VOID)
void SetMapRegisterBase(__in PVOID Value)
virtual VOID CallEvtDmaCompleted(__in DMA_COMPLETION_STATUS)
BOOLEAN IsMapRegisterBaseSet(VOID)
virtual _Must_inspect_result_ NTSTATUS StageTransfer(VOID)
virtual IO_ALLOCATION_ACTION GetAdapterControlReturnValue(VOID)
FxDmaTransactionTransferComplete m_TransferCompleteFunction
FxDmaTransactionProgramOrReserveDma m_DmaAcquiredFunction
__forceinline FxDmaEnabler * GetDmaEnabler(VOID)
FxDmaTransactionState m_State
__forceinline WDFDMATRANSACTION GetHandle(VOID)
PFN_WDF_DMA_TRANSACTION_DMA_TRANSFER_COMPLETE Method
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
_In_ PIRP Irp
Definition: csq.h:116
#define TRACINGDMA
Definition: dbgtrace.h:71
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
action
Definition: namespace.c:707
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
PFX_DRIVER_GLOBALS pFxDriverGlobals
@ FxDmaTransactionStateReserved
FxDmaSystemTransaction * systemTransaction
#define ASSERT(a)
Definition: mode.c:44
static IPrintDialogCallback callback
Definition: printdlg.c:326
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
BOOLEAN FxVerifierOn
Definition: fxglobals.h:420
Definition: ps.c:97
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:213
enum _IO_ALLOCATION_ACTION IO_ALLOCATION_ACTION
DMA_COMPLETION_STATUS
Definition: iotypes.h:2301
@ DmaError
Definition: iotypes.h:2304
@ DmaCancelled
Definition: iotypes.h:2305
#define NT_ASSERTMSG
Definition: rtlfuncs.h:3328

Referenced by AllocateAdapterChannel().

◆ _Create()

_Must_inspect_result_ NTSTATUS FxDmaPacketTransaction::_Create ( __in PFX_DRIVER_GLOBALS  FxDriverGlobals,
__in PWDF_OBJECT_ATTRIBUTES  Attributes,
__in FxDmaEnabler DmaEnabler,
__out WDFDMATRANSACTION *  Transaction 
)
static

Definition at line 1189 of file fxdmatransaction.cpp.

1195{
1196 FxDmaPacketTransaction* pTransaction;
1197 WDFOBJECT hTransaction;
1199
1200 pTransaction = new (FxDriverGlobals, Attributes, DmaEnabler->GetTransferContextSize())
1201 FxDmaPacketTransaction(FxDriverGlobals,
1202 sizeof(FxDmaPacketTransaction),
1203 DmaEnabler->GetTransferContextSize(),
1204 DmaEnabler);
1205
1206 if (pTransaction == NULL) {
1209 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
1210 "Could not allocate memory for WDFTRANSACTION, %!STATUS!", status);
1211 return status;
1212 }
1213
1214 //
1215 // Commit and apply the attributes
1216 //
1217 status = pTransaction->Commit(Attributes, &hTransaction, DmaEnabler);
1218 if (NT_SUCCESS(status)) {
1219 *Transaction = (WDFDMATRANSACTION)hTransaction;
1220 }
1221 else {
1222 //
1223 // This will properly clean up the target's state and free it
1224 //
1225 pTransaction->DeleteFromFailedCreate();
1226 }
1227
1228 return status;
1229}
VOID DeleteFromFailedCreate(VOID)
Definition: fxobject.cpp:391
_Must_inspect_result_ NTSTATUS Commit(__in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __out_opt WDFOBJECT *ObjectHandle, __in_opt FxObject *Parent=NULL, __in BOOLEAN AssignDriverAsDefaultParent=TRUE)
Definition: fxobject.cpp:904
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes

Referenced by switch().

◆ _Requires_lock_held_()

FxDmaPacketTransaction::_Requires_lock_held_ ( this  )
inlineprotected

Definition at line 988 of file fxdmatransaction.hpp.

991 :__WARNING_FAILING_TO_RELEASE_MEDIUM_CONFIDENCE, "transferring lock name from 'this->TransferStateLock'")
992 UnlockTransferState(
994 )
995 {
996#pragma prefast(suppress:__WARNING_CALLER_FAILING_TO_HOLD, "transferring lock name from 'this->TransferStateLock'")
998 }
__drv_restoresIRQL KIRQL __in BOOLEAN Unlock
Definition: fxobject.hpp:1474
#define __in
Definition: dbghelp.h:35
#define __drv_restoresIRQL
Definition: driverspecs.h:322

◆ AcquireDevice()

_Must_inspect_result_ NTSTATUS FxDmaPacketTransaction::AcquireDevice ( VOID  )
inlineprotected

Definition at line 1021 of file fxdmatransaction.hpp.

1024 {
1025 if (m_DmaEnabler->UsesDmaV3() == FALSE)
1026 {
1028 }
1029 else
1030 {
1031 return STATUS_SUCCESS;
1032 }
1033 }
__inline _Must_inspect_result_ NTSTATUS AcquireDmaPacketTransaction(VOID)
Definition: fxdevice.hpp:354
BOOLEAN UsesDmaV3(VOID)
FxDmaEnabler * m_DmaEnabler
CfxDevice * GetDevice(VOID)
Definition: fxobject.hpp:781
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by StartTransfer().

◆ AllocateAdapterChannel()

_Must_inspect_result_ NTSTATUS FxDmaPacketTransaction::AllocateAdapterChannel ( __in BOOLEAN  MapRegistersReserved)
inlineprotected

Definition at line 1049 of file fxdmatransaction.hpp.

1052 {
1054 KIRQL irql;
1055
1057
1058 if (GetDriverGlobals()->FxVerifierOn) {
1059
1060 if (MapRegistersReserved == FALSE) {
1063 "Allocating %d map registers for "
1064 "WDFDMATRANSACTION %p",
1066 GetHandle()
1067 );
1068 }
1069 else {
1072 "Using %d reserved map registers for "
1073 "WDFDMATRANSACTION %p",
1075 GetHandle()
1076 );
1077 }
1078 }
1079
1080 if (m_DmaEnabler->UsesDmaV3()) {
1081 PDMA_OPERATIONS dmaOperations =
1083
1084 if (MapRegistersReserved == FALSE)
1085 {
1086 status = dmaOperations->AllocateAdapterChannelEx(
1091 m_Flags,
1092#pragma prefast(suppress: __WARNING_CLASS_MISMATCH_NONE, "This warning requires a wrapper class for the DRIVER_CONTROL type.")
1094 this,
1095 NULL
1096 );
1097 }
1098 else {
1099#pragma prefast(suppress:__WARNING_PASSING_FUNCTION_UNEXPECTED_NULL, "_AdapterControl does not actually use the IRP parameter.");
1101 NULL,
1103 this);
1105 }
1106 }
1107 else {
1108
1109 ASSERTMSG("Prereserved map registers are not compatible with DMA V2",
1110 MapRegistersReserved == FALSE);
1111
1116#pragma prefast(suppress: __WARNING_CLASS_MISMATCH_NONE, "This warning requires a wrapper class for the DRIVER_CONTROL type.")
1118 this);
1119 }
1120
1122
1123 if (!NT_SUCCESS(status))
1124 {
1127 "Allocating DMA resources (%d map registers) for WDFDMATRANSACTION %p "
1128 "returned %!STATUS!",
1130 GetHandle(),
1131 status
1132 );
1133 }
1134
1135 return status;
1136 }
PDEVICE_OBJECT m_FDO
static IO_ALLOCATION_ACTION NTAPI _AdapterControl(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PVOID MapRegisterBase, __in PVOID Context)
_Must_inspect_result_ NTSTATUS AllocateAdapterChannel(__in BOOLEAN MapRegistersReserved)
FxDmaDescription * m_AdapterInfo
KIRQL irql
Definition: wave.h:1
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
return pDmaTrans GetTransferContext()
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2297
PALLOCATE_ADAPTER_CHANNEL_EX AllocateAdapterChannelEx
Definition: iotypes.h:2655
PDMA_ADAPTER AdapterObject
#define __WARNING_CLASS_MISMATCH_NONE
Definition: suppress.h:563
#define GetHandle(h)
Definition: treelist.c:116

Referenced by AllocateAdapterChannel(), and StartTransfer().

◆ CallEvtDmaCompleted()

virtual VOID FxDmaPacketTransaction::CallEvtDmaCompleted ( __in DMA_COMPLETION_STATUS  )
inlineprotectedvirtual

Reimplemented in FxDmaSystemTransaction.

Definition at line 1394 of file fxdmatransaction.hpp.

1397 {
1398 //
1399 // Packet mode DMA doesn't support cancellation or
1400 // completion routines. So this should never run.
1401 //
1402 ASSERTMSG("EvtDmaCompleted is not a valid callback for "
1403 "a packet-mode transaction",
1404 FALSE);
1405 return;
1406 }

Referenced by _AdapterControl(), and StageTransfer().

◆ ClearMapRegisterBase()

void FxDmaPacketTransaction::ClearMapRegisterBase ( VOID  )
inlineprotected

Definition at line 929 of file fxdmatransaction.hpp.

932 {
933 NT_ASSERTMSG("Map register base was not set",
936 }
#define TRUE
Definition: types.h:120

Referenced by ReleaseResources().

◆ FlushAdapterBuffers()

FORCEINLINE NTSTATUS FxDmaPacketTransaction::FlushAdapterBuffers ( VOID  )
inlineprotected

Definition at line 1266 of file fxdmatransaction.hpp.

1269 {
1270 PDMA_OPERATIONS dmaOperations =
1272
1274
1275#if DBG
1276 ULONG_PTR mapRegistersRequired;
1277
1278 mapRegistersRequired = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
1282 );
1283 NT_ASSERTMSG("Mapping requires too many map registers",
1284 mapRegistersRequired <= m_MapRegistersNeeded);
1285#endif
1286
1287 if (GetDriverGlobals()->FxVerifierOn) {
1289 "Flushing DMA buffers for WDFDMATRANSACTION %p. "
1290 "MDL %p, Offset %I64x, Length %I64x",
1291 GetHandle(),
1295 }
1296
1297 if (m_DmaEnabler->UsesDmaV3()) {
1298 status = dmaOperations->FlushAdapterBuffersEx(
1305 );
1306 }
1307 else if (dmaOperations->FlushAdapterBuffers(
1316 }
1317 else {
1319 }
1320
1321 if (!NT_SUCCESS(status)) {
1323 "Flushing DMA buffers for WDFDMATRANSACTION %p ("
1324 "MDL %p, Offset %I64x, Length %I64x)"
1325 "completed with %!STATUS!",
1326 GetHandle(),
1330 status);
1331 }
1332
1333 return status;
1334 }
unsigned char BOOLEAN
static PVOID GetStartVaFromOffset(__in PMDL Mdl, __in size_t Offset)
WDF_DMA_DIRECTION m_DmaDirection
PFLUSH_ADAPTER_BUFFERS_EX FlushAdapterBuffersEx
Definition: iotypes.h:2661
PFLUSH_ADAPTER_BUFFERS FlushAdapterBuffers
Definition: iotypes.h:2640
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)

Referenced by TransferCompleted().

◆ FreeMapRegistersAndAdapter()

virtual VOID FxDmaPacketTransaction::FreeMapRegistersAndAdapter ( VOID  )
inlineprotectedvirtual

Reimplemented in FxDmaSystemTransaction.

Definition at line 1338 of file fxdmatransaction.hpp.

1341 {
1342 KIRQL irql;
1343
1344 PVOID mapRegisterBase = GetMapRegisterBase();
1345
1346 //
1347 // It's illegal to free a NULL map register base, even if the HAL gave it
1348 // to us.
1349 //
1350 if (mapRegisterBase == NULL) {
1351 if (GetDriverGlobals()->FxVerifierOn) {
1353 "Skipping free of %d map registers for WDFDMATRANSACTION %p "
1354 "because base was NULL",
1356 GetHandle());
1357 }
1358
1359 return;
1360 }
1361
1362 //
1363 // Free the map registers
1364 //
1366
1367 if (GetDriverGlobals()->FxVerifierOn) {
1369 "Freeing %d map registers for WDFDMATRANSACTION %p "
1370 "(base %p)",
1372 GetHandle(),
1373 mapRegisterBase);
1374 }
1375
1376 //
1377 // If we pre-reserved map registers then Reserved contains
1378 // the number to free. Otherwise Needed is the number allocated
1379 // for the last transaction, which is the number to free.
1380 //
1382 FreeMapRegisters(m_AdapterInfo->AdapterObject,
1383 mapRegisterBase,
1388
1389 return;
1390 }

Referenced by ReleaseResources().

◆ GetAdapterControlReturnValue()

virtual IO_ALLOCATION_ACTION FxDmaPacketTransaction::GetAdapterControlReturnValue ( VOID  )
inlineprotectedvirtual

Reimplemented in FxDmaSystemTransaction.

Definition at line 960 of file fxdmatransaction.hpp.

963 {
965 }
@ DeallocateObjectKeepRegisters
Definition: iotypes.h:204

Referenced by _AdapterControl().

◆ GetMapRegisterBase()

PVOID FxDmaPacketTransaction::GetMapRegisterBase ( VOID  )
inlineprotected

Definition at line 949 of file fxdmatransaction.hpp.

952 {
953 NT_ASSERTMSG("Map register base is not set",
955 return m_MapRegisterBase;
956 }

Referenced by AllocateAdapterChannel(), FlushAdapterBuffers(), FreeMapRegistersAndAdapter(), and MapTransfer().

◆ GetTransferCompletionRoutine()

virtual PDMA_COMPLETION_ROUTINE FxDmaPacketTransaction::GetTransferCompletionRoutine ( VOID  )
inlineprotectedvirtual

Reimplemented in FxDmaSystemTransaction.

Definition at line 1002 of file fxdmatransaction.hpp.

1005 {
1006 return NULL;
1007 }

Referenced by StageTransfer().

◆ InitializeResources()

_Must_inspect_result_ NTSTATUS FxDmaPacketTransaction::InitializeResources ( VOID  )
virtual

Implements FxDmaTransactionBase.

Definition at line 1233 of file fxdmatransaction.cpp.

1236{
1237 KIRQL oldIrql;
1239 LockTransferState(&oldIrql);
1241 UnlockTransferState(oldIrql);
1242 return STATUS_SUCCESS;
1243}

Referenced by ReserveAdapter().

◆ IsMapRegisterBaseSet()

BOOLEAN FxDmaPacketTransaction::IsMapRegisterBaseSet ( VOID  )
inlineprotected

Definition at line 940 of file fxdmatransaction.hpp.

943 {
945 }

Referenced by _AdapterControl(), and ReleaseResources().

◆ MapTransfer()

FORCEINLINE NTSTATUS FxDmaPacketTransaction::MapTransfer ( __out_bcount_opt(ScatterGatherListCb) PSCATTER_GATHER_LIST  ScatterGatherList,
__in ULONG  ScatterGatherListCb,
__in_opt PDMA_COMPLETION_ROUTINE  CompletionRoutine,
__in_opt PVOID  CompletionContext,
__out ULONG TransferLength 
)
inlineprotected

Definition at line 1140 of file fxdmatransaction.hpp.

1148 {
1149 //
1150 // Cache globals & object handle since call to MapTransferEx could
1151 // result in a DmaComplete callback before returning.
1152 //
1154 WDFDMATRANSACTION handle = GetHandle();
1155#if DBG
1156 ULONG_PTR mapRegistersRequired;
1157
1158 mapRegistersRequired = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
1162 );
1163 NT_ASSERTMSG("Mapping requires too many map registers",
1164 mapRegistersRequired <= m_MapRegistersNeeded);
1165#endif
1166
1168
1169 //
1170 // Assume we're going to transfer the entire current fragment.
1171 // MapTransfer may say otherwise.
1172 //
1173
1174 *TransferLength = (ULONG) m_CurrentFragmentLength;
1175
1176 //
1177 // Map the transfer.
1178 //
1179
1182 "Mapping transfer for WDFDMATRANSACTION %p. "
1183 "MDL %p, Offset %I64x, Length %x, MapRegisterBase %p",
1184 handle,
1187 *TransferLength,
1189 }
1190
1191 if (m_DmaEnabler->UsesDmaV3()) {
1192
1193 PDMA_OPERATIONS dmaOperations =
1195
1196 status = dmaOperations->MapTransferEx(
1202 TransferLength,
1204 ScatterGatherList,
1205 ScatterGatherListCb,
1208 );
1209
1211 "With these parameters, MapTransferEx should never fail",
1213 );
1214 }
1215 else {
1216 NT_ASSERTMSG("cannot use DMA completion routine with DMAv2",
1218
1220 "scatter gather list length must be large enough for at least one element",
1221 (ScatterGatherListCb >= (sizeof(SCATTER_GATHER_LIST) +
1222 sizeof(SCATTER_GATHER_ELEMENT)))
1223 );
1224
1225 //
1226 // This matches the assertion above. There's no way to explain to
1227 // prefast that this code path requires the caller to provide a buffer
1228 // of sufficient size to store the SGL. The only case which doesn't
1229 // provide any buffer is system-mode DMA and that uses DMA v3 and so
1230 // won't go through this path.
1231 //
1232
1233 __assume((ScatterGatherListCb >= (sizeof(SCATTER_GATHER_LIST) +
1234 sizeof(SCATTER_GATHER_ELEMENT))));
1235
1236 ScatterGatherList->NumberOfElements = 1;
1237 ScatterGatherList->Reserved = 0;
1238 ScatterGatherList->Elements[0].Address =
1245 TransferLength,
1247 ScatterGatherList->Elements[0].Length = *TransferLength;
1248
1250 }
1251
1254 "MapTransfer mapped next %d bytes of "
1255 "WDFDMATRANSACTION %p - status %!STATUS!",
1256 *TransferLength,
1257 handle,
1258 status);
1259 }
1260
1261 return status;
1262 }
FORCEINLINE NTSTATUS MapTransfer(__out_bcount_opt(ScatterGatherListCb) PSCATTER_GATHER_LIST ScatterGatherList, __in ULONG ScatterGatherListCb, __in_opt PDMA_COMPLETION_ROUTINE CompletionRoutine, __in_opt PVOID CompletionContext, __out ULONG *TransferLength)
#define __assume(x)
Definition: intrin.h:108
PMAP_TRANSFER_EX MapTransferEx
Definition: iotypes.h:2658
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE _In_opt_ __drv_aliasesMem WDFCONTEXT CompletionContext
Definition: wdfrequest.h:898
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:895
struct _SCATTER_GATHER_LIST SCATTER_GATHER_LIST
Definition: iotypes.h:2206

Referenced by MapTransfer(), and StageTransfer().

◆ PreMapTransfer()

virtual BOOLEAN FxDmaPacketTransaction::PreMapTransfer ( VOID  )
inlineprotectedvirtual

Reimplemented in FxDmaSystemTransaction.

Definition at line 969 of file fxdmatransaction.hpp.

972 {
973 return TRUE;
974 }

Referenced by StageTransfer().

◆ ReleaseAdapter()

VOID FxDmaPacketTransaction::ReleaseAdapter ( VOID  )

Definition at line 1465 of file fxdmatransaction.cpp.

1468{
1470 WDFDMATRANSACTION dmaTransaction = GetHandle();
1471
1474 "Enter WDFDMATRANSACTION %p", dmaTransaction);
1475 }
1476
1477 //
1478 // Must not be in invalid, created, transfer or deleted state
1479 //
1484
1486 "WDFDMATRANSACTION %p state %!FxDmaTransactionState! "
1487 "is invalid", dmaTransaction, m_State);
1488
1490 WDF_DMA_FATAL_ERROR, // specific type
1491 (ULONG_PTR) GetObjectHandle(), // parm 2
1492 (ULONG_PTR) m_State); // parm 3
1493 }
1494
1495 //
1496 // The caller wants to free the reserved map registers, so force their
1497 // release.
1498 //
1500
1503 "Exit WDFDMATRANSACTION %p",
1504 dmaTransaction);
1505 }
1506
1507 return;
1508}
VOID ReleaseForReuse(__in BOOLEAN ForceRelease)
return pObject GetObjectHandle()
@ FxDmaTransactionStateDeleted
@ FxDmaTransactionStateInvalid
@ FxDmaTransactionStateTransfer
@ FxDmaTransactionStateCreated
#define FxVerifierBugCheck(FxDriverGlobals, Error,...)
Definition: fxverifier.h:58
@ WDF_DMA_FATAL_ERROR
Definition: wdfbugcodes.h:65

◆ ReleaseDevice()

FORCEINLINE VOID FxDmaPacketTransaction::ReleaseDevice ( VOID  )
inlineprotected

Definition at line 1037 of file fxdmatransaction.hpp.

1040 {
1041 if (m_DmaEnabler->UsesDmaV3() == FALSE)
1042 {
1044 }
1045 }
__inline VOID ReleaseDmaPacketTransaction(VOID)
Definition: fxdevice.hpp:373

Referenced by ReleaseResources(), and StartTransfer().

◆ ReleaseResources()

VOID FxDmaPacketTransaction::ReleaseResources ( __in BOOLEAN  ForceRelease)
virtual

Implements FxDmaTransactionBase.

Definition at line 1246 of file fxdmatransaction.cpp.

1249{
1250 //
1251 // If the map register base hasn't been assigned, then just
1252 // skip this.
1253 //
1254
1255 if (IsMapRegisterBaseSet() == FALSE) {
1256 return;
1257 }
1258
1259 //
1260 // Map registers are reserved. Unless the caller is forcing
1261 // us to free them, just return. Otherwise updated the
1262 // number of map registers that FreeMapRegistersAndAdapter
1263 // is going to look at.
1264 //
1265 if ((m_MapRegistersReserved > 0) && (ForceRelease == FALSE))
1266 {
1267 return;
1268 }
1269
1270 //
1271 // Free the map registers and release the device.
1272 //
1274
1276
1277 ReleaseDevice();
1278
1281}
virtual VOID FreeMapRegistersAndAdapter(VOID)
FORCEINLINE VOID ReleaseDevice(VOID)

◆ ReserveAdapter()

_Must_inspect_result_ NTSTATUS FxDmaPacketTransaction::ReserveAdapter ( __in ULONG  NumberOfMapRegisters,
__in WDF_DMA_DIRECTION  Direction,
__in PFN_WDF_RESERVE_DMA  Callback,
__in_opt PVOID  Context 
)

Definition at line 1285 of file fxdmatransaction.cpp.

1291{
1294 WDFDMATRANSACTION dmaTransaction = GetHandle();
1295
1298 "Enter WDFDMATRANSACTION %p", dmaTransaction);
1299 }
1300
1301 //
1302 // If caller doesn't supply a map register count then we get the count
1303 // out of the transaction. So the transaction must be initialized.
1304 //
1305 // Otherwise the transaction can't be executing.
1306 //
1307 if (NumberOfMapRegisters == 0) {
1310
1312 "RequiredMapRegisters cannot be 0 because "
1313 "WDFDMATRANSACTION %p is not initialized ("
1314 "state is %!FxDmaTransactionState!) - %!STATUS!",
1315 GetHandle(),
1316 m_State,
1317 status);
1319 WDF_DMA_FATAL_ERROR, // specific type
1320 (ULONG_PTR) GetObjectHandle(), // parm 2
1321 (ULONG_PTR) m_State); // parm 3
1322 }
1323 }
1327
1329 "WDFDMATRANSACTION %p state %!FxDmaTransactionState! "
1330 "is invalid", dmaTransaction, m_State);
1331
1333 WDF_DMA_FATAL_ERROR, // specific type
1334 (ULONG_PTR) GetObjectHandle(), // parm 2
1335 (ULONG_PTR) m_State); // parm 3
1336 }
1337
1338 //
1339 // Must not already have reserved map registers
1340 //
1341 if (m_MapRegistersReserved != 0)
1342 {
1344 "WDFDMATRANSACTION %p already has allocated map registers.",
1345 dmaTransaction);
1346
1348 WDF_DMA_FATAL_ERROR, // specific type
1349 (ULONG_PTR) GetObjectHandle(), // parm 2
1350 (ULONG_PTR) m_State); // parm 3
1351 }
1352
1353 //
1354 // Get the adapter
1355 //
1358 } else {
1360 }
1361
1362 //
1363 // Save the number of map registers being reserved.
1364 //
1365 if (NumberOfMapRegisters != 0) {
1366
1367 //
1368 // Use the number the caller passed us
1369 //
1371 }
1372 else if (m_DmaEnabler->IsBusMaster() == FALSE) {
1373
1374 //
1375 // For system DMA use all the map registers we have
1376 //
1378
1379 } else {
1380
1381 //
1382 // Compute the number of map registers required based on
1383 // the MDL and length passed in
1384 //
1386 m_StartMdl,
1390 NULL,
1392 );
1393
1394 if (!NT_SUCCESS(status)) {
1396 goto End;
1397 }
1398 }
1399
1400 //
1401 // Initialize the DmaTransaction object with enough data to
1402 // trick StartTransfer into allocating the adapter channel for us.
1403 //
1405 m_StartMdl = NULL;
1406 m_StartOffset = 0;
1409 m_Remaining = 0;
1411
1412 //
1413 // Save the callback and context
1414 //
1417
1418 //
1419 // If needed, initialize the transfer context.
1420 //
1421 if (m_DmaEnabler->UsesDmaV3()) {
1424 }
1425
1427 if (NT_SUCCESS(status)) {
1428 //
1429 // Set the state to reserved so _AdapterControl knows which
1430 // callback to invoke.
1431 //
1433 } else {
1435 goto End;
1436 }
1437
1438 //
1439 // Start the adapter channel allocation through StartTransfer
1440 //
1442
1443End:
1444 if (!NT_SUCCESS(status)) {
1449
1450 if (m_EncodedRequest != NULL) {
1452 }
1453 }
1454
1457 "Exit WDFDMATRANSACTION %p, %!STATUS!",
1458 dmaTransaction, status);
1459 }
1460
1461 return status;
1462}
VOID InitializeTransferContext(__out PVOID Context, __in WDF_DMA_DIRECTION Direction)
__inline FxDmaDescription * GetWriteDmaDescription(VOID)
__inline FxDmaDescription * GetReadDmaDescription(VOID)
virtual _Must_inspect_result_ NTSTATUS StartTransfer(VOID)
virtual _Must_inspect_result_ NTSTATUS InitializeResources(VOID)
__forceinline VOID ReleaseButRetainRequest(VOID)
static _Must_inspect_result_ NTSTATUS _CalculateRequiredMapRegisters(__in PMDL Mdl, __in size_t CurrentOffset, __in ULONG Length, __in ULONG AvailableMapRegisters, __out_opt PULONG PossibleTransferLength, __out PULONG MapRegistersRequired)
union FxDmaTransactionProgramOrReserveDma::@4632 Method
@ FxDmaTransactionStateInitialized
@ FxDmaTransactionStateReleased
@ FxDmaTransactionStateTransferFailed
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ WDFDMAENABLER _In_ WDF_DMA_DIRECTION DmaDirection
@ WdfDmaDirectionReadFromDevice
Definition: wdfdmaenabler.h:65
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209

◆ Reuse()

virtual VOID FxDmaPacketTransaction::Reuse ( VOID  )
inlineprotectedvirtual

Reimplemented from FxDmaTransactionBase.

Reimplemented in FxDmaSystemTransaction.

Definition at line 905 of file fxdmatransaction.hpp.

908 {
909 return;
910 }

Referenced by FxDmaSystemTransaction::Reuse().

◆ SetDeviceAddressOffset()

VOID FxDmaPacketTransaction::SetDeviceAddressOffset ( __in ULONG  Offset)
inline

Definition at line 802 of file fxdmatransaction.hpp.

805 {
807 }
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101

◆ SetMapRegisterBase()

void FxDmaPacketTransaction::SetMapRegisterBase ( __in PVOID  Value)
inlineprotected

Definition at line 916 of file fxdmatransaction.hpp.

919 {
920 NT_ASSERTMSG("Map register base is already set",
922
925 }
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413

Referenced by _AdapterControl().

◆ StageTransfer()

_Must_inspect_result_ NTSTATUS FxDmaPacketTransaction::StageTransfer ( VOID  )
virtual

Implements FxDmaTransactionBase.

Definition at line 1796 of file fxdmatransaction.cpp.

1799{
1800 PSCATTER_GATHER_LIST sgList;
1801
1803#ifndef __REACTOS__
1804 UCHAR_MEMORY_ALIGNED sgListBuffer[sizeof(SCATTER_GATHER_LIST)
1805 + sizeof(SCATTER_GATHER_ELEMENT)];
1806#else
1807 UCHAR sgListBuffer[sizeof(SCATTER_GATHER_LIST)
1808 + sizeof(SCATTER_GATHER_ELEMENT)];
1809#endif
1810
1811 WDFDMATRANSACTION dmaTransaction;
1812
1813 KIRQL oldIrql;
1814 BOOLEAN stagingNeeded;
1815
1817
1818 //
1819 // Client driver could complete and delete the object in
1820 // EvtProgramDmaFunction. So, save the handle because we need it
1821 // for tracing after we invoke the callback.
1822 //
1824 dmaTransaction = GetHandle();
1825
1828 "Enter WDFDMATRANSACTION %p ", dmaTransaction);
1829 }
1830
1831 //
1832 // For packet base DMA, current and startMDL will always be
1833 // same. For V2 DMA we don't support MDL chains. For V3 DMA
1834 // we use the HAL's support for MDL chains and don't walk through
1835 // the MDL chain on our own.
1836 //
1838
1839 LockTransferState(&oldIrql);
1840
1841 if (m_TransferState.CurrentStagingThread != NULL) {
1842
1843 //
1844 // Staging in progress. Indicate that another staging will
1845 // be needed.
1846 //
1847 m_TransferState.RerunStaging = TRUE;
1848
1849 stagingNeeded = FALSE;
1850
1854 "Staging next fragment of WDFDMATRANSACTION %p "
1855 "deferred",
1856 dmaTransaction
1857 );
1858 }
1859 }
1860 else {
1861 //
1862 // Staging isn't in progress anyplace else. Indicate that it's
1863 // running now so that any parallel attempt is blocked.
1864 //
1865 m_TransferState.CurrentStagingThread = KeGetCurrentThread();
1866
1867 ASSERTMSG("The thread which was staging didn't clear "
1868 "RerunStaging",
1869 (m_TransferState.RerunStaging == FALSE));
1870
1871 stagingNeeded = TRUE;
1872 }
1873
1874 UnlockTransferState(oldIrql);
1875
1876 //
1877 // Take a reference on the transaction so that we can safely
1878 // manipulate the transfer state even after it's destroyed.
1879 //
1881
1882 //
1883 // Loop for as long as staging is required
1884 //
1885 while (stagingNeeded) {
1886
1887 //
1888 // Calculate length for this packet.
1889 //
1891
1892 //
1893 // Calculate address for this packet.
1894 //
1896
1897 //
1898 // Adjust the fragment length for the number of reserved map registers.
1899 //
1900 if ((m_MapRegistersReserved > 0) &&
1902 {
1903 size_t currentOffset = m_CurrentFragmentOffset;
1904 size_t currentPageOffset;
1905 PMDL mdl;
1906
1907 for (mdl = m_CurrentFragmentMdl; mdl != NULL; mdl = mdl->Next)
1908 {
1909 //
1910 // For packet/system transfers of chained MDLs, m_CurrentFragmentMdl
1911 // is never adjusted, and m_CurrentFragmentOFfset is the offset
1912 // into the entire chain.
1913 //
1914 // Locate the MDL which contains the current fragment.
1915 //
1916 ULONG mdlBytes = MmGetMdlByteCount(mdl);
1917 if (mdlBytes >= currentOffset)
1918 {
1919 //
1920 // This MDL is larger than the remaining offset, so it
1921 // contains the start address.
1922 //
1923 break;
1924 }
1925
1926 currentOffset -= mdlBytes;
1927 }
1928
1929 ASSERT(mdl != NULL);
1930
1931 //
1932 // Compute page offset from current MDL's initial page offset
1933 // and the offset into that MDL
1934 //
1935
1936 currentPageOffset = BYTE_OFFSET(MmGetMdlByteOffset(mdl) +
1937 currentOffset);
1938
1939 //
1940 // Compute the maximum number of bytes we can transfer with
1941 // the number of map registers we have reserved, taking into
1942 // account the offset of the first page.
1943 //
1944 size_t l = ((PAGE_SIZE * (m_MapRegistersReserved - 1)) +
1945 (PAGE_SIZE - currentPageOffset));
1946
1948 }
1949
1951
1954 "Initiating %s transfer for WDFDMATRANSACTION %p. "
1955 "Mdl %p, Offset %I64x, Length %I64x",
1956 m_Transferred == 0 ? "first" : "next",
1957 GetHandle(),
1961 }
1962
1963 //
1964 // Check for a pending cancellation. This can happen if the cancel
1965 // occurred between DMA completion and FlushAdapterBuffers -
1966 // FlushAdapterBuffers will clear the canceled bit in the transfer
1967 // context (TC), which would allow MapTransfer to succeed.
1968 //
1969 // An unprotected check of IsCancelled here is safe. A concurrent
1970 // cancel at this point would mark the TC cancelled such that
1971 // MapTransfer will fail.
1972 //
1973 if (m_IsCancelled == TRUE) {
1975 goto End;
1976 }
1977
1978 //
1979 // Profile specific work before mapping the transfer. if this
1980 // fails consider 'this' invalid.
1981 //
1982 if (PreMapTransfer() == FALSE) {
1984 goto End;
1985 }
1986
1987 //
1988 // Map this packet for transfer.
1989 //
1990
1991 //
1992 // For packet based DMA we use a single entry on-stack SGL. This
1993 // allows us to map multiple packet-based requests concurrently and
1994 // we know packet base DMA only requires a single SGL
1995 //
1996 // NOTE: It turns out the HAL doesn't handle chained MDLs in packet
1997 // mode correctly. It makes each MDL continguous, but returns
1998 // a list of SG elements - one for each MDL. That's scatter
1999 // gather DMA, not packet DMA.
2000 //
2001 // So it's actually very important in Win8 that we only use a
2002 // single entry SGL when calling MapTransferEx. This ensures
2003 // we only map the first MDL in the chain and thus get a
2004 // contiguous buffer
2005 //
2006 // For system DMA we use the SystemSGList stored in the DMA enabler
2007 // We can use a shared one in that case because we won't be mapping
2008 // multiple system DMA requests concurrently (HAL doesn't allow it)
2009 //
2010 FxDmaEnabler* enabler;
2011 size_t sgListSize;
2012
2013 enabler = GetDmaEnabler();
2014
2015 if (enabler->IsBusMaster()) {
2016 sgList = (PSCATTER_GATHER_LIST)sgListBuffer;
2017 sgListSize = sizeof(sgListBuffer);
2018 } else {
2019 sgList = enabler->m_SGList.SystemProfile.List;
2020 sgListSize = enabler->m_SGListSize;
2021 }
2022
2023 ULONG mappedBytes;
2024
2025 status = MapTransfer(sgList,
2026 (ULONG) sgListSize,
2028 this,
2029 &mappedBytes);
2030
2031 NT_ASSERTMSG("Unexpected failure of MapTransfer",
2032 ((NT_SUCCESS(status) == TRUE) ||
2033 (status == STATUS_CANCELLED)));
2034
2035 if (NT_SUCCESS(status)) {
2036
2037 NT_ASSERTMSG("unexpected number of mapped bytes",
2038 ((mappedBytes > 0) &&
2039 (mappedBytes <= m_CurrentFragmentLength)));
2040
2041 //
2042 // Adjust the remaining byte count if the HAL mapped less data than we
2043 // requested.
2044 //
2045 if (mappedBytes < m_CurrentFragmentLength) {
2046 m_Remaining += m_CurrentFragmentLength - mappedBytes;
2047 m_CurrentFragmentLength = mappedBytes;
2048 }
2049
2050 //
2051 // Do client PFN_WDF_PROGRAM_DMA callback.
2052 //
2054
2057 "Invoking ProgramDma callback %p (context %p) for "
2058 "WDFDMATRANSACTION %p.",
2061 GetHandle()
2062 );
2063 }
2064
2065 //
2066 // Call program DMA
2067 //
2069 GetHandle(),
2073 sgList
2074 );
2075 }
2076 }
2077
2078End:
2079 //
2080 // Process any pending completion or nested staging.
2081 //
2082 {
2083 LockTransferState(&oldIrql);
2084
2085 //
2086 // While staging we could either have deferred a call to the
2087 // completion routine or deferred another call to stage the
2088 // next fragment. We should not ever have to do both - this
2089 // would imply that the driver didn't wait for its DMA completion
2090 // routine to run when calling TransferComplete*.
2091 //
2092 ASSERTMSG("driver called TransferComplete with pending DMA "
2093 "completion callback",
2094 !((m_TransferState.RerunCompletion == TRUE) &&
2095 (m_TransferState.RerunStaging == TRUE)));
2096
2097 //
2098 // Check for pending completion. save the status away and clear it
2099 // before dropping the lock.
2100 //
2101 if (m_TransferState.RerunCompletion == TRUE) {
2102 DMA_COMPLETION_STATUS completionStatus;
2104
2105 //
2106 // Save the completion status for when we drop the lock.
2107 //
2108 completionStatus = m_TransferState.CompletionStatus;
2109
2110 ASSERTMSG("completion needed, but status was not set or was "
2111 "already cleared",
2112 completionStatus != UNDEFINED_DMA_COMPLETION_STATUS);
2113
2114 ASSERTMSG("completion needed, but mapping failed so there shouldn't "
2115 "be any parallel work going on",
2117
2118 //
2119 // Clear the completion needed state.
2120 //
2121 m_TransferState.RerunCompletion = FALSE;
2123
2124 //
2125 // Drop the lock, call the completion routine, then take the
2126 // lock again.
2127 //
2128 UnlockTransferState(oldIrql);
2131 "Invoking DmaCompleted callback %p (context %p) "
2132 "for WDFDMATRANSACTION %p (status %x) "
2133 "after deferral",
2136 GetHandle(),
2137 completionStatus);
2138 }
2139 CallEvtDmaCompleted(completionStatus);
2140 LockTransferState(&oldIrql);
2141
2142 //
2143 // Staging is blocked, which means we aren't starting up the
2144 // next transfer. Therefore we cannot have a queued completion.
2145 //
2146 ASSERTMSG("RerunCompletion should not be set on an unstaged "
2147 "transaction",
2148 m_TransferState.RerunCompletion == FALSE);
2149 }
2150
2151 //
2152 // Capture whether another staging is needed. If none is needed
2153 // then we can clear staging in progress.
2154 //
2155 if (m_TransferState.RerunStaging == TRUE) {
2156 stagingNeeded = TRUE;
2157 m_TransferState.RerunStaging = FALSE;
2158 }
2159 else {
2160 m_TransferState.CurrentStagingThread = NULL;
2161 stagingNeeded = FALSE;
2162 }
2163
2164 UnlockTransferState(oldIrql);
2165 }
2166
2167#if DBG
2168 if (!NT_SUCCESS(status)) {
2169 ASSERTMSG("MapTransfer returned an error - there should not be any "
2170 "deferred work.",
2171 (stagingNeeded == FALSE));
2172 }
2173#endif
2174
2175 } // while(stagingNeeded)
2176
2178
2181 "Exit WDFDMATRANSACTION %p, "
2182 "%!STATUS!", dmaTransaction,
2183 status);
2184 }
2185
2186 return status;
2187}
#define VOID
Definition: acefi.h:82
r l[0]
Definition: byte_order.h:168
_In_ BOOLEAN Release
Definition: cdrom.h:920
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
size_t m_SGListSize
struct FxDmaEnabler::@5118::@5120 SystemProfile
union FxDmaEnabler::@5118 m_SGList
virtual BOOLEAN PreMapTransfer(VOID)
virtual PDMA_COMPLETION_ROUTINE GetTransferCompletionRoutine(VOID)
BOOLEAN InvokeProgramDma(__in WDFDMATRANSACTION Transaction, __in WDFDEVICE Device, __in PVOID Context, __in WDF_DMA_DIRECTION Direction, __in PSCATTER_GATHER_LIST SgList)
ULONG __inline AddRef(__in_opt PVOID Tag=NULL, __in LONG Line=0, __in_opt PSTR File=NULL)
Definition: fxobject.hpp:826
CfxDeviceBase * m_DeviceBase
Definition: fxobject.hpp:328
#define PAGE_SIZE
Definition: env_spec_w32.h:49
return pDmaTrans GetDmaEnabler() -> GetDeviceHandle()
MDL * mdl
__inline size_t FxSizeTMin(__in size_t A, __in size_t B)
Definition: fxglobals.h:997
#define KeGetCurrentThread
Definition: hal.h:55
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2206
#define MmGetMdlByteOffset(_Mdl)
#define MmGetMdlByteCount(_Mdl)
#define BYTE_OFFSET(Va)
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by _AdapterControl().

◆ StartTransfer()

_Must_inspect_result_ NTSTATUS FxDmaPacketTransaction::StartTransfer ( VOID  )
virtual

Implements FxDmaTransactionBase.

Definition at line 1512 of file fxdmatransaction.cpp.

1515{
1518 WDFDMATRANSACTION dmaTransaction;
1519
1520 //
1521 // Client driver could complete and delete the object in
1522 // EvtProgramDmaFunction. So, save the handle because we need it
1523 // for tracing after we invoke the callback.
1524 //
1525 dmaTransaction = GetHandle();
1526
1529 "Enter WDFDMATRANSACTION %p",
1530 dmaTransaction);
1531
1533 "Starting WDFDMATRANSACTION %p - MDL %#p, "
1534 "offset %I64x, length %I64x",
1535 dmaTransaction,
1536 m_StartMdl,
1539 }
1540
1541 //
1542 // Reference the device when using DMA v2. For DMA v3 we can support
1543 // concurrent attempts to allocate the channel.
1544 //
1546 if (!NT_SUCCESS(status)) {
1547
1548 NT_ASSERTMSG("AcquireDevice should never fail when DMAv3 is in use",
1550
1552 "Only one transaction can be queued "
1553 "at one time on a packet based WDFDMAENABLER %p "
1554 "%!STATUS!", m_DmaEnabler->GetHandle(),
1555 status);
1557 return status;
1558 }
1559
1560 //
1561 // Calculate the initial DMA transfer length.
1562 //
1564
1566
1568 //
1569 // Caller is simply reserving the DMA adapter for later use. Ask for
1570 // as many map registers as the driver requested.
1571 //
1573
1574 ASSERT(m_MapRegistersNeeded <= m_AdapterInfo->NumberOfMapRegisters);
1575
1577
1578 }
1579 else {
1580
1581 if (m_DmaEnabler->IsBusMaster() == FALSE) {
1582
1583 //
1584 // Use as many map registers as we were granted.
1585 //
1587 } else {
1588
1589 //
1590 // If the transfer is the size of the transaction then use the offset
1591 // to determine the number of map registers needed. If it's smaller
1592 // then use the worst-case offset to make sure we ask for enough MR's
1593 // to account for a bigger offset in one of the later transfers.
1594 //
1595 // Example:
1596 // Transaction is 8 KB and is page aligned
1597 // if max transfer is >= 8KB then this will be one transfer and only
1598 // requires two map registers. Even if the driver completes a partial
1599 // transfer and we have to do the rest in a second transfer it will
1600 // fit within two map registers becuase the overall transaction does
1601 // (and a partial transfer can't take more map registers than the
1602 // whole transaction would).
1603 //
1604 // If max transfer is 2KB then this nominally requires 4 2KB transfers.
1605 // In this case however, a partial completion of one of those transfers
1606 // would leave us attempting a second 2KB transfer starting on an
1607 // unaligned address. For example, we might transfer 2KB, then 1KB
1608 // then 2KB. Even though the first transfer was page aligned, the
1609 // 3rd transfer isn't and could cross a page boundary, requiring two
1610 // map registers rather than one.
1611 //
1612 // To account for this second case, ignore the actual MDL offset and
1613 // instead compute the maximum number of map registers than an N byte
1614 // transfer could take (with worst-case alignment).
1615 //
1616 //
1622 (PVOID)(ULONG_PTR) (PAGE_SIZE -1)),
1624 );
1625
1626
1627 ASSERT(m_MapRegistersNeeded <= m_AdapterInfo->NumberOfMapRegisters);
1628 }
1629
1630 //
1631 // NOTE: the number of map registers needed for this transfer may
1632 // exceed the number that we've reserved. StageTransfer will
1633 // take care of fragmenting the transaction accordingly.
1634 //
1636 }
1637
1638 if (!NT_SUCCESS(status)) {
1640 "AllocateAdapterChannel failed for "
1641 "WDFDMATRANSACTION %p, %!STATUS!",
1642 dmaTransaction, status);
1643 ReleaseDevice();
1644 }
1645
1646 //
1647 // Before AllocateAdapterChannel returns, _AdapterControl can get called
1648 // on another thread and the driver could delete the transaction object.
1649 // So don't touch the object after this point.
1650 //
1653 "Exit WDFDMATRANSACTION %p, "
1654 "%!STATUS!", dmaTransaction, status);
1655 }
1656
1657 return status;
1658}
__inline WDFDMAENABLER GetHandle(VOID)
_Must_inspect_result_ NTSTATUS AcquireDevice(VOID)
FxVerifierDbgBreakPoint(pFxDriverGlobals)

Referenced by ReserveAdapter().

◆ TransferCompleted()

_Must_inspect_result_ NTSTATUS FxDmaPacketTransaction::TransferCompleted ( VOID  )
virtual

Implements FxDmaTransactionBase.

Definition at line 2191 of file fxdmatransaction.cpp.

2194{
2197
2198 //
2199 // Flush the buffers
2200 //
2202
2203 if (!NT_SUCCESS(status)) {
2205 "FlushAdapterBuffers on WDFDMATRANSACTION %p "
2206 "failed, %!STATUS!",
2207 GetHandle(), status);
2209 }
2210
2211 return status;
2212}
FORCEINLINE NTSTATUS FlushAdapterBuffers(VOID)

Member Data Documentation

◆ CompletionStatus

DMA_COMPLETION_STATUS FxDmaPacketTransaction::CompletionStatus

Definition at line 884 of file fxdmatransaction.hpp.

◆ CurrentStagingThread

PKTHREAD FxDmaPacketTransaction::CurrentStagingThread

Definition at line 868 of file fxdmatransaction.hpp.

◆ m_DeviceAddressOffset

ULONG FxDmaPacketTransaction::m_DeviceAddressOffset
protected

◆ m_IsCancelled

ULONG FxDmaPacketTransaction::m_IsCancelled
protected

◆ m_MapRegisterBase

PVOID FxDmaPacketTransaction::m_MapRegisterBase
protected

◆ m_MapRegisterBaseSet

BOOLEAN FxDmaPacketTransaction::m_MapRegisterBaseSet
protected

◆ m_MapRegistersNeeded

◆ m_MapRegistersReserved

ULONG FxDmaPacketTransaction::m_MapRegistersReserved
protected

◆ 

struct { ... } FxDmaPacketTransaction::m_TransferState

◆ RerunCompletion

BOOLEAN FxDmaPacketTransaction::RerunCompletion

Definition at line 883 of file fxdmatransaction.hpp.

◆ RerunStaging

BOOLEAN FxDmaPacketTransaction::RerunStaging

Definition at line 875 of file fxdmatransaction.hpp.


The documentation for this class was generated from the following files: