ReactOS 0.4.15-dev-7887-g64a59a1
fxdmatransaction.hpp
Go to the documentation of this file.
1//
2// Copyright (C) Microsoft. All rights reserved.
3//
4#ifndef _FXDMATRANSACTION_HPP_
5#define _FXDMATRANSACTION_HPP_
6
7extern "C" {
8// #include "FxDmaTransaction.hpp.tmh"
9}
10
12
13//
14// This type is used to allocate scatter-gather list of 1 element on the stack.
15//
16typedef DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) UCHAR UCHAR_MEMORY_ALIGNED;
17
18// begin_wpp enum
19
20//
21// FxDmaTransactionStateCreated when the object is created.
22// FxDmaTransactionStateInitialized when object is initialized using with
23// Mdl/VA/Length.
24// FxDmaTransactionStateReserved when driver calls AllocateResources until
25// the adapter control routine returns
26// FxDmaTransactionStateTransfer is called when the driver call Execute
27// to start the DMA transfer.
28// FxDmaTransactionStateTransferCompleted is when transfer is completed or
29// aborted
30// FxDmaTransactionStateTransferFailed is set if the framework is not able
31// to start the transfer due to error.
32// FxDmaTransactionStateReleased is set when the object is reinitailized for reuse
33// FxDmaTransactionStateDeleted is set in the Dipose due to WdfObjectDelete
34//
45};
46
47//
48// FxDmaCompletionTypeFull is used when the driver calls WdfDmaTransactionDmaComplete
49// to indicate that last framgement has been transmitted fully and to initiate
50// the transfer of next fragment.
51// FxDmaCompletionTypePartial is used when the driver completes the transfer and
52// specifies a amount of bytes it has transfered, and to initiate the next transfer
53// from the untransmitted portion of the buffer.
54// FxDmaCompletionTypeAbort i used when the driver calls DmaCompleteFinal to indicate
55// that's the final transfer and not initiate anymore transfers for the remaining
56// data.
57//
62};
63
64// end_wpp
65
66//
67// This tag is used to track whether the request pointer in the transaction
68// has a reference taken on it. Since the pointer is guaranteed to be
69// 4-byte aligned this can be set and cleared without destroying the pointer.
70//
71#define FX_STRONG_REF_TAG 0x1
72
73//
74// Simple set of macros to encode and decode tagged pointers.
75//
76#define FX_ENCODE_POINTER(T,p,tag) ((T*) ((ULONG_PTR) p | (ULONG_PTR) tag))
77#define FX_DECODE_POINTER(T,p,tag) ((T*) ((ULONG_PTR) p & ~(ULONG_PTR) tag))
78#define FX_IS_POINTER_ENCODED(p,tag) ((((ULONG_PTR) p & (ULONG_PTR) tag) == tag) ? TRUE : FALSE)
79
80//
81// An uninitialized value for Dma completion status
82//
83
84#define UNDEFINED_DMA_COMPLETION_STATUS ((DMA_COMPLETION_STATUS) -1)
85
87
88 friend class FxDmaEnabler;
89
90public:
91
93 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
94 __in USHORT ObjectSize,
95 __in USHORT ExtraSize,
97 );
98
99 static
100 VOID
103 __in size_t CurrentOffset,
104 __in ULONG Transferred,
105 __deref_out PMDL *NextMdl,
106 __out size_t *NextOffset
107 );
108
110 static
113 __in PMDL Mdl,
114 __in size_t CurrentOffset,
116 __in ULONG AvailableMapRegisters,
117 __out_opt PULONG PossibleTransferLength,
118 __out PULONG MapRegistersRequired
119 );
120
121 virtual
122 BOOLEAN
123 Dispose(
124 VOID
125 );
126
130 __in PFN_WDF_PROGRAM_DMA ProgramDmaFunction,
132 __in PMDL Mdl,
133 __in size_t Offset,
135 );
136
138 virtual
141 VOID
142 )=0;
143
146 Execute(
148 );
149
151 virtual
154 VOID
155 )=0;
156
158 virtual
161 VOID
162 )=0;
163
164 BOOLEAN
166 __in size_t TransferredLength,
167 __out NTSTATUS * ReturnStatus,
168 __in FxDmaCompletionType CompletionType
169 );
170
172 virtual
175 VOID
176 )=0;
177
178 VOID
180 __in BOOLEAN ForceRelease
181 );
182
183 virtual
184 VOID
186 __in BOOLEAN ForceRelease
187 )=0;
188
189 VOID
193 );
194
195 __forceinline
196 size_t
198 VOID
199 )
200 {
201 return m_Transferred;
202 }
203
204 __forceinline
207 VOID
208 )
209 {
210 return m_DmaEnabler;
211 }
212
213 __forceinline
214 FxRequest *
216 VOID
217 )
218 {
219 //
220 // Strip out the strong reference tag if it's set
221 //
225 }
226
227 __forceinline
228 BOOLEAN
230 VOID
231 )
232 {
234 }
235
236 __forceinline
237 VOID
240 )
241 {
243
244 //
245 // Make sure the pointer doesn't have the strong ref flag set already
246 //
248
250 }
251
252 __forceinline
253 VOID
255 VOID
256 )
257 {
259 ASSERT(IsRequestReferenced() == false);
260
261 //
262 // Take a reference on the irp to catch completion of request
263 // when there is a pending DMA transaction.
264 // While there is no need to take a reference on request itself,
265 // I'm keeping it to avoid regression as we are so close to
266 // shipping this.
267 //
269
270 //
271 // Increment reference to this Request.
272 // See complementary section in WdfDmaTransactionDelete
273 // and WdfDmaTransactionRelease.
274 //
275 m_EncodedRequest->ADDREF( this );
276
280 }
281
282 __forceinline
283 VOID
285 VOID
286 )
287 {
290
291 //
292 // Clear the referenced bit on the encoded request.
293 //
297
298 //
299 // Release this reference to the Irp and FxRequest.
300 //
302
303 m_EncodedRequest->RELEASE( this );
304 }
305
306 __forceinline
307 VOID
309 VOID
310 )
311 {
312 if (IsRequestReferenced()) {
314 }
316 }
317
318 __forceinline
319 size_t
321 VOID
322 )
323 {
324 return m_MaxFragmentLength;
325 }
326
327 __forceinline
328 VOID
330 size_t MaximumFragmentLength
331 )
332 {
333 if (MaximumFragmentLength < m_AdapterInfo->MaximumFragmentLength) {
334 m_MaxFragmentLength = MaximumFragmentLength;
335 }
336 }
337
338 __forceinline
339 size_t
341 VOID
342 )
343 {
345 }
346
347 __forceinline
348 WDFDMATRANSACTION
350 VOID
351 )
352 {
353 return (WDFDMATRANSACTION) GetObjectHandle();
354 }
355
356 PVOID
358 VOID
359 )
360 {
361 return m_TransferContext;
362 }
363
364 VOID
367 );
368
369 BOOLEAN
371 VOID
372 );
373
376 VOID
377 )
378 {
379 return m_State;
380 }
381
382protected:
383
385
387
389
390 //
391 // Depending on the direction of the transfer, this one
392 // points to either m_ReadAdapterInfo or m_WriteAdapterInfo
393 // structure of the DMA enabler.
394 //
396
397 //
398 // Request associated with this transfer. Encoding uses the
399 // FX_[EN|DE]CODE_POINTER macros with the FX_STRONG_REF_TAG
400 // to indicate whether the reference has been taken or not
401 //
403
404 //
405 // Callback and context for ProgramDma function
406 //
407 // The callback is overloaded to also hold the callback for
408 // Packet & System transfer's Reserve callback (to save space.)
409 // This is possible because the driver may not call execute
410 // and reserve in parallel on the same transaction. Disambiguate
411 // using the state of the transaction.
412 //
415
416 //
417 // The DMA transfer context (when using V3 DMA)
418 //
420
421 //
422 // This is the first MDL of the transaction.
423 //
425
426 //
427 // This is the MDL where the current transfer is being executed.
428 // If the data spans multiple MDL then this would be different
429 // from the startMDL when we stage large transfers and also
430 // if the driver performs partial transfers.
431 //
433
434 //
435 // Starting offset in the first m_StartMdl. This might be same as
436 // m_StartMdl->StartVA.
437 //
439
440 //
441 // Points to address where the next transfer will begin.
442 //
444
445 //
446 // This is maximum length of transfer that can be made. This is
447 // computed based on the available map registers and driver
448 // configuration.
449 //
451
452 //
453 // Length of the whole transaction.
454 //
456
457 //
458 // Number of bytes pending to be transfered.
459 //
461
462 //
463 // Total number of bytes transfered.
464 //
466
467 //
468 // Number of bytes transfered in the last transaction.
469 //
471
472 //
473 // DMA flags for passing to GetScatterGatherListEx &
474 // AllocateAdapterChannelEx
475 //
476
478
479 static
480 PVOID
482 __in PMDL Mdl,
483 __in size_t Offset
484 )
485 {
487 }
488
489 virtual
490 VOID
492 VOID
493 )
494 {
495 return;
496 }
497
498};
499
501
502public:
503
505 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
506 __in USHORT ExtraSize,
508 );
509
510 virtual
511 BOOLEAN
512 Dispose(
513 VOID
514 );
515
517 virtual
520 VOID
521 );
522
524 virtual
527 VOID
528 );
529
531 virtual
534 VOID
535 );
536
538 virtual
541 VOID
542 );
543
544 virtual
545 VOID
547 __in BOOLEAN ForceRelease
548 );
549
551 static
553 _Create(
554 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
557 __out WDFDMATRANSACTION* Transaction
558 );
559
560protected:
561
562 //
563 // Scatter-Gather list provided by the system.
564 //
566
567 //
568 // Preallocated memory from lookaside buffer for the
569 // scatter-gather list when running on XP and later OSes.
570 //
572
573
574private:
575
576 static
577 VOID
580 __in IRP * Irp,
583 );
584
588 __in PMDL Mdl,
589 __in size_t CurrentOffset,
593 )
594 {
596 KIRQL irql;
597
599
600 if (m_DmaEnabler->UsesDmaV3())
601 {
602 PDMA_OPERATIONS dmaOperations =
604
605 status = dmaOperations->GetScatterGatherListEx(
609 Mdl,
610 CurrentOffset,
611 Length,
612 m_Flags,
614 Context,
616 NULL,
617 NULL,
618 NULL
619 );
620 }
621 else
622 {
626 Mdl,
627 GetStartVaFromOffset(Mdl, CurrentOffset),
628 Length,
630 Context,
632 }
633
635
636 return status;
637 }
638
639 VOID
642 )
643 {
644 KIRQL irql;
645
647
653
654 return;
655 }
656
660 __in PMDL Mdl,
661 __in size_t CurrentOffset,
665 __in PVOID ScatterGatherBuffer,
666 __in ULONG ScatterGatherBufferLength
667 )
668 {
670 KIRQL irql;
671
673
674 if (m_DmaEnabler->UsesDmaV3()) {
675
676 PDMA_OPERATIONS dmaOperations =
678 ULONG flags = 0;
679
680 if (GetDriverGlobals()->IsVersionGreaterThanOrEqualTo(1,15)) {
681 //
682 // Though the correct behavior is to pass the m_Flags to the
683 // BuildScatterGatherListEx function, the code was not doing it
684 // for versions <= 1.13. To reduce any chance of regression,
685 // the m_Flags is honored for drivers that are 1.15
686 // or newer.
687 //
688 flags = m_Flags;
689 }
690
691 status = dmaOperations->BuildScatterGatherListEx(
695 Mdl,
696 CurrentOffset,
697 Length,
698 flags,
700 Context,
702 ScatterGatherBuffer,
703 ScatterGatherBufferLength,
704 NULL,
705 NULL,
706 NULL
707 );
708 }
709 else {
710
714 Mdl,
715 GetStartVaFromOffset(Mdl, CurrentOffset),
716 Length,
718 Context,
720 ScatterGatherBuffer,
721 ScatterGatherBufferLength);
722 }
723
724
726
727 return status;
728 }
729};
730
732
733protected:
735 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
736 __in USHORT ObjectSize,
737 __in USHORT ExtraSize,
739 );
740
741public:
742
744 virtual
747 VOID
748 );
749
757 );
758
759 VOID
761 VOID
762 );
763
765 virtual
768 VOID
769 );
770
772 virtual
775 VOID
776 );
777
779 virtual
782 VOID
783 );
784
785 virtual
786 VOID
788 __in BOOLEAN ForceRelease
789 );
790
792 static
794 _Create(
795 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
798 __out WDFDMATRANSACTION* Transaction
799 );
800
801 VOID
804 )
805 {
807 }
808
809protected:
810
811 //
812 // Number of map registers to be used in this transfer.
813 // This value is the least of the number of map registers
814 // needed to satisfy the current transfer request, and the
815 // number of available map registers returned by IoGetDmaAdapter.
816 //
818
819 //
820 // Opaque-value represents the map registers that the system has
821 // assigned for this transfer operation. We pass this value in
822 // FlushAdapterBuffers, FreeMapRegisters, and MapTransfer.
823 //
825
826 //
827 // TRUE when the map register base above is valid. The HAL can give
828 // us a NULL map register base when double buffering isn't required,
829 // so we can't just do a NULL test on m_MapRegisterBase to know if
830 // the DMA channel is allocated.
831 //
833
834 //
835 // For system-DMA this provides the offset from the original
836 // DeviceAddress used to compute the device register to or from which
837 // DMA should occur.
838 //
840
841 //
842 // 0 if the transaction has not reserved the enabler. Otherwise
843 // this is the number of map registers requested for the reservation.
844 // This value persists across a reuse and reinitialization of the
845 // transaction, and is only cleared when the enabler is released.
846 //
848
849 //
850 // These fields are used to defer completion or staging while another
851 // thread/CPU is already staging. They are protected by the
852 // transfer state lock.
853 //
854 // These values are cleared when checked, not in InitializeResources.
855 // It's possible for a transaction being staged to complete on another
856 // CPU, get reused and reinitialized. Clearing these values in
857 // InitializeResources would destroy the state the prior call to
858 // StageTransfer depends on.
859 //
860 struct {
861
862 //
863 // Non-null when a staging operation is in progress on some CPU.
864 // When set any attempt to call the DMA completion routine or
865 // stage the transfer again (due to a call to TransferComplete)
866 // will be deferred to this thread.
867 //
869
870 //
871 // Indicates that a nested or concurrent attempt to stage
872 // the transaction was deferred. The CurrentStagingThread
873 // will restage the transaction.
874 //
876
877 //
878 // Indicates that a nested or concurrent attempt to call the
879 // DMA completion routine occurred. The CurrentStagingThread
880 // will call the DMA completion routine when it unwinds providing
881 // the saved CompletionStatus
882 //
885
887
888 //
889 // Indicates that the DMA transfer has been cancelled.
890 // Set during StopTransfer and cleared during InitializeResources
891 // Checked during StageTransfer. Stop and Initialize should never
892 // race (it's not valid for the driver to stop an uninitialized
893 // transaction). Stop and Stage can race but in that case Stop
894 // will mark the transaction context such that MapTransfer fails
895 // (and that's protected by a HAL lock).
896 //
897 // So this field does not need to be volatile or interlocked, but
898 // it needs to be sized to allow atomic writes.
899 //
901
902
903 virtual
904 VOID
906 VOID
907 )
908 {
909 return;
910 }
911
912protected:
913
914 inline
915 void
918 )
919 {
920 NT_ASSERTMSG("Map register base is already set",
922
925 }
926
927 inline
928 void
930 VOID
931 )
932 {
933 NT_ASSERTMSG("Map register base was not set",
936 }
937
938 inline
939 BOOLEAN
941 VOID
942 )
943 {
945 }
946
947 inline
948 PVOID
950 VOID
951 )
952 {
953 NT_ASSERTMSG("Map register base is not set",
955 return m_MapRegisterBase;
956 }
957
958 virtual
961 VOID
962 )
963 {
965 }
966
967 virtual
968 BOOLEAN
970 VOID
971 )
972 {
973 return TRUE;
974 }
975
977 VOID
979#pragma prefast(suppress:__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 }
987
989 _Releases_lock_(this)
990 VOID
991#pragma prefast(suppress:__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 }
999
1000 virtual
1003 VOID
1004 )
1005 {
1006 return NULL;
1007 }
1008
1009 static
1011 STDCALL
1014 __in PIRP Irp,
1017 );
1018
1020 NTSTATUS
1022 VOID
1023 )
1024 {
1025 if (m_DmaEnabler->UsesDmaV3() == FALSE)
1026 {
1028 }
1029 else
1030 {
1031 return STATUS_SUCCESS;
1032 }
1033 }
1034
1036 VOID
1038 VOID
1039 )
1040 {
1041 if (m_DmaEnabler->UsesDmaV3() == FALSE)
1042 {
1044 }
1045 }
1046
1048 NTSTATUS
1050 __in BOOLEAN MapRegistersReserved
1051 )
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 }
1137
1139 NTSTATUS
1141 __out_bcount_opt(ScatterGatherListCb)
1142 PSCATTER_GATHER_LIST ScatterGatherList,
1143 __in ULONG ScatterGatherListCb,
1146 __out ULONG *TransferLength
1147 )
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 }
1263
1265 NTSTATUS
1267 VOID
1268 )
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 }
1335
1336 virtual
1337 VOID
1339 VOID
1340 )
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 }
1391
1392 virtual
1393 VOID
1395 __in DMA_COMPLETION_STATUS /* Status */
1396 )
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 }
1407
1408};
1409
1411
1413
1414public:
1415
1417 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
1418 __in USHORT ExtraSize,
1420 );
1421
1423 static
1424 NTSTATUS
1425 _Create(
1426 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
1429 __out WDFDMATRANSACTION* Transaction
1430 );
1431
1432 VOID
1436 )
1437 {
1440 }
1441
1442 VOID
1446 )
1447 {
1450 }
1451
1452 VOID
1454 VOID
1455 );
1456
1457protected:
1458
1459 //
1460 // Callback and context for configure channel callback
1461 //
1464
1465 //
1466 // Callback and context for DMA completion callback
1467 //
1470
1473 VOID
1474 )
1475 {
1476 return KeepObject;
1477 }
1478
1479 VOID
1481 VOID
1482 )
1483 {
1485 KIRQL irql;
1486
1488
1491 "Freeing adapter channel for WDFDMATRANSACTION %p",
1492 GetHandle());
1493 }
1494
1496 FreeAdapterChannel(m_AdapterInfo->AdapterObject);
1498
1499 return;
1500 }
1501
1502 BOOLEAN
1504 VOID
1505 )
1506 {
1508
1510
1511 //
1512 // Cancel the transfer. if it's not yet mapped this will mark the
1513 // TC so that mapping will fail. If it's running this will invoke the
1514 // DMA completion routine.
1515 //
1516 status =
1517 m_AdapterInfo->AdapterObject->DmaOperations->CancelMappedTransfer(
1520 );
1521
1523 "Stopping WDFDMATRANSACTION %p returned status %!STATUS!",
1524 GetHandle(),
1525 status);
1526
1527 return NT_SUCCESS(status);
1528 }
1529
1530 VOID
1532 VOID
1533 )
1534 {
1535 FxDmaPacketTransaction::Reuse(); // __super call
1538
1541 }
1542
1543 VOID
1546 );
1547
1548 virtual
1549 BOOLEAN
1551 VOID
1552 );
1553
1554 virtual
1557 VOID
1558 );
1559
1560 static DMA_COMPLETION_ROUTINE _SystemDmaCompletion;
1561};
1562
1563#endif // _FXDMATRANSACTION_HPP_
static PMDL CurrentMdl
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
__inline _Must_inspect_result_ NTSTATUS AcquireDmaPacketTransaction(VOID)
Definition: fxdevice.hpp:354
__inline VOID ReleaseDmaPacketTransaction(VOID)
Definition: fxdevice.hpp:373
BOOLEAN UsesDmaV3(VOID)
PDEVICE_OBJECT m_FDO
virtual VOID Reuse(VOID)
VOID SetDeviceAddressOffset(__in ULONG Offset)
void SetMapRegisterBase(__in PVOID Value)
virtual VOID FreeMapRegistersAndAdapter(VOID)
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 CallEvtDmaCompleted(__in DMA_COMPLETION_STATUS)
_Acquires_lock_(this) VOID __drv_raisesIRQL(DISPATCH_LEVEL) LockTransferState(__out __drv_deref(__drv_savesIRQL) KIRQL *OldIrql)
static IO_ALLOCATION_ACTION STDCALL _AdapterControl(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PVOID MapRegisterBase, __in PVOID Context)
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in FxDmaEnabler *DmaEnabler, __out WDFDMATRANSACTION *Transaction)
_Requires_lock_held_(this) _Releases_lock_(this) VOID UnlockTransferState(__in __drv_restoresIRQL KIRQL OldIrql)
FORCEINLINE VOID ReleaseDevice(VOID)
DMA_COMPLETION_STATUS CompletionStatus
struct FxDmaPacketTransaction::@4340 m_TransferState
_Must_inspect_result_ NTSTATUS AllocateAdapterChannel(__in BOOLEAN MapRegistersReserved)
BOOLEAN IsMapRegisterBaseSet(VOID)
virtual BOOLEAN PreMapTransfer(VOID)
_Must_inspect_result_ NTSTATUS ReserveAdapter(__in ULONG NumberOfMapRegisters, __in WDF_DMA_DIRECTION Direction, __in PFN_WDF_RESERVE_DMA Callback, __in_opt PVOID Context)
virtual _Must_inspect_result_ NTSTATUS TransferCompleted(VOID)
_Must_inspect_result_ NTSTATUS AcquireDevice(VOID)
virtual _Must_inspect_result_ NTSTATUS StartTransfer(VOID)
virtual VOID ReleaseResources(__in BOOLEAN ForceRelease)
virtual _Must_inspect_result_ NTSTATUS StageTransfer(VOID)
virtual PDMA_COMPLETION_ROUTINE GetTransferCompletionRoutine(VOID)
virtual _Must_inspect_result_ NTSTATUS InitializeResources(VOID)
virtual IO_ALLOCATION_ACTION GetAdapterControlReturnValue(VOID)
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in FxDmaEnabler *DmaEnabler, __out WDFDMATRANSACTION *Transaction)
virtual _Must_inspect_result_ NTSTATUS InitializeResources(VOID)
static VOID _AdapterListControl(__in DEVICE_OBJECT *DeviceObject, __in IRP *Irp, __in SCATTER_GATHER_LIST *SgList, __in VOID *Context)
virtual _Must_inspect_result_ NTSTATUS StartTransfer(VOID)
_Must_inspect_result_ NTSTATUS BuildScatterGatherList(__in PMDL Mdl, __in size_t CurrentOffset, __in ULONG Length, __in PDRIVER_LIST_CONTROL ExecutionRoutine, __in PVOID Context, __in PVOID ScatterGatherBuffer, __in ULONG ScatterGatherBufferLength)
virtual _Must_inspect_result_ NTSTATUS TransferCompleted(VOID)
_Must_inspect_result_ NTSTATUS GetScatterGatherList(__in PMDL Mdl, __in size_t CurrentOffset, __in ULONG Length, __in PDRIVER_LIST_CONTROL ExecutionRoutine, __in PVOID Context)
virtual _Must_inspect_result_ NTSTATUS StageTransfer(VOID)
VOID PutScatterGatherList(__in PSCATTER_GATHER_LIST ScatterGather)
virtual VOID ReleaseResources(__in BOOLEAN ForceRelease)
static DMA_COMPLETION_ROUTINE _SystemDmaCompletion
BOOLEAN CancelMappedTransfer(VOID)
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in FxDmaEnabler *DmaEnabler, __out WDFDMATRANSACTION *Transaction)
IO_ALLOCATION_ACTION GetAdapterControlReturnValue(VOID)
VOID CallEvtDmaCompleted(__in DMA_COMPLETION_STATUS Status)
VOID SetConfigureChannelCallback(__in_opt PFN_WDF_DMA_TRANSACTION_CONFIGURE_DMA_CHANNEL Callback, __in_opt PVOID Context)
FxDmaTransactionConfigureChannel m_ConfigureChannelFunction
virtual PDMA_COMPLETION_ROUTINE GetTransferCompletionRoutine(VOID)
VOID SetTransferCompleteCallback(__in_opt PFN_WDF_DMA_TRANSACTION_DMA_TRANSFER_COMPLETE Callback, __in_opt PVOID Context)
virtual BOOLEAN PreMapTransfer(VOID)
FxDmaTransactionTransferComplete m_TransferCompleteFunction
__forceinline size_t GetMaximumFragmentLength(VOID)
__forceinline VOID SetMaximumFragmentLength(size_t MaximumFragmentLength)
__forceinline size_t GetCurrentFragmentLength(VOID)
__forceinline BOOLEAN IsRequestReferenced(VOID)
__forceinline VOID ReleaseButRetainRequest(VOID)
VOID SetImmediateExecution(__in BOOLEAN Value)
static PVOID GetStartVaFromOffset(__in PMDL Mdl, __in size_t Offset)
__forceinline FxRequest * GetRequest(VOID)
virtual _Must_inspect_result_ NTSTATUS TransferCompleted(VOID)=0
virtual VOID ReleaseResources(__in BOOLEAN ForceRelease)=0
FxDmaTransactionProgramOrReserveDma m_DmaAcquiredFunction
FxDmaDescription * m_AdapterInfo
virtual _Must_inspect_result_ NTSTATUS StartTransfer(VOID)=0
__forceinline VOID SetRequest(__in FxRequest *Request)
FxDmaEnabler * m_DmaEnabler
VOID ReleaseForReuse(__in BOOLEAN ForceRelease)
__forceinline size_t GetBytesTransferred(VOID)
virtual _Must_inspect_result_ NTSTATUS StageTransfer(VOID)=0
FxDmaTransactionState GetTransactionState(VOID)
__forceinline VOID ReferenceRequest(VOID)
WDF_DMA_DIRECTION m_DmaDirection
__forceinline FxDmaEnabler * GetDmaEnabler(VOID)
__forceinline VOID ClearRequest(VOID)
_Must_inspect_result_ NTSTATUS Execute(__in PVOID Context)
FxDmaTransactionState m_State
VOID GetTransferInfo(__out_opt ULONG *MapRegisterCount, __out_opt ULONG *ScatterGatherElementCount)
virtual _Must_inspect_result_ NTSTATUS InitializeResources(VOID)=0
virtual VOID Reuse(VOID)
virtual BOOLEAN Dispose(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)
static VOID _ComputeNextTransferAddress(__in PMDL CurrentMdl, __in size_t CurrentOffset, __in ULONG Transferred, __deref_out PMDL *NextMdl, __out size_t *NextOffset)
BOOLEAN DmaCompleted(__in size_t TransferredLength, __out NTSTATUS *ReturnStatus, __in FxDmaCompletionType CompletionType)
__forceinline WDFDMATRANSACTION GetHandle(VOID)
PFN_WDF_DMA_TRANSACTION_CONFIGURE_DMA_CHANNEL Method
PFN_WDF_DMA_TRANSACTION_DMA_TRANSFER_COMPLETE Method
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
__drv_restoresIRQL KIRQL __in BOOLEAN Unlock
Definition: fxobject.hpp:1474
CfxDevice * GetDevice(VOID)
Definition: fxobject.hpp:781
__in __drv_restoresIRQL KIRQL OldIrql
Definition: fxobject.hpp:1465
VOID ReleaseIrpReference(VOID)
Definition: fxrequest.cpp:2512
VOID AddIrpReference(VOID)
Definition: fxrequest.cpp:2470
#define _Releases_lock_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define __out_opt
Definition: dbghelp.h:65
#define __in
Definition: dbghelp.h:35
#define __deref_out
Definition: dbghelp.h:26
#define __in_opt
Definition: dbghelp.h:38
#define __out
Definition: dbghelp.h:62
#define __out_bcount_opt(x)
Definition: dbghelp.h:71
#define TRACINGDMA
Definition: dbgtrace.h:71
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
KIRQL irql
Definition: wave.h:1
#define __drv_savesIRQL
Definition: driverspecs.h:326
#define __drv_deref(annotes)
Definition: driverspecs.h:265
#define __drv_restoresIRQL
Definition: driverspecs.h:322
#define __drv_raisesIRQL(irql)
Definition: driverspecs.h:312
UCHAR KIRQL
Definition: env_spec_w32.h:591
#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
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
PFX_DRIVER_GLOBALS pFxDriverGlobals
return pObject GetObjectHandle()
#define FX_DECODE_POINTER(T, p, tag)
#define FX_STRONG_REF_TAG
#define FX_IS_POINTER_ENCODED(p, tag)
FxDmaTransactionState
@ FxDmaTransactionStateDeleted
@ FxDmaTransactionStateInitialized
@ FxDmaTransactionStateTransferCompleted
@ FxDmaTransactionStateInvalid
@ FxDmaTransactionStateReleased
@ FxDmaTransactionStateReserved
@ FxDmaTransactionStateTransfer
@ FxDmaTransactionStateCreated
@ FxDmaTransactionStateTransferFailed
#define FX_ENCODE_POINTER(T, p, tag)
FxDmaCompletionType
@ FxDmaCompletionTypeAbort
@ FxDmaCompletionTypePartial
@ FxDmaCompletionTypeFull
systemTransaction StopTransfer()
return pDmaTrans CancelResourceAllocation()
pDmaTrans ReleaseAdapter()
return pDmaTrans GetTransferContext()
Status
Definition: gdiplustypes.h:25
GLbitfield flags
Definition: glext.h:7161
boolean suppress
Definition: jpeglib.h:1006
#define __assume(x)
Definition: intrin.h:108
#define ASSERT(a)
Definition: mode.c:44
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define DECLSPEC_ALIGN(x)
Definition: ntbasedef.h:251
#define MEMORY_ALLOCATION_ALIGNMENT
Definition: ntbasedef.h:90
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2295
PFLUSH_ADAPTER_BUFFERS_EX FlushAdapterBuffersEx
Definition: iotypes.h:2659
PMAP_TRANSFER_EX MapTransferEx
Definition: iotypes.h:2656
PALLOCATE_ADAPTER_CHANNEL_EX AllocateAdapterChannelEx
Definition: iotypes.h:2653
PFLUSH_ADAPTER_BUFFERS FlushAdapterBuffers
Definition: iotypes.h:2638
PGET_SCATTER_GATHER_LIST_EX GetScatterGatherListEx
Definition: iotypes.h:2657
PBUILD_SCATTER_GATHER_LIST_EX BuildScatterGatherListEx
Definition: iotypes.h:2658
BOOLEAN FxVerifierOn
Definition: fxglobals.h:420
PDMA_ADAPTER AdapterObject
Definition: ps.c:97
#define __WARNING_CLASS_MISMATCH_NONE
Definition: suppress.h:563
#define GetHandle(h)
Definition: treelist.c:116
uint32_t * PULONG
Definition: typedefs.h:59
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define STDCALL
Definition: wdf.h:45
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_Must_inspect_result_ _In_ WDFDMAENABLER DmaEnabler
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_In_ WDFDMAENABLER _In_ WDF_DMA_DIRECTION DmaDirection
enum _WDF_DMA_DIRECTION WDF_DMA_DIRECTION
EVT_WDF_DMA_TRANSACTION_DMA_TRANSFER_COMPLETE * PFN_WDF_DMA_TRANSACTION_DMA_TRANSFER_COMPLETE
EVT_WDF_PROGRAM_DMA * PFN_WDF_PROGRAM_DMA
EVT_WDF_RESERVE_DMA * PFN_WDF_RESERVE_DMA
WDF_EXTERN_C_START typedef _In_ WDFDEVICE _In_ WDFCONTEXT _In_ WDF_DMA_DIRECTION _In_ PSCATTER_GATHER_LIST SgList
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
WDF_EXTERN_C_START typedef _In_ WDFDEVICE _In_ WDFCONTEXT _In_ WDF_DMA_DIRECTION Direction
_In_ WDFDMATRANSACTION _Out_opt_ ULONG * MapRegisterCount
_In_ WDFDMATRANSACTION _In_ size_t TransferredLength
EVT_WDF_DMA_TRANSACTION_CONFIGURE_DMA_CHANNEL * PFN_WDF_DMA_TRANSACTION_CONFIGURE_DMA_CHANNEL
_In_ WDFDMATRANSACTION _Out_opt_ ULONG _Out_opt_ ULONG * ScatterGatherElementCount
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_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
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
#define FORCEINLINE
Definition: wdftypes.h:67
_Out_ PULONG NumberOfMapRegisters
Definition: halfuncs.h:209
_In_ PDEVICE_OBJECT _In_ ULONG _In_ PDRIVER_CONTROL ExecutionRoutine
Definition: iofuncs.h:1399
struct _SCATTER_GATHER_LIST SCATTER_GATHER_LIST
Definition: iotypes.h:2204
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2204
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:213
enum _IO_ALLOCATION_ACTION IO_ALLOCATION_ACTION
@ KeepObject
Definition: iotypes.h:202
@ DeallocateObjectKeepRegisters
Definition: iotypes.h:204
DRIVER_LIST_CONTROL * PDRIVER_LIST_CONTROL
Definition: iotypes.h:2377
_In_ struct _IRP _In_ struct _SCATTER_GATHER_LIST * ScatterGather
Definition: iotypes.h:2375
DMA_COMPLETION_STATUS
Definition: iotypes.h:2299
DMA_COMPLETION_ROUTINE * PDMA_COMPLETION_ROUTINE
Definition: iotypes.h:2488
#define MmGetMdlVirtualAddress(_Mdl)
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define NT_ASSERTMSG
Definition: rtlfuncs.h:3311
static void Initialize()
Definition: xlate.c:212
unsigned char UCHAR
Definition: xmlstorage.h:181