Linux Device Drivers 2nd Edition (779877), страница 58
Текст из файла (страница 58)
Each device node (with a unique minor number) accesses a different port. The short driver doesn’t do anything useful; it just isolates for externaluse a single instruction acting on a port. If you are not used to port I/O, you canuse short to get familiar with it; you can measure the time it takes to transfer datathrough 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 haveallocated it. Most modern distributions set up the parallel port drivers as modulesthat 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 (onthe console or in the system log file), some other driver has probably alreadytaken the port. A quick look at /pr oc/ioports will usually tell you which driver isgetting in the way. The same caveat applies to other I/O devices if you are notusing the parallel interface.From now on, we’ll just refer to ‘‘the parallel interface’’ to simplify the discussion.However, you can set the base module parameter at load time to redirect short toother I/O devices. This feature allows the sample code to run on any Linux platform where you have access to a digital I/O interface that is accessible via outband inb (even though the actual hardware is memory-mapped on all platforms butthe x86).
Later, in “Using I/O Memory,” we’ll show how short can be used withgeneric memory-mapped digital I/O as well.To watch what happens on the parallel connector, and if you have a bit of aninclination to work with hardware, you can solder a few LEDs to the output pins.Each LED should be connected in series to a 1-KΩ resistor leading to a ground pin(unless, of course, your LEDs have the resistor built in).
If you connect an outputpin to an input pin, you’ll generate your own input to be read from the inputports.Note that you cannot just connect a printer to the parallel port and see data sent toshort. This driver implements simple access to the I/O ports and does not performthe handshake that printers need to operate on the data.If you are going to view parallel data by soldering LEDs to a D-type connector, wesuggest that you not use pins 9 and 10, because we’ll be connecting them togetherlater to run the sample code shown in Chapter 9.As far as short is concerned, /dev/short0 writes to and reads from the eight-bit portlocated at the I/O address base (0x378 unless changed at load time).
/dev/short1writes to the eight-bit port located at base + 1, and so on up to base + 7.23722 June 2001 16:39http://openlib.org.uaChapter 8: Hardware ManagementThe actual output operation performed by /dev/short0 is based on a tight loopusing 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++), address);wmb();}You can run the following command to light your LEDs:echo-n "any string"> /dev/short0Each LED monitors a single bit of the output port. Remember that only the lastcharacter written remains steady on the output pins long enough to be perceivedby your eyes.
For that reason, we suggest that you prevent automatic insertion of atrailing newline by passing the -n option to echo.Reading is performed by a similar function, built around inb instead of outb. Inorder to read ‘‘meaningful’’ values from the parallel port, you need to have somehardware connected to the input pins of the connector to generate signals. If thereis no signal, you’ll read an endless stream of identical bytes. If you choose to readfrom an output port, you’ll 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 like:dd if=/dev/short0 bs=1 count=1 | od -t x1To demonstrate the use of all the I/O instructions, there are three variations ofeach short device: /dev/short0 performs the loop just shown, /dev/short0p usesoutb_ p and inb_ p in place of the ‘‘fast’’ functions, and /dev/short0s uses the stringinstructions. There are eight such devices, from short0 to short7. Although the PCparallel interface has only three ports, you may need more of them if using a different I/O device to run your tests.The 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 wantto look at the source for the parport and parport_ pc modules to see how complicated this device can get in real life in order to support a range of devices (printers, tape backup, network interfaces) on the parallel port.Using I/O MemoryDespite the popularity of I/O ports in the x86 world, the main mechanism used tocommunicate with devices is through memory-mapped registers and device memory. Both are called I/O memory because the difference between registers andmemory is transparent to software.23822 June 2001 16:39http://openlib.org.uaUsing I/O MemoryI/O memory is simply a region of RAM-like locations that the device makes available to the processor over the bus.
This memory can be used for a number of purposes, such as holding video data or Ethernet packets, as well as implementingdevice registers that behave just like I/O ports (i.e., they have side effects associated with reading and writing them).The way used to access I/O memory depends on the computer architecture, bus,and device being used, though the principles are the same everywhere. The discussion in this chapter touches mainly on ISA and PCI memory, while trying toconvey general information as well. Although access to PCI memory is introducedhere, a thorough discussion of PCI is deferred to Chapter 15.According to the computer platform and bus being used, I/O memory may or maynot be accessed through page tables. When access passes though page tables, thekernel must first arrange for the physical address to be visible from your driver(this usually means that you must call ior emap before doing any I/O).
If no pagetables are needed, then I/O memory locations look pretty much like I/O ports,and you can just read and write to them using proper wrapper functions.Whether or not ior emap is required to access I/O memory, direct use of pointersto I/O memory is a discouraged practice. Even though (as introduced in “I/O Portsand I/O Memory”) I/O memory is addressed like normal RAM at hardware level,the extra care outlined in “I/O Registers and Conventional Memory” suggestsavoiding normal pointers. The wrapper functions used to access I/O memory areboth safe on all platforms and optimized away whenever straight pointer dereferencing can perform the operation.Therefore, even though dereferencing a pointer works (for now) on the x86, failure to use the proper macros will hinder the portability and readability of thedriver.Remember from Chapter 2 that device memory regions must be allocated prior touse.
This is similar to how I/O ports are registered and is accomplished by the following functions:int check_mem_region(unsigned long start, unsigned long len);void request_mem_region(unsigned long start, unsigned long len,char *name);void release_mem_region(unsigned long start, unsigned long len);The start argument to pass to the functions is the physical address of the memory region, before any remapping takes place. The functions would normally beused in a manner such as the following:if (check_mem_region(mem_addr, mem_size)) {printk("drivername: memory already in use\n");return -EBUSY;}request_mem_region(mem_addr, mem_size, "drivername");23922 June 2001 16:39http://openlib.org.uaChapter 8: Hardware Management[...]release_mem_region(mem_addr, mem_size);Directly Mapped MemorySeveral computer platforms reserve part of their memory address space for I/Olocations, and automatically disable memory management for any (virtual) addressin that memory range.The MIPS processors used in personal digital assistants (PDAs) offer an interestingexample of this setup.