Disclaimer: this text came from TWiki, and I converted it by hand and in a rush. So, some things may be fscked up. :-)
And what's more, there is a stupid MicKI bug - this page isn't generated succesfully (it ends abruptly). I'll fix it some day
(famous last words).
DMA allows devices to do memory transfers without CPU intervention. What follows here
is a summary of some random documents I fished off the net. Have fun!
(See
http://www.infran.ru/TechInfo/BSD/handbook257.html and beyond.)
I spose this comes from the
FreeBSD handbook, section 22.3,
but couldn't be arsed to verify :-)
This text focuses on the IBM PC's DMA subsystem
(See
http://www.infran.ru/TechInfo/BSD/handbook257.html.)
The PC's DMA system uses an Intel 8237 DMA controller (
DMAC hereafter) or similar. It
has 4 independently
programmable channels. More channels may be active simultaneously. Later PC's came with
a 2nd DMAC (channels 4..7), which could move 16 bits at a time (old one only 8).
DMACs 1 and 2 are identical but have different pin wiring, determining mode.
The 8237 basically has this pin configuration, for each channel:
* general signals
* DRQ (DMA ReQuest)
* DACK (DMA ACKnowledge)
* additional signals
* HRQ (Hold ReQuest)
* HLDA (HoLD Acknowledge)
* EOP (End Of Process)
* bus control signals
* MEMR (MEMory Read)
* MEMW (MEMory Write)
* IOR (I/O Read)
* IOW (I/O Write)
The 8237 is a so-called
fly-by DMAC: transfered data does not pass through the
DMAC itself, and is not stored in the DMAC. An implication of this (looking at
the pinout) is that
transfers can only take place between I/O and memory. The 8237
itself is well capable of I/O-I/O or mem-mem by coupling 2 channels, but hard wired not
to do so in the PC architecture, since mem-mem using CPU is faster.
(See
http://www.infran.ru/TechInfo/BSD/handbook258.html#410.)
In this example, the FDC wants to transfer a byte to memory 0x00123456. (FDC happens to use
DMA channel 2 in PC.) The chain of events is like this:
- FDC asserts DRQ2
- DMAC will make sure DMA channel 2 has been programmed and enabled, and no other channels are active or have higher priority.
- DMAC asks CPU to release the bus so that DMAC may use it, by asserting HRQ pin, connected to CPU.
- CPU detects HRQ, and releases the bus as soon as it can. MEMR, MEMW, IOR, IOW etc which are normally CPU-generated are tri-stated
- CPU asserts HLDA, telling DMAC it is now in charge of the bus
- CPU can do some instructions that don't use the bus, but will block on instructions that do, until DMAC is done
- DMAC controls MEMR, MEMW, IOR, IOW, and 16-bit address outputs are set to 0x3456 (destination address lo-word).
- DMAC notifies initiating device (FDC) that transfer is beginning: asserts DACK2
- FDC places byte to transfer on data bus
- assuming FDC is fast enough (there's some READY-pin on DMAC to let FDC stall it?), DMAC waits one DMA clock, inhibit MEMW and IOR, so that memory will latch/store FDC's byte;
- FDC sees MEMW/IOR being inhibited, indicating transfer is done
- FDC inhibits DRQ2 to indicate to DMAC it's no longer needed
- DMAC inhibits DACK2 to indicate to FDC to stop placing data on bus (..?)
- DMAC checks if there are other channel transfers pending
- if not, it tri-states MEMR, MEMW, IOR, IOW
- DMAC will inhibit HRQ
- CPU will notice this, and inhibits HOLDA
- CPU activates MEMR, MEMW, IOR, IOW lines and address lines, and resumes execution
For a floppy sector, the above transfer (8-bits at a time) is repeated 512 times. The DMAC
internal address- and counter registers are updated.
When
counter register reaches zero, DMAC asserts EOP, indicating data transfer has completed;
this event is called
TC (Terminal Count) event. There is only 1 EOP signal, since only 1 DMA
channel may be active at any time.