The I/O Bus, Interrupts and DMA

First off, remember that the I/O bus is really not that much different from the 'system' bus. I.e. it is really just a composition of data bus, address bus and control lines. Many years ago, the I/O bus and system bus were in fact one bus (or, to be more precise, just one collection of the aforementioned components). In modern computers, the huge difference in bandwidth requirements between components like memory and hard disks means that the computer, as a whole, can no longer be supported by the 'single bus' architecture. Hence why we now have an I/O bus in addition to a system bus.

The I/O bus allows the CPU and memory to be accessed by peripheral devices such as hard disks, floppy drives, sound cards, modems and network cards. These devices require much lower bandwidth than the memory bus and therefore run much more slowly. Some of these devices must be plugged into expansion slots on the motherboard, such as sound cards and modems. Other devices are integrated into the motherboard, yet still interface with the I/O bus. For example, floppy drives and serial ports use integrated ISA controllers; hard drives utilise integrated EIDE controllers which utilise PCI.

The following topics are covered on this page:

Input/Output (I/O) Addresses

Recall that when the CPU needs to access memory, the CPU specifies the address in memory where the required data resides. Similarly, when the CPU needs to talk to a peripheral device (or vice versa), that particular device has its own binary address. The device reserves a region in memory that is used to allow communication between the device and the rest of the system. However, rather than specifying the address of a single byte in memory, a device can have an I/O address range that covers several bytes. This is because some devices must move more data to and from memory than others. For example, COM1, a communications port that is a standard component on most IBM-compatible PCs uses the ISA bus (although it does not plug into an expansion slot) and has an I/O address range of 03F8-03FFH. This is an 8 byte address range. Similarly, a hard disk controller has an 8 byte range. Some devices use an even larger range. For example, one Ethernet network card in my computer has a 32 byte range, while my second Ethernet card has a 256 byte range.

Interrupt Request (IRQ)

In addition to the I/O address range allocated to a device, each device is also allocated an interrupt request (IRQ) line (aka Hardware Interrupt). These lines are an example of some of the control lines mentioned earlier. Anyone who has ever built a PC before the days of PCI and Plug and Play will know exactly why IRQ addresses are infamous and problematic.

I/O Strategies - polling, interrupts and DMA

Why would a hardware device need an IRQ line? To answer this question, you need to know the basics of the three methods by which a CPU 'services' the needs of a hardware device. These are polling, interrupts and DMA. (We will look at the latter in a while.)

Polling is a strategy whereby the CPU constantly looks to see if a device needs its attention. As an analogy, imagine a shop keeper who spends most of his time in the back office. He must constantly stop what he's doing in the back and visit the front of the shop to see if there are any customers that need serving. Back in the computer world, we can see that polling places high demands on the CPU. It must constantly waste cycles checking to see if a device needs its attention. (Note that the instructions to poll a device are usually part of a program being run by the CPU. Hence polling is also known as program-controlled I/O.)

Clearly, a much more efficient strategy is for the CPU to simply wait for another device to shout, "Oi, I need some attention over here!". So, an interrupt request is what device sends when it wants the attention of the CPU.

To avoid several devices attempting to talk to the CPU at the same time (and thereby stuffing up the system), each device is allocated a different IRQ input line.


Interrupts - How it Works

How does it work? The device sends a request via its dedicated IRQ line to the interrupt controller (more on this later) which forwards the request onto the CPU. There are 256 different types of request, and each is mapped to a program (either in software as part of the operating system, or in firmware on ROM BIOS) called an interrupt service routine or ISR for short. What actually happens is that each of the 256 possible interrupts is stored in a table right at the bottom of system memory called the interrupt vector table or IVT. This table has an entry for each type of interrupt request, and maps each to a pointer in memory. This pointer is simply an address in memory where that particular request's ISR is held. At boot time, the IVT is populated by the ROM BIOS and by the operating system. This strategy is a good one, because if the BIOS code or operating system changes, it is only necessary to change the addresses pointed to in the IVT. Otherwise, the whole interrupt system remains static.

When a device issues an interrupt to the CPU (via the controller), the CPU finishes whatever instruction it's currently working on, dumps all the register data relevant to the current program somewhere (such as the stack, or main memory), and then goes about performing the appropriate ISR. When the ISR is complete, the CPU restores its state to how it was before the ISR began and goes back to whatever program it was performing before it was interrupted.

Modern PCs based on the IBM AT architecture have 16 input lines, aka IRQ channels (0 through 15), while the original XT systems had only 8 (0 to 7). This is because the original interrupt controller only had 8 input lines. In order to increase the number of available input lines to support additional hardware, a second IRQ controller was added with the move to 16 bit ISA (more on this later). However, the second controller does not output directly to the CPU like the the first controller. Instead, it is cascaded to the first controller. This means that the second controllers output feeds into an input line on the first controller. So the CPU receives requests from channels 8 to 15 via the first controller. The consequence of this is that the second controller itself requires an IRQ channel: IRQ 2. Hence there are only 15 available channels, not 16. This does pose a backwards compatability question though: what happens to older hardware designed to use IRQ 2? Well, on the AT based systems, requests to IRQ2 actually get mapped to IRQ 9. (Rather than IRQ 2 signalling to the CPU via the ISA bus, it is wired directly to IRQ 9 of the second controller.) Therefore, to all intents and purposes, IRQs 2 and 9 are the same IRQ input.

Technically, lower IRQs have higher priority. I.e. IRQ 0 is at higher priority than 1, which is at higher priority than 2, and so on. (However, because the second controller is mapped to IRQ 2, the result is that IRQs 8 to 15 are all at a higher priority than IRQ 3.)

Why do computers use this priority system? Well, it's all about coordinating interrupts. Imagine the CPU has been interrupted by device A and has now started performing the ISR. If hardware device B has an IRQ line at a higher priority than A, then it could issue an interrupt which would interrupt the ISR the CPU is currently working on. The CPU would go about performing the new ISR. It would then return to the first ISR and then finally, back to the original program. However, if device B has a line at a lower priority than A, then its interrupt request would be ignored by the CPU until it had finished performing the first ISR.

In principle, this approach can be used to make sure that time-critical I/O happens promptly, while less important I/O would have to wait. In practice, on modern PCs, these priorities make little real difference.


Example IRQ Assignments

The following list shows the IRQ assignments in my computer (at least, as they were way back in 2002). As the list shows, 15 IRQs is very limiting indeed and is probably the main cause of hardware conflicts; at least it was the main cause before PCI and Plug and Play. If more than one ISA device is allocated to the same IRQ, an IRQ conflict will result. Sometimes we are forced to share IRQs however. For example, a once very common problem occured when running an ISA modem on COM3. COM3 actually shares its IRQ (4) with COM1. If a serial mouse was attached to COM1 and the modem was used, a common result was that the mouse stopped working! (I know I had this happen to me once-upon-a-time.) You will notice from the list that PCI devices are able to share IRQs (more on this later.)

IRQ Device
0 (ISA) System timer
1 (ISA) Cordless iTouch Pro Keyboard (PS/2)
2 (ISA) Programmable interrupt controller
3 (ISA) Communications Port (COM2)
4 (ISA) Communications Port (COM1)
5 (PCI) Realtek RTL8029(AS)-based Ethernet Adapter
5 (PCI) VIA USB 2.0 Enhanced Host Controller
6 (ISA) Standard Floppy Disk Controller
8 (ISA) System CMOS/real time clock
9 (ISA) Microsoft ACPI-Compliant System
10 (PCI) Creative SoundBlaster Audigy
10 (PCI) HPT372 UDMA/ATA133 RAID Controller
10 (PCI) VIA Rev 5 USB Universal Host Controller
11 (PCI) 3D Prophet FDX 8500 LE
11 (PCI) OHCI Compliant IEEE 1394 Host Controller
11 (PCI) VIA Rev 5 USB Universal Host Controller
11 (PCI) VIA Rhine II Fast Ethernet Adapter
12 (ISA) Logitech Cordless9 (PS/2)
13 (ISA) Numeric data processor
14 (ISA) Primary BM Ultra DMA Channel
15 (ISA) Secondary BM Ultra DMA Channel

In order for a device to work correctly, the IRQ values and I/O address ranges must be specified correctly. Since old 'legacy' devices have been replaced by Plug and Play devices, much of the pain has been taken out of their configuration. Of course, having a PnP-compatible operating system, such as Windows 98 or XP, greatly helps. (Windows 95 also attempted PnP. However, because it wasn't very good at it, and neither was the hardware at the time, it was dubbed 'Plug and Pray'.) Actually, most of the self-configuration of PnP devices is done by the BIOS at boot time, but a compatible OS is also necessary.

Direct Memory Access (DMA)

There is one more setting which may be required by a peripheral device: a Direct Memory Access (DMA) channel. Normally, when a device needs to access system memory, it does so via the CPU. The CPU fetches the data from RAM and stores it in CPU registers. It then sends that data off to the device requesting the data. The CPU must control every aspect of data transfer between a device and memory. Also remember that most CPU interactions with I/O devices take place using interrupts, and as we've already seen, interrupts use significant CPU overhead.

Where devices may need to transfer large contiguous blocks of data from/to RAM (this is called large block transfers), it is more efficient to 'cut out the middleman'. This is why devices like sound cards can use DMA channels; they provide a route for direct communicate with memory, without going through the CPU. The CPU still initiates the transfer, but only by telling the DMA controller to take care of it. Basically, the CPU says to the DMA controller something like, Please send x bytes of data, starting at address y to device z. The DMA controller then handles the specifics of what follows.

It should also be noted that when a program running on a CPU initiates a DMA transfer, execution of that program is suspended until the DMA transfer is completed. However, in a multitasking environment, the CPU is free to perform other tasks while waiting for the DMA request to complete.

Standard DMA is also known as third-party DMA. This is because the standard system DMA controller - which is a part of the ISA I/O implementation (more on this later) - controls the transfer, rather than the device itself. Unfortunately, the standard DMA controllers are very slow and therefore are limited to devices with slow data throughput, such as a sound card.

There are 8 DMA channels in total - numbered 0 through 7 - provided by two DMA controllers which are chained much like the IRQ controllers already mentioned. Only 7 channels are available since DMA 4 is used in chaining the controllers and is therefore unavailable. Note that these channels are only available to ISA devices (and since the original DMA controller was built on an 8 bit architecture, only 16 bit ISA cards can access channels 5, 6 and 7).

Newer devices support Bus Mastering whereby the device itself has its own DMA controller - hence first party DMA. Since these DMA controllers do not rely on the old ISA technology, they permit much more rapid communication with memory. Bus mastering devices do not use standard DMA but instead usually use the PCI I/O bus (more on this later).

Now move on to look at the standard bus types.