Accessing I/O Ports, Part 2

By Danny Kalev, ITworld |  How-to Add a new comment

Descriptors vs. Direct Access
The technique presented last week for accessing I/O ports is portable
and safe but too slow for certain applications. Instead of using a
descriptor, Linux allows a process to write to an I/O port directly,
thereby avoiding the overhead associated with write() and read().

The outb() Syscall
A process can call the function outb() to write directly to an I/O
port. outb() takes two arguments: the data to be written to the I/O
port and the I/O port number. For example, to write the character 0x01
to our remote control, call outb() as follows:

outb(0x01, 0x378+2); /*turn the lights on*/

The use of symbolic constants can make the code more readable:

const char ON=0x01;
const char OFF=0x00;
const int PORT=0x378+2;
outb(OFF, PORT); /*turn the lights off*/

Obtaining Permissions
This is all well and good; however, by default Linux terminates a
process that attempts to access an I/O port directly (with good
reason!). A process that accesses I/O ports directly must get the
necessary permissions beforehand using one of two methods. The first
(and safer) way is to call ioperm(). ioperm() allows a process with
super-user privileges access to each I/O port in the range 0-0x3ff.
Thus, if you wish to access the ports 0x378, 0x379, and 0x380 (the
ports that access /dev/lp1), call ioperm() as follows:

ioperm(0x378, 3, 1);

The first argument is the first port in the range. The second argument
is the number of ports in the range. The last argument is either 1 or
0. The value 1 allows access to the ports in the range and 0 denies
access to them. ioperm() returns 0 on success and -1 on error.
Alternatively, a process with super-user privileges can enable access
to all the I/O ports at once by calling the iopl() function as follows:

iopl(3);

The above call causes a process to switch to what is known as "I/O
protection level 3", which grants a process full access to the I/O bus.
As a rule, you should use ioperm() to obtain permission to access I/O
ports; use iopl() only if your process needs to access ports higher
than 0x3ff.

A note on last week's tip:
The device names "dev/port" and "dev/lp1" should read "/dev/port"
and "/dev/lp1", respectively.

    Add a comment

    Post a comment using one of these accounts
    Or join now
    At least 6 characters

    Note: Comment will appear soon after you have activated your account.
    Obscene/spam comments will be removed and accounts suspended.
    The information you submit is subject to our Privacy Policy and Terms of Service.

    ITworld LIVE

    How-toWhite Papers & Webcasts

    White Paper

    Differentiating Unified Storage Appliances

    Are your storage systems flexible and adaptable enough to meet your company's changing demands? That's not an easy question to answer. Download this Tech Dossier to understand the benefits of unified storage systems, and what you need to consider when looking for a product that meets your specific needs.

    See more White Papers | Webcasts

    Ask a question

    Ask a Question