Blumrich et al. described one of the first user-level DMA solutions [2], developed in conjunction with the SHRIMP prototype. In SHRIMP, each page that is used for communication, is ``mapped out'' to another page in a different workstation. In this DMA mode of operation, if a local page is used as the source argument in a DMA operation, the destination argument will always be its mapped-out page. To start a DMA operation, an access to a shadow address is performed. This access, passes to the DMA engine, the source address, the destination address (the ``mapped out'' page), the size of the DMA, and returns the success/failure of the DMA initiation. All this information is passed by using a compare-and-exchange atomic instruction. The address argument of the instruction is the source address, the data argument of the instruction is the size of the transfer, and the return value is used to determine if the DMA operation has started correctly.
This solution, although correct, is of limited functionality. A DMA operation can happen only between a page and its mapped out counterpart, which is very restrictive in practice. To achieve arbitrary user-level DMA transfers, the mapping between a page and its ``mapped-out'' page would have to change, which would result in significant operating system overhead.