Accessing I/O ports

When you're porting code that accesses hardware, the x86 architecture has a set of instructions that manipulate a separate address space called the I/O address space. This address space is completely separate from the memory address space. On non-x86 platforms, such an address space doesn't exist—all devices are mapped into memory.

In order to keep code portable, we've defined a number of functions that isolate this behavior. By including the file <hw/inout.h>, you get the following functions:

in8()
Reads an 8-bit value.
in16(), inbe16(), inle16()
Reads a 16-bit value.
in32(), inbe32(), inle32()
Reads a 32-bit value.
in8s()
Reads a number of 8-bit values.
in16s()
Reads a number of 16-bit values.
in32s()
Reads a number of 32-bit values.
out8()
Writes a 8-bit value.
out16(), outbe16(), outle16()
Writes a 16-bit value.
out32(), outbe32(), outle32()
Writes a 32-bit value.
out8s()
Writes a number of 8-bit values.
out16s()
Writes a number of 16-bit values.
out32s()
Writes a number of 32-bit values.

On the x86 architecture, these functions perform the machine instructions in, out, rep ins*, and rep outs*. On non-x86 architectures, they dereference the supplied address (the addr parameter) and perform memory accesses.

Note that the calling process must use mmap_device_io() to access the device's I/O registers.