[PATCH] doc-rst: DocBook to reST migration of the uio-howto.tmpl
From: Markus Heiser
Date: Tue Oct 18 2016 - 11:54:42 EST
The migration is done with the dbxml2rst project with small additional
handmade. The uio-howto is chunked along its chapters into smal parts.
[1] https://return42.github.io/dbxml2rst/
Signed-off-by: Markus Heiser <markus.heiser@xxxxxxxxxxx>
---
Documentation/DocBook/Makefile | 2 +-
Documentation/DocBook/uio-howto.tmpl | 1050 ----------------------
Documentation/conf.py | 2 +
Documentation/index.rst | 1 +
Documentation/uio-howto/about_uio.rst | 150 ++++
Documentation/uio-howto/aboutthisdoc.rst | 103 +++
Documentation/uio-howto/conf.py | 10 +
Documentation/uio-howto/custom_kernel_module.rst | 245 +++++
Documentation/uio-howto/index.rst | 45 +
Documentation/uio-howto/uio_pci_generic.rst | 168 ++++
Documentation/uio-howto/userspace_driver.rst | 86 ++
11 files changed, 811 insertions(+), 1051 deletions(-)
delete mode 100644 Documentation/DocBook/uio-howto.tmpl
create mode 100644 Documentation/uio-howto/about_uio.rst
create mode 100644 Documentation/uio-howto/aboutthisdoc.rst
create mode 100644 Documentation/uio-howto/conf.py
create mode 100644 Documentation/uio-howto/custom_kernel_module.rst
create mode 100644 Documentation/uio-howto/index.rst
create mode 100644 Documentation/uio-howto/uio_pci_generic.rst
create mode 100644 Documentation/uio-howto/userspace_driver.rst
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index fdf8232..26e97e2 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -11,7 +11,7 @@ DOCBOOKS := z8530book.xml \
writing_usb_driver.xml networking.xml \
kernel-api.xml filesystems.xml lsm.xml usb.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 \
debugobjects.xml sh.xml regulator.xml \
alsa-driver-api.xml writing-an-alsa-driver.xml \
tracepoint.xml w1.xml \
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
deleted file mode 100644
index cd0e452..0000000
--- a/Documentation/DocBook/uio-howto.tmpl
+++ /dev/null
@@ -1,1050 +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@xxxxxxxxxxxx</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@xxxxxxxxxx)</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.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@xxxxxxxxxxxx</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@xxxxxxxxxxxx</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>
-
-<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>
diff --git a/Documentation/conf.py b/Documentation/conf.py
index 0cc8765..867715f 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -342,6 +342,8 @@ latex_documents = [
'The kernel development community', 'manual'),
('gpu/index', 'gpu.tex', 'Linux GPU Driver Developer\'s Guide',
'The kernel development community', 'manual'),
+ ('uio-howto/index', 'uio-howto.tex', 'The Userspace I/O HOWTO',
+ 'The kernel development community', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
diff --git a/Documentation/index.rst b/Documentation/index.rst
index c53d089..246db7c 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -18,6 +18,7 @@ Contents:
media/index
gpu/index
80211/index
+ uio-howto/index
Indices and tables
==================
diff --git a/Documentation/uio-howto/about_uio.rst b/Documentation/uio-howto/about_uio.rst
new file mode 100644
index 0000000..cd9ca32
--- /dev/null
+++ b/Documentation/uio-howto/about_uio.rst
@@ -0,0 +1,150 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _about_uio:
+
+*********
+About UIO
+*********
+
+If you use UIO for your card's driver, here's what you get:
+
+- only one small kernel module to write and maintain.
+
+- develop the main part of your driver in user space, with all the
+ tools and libraries you're used to.
+
+- bugs in your driver won't crash the kernel.
+
+- updates of your driver can take place without recompiling the kernel.
+
+
+.. _how_uio_works:
+
+How UIO works
+=============
+
+Each UIO device is accessed through a device file and several sysfs attribute
+files. The device file will be called ``/dev/uio0`` for the first device, and
+``/dev/uio1``, ``/dev/uio2`` and so on for subsequent devices.
+
+``/dev/uioX`` is used to access the address space of the card. Just use
+:c:func:`mmap()` to access registers or RAM locations of your card.
+
+Interrupts are handled by reading from ``/dev/uioX``. A blocking
+:c:func:`read()` from ``/dev/uioX`` will return as soon as an interrupt
+occurs. You can also use :c:func:`select()` on ``/dev/uioX`` to wait for an
+interrupt. The integer value read from ``/dev/uioX`` represents the total
+interrupt count. You can use this number to figure out if you missed some
+interrupts.
+
+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.
+
+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 ``/dev/uioX`` will call the :c:func:`irqcontrol()` 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
+:c:func:`irqcontrol()`, :c:func:`write()` will return with ``-ENOSYS``.
+
+To handle interrupts properly, your custom kernel module can provide its own
+interrupt handler. It will automatically be called by the built-in handler.
+
+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
+:c:func:`uio_event_notify()` from the timer's event handler.
+
+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.
+
+The following standard attributes are provided by the UIO framework:
+
+- ``name``: The name of your device. It is recommended to use the name of your
+ kernel module for this.
+
+- ``version``: 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.
+
+- ``event``: The total number of interrupts handled by the driver since the last
+ time the device node was read.
+
+These attributes appear under the ``/sys/class/uio/uioX`` 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.
+
+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.
+
+Each mapping has its own directory in sysfs, the first mapping appears as
+``/sys/class/uio/uioX/maps/map0/``. Subsequent mappings create directories
+``map1/``, ``map2/``, and so on. These directories will only appear if the size
+of the mapping is not 0.
+
+Each ``mapX/`` directory contains four read-only files that show attributes of
+the memory:
+
+- ``name``: 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.
+
+- ``addr``: The address of memory that can be mapped.
+
+- ``size``: The size, in bytes, of the memory pointed to by addr.
+
+- ``offset``: The offset, in bytes, that has to be added to the pointer returned
+ by :c:func:`mmap()` to get to the actual device memory. This is important if
+ the device's memory is not page aligned. Remember that pointers returned by
+ :c:func:`mmap()` are always page aligned, so it is good style to always add
+ this offset.
+
+From userspace, the different mappings are distinguished by adjusting the
+``offset`` parameter of the :c:func:`mmap()` call. To map the memory of mapping
+N, you have to use N times the page size as your offset:
+
+.. code-block:: c
+
+ offset = N * getpagesize();
+
+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 :c:func:`ioperm()`, :c:func:`iopl()`,
+:c:func:`inb()`, :c:func:`outb()`, and similar functions.
+
+Since these ioport regions can not be mapped, they will not appear under
+``/sys/class/uio/uioX/maps/`` 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.
+
+To address this situation, the new directory ``/sys/class/uio/uioX/portio/`` 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 ``port0``,
+``port1``, and so on, will appear underneath ``/sys/class/uio/uioX/portio/``.
+
+Each ``portX/`` directory contains four read-only files that show name, start,
+size, and type of the port region:
+
+- ``name``: 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.
+
+- ``start``: The first port of this region.
+
+- ``size``: The number of ports in this region.
+
+- ``porttype``: A string describing the type of port.
diff --git a/Documentation/uio-howto/aboutthisdoc.rst b/Documentation/uio-howto/aboutthisdoc.rst
new file mode 100644
index 0000000..06e9ca6
--- /dev/null
+++ b/Documentation/uio-howto/aboutthisdoc.rst
@@ -0,0 +1,103 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+*******************
+About this document
+*******************
+
+Translations
+============
+
+If you know of any translations for this document, or you are interested in
+translating it, please email me hjk@xxxxxxxxxxxxx
+
+
+Preface
+=======
+
+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.
+
+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.
+
+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:
+
+- The device has memory that can be mapped. The device can be controlled
+ completely by writing to this memory.
+
+- The device usually generates interrupts.
+
+- The device does not fit into one of the standard kernel subsystems.
+
+
+Acknowledgments
+===============
+
+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.
+
+
+Feedback
+========
+
+Find something wrong with this document? (Or perhaps something right?) I would
+love to hear from you. Please email me at hjk@xxxxxxxxxxxxx
+
+Revision History
+================
+
+:revision: 0.9 / 2009-07-16 (*mst*)
+
+ Added generic pci driver
+
+
+:revision: 0.8 / 2008-12-24 (*hjk*)
+
+ Added name attributes in mem and portio sysfs directories.
+
+
+:revision: 0.7 / 2008-12-23 (*hjk*)
+
+ Added generic platform drivers and offset attribute.
+
+
+:revision: 0.6 / 2008-12-05 (*hjk*)
+
+ Added description of portio sysfs attributes.
+
+
+:revision: 0.5 / 2008-05-22 (*hjk*)
+
+ Added description of write() function.
+
+
+:revision: 0.4 / 2007-11-26 (*hjk*)
+
+ Removed section about uio_dummy.
+
+
+:revision: 0.3 / 2007-04-29 (*hjk*)
+
+ Added section about userspace drivers.
+
+
+:revision: 0.2 / 2007-02-13 (*hjk*)
+
+ Update after multiple mappings were added.
+
+
+:revision: 0.1 / 2006-12-11 (*hjk*)
+
+ First draft.
+
+
diff --git a/Documentation/uio-howto/conf.py b/Documentation/uio-howto/conf.py
new file mode 100644
index 0000000..c13fea7
--- /dev/null
+++ b/Documentation/uio-howto/conf.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = u'The Userspace I/O HOWTO'
+
+tags.add("subproject")
+
+latex_documents = [
+ ('index', 'uio-howto.tex', 'The Userspace I/O HOWTO',
+ 'The kernel development community', 'manual'),
+]
diff --git a/Documentation/uio-howto/custom_kernel_module.rst b/Documentation/uio-howto/custom_kernel_module.rst
new file mode 100644
index 0000000..320c420
--- /dev/null
+++ b/Documentation/uio-howto/custom_kernel_module.rst
@@ -0,0 +1,245 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _custom_kernel_module:
+
+******************************
+Writing your own kernel module
+******************************
+
+Please have a look at ``uio_cif.c`` as an example. The following paragraphs
+explain the different sections of this file.
+
+
+.. _uio_info:
+
+struct uio_info
+===============
+
+This structure tells the framework the details of your driver, Some of
+the members are required, others are optional.
+
+- ``const char *name``: Required. The name of your driver as it will appear in
+ sysfs. I recommend using the name of your module for this.
+
+- ``const char *version``: Required. This string appears in
+ ``/sys/class/uio/uioX/version``.
+
+- ``struct uio_mem mem[ MAX_UIO_MAPS ]``: Required if you have memory that can
+ be mapped with :c:func:`mmap()`. For each mapping you need to fill one of the
+ ``uio_mem`` structures. See the description below for details.
+
+- ``struct uio_port port[ MAX_UIO_PORTS_REGIONS ]``: Required if you want to
+ pass information about ioports to userspace. For each port region you need to
+ fill one of the ``uio_port`` structures. See the description below for
+ details.
+
+- ``long irq``: 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 ``irq`` to ``UIO_IRQ_CUSTOM``. If you had no interrupt
+ at all, you could set ``irq`` to ``UIO_IRQ_NONE``, though this rarely makes
+ sense.
+
+- ``unsigned long irq_flags``: Required if you've set ``irq`` to a hardware
+ interrupt number. The flags given here will be used in the call to
+ :c:func:`request_irq()`.
+
+- ``int (*mmap)(struct uio_info *info, struct vm_area_struct *vma)``:
+ Optional. If you need a special :c:func:`mmap()` function, you can set it
+ here. If this pointer is not NULL, your :c:func:`mmap()` will be called
+ instead of the built-in one.
+
+- ``int (*open)(struct uio_info *info, struct inode *inode)``: Optional. You
+ might want to have your own :c:func:`open()`, e.g. to enable interrupts only
+ when your device is actually used.
+
+- ``int (*release)(struct uio_info *info, struct inode *inode)``: Optional. If
+ you define your own :c:func:`open()`, you will probably also want a custom
+ :c:func:`release()` function.
+
+- ``int (*irqcontrol)(struct uio_info *info, s32 irq_on)``: Optional. If you
+ need to be able to enable or disable interrupts from userspace by writing to
+ ``/dev/uioX``, you can implement this function. The parameter ``irq_on`` will
+ be 0 to disable interrupts and 1 to enable them.
+
+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 ``struct uio_mem`` in the
+``mem[]`` array. Here's a description of the fields of ``struct uio_mem``:
+
+- ``const char *name``: Optional. Set this to help identify the memory region,
+ it will show up in the corresponding sysfs node.
+
+- ``int memtype``: Required if the mapping is used. Set this to ``UIO_MEM_PHYS``
+ if you you have physical memory on your card to be mapped. Use
+ ``UIO_MEM_LOGICAL`` for logical memory (e.g. allocated with
+ :c:func:`kmalloc()`). There's also ``UIO_MEM_VIRTUAL`` for virtual memory.
+
+- ``phys_addr_t addr``: Required if the mapping is used. Fill in the address of
+ your memory block. This address is the one that appears in sysfs.
+
+- ``resource_size_t size``: Fill in the size of the memory block that ``addr``
+ points to. If ``size`` is zero, the mapping is considered unused. Note that
+ you *must* initialize ``size`` with zero for all unused mappings.
+
+- ``void *internal_addr``: If you have to access this memory region from within
+ your kernel module, you will want to map it internally by using something like
+ :c:func:`ioremap()`. Addresses returned by this function cannot be mapped to
+ user space, so you must not store it in ``addr``. Use ``internal_addr``
+ instead to remember such an address.
+
+Please do not touch the ``map`` element of ``struct uio_mem``! It is used by the
+UIO framework to set up sysfs files for this mapping. Simply leave it alone.
+
+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 ``struct uio_port`` in the
+``port[]`` array. Here's a description of the fields of ``struct uio_port``:
+
+- ``char *porttype``: Required. Set this to one of the predefined constants. Use
+ ``UIO_PORT_X86`` for the ioports found in x86 architectures.
+
+- ``unsigned long start``: Required if the port region is used. Fill in the
+ number of the first port of this region.
+
+- ``unsigned long size``: Fill in the number of ports in this region. If
+ ``size`` is zero, the region is considered unused. Note that you *must*
+ initialize ``size`` with zero for all unused regions.
+
+Please do not touch the ``portio`` element of ``struct uio_port``! It is used
+internally by the UIO framework to set up sysfs files for this region. Simply
+leave it alone.
+
+
+.. _adding_irq_handler:
+
+Adding an interrupt handler
+===========================
+
+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
+*have* to perform after each interrupt, then your handler can be empty.
+
+If, on the other hand, your hardware *needs* some action to be performed after
+each interrupt, then you *must* 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.
+
+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.
+
+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.
+
+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.
+
+
+.. _using_uio_pdrv:
+
+Using uio_pdrv for platform devices
+===================================
+
+In many cases, UIO drivers for platform devices can be handled in a generic
+way. In the same place where you define your ``struct platform_device``, you
+simply also implement your interrupt handler and fill your ``struct
+uio_info``. A pointer to this ``struct uio_info`` is then used as
+``platform_data`` for your platform device.
+
+You also need to set up an array of ``struct resource`` containing addresses and
+sizes of your memory mappings. This information is passed to the driver using
+the ``.resource`` and ``.num_resources`` elements of ``struct platform_device``.
+
+You now have to set the ``.name`` element of ``struct platform_device`` to
+``"uio_pdrv"`` to use the generic UIO platform device driver. This driver will
+fill the ``mem[]`` array according to the resources given, and register the
+device.
+
+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.
+
+
+.. _using_uio_pdrv_genirq:
+
+Using uio_pdrv_genirq for platform devices
+==========================================
+
+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 ``uio_pdrv`` one
+step further and use a generic interrupt handler. That's what
+``uio_pdrv_genirq`` does.
+
+The setup for this driver is the same as described above for ``uio_pdrv``,
+except that you do not implement an interrupt handler. The ``.handler`` element
+of ``struct uio_info`` must remain ``NULL``. The ``.irq_flags`` element must not
+contain ``IRQF_SHARED``.
+
+You will set the ``.name`` element of ``struct platform_device`` to
+``"uio_pdrv_genirq"`` to use this driver.
+
+The generic interrupt handler of ``uio_pdrv_genirq`` will simply disable the
+interrupt line using :c:func:`disable_irq_nosync()`. After doing its work,
+userspace can reenable the interrupt by writing 0x00000001 to the UIO device
+file. The driver already implements an :c:func:`irq_control()` to make this
+possible, you must not implement your own.
+
+Using ``uio_pdrv_genirq`` 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.
+
+
+.. _using-uio_dmem_genirq:
+
+Using uio_dmem_genirq for platform devices
+==========================================
+
+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 ``uio_dmem_genirq`` driver provides a way to accomplish
+this.
+
+This driver is used in a similar manner to the ``"uio_pdrv_genirq"`` driver with
+respect to interrupt configuration and handling.
+
+Set the ``.name`` element of ``struct platform_device`` to ``"uio_dmem_genirq"``
+to use this driver.
+
+When using this driver, fill in the ``.platform_data`` element of ``struct
+platform_device``, which is of type ``struct uio_dmem_genirq_pdata`` and which
+contains the following elements:
+
+- ``struct uio_info uioinfo``: The same structure used as the
+ ``uio_pdrv_genirq`` platform data
+
+- ``unsigned int *dynamic_region_sizes``: Pointer to list of sizes of dynamic
+ memory regions to be mapped into user space.
+
+- ``unsigned int num_dynamic_regions``: Number of elements in
+ ``dynamic_region_sizes`` array.
+
+The dynamic regions defined in the platform data will be appended to the
+``mem[]`` array after the platform device resources, which implies that the
+total number of static and dynamic memory regions cannot exceed
+``MAX_UIO_MAPS``.
+
+The dynamic memory regions will be allocated when the UIO device file,
+``/dev/uioX`` is opened. Similar to static memory resources, the memory region
+information for dynamic regions is then visible via sysfs at
+``/sys/class/uio/uioX/maps/mapY/*``. 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.
diff --git a/Documentation/uio-howto/index.rst b/Documentation/uio-howto/index.rst
new file mode 100644
index 0000000..e010dc4
--- /dev/null
+++ b/Documentation/uio-howto/index.rst
@@ -0,0 +1,45 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _uio-howto:
+
+=======================
+The Userspace I/O HOWTO
+=======================
+
+This HOWTO describes concept and usage of Linux kernel's Userspace
+I/O system.
+
+.. toctree::
+ :maxdepth: 1
+
+ aboutthisdoc
+ about_uio
+ custom_kernel_module
+ userspace_driver
+ uio_pci_generic
+
+.. only:: subproject
+
+ Indices
+ =======
+
+ * :ref:`genindex`
+
+*******************
+Further information
+*******************
+
+- `OSADL homepage. <http://www.osadl.org>`__
+
+- `Linutronix homepage. <http://www.linutronix.de>`__
+
+*********
+Copyright
+*********
+
+This documentation is Free Software licensed under the terms of the GPL
+version 2.
+
+**Copyright** 2006-2008 : Hans-JÃrgen Koch.
+
+**Copyright** 2009 : Red Hat Inc, Michael S. Tsirkin (mst@xxxxxxxxxx)
diff --git a/Documentation/uio-howto/uio_pci_generic.rst b/Documentation/uio-howto/uio_pci_generic.rst
new file mode 100644
index 0000000..181344e
--- /dev/null
+++ b/Documentation/uio-howto/uio_pci_generic.rst
@@ -0,0 +1,168 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _uio_pci_generic:
+
+**********************
+Generic PCI UIO driver
+**********************
+
+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.
+
+
+.. _uio_pci_generic_binding:
+
+Making the driver recognize the device
+======================================
+
+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:
+
+
+.. code-block:: sh
+
+ modprobe uio_pci_generic
+ echo "8086 10f5" > /sys/bus/pci/drivers/uio_pci_generic/new_id
+
+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:
+
+
+.. code-block:: sh
+
+ 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
+
+You can verify that the device has been bound to the driver by looking
+for it in sysfs, for example like the following:
+
+
+.. code-block:: sh
+
+ ls -l /sys/bus/pci/devices/0000:00:19.0/driver
+
+Which if successful should print
+
+
+.. code-block:: sh
+
+ .../0000:00:19.0/driver -> ../../../bus/pci/drivers/uio_pci_generic
+
+Note that the generic driver will not bind to old PCI 2.2 devices. If
+binding the device failed, run the following command:
+
+
+.. code-block:: sh
+
+ dmesg
+
+and look in the output for failure reasons
+
+
+.. _uio_pci_generic_internals:
+
+Things to know about uio_pci_generic
+====================================
+
+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.
+
+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.
+
+
+.. _uio_pci_generic_userspace:
+
+Writing userspace driver using uio_pci_generic
+==============================================
+
+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.
+
+
+.. _uio_pci_generic_example:
+
+Example code using uio_pci_generic
+==================================
+
+Here is some sample userspace driver code using uio_pci_generic:
+
+.. code-block:: c
+
+ #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;
+ }
diff --git a/Documentation/uio-howto/userspace_driver.rst b/Documentation/uio-howto/userspace_driver.rst
new file mode 100644
index 0000000..fc119ba
--- /dev/null
+++ b/Documentation/uio-howto/userspace_driver.rst
@@ -0,0 +1,86 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _userspace_driver:
+
+*****************************
+Writing a driver in userspace
+*****************************
+
+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.
+
+
+.. _getting_uio_information:
+
+Getting information about your UIO device
+=========================================
+
+Information about all UIO devices is available in sysfs. The first thing
+you should do in your driver is check ``name`` and ``version`` to make
+sure your talking to the right device and that its kernel driver has the
+version you expect.
+
+You should also make sure that the memory mapping you need exists and
+has the size you expect.
+
+There is a tool called ``lsuio`` that lists UIO devices and their
+attributes. It is available here:
+
+`http://www.osadl.org/projects/downloads/UIO/user/ <http://www.osadl.org/projects/downloads/UIO/user/>`__
+
+With ``lsuio`` you can quickly check if your kernel module is loaded and
+which attributes it exports. Have a look at the manpage for details.
+
+The source code of ``lsuio`` can serve as an example for getting
+information about an UIO device. The file ``uio_helper.c`` contains a
+lot of functions you could use in your userspace driver code.
+
+
+.. _mmap_device_memory:
+
+mmap() device memory
+====================
+
+After you made sure you've got the right device with the memory mappings
+you need, all you have to do is to call :c:func:`mmap()` to map the
+device's memory to userspace.
+
+The parameter ``offset`` of the :c:func:`mmap()` 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:
+
+
+.. code-block:: c
+
+ offset = N * getpagesize();
+
+N starts from zero, so if you've got only one memory range to map, set
+``offset = 0``. A drawback of this technique is that memory is always
+mapped beginning with its start address.
+
+
+.. _wait_for_interrupts:
+
+Waiting for interrupts
+======================
+
+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.
+
+``/dev/uioX`` is a read-only file. A :c:func:`read()` will always
+block until an interrupt occurs. There is only one legal value for the
+``count`` parameter of :c:func:`read()`, and that is the size of a
+signed 32 bit integer (4). Any other value for ``count`` causes
+:c:func:`read()` 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.
+
+You can also use :c:func:`select()` on ``/dev/uioX``.
--
2.7.4