ReactOS  r74662
Implementation Notes

Concepts:

  • Map register

    Abstract encapsulation of physically contiguous buffer that resides in memory accessible by both the DMA device / controller and the system. The map registers are allocated and distributed on demand and are scarce resource.

    The actual use of map registers is to allow transfers from/to buffer located in physical memory at address inaccessible by the DMA device / controller directly. For such transfers the map register buffers are used as intermediate data storage.

  • Master adapter

    A container for map registers (typically corresponding to one physical bus connection type). There can be master adapters for 24-bit address ranges, 32-bit address ranges, etc. Every time a new DMA adapter is created it's associated with a corresponding master adapter that is used for any map register allocation requests.

  • Bus-master / Slave DMA

    Slave DMA is term used for DMA transfers done by the system (E)ISA controller as opposed to transfers mastered by the device itself (hence the name).

    For slave DMA special care is taken to actually access the system controller and handle the transfers. The relevant code is in HalpDmaInitializeEisaAdapter, HalReadDmaCounter, IoFlushAdapterBuffers and IoMapTransfer.

Implementation:

  • Allocation of map registers

    Initial set of map registers is allocated on the system start to ensure that low memory won't get filled up later. Additional map registers are allocated as needed by HalpGrowMapBuffers. This routine is called on two places:

    • HalGetAdapter, since we're at PASSIVE_LEVEL and it's known that more map registers will probably be needed.
    • IoAllocateAdapterChannel (indirectly using HalpGrowMapBufferWorker since we're at DISPATCH_LEVEL and call HalpGrowMapBuffers directly) when no more map registers are free.

    Note that even if no more map registers can be allocated it's not the end of the world. The adapters waiting for free map registers are queued in the master adapter's queue and once one driver hands back it's map registers (using IoFreeMapRegisters or indirectly using the execution routine callback in IoAllocateAdapterChannel) the queue gets processed and the map registers are reassigned.