diff options
Diffstat (limited to 'Documentation/DocBook')
-rw-r--r-- | Documentation/DocBook/Makefile | 7 | ||||
-rw-r--r-- | Documentation/DocBook/deviceiobook.tmpl | 323 | ||||
-rw-r--r-- | Documentation/DocBook/iio.tmpl | 697 | ||||
-rw-r--r-- | Documentation/DocBook/kgdb.tmpl | 8 | ||||
-rw-r--r-- | Documentation/DocBook/libata.tmpl | 2 | ||||
-rw-r--r-- | Documentation/DocBook/regulator.tmpl | 304 | ||||
-rw-r--r-- | Documentation/DocBook/uio-howto.tmpl | 1112 |
7 files changed, 9 insertions, 2444 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index a6eb7dcd4dd5..60a17b7da834 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -11,9 +11,9 @@ DOCBOOKS := z8530book.xml \ writing_usb_driver.xml networking.xml \ kernel-api.xml filesystems.xml lsm.xml kgdb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ - genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ + genericirq.xml s390-drivers.xml scsi.xml \ sh.xml regulator.xml w1.xml \ - writing_musb_glue_layer.xml iio.xml + writing_musb_glue_layer.xml ifeq ($(DOCBOOKS),) @@ -71,6 +71,7 @@ installmandocs: mandocs # no-op for the DocBook toolchain epubdocs: latexdocs: +linkcheckdocs: ### #External programs used @@ -272,6 +273,6 @@ cleandocs: $(Q)rm -rf $(call objectify, $(clean-dirs)) # Declare the contents of the .PHONY variable as phony. We keep that -# information in a variable se we can use it in if_changed and friends. +# information in a variable so we can use it in if_changed and friends. .PHONY: $(PHONY) diff --git a/Documentation/DocBook/deviceiobook.tmpl b/Documentation/DocBook/deviceiobook.tmpl deleted file mode 100644 index 54199a0dcf9a..000000000000 --- a/Documentation/DocBook/deviceiobook.tmpl +++ /dev/null @@ -1,323 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" - "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> - -<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@lxorguk.ukuu.org.uk</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 id="getting_access_to_the_device"> - <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 id="accessing_the_device"> - <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>readb_relaxed</function>, - <function>readw_relaxed</function>, <function>readl_relaxed</function>, - <function>readq_relaxed</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. - </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 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. - </para> - - <para> - 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. - </para> - -<programlisting> -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(&reg->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(&reg->ictrl); - ha->flags.ints_enabled = 0; -} -</programlisting> - - <para> - In addition to write posting, on some large multiprocessing systems - (e.g. SGI Challenge, Origin and Altix machines) posted writes won't - be strongly ordered coming from different CPUs. Thus it's important - to properly protect parts of your driver that do memory-mapped writes - with locks and use the <function>mmiowb</function> to make sure they - arrive in the order intended. Issuing a regular <function>readX - </function> will also ensure write ordering, but should only be used - when the driver has to be sure that the write has actually arrived - at the device (not that it's simply ordered with respect to other - writes), since a full <function>readX</function> is a relatively - expensive operation. - </para> - - <para> - Generally, one should use <function>mmiowb</function> prior to - releasing a spinlock that protects regions using <function>writeb - </function> or similar functions that aren't surrounded by <function> - readb</function> calls, which will ensure ordering and flushing. The - following pseudocode illustrates what might occur if write ordering - isn't guaranteed via <function>mmiowb</function> or one of the - <function>readX</function> functions. - </para> - -<programlisting> -CPU A: spin_lock_irqsave(&dev_lock, flags) -CPU A: ... -CPU A: writel(newval, ring_ptr); -CPU A: spin_unlock_irqrestore(&dev_lock, flags) - ... -CPU B: spin_lock_irqsave(&dev_lock, flags) -CPU B: writel(newval2, ring_ptr); -CPU B: ... -CPU B: spin_unlock_irqrestore(&dev_lock, flags) -</programlisting> - - <para> - In the case above, newval2 could be written to ring_ptr before - newval. Fixing it is easy though: - </para> - -<programlisting> -CPU A: spin_lock_irqsave(&dev_lock, flags) -CPU A: ... -CPU A: writel(newval, ring_ptr); -CPU A: mmiowb(); /* ensure no other writes beat us to the device */ -CPU A: spin_unlock_irqrestore(&dev_lock, flags) - ... -CPU B: spin_lock_irqsave(&dev_lock, flags) -CPU B: writel(newval2, ring_ptr); -CPU B: ... -CPU B: mmiowb(); -CPU B: spin_unlock_irqrestore(&dev_lock, flags) -</programlisting> - - <para> - See tg3.c for a real world example of how to use <function>mmiowb - </function> - </para> - - <para> - 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 <function>readb</function> 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 - <function>readb</function> call has no relation to any previous DMA - writes performed by the device. The driver can use - <function>readb_relaxed</function> 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 <function>readX_relaxed</function>. In many cases, - a majority of the driver's <function>readX</function> calls can - safely be converted to <function>readX_relaxed</function> calls, since - only a few will indicate or depend on DMA completion. - </para> - </sect1> - - </chapter> - - <chapter id="port_space_accesses"> - <title>Port Space Accesses</title> - <sect1 id="port_space_explained"> - <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 id="accessing_port_space"> - <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> -!Iarch/x86/include/asm/io.h -!Elib/pci_iomap.c - </chapter> - -</book> diff --git a/Documentation/DocBook/iio.tmpl b/Documentation/DocBook/iio.tmpl deleted file mode 100644 index e2ab6a1f223e..000000000000 --- a/Documentation/DocBook/iio.tmpl +++ /dev/null @@ -1,697 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" - "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> - -<book id="iioid"> - <bookinfo> - <title>Industrial I/O driver developer's guide </title> - - <authorgroup> - <author> - <firstname>Daniel</firstname> - <surname>Baluta</surname> - <affiliation> - <address> - <email>daniel.baluta@intel.com</email> - </address> - </affiliation> - </author> - </authorgroup> - - <copyright> - <year>2015</year> - <holder>Intel Corporation</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 version 2. - </para> - </legalnotice> - </bookinfo> - - <toc></toc> - - <chapter id="intro"> - <title>Introduction</title> - <para> - The main purpose of the Industrial I/O subsystem (IIO) is to provide - support for devices that in some sense perform either analog-to-digital - conversion (ADC) or digital-to-analog conversion (DAC) or both. The aim - is to fill the gap between the somewhat similar hwmon and input - subsystems. - Hwmon is directed at low sample rate sensors used to monitor and - control the system itself, like fan speed control or temperature - measurement. Input is, as its name suggests, focused on human interaction - input devices (keyboard, mouse, touchscreen). In some cases there is - considerable overlap between these and IIO. - </para> - <para> - Devices that fall into this category include: - <itemizedlist> - <listitem> - analog to digital converters (ADCs) - </listitem> - <listitem> - accelerometers - </listitem> - <listitem> - capacitance to digital converters (CDCs) - </listitem> - <listitem> - digital to analog converters (DACs) - </listitem> - <listitem> - gyroscopes - </listitem> - <listitem> - inertial measurement units (IMUs) - </listitem> - <listitem> - color and light sensors - </listitem> - <listitem> - magnetometers - </listitem> - <listitem> - pressure sensors - </listitem> - <listitem> - proximity sensors - </listitem> - <listitem> - temperature sensors - </listitem> - </itemizedlist> - Usually these sensors are connected via SPI or I2C. A common use case of the - sensors devices is to have combined functionality (e.g. light plus proximity - sensor). - </para> - </chapter> - <chapter id='iiosubsys'> - <title>Industrial I/O core</title> - <para> - The Industrial I/O core offers: - <itemizedlist> - <listitem> - a unified framework for writing drivers for many different types of - embedded sensors. - </listitem> - <listitem> - a standard interface to user space applications manipulating sensors. - </listitem> - </itemizedlist> - The implementation can be found under <filename> - drivers/iio/industrialio-*</filename> - </para> - <sect1 id="iiodevice"> - <title> Industrial I/O devices </title> - -!Finclude/linux/iio/iio.h iio_dev -!Fdrivers/iio/industrialio-core.c iio_device_alloc -!Fdrivers/iio/industrialio-core.c iio_device_free -!Fdrivers/iio/industrialio-core.c iio_device_register -!Fdrivers/iio/industrialio-core.c iio_device_unregister - - <para> - An IIO device usually corresponds to a single hardware sensor and it - provides all the information needed by a driver handling a device. - Let's first have a look at the functionality embedded in an IIO - device then we will show how a device driver makes use of an IIO - device. - </para> - <para> - There are two ways for a user space application to interact - with an IIO driver. - <itemizedlist> - <listitem> - <filename>/sys/bus/iio/iio:deviceX/</filename>, this - represents a hardware sensor and groups together the data - channels of the same chip. - </listitem> - <listitem> - <filename>/dev/iio:deviceX</filename>, character device node - interface used for buffered data transfer and for events information - retrieval. - </listitem> - </itemizedlist> - </para> - A typical IIO driver will register itself as an I2C or SPI driver and will - create two routines, <function> probe </function> and <function> remove - </function>. At <function>probe</function>: - <itemizedlist> - <listitem>call <function>iio_device_alloc</function>, which allocates memory - for an IIO device. - </listitem> - <listitem> initialize IIO device fields with driver specific information - (e.g. device name, device channels). - </listitem> - <listitem>call <function> iio_device_register</function>, this registers the - device with the IIO core. After this call the device is ready to accept - requests from user space applications. - </listitem> - </itemizedlist> - At <function>remove</function>, we free the resources allocated in - <function>probe</function> in reverse order: - <itemizedlist> - <listitem><function>iio_device_unregister</function>, unregister the device - from the IIO core. - </listitem> - <listitem><function>iio_device_free</function>, free the memory allocated - for the IIO device. - </listitem> - </itemizedlist> - - <sect2 id="iioattr"> <title> IIO device sysfs interface </title> - <para> - Attributes are sysfs files used to expose chip info and also allowing - applications to set various configuration parameters. For device - with index X, attributes can be found under - <filename>/sys/bus/iio/iio:deviceX/ </filename> directory. - Common attributes are: - <itemizedlist> - <listitem><filename>name</filename>, description of the physical - chip. - </listitem> - <listitem><filename>dev</filename>, shows the major:minor pair - associated with <filename>/dev/iio:deviceX</filename> node. - </listitem> - <listitem><filename>sampling_frequency_available</filename>, - available discrete set of sampling frequency values for - device. - </listitem> - </itemizedlist> - Available standard attributes for IIO devices are described in the - <filename>Documentation/ABI/testing/sysfs-bus-iio </filename> file - in the Linux kernel sources. - </para> - </sect2> - <sect2 id="iiochannel"> <title> IIO device channels </title> -!Finclude/linux/iio/iio.h iio_chan_spec structure. - <para> - An IIO device channel is a representation of a data channel. An - IIO device can have one or multiple channels. For example: - <itemizedlist> - <listitem> - a thermometer sensor has one channel representing the - temperature measurement. - </listitem> - <listitem> - a light sensor with two channels indicating the measurements in - the visible and infrared spectrum. - </listitem> - <listitem> - an accelerometer can have up to 3 channels representing - acceleration on X, Y and Z axes. - </listitem> - </itemizedlist> - An IIO channel is described by the <type> struct iio_chan_spec - </type>. A thermometer driver for the temperature sensor in the - example above would have to describe its channel as follows: - <programlisting> - static const struct iio_chan_spec temp_channel[] = { - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), - }, - }; - - </programlisting> - Channel sysfs attributes exposed to userspace are specified in - the form of <emphasis>bitmasks</emphasis>. Depending on their - shared info, attributes can be set in one of the following masks: - <itemizedlist> - <listitem><emphasis>info_mask_separate</emphasis>, attributes will - be specific to this channel</listitem> - <listitem><emphasis>info_mask_shared_by_type</emphasis>, - attributes are shared by all channels of the same type</listitem> - <listitem><emphasis>info_mask_shared_by_dir</emphasis>, attributes - are shared by all channels of the same direction </listitem> - <listitem><emphasis>info_mask_shared_by_all</emphasis>, - attributes are shared by all channels</listitem> - </itemizedlist> - When there are multiple data channels per channel type we have two - ways to distinguish between them: - <itemizedlist> - <listitem> set <emphasis> .modified</emphasis> field of <type> - iio_chan_spec</type> to 1. Modifiers are specified using - <emphasis>.channel2</emphasis> field of the same - <type>iio_chan_spec</type> structure and are used to indicate a - physically unique characteristic of the channel such as its direction - or spectral response. For example, a light sensor can have two channels, - one for infrared light and one for both infrared and visible light. - </listitem> - <listitem> set <emphasis>.indexed </emphasis> field of - <type>iio_chan_spec</type> to 1. In this case the channel is - simply another instance with an index specified by the - <emphasis>.channel</emphasis> field. - </listitem> - </itemizedlist> - Here is how we can make use of the channel's modifiers: - <programlisting> - static const struct iio_chan_spec light_channels[] = { - { - .type = IIO_INTENSITY, - .modified = 1, - .channel2 = IIO_MOD_LIGHT_IR, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ), - }, - { - .type = IIO_INTENSITY, - .modified = 1, - .channel2 = IIO_MOD_LIGHT_BOTH, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ), - }, - { - .type = IIO_LIGHT, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), - .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ), - }, - - } - </programlisting> - This channel's definition will generate two separate sysfs files - for raw data retrieval: - <itemizedlist> - <listitem> - <filename>/sys/bus/iio/iio:deviceX/in_intensity_ir_raw</filename> - </listitem> - <listitem> - <filename>/sys/bus/iio/iio:deviceX/in_intensity_both_raw</filename> - </listitem> - </itemizedlist> - one file for processed data: - <itemizedlist> - <listitem> - <filename>/sys/bus/iio/iio:deviceX/in_illuminance_input - </filename> - </listitem> - </itemizedlist> - and one shared sysfs file for sampling frequency: - <itemizedlist> - <listitem> - <filename>/sys/bus/iio/iio:deviceX/sampling_frequency. - </filename> - </listitem> - </itemizedlist> - </para> - <para> - Here is how we can make use of the channel's indexing: - <programlisting> - static const struct iio_chan_spec light_channels[] = { - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - }, - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - }, - } - </programlisting> - This will generate two separate attributes files for raw data - retrieval: - <itemizedlist> - <listitem> - <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage0_raw</filename>, - representing voltage measurement for channel 0. - </listitem> - <listitem> - <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage1_raw</filename>, - representing voltage measurement for channel 1. - </listitem> - </itemizedlist> - </para> - </sect2> - </sect1> - - <sect1 id="iiobuffer"> <title> Industrial I/O buffers </title> -!Finclude/linux/iio/buffer.h iio_buffer -!Edrivers/iio/industrialio-buffer.c - - <para> - The Industrial I/O core offers a way for continuous data capture - based on a trigger source. Multiple data channels can be read at once - from <filename>/dev/iio:deviceX</filename> character device node, - thus reducing the CPU load. - </para> - - <sect2 id="iiobuffersysfs"> - <title>IIO buffer sysfs interface </title> - <para> - An IIO buffer has an associated attributes directory under <filename> - /sys/bus/iio/iio:deviceX/buffer/</filename>. Here are the existing - attributes: - <itemizedlist> - <listitem> - <emphasis>length</emphasis>, the total number of data samples - (capacity) that can be stored by the buffer. - </listitem> - <listitem> - <emphasis>enable</emphasis>, activate buffer capture. - </listitem> - </itemizedlist> - - </para> - </sect2> - <sect2 id="iiobuffersetup"> <title> IIO buffer setup </title> - <para>The meta information associated with a channel reading - placed in a buffer is called a <emphasis> scan element </emphasis>. - The important bits configuring scan elements are exposed to - userspace applications via the <filename> - /sys/bus/iio/iio:deviceX/scan_elements/</filename> directory. This - file contains attributes of the following form: - <itemizedlist> - <listitem><emphasis>enable</emphasis>, used for enabling a channel. - If and only if its attribute is non zero, then a triggered capture - will contain data samples for this channel. - </listitem> - <listitem><emphasis>type</emphasis>, description of the scan element - data storage within the buffer and hence the form in which it is - read from user space. Format is <emphasis> - [be|le]:[s|u]bits/storagebitsXrepeat[>>shift] </emphasis>. - <itemizedlist> - <listitem> <emphasis>be</emphasis> or <emphasis>le</emphasis>, specifies - big or little endian. - </listitem> - <listitem> - <emphasis>s </emphasis>or <emphasis>u</emphasis>, specifies if - signed (2's complement) or unsigned. - </listitem> - <listitem><emphasis>bits</emphasis>, is the number of valid data - bits. - </listitem> - <listitem><emphasis>storagebits</emphasis>, is the number of bits - (after padding) that it occupies in the buffer. - </listitem> - <listitem> - <emphasis>shift</emphasis>, if specified, is the shift that needs - to be applied prior to masking out unused bits. - </listitem> - <listitem> - <emphasis>repeat</emphasis>, specifies the number of bits/storagebits - repetitions. When the repeat element is 0 or 1, then the repeat - value is omitted. - </listitem> - </itemizedlist> - </listitem> - </itemizedlist> - For example, a driver for a 3-axis accelerometer with 12 bit - resolution where data is stored in two 8-bits registers as - follows: - <programlisting> - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - |D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06) - +---+---+---+---+---+---+---+---+ - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - |D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07) - +---+---+---+---+---+---+---+---+ - </programlisting> - - will have the following scan element type for each axis: - <programlisting> - $ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type - le:s12/16>>4 - </programlisting> - A user space application will interpret data samples read from the - buffer as two byte little endian signed data, that needs a 4 bits - right shift before masking out the 12 valid bits of data. - </para> - <para> - For implementing buffer support a driver should initialize the following - fields in <type>iio_chan_spec</type> definition: - <programlisting> - struct iio_chan_spec { - /* other members */ - int scan_index - struct { - char sign; - u8 realbits; - u8 storagebits; - u8 shift; - u8 repeat; - enum iio_endian endianness; - } scan_type; - }; - </programlisting> - The driver implementing the accelerometer described above will - have the following channel definition: - <programlisting> - struct struct iio_chan_spec accel_channels[] = { - { - .type = IIO_ACCEL, - .modified = 1, - .channel2 = IIO_MOD_X, - /* other stuff here */ - .scan_index = 0, - .scan_type = { - .sign = 's', - .realbits = 12, - .storagebits = 16, - .shift = 4, - .endianness = IIO_LE, - }, - } - /* similar for Y (with channel2 = IIO_MOD_Y, scan_index = 1) - * and Z (with channel2 = IIO_MOD_Z, scan_index = 2) axis - */ - } - </programlisting> - </para> - <para> - Here <emphasis> scan_index </emphasis> defines the order in which - the enabled channels are placed inside the buffer. Channels with a lower - scan_index will be placed before channels with a higher index. Each - channel needs to have a unique scan_index. - </para> - <para> - Setting scan_index to -1 can be used to indicate that the specific - channel does not support buffered capture. In this case no entries will - be created for the channel in the scan_elements directory. - </para> - </sect2> - </sect1> - - <sect1 id="iiotrigger"> <title> Industrial I/O triggers </title> -!Finclude/linux/iio/trigger.h iio_trigger -!Edrivers/iio/industrialio-trigger.c - <para> - In many situations it is useful for a driver to be able to - capture data based on some external event (trigger) as opposed - to periodically polling for data. An IIO trigger can be provided - by a device driver that also has an IIO device based on hardware - generated events (e.g. data ready or threshold exceeded) or - provided by a separate driver from an independent interrupt - source (e.g. GPIO line connected to some external system, timer - interrupt or user space writing a specific file in sysfs). A - trigger may initiate data capture for a number of sensors and - also it may be completely unrelated to the sensor itself. - </para> - - <sect2 id="iiotrigsysfs"> <title> IIO trigger sysfs interface </title> - There are two locations in sysfs related to triggers: - <itemizedlist> - <listitem><filename>/sys/bus/iio/devices/triggerY</filename>, - this file is created once an IIO trigger is registered with - the IIO core and corresponds to trigger with index Y. Because - triggers can be very different depending on type there are few - standard attributes that we can describe here: - <itemizedlist> - <listitem> - <emphasis>name</emphasis>, trigger name that can be later - used for association with a device. - </listitem> - <listitem> - <emphasis>sampling_frequency</emphasis>, some timer based - triggers use this attribute to specify the frequency for - trigger calls. - </listitem> - </itemizedlist> - </listitem> - <listitem> - <filename>/sys/bus/iio/devices/iio:deviceX/trigger/</filename>, this - directory is created once the device supports a triggered - buffer. We can associate a trigger with our device by writing - the trigger's name in the <filename>current_trigger</filename> file. - </listitem> - </itemizedlist> - </sect2> - - <sect2 id="iiotrigattr"> <title> IIO trigger setup</title> - - <para> - Let's see a simple example of how to setup a trigger to be used - by a driver. - - <programlisting> - struct iio_trigger_ops trigger_ops = { - .set_trigger_state = sample_trigger_state, - .validate_device = sample_validate_device, - } - - struct iio_trigger *trig; - - /* first, allocate memory for our trigger */ - trig = iio_trigger_alloc(dev, "trig-%s-%d", name, idx); - - /* setup trigger operations field */ - trig->ops = &trigger_ops; - - /* now register the trigger with the IIO core */ - iio_trigger_register(trig); - </programlisting> - </para> - </sect2> - - <sect2 id="iiotrigsetup"> <title> IIO trigger ops</title> -!Finclude/linux/iio/trigger.h iio_trigger_ops - <para> - Notice that a trigger has a set of operations attached: - <itemizedlist> - <listitem> - <function>set_trigger_state</function>, switch the trigger on/off - on demand. - </listitem> - <listitem> - <function>validate_device</function>, function to validate the - device when the current trigger gets changed. - </listitem> - </itemizedlist> - </para> - </sect2> - </sect1> - <sect1 id="iiotriggered_buffer"> - <title> Industrial I/O triggered buffers </title> - <para> - Now that we know what buffers and triggers are let's see how they - work together. - </para> - <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title> -!Edrivers/iio/buffer/industrialio-triggered-buffer.c -!Finclude/linux/iio/iio.h iio_buffer_setup_ops - - - <para> - A typical triggered buffer setup looks like this: - <programlisting> - const struct iio_buffer_setup_ops sensor_buffer_setup_ops = { - .preenable = sensor_buffer_preenable, - .postenable = sensor_buffer_postenable, - .postdisable = sensor_buffer_postdisable, - .predisable = sensor_buffer_predisable, - }; - - irqreturn_t sensor_iio_pollfunc(int irq, void *p) - { - pf->timestamp = iio_get_time_ns((struct indio_dev *)p); - return IRQ_WAKE_THREAD; - } - - irqreturn_t sensor_trigger_handler(int irq, void *p) - { - u16 buf[8]; - int i = 0; - - /* read data for each active channel */ - for_each_set_bit(bit, active_scan_mask, masklength) - buf[i++] = sensor_get_data(bit) - - iio_push_to_buffers_with_timestamp(indio_dev, buf, timestamp); - - iio_trigger_notify_done(trigger); - return IRQ_HANDLED; - } - - /* setup triggered buffer, usually in probe function */ - iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc, - sensor_trigger_handler, - sensor_buffer_setup_ops); - </programlisting> - </para> - The important things to notice here are: - <itemizedlist> - <listitem><function> iio_buffer_setup_ops</function>, the buffer setup - functions to be called at predefined points in the buffer configuration - sequence (e.g. before enable, after disable). If not specified, the - IIO core uses the default <type>iio_triggered_buffer_setup_ops</type>. - </listitem> - <listitem><function>sensor_iio_pollfunc</function>, the function that - will be used as top half of poll function. It should do as little - processing as possible, because it runs in interrupt context. The most - common operation is recording of the current timestamp and for this reason - one can use the IIO core defined <function>iio_pollfunc_store_time - </function> function. - </listitem> - <listitem><function>sensor_trigger_handler</function>, the function that - will be used as bottom half of the poll function. This runs in the - context of a kernel thread and all the processing takes place here. - It usually reads data from the device and stores it in the internal - buffer together with the timestamp recorded in the top half. - </listitem> - </itemizedlist> - </sect2> - </sect1> - </chapter> - <chapter id='iioresources'> - <title> Resources </title> - IIO core may change during time so the best documentation to read is the - source code. There are several locations where you should look: - <itemizedlist> - <listitem> - <filename>drivers/iio/</filename>, contains the IIO core plus - and directories for each sensor type (e.g. accel, magnetometer, - etc.) - </listitem> - <listitem> - <filename>include/linux/iio/</filename>, contains the header - files, nice to read for the internal kernel interfaces. - </listitem> - <listitem> - <filename>include/uapi/linux/iio/</filename>, contains files to be - used by user space applications. - </listitem> - <listitem> - <filename>tools/iio/</filename>, contains tools for rapidly - testing buffers, events and device creation. - </listitem> - <listitem> - <filename>drivers/staging/iio/</filename>, contains code for some - drivers or experimental features that are not yet mature enough - to be moved out. - </listitem> - </itemizedlist> - <para> - Besides the code, there are some good online documentation sources: - <itemizedlist> - <listitem> - <ulink url="http://marc.info/?l=linux-iio"> Industrial I/O mailing - list </ulink> - </listitem> - <listitem> - <ulink url="http://wiki.analog.com/software/linux/docs/iio/iio"> - Analog Device IIO wiki page </ulink> - </listitem> - <listitem> - <ulink url="https://fosdem.org/2015/schedule/event/iiosdr/"> - Using the Linux IIO framework for SDR, Lars-Peter Clausen's - presentation at FOSDEM </ulink> - </listitem> - </itemizedlist> - </para> - </chapter> -</book> - -<!-- -vim: softtabstop=2:shiftwidth=2:expandtab:textwidth=72 ---> diff --git a/Documentation/DocBook/kgdb.tmpl b/Documentation/DocBook/kgdb.tmpl index f3abca7ec53d..856ac20bf367 100644 --- a/Documentation/DocBook/kgdb.tmpl +++ b/Documentation/DocBook/kgdb.tmpl @@ -115,12 +115,12 @@ </para> <para> If the architecture that you are using supports the kernel option - CONFIG_DEBUG_RODATA, you should consider turning it off. This + CONFIG_STRICT_KERNEL_RWX, you should consider turning it off. This option will prevent the use of software breakpoints because it marks certain regions of the kernel's memory space as read-only. If kgdb supports it for the architecture you are using, you can use hardware breakpoints if you desire to run with the - CONFIG_DEBUG_RODATA option turned on, else you need to turn off + CONFIG_STRICT_KERNEL_RWX option turned on, else you need to turn off this option. </para> <para> @@ -135,7 +135,7 @@ <para>Here is an example set of .config symbols to enable or disable for kgdb: <itemizedlist> - <listitem><para># CONFIG_DEBUG_RODATA is not set</para></listitem> + <listitem><para># CONFIG_STRICT_KERNEL_RWX is not set</para></listitem> <listitem><para>CONFIG_FRAME_POINTER=y</para></listitem> <listitem><para>CONFIG_KGDB=y</para></listitem> <listitem><para>CONFIG_KGDB_SERIAL_CONSOLE=y</para></listitem> @@ -166,7 +166,7 @@ </para> <para>Here is an example set of .config symbols to enable/disable kdb: <itemizedlist> - <listitem><para># CONFIG_DEBUG_RODATA is not set</para></listitem> + <listitem><para># CONFIG_STRICT_KERNEL_RWX is not set</para></listitem> <listitem><para>CONFIG_FRAME_POINTER=y</para></listitem> <listitem><para>CONFIG_KGDB=y</para></listitem> <listitem><para>CONFIG_KGDB_SERIAL_CONSOLE=y</para></listitem> diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl index d7fcdc5a4379..0320910b866d 100644 --- a/Documentation/DocBook/libata.tmpl +++ b/Documentation/DocBook/libata.tmpl @@ -1020,7 +1020,7 @@ and other resources, etc. </itemizedlist> <para> - Of errors detected as above, the followings are not ATA/ATAPI + Of errors detected as above, the following are not ATA/ATAPI device errors but ATA bus errors and should be handled according to <xref linkend="excatATAbusErr"/>. </para> diff --git a/Documentation/DocBook/regulator.tmpl b/Documentation/DocBook/regulator.tmpl deleted file mode 100644 index 3b08a085d2c7..000000000000 --- a/Documentation/DocBook/regulator.tmpl +++ /dev/null @@ -1,304 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" - "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> - -<book id="regulator-api"> - <bookinfo> - <title>Voltage and current regulator API</title> - - <authorgroup> - <author> - <firstname>Liam</firstname> - <surname>Girdwood</surname> - <affiliation> - <address> - <email>lrg@slimlogic.co.uk</email> - </address> - </affiliation> - </author> - <author> - <firstname>Mark</firstname> - <surname>Brown</surname> - <affiliation> - <orgname>Wolfson Microelectronics</orgname> - <address> - <email>broonie@opensource.wolfsonmicro.com</email> - </address> - </affiliation> - </author> - </authorgroup> - - <copyright> - <year>2007-2008</year> - <holder>Wolfson Microelectronics</holder> - </copyright> - <copyright> - <year>2008</year> - <holder>Liam Girdwood</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 version 2 as published by the Free Software Foundation. - </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> - This framework is designed to provide a standard kernel - interface to control voltage and current regulators. - </para> - <para> - The intention is to allow systems to dynamically control - regulator power output in order to save power and prolong - battery life. This applies to both voltage regulators (where - voltage output is controllable) and current sinks (where current - limit is controllable). - </para> - <para> - Note that additional (and currently more complete) documentation - is available in the Linux kernel source under - <filename>Documentation/power/regulator</filename>. - </para> - - <sect1 id="glossary"> - <title>Glossary</title> - <para> - The regulator API uses a number of terms which may not be - familiar: - </para> - <glossary> - - <glossentry> - <glossterm>Regulator</glossterm> - <glossdef> - <para> - Electronic device that supplies power to other devices. Most - regulators can enable and disable their output and some can also - control their output voltage or current. - </para> - </glossdef> - </glossentry> - - <glossentry> - <glossterm>Consumer</glossterm> - <glossdef> - <para> - Electronic device which consumes power provided by a regulator. - These may either be static, requiring only a fixed supply, or - dynamic, requiring active management of the regulator at - runtime. - </para> - </glossdef> - </glossentry> - - <glossentry> - <glossterm>Power Domain</glossterm> - <glossdef> - <para> - The electronic circuit supplied by a given regulator, including - the regulator and all consumer devices. The configuration of - the regulator is shared between all the components in the - circuit. - </para> - </glossdef> - </glossentry> - - <glossentry> - <glossterm>Power Management Integrated Circuit</glossterm> - <acronym>PMIC</acronym> - <glossdef> - <para> - An IC which contains numerous regulators and often also other - subsystems. In an embedded system the primary PMIC is often - equivalent to a combination of the PSU and southbridge in a - desktop system. - </para> - </glossdef> - </glossentry> - </glossary> - </sect1> - </chapter> - - <chapter id="consumer"> - <title>Consumer driver interface</title> - <para> - This offers a similar API to the kernel clock framework. - Consumer drivers use <link - linkend='API-regulator-get'>get</link> and <link - linkend='API-regulator-put'>put</link> operations to acquire and - release regulators. Functions are - provided to <link linkend='API-regulator-enable'>enable</link> - and <link linkend='API-regulator-disable'>disable</link> the - regulator and to get and set the runtime parameters of the - regulator. - </para> - <para> - When requesting regulators consumers use symbolic names for their - supplies, such as "Vcc", which are mapped into actual regulator - devices by the machine interface. - </para> - <para> - A stub version of this API is provided when the regulator - framework is not in use in order to minimise the need to use - ifdefs. - </para> - - <sect1 id="consumer-enable"> - <title>Enabling and disabling</title> - <para> - The regulator API provides reference counted enabling and - disabling of regulators. Consumer devices use the <function><link - linkend='API-regulator-enable'>regulator_enable</link></function> - and <function><link - linkend='API-regulator-disable'>regulator_disable</link> - </function> functions to enable and disable regulators. Calls - to the two functions must be balanced. - </para> - <para> - Note that since multiple consumers may be using a regulator and - machine constraints may not allow the regulator to be disabled - there is no guarantee that calling - <function>regulator_disable</function> will actually cause the - supply provided by the regulator to be disabled. Consumer - drivers should assume that the regulator may be enabled at all - times. - </para> - </sect1> - - <sect1 id="consumer-config"> - <title>Configuration</title> - <para> - Some consumer devices may need to be able to dynamically - configure their supplies. For example, MMC drivers may need to - select the correct operating voltage for their cards. This may - be done while the regulator is enabled or disabled. - </para> - <para> - The <function><link - linkend='API-regulator-set-voltage'>regulator_set_voltage</link> - </function> and <function><link - linkend='API-regulator-set-current-limit' - >regulator_set_current_limit</link> - </function> functions provide the primary interface for this. - Both take ranges of voltages and currents, supporting drivers - that do not require a specific value (eg, CPU frequency scaling - normally permits the CPU to use a wider range of supply - voltages at lower frequencies but does not require that the - supply voltage be lowered). Where an exact value is required - both minimum and maximum values should be identical. - </para> - </sect1> - - <sect1 id="consumer-callback"> - <title>Callbacks</title> - <para> - Callbacks may also be <link - linkend='API-regulator-register-notifier'>registered</link> - for events such as regulation failures. - </para> - </sect1> - </chapter> - - <chapter id="driver"> - <title>Regulator driver interface</title> - <para> - Drivers for regulator chips <link - linkend='API-regulator-register'>register</link> the regulators - with the regulator core, providing operations structures to the - core. A <link - linkend='API-regulator-notifier-call-chain'>notifier</link> interface - allows error conditions to be reported to the core. - </para> - <para> - Registration should be triggered by explicit setup done by the - platform, supplying a <link - linkend='API-struct-regulator-init-data'>struct - regulator_init_data</link> for the regulator containing - <link linkend='machine-constraint'>constraint</link> and - <link linkend='machine-supply'>supply</link> information. - </para> - </chapter> - - <chapter id="machine"> - <title>Machine interface</title> - <para> - This interface provides a way to define how regulators are - connected to consumers on a given system and what the valid - operating parameters are for the system. - </para> - - <sect1 id="machine-supply"> - <title>Supplies</title> - <para> - Regulator supplies are specified using <link - linkend='API-struct-regulator-consumer-supply'>struct - regulator_consumer_supply</link>. This is done at - <link linkend='driver'>driver registration - time</link> as part of the machine constraints. - </para> - </sect1> - - <sect1 id="machine-constraint"> - <title>Constraints</title> - <para> - As well as defining the connections the machine interface - also provides constraints defining the operations that - clients are allowed to perform and the parameters that may be - set. This is required since generally regulator devices will - offer more flexibility than it is safe to use on a given - system, for example supporting higher supply voltages than the - consumers are rated for. - </para> - <para> - This is done at <link linkend='driver'>driver - registration time</link> by providing a <link - linkend='API-struct-regulation-constraints'>struct - regulation_constraints</link>. - </para> - <para> - The constraints may also specify an initial configuration for the - regulator in the constraints, which is particularly useful for - use with static consumers. - </para> - </sect1> - </chapter> - - <chapter id="api"> - <title>API reference</title> - <para> - Due to limitations of the kernel documentation framework and the - existing layout of the source code the entire regulator API is - documented here. - </para> -!Iinclude/linux/regulator/consumer.h -!Iinclude/linux/regulator/machine.h -!Iinclude/linux/regulator/driver.h -!Edrivers/regulator/core.c - </chapter> -</book> diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl deleted file mode 100644 index 5210f8a577c6..000000000000 --- a/Documentation/DocBook/uio-howto.tmpl +++ /dev/null @@ -1,1112 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" -"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - -<book id="index"> -<bookinfo> -<title>The Userspace I/O HOWTO</title> - -<author> - <firstname>Hans-Jürgen</firstname> - <surname>Koch</surname> - <authorblurb><para>Linux developer, Linutronix</para></authorblurb> - <affiliation> - <orgname> - <ulink url="http://www.linutronix.de">Linutronix</ulink> - </orgname> - - <address> - <email>hjk@hansjkoch.de</email> - </address> - </affiliation> -</author> - -<copyright> - <year>2006-2008</year> - <holder>Hans-Jürgen Koch.</holder> -</copyright> -<copyright> - <year>2009</year> - <holder>Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)</holder> -</copyright> - -<legalnotice> -<para> -This documentation is Free Software licensed under the terms of the -GPL version 2. -</para> -</legalnotice> - -<pubdate>2006-12-11</pubdate> - -<abstract> - <para>This HOWTO describes concept and usage of Linux kernel's - Userspace I/O system.</para> -</abstract> - -<revhistory> - <revision> - <revnumber>0.10</revnumber> - <date>2016-10-17</date> - <authorinitials>sch</authorinitials> - <revremark>Added generic hyperv driver - </revremark> - </revision> - <revision> - <revnumber>0.9</revnumber> - <date>2009-07-16</date> - <authorinitials>mst</authorinitials> - <revremark>Added generic pci driver - </revremark> - </revision> - <revision> - <revnumber>0.8</revnumber> - <date>2008-12-24</date> - <authorinitials>hjk</authorinitials> - <revremark>Added name attributes in mem and portio sysfs directories. - </revremark> - </revision> - <revision> - <revnumber>0.7</revnumber> - <date>2008-12-23</date> - <authorinitials>hjk</authorinitials> - <revremark>Added generic platform drivers and offset attribute.</revremark> - </revision> - <revision> - <revnumber>0.6</revnumber> - <date>2008-12-05</date> - <authorinitials>hjk</authorinitials> - <revremark>Added description of portio sysfs attributes.</revremark> - </revision> - <revision> - <revnumber>0.5</revnumber> - <date>2008-05-22</date> - <authorinitials>hjk</authorinitials> - <revremark>Added description of write() function.</revremark> - </revision> - <revision> - <revnumber>0.4</revnumber> - <date>2007-11-26</date> - <authorinitials>hjk</authorinitials> - <revremark>Removed section about uio_dummy.</revremark> - </revision> - <revision> - <revnumber>0.3</revnumber> - <date>2007-04-29</date> - <authorinitials>hjk</authorinitials> - <revremark>Added section about userspace drivers.</revremark> - </revision> - <revision> - <revnumber>0.2</revnumber> - <date>2007-02-13</date> - <authorinitials>hjk</authorinitials> - <revremark>Update after multiple mappings were added.</revremark> - </revision> - <revision> - <revnumber>0.1</revnumber> - <date>2006-12-11</date> - <authorinitials>hjk</authorinitials> - <revremark>First draft.</revremark> - </revision> -</revhistory> -</bookinfo> - -<chapter id="aboutthisdoc"> -<?dbhtml filename="aboutthis.html"?> -<title>About this document</title> - -<sect1 id="translations"> -<?dbhtml filename="translations.html"?> -<title>Translations</title> - -<para>If you know of any translations for this document, or you are -interested in translating it, please email me -<email>hjk@hansjkoch.de</email>. -</para> -</sect1> - -<sect1 id="preface"> -<title>Preface</title> - <para> - For many types of devices, creating a Linux kernel driver is - overkill. All that is really needed is some way to handle an - interrupt and provide access to the memory space of the - device. The logic of controlling the device does not - necessarily have to be within the kernel, as the device does - not need to take advantage of any of other resources that the - kernel provides. One such common class of devices that are - like this are for industrial I/O cards. - </para> - <para> - To address this situation, the userspace I/O system (UIO) was - designed. For typical industrial I/O cards, only a very small - kernel module is needed. The main part of the driver will run in - user space. This simplifies development and reduces the risk of - serious bugs within a kernel module. - </para> - <para> - Please note that UIO is not an universal driver interface. Devices - that are already handled well by other kernel subsystems (like - networking or serial or USB) are no candidates for an UIO driver. - Hardware that is ideally suited for an UIO driver fulfills all of - the following: - </para> -<itemizedlist> -<listitem> - <para>The device has memory that can be mapped. The device can be - controlled completely by writing to this memory.</para> -</listitem> -<listitem> - <para>The device usually generates interrupts.</para> -</listitem> -<listitem> - <para>The device does not fit into one of the standard kernel - subsystems.</para> -</listitem> -</itemizedlist> -</sect1> - -<sect1 id="thanks"> -<title>Acknowledgments</title> - <para>I'd like to thank Thomas Gleixner and Benedikt Spranger of - Linutronix, who have not only written most of the UIO code, but also - helped greatly writing this HOWTO by giving me all kinds of background - information.</para> -</sect1> - -<sect1 id="feedback"> -<title>Feedback</title> - <para>Find something wrong with this document? (Or perhaps something - right?) I would love to hear from you. Please email me at - <email>hjk@hansjkoch.de</email>.</para> -</sect1> -</chapter> - -<chapter id="about"> -<?dbhtml filename="about.html"?> -<title>About UIO</title> - -<para>If you use UIO for your card's driver, here's what you get:</para> - -<itemizedlist> -<listitem> - <para>only one small kernel module to write and maintain.</para> -</listitem> -<listitem> - <para>develop the main part of your driver in user space, - with all the tools and libraries you're used to.</para> -</listitem> -<listitem> - <para>bugs in your driver won't crash the kernel.</para> -</listitem> -<listitem> - <para>updates of your driver can take place without recompiling - the kernel.</para> -</listitem> -</itemizedlist> - -<sect1 id="how_uio_works"> -<title>How UIO works</title> - <para> - Each UIO device is accessed through a device file and several - sysfs attribute files. The device file will be called - <filename>/dev/uio0</filename> for the first device, and - <filename>/dev/uio1</filename>, <filename>/dev/uio2</filename> - and so on for subsequent devices. - </para> - - <para><filename>/dev/uioX</filename> is used to access the - address space of the card. Just use - <function>mmap()</function> to access registers or RAM - locations of your card. - </para> - - <para> - Interrupts are handled by reading from - <filename>/dev/uioX</filename>. A blocking - <function>read()</function> from - <filename>/dev/uioX</filename> will return as soon as an - interrupt occurs. You can also use - <function>select()</function> on - <filename>/dev/uioX</filename> to wait for an interrupt. The - integer value read from <filename>/dev/uioX</filename> - represents the total interrupt count. You can use this number - to figure out if you missed some interrupts. - </para> - <para> - For some hardware that has more than one interrupt source internally, - but not separate IRQ mask and status registers, there might be - situations where userspace cannot determine what the interrupt source - was if the kernel handler disables them by writing to the chip's IRQ - register. In such a case, the kernel has to disable the IRQ completely - to leave the chip's register untouched. Now the userspace part can - determine the cause of the interrupt, but it cannot re-enable - interrupts. Another cornercase is chips where re-enabling interrupts - is a read-modify-write operation to a combined IRQ status/acknowledge - register. This would be racy if a new interrupt occurred - simultaneously. - </para> - <para> - To address these problems, UIO also implements a write() function. It - is normally not used and can be ignored for hardware that has only a - single interrupt source or has separate IRQ mask and status registers. - If you need it, however, a write to <filename>/dev/uioX</filename> - will call the <function>irqcontrol()</function> function implemented - by the driver. You have to write a 32-bit value that is usually either - 0 or 1 to disable or enable interrupts. If a driver does not implement - <function>irqcontrol()</function>, <function>write()</function> will - return with <varname>-ENOSYS</varname>. - </para> - - <para> - To handle interrupts properly, your custom kernel module can - provide its own interrupt handler. It will automatically be - called by the built-in handler. - </para> - - <para> - For cards that don't generate interrupts but need to be - polled, there is the possibility to set up a timer that - triggers the interrupt handler at configurable time intervals. - This interrupt simulation is done by calling - <function>uio_event_notify()</function> - from the timer's event handler. - </para> - - <para> - Each driver provides attributes that are used to read or write - variables. These attributes are accessible through sysfs - files. A custom kernel driver module can add its own - attributes to the device owned by the uio driver, but not added - to the UIO device itself at this time. This might change in the - future if it would be found to be useful. - </para> - - <para> - The following standard attributes are provided by the UIO - framework: - </para> -<itemizedlist> -<listitem> - <para> - <filename>name</filename>: The name of your device. It is - recommended to use the name of your kernel module for this. - </para> -</listitem> -<listitem> - <para> - <filename>version</filename>: A version string defined by your - driver. This allows the user space part of your driver to deal - with different versions of the kernel module. - </para> -</listitem> -<listitem> - <para> - <filename>event</filename>: The total number of interrupts - handled by the driver since the last time the device node was - read. - </para> -</listitem> -</itemizedlist> -<para> - These attributes appear under the - <filename>/sys/class/uio/uioX</filename> directory. Please - note that this directory might be a symlink, and not a real - directory. Any userspace code that accesses it must be able - to handle this. -</para> -<para> - Each UIO device can make one or more memory regions available for - memory mapping. This is necessary because some industrial I/O cards - require access to more than one PCI memory region in a driver. -</para> -<para> - Each mapping has its own directory in sysfs, the first mapping - appears as <filename>/sys/class/uio/uioX/maps/map0/</filename>. - Subsequent mappings create directories <filename>map1/</filename>, - <filename>map2/</filename>, and so on. These directories will only - appear if the size of the mapping is not 0. -</para> -<para> - Each <filename>mapX/</filename> directory contains four read-only files - that show attributes of the memory: -</para> -<itemizedlist> -<listitem> - <para> - <filename>name</filename>: A string identifier for this mapping. This - is optional, the string can be empty. Drivers can set this to make it - easier for userspace to find the correct mapping. - </para> -</listitem> -<listitem> - <para> - <filename>addr</filename>: The address of memory that can be mapped. - </para> -</listitem> -<listitem> - <para> - <filename>size</filename>: The size, in bytes, of the memory - pointed to by addr. - </para> -</listitem> -<listitem> - <para> - <filename>offset</filename>: The offset, in bytes, that has to be - added to the pointer returned by <function>mmap()</function> to get - to the actual device memory. This is important if the device's memory - is not page aligned. Remember that pointers returned by - <function>mmap()</function> are always page aligned, so it is good - style to always add this offset. - </para> -</listitem> -</itemizedlist> - -<para> - From userspace, the different mappings are distinguished by adjusting - the <varname>offset</varname> parameter of the - <function>mmap()</function> call. To map the memory of mapping N, you - have to use N times the page size as your offset: -</para> -<programlisting format="linespecific"> -offset = N * getpagesize(); -</programlisting> - -<para> - Sometimes there is hardware with memory-like regions that can not be - mapped with the technique described here, but there are still ways to - access them from userspace. The most common example are x86 ioports. - On x86 systems, userspace can access these ioports using - <function>ioperm()</function>, <function>iopl()</function>, - <function>inb()</function>, <function>outb()</function>, and similar - functions. -</para> -<para> - Since these ioport regions can not be mapped, they will not appear under - <filename>/sys/class/uio/uioX/maps/</filename> like the normal memory - described above. Without information about the port regions a hardware - has to offer, it becomes difficult for the userspace part of the - driver to find out which ports belong to which UIO device. -</para> -<para> - To address this situation, the new directory - <filename>/sys/class/uio/uioX/portio/</filename> was added. It only - exists if the driver wants to pass information about one or more port - regions to userspace. If that is the case, subdirectories named - <filename>port0</filename>, <filename>port1</filename>, and so on, - will appear underneath - <filename>/sys/class/uio/uioX/portio/</filename>. -</para> -<para> - Each <filename>portX/</filename> directory contains four read-only - files that show name, start, size, and type of the port region: -</para> -<itemizedlist> -<listitem> - <para> - <filename>name</filename>: A string identifier for this port region. - The string is optional and can be empty. Drivers can set it to make it - easier for userspace to find a certain port region. - </para> -</listitem> -<listitem> - <para> - <filename>start</filename>: The first port of this region. - </para> -</listitem> -<listitem> - <para> - <filename>size</filename>: The number of ports in this region. - </para> -</listitem> -<listitem> - <para> - <filename>porttype</filename>: A string describing the type of port. - </para> -</listitem> -</itemizedlist> - - -</sect1> -</chapter> - -<chapter id="custom_kernel_module" xreflabel="Writing your own kernel module"> -<?dbhtml filename="custom_kernel_module.html"?> -<title>Writing your own kernel module</title> - <para> - Please have a look at <filename>uio_cif.c</filename> as an - example. The following paragraphs explain the different - sections of this file. - </para> - -<sect1 id="uio_info"> -<title>struct uio_info</title> - <para> - This structure tells the framework the details of your driver, - Some of the members are required, others are optional. - </para> - -<itemizedlist> -<listitem><para> -<varname>const char *name</varname>: Required. The name of your driver as -it will appear in sysfs. I recommend using the name of your module for this. -</para></listitem> - -<listitem><para> -<varname>const char *version</varname>: Required. This string appears in -<filename>/sys/class/uio/uioX/version</filename>. -</para></listitem> - -<listitem><para> -<varname>struct uio_mem mem[ MAX_UIO_MAPS ]</varname>: Required if you -have memory that can be mapped with <function>mmap()</function>. For each -mapping you need to fill one of the <varname>uio_mem</varname> structures. -See the description below for details. -</para></listitem> - -<listitem><para> -<varname>struct uio_port port[ MAX_UIO_PORTS_REGIONS ]</varname>: Required -if you want to pass information about ioports to userspace. For each port -region you need to fill one of the <varname>uio_port</varname> structures. -See the description below for details. -</para></listitem> - -<listitem><para> -<varname>long irq</varname>: Required. If your hardware generates an -interrupt, it's your modules task to determine the irq number during -initialization. If you don't have a hardware generated interrupt but -want to trigger the interrupt handler in some other way, set -<varname>irq</varname> to <varname>UIO_IRQ_CUSTOM</varname>. -If you had no interrupt at all, you could set -<varname>irq</varname> to <varname>UIO_IRQ_NONE</varname>, though this -rarely makes sense. -</para></listitem> - -<listitem><para> -<varname>unsigned long irq_flags</varname>: Required if you've set -<varname>irq</varname> to a hardware interrupt number. The flags given -here will be used in the call to <function>request_irq()</function>. -</para></listitem> - -<listitem><para> -<varname>int (*mmap)(struct uio_info *info, struct vm_area_struct -*vma)</varname>: Optional. If you need a special -<function>mmap()</function> function, you can set it here. If this -pointer is not NULL, your <function>mmap()</function> will be called -instead of the built-in one. -</para></listitem> - -<listitem><para> -<varname>int (*open)(struct uio_info *info, struct inode *inode) -</varname>: Optional. You might want to have your own -<function>open()</function>, e.g. to enable interrupts only when your -device is actually used. -</para></listitem> - -<listitem><para> -<varname>int (*release)(struct uio_info *info, struct inode *inode) -</varname>: Optional. If you define your own -<function>open()</function>, you will probably also want a custom -<function>release()</function> function. -</para></listitem> - -<listitem><para> -<varname>int (*irqcontrol)(struct uio_info *info, s32 irq_on) -</varname>: Optional. If you need to be able to enable or disable -interrupts from userspace by writing to <filename>/dev/uioX</filename>, -you can implement this function. The parameter <varname>irq_on</varname> -will be 0 to disable interrupts and 1 to enable them. -</para></listitem> -</itemizedlist> - -<para> -Usually, your device will have one or more memory regions that can be mapped -to user space. For each region, you have to set up a -<varname>struct uio_mem</varname> in the <varname>mem[]</varname> array. -Here's a description of the fields of <varname>struct uio_mem</varname>: -</para> - -<itemizedlist> -<listitem><para> -<varname>const char *name</varname>: Optional. Set this to help identify -the memory region, it will show up in the corresponding sysfs node. -</para></listitem> - -<listitem><para> -<varname>int memtype</varname>: Required if the mapping is used. Set this to -<varname>UIO_MEM_PHYS</varname> if you you have physical memory on your -card to be mapped. Use <varname>UIO_MEM_LOGICAL</varname> for logical -memory (e.g. allocated with <function>kmalloc()</function>). There's also -<varname>UIO_MEM_VIRTUAL</varname> for virtual memory. -</para></listitem> - -<listitem><para> -<varname>phys_addr_t addr</varname>: Required if the mapping is used. -Fill in the address of your memory block. This address is the one that -appears in sysfs. -</para></listitem> - -<listitem><para> -<varname>resource_size_t size</varname>: Fill in the size of the -memory block that <varname>addr</varname> points to. If <varname>size</varname> -is zero, the mapping is considered unused. Note that you -<emphasis>must</emphasis> initialize <varname>size</varname> with zero for -all unused mappings. -</para></listitem> - -<listitem><para> -<varname>void *internal_addr</varname>: If you have to access this memory -region from within your kernel module, you will want to map it internally by -using something like <function>ioremap()</function>. Addresses -returned by this function cannot be mapped to user space, so you must not -store it in <varname>addr</varname>. Use <varname>internal_addr</varname> -instead to remember such an address. -</para></listitem> -</itemizedlist> - -<para> -Please do not touch the <varname>map</varname> element of -<varname>struct uio_mem</varname>! It is used by the UIO framework -to set up sysfs files for this mapping. Simply leave it alone. -</para> - -<para> -Sometimes, your device can have one or more port regions which can not be -mapped to userspace. But if there are other possibilities for userspace to -access these ports, it makes sense to make information about the ports -available in sysfs. For each region, you have to set up a -<varname>struct uio_port</varname> in the <varname>port[]</varname> array. -Here's a description of the fields of <varname>struct uio_port</varname>: -</para> - -<itemizedlist> -<listitem><para> -<varname>char *porttype</varname>: Required. Set this to one of the predefined -constants. Use <varname>UIO_PORT_X86</varname> for the ioports found in x86 -architectures. -</para></listitem> - -<listitem><para> -<varname>unsigned long start</varname>: Required if the port region is used. -Fill in the number of the first port of this region. -</para></listitem> - -<listitem><para> -<varname>unsigned long size</varname>: Fill in the number of ports in this -region. If <varname>size</varname> is zero, the region is considered unused. -Note that you <emphasis>must</emphasis> initialize <varname>size</varname> -with zero for all unused regions. -</para></listitem> -</itemizedlist> - -<para> -Please do not touch the <varname>portio</varname> element of -<varname>struct uio_port</varname>! It is used internally by the UIO -framework to set up sysfs files for this region. Simply leave it alone. -</para> - -</sect1> - -<sect1 id="adding_irq_handler"> -<title>Adding an interrupt handler</title> - <para> - What you need to do in your interrupt handler depends on your - hardware and on how you want to handle it. You should try to - keep the amount of code in your kernel interrupt handler low. - If your hardware requires no action that you - <emphasis>have</emphasis> to perform after each interrupt, - then your handler can be empty.</para> <para>If, on the other - hand, your hardware <emphasis>needs</emphasis> some action to - be performed after each interrupt, then you - <emphasis>must</emphasis> do it in your kernel module. Note - that you cannot rely on the userspace part of your driver. Your - userspace program can terminate at any time, possibly leaving - your hardware in a state where proper interrupt handling is - still required. - </para> - - <para> - There might also be applications where you want to read data - from your hardware at each interrupt and buffer it in a piece - of kernel memory you've allocated for that purpose. With this - technique you could avoid loss of data if your userspace - program misses an interrupt. - </para> - - <para> - A note on shared interrupts: Your driver should support - interrupt sharing whenever this is possible. It is possible if - and only if your driver can detect whether your hardware has - triggered the interrupt or not. This is usually done by looking - at an interrupt status register. If your driver sees that the - IRQ bit is actually set, it will perform its actions, and the - handler returns IRQ_HANDLED. If the driver detects that it was - not your hardware that caused the interrupt, it will do nothing - and return IRQ_NONE, allowing the kernel to call the next - possible interrupt handler. - </para> - - <para> - If you decide not to support shared interrupts, your card - won't work in computers with no free interrupts. As this - frequently happens on the PC platform, you can save yourself a - lot of trouble by supporting interrupt sharing. - </para> -</sect1> - -<sect1 id="using_uio_pdrv"> -<title>Using uio_pdrv for platform devices</title> - <para> - In many cases, UIO drivers for platform devices can be handled in a - generic way. In the same place where you define your - <varname>struct platform_device</varname>, you simply also implement - your interrupt handler and fill your - <varname>struct uio_info</varname>. A pointer to this - <varname>struct uio_info</varname> is then used as - <varname>platform_data</varname> for your platform device. - </para> - <para> - You also need to set up an array of <varname>struct resource</varname> - containing addresses and sizes of your memory mappings. This - information is passed to the driver using the - <varname>.resource</varname> and <varname>.num_resources</varname> - elements of <varname>struct platform_device</varname>. - </para> - <para> - You now have to set the <varname>.name</varname> element of - <varname>struct platform_device</varname> to - <varname>"uio_pdrv"</varname> to use the generic UIO platform device - driver. This driver will fill the <varname>mem[]</varname> array - according to the resources given, and register the device. - </para> - <para> - The advantage of this approach is that you only have to edit a file - you need to edit anyway. You do not have to create an extra driver. - </para> -</sect1> - -<sect1 id="using_uio_pdrv_genirq"> -<title>Using uio_pdrv_genirq for platform devices</title> - <para> - Especially in embedded devices, you frequently find chips where the - irq pin is tied to its own dedicated interrupt line. In such cases, - where you can be really sure the interrupt is not shared, we can take - the concept of <varname>uio_pdrv</varname> one step further and use a - generic interrupt handler. That's what - <varname>uio_pdrv_genirq</varname> does. - </para> - <para> - The setup for this driver is the same as described above for - <varname>uio_pdrv</varname>, except that you do not implement an - interrupt handler. The <varname>.handler</varname> element of - <varname>struct uio_info</varname> must remain - <varname>NULL</varname>. The <varname>.irq_flags</varname> element - must not contain <varname>IRQF_SHARED</varname>. - </para> - <para> - You will set the <varname>.name</varname> element of - <varname>struct platform_device</varname> to - <varname>"uio_pdrv_genirq"</varname> to use this driver. - </para> - <para> - The generic interrupt handler of <varname>uio_pdrv_genirq</varname> - will simply disable the interrupt line using - <function>disable_irq_nosync()</function>. After doing its work, - userspace can reenable the interrupt by writing 0x00000001 to the UIO - device file. The driver already implements an - <function>irq_control()</function> to make this possible, you must not - implement your own. - </para> - <para> - Using <varname>uio_pdrv_genirq</varname> not only saves a few lines of - interrupt handler code. You also do not need to know anything about - the chip's internal registers to create the kernel part of the driver. - All you need to know is the irq number of the pin the chip is - connected to. - </para> -</sect1> - -<sect1 id="using-uio_dmem_genirq"> -<title>Using uio_dmem_genirq for platform devices</title> - <para> - In addition to statically allocated memory ranges, they may also be - a desire to use dynamically allocated regions in a user space driver. - In particular, being able to access memory made available through the - dma-mapping API, may be particularly useful. The - <varname>uio_dmem_genirq</varname> driver provides a way to accomplish - this. - </para> - <para> - This driver is used in a similar manner to the - <varname>"uio_pdrv_genirq"</varname> driver with respect to interrupt - configuration and handling. - </para> - <para> - Set the <varname>.name</varname> element of - <varname>struct platform_device</varname> to - <varname>"uio_dmem_genirq"</varname> to use this driver. - </para> - <para> - When using this driver, fill in the <varname>.platform_data</varname> - element of <varname>struct platform_device</varname>, which is of type - <varname>struct uio_dmem_genirq_pdata</varname> and which contains the - following elements: - </para> - <itemizedlist> - <listitem><para><varname>struct uio_info uioinfo</varname>: The same - structure used as the <varname>uio_pdrv_genirq</varname> platform - data</para></listitem> - <listitem><para><varname>unsigned int *dynamic_region_sizes</varname>: - Pointer to list of sizes of dynamic memory regions to be mapped into - user space. - </para></listitem> - <listitem><para><varname>unsigned int num_dynamic_regions</varname>: - Number of elements in <varname>dynamic_region_sizes</varname> array. - </para></listitem> - </itemizedlist> - <para> - The dynamic regions defined in the platform data will be appended to - the <varname> mem[] </varname> array after the platform device - resources, which implies that the total number of static and dynamic - memory regions cannot exceed <varname>MAX_UIO_MAPS</varname>. - </para> - <para> - The dynamic memory regions will be allocated when the UIO device file, - <varname>/dev/uioX</varname> is opened. - Similar to static memory resources, the memory region information for - dynamic regions is then visible via sysfs at - <varname>/sys/class/uio/uioX/maps/mapY/*</varname>. - The dynamic memory regions will be freed when the UIO device file is - closed. When no processes are holding the device file open, the address - returned to userspace is ~0. - </para> -</sect1> - -</chapter> - -<chapter id="userspace_driver" xreflabel="Writing a driver in user space"> -<?dbhtml filename="userspace_driver.html"?> -<title>Writing a driver in userspace</title> - <para> - Once you have a working kernel module for your hardware, you can - write the userspace part of your driver. You don't need any special - libraries, your driver can be written in any reasonable language, - you can use floating point numbers and so on. In short, you can - use all the tools and libraries you'd normally use for writing a - userspace application. - </para> - -<sect1 id="getting_uio_information"> -<title>Getting information about your UIO device</title> - <para> - Information about all UIO devices is available in sysfs. The - first thing you should do in your driver is check - <varname>name</varname> and <varname>version</varname> to - make sure your talking to the right device and that its kernel - driver has the version you expect. - </para> - <para> - You should also make sure that the memory mapping you need - exists and has the size you expect. - </para> - <para> - There is a tool called <varname>lsuio</varname> that lists - UIO devices and their attributes. It is available here: - </para> - <para> - <ulink url="http://www.osadl.org/projects/downloads/UIO/user/"> - http://www.osadl.org/projects/downloads/UIO/user/</ulink> - </para> - <para> - With <varname>lsuio</varname> you can quickly check if your - kernel module is loaded and which attributes it exports. - Have a look at the manpage for details. - </para> - <para> - The source code of <varname>lsuio</varname> can serve as an - example for getting information about an UIO device. - The file <filename>uio_helper.c</filename> contains a lot of - functions you could use in your userspace driver code. - </para> -</sect1> - -<sect1 id="mmap_device_memory"> -<title>mmap() device memory</title> - <para> - After you made sure you've got the right device with the - memory mappings you need, all you have to do is to call - <function>mmap()</function> to map the device's memory - to userspace. - </para> - <para> - The parameter <varname>offset</varname> of the - <function>mmap()</function> call has a special meaning - for UIO devices: It is used to select which mapping of - your device you want to map. To map the memory of - mapping N, you have to use N times the page size as - your offset: - </para> -<programlisting format="linespecific"> - offset = N * getpagesize(); -</programlisting> - <para> - N starts from zero, so if you've got only one memory - range to map, set <varname>offset = 0</varname>. - A drawback of this technique is that memory is always - mapped beginning with its start address. - </para> -</sect1> - -<sect1 id="wait_for_interrupts"> -<title>Waiting for interrupts</title> - <para> - After you successfully mapped your devices memory, you - can access it like an ordinary array. Usually, you will - perform some initialization. After that, your hardware - starts working and will generate an interrupt as soon - as it's finished, has some data available, or needs your - attention because an error occurred. - </para> - <para> - <filename>/dev/uioX</filename> is a read-only file. A - <function>read()</function> will always block until an - interrupt occurs. There is only one legal value for the - <varname>count</varname> parameter of - <function>read()</function>, and that is the size of a - signed 32 bit integer (4). Any other value for - <varname>count</varname> causes <function>read()</function> - to fail. The signed 32 bit integer read is the interrupt - count of your device. If the value is one more than the value - you read the last time, everything is OK. If the difference - is greater than one, you missed interrupts. - </para> - <para> - You can also use <function>select()</function> on - <filename>/dev/uioX</filename>. - </para> -</sect1> - -</chapter> - -<chapter id="uio_pci_generic" xreflabel="Using Generic driver for PCI cards"> -<?dbhtml filename="uio_pci_generic.html"?> -<title>Generic PCI UIO driver</title> - <para> - The generic driver is a kernel module named uio_pci_generic. - It can work with any device compliant to PCI 2.3 (circa 2002) and - any compliant PCI Express device. Using this, you only need to - write the userspace driver, removing the need to write - a hardware-specific kernel module. - </para> - -<sect1 id="uio_pci_generic_binding"> -<title>Making the driver recognize the device</title> - <para> -Since the driver does not declare any device ids, it will not get loaded -automatically and will not automatically bind to any devices, you must load it -and allocate id to the driver yourself. For example: - <programlisting> - modprobe uio_pci_generic - echo "8086 10f5" > /sys/bus/pci/drivers/uio_pci_generic/new_id - </programlisting> - </para> - <para> -If there already is a hardware specific kernel driver for your device, the -generic driver still won't bind to it, in this case if you want to use the -generic driver (why would you?) you'll have to manually unbind the hardware -specific driver and bind the generic driver, like this: - <programlisting> - echo -n 0000:00:19.0 > /sys/bus/pci/drivers/e1000e/unbind - echo -n 0000:00:19.0 > /sys/bus/pci/drivers/uio_pci_generic/bind - </programlisting> - </para> - <para> -You can verify that the device has been bound to the driver -by looking for it in sysfs, for example like the following: - <programlisting> - ls -l /sys/bus/pci/devices/0000:00:19.0/driver - </programlisting> -Which if successful should print - <programlisting> - .../0000:00:19.0/driver -> ../../../bus/pci/drivers/uio_pci_generic - </programlisting> -Note that the generic driver will not bind to old PCI 2.2 devices. -If binding the device failed, run the following command: - <programlisting> - dmesg - </programlisting> -and look in the output for failure reasons - </para> -</sect1> - -<sect1 id="uio_pci_generic_internals"> -<title>Things to know about uio_pci_generic</title> - <para> -Interrupts are handled using the Interrupt Disable bit in the PCI command -register and Interrupt Status bit in the PCI status register. All devices -compliant to PCI 2.3 (circa 2002) and all compliant PCI Express devices should -support these bits. uio_pci_generic detects this support, and won't bind to -devices which do not support the Interrupt Disable Bit in the command register. - </para> - <para> -On each interrupt, uio_pci_generic sets the Interrupt Disable bit. -This prevents the device from generating further interrupts -until the bit is cleared. The userspace driver should clear this -bit before blocking and waiting for more interrupts. - </para> -</sect1> -<sect1 id="uio_pci_generic_userspace"> -<title>Writing userspace driver using uio_pci_generic</title> - <para> -Userspace driver can use pci sysfs interface, or the -libpci libray that wraps it, to talk to the device and to -re-enable interrupts by writing to the command register. - </para> -</sect1> -<sect1 id="uio_pci_generic_example"> -<title>Example code using uio_pci_generic</title> - <para> -Here is some sample userspace driver code using uio_pci_generic: -<programlisting> -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> - -int main() -{ - int uiofd; - int configfd; - int err; - int i; - unsigned icount; - unsigned char command_high; - - uiofd = open("/dev/uio0", O_RDONLY); - if (uiofd < 0) { - perror("uio open:"); - return errno; - } - configfd = open("/sys/class/uio/uio0/device/config", O_RDWR); - if (configfd < 0) { - perror("config open:"); - return errno; - } - - /* Read and cache command value */ - err = pread(configfd, &command_high, 1, 5); - if (err != 1) { - perror("command config read:"); - return errno; - } - command_high &= ~0x4; - - for(i = 0;; ++i) { - /* Print out a message, for debugging. */ - if (i == 0) - fprintf(stderr, "Started uio test driver.\n"); - else - fprintf(stderr, "Interrupts: %d\n", icount); - - /****************************************/ - /* Here we got an interrupt from the - device. Do something to it. */ - /****************************************/ - - /* Re-enable interrupts. */ - err = pwrite(configfd, &command_high, 1, 5); - if (err != 1) { - perror("config write:"); - break; - } - - /* Wait for next interrupt. */ - err = read(uiofd, &icount, 4); - if (err != 4) { - perror("uio read:"); - break; - } - - } - return errno; -} - -</programlisting> - </para> -</sect1> - -</chapter> - -<chapter id="uio_hv_generic" xreflabel="Using Generic driver for Hyper-V VMBUS"> -<?dbhtml filename="uio_hv_generic.html"?> -<title>Generic Hyper-V UIO driver</title> - <para> - The generic driver is a kernel module named uio_hv_generic. - It supports devices on the Hyper-V VMBus similar to uio_pci_generic - on PCI bus. - </para> - -<sect1 id="uio_hv_generic_binding"> -<title>Making the driver recognize the device</title> - <para> -Since the driver does not declare any device GUID's, it will not get loaded -automatically and will not automatically bind to any devices, you must load it -and allocate id to the driver yourself. For example, to use the network device -GUID: - <programlisting> - modprobe uio_hv_generic - echo "f8615163-df3e-46c5-913f-f2d2f965ed0e" > /sys/bus/vmbus/drivers/uio_hv_generic/new_id - </programlisting> - </para> - <para> -If there already is a hardware specific kernel driver for the device, the -generic driver still won't bind to it, in this case if you want to use the -generic driver (why would you?) you'll have to manually unbind the hardware -specific driver and bind the generic driver, like this: - <programlisting> - echo -n vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3 > /sys/bus/vmbus/drivers/hv_netvsc/unbind - echo -n vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3 > /sys/bus/vmbus/drivers/uio_hv_generic/bind - </programlisting> - </para> - <para> -You can verify that the device has been bound to the driver -by looking for it in sysfs, for example like the following: - <programlisting> - ls -l /sys/bus/vmbus/devices/vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3/driver - </programlisting> -Which if successful should print - <programlisting> - .../vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3/driver -> ../../../bus/vmbus/drivers/uio_hv_generic - </programlisting> - </para> -</sect1> - -<sect1 id="uio_hv_generic_internals"> -<title>Things to know about uio_hv_generic</title> - <para> -On each interrupt, uio_hv_generic sets the Interrupt Disable bit. -This prevents the device from generating further interrupts -until the bit is cleared. The userspace driver should clear this -bit before blocking and waiting for more interrupts. - </para> -</sect1> -</chapter> - -<appendix id="app1"> -<title>Further information</title> -<itemizedlist> - <listitem><para> - <ulink url="http://www.osadl.org"> - OSADL homepage.</ulink> - </para></listitem> - <listitem><para> - <ulink url="http://www.linutronix.de"> - Linutronix homepage.</ulink> - </para></listitem> -</itemizedlist> -</appendix> - -</book> |