Yesterday i talked about how to do your DMA operations the old way.  And it's painful.  Very, very painful.  Fortunately for those of you with bus-mastering controllers there's a much easier way.


AllocateAdapterChannel suffers from some real problems.  It can't fail if the system is low on memory, so it can't allocate memory in order to track more than one request at a time.  It was designed to manage slave-mode devices and that makes it clumsy for more modern controllers.  Fortunately there's an alternative - GetScatterGatherList (and it's cousin BuildScatterGatherList, which i'll discuss tomorrow).

GetScatterGatherList replaces both the AllocateAdapterChannel and MapTransfer methods.  It allocates the scatter-gather list for you and fills it in so your AdapterListControl routine (equivalent of the ExecutionRoutine) only has to start the transfer.  When you're done you call PutScatterGatherList to flush the buffers and free the map registers.

Additionally since GetScatterGatherList does allocate memory, it can keep track of more than one request for mapping at a time.  This means you don't need to serialize your calls to it (though you still need to call it at DISPATCH_LEVEL).

Finally GetScatterGatherList will handle chained MDLs as long as the sum total of map registers required by all the MDLs doesn't exceed the number you allocated.  This is another terrific simplification.

So what's the downside of calling GetScatterGatherList?  There are two - one small and one big.  The small disadvantage is that it does a bunch of work up front to map the transfer.  If you absolustely must map in small chunks to get your transfer started faster then AllocateAdapterChannel+MapTransfer is the better choice.  Still this isn't a big deal.

The much bigger problem is that GetScatterGatherList allocates memory, which means that it can fail if resources are low.  If your driver is trying to ensure forward progress in low memory conditions (meaning you don't just fail when you can't allocate pool) then GetScatterGatherList is going to be a problem.  Fortunately there's an alternative - BuildScatterGatherList - which i'll talk about next time.

So to summarize - forget everything i said last time about AllocateAdapterChannel & MapTransfer.  It's far too complicated and provides little benefit.  [Get|Build]ScatterGatherList is a much better option.

-p