PrepareForDMA failing

I'm trying to prepare a buffer for DMA, but PrepareForDMA always fails with error 0xe00002c2 - kIOReturnBadArgument.

I've watched the WWDC20 session, but I'm not sure what I'm doing wrong - any help much appreciated!

Code Block c
constexpr auto bufferSize = 1024u;
struct DMABufferInfo {
    IOBufferMemoryDescriptor* descriptor;
    IODMACommand* command;
    uint32_t segmentsCount;
    IOAddressSegment segments[32];
    uint64_t flags;
};
struct Driver_IVars
{
    IOPCIDevice* device;
    DMABufferInfo bufferInfo;
}
...
kern_return_t
IMPL(Driver, Start)
{
/*
* Successfully opens device
* Writes to PCIDevice command register
*/
...
os_log(OS_LOG_DEFAULT, "Allocating buffer...");
    ret = IOBufferMemoryDescriptor::Create(
    kIOMemoryDirectionOut,
    bufferSize,
        0,
        &ivars->bufferInfo.descriptor
    );
    __Require(ret == kIOReturnSuccess, Exit);
ret = ivars->bufferInfo.descriptor->SetLength(bufferSize);
__Require(ret == kIOReturnSuccess, Exit);
os_log(OS_LOG_DEFAULT, "Creating IODMACommand...");
IODMACommandSpecification dmaSpecification;
bzero(&dmaSpecification, sizeof(dmaSpecification));
dmaSpecification.options = kIODMACommandSpecificationNoOptions;
dmaSpecification.maxAddressBits = 64;
    IODMACommand::Create(
ivars->device,
kIODMACommandCreateNoOptions,
&dmaSpecification,
&ivars->bufferInfo.command
);
    __Require(ret == kIOReturnSuccess, Exit);
    os_log(OS_LOG_DEFAULT, "Preparing For DMA...");
    ret = ivars->bufferInfo.command->PrepareForDMA(
kIODMACommandPrepareForDMANoOptions,
ivars->bufferInfo.descriptor,
0,
0,
&ivars->bufferInfo.flags,
&ivars->bufferInfo.segmentsCount,
ivars->bufferInfo.segments
);
__Require(ret == kIOReturnSuccess, Exit);
os_log(OS_LOG_DEFAULT, "Prepared buffer for DMA");
Exit:
os_log(OS_LOG_DEFAULT, "Exiting: %s, ret = %#010x",__FUNCTION__, ret);
return ret;
}


Log output:
Code Block none
Allocating playback buffer...
Creating IODMACommand...
Preparing For DMA...
Exiting: Start_Impl, ret = 0xe00002c2


Try setting ivars->bufferInfo.segmentsCount to 1 (or any non-zero value) before passing it to PrepareForDMA. That should stop the kIOReturnBadArgument issues.
Thanks Drewbadour - setting it to 1 didn't seem to work for me, but setting it to 32 did. Maybe it depends on the buffer size.
PrepareForDMA failing
 
 
Q