IBM PC DMA Addressing
This note explains specific details of the PC's DMA address-line manipulation.
Building on its predecessor which had only four 8-bit DMA channels, the AT-architecture version of the PC added a second DMA controller to provide three extra channels. Each of the new channels is for 16-bit transfers.
Both controllers support four channels but in the second controller one channel is dedicated to 'cascade' control signals from the first controller. Hence there are only three 16-bit channels available rather than four.
There is much potential for confusion surrounding the way that the DMA chips are connected to the rest of the PC. This note attempts to clear up that confusion. It may help to review this material before and after looking at tutorials on the topic.
IBM's design used three different chip types all of which are used in a DMA transfer:
- 8537A-5 DMA controller
- ALS573 address latch
- LS612 page register
IBM also played a few tricks with how they were connected to the motherboard. Programming these or their descendants today is not a problem as long as that wiring is understood.
The notes below include information from The Undocumented PC - A Programmer's Guide to I/O, CPUs, and Fixed Memory Areas, Frank van Gilluwe, the IBM Personal Computer/AT Technical Reference, and The Indispensable PC Hardware Book, Hans-Peter Messmer.
First things first. The assignment of DMA channels isFirst DMA chip (8-bit)
|0||Unassigned (was used for DRAM refresh in the original IBM Personal Computer)|
|3||Hard disk or unused|
|4||Not usable - dedicated to receive signals from the first DMA chip (and Channel 4's page register used for DRAM refresh)|
|5||Unassigned (would be used for hard disk DMA later in PS/2 models)|
Although one DMA chip manages 8-bit transfers and the other manages 16-bit transfers both chips are of exactly the same type, i.e. they are 8237A DMA controllers. The difference in transfer width results not from anything intrinsic with the chips but from how they are connected to the address bus. This has implications for the locations of their registers as well as how they are programmed.
Each 8237 has only eight address lines which we will call DMA-A7 through DMA-A0. The 8237 is designed to work with an external address latch to provide DMA-A15 through DMA-A8 resulting in 16 address lines. To provide further address lines for each channel (24 in total) IBM added another chip to the PC, a DMA page register. There is one page register for each channel. These features and the number of internal registers of the 8237 itself make programming the DMA one of the more challenging aspects of the PC architecture to understand. One issue is the anomaly as to how the chips are connected to the address bus.
- How are they connected?
Using the name 'Sys-A0' for system address line 0 etc the DMA controllers, DMA address latches and DMA page registers are wired as follows. Note carefully the differences between 8-bit and 16-bit wiring.
+- DMA-A0 --- Sys-A0 | DMA-A1 --- Sys-A1 | DMA-A2 --- Sys-A2 8237A ----- + DMA-A3 --- Sys-A3 (DMA controller) | DMA-A4 --- Sys-A4 | DMA-A5 --- Sys-A5 | DMA-A6 --- Sys-A6 +- DMA-A7 --- Sys-A7 +- DMA-A8 --- Sys-A8 | DMA-A9 --- Sys-A9 | DMA-A10 --- Sys-A10 ALS573 ----- + DMA-A11 --- Sys-A11 (address latch) | DMA-A12 --- Sys-A12 | DMA-A13 --- Sys-A13 | DMA-A14 --- Sys-A14 +- DMA-A15 --- Sys-A15 +- PR-A16 --- Sys-A16 | PR-A17 --- Sys-A17 | PR-A18 --- Sys-A18 LS612 ----- + PR-A19 --- Sys-A19 (page register) | PR-A20 --- Sys-A20 | PR-A21 --- Sys-A21 | PR-A22 --- Sys-A22 +- PR-A23 --- Sys-A23
--- Sys-A0 (forced to zero) +- DMA-A0 --- Sys-A1 | DMA-A1 --- Sys-A2 | DMA-A2 --- Sys-A3 | DMA-A3 --- Sys-A4 8237A ----- + DMA-A4 --- Sys-A5 (DMA controller) | DMA-A5 --- Sys-A6 | DMA-A6 --- Sys-A7 | +- DMA-A7 --- Sys-A8 +- DMA-A8 --- Sys-A9 | DMA-A9 --- Sys-A10 | DMA-A10 --- Sys-A11 | DMA-A11 --- Sys-A12 ALS573 ----- + DMA-A12 --- Sys-A13 (address latch) | DMA-A13 --- Sys-A14 | DMA-A14 --- Sys-A15 | +- DMA-A15 --- Sys-A16 +- PR-A16 --- (not connected) | PR-A17 --- Sys-A17 | PR-A18 --- Sys-A18 LS612 ----- + PR-A19 --- Sys-A19 (page register) | PR-A20 --- Sys-A20 | PR-A21 --- Sys-A21 | PR-A22 --- Sys-A22 +- PR-A23 --- Sys-A23
Note that for 16-bit DMA
- The DMA chip's address line A0 is wired to system address line A1. This means that the 16-bit DMA chip can only generate even addresses. It cannot generate a bit on system address line A0. Since the DMA controller's address lines are used when selecting one of its internal registers they too cannot occupy odd-numbered I/O port addresses. Its I/O ports (while still being 8-bit ports) therefore appear to be two bytes apart.
- Like the DMA controller the DMA address latch is also wired one bit higher. It has to be so that the addresses the DMA controller and address latch pair generates are consistent. Between them they generate 16 bits of the address, A16 down to A1 rather than the 16 bits of the 8-bit registers A15 down to A0.
- The 16-bit DMA page registers are not wired one bit higher. Instead their A16 lines are unused. Otherwise they are connected as are those for 8-bit transfers. Thus the total range of 16-bit DMA is still 24-bit (i.e. 16MiBytes) rather than 25-bit (32MiBytes).
It should be noted that the term 'page' in DMA transfers is not related to 'page' or 'paging' in CPU memory management terms. DMA pages are simply ranges in which the page register retains a given value. Each DMA page is 16 bits in width giving sizes of 64K or 128K bytes depending on whether you are using 8-bit or 16-bit transfers.
- Setting DMA addresses
In the above diagrams the lines beginning "DMA" are programmed into the DMA controllers. Those beginning "PR" are programmed into the page registers.
Given the above connections how are addresses loaded to the registers? By way of example we will show code for 8-bit channel 2 (used for the PC's floppy disk) and 16-bit channel 5. In each case the address to be loaded for DMA is to come from EBX and is assumed to fit in the PC's DMA range, i.e. 24 bits. Note that the following is pseudo-code purely to illustrate the programming of addresses. In reality the byte values would be moved to AL prior to being output. There is not really an "OUT …,BH" instruction, for example.
8-bit DMA address setup
out 0x0C,AL ;Reset byte flip-flop (see note 1, below) out 0x04,BL ;Set address bits 7 down to 0 out 0x04,BH ;Set address bits 15 down to 8 (see note 2, below) shr EBX,16 ;Shift the octets down out 0x81,BL ;Put address bits 23 down to 16 in the page register
Note 1: An output to port 0x0C simply resets the DMA's internal byte flip-flop. The value written to the flip-flop is unimportant as it is ignored by the DMA controller. See note 2.
Note 2: Both of the lower address bytes are written to the same port. The 8237A alternately stores the byte written to this port into the low and high bytes of its internal address register. Resetting the DMA's byte flip-flop ensures that it expects to receive the lower byte next.
Note 3: The third address byte is written to the page register, not to the DMA controller.
Note 4: Nothing is written to the DMA address latch. It will be programmed by the DMA controller as needed.
The meaning of addresses such as 0x0C used in the above code will be explained later. For now the comments should make their function clear.
16-bit DMA address setup
shr EBX,1 ;Divide address by 2 jc bad_address ;If it was odd we cannot program it out 0xD8,AL ;Reset byte flip-flop (see note 1, below) out 0xC4,BL ;Set address bits 8 down to 1 out 0xC4,BH ;Set address bits 16 down to 9 (see note 2, below) shr EBX,15 ;Shift the address down 15 bits (see note 3, below) and BL,0xFE ;Clear the low bit (see note 4, below) out 0x8B,BL ;Put 7 address bits 23 down to 17 to page register
Note 1: As for 8-bit there is a byte flip-flop to be reset. The value written does not matter.
Note 2: Again, both of the lower two address bytes are written to the same port, low-byte first then high byte, but this time the address lines written to the DMA controller are A16 down to A1. As with the 8-bit DMA controller these bits go in on DMA controller data lines 7 down to 0. Unlike its address bus connections the DMA controller is connected normally to the data bus, i.e. from D0 upwards.
Note 3: This completes a 16-bit shift.
Note 4: Clearing the low bit as shown here is not necessary. Even if set to 1 it will be ignored. It is reset here simply to emphasise that it is not used.
- Where are the DMA address and count registers?
There are two 8237A DMA controllers with four channels each. The address and count registers for each channel are 16-bit but the ports used to write them are 8-bit. In other words to write one of these 16-bit registers you must send the DMA two separate bytes one at a time. The 8-bit ports appear at the following addresses.8-bit DMA Controller
|8-bit I/O Port||Use|
|0x00||Channel 0 address|
|0x01||Channel 0 count|
|0x02||Channel 1 address|
|0x03||Channel 1 count|
|0x04||Channel 2 address|
|0x05||Channel 2 count|
|0x06||Channel 3 address|
|0x07||Channel 3 count|
|8-bit I/O Port||Use|
|0xC0||Channel 4 address|
|0xC2||Channel 4 count|
|0xC4||Channel 5 address|
|0xC6||Channel 5 count|
|0xC8||Channel 6 address|
|0xCA||Channel 6 count|
|0xCC||Channel 7 address|
|0xCE||Channel 7 count|
Note that the I/O port addresses of the 16-bit DMA controller have gaps between them. This is due to being wired to system address lines A1 upwards, as mentioned above. There is no other device in port address 0xC1, for example.
- Where are the DMA latch registers?
There are two ALS573 address latches (one per DMA controller). You do not need to program the DMA latch registers. Instead, the DMA controller will set and maintain a value in these as its work progresses. Each time it begins a new 256-byte (for 8-bit transfers) or 512-byte (for 16-bit transfers) block it will load the correct value into its DMA latch register.
- Where are the page registers?
Good question. Their locations are jumbled about and don't seem to make sense. The don't follow on from each other. There is a reason which is explained here. You don't need to know this but read on if you are curious.
The PC needs eight page registers, one for each DMA channel. The LS612 IC contains twice as many, i.e. sixteen page registers. Since not all of these were needed IBM was free to play another addressing trick. To select a page register for each of the eight DMA channels IBM fed the DMA Acknowledge (DACK) outputs from the 8237 DMA controllers (which are generated when servicing a transfer) in a peculiar way to the LS612 addressing inputs. Since there are sixteen page registers in the chip the LS612 has four address input bits. IBM wired these as follows.
- Bit 3 is taken direct from DACK4.
- Bit 2 is the NAND of DACK0 and one of the refresh signals. If DACK0 is active (low) or the refresh signal is low bit 2 would be high, otherwise bit 2 would be low.
- Bit 1 is the AND of DACK2 and DACK6. If either is active (low) bit 1 would be low, otherwise bit 1 would be high.
- Bit 0 is the AND of DACK3 and DACK7. If either is active (low) bit 0 would be low, otherwise bit 0 would be high.
You should be able to see the effects of the above mappings on bits 3 down to 0 in the following table. Remember that only one DACK can be asserted at a time. As well as hexadecimal the table shows the I/O port addresses in binary to make recognition easier. The effect of the mappings is that the locations of the page registers do not follow the normal ascending sequence. They appear at the I/O port addresses stated. It may be odd but that's the way it was set up. It is easy enough to deal with in code with a small array of constants.
- I/O Port SummaryPage Register Addresses
|DMA Channel||Page register||Address register||Count register||High page register*|
(*) The high page register is an EISA addition. See The Indispensable PC Hardware Book for details.Port Address Summary
The DMA controller IC occupies 16 ports as follows. Since 8-bit DMA is addressed from zero the port numbers given can be used directly. For 16-bit DMA double the port numbers (since it is wired from line A1, as explained above) and add the DMA chip's base address 0xC0.
|0x00 to 0x07||Address and command registers, as above|
For further information on DMA programming see the DMA Programming section of this wiki.