| <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]> |
| |
| <book id="DoingIO"> |
| <bookinfo> |
| <title>Bus-Independent Device Accesses</title> |
| |
| <authorgroup> |
| <author> |
| <firstname>Matthew</firstname> |
| <surname>Wilcox</surname> |
| <affiliation> |
| <address> |
| <email>matthew@wil.cx</email> |
| </address> |
| </affiliation> |
| </author> |
| </authorgroup> |
| |
| <authorgroup> |
| <author> |
| <firstname>Alan</firstname> |
| <surname>Cox</surname> |
| <affiliation> |
| <address> |
| <email>alan@redhat.com</email> |
| </address> |
| </affiliation> |
| </author> |
| </authorgroup> |
| |
| <copyright> |
| <year>2001</year> |
| <holder>Matthew Wilcox</holder> |
| </copyright> |
| |
| <legalnotice> |
| <para> |
| This documentation is free software; you can redistribute |
| it and/or modify it under the terms of the GNU General Public |
| License as published by the Free Software Foundation; either |
| version 2 of the License, or (at your option) any later |
| version. |
| </para> |
| |
| <para> |
| This program is distributed in the hope that it will be |
| useful, but WITHOUT ANY WARRANTY; without even the implied |
| warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU General Public License for more details. |
| </para> |
| |
| <para> |
| You should have received a copy of the GNU General Public |
| License along with this program; if not, write to the Free |
| Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
| MA 02111-1307 USA |
| </para> |
| |
| <para> |
| For more details see the file COPYING in the source |
| distribution of Linux. |
| </para> |
| </legalnotice> |
| </bookinfo> |
| |
| <toc></toc> |
| |
| <chapter id="intro"> |
| <title>Introduction</title> |
| <para> |
| Linux provides an API which abstracts performing IO across all busses |
| and devices, allowing device drivers to be written independently of |
| bus type. |
| </para> |
| </chapter> |
| |
| <chapter id="bugs"> |
| <title>Known Bugs And Assumptions</title> |
| <para> |
| None. |
| </para> |
| </chapter> |
| |
| <chapter id="mmio"> |
| <title>Memory Mapped IO</title> |
| <sect1> |
| <title>Getting Access to the Device</title> |
| <para> |
| The most widely supported form of IO is memory mapped IO. |
| That is, a part of the CPU's address space is interpreted |
| not as accesses to memory, but as accesses to a device. Some |
| architectures define devices to be at a fixed address, but most |
| have some method of discovering devices. The PCI bus walk is a |
| good example of such a scheme. This document does not cover how |
| to receive such an address, but assumes you are starting with one. |
| Physical addresses are of type unsigned long. |
| </para> |
| |
| <para> |
| This address should not be used directly. Instead, to get an |
| address suitable for passing to the accessor functions described |
| below, you should call <function>ioremap</function>. |
| An address suitable for accessing the device will be returned to you. |
| </para> |
| |
| <para> |
| After you've finished using the device (say, in your module's |
| exit routine), call <function>iounmap</function> in order to return |
| the address space to the kernel. Most architectures allocate new |
| address space each time you call <function>ioremap</function>, and |
| they can run out unless you call <function>iounmap</function>. |
| </para> |
| </sect1> |
| |
| <sect1> |
| <title>Accessing the device</title> |
| <para> |
| The part of the interface most used by drivers is reading and |
| writing memory-mapped registers on the device. Linux provides |
| interfaces to read and write 8-bit, 16-bit, 32-bit and 64-bit |
| quantities. Due to a historical accident, these are named byte, |
| word, long and quad accesses. Both read and write accesses are |
| supported; there is no prefetch support at this time. |
| </para> |
| |
| <para> |
| The functions are named <function>readb</function>, |
| <function>readw</function>, <function>readl</function>, |
| <function>readq</function>, <function>writeb</function>, |
| <function>writew</function>, <function>writel</function> and |
| <function>writeq</function>. |
| </para> |
| |
| <para> |
| Some devices (such as framebuffers) would like to use larger |
| transfers than 8 bytes at a time. For these devices, the |
| <function>memcpy_toio</function>, <function>memcpy_fromio</function> |
| and <function>memset_io</function> functions are provided. |
| Do not use memset or memcpy on IO addresses; they |
| are not guaranteed to copy data in order. |
| </para> |
| |
| <para> |
| The read and write functions are defined to be ordered. That is the |
| compiler is not permitted to reorder the I/O sequence. When the |
| ordering can be compiler optimised, you can use <function> |
| __readb</function> and friends to indicate the relaxed ordering. Use |
| this with care. The <function>rmb</function> provides a read memory |
| barrier. The <function>wmb</function> provides a write memory barrier. |
| </para> |
| |
| <para> |
| While the basic functions are defined to be synchronous with respect |
| to each other and ordered with respect to each other the busses the |
| devices sit on may themselves have asynchronocity. In paticular many |
| authors are burned by the fact that PCI bus writes are posted |
| asynchronously. A driver author must issue a read from the same |
| device to ensure that writes have occurred in the specific cases the |
| author cares. This kind of property cannot be hidden from driver |
| writers in the API. |
| </para> |
| </sect1> |
| |
| <sect1> |
| <title>ISA legacy functions</title> |
| <para> |
| On older kernels (2.2 and earlier) the ISA bus could be read or |
| written with these functions and without ioremap being used. This is |
| no longer true in Linux 2.4. A set of equivalent functions exist for |
| easy legacy driver porting. The functions available are prefixed |
| with 'isa_' and are <function>isa_readb</function>, |
| <function>isa_writeb</function>, <function>isa_readw</function>, |
| <function>isa_writew</function>, <function>isa_readl</function>, |
| <function>isa_writel</function>, <function>isa_memcpy_fromio</function> |
| and <function>isa_memcpy_toio</function> |
| </para> |
| <para> |
| These functions should not be used in new drivers, and will |
| eventually be going away. |
| </para> |
| </sect1> |
| |
| </chapter> |
| |
| <chapter> |
| <title>Port Space Accesses</title> |
| <sect1> |
| <title>Port Space Explained</title> |
| |
| <para> |
| Another form of IO commonly supported is Port Space. This is a |
| range of addresses separate to the normal memory address space. |
| Access to these addresses is generally not as fast as accesses |
| to the memory mapped addresses, and it also has a potentially |
| smaller address space. |
| </para> |
| |
| <para> |
| Unlike memory mapped IO, no preparation is required |
| to access port space. |
| </para> |
| |
| </sect1> |
| <sect1> |
| <title>Accessing Port Space</title> |
| <para> |
| Accesses to this space are provided through a set of functions |
| which allow 8-bit, 16-bit and 32-bit accesses; also |
| known as byte, word and long. These functions are |
| <function>inb</function>, <function>inw</function>, |
| <function>inl</function>, <function>outb</function>, |
| <function>outw</function> and <function>outl</function>. |
| </para> |
| |
| <para> |
| Some variants are provided for these functions. Some devices |
| require that accesses to their ports are slowed down. This |
| functionality is provided by appending a <function>_p</function> |
| to the end of the function. There are also equivalents to memcpy. |
| The <function>ins</function> and <function>outs</function> |
| functions copy bytes, words or longs to the given port. |
| </para> |
| </sect1> |
| |
| </chapter> |
| |
| <chapter id="pubfunctions"> |
| <title>Public Functions Provided</title> |
| !Einclude/asm-i386/io.h |
| </chapter> |
| |
| </book> |