Using I/O Ports
I/O ports are the means by which drivers communicate with many devices out there—at least part of the time. This section covers the various functions available for making use of I/O ports; we also touch on some portability issues.
Let us start with a quick reminder that I/O ports must be allocated before being used by your driver. As we discussed in Section 2.5.1 in Chapter 2, the functions used to allocate and free ports are:
#include <linux/ioport.h>
int check_region(unsigned long start, unsigned long len);
struct resource *request_region(unsigned long start,
unsigned long len, char *name);
void release_region(unsigned long start, unsigned long len);After a driver has requested the range of I/O ports it needs to use in its activities, it must read and/or write to those ports. To this aim, most hardware differentiates between 8-bit, 16-bit, and 32-bit ports. Usually you can’t mix them like you normally do with system memory access.[32]
A C program, therefore, must call different functions to access
different size ports. As suggested in the previous section, computer
architectures that support only memory-mapped I/O registers fake port
I/O by remapping port addresses to memory addresses, and the kernel
hides the details from the driver in order to ease portability. The
Linux kernel headers (specifically, the architecture-dependent header
<asm/io.h>) define the following inline
functions to access I/O ports.
Note
From now on, when we use unsigned ...