I’ve briefly explained Direct Memory Access, and then applied it specifically to Windows and graphics cards, however, this blog post will take a look at the general aspect of Direct Memory Access and how it works.
Direct Memory Access (DMA) enables devices to be able to directly access and transfer data between the device’s bus or own memory and RAM within the need of interrupting the CPU, and using the CPU to complete such operations. Traditionally, without the use of DMA, the CPU would use PIO (Programmed I/O) and be fully occupied with this operation for the duration of the read or write transfer operation. DMA removes this, and enables the CPU to complete other tasks. Although, the CPU still has to initiate the transfer, and will receive a interrupt to show that DMA transfer has completed.
Typically, there are two types of DMA implementations: ISA and PCI. These two implementations work differently from each other, with PCI using the concept of Bus Mastering or first-party DMA, and ISA using a DMA controller resulting in the concept of third-party DMA.
ISA DMA Internals
I’ll start firstly with concept of the DMA controller, even though it’s pretty much obsolete, and is only used on motherboards with old ISA buses. I will not speak much about the old version of Direct Memory Controller, since it’s a old technology and most likely will never debug a system using this.
The DMA Controller is called the ISA Direct Memory Access Controller or DMAC. The DMAC connects the devices to Channels. Each Channel consists of two parts: DMA Acknowledge (DACK) and DRQ (DMA Request).
|Simplified DMA Controller Diagram|
With the DMAC, there is currently 8 different channels, with the method of connecting two different DMACs together, to create a Master and Slave configuration. Each Channel was assigned to a different device, with some being created for a specific device, like Channel 2 being used for the FDC (Floppy Disk Controller).
Channel 0: Reserved for system use.
Channel 1: Available
Channel 2: Floppy Disk Controller
Channel 3: Hard Disk Controller
Channel 4: Slave DMAC input to Master DMAC
Channel 5: Available
Channel 6: Available
Channel 7: Available
The Channels which are marked Available can be used for any device. Due to the limitations of the DMAC, the above Channels would used by two DMACs like in the diagram below.
The HOLD (Hold Acknowledge) and HLDA pins are used to take control of the ISA bus for DMA transfers. The HOLD pin is signaled by the Master DMAC to request control, and the HLDA pin is signaled by the processor to acknowledge and accept this request.
You may notice the TC (Terminal Count line) and a OR gate. The result of the OR Gate depends upon the condition sent by the Master DMAC and the Slave DMAC. The TC line will be raised, when the transfer request sent to the DMAC has been completed. Using the knowledge about Truth Tables, two truths (two 1’s) will output a truth or 1.
There is some important aspects to remember with DMA on ISA implementations. DMA can only access physical memory addresses, and therefore will never to be able to access virtual memory addresses. Furthermore, the Master DMAC can access 16-bits, whereas, the Slave DMAC can access 8-bits for transfers. DMAC0 is the Slave and DMAC1 is the Master. All registers are 16-bits.
Port Mapping and Registers
With operating system kernel development, these generic registers are usually defined with a enumeration for easier readability when writing the code.These registers are used to set certain settings for the DMA Controllers, such as clearing the flip flop register to it’s original state, this is important for when your doing 16-bit transfers on the Slave DMAC.
The Channel Ports use Port-Mapped I/O which separates a device address space from memory, each port is used to access a certain device. To use these ports, you would need to use the Intel In (Input from Port) and Out (Output from Port) instructions.
Each Channel Port is separated into a base address and a counter. The base address is used to find the location in memory where to read or write to, and the counter is used to show much is being transferred on that channel.
Please note that I haven’t shown all the registers, and will provide references if your interested.
Operation Modes are used to define how data will be transferred using DMA, the three types of operation are: Burst Mode, Cycle Stealing Mode and Transparent Mode.
Burst Mode: Data is transferred in one complete contiguous sequence, which causes the CPU to become inactive until the DMAC transfers control back to the CPU. The control is transferred using Bus Request (BR) and Bus Grant (BG) signals.
Cycle Stealing Mode: The DMAC transfers one byte at a time and transfers control back to the CPU, this process is continously repeated with BG and BR signals until the data transfer is complete. This is used to stop the CPU from being completely idle, which can comprise system performance since nothing can executed by the CPU.
Transparent Mode: The DMAC only transfers data when the CPU is idle in terms of not executing any instructions related to any buses. The DMAC will need to work out when the CPU is idle which can be complicated.
The second part of this blog post will take a look at the PCI DMA and the concept of first-party DMA. Again, you can find more information in the References section, I chose not to explain all of ISA DMA since it’s a old and almost obsolete technology which only used in old Windows systems.