What is DMA (part 7) – Scatter Gather DMA the "new" way

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.



Comments (2)
  1. Hi Peter

    I’ve followed your articles and I’ve liked very much. I’m asking myself about wich will be the next subject.

    In respect of your post. It may be difficult to maintain projects that need to run over Windows NT or even over Windows 98 and Windows Me which don’t implement GetScatterGatherList.

    Have you seen any circumstance like this or the old versions of Windows are dead?

    Sorry my English.

  2. PeterWieland says:

    Thank you.

    Yes we see this issue all the time.  It’s an unfortunate side effect of adding new functionality that it may not be usable by everyone.  There are functions like MmGetSystemRoutineAddress and IoIsWdmVersionAvaialble that can let you handle this (by late-binding your DLL imports if they’re available or falling back to older behavior if not).  But it’s never pleasant when you have to do this.


Comments are closed.

Skip to main content