Lesson 43 of 48 advanced

8237 DMA Controller

Data Transfer Without CPU Overhead

Open interactive version (quiz + challenge)

Real-world analogy

Imagine you are a manager (CPU) who normally carries every box from the warehouse (memory) to the shipping dock (I/O device) yourself — one box at a time, reading the label, picking it up, walking over, putting it down. The 8237 DMA is like hiring a forklift driver who takes over: you tell him 'move 1000 boxes from aisle 5 to the dock,' and he does it all while you sit at your desk doing other paperwork. You only lend him your hallway (bus) while he works.

What is it?

The 8237 DMA Controller enables peripheral devices to transfer data directly to/from memory without CPU involvement. It has 4 channels, each with address and count registers. When a device asserts DREQ, the 8237 requests the bus from the CPU (HRQ/HLDA), then autonomously generates addresses and control signals to move data. It supports single, block, demand, and cascade transfer modes, freeing the CPU for other tasks during bulk data movement.

Real-world relevance

Every modern computer uses DMA extensively. When you copy a large file, the disk controller uses DMA to move data to RAM without CPU intervention. Your sound card uses DMA to stream audio samples. Network cards use DMA to receive packets. Modern DMA controllers are far more capable than the 8237 (scatter-gather lists, virtual addresses), but the fundamental concept — letting hardware move data without the CPU — is identical.

Key points

Code example

; =============================================
; 8237 DMA — Floppy Disk Read Setup
; =============================================
;
; Transfer 512 bytes from floppy to memory at 1000h
; Using DMA Channel 2 (IBM PC floppy channel)
;
; Disable DMA channel 2 during setup:
  MOV AL, 06h           ; mask CH2 (04h + 02h)
  OUT 0Ah, AL           ; single mask register
;
; Set mode: single transfer, write (device→mem), CH2
  MOV AL, 46h           ; 01 0 0 01 10
  OUT 0Bh, AL           ; mode register
;
; Clear byte pointer flip-flop:
  MOV AL, 00h
  OUT 0Ch, AL           ; resets LSB/MSB toggle
;
; Set start address = 1000h:
  MOV AL, 00h           ; address LSB
  OUT 04h, AL           ; CH2 address register
  MOV AL, 10h           ; address MSB
  OUT 04h, AL
;
; Set count = 511 (transfers 512 bytes):
  MOV AL, 0FFh          ; count LSB (01FFh)
  OUT 05h, AL           ; CH2 count register
  MOV AL, 01h           ; count MSB
  OUT 05h, AL
;
; Set page register = 0 (physical page 0):
  MOV AL, 00h
  OUT 81h, AL           ; CH2 page register
;
; Enable DMA channel 2:
  MOV AL, 02h           ; unmask CH2
  OUT 0Ah, AL
;
; DMA is armed!
; Now send 'read sector' command to floppy controller
; FDC will assert DREQ2 for each byte
; 8237 handles the entire 512-byte transfer
; CPU is FREE to do other work
; When done: TC asserted → interrupt via IRQ6

Line-by-line walkthrough

  1. 1. Title comment for floppy disk DMA setup
  2. 2. Separator line
  3. 3. Blank line
  4. 4. Description: transfer 512 bytes from floppy to memory address 1000h
  5. 5. Using DMA Channel 2, which is the standard IBM PC floppy channel
  6. 6. Blank line
  7. 7. First, disable (mask) CH2 so we can safely modify its registers
  8. 8. 06h = mask bit set + channel 2 selection
  9. 9. Write to single mask register at port 0Ah
  10. 10. Blank line
  11. 11. Set the transfer mode for CH2
  12. 12. 46h = single transfer, write (I/O to memory), channel 2
  13. 13. Write to mode register at port 0Bh
  14. 14. Blank line
  15. 15. Clear the byte pointer flip-flop to ensure next write goes to LSB first
  16. 16. Any value written to port 0Ch clears the flip-flop
  17. 17. Write to clear flip-flop register
  18. 18. Blank line
  19. 19. Set the starting memory address to 1000h
  20. 20. First write LSB = 00h to CH2 address register at port 04h
  21. 21. Write LSB
  22. 22. Then write MSB = 10h
  23. 23. Write MSB — CH2 will start transferring to address 1000h
  24. 24. Blank line
  25. 25. Set byte count to 511 (8237 transfers count+1 bytes, so 511+1=512)
  26. 26. LSB of 511 (01FFh) is FFh
  27. 27. Write LSB to CH2 count register at port 05h
  28. 28. MSB is 01h
  29. 29. Write MSB — 8237 will transfer 512 bytes total
  30. 30. Blank line
  31. 31. Set the page register for physical address bits A16-A19
  32. 32. Address 1000h is in page 0 (A19-A16 = 0000)
  33. 33. Write to CH2 page register at port 81h
  34. 34. Blank line
  35. 35. Enable CH2 by clearing its mask bit
  36. 36. 02h = unmask channel 2
  37. 37. Write to single mask register — DMA is now armed and ready
  38. 38. Blank line
  39. 39. Comment: 8237 is waiting for DREQ2 from floppy controller
  40. 40. Comment: send read command to FDC to start the disk operation
  41. 41. Comment: FDC asserts DREQ2 each time a byte is ready
  42. 42. Comment: 8237 handles the complete transfer autonomously
  43. 43. Comment: CPU is free to execute other code during the transfer
  44. 44. Comment: terminal count triggers IRQ6 to notify CPU of completion

Spot the bug

; DMA CH1 transfer 256 bytes to address 2000h
;
  MOV AL, 45h          ; mode: single, write, CH1
  OUT 0Bh, AL
;
  OUT 0Ch, AL          ; clear flip-flop
;
  MOV AL, 00h
  OUT 02h, AL          ; CH1 addr LSB
  MOV AL, 20h
  OUT 02h, AL          ; CH1 addr MSB
;
  MOV AL, 00h          ; count = 256
  OUT 03h, AL          ; CH1 count LSB
  MOV AL, 01h
  OUT 03h, AL          ; CH1 count MSB
;
  MOV AL, 01h
  OUT 0Ah, AL          ; unmask CH1
Need a hint?
The count register should hold N-1 for N bytes. What value does 0100h represent?
Show answer
The count is loaded with 256 (0100h), but the 8237 transfers count+1 bytes. So this actually transfers 257 bytes, not 256. For 256 bytes, load count-1 = 255 = 00FFh. Fix: change count LSB to FFh (MOV AL, 0FFh) and count MSB to 00h (MOV AL, 00h).

Explain like I'm 5

Normally, if you want to move toys from one box to another, YOU have to pick up each toy and carry it. That takes all your time! DMA is like having a robot arm that moves the toys for you. You just tell the robot: 'Move 10 toys from the red box to the blue box.' The robot does all the carrying while you go play with other things. When the robot finishes, it taps you on the shoulder (interrupt) and says 'All done!'

Fun fact

The 8237 DMA controller could transfer data at about 1.6 MB/s in the original IBM PC — which was actually faster than the CPU could manage with programmed I/O loops. This speed advantage was crucial for floppy disk access: without DMA, the 4.77 MHz 8088 could barely keep up with the floppy data rate, and missed bytes would require re-reading the entire track. DMA made reliable floppy access possible on early PCs.

Hands-on challenge

Program the 8237 to transfer 1024 bytes from a hypothetical ADC (Analog-to-Digital Converter) device on DMA channel 1 into a memory buffer at physical address 28000h. Calculate the page register value, determine if the transfer crosses a 64KB boundary, and write the complete setup code including mode, address, count, page, and unmask.

More resources

Open interactive version (quiz + challenge) ← Back to course: Microprocessor A–Z