123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- .. Copyright 2001 Matthew Wilcox
- ..
- .. 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.
- ===============================
- Bus-Independent Device Accesses
- ===============================
- :Author: Matthew Wilcox
- :Author: Alan Cox
- Introduction
- ============
- Linux provides an API which abstracts performing IO across all busses
- and devices, allowing device drivers to be written independently of bus
- type.
- Memory Mapped IO
- ================
- Getting Access to the Device
- ----------------------------
- 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.
- This address should not be used directly. Instead, to get an address
- suitable for passing to the accessor functions described below, you
- should call ioremap(). An address suitable for accessing
- the device will be returned to you.
- After you've finished using the device (say, in your module's exit
- routine), call iounmap() in order to return the address
- space to the kernel. Most architectures allocate new address space each
- time you call ioremap(), and they can run out unless you
- call iounmap().
- Accessing the device
- --------------------
- 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.
- The functions are named readb(), readw(), readl(), readq(),
- readb_relaxed(), readw_relaxed(), readl_relaxed(), readq_relaxed(),
- writeb(), writew(), writel() and writeq().
- Some devices (such as framebuffers) would like to use larger transfers than
- 8 bytes at a time. For these devices, the memcpy_toio(),
- memcpy_fromio() and memset_io() functions are
- provided. Do not use memset or memcpy on IO addresses; they are not
- guaranteed to copy data in order.
- 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 __readb() and friends to
- indicate the relaxed ordering. Use this with care.
- 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 asynchronicity. In particular 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. In some
- cases, the read used to flush the device may be expected to fail (if the
- card is resetting, for example). In that case, the read should be done
- from config space, which is guaranteed to soft-fail if the card doesn't
- respond.
- The following is an example of flushing a write to a device when the
- driver would like to ensure the write's effects are visible prior to
- continuing execution::
- static inline void
- qla1280_disable_intrs(struct scsi_qla_host *ha)
- {
- struct device_reg *reg;
- reg = ha->iobase;
- /* disable risc and host interrupts */
- WRT_REG_WORD(®->ictrl, 0);
- /*
- * The following read will ensure that the above write
- * has been received by the device before we return from this
- * function.
- */
- RD_REG_WORD(®->ictrl);
- ha->flags.ints_enabled = 0;
- }
- PCI ordering rules also guarantee that PIO read responses arrive after any
- outstanding DMA writes from that bus, since for some devices the result of
- a readb() call may signal to the driver that a DMA transaction is
- complete. In many cases, however, the driver may want to indicate that the
- next readb() call has no relation to any previous DMA writes
- performed by the device. The driver can use readb_relaxed() for
- these cases, although only some platforms will honor the relaxed
- semantics. Using the relaxed read functions will provide significant
- performance benefits on platforms that support it. The qla2xxx driver
- provides examples of how to use readX_relaxed(). In many cases, a majority
- of the driver's readX() calls can safely be converted to readX_relaxed()
- calls, since only a few will indicate or depend on DMA completion.
- Port Space Accesses
- ===================
- Port Space Explained
- --------------------
- 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.
- Unlike memory mapped IO, no preparation is required to access port
- space.
- Accessing Port Space
- --------------------
- 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 inb(), inw(),
- inl(), outb(), outw() and
- outl().
- 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 ``_p`` to the end of the function.
- There are also equivalents to memcpy. The ins() and
- outs() functions copy bytes, words or longs to the given
- port.
- Public Functions Provided
- =========================
- .. kernel-doc:: arch/x86/include/asm/io.h
- :internal:
- .. kernel-doc:: lib/pci_iomap.c
- :export:
|