7.4 Interrupt-Driven I/O
The problem with programmed I/O is that the processor has to wait a long time for the I/
O module of concern to be ready for either reception or transmission of data. The
processor, while waiting, must repeatedly interrogate the status of the I/O module. As e
result, the level of the performance of the entire system is severely degraded.
An alternative is for the processor to issue an I/O command to a module and then go on to
do some other useful work. The I/O module will then interrupt the processor to request
service when it is ready to exchange data with the processor. The processor then executes
the data transfer, as before, and then resumes its former processing.
Let us consider how this works, first from the point of view of the I/O module. For input,
the I/O module receives a READ command from the processor. The I/O module then
proceeds to read data in from an associated peripheral. Once the data are in the module’s
data register, the module signals an interrupt to the processor over a control line. The
module then waits until its data are requested by the processor. When the request is made,
the module places its data on the data bus and it then ready for another I/O operation.
From the processor’s point of view, the action for input is as follows. The processor
issues a READ command. It then goes off and does something else (e.g the processor
may be working on several different programs at the same time). At the end of each
instruction cycle, the processor checks for interrupts (Figure 3.9). When the interrupt
from the I/O module occurs, the processor saves the context (e.g.. Program counter and
processor registers) of the current program and processes the interrupt. In this case, the
processor reads the word of data from the I/O module and stores it in memory. It then
restores the context of the program it was working on (or some other program) and
resumes execution.
Figure 7.5b shows the use of interrupt I/O for reading in block of data. Compare this with
Figure 7.5a. Interrupt I/O is more efficient than programmed I/O because it eliminates
needless waiting. However, interrupt I/O still consumes a lot of processor time, because
every word of data that goes from memory to I/O module or from I/O module to memory
must pass through the processor.
Interrupt Processing
Let us consider the role of the processor in interrupt-driven I/O in more detail. The
occurrence of an interrupt triggers a number of events, both in the processor hardware
and in software. Figure 7.7 shows a typical sequence. When an I/O device completes an I/
O operation, the following sequence of hardware events occurs:
1. The device issues an interrupt signal to the processor.
2. The processor finishes execution of the current instruction before responding to the
interrupt, as indicated in Figure 3.9
3. The processor tests for an interrupt, determines that there is one, and sends an
acknowledgment signal to the device that issued the interrupt. The acknowledgment
allows the devices to remove its interrupt signal.
4. The processor now needs to prepare to transfer control to the interrupt routine. To
begin, it needs to save information needed to resume the current program at the point of
interrupt. The minimum information required is (a) the status of the processor, which is
contained in a register called the program status word (PSW), and (b) the location of the
next instruction to be executed, which is contained in the program counter. These can be
pushed onto the system control stack.
5. The processor now loads the program counter with the entry location of the interrupt-
handling program that will respond to this interrupt. Depending on the computer
architecture and operating system design, there may be a single program, one program for
each type of interrupt, or one program for each device and each type of interrupt. If there
is more than one interrupt-handling routine, the processor must determine which one to
invoke. This information may have been included in the original interrupt signal, or the
processor may have to issue a request to the device that issued the interrupt to get a
response that contains the needed information.
Once the program counter has been loaded, the processor proceeds to the next instruction
cycle, which begins with an instruction fetch. Because the instruction fetch is determined
by the contents of the program counter, the result is that control is transferred to the
interrupt-handler program. The execution of this program results in the following
operations:
6. At this point, the program counter and PSW relating to the interrupted program have
been saved on the system stack. However, there is other information that is considered
part of the “state” of the executing program. In particular, the contents of the processor
registers need to be saved, because these register may be used by the interrupt handler.
So, all of there values, plus any other state information, need to be saved. Typically, the
interrupt handler will begin by saving the contents of all registers on the stack. Figure
7.8a shows a simple example. In this case, a user program is interrupt after the instruction
at location N. The contents of all of the registers plus the address of the next instruction
(N+1) are pushed onto the stack. The stack pointer is updated to point to the new top of
stack, and the program counter is updated to point to the beginning of the interrupt
service routine.
7. The interrupt handler next processes the interrupt. This includes an examination of
status information relating to the I/O operation or other event that caused an interrupt. It
may also involve sending additional commands or acknowledgments to the I/O device.
8. When interrupt processing is complete, the saved register values are retrieved from the
stack and restored to the registers (e.g see Figure 7.8b)
9. The final act is to restore the PSW and program counter values from the stack. As a
result, the next instruction to be executed will be from the previously interrupt program.
Note that it is important to save all the state information about the interrupted program
for later resumption. This is because the interrupt is not a routine called from the
program. Rather, the interrupt can occur at any time and therefore at any point in the
execution of a user program. Its occurrence is unpredictable. Indeed, as we will see in the
next chapter, the two programs may not have anything in common and may belong to two
different users.
Design Issues
Two design issues arise in implementing interrupt I/O. First, because there will almost
invariably be multiple I/O modules, how does the processor determine which device
issued the interrupt? And second, if multiple interrupt have occurred, how does the
processor decide which one to process?
Let us consider device identification first. Four general categories of techniques are in
common use:
-Multiple interrupt lines
-Software poll
-Daisy chain (hardware poll, vectored)
-Bus arbitration (vectored)
The most straightforward approach to the problem is to provide multiple interrupt lines
between the processor and the I/O modules. However, it is impractical to dedicate more
than a few bus lines or processor pins to interrupt lines. Consequently, even if multiple
lines are used, it is likely that each line will have multiple I/O module attached to it.
Thus, one of the other three techniques must be used on each line.
One alternative is the software poll. When processor detects an interrupt, it branches to an
interrupt-service routine whose job it is to poll each I/O module to determine which
module caused the interrupt. The poll could be in the form of a separate command line
(e.g Test I/O). In this case, the processor raises TESTI/O module responds positively if it
set the interrupt. Alternatively, each I/O module could contain an addressable status
register. The processor then reads the status register of each I/O module to identify the
interrupting module. Once the correct module is identified, the processor branches to a
device-service routine specific to that device.
The disadvantage of the software poll is that it is time consuming. A more efficient
technique is to use a daisy chain, which provides, in effect, a hardware poll. An I/O
modules share a common interrupt request line. The interrupt acknowledge line is daisy
chained through the modules. When the processor senses an interrupt, it sends out an
interrupt acknowledge. This signal propagates through a series of I/O module until it gets
to a requesting module. The requesting module typically responds by placing a word on
the data lines. This word is referred to as a vector and is either the address of the I/O
module or some other unique identifier. In either case, the processor uses the vector as a
pointer to the appropriate device-service routine. This avoids the need to execute a
general interrupt-service routine first. This technique is called a vectored interrupt.
There is another technique that makes use of vectored interrupt, and that is bus
arbitration. With bus arbitration, an I/O module must first gain control of the bus before it
can raise the interrupt request line. Thus, only one module can raise the line at a time.
When the processor detects the interrupt, it responds on the interrupt acknowledge line.
The requesting module then places its vector on the data lines.
The aforementioned techniques serve to identify the requesting I/O module. They also
provide a way of assigning priorities when more than one device is requesting interrupt
service. With multiple lines, the processor just picks the interrupt line with the highest
priority. With software polling, the order in which modules are polled determines their
priority. Similarly, the order of modules on a daisy chain determines their priority.
Finally, bus arbitration can employ a priority scheme, as discussed in Section 3.4
We now turn to two examples of interrupt structures.
Intel 82C59A Interrupt Controller
The Intel 80386 provides a single Interrupt Request (INTR) and a single Interrupt
Acknowledge (INTA) line. To allow the 80386 to handle a variety of devices and priority
structures, it is usually configured with an external interrupt arbiter, the 82C59A.
External devices are connected to the 82C59A, which in turn connects to the 80386.
Figure 7.9 shows the use of the 82C59A to connect multiple I/O modules for the 80386.
A single 82C59A can handle up to 8 modules. If control for more than 8 modules is
required, a cascade arrangement can be used to handle up to 64 modules.
The 82C59A’s sole responsibility is the management of interrupts. It accepts interrupt
requests from attached modules, determines which interrupt has the highest priority, and
then signals the processor by raising the INTR line. The processor acknowledges via the
INTA line. This prompts the 82C59A to place the appropriate vector information on the
data bus. The processor can then proceed to process the interrupt and to communicate
directly with the I/O module to read or write data.
The 82C59A is programmable. The 80386 determines the priority scheme to be used by
setting a control word in the 82C59A. The following interrupt modes are possible:
- Fully nested: The interrupt requests are ordered in priority from 0 (IR0) through 7 (IR7).
- Rotating: In some applications a number of interrupt devices are of equal priority. In
this mode a device, after being serviced, receives the lowest priority in the group.
- Special mask: This allows the processor to inhibit interrupt from certain devices.
The Inter 82C55A Programmable Peripheral Interface
As an example of an I/O module used for programmed I/O and interrupt-driven I/O, we
consider the Intel 82C55A Programmable Peripheral Interface. The 82C55A is a single-
chip, general-purpose I/O module designed for use with the Intel 80386 processor. Figure
7.10 shows a general block diagram plus the pin assignment for the 40-pin package in
which it is housed.
The right side of the block diagram is the external interface of the 82C55A. The 24 I/O
lines are programmable by the 80386 by means of the control register. The 80386 can set
the value of the control register to specify a variety of operating modes and configuration.
The 24 lines are divided into three 8-bit groups (A,B,C). each group can function as an 8-
bit port. In addition, group C is subdivided into 4-bit groups (Ca and Cb), which may be
used in conjunction with the A and B I/O ports. Configured in this manner, they carry
control and status signals.
The left side of block diagram is the internal interface to the 80386 bus. It includes an 8-
bit bidirectional data bus (D0 through D7), used to transfer data to and from the I/O ports
and transfer control information to the control register. The two address lines specify one
of the there I/O ports or the control register. A transfer takes place when the CHIP
SELECT line is enabled together with either the READ or WRITE line. The RESET, line
is used to initialize the module.
The control register is loaded by the processor to control the mode of operation and to
define signals, if any. In Mode 0 operation, the three groups of eight external lines
function as three 8-bit I/O ports. Each port can be designated as input or output.
Otherwise, groups A and B function as I/O ports, and the lines of group C serve as
control lines for A and B. The control signals serve two principal purposes:
“handshaking” and interrupt request. Handshaking is a simple timing mechanism. One
control line is used by the sender as a DATA READY line, to indicate when the data are
present on the I/O data lines. Another line is used by the receiver as an
ACKNOWLEDGE, indicating that the data have been read and the data lines may be
cleared. Another line may be designated as an INTERRUPT REQUEST line and tied
back to the system bus.
Because the 82C55A is programmable via the control register, it can be used to control a
variety of simple peripheral device. Figure 7.11 illustrates its use to control a
keyboard/display terminal. The keyboard provides 8-bit of input. Two of these bits,
SHIFT and CONTROL, have special meaning to the keyboard-handling program
executing in the processor. However, this interpretation is transparent to the
82C55A,which simply accepts the 8 bits of data and presents them on the system data
bus. Two handshaking control lines are provided for use with the keyboard.
The display is also linked by an 8-bit data port. Again, two of the bits have special
meanings that are transparent to the 82C55A. In addition to two handshaking lines, two
lines provide additional control functions
7.5 Direct Memory Access
Drawbacks of programmed and Interrupt-driven I/O
Interrupt-driven I/O, though more efficient than simple programmed I/O, still requires the
active intervention of the processor to transfer data between memory and an I/O module,
and any data transfer must traverse a path through the processor. Thus, both these forms
of I/O suffer from two inherent drawbacks:
1: The I/O transfer rate is limited by the speed with which the processor can test and
service a device.
2: The processor is tied up in managing an I/O transfer a number of instructions must be
executed for each I/O transfer (e.g: figure 7.5).
There is somewhat of a trade-off between these two drawbacks. Consider the transfer of
block of data. Using simple programmed I/O, the processor is dedicated to the task of I/O
and can move data at a rather high rate, at the cost of doing nothing else. Interrupt I/O
frees up the processor to some extent at the expense of the I/O transfer rate. Nevertheless,
both methods have an adverse impact on both processor activity and I/O transfer rate.
When large volumes of date are to be moved, a more efficient technique is required:
direct memory access (DMA).
DMA Function
DMA involves an additional module on the system bus. The DMA module (Figure 7.12)
is capable of mimicking the processor and, indeed, of taking over control of the system
from the processor. It needs to do this to transfer data to and from memory over the
system bus, For this purpose, the DMA module must use the bus only when the processor
dose not need it, or it must force the processor to suspend operation temporarily. The
latter technique is more common and is referred to as cycle stealing, because the DMA
module in effect steals a bus cycle.
When the processor wishes to read or write a block of data, it issues a command to the
DMA module, by sending to the DMA module the following information:
-Whether a read or write is requested, using the read or write control line between the
processor and the DMA module
-The address of the I/O device involved, communicated on the data lines
-The starting location in memory to read from or write to, communicated on the data lines
and stored by the DMA module in its address register
-The number of words to be read or written, again communicated via the data lines and
stored in the data count register
The processor then continues with other work. It has delegated this I/O operation to the
DMA module. The DMA module transfers the entire block of data, one word at a time,
directly to or from memory, without going through the processor. When the transfer is
complete, the DMA module sends an interrupt signal to the processor. Thus, the
processor is involved only at the beginning and end of the transfer (Figure 7.5c).
Figure 7.13 shows where in the instruction cycle the processor may be suspended. In each
case, the processor is suspended just before it needs to use the bus. The DMA module
then transfers one word and returns control to the processor. Note that this is not an
interrupt, the processor dose not save a context and do something else. Rather the
processor pauses for one bus cycle, the overall effect is to cause the processor to execute
more slowly. Nevertheless, for a multiple- word I/O transfer, DMA is far more efficient
than interrupt-driven or programmed I/O.
The DMA mechanism can be configured in a variety of ways. Some possibilities are
shown in figure 7.14. In the first example, all modules share the same system bus. The
DMA module, acting as a surrogate processor, uses programmed I/O to exchange data
between memory and an I/O module through the DMA module. This configuration, while
it may be inexpensive, is clearly inefficient. As with processor-controlled programmed I/
O, each transfer of a word consumes two bus cycles.
The number of required bus cycles can be cut substantially by integrating the DMA and I/
O functions. As Figure 7.14b indicates this means that there is a path between the DMA
module and one or more I/O modules that dose not include the system bus. The DMA
logic may actually be a part of an I/O module, or it may be a separate module that
controls one or more I/O modules. This concept can be taken one step further by
connecting I/O modules to the DMA module using an I/O bus (figure 7.14c). This
reduces the number of I/O interfaces in the DMA module to one and provides for an
easily expandable configuration. In all of these cases (figures 7.14c) the system bus that
the DMA module shares with memory. The exchange of data between the DMA and I/O
modules takes place off the system bus.
7.6 I/O Channels and Processors
The Evolution of the I/O Function
As computer systems have evolved, there has been a pattern of increasing complexity and
sophistication of individual components. Nowhere is this more evident than in the I/O
function. We have already seen part of that evolution. The evolutionary steps can be
summarized as follows:
1. The CPU directly controls a peripheral device. This is seen in simple microprocessor-
controlled devices.
2. A controller or I/O module is added. The CPU uses programmed I/O without interrupt.
With this step, the CPU becomes somewhat divorced from the specific details of external
device interfaces.
3. The same configuration as in step 2 is used, but now interrupt are employed, the CPU
need not spend time waiting for an I/O operation to be performed, increasing efficiency.
4. The I/O module is given direct access to memory via DMA. It can now move a block
of data to or from memory without involving the CPU, except at the beginning and end of
the transfer.
5. The I/O module is enhanced to become a processor in its own right, with a specialized
instruction set tailored for I/O. The CPU directs the I/O processor to execute an I/O
program in memory. The I/O processor fetches and executes these instructions without
CPU intervention. This allows the CPU to specify a sequence of I/O activities and to be
interrupted only when the sequence has been preformed
6. the I/O module has a local memory of its own and is, in fact, a computer in its own
right. With this architecture, a large set of I/O devices can be controlled, with minimal
CPU involvement. A common use for such an architecture has been to control
communication with interactive terminals. The I/O processor takes care of most of the
tasks involved in controlling the terminals.
As one proceeds along this evolutionary path, more and more of the I/O function is
preformed without CPU involvement. The CPU is increasingly relieved of I/O related
tasks, improving performance. With the last two steps (5-6) a major change occurs with
the introduction of the concept of an I/O module capable of executing a program. For step
5, the I/O module is often referred to as an I/O channel.
For step 6 the term I/O processor is often used. However, both terms are on occasion
applied to both situations, In what follows. We will use the term I/O channel.
CHARACTERISTICS OF I/O CHANNELS.
The I/O channel represents an extension of the DMA concept. An I/O channel has the
ability to execute I/O instructions. Which gives it complete control over I/O operations.
In a computer system with such devices, the CPU does not execute I/O instructions. Such
instructions are stored in main memory to be executed by a special-purpose in the I/O
channel itself. Thus, the CPU initiates an I/O transfer by instructing the I/O channel to
execute a program in memory. The program will specify the device or devices, the area
or areas of memory for storage, priority, and actions to be taken for certain error
conditions. The I/O channel follows these instructions and controls the data transfer.
Two types of I/O channels are common, as illustrated in Figure 7.15. A selector channel
controls multiple high-speed devices and, at any one time, is dedicated to the transfer of
data with one of those devices. Thus, the I/O channel selects one device and effect the
data transfer. Each device, or a small set of devices, is handled by a controller, or I/O
module, that is much like the I/O modules we have been discussing.
Thus, the I/O channel serves in place of the CPU in controlling these I/O controllers. A
multiplexor channel can handle I/O with multiple devices at the same time. For low-
speed devices, a byte multiplexor accepts or transmits characters as fast as possible to
multiple devices. For example, the resultant character stream from three devices with
different rates and individual streams A1A2A3…B1B2B3…
And C1C2C3… might be A1B1C1A2C2A3B2, and so on. For high-speed devices, a
block multiplexor interleaves blocks of data from several devices