Three Modes of Transfer
Data between memory and an I/O device can be transferred in three ways, differing in who supervises the transfer and what the CPU does meanwhile.
1. Programmed I/O
The CPU executes a program that:
1. reads the device STATUS register,
2. tests the ready/flag bit,
3. loops back if not ready (this loop is called POLLING or BUSY WAITING),
4. transfers one word when ready,
5. repeats for the next word.
Typical loop:
LOOP: IN STATUS ; read the status register
AND #01H ; mask the "ready" bit
BZ LOOP ; not ready -> poll again
IN DATA ; ready -> read the data byte
STA BUFFER ; store it in memory
INC POINTER
DEC COUNT
BNZ LOOP ; more bytes to go
The flag mechanism
1. The interface sets its FLAG bit when the device has data ready.
2. The CPU keeps reading the status register until it sees flag = 1.
3. The CPU reads the data register — reading it CLEARS the flag.
4. The interface can now accept the next item from the device.
The cost
Q: A keyboard delivers 10 characters per second. The CPU runs at
1 GHz and the polling loop takes 5 instructions (5 ns).
Time available per character = 100 ms
Time actually needed = 5 ns
CPU utilisation for useful work = 5ns / 100ms = 0.000005 %
The CPU spends 99.999995% of its time in the polling loop
doing NOTHING.
Verdict: programmed I/O is simple and needs no extra hardware, but it wastes the CPU almost entirely. It is used only in small embedded systems, in bootloaders, and where the device is nearly as fast as the CPU.
2. Interrupt-Driven I/O
Instead of the CPU asking "are you ready?", the DEVICE says
"I am ready" by asserting an INTERRUPT REQUEST line.
The CPU:
- runs other programs while the device is busy,
- is interrupted when the device becomes ready,
- suspends the current program, saves its state,
- executes an INTERRUPT SERVICE ROUTINE (ISR) that transfers the word,
- restores the saved state and resumes the interrupted program.
The interrupt cycle
1. Device asserts the interrupt request line.
2. CPU finishes the CURRENT INSTRUCTION (interrupts are checked at
instruction boundaries, never mid-instruction).
3. CPU saves PC and the status flags (usually on the stack).
4. CPU disables further interrupts (IEN <- 0).
5. CPU determines WHICH device interrupted (polling, daisy chain
or vectored interrupt).
6. CPU branches to the ISR address.
7. ISR transfers the data and clears the device flag.
8. ISR ends with a RETURN FROM INTERRUPT that restores PC and flags
and re-enables interrupts.
Identifying the interrupting device
| Method | How it works | Speed |
|---|---|---|
| Software polling | The ISR reads each device's status in priority order | Slow (n reads) |
| Daisy chaining | Hardware priority chain; the winner places its vector on the bus | Fast |
| Parallel priority | A priority encoder + mask register produces the vector | Fastest |
| Vectored interrupt | The device supplies its own ISR address directly | Fastest |
Types of interrupt
EXTERNAL : from I/O devices, timers, power failure
INTERNAL (traps/exceptions): divide by zero, invalid opcode,
stack overflow, page fault — caused by the program itself
SOFTWARE : deliberately caused by an instruction (INT n, SVC, syscall)
— the standard mechanism for system calls
MASKABLE : can be disabled by the CPU (most device interrupts)
NON-MASKABLE (NMI): cannot be disabled — power failure, hardware fault
3. Direct Memory Access (DMA)
In BOTH previous modes the data passes THROUGH the CPU:
Device -> CPU register -> Memory (two bus transfers per word)
DMA removes the CPU from the path entirely:
Device -> Memory (one bus transfer per word)
A DMA CONTROLLER takes over the buses and performs the transfer.
The next lesson covers DMA in full. In this comparison, note only the essentials:
1. CPU programs the DMA controller: start address, word count, direction.
2. CPU resumes other work.
3. DMA controller requests the bus (BUS REQUEST / HOLD).
4. CPU relinquishes the bus (BUS GRANT / HLDA) and floats its bus drivers.
5. DMA controller transfers the whole block directly to/from memory.
6. DMA controller interrupts the CPU when the block is complete.
4. Complete Comparison
| Basis | Programmed I/O | Interrupt-driven I/O | DMA |
|---|---|---|---|
| Who initiates | CPU (polls) | Device (interrupts) | Device, via the DMA controller |
| CPU involvement | Total — every word, plus waiting | Per word, but no waiting | Only at start and end of the block |
| CPU idle time | Enormous (busy waiting) | None | None |
| Data path | Device → CPU → Memory | Device → CPU → Memory | Device → Memory |
| Transfers per word | 2 bus cycles | 2 bus cycles | 1 bus cycle |
| Speed | Slowest | Medium | Fastest |
| Extra hardware | None | Interrupt logic | DMA controller |
| Overhead per word | Polling loop | Context save/restore | None |
| Best for | Very slow or very simple devices | Moderate-rate devices; unpredictable timing | High-speed block devices (disk, network, graphics) |
| Example | Reading a switch | Keyboard, mouse, UART | Disk, SSD, NIC, sound card |
5. Which Mode to Choose
Device is slower than the CPU by a huge factor,
and transfers are single bytes at unpredictable times
-> INTERRUPT-DRIVEN I/O
Device transfers LARGE BLOCKS at high speed
-> DMA
Device is simple, the system is tiny, or you are in a boot loader
where interrupts are not yet set up
-> PROGRAMMED I/O
6. Worked Comparison Numerical
A disk transfers 4 KB blocks at 4 MB/s. The CPU runs at 1 GHz.
An interrupt costs 500 cycles of overhead; a programmed-I/O
transfer of one word costs 20 cycles.
PROGRAMMED I/O (4-byte words):
Words per block = 4096 / 4 = 1024
Cycles = 1024 x 20 = 20,480 cycles per block, PLUS the CPU
must poll for the entire transfer duration (1 ms) = 1,000,000 cycles.
-> essentially 100% CPU usage.
INTERRUPT-DRIVEN (one interrupt per word):
1024 interrupts x 500 cycles = 512,000 cycles per block = 51% CPU.
DMA (one interrupt per block):
1 interrupt x 500 cycles = 500 cycles per block = 0.05% CPU.
This is why every modern high-speed device uses DMA. The next lesson looks at how the CPU sorts out which interrupt to service first when several arrive at once.