Setting up DMA - User Buffer, Handing I/O

@Tim_Roberts said:
Where do you get the STATUS_INSUFFICIENT_RESOURCES?
The call to CalculateScatterGatherList

To close off this thread:

I haven’t had any luck making this work. I continue to get STATUS_INSUFFICIENT_RESOURCES from CalculateScatterGatherList.

  • For now, I will set aside the “Hanging Direct I/O” approach and use the method of exposing a Common_Buffer to UserSW approach as it is working.
  • Still, it’s on the back burner, so if you have any suggestions / comments, please post away - thanks in advance.

Recap of my [failed] implementation (Note: Code snippets have been “simplified” for brevity):

User SW:

    // SW is allocating a data buffer using Large Pages (2MB). For this, SW needs to be running as Admin + have SE Privilege.
    tp.Privileges[ 0 ].Attributes = SE_PRIVILEGE_ENABLED;

      // enable privilege
    status = AdjustTokenPrivileges( hToken, FALSE, &tp, 0, ( PTOKEN_PRIVILEGES ) NULL, 0 );

   // For testing, allocate 4MB (2 pages) but will eventually need much more than this.
   pointerToMemory = VirtualAlloc( NULL, 
                                   memorySize,
                                   MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES,
                                   PAGE_EXECUTE_READWRITE );

    DeviceIoControl( pDevice->hFile,
                    IOCTL_SETUP_HOST_MEMORY_DMA,
                    inDataHostMemoryInfoP, sizeof( SetupHostMemoryInputBufferType ),
                    pointerToMemory , memorySize,
                    &bytesReturned, NULL ) );

Driver Device Add:

WDF_DMA_ENABLER_CONFIG dmaEnablerConfig;
WDF_DMA_ENABLER_CONFIG_INIT( &dmaEnablerConfig, WdfDmaProfileScatterGather64Duplex, 1024*4 );

dmaEnablerConfig.AddressWidthOverride = 0;

NTSTATUS status{ WdfDmaEnablerCreate( wdfDevice, &dmaEnablerConfig, WDF_NO_OBJECT_ATTRIBUTES, &( myDmaEnabler ) ) };
if( !NT_SUCCESS( status ) )
{
    TraceEvents( TRACE_LEVEL_ERROR, DBG_INIT, "WdfDmaEnablerCreate() failed with status=[%!STATUS!]", status );
}

Driver Device Process IOCTL:

void EvtIoInCallerContext( IN WDFDEVICE  device, IN WDFREQUEST  request )
  // Get the outbuffer from the IOCTL request
  WDFMEMORY outputBufferObj{ nullptr };
  WdfRequestRetrieveOutputMemory( request, &outputBufferObj );

  // Get the outbuffer size. Note: outBuffP not actually needed, we just want the size.
  PVOID outBuffP = WdfMemoryGetBuffer( outputBufferObj, &outBuffByteSize );

  // Get the MDL from the outbuffer
  WdfRequestRetrieveOutputWdmMdl( request, &hostMemoryMdlP );

  // Get the DMA adapter.
  PDMA_ADAPTER dmaAdapter = WdfDmaEnablerWdmGetDmaAdapter( myDmaEnabler,
                                                           WdfDmaDirectionReadFromDevice );

  // Get the Kernel Virtual Address for the MDL
  hostMemoryKvaP = MmGetSystemAddressForMdlSafe( hostMemoryMdlP, 
                                                                 HighPagePriority );

  // Get the SG List size
  dmaAdapter->DmaOperations->CalculateScatterGatherList( dmaAdapter,
                                                         hostMemoryMdlP, 
                                                         hostMemoryKvaP,
                                                         hostMemoryMdlP->ByteCount,
                                                         &sgByteSize, 
                                                         &numMapRegisters );
  // Allocate memory for the SG List
  PVOID scatterGatherListBuffP{ nullptr };
  WdfMemoryCreate( &buffAttributes, PagedPool, 0,
                   static_cast<size_t>( sgByteSize ),
                   &scatterGatherMemoryObj, &scatterGatherListBuffP );

  // Get the Device Object
  PDEVICE_OBJECT deviceObjectP = WdfDeviceWdmGetDeviceObject( device );

  // Get the SG List
  dmaAdapter->DmaOperations->BuildScatterGatherList( dmaAdapter, deviceObjectP,
                                                                hostMemoryMdlP, hostMemoryKvaP, 
                                                                static_cast<ULONG>( outBuffByteSize ),
                                                                &(MyAdapterListControl), deviceContextP, FALSE,
                                                                scatterGatherListBuffP, sgByteSize );