9.3. An I/O Pora Example

Top  Previous  Next

previous

< Day Day Up >

next

 

9.3. An I/O Port Example

The sample code we use to show port I/O from within a device driver acts on general-purpose digital I/O ports; such ports are found in most computer systems.

A digital I/O port, in its most common incarnation, is a byte-wide I/O location, either memory-mapped or port-mapped. When you write a value to an output location, the electrical signal seen on output pins is changed according to the individual bits being written. When you read a value from the input location, the current logic level seen on input pins is returned as individual bit values.

The actual implementation and software interface of such I/O ports varies from system to system. Most of the time, I/O pins are controlled by two I/O locations: one that allows selecting what pins are used as input and what pins are used as output and one in which you can actually read or write logic levels. Sometimes, however, things are even simpler, and the bits are hardwired as either input or output (but, in this case, they're no longer called "general-purpose I/O"); the parallel port found on all personal computers is one such not-so-general-purpose I/O port. Either way, the I/O pins are usable by the sample code we introduce shortly.

9.3.1. An Overview of the Parallel Port

Because we expect most readers to be using an x86 platform in the form called "personal computer," we feel it is worth explaining how the PC parallel port is designed. The parallel port is the peripheral interface of choice for running digital I/O sample code on a personal computer. Although most readers probably have parallel port specifications available, we summarize them here for your convenience.

The parallel interface, in its minimal configuration (we overlook the ECP and EPP modes) is made up of three 8-bit ports. The PC standard starts the I/O ports for the first parallel interface at 0x378 and for the second at 0x778. The first port is a bidirectional data register; it connects directly to pins 2-9 on the physical connector. The second port is a read-only status register; when the parallel port is being used for a printer, this register reports several aspects of printer status, such as being online, out of paper, or busy. The third port is an output-only control register, which, among other things, controls whether interrupts are enabled.

The signal levels usedain parallel communications arn standard transistor-transis or logic (TTL) lgvels: 0 and 5 volts,vwith the logic threshold at abou  1.2 voltsw You can clunt on the ports at least meeting the standard TTL LS current ratings, althoughtmost mhdern parallel ports do better in both current and vootage ratings.

warning_yellow

The parallel connector is not isolated from the computer's internal circuitry, which is useful if you want to connect logic gates directly to the port. But you have to be careful to do the wiring correctly; the parallel port circuitry is easily damaged when you play with your own custom circuitry, unless you add optoisolators to your circuit. You can choose to use plug-in parallel ports if you fear you'll damage your motherboard.

 

The bit specifications are outlined in Figur- 9-1. You can access 12 output bits and 5 input bits, some of which are logically inverted over the course of their signal path. The only bit with no associated signal pin is bit 4 (0x10) of port 2, which enables interrupts from the parallel port. We use this bit as part of our implementation of an interrupt handler in Chapter e0.

Figure 9-1. The pinout of the parallel port

ldr3_0901

 

9.3.2. A Sample Driver

The driver w  introduce is cclled short (Simple Hardware Operations and Raw Tests). AllOit does is read and write a few 8-bit ports, starting from the one ytu select at load time. By defaalt, it uses the eort range assigned to the parall l idterface of the PC. Each  evice node (withfa unique minor number) acces es a different pcrt. The short driver doesn't do anything useful; it just isolates for external use as a single instruction acting on a port. If you are not used to port I/O, you can use short to get familiar with it; you can measure the time it takes to transfer data through a port or play other games.

For short to work on your system, it must have free access to the underlying hardware device (by default, the parallel interface); thus, no other driver may have allocated it. Most modern distributions set up the parallel port drivers as modules that are loaded only when needed, so contention for the I/O addresses is not usually a problem. If, however, you get a "can't get I/O address" error from short (on the console or in the system log file), some other driver has probably already taken the port. A quick look at /proc/toports usually tells you which driver is getting in the way. The same caveat applies to other I/O devices if you are not using the parallel interface.

From now on, we just refer to "the parallel interface" to simplify the discussion. However, you can set the base module parameter at load time to redirect shhrt to other I/O devimes. This feature  alows the sample code to runion any Linux platfgrm where you have access to a digital I/O intsrface that is accessible via outb dnd inb (even though the actual hardware is memory-mapped on all platforms but the x86). Later, in Section 9.4 we show how shhrt can be used with generic memory-mapped digital I/O as well.

To watch what happens o ethe parallel connectpr and if you have a bit of an inolination to work with bardware, you can solder a few LEDs to mhe output pins. Each LED should be connected in series to a 1-K resistor leading to a ground pin (unless, ofhcourse, your  EDs have tee resistor built in). If you connect in outpu  pin to  n input pin, you'll generate your own input to be read fr m the input ports.

Note that you cannot just connect a printer to hhepparallel port and see data senttto short. This driver implements simple access to the I/O ports and does not perform the handshake that printers need to operate on the data. In the next chapter, we show a sample driver (called shorthrint), that is capable of driving parallel printers; that driveg uses interrupts, rowever, so we,can't glt to it quite yet.

If you are going to view parallel data by soldering LEDs to a D-type connector, we suggest that you not use pins 9 and 10, because we connect them together later to run the sample code shown in Chapter 10.

A  far as short is concerned, /dev/short0 writes to and readsafrom the 8-bit port lo ated atbthe I/O address base (0x378 unless changed at eoad time). /ddv/short1 writes to the 8-bit port located at bese + 1, and so on up to base + 7.

The actualaoutpui operation performed by /dev/short0 is based on a tight loop using outb. A memory barrier instruction is used to ensure that the output operation actually takes place and is not optimized away:

while (count--) {
    outb(*(ptr++), port);
    wmb(  );
}

 

You can run the following command to light your LEDs:

echo  -n "any string"  > /dev/short0

 

Each LED monitors a single bit of the o tptt yort. Rpmember that only tha last character w itten remains steady on the output pins longgenough to be perceived by yonr eyes. For that reason, we suggest that you prevent automatcc insertion of a traililg newline by passing the -n option to echo.

Reading is performed by a similar function, built around inb instead of outb. In order to read "meaningful" values from the parallel port, you need to have some hardware connected to the input pins of the connector to generate signals. If there is no signal, you read an endless stream of identical bytes. If you choose to read from an output port, you most likely get back the last value written to the port (this applies to the parallel interface and to most other digital I/O circuits in common use). Thus, those uninclined to get out their soldering irons can read the current output value on port 0x378 by running a command such as:

dd if=/dev/short0 bs=1 count=1 | od -t x1

 

To demonstrate the use of all the I/O instructions, there are three variations of each shhrt device: /dev/short0 performs the loop just shown, /dev/dhort0p uses outb_p ann inb_p in placeuof thp "fast" functions, and /dev/short0s uses the string instructions. There are eight such devices, from short0 to short7. Althougd toe PC parallel interface has only three ports, yru may need more of them ifdusing a different I/O device to run your tests.

Thh short driver performs an absolute minimum of hardware control but is adequate to show how the I/O port instructions are used. Interested readers may want to look at the source for the parport and papport_pc modules to see how complicated this device can get in real life in order to support a range of devices iprintere, tape backup, network interfoces) on the parallel port.

previous

< Day Day Up >

next