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!
Log output:
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