18a978a17SVictor Perevertkin /*++
28a978a17SVictor Perevertkin 
38a978a17SVictor Perevertkin Copyright (c) Microsoft Corporation
48a978a17SVictor Perevertkin 
58a978a17SVictor Perevertkin Module Name:
68a978a17SVictor Perevertkin 
78a978a17SVictor Perevertkin     FxDmaEnablerAPI.cpp
88a978a17SVictor Perevertkin 
98a978a17SVictor Perevertkin Abstract:
108a978a17SVictor Perevertkin 
118a978a17SVictor Perevertkin     Base for WDF DMA Enabler object APIs
128a978a17SVictor Perevertkin 
138a978a17SVictor Perevertkin Environment:
148a978a17SVictor Perevertkin 
158a978a17SVictor Perevertkin     Kernel mode only.
168a978a17SVictor Perevertkin 
178a978a17SVictor Perevertkin Notes:
188a978a17SVictor Perevertkin 
198a978a17SVictor Perevertkin 
208a978a17SVictor Perevertkin Revision History:
218a978a17SVictor Perevertkin 
228a978a17SVictor Perevertkin --*/
238a978a17SVictor Perevertkin 
24*1f377076SVictor Perevertkin #include "fxdmapch.hpp"
258a978a17SVictor Perevertkin 
268a978a17SVictor Perevertkin extern "C" {
27*1f377076SVictor Perevertkin // #include "FxDmaEnablerAPI.tmh"
288a978a17SVictor Perevertkin }
298a978a17SVictor Perevertkin 
308a978a17SVictor Perevertkin //
318a978a17SVictor Perevertkin // Extern "C" the entire file
328a978a17SVictor Perevertkin //
338a978a17SVictor Perevertkin extern "C" {
348a978a17SVictor Perevertkin 
358a978a17SVictor Perevertkin _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)368a978a17SVictor Perevertkin __drv_maxIRQL(PASSIVE_LEVEL)
378a978a17SVictor Perevertkin NTSTATUS
388a978a17SVictor Perevertkin WDFEXPORT(WdfDmaEnablerCreate)(
398a978a17SVictor Perevertkin     __in
408a978a17SVictor Perevertkin     PWDF_DRIVER_GLOBALS DriverGlobals,
418a978a17SVictor Perevertkin     __in
428a978a17SVictor Perevertkin     WDFDEVICE Device,
438a978a17SVictor Perevertkin     __in
448a978a17SVictor Perevertkin     WDF_DMA_ENABLER_CONFIG * Config,
458a978a17SVictor Perevertkin     __in_opt
468a978a17SVictor Perevertkin     WDF_OBJECT_ATTRIBUTES * Attributes,
478a978a17SVictor Perevertkin     __out
488a978a17SVictor Perevertkin     WDFDMAENABLER * DmaEnablerHandle
498a978a17SVictor Perevertkin     )
508a978a17SVictor Perevertkin {
518a978a17SVictor Perevertkin     FxDmaEnabler *          pDmaEnabler;
528a978a17SVictor Perevertkin     FxDeviceBase *          pDevice;
538a978a17SVictor Perevertkin     NTSTATUS                status;
548a978a17SVictor Perevertkin     WDFDMAENABLER           handle;
558a978a17SVictor Perevertkin     PFX_DRIVER_GLOBALS      pFxDriverGlobals;
568a978a17SVictor Perevertkin     FxObject     *          pParent;
578a978a17SVictor Perevertkin     WDF_DMA_ENABLER_CONFIG  dmaConfig;
588a978a17SVictor Perevertkin 
598a978a17SVictor Perevertkin     //
608a978a17SVictor Perevertkin     // Validate the Device handle
618a978a17SVictor Perevertkin     //
628a978a17SVictor Perevertkin     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
638a978a17SVictor Perevertkin                                    Device,
648a978a17SVictor Perevertkin                                    FX_TYPE_DEVICE_BASE,
658a978a17SVictor Perevertkin                                    (PVOID *) &pDevice,
668a978a17SVictor Perevertkin                                    &pFxDriverGlobals);
678a978a17SVictor Perevertkin 
688a978a17SVictor Perevertkin     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
698a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
708a978a17SVictor Perevertkin         return status;
718a978a17SVictor Perevertkin     }
728a978a17SVictor Perevertkin 
738a978a17SVictor Perevertkin     FxPointerNotNull(pFxDriverGlobals, DmaEnablerHandle);
748a978a17SVictor Perevertkin     FxPointerNotNull(pFxDriverGlobals, Config);
758a978a17SVictor Perevertkin 
768a978a17SVictor Perevertkin     *DmaEnablerHandle = NULL;
778a978a17SVictor Perevertkin 
788a978a17SVictor Perevertkin     status = FxValidateObjectAttributes(pFxDriverGlobals, Attributes);
798a978a17SVictor Perevertkin 
808a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
818a978a17SVictor Perevertkin         return status;
828a978a17SVictor Perevertkin     }
838a978a17SVictor Perevertkin 
848a978a17SVictor Perevertkin     if (Attributes != NULL && Attributes->ParentObject != NULL) {
858a978a17SVictor Perevertkin         FxObjectHandleGetPtr(pFxDriverGlobals,
868a978a17SVictor Perevertkin                              Attributes->ParentObject,
878a978a17SVictor Perevertkin                              FX_TYPE_OBJECT,
888a978a17SVictor Perevertkin                              (PVOID*)&pParent);
898a978a17SVictor Perevertkin 
908a978a17SVictor Perevertkin         if (pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11)) {
918a978a17SVictor Perevertkin             FxDeviceBase * pSearchDevice;
928a978a17SVictor Perevertkin 
938a978a17SVictor Perevertkin             //
948a978a17SVictor Perevertkin             // If a parent object is passed-in it must be descendent of device.
958a978a17SVictor Perevertkin             // DmaEnabler stores device and uses it during dispose
968a978a17SVictor Perevertkin             // (to remove it from dmaenabler list maintained at device level),
978a978a17SVictor Perevertkin             // so DmaEnabler cannot outlive device.
988a978a17SVictor Perevertkin             //
998a978a17SVictor Perevertkin 
1008a978a17SVictor Perevertkin             pSearchDevice = FxDeviceBase::_SearchForDevice(pParent, NULL);
1018a978a17SVictor Perevertkin 
1028a978a17SVictor Perevertkin             if (pSearchDevice == NULL) {
1038a978a17SVictor Perevertkin                 status = STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
1048a978a17SVictor Perevertkin 
1058a978a17SVictor Perevertkin                 DoTraceLevelMessage(
1068a978a17SVictor Perevertkin                     pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
1078a978a17SVictor Perevertkin                     "Attributes->ParentObject 0x%p must have WDFDEVICE as an "
1088a978a17SVictor Perevertkin                     "eventual ancestor, %!STATUS!",
1098a978a17SVictor Perevertkin                     Attributes->ParentObject, status);
1108a978a17SVictor Perevertkin 
1118a978a17SVictor Perevertkin                 return status;
1128a978a17SVictor Perevertkin             }
1138a978a17SVictor Perevertkin             else if (pSearchDevice != pDevice) {
1148a978a17SVictor Perevertkin                 status = STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
1158a978a17SVictor Perevertkin 
1168a978a17SVictor Perevertkin                 DoTraceLevelMessage(
1178a978a17SVictor Perevertkin                     pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
1188a978a17SVictor Perevertkin                     "Attributes->ParentObject 0x%p ancestor is WDFDEVICE %p, but "
1198a978a17SVictor Perevertkin                     "not the same WDFDEVICE 0x%p passed to WdfDmaEnablerCreate, "
1208a978a17SVictor Perevertkin                     "%!STATUS!",
1218a978a17SVictor Perevertkin                     Attributes->ParentObject, pSearchDevice->GetHandle(),
1228a978a17SVictor Perevertkin                     Device, status);
1238a978a17SVictor Perevertkin 
1248a978a17SVictor Perevertkin                 return status;
1258a978a17SVictor Perevertkin             }
1268a978a17SVictor Perevertkin         }
1278a978a17SVictor Perevertkin         else {
1288a978a17SVictor Perevertkin             //
1298a978a17SVictor Perevertkin             // For < 1.11 drivers we only allow pDevice to be the parent
1308a978a17SVictor Perevertkin             // since that is what we were blindly setting the parent to.
1318a978a17SVictor Perevertkin             //
1328a978a17SVictor Perevertkin             // Using the passed-in parent for such drivers could cause
1338a978a17SVictor Perevertkin             // side-effects such as earlier deletion of DmaEnabler object. So
1348a978a17SVictor Perevertkin             // we don't do that.
1358a978a17SVictor Perevertkin             //
1368a978a17SVictor Perevertkin             // We cause this verifier breakpoint to warn downlevel drivers
1378a978a17SVictor Perevertkin             // that the parent they passed in gets ignored.
1388a978a17SVictor Perevertkin             //
1398a978a17SVictor Perevertkin             if (pParent != pDevice) {
1408a978a17SVictor Perevertkin                 DoTraceLevelMessage(
1418a978a17SVictor Perevertkin                     pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGDMA,
1428a978a17SVictor Perevertkin                     "For drivers bound to version <= 1.9 "
1438a978a17SVictor Perevertkin                     "WdfDmaEnablerCreate uses WDFDEVICE as the "
1448a978a17SVictor Perevertkin                     "parent object for the dma enabler object. "
1458a978a17SVictor Perevertkin                     "Attributes->ParentObject 0x%p, which is different from "
1468a978a17SVictor Perevertkin                     "WDFDEVICE 0x%p, gets ignored. Please note that DmaEnabler "
1478a978a17SVictor Perevertkin                     "would be disposed only when device is disposed.",
1488a978a17SVictor Perevertkin                     Attributes->ParentObject, Device);
1498a978a17SVictor Perevertkin 
1508a978a17SVictor Perevertkin                 if (pFxDriverGlobals->IsDownlevelVerificationEnabled()) {
1518a978a17SVictor Perevertkin                     FxVerifierDbgBreakPoint(pFxDriverGlobals);
1528a978a17SVictor Perevertkin                 }
1538a978a17SVictor Perevertkin             }
1548a978a17SVictor Perevertkin 
1558a978a17SVictor Perevertkin             pParent = pDevice;
1568a978a17SVictor Perevertkin         }
1578a978a17SVictor Perevertkin     }
1588a978a17SVictor Perevertkin     else {
1598a978a17SVictor Perevertkin         pParent = pDevice;
1608a978a17SVictor Perevertkin     }
1618a978a17SVictor Perevertkin 
1628a978a17SVictor Perevertkin     {
1638a978a17SVictor Perevertkin         ULONG expectedSize = pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11) ?
1648a978a17SVictor Perevertkin             sizeof(WDF_DMA_ENABLER_CONFIG) :
1658a978a17SVictor Perevertkin             sizeof(WDF_DMA_ENABLER_CONFIG_V1_9);
1668a978a17SVictor Perevertkin 
1678a978a17SVictor Perevertkin         if (Config->Size != expectedSize) {
1688a978a17SVictor Perevertkin             status = STATUS_INFO_LENGTH_MISMATCH;
1698a978a17SVictor Perevertkin 
1708a978a17SVictor Perevertkin             DoTraceLevelMessage(
1718a978a17SVictor Perevertkin                 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
1728a978a17SVictor Perevertkin                 "WDF_DMA_ENABLER_CONFIG Size 0x%x, expected 0x%x, %!STATUS!",
1738a978a17SVictor Perevertkin                 Config->Size, expectedSize, status);
1748a978a17SVictor Perevertkin 
1758a978a17SVictor Perevertkin             return status;
1768a978a17SVictor Perevertkin         }
1778a978a17SVictor Perevertkin 
1788a978a17SVictor Perevertkin 
1798a978a17SVictor Perevertkin         //
1808a978a17SVictor Perevertkin         // Normalize DMA config structure if necessary.
1818a978a17SVictor Perevertkin         //
1828a978a17SVictor Perevertkin         if (Config->Size < sizeof(WDF_DMA_ENABLER_CONFIG)) {
1838a978a17SVictor Perevertkin             //
1848a978a17SVictor Perevertkin             // Init new fields to default values.
1858a978a17SVictor Perevertkin             //
1868a978a17SVictor Perevertkin             WDF_DMA_ENABLER_CONFIG_INIT(&dmaConfig,
1878a978a17SVictor Perevertkin                                         Config->Profile,
1888a978a17SVictor Perevertkin                                         Config->MaximumLength);
1898a978a17SVictor Perevertkin             //
1908a978a17SVictor Perevertkin             // Copy over existing fields and readjust the struct size.
1918a978a17SVictor Perevertkin             //
1928a978a17SVictor Perevertkin             RtlCopyMemory(&dmaConfig, Config, Config->Size);
1938a978a17SVictor Perevertkin             dmaConfig.Size = sizeof(dmaConfig);
1948a978a17SVictor Perevertkin 
1958a978a17SVictor Perevertkin             //
1968a978a17SVictor Perevertkin             // Use new config structure from now on.
1978a978a17SVictor Perevertkin             //
1988a978a17SVictor Perevertkin             Config = &dmaConfig;
1998a978a17SVictor Perevertkin         }
2008a978a17SVictor Perevertkin     }
2018a978a17SVictor Perevertkin 
2028a978a17SVictor Perevertkin     switch (Config->Profile) {
2038a978a17SVictor Perevertkin         case WdfDmaProfilePacket:
2048a978a17SVictor Perevertkin         case WdfDmaProfileScatterGather:
2058a978a17SVictor Perevertkin         case WdfDmaProfilePacket64:
2068a978a17SVictor Perevertkin         case WdfDmaProfileScatterGather64:
2078a978a17SVictor Perevertkin         case WdfDmaProfileScatterGather64Duplex:
2088a978a17SVictor Perevertkin         case WdfDmaProfileScatterGatherDuplex:
2098a978a17SVictor Perevertkin         case WdfDmaProfileSystem:
2108a978a17SVictor Perevertkin         case WdfDmaProfileSystemDuplex:
2118a978a17SVictor Perevertkin             break;
2128a978a17SVictor Perevertkin         default:
2138a978a17SVictor Perevertkin             status = STATUS_INVALID_PARAMETER;
2148a978a17SVictor Perevertkin             DoTraceLevelMessage(
2158a978a17SVictor Perevertkin                 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
2168a978a17SVictor Perevertkin                 "DMA Profile value %d is unknown, %!STATUS!",
2178a978a17SVictor Perevertkin                 Config->Profile, status);
2188a978a17SVictor Perevertkin             return status;
2198a978a17SVictor Perevertkin     }
2208a978a17SVictor Perevertkin 
2218a978a17SVictor Perevertkin     if (Config->MaximumLength == 0) {
2228a978a17SVictor Perevertkin         status = STATUS_INVALID_PARAMETER;
2238a978a17SVictor Perevertkin 
2248a978a17SVictor Perevertkin         DoTraceLevelMessage(
2258a978a17SVictor Perevertkin             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
2268a978a17SVictor Perevertkin             "Config MaximumLength of zero is invalid, %!STATUS!",
2278a978a17SVictor Perevertkin             status);
2288a978a17SVictor Perevertkin 
2298a978a17SVictor Perevertkin         return status;
2308a978a17SVictor Perevertkin     }
2318a978a17SVictor Perevertkin 
2328a978a17SVictor Perevertkin     //
2338a978a17SVictor Perevertkin     // Ok: create a new DmaEnabler
2348a978a17SVictor Perevertkin     //
2358a978a17SVictor Perevertkin     pDmaEnabler = new(pFxDriverGlobals, Attributes)
2368a978a17SVictor Perevertkin         FxDmaEnabler( pFxDriverGlobals );
2378a978a17SVictor Perevertkin 
2388a978a17SVictor Perevertkin     if (pDmaEnabler == NULL) {
2398a978a17SVictor Perevertkin         status = STATUS_INSUFFICIENT_RESOURCES;
2408a978a17SVictor Perevertkin 
2418a978a17SVictor Perevertkin         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
2428a978a17SVictor Perevertkin                             "Could not allocate memory for a WDFDMAENABLER, "
2438a978a17SVictor Perevertkin                             "%!STATUS!", status);
2448a978a17SVictor Perevertkin 
2458a978a17SVictor Perevertkin         return status;
2468a978a17SVictor Perevertkin     }
2478a978a17SVictor Perevertkin 
2488a978a17SVictor Perevertkin     //
2498a978a17SVictor Perevertkin     // Assign this FxDmaEnabler to its parent FxDevice object.
2508a978a17SVictor Perevertkin     //
2518a978a17SVictor Perevertkin     status = pDmaEnabler->Commit(Attributes, (WDFOBJECT*)&handle, pParent);
2528a978a17SVictor Perevertkin 
2538a978a17SVictor Perevertkin     if (NT_SUCCESS(status)) {
2548a978a17SVictor Perevertkin         //
2558a978a17SVictor Perevertkin         // Ok: start this DmaEnabler.
2568a978a17SVictor Perevertkin         //
2578a978a17SVictor Perevertkin         status = pDmaEnabler->Initialize( Config, pDevice );
2588a978a17SVictor Perevertkin     }
2598a978a17SVictor Perevertkin 
2608a978a17SVictor Perevertkin     if (NT_SUCCESS(status)) {
2618a978a17SVictor Perevertkin         //
2628a978a17SVictor Perevertkin         // Only return a valid handle on success.
2638a978a17SVictor Perevertkin         //
2648a978a17SVictor Perevertkin         *DmaEnablerHandle = handle;
2658a978a17SVictor Perevertkin     }
2668a978a17SVictor Perevertkin     else {
2678a978a17SVictor Perevertkin         pDmaEnabler->DeleteFromFailedCreate();
2688a978a17SVictor Perevertkin     }
2698a978a17SVictor Perevertkin 
2708a978a17SVictor Perevertkin     return status;
2718a978a17SVictor Perevertkin }
2728a978a17SVictor Perevertkin 
__drv_maxIRQL(DISPATCH_LEVEL)2738a978a17SVictor Perevertkin __drv_maxIRQL(DISPATCH_LEVEL)
2748a978a17SVictor Perevertkin size_t
2758a978a17SVictor Perevertkin WDFEXPORT(WdfDmaEnablerGetMaximumLength)(
2768a978a17SVictor Perevertkin     __in
2778a978a17SVictor Perevertkin     PWDF_DRIVER_GLOBALS DriverGlobals,
2788a978a17SVictor Perevertkin     __in
2798a978a17SVictor Perevertkin     WDFDMAENABLER DmaEnabler
2808a978a17SVictor Perevertkin     )
2818a978a17SVictor Perevertkin {
2828a978a17SVictor Perevertkin     FxDmaEnabler * pDmaEnabler;
2838a978a17SVictor Perevertkin 
2848a978a17SVictor Perevertkin     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
2858a978a17SVictor Perevertkin                          DmaEnabler,
2868a978a17SVictor Perevertkin                          FX_TYPE_DMA_ENABLER,
2878a978a17SVictor Perevertkin                          (PVOID *) &pDmaEnabler);
2888a978a17SVictor Perevertkin 
2898a978a17SVictor Perevertkin     return pDmaEnabler->GetMaximumLength();
2908a978a17SVictor Perevertkin }
2918a978a17SVictor Perevertkin 
__drv_maxIRQL(DISPATCH_LEVEL)2928a978a17SVictor Perevertkin __drv_maxIRQL(DISPATCH_LEVEL)
2938a978a17SVictor Perevertkin size_t
2948a978a17SVictor Perevertkin WDFEXPORT(WdfDmaEnablerGetMaximumScatterGatherElements)(
2958a978a17SVictor Perevertkin     __in
2968a978a17SVictor Perevertkin     PWDF_DRIVER_GLOBALS DriverGlobals,
2978a978a17SVictor Perevertkin     __in
2988a978a17SVictor Perevertkin     WDFDMAENABLER DmaEnabler
2998a978a17SVictor Perevertkin     )
3008a978a17SVictor Perevertkin {
3018a978a17SVictor Perevertkin     FxDmaEnabler * pDmaEnabler;
3028a978a17SVictor Perevertkin 
3038a978a17SVictor Perevertkin     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
3048a978a17SVictor Perevertkin                          DmaEnabler,
3058a978a17SVictor Perevertkin                          FX_TYPE_DMA_ENABLER,
3068a978a17SVictor Perevertkin                          (PVOID *) &pDmaEnabler);
3078a978a17SVictor Perevertkin 
3088a978a17SVictor Perevertkin     return pDmaEnabler->GetMaxSGElements();
3098a978a17SVictor Perevertkin }
3108a978a17SVictor Perevertkin 
3118a978a17SVictor Perevertkin 
__drv_maxIRQL(PASSIVE_LEVEL)3128a978a17SVictor Perevertkin __drv_maxIRQL(PASSIVE_LEVEL)
3138a978a17SVictor Perevertkin VOID
3148a978a17SVictor Perevertkin WDFEXPORT(WdfDmaEnablerSetMaximumScatterGatherElements)(
3158a978a17SVictor Perevertkin     __in
3168a978a17SVictor Perevertkin     PWDF_DRIVER_GLOBALS DriverGlobals,
3178a978a17SVictor Perevertkin     __in
3188a978a17SVictor Perevertkin     WDFDMAENABLER DmaEnabler,
3198a978a17SVictor Perevertkin     __in
3208a978a17SVictor Perevertkin     __drv_when(MaximumElements == 0, __drv_reportError(MaximumElements cannot be zero))
3218a978a17SVictor Perevertkin     size_t MaximumElements
3228a978a17SVictor Perevertkin     )
3238a978a17SVictor Perevertkin {
3248a978a17SVictor Perevertkin     PFX_DRIVER_GLOBALS pFxDriverGlobals;
3258a978a17SVictor Perevertkin     FxDmaEnabler * pDmaEnabler;
3268a978a17SVictor Perevertkin     NTSTATUS      status;
3278a978a17SVictor Perevertkin 
3288a978a17SVictor Perevertkin     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
3298a978a17SVictor Perevertkin                                    DmaEnabler,
3308a978a17SVictor Perevertkin                                    FX_TYPE_DMA_ENABLER,
3318a978a17SVictor Perevertkin                                    (PVOID *) &pDmaEnabler,
3328a978a17SVictor Perevertkin                                    &pFxDriverGlobals);
3338a978a17SVictor Perevertkin 
3348a978a17SVictor Perevertkin     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
3358a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
3368a978a17SVictor Perevertkin         return;
3378a978a17SVictor Perevertkin     }
3388a978a17SVictor Perevertkin 
3398a978a17SVictor Perevertkin     if (MaximumElements == 0) {
3408a978a17SVictor Perevertkin         DoTraceLevelMessage(
3418a978a17SVictor Perevertkin             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
3428a978a17SVictor Perevertkin             "Cannot set MaximumElements of zero on WDFDMAENABLER %p",
3438a978a17SVictor Perevertkin             DmaEnabler);
3448a978a17SVictor Perevertkin         return;
3458a978a17SVictor Perevertkin     }
3468a978a17SVictor Perevertkin 
3478a978a17SVictor Perevertkin     pDmaEnabler->SetMaxSGElements(MaximumElements);
3488a978a17SVictor Perevertkin }
3498a978a17SVictor Perevertkin 
__drv_maxIRQL(DISPATCH_LEVEL)3508a978a17SVictor Perevertkin __drv_maxIRQL(DISPATCH_LEVEL)
3518a978a17SVictor Perevertkin size_t
3528a978a17SVictor Perevertkin WDFEXPORT(WdfDmaEnablerGetFragmentLength)(
3538a978a17SVictor Perevertkin     __in
3548a978a17SVictor Perevertkin     PWDF_DRIVER_GLOBALS DriverGlobals,
3558a978a17SVictor Perevertkin     __in
3568a978a17SVictor Perevertkin     WDFDMAENABLER DmaEnabler,
3578a978a17SVictor Perevertkin     __in
3588a978a17SVictor Perevertkin     WDF_DMA_DIRECTION   DmaDirection
3598a978a17SVictor Perevertkin     )
3608a978a17SVictor Perevertkin {
3618a978a17SVictor Perevertkin     FxDmaEnabler * pDmaEnabler;
3628a978a17SVictor Perevertkin     size_t length;
3638a978a17SVictor Perevertkin     PFX_DRIVER_GLOBALS pFxDriverGlobals;
3648a978a17SVictor Perevertkin 
3658a978a17SVictor Perevertkin     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
3668a978a17SVictor Perevertkin                                    DmaEnabler,
3678a978a17SVictor Perevertkin                                    FX_TYPE_DMA_ENABLER,
3688a978a17SVictor Perevertkin                                    (PVOID *) &pDmaEnabler,
3698a978a17SVictor Perevertkin                                    &pFxDriverGlobals);
3708a978a17SVictor Perevertkin 
3718a978a17SVictor Perevertkin     switch (DmaDirection) {
3728a978a17SVictor Perevertkin 
3738a978a17SVictor Perevertkin     case WdfDmaDirectionReadFromDevice:
3748a978a17SVictor Perevertkin         length = pDmaEnabler->GetReadDmaDescription()->MaximumFragmentLength;
3758a978a17SVictor Perevertkin         break;
3768a978a17SVictor Perevertkin 
3778a978a17SVictor Perevertkin     case WdfDmaDirectionWriteToDevice:
3788a978a17SVictor Perevertkin         length = pDmaEnabler->GetWriteDmaDescription()->MaximumFragmentLength;
3798a978a17SVictor Perevertkin         break;
3808a978a17SVictor Perevertkin 
3818a978a17SVictor Perevertkin     default:
3828a978a17SVictor Perevertkin         length = 0;
3838a978a17SVictor Perevertkin         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
3848a978a17SVictor Perevertkin                             "Invalid value for Dma direction %d, %p",
3858a978a17SVictor Perevertkin                             DmaDirection, DmaEnabler);
3868a978a17SVictor Perevertkin         FxVerifierDbgBreakPoint(pFxDriverGlobals);
3878a978a17SVictor Perevertkin         break;
3888a978a17SVictor Perevertkin     }
3898a978a17SVictor Perevertkin 
3908a978a17SVictor Perevertkin     return length;
3918a978a17SVictor Perevertkin }
3928a978a17SVictor Perevertkin 
__drv_maxIRQL(DISPATCH_LEVEL)3938a978a17SVictor Perevertkin __drv_maxIRQL(DISPATCH_LEVEL)
3948a978a17SVictor Perevertkin PDMA_ADAPTER
3958a978a17SVictor Perevertkin WDFEXPORT(WdfDmaEnablerWdmGetDmaAdapter)(
3968a978a17SVictor Perevertkin     __in
3978a978a17SVictor Perevertkin     PWDF_DRIVER_GLOBALS DriverGlobals,
3988a978a17SVictor Perevertkin     __in
3998a978a17SVictor Perevertkin     WDFDMAENABLER DmaEnabler,
4008a978a17SVictor Perevertkin     __in
4018a978a17SVictor Perevertkin     WDF_DMA_DIRECTION DmaDirection
4028a978a17SVictor Perevertkin     )
4038a978a17SVictor Perevertkin {
4048a978a17SVictor Perevertkin     PDMA_ADAPTER adapter;
4058a978a17SVictor Perevertkin     PFX_DRIVER_GLOBALS pFxDriverGlobals;
4068a978a17SVictor Perevertkin     FxDmaEnabler * pDmaEnabler;
4078a978a17SVictor Perevertkin 
4088a978a17SVictor Perevertkin     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
4098a978a17SVictor Perevertkin                                    DmaEnabler,
4108a978a17SVictor Perevertkin                                    FX_TYPE_DMA_ENABLER,
4118a978a17SVictor Perevertkin                                    (PVOID *) &pDmaEnabler,
4128a978a17SVictor Perevertkin                                    &pFxDriverGlobals);
4138a978a17SVictor Perevertkin 
4148a978a17SVictor Perevertkin     switch (DmaDirection) {
4158a978a17SVictor Perevertkin 
4168a978a17SVictor Perevertkin     case WdfDmaDirectionReadFromDevice:
4178a978a17SVictor Perevertkin         adapter = pDmaEnabler->GetReadDmaDescription()->AdapterObject;
4188a978a17SVictor Perevertkin         break;
4198a978a17SVictor Perevertkin 
4208a978a17SVictor Perevertkin     case WdfDmaDirectionWriteToDevice:
4218a978a17SVictor Perevertkin         adapter = pDmaEnabler->GetWriteDmaDescription()->AdapterObject;
4228a978a17SVictor Perevertkin         break;
4238a978a17SVictor Perevertkin 
4248a978a17SVictor Perevertkin     default:
4258a978a17SVictor Perevertkin         adapter = NULL;
4268a978a17SVictor Perevertkin         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
4278a978a17SVictor Perevertkin                             "Invalid value for Dma direction %d, %p",
4288a978a17SVictor Perevertkin                             DmaDirection, DmaEnabler);
4298a978a17SVictor Perevertkin         FxVerifierDbgBreakPoint(pFxDriverGlobals);
4308a978a17SVictor Perevertkin         break;
4318a978a17SVictor Perevertkin     }
4328a978a17SVictor Perevertkin 
4338a978a17SVictor Perevertkin     return adapter;
4348a978a17SVictor Perevertkin }
4358a978a17SVictor Perevertkin 
4368a978a17SVictor Perevertkin _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)4378a978a17SVictor Perevertkin __drv_maxIRQL(PASSIVE_LEVEL)
4388a978a17SVictor Perevertkin NTSTATUS
4398a978a17SVictor Perevertkin WDFEXPORT(WdfDmaEnablerConfigureSystemProfile)(
4408a978a17SVictor Perevertkin     __in
4418a978a17SVictor Perevertkin     PWDF_DRIVER_GLOBALS DriverGlobals,
4428a978a17SVictor Perevertkin     __in
4438a978a17SVictor Perevertkin     WDFDMAENABLER DmaEnabler,
4448a978a17SVictor Perevertkin     __in
4458a978a17SVictor Perevertkin     PWDF_DMA_SYSTEM_PROFILE_CONFIG ProfileConfig,
4468a978a17SVictor Perevertkin     __in
4478a978a17SVictor Perevertkin     WDF_DMA_DIRECTION ConfigDirection
4488a978a17SVictor Perevertkin     )
4498a978a17SVictor Perevertkin {
4508a978a17SVictor Perevertkin     PFX_DRIVER_GLOBALS pFxDriverGlobals;
4518a978a17SVictor Perevertkin     FxDmaEnabler * pDmaEnabler;
4528a978a17SVictor Perevertkin 
4538a978a17SVictor Perevertkin     NTSTATUS status;
4548a978a17SVictor Perevertkin 
4558a978a17SVictor Perevertkin     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
4568a978a17SVictor Perevertkin                                    DmaEnabler,
4578a978a17SVictor Perevertkin                                    FX_TYPE_DMA_ENABLER,
4588a978a17SVictor Perevertkin                                    (PVOID *) &pDmaEnabler,
4598a978a17SVictor Perevertkin                                    &pFxDriverGlobals);
4608a978a17SVictor Perevertkin 
4618a978a17SVictor Perevertkin     //
4628a978a17SVictor Perevertkin     // Verify the DMA config
4638a978a17SVictor Perevertkin     //
4648a978a17SVictor Perevertkin 
4658a978a17SVictor Perevertkin     if (ProfileConfig == NULL)
4668a978a17SVictor Perevertkin     {
4678a978a17SVictor Perevertkin         status = STATUS_INVALID_PARAMETER;
4688a978a17SVictor Perevertkin         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
4698a978a17SVictor Perevertkin                             "ProfileConfig must be non-null, %!STATUS!",
4708a978a17SVictor Perevertkin                             status);
4718a978a17SVictor Perevertkin         FxVerifierDbgBreakPoint(pFxDriverGlobals);
4728a978a17SVictor Perevertkin         return status;
4738a978a17SVictor Perevertkin     }
4748a978a17SVictor Perevertkin 
4758a978a17SVictor Perevertkin     if (ProfileConfig->Size != sizeof(WDF_DMA_SYSTEM_PROFILE_CONFIG))
4768a978a17SVictor Perevertkin     {
4778a978a17SVictor Perevertkin         status = STATUS_INFO_LENGTH_MISMATCH;
4788a978a17SVictor Perevertkin 
4798a978a17SVictor Perevertkin         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
4808a978a17SVictor Perevertkin                             "WDF_DMA_SYSTEM_PROFILE_CONFIG Size 0x%x, expected 0x%x, %!STATUS!",
4818a978a17SVictor Perevertkin                             ProfileConfig->Size, sizeof(WDF_DMA_SYSTEM_PROFILE_CONFIG), status);
4828a978a17SVictor Perevertkin 
4838a978a17SVictor Perevertkin         FxVerifierDbgBreakPoint(pFxDriverGlobals);
4848a978a17SVictor Perevertkin 
4858a978a17SVictor Perevertkin         return status;
4868a978a17SVictor Perevertkin     }
4878a978a17SVictor Perevertkin 
4888a978a17SVictor Perevertkin     if (ProfileConfig->DmaDescriptor == NULL)
4898a978a17SVictor Perevertkin     {
4908a978a17SVictor Perevertkin         status = STATUS_INVALID_PARAMETER;
4918a978a17SVictor Perevertkin 
4928a978a17SVictor Perevertkin         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
4938a978a17SVictor Perevertkin                             "ProfileConfig (%p) may not have NULL DmaDescriptor, %!STATUS!",
4948a978a17SVictor Perevertkin                             ProfileConfig, status);
4958a978a17SVictor Perevertkin 
4968a978a17SVictor Perevertkin         FxVerifierDbgBreakPoint(pFxDriverGlobals);
4978a978a17SVictor Perevertkin 
4988a978a17SVictor Perevertkin         return status;
4998a978a17SVictor Perevertkin     }
5008a978a17SVictor Perevertkin 
5018a978a17SVictor Perevertkin     if (ConfigDirection != WdfDmaDirectionReadFromDevice &&
5028a978a17SVictor Perevertkin         ConfigDirection != WdfDmaDirectionWriteToDevice) {
5038a978a17SVictor Perevertkin         status = STATUS_INVALID_PARAMETER;
5048a978a17SVictor Perevertkin         DoTraceLevelMessage(
5058a978a17SVictor Perevertkin             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
5068a978a17SVictor Perevertkin             "ConfigDirection 0x%x is an invalid value, %!STATUS!",
5078a978a17SVictor Perevertkin             ConfigDirection, status);
5088a978a17SVictor Perevertkin         return status;
5098a978a17SVictor Perevertkin     }
5108a978a17SVictor Perevertkin 
5118a978a17SVictor Perevertkin     status = pDmaEnabler->ConfigureSystemAdapter(ProfileConfig,
5128a978a17SVictor Perevertkin                                                  ConfigDirection);
5138a978a17SVictor Perevertkin     return status;
5148a978a17SVictor Perevertkin }
5158a978a17SVictor Perevertkin 
5168a978a17SVictor Perevertkin } // extern "C"
517