Alignment of buffer from AllocateCommonBuffer

I have a bus master dma device which cannot work across a 32MB physical
address boundary. I am allocating a common buffer for the dma, and it
occasionally lands across a 32MB boundary. Our fix has been to allocate
twice what we need (we need ~700 kB, so allocate 1.4MB), and use a half that
does not land on the 32MB boundary. This seems wasteful.

Another possible fix is to keep allocating correctly sized buffers until we
get a “good” one, and then free the rest.

There is an AlignmentRequirement field in the device object that seems like
it should help, but it only allows alighment up to 512 bytes.

Any other ideas?

Niels Jensen

Niels Jensen wrote:

I have a bus master dma device which cannot work across a 32MB physical
address boundary.

Weeeelllll… it gets ugly. The only function that I’m aware of
that’ll let you allocate memory with the alignment requirement that you
need is MmAllocateContiguousMemorySpecifyCache.

If you MmAllocateContiguousMemory, and then call MmGetPhysicalAddress,
it’ll work but you’ll be violating the Windows DMA abstraction with no
guarantee that your code will work in future.

OTOH, if you try to be good and follow the DMA abstraction, and build an
MDL that describes the allocated region and pass that into
AllocateAdapterChannel (returning “DeallocateObjectKeepRegisters” from
your execution rutine), that’ll only work if your device has been
declared as supporting scatter/gather via the DEVICE_DESCRIPTION data
structure.

In either case, you wind up with code that’s difficult to document and
which relies on the intracacies of the current implementation of the
Windows standard DMA components.

So, you’re damned if you do and damned if you don’t.

Have you tried allocating a few 700K blocks in a loop, and checking the
alignment of each, to see if you can get one that coincidentally will
meet your alignment requirement?? i.e.

while (maxTries–) {

goodBuffer = AllocateCommonBuffer(“the size you need”);

if ( “buffer meets alignment requirement”) {
break;
} else {
unalignedBuffer[i++]=buffer;
}
}

for(j=0;j _ReturnCommonBuffer(unalignedBuffer[j]);
}

if(goodBuffer == NULL) {
goodBuffer = AllocateCommonBuffer(“twice the size”);
bigBufferUsed = TRUE;
}

If you prototype that and find it doesn’t ever do any good, I’d do what
you’re doing now. That’s life in the driver business,

Peter
OSR_