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