diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index fd2ef4d29b6d..a0af560ed740 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -408,6 +408,10 @@ X!Edrivers/pnp/system.c
!Edrivers/pnp/manager.c
!Edrivers/pnp/support.c
+ Userspace IO devices
+!Edrivers/uio/uio.c
+!Iinclude/linux/uio_driver.h
+
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
new file mode 100644
index 000000000000..e3bb29a8d8dd
--- /dev/null
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -0,0 +1,611 @@
+
+
+
+
+
+The Userspace I/O HOWTO
+
+
+ Hans-Jürgen
+ Koch
+ Linux developer, Linutronix
+
+
+ Linutronix
+
+
+
+ hjk@linutronix.de
+
+
+
+
+2006-12-11
+
+
+ This HOWTO describes concept and usage of Linux kernel's
+ Userspace I/O system.
+
+
+
+
+ 0.3
+ 2007-04-29
+ hjk
+ Added section about userspace drivers.
+
+
+ 0.2
+ 2007-02-13
+ hjk
+ Update after multiple mappings were added.
+
+
+ 0.1
+ 2006-12-11
+ hjk
+ First draft.
+
+
+
+
+
+
+About this document
+
+
+
+Copyright and License
+
+ Copyright (c) 2006 by Hans-Jürgen Koch.
+
+This documentation is Free Software licensed under the terms of the
+GPL version 2.
+
+
+
+
+
+Translations
+
+If you know of any translations for this document, or you are
+interested in translating it, please email me
+hjk@linutronix.de.
+
+
+
+
+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.
+
+
+
+
+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@linutronix.de.
+
+
+
+
+
+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.
+
+
+ if you need to keep some parts of your driver closed source,
+ you can do so without violating the GPL license on the kernel.
+
+
+
+
+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
+ mmap() to access registers or RAM
+ locations of your card.
+
+
+
+ Interrupts are handled by reading from
+ /dev/uioX. A blocking
+ read() from
+ /dev/uioX will return as soon as an
+ interrupt occurs. You can also use
+ 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.
+
+
+
+ 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.
+ See drivers/uio/uio_dummy.c for an
+ example of this technique.
+
+
+
+ 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 two read-only files
+ that show start address and size of the memory:
+
+
+
+
+ addr: The address of memory that can be mapped.
+
+
+
+
+ size: The size, in bytes, of the memory
+ pointed to by addr.
+
+
+
+
+
+ From userspace, the different mappings are distinguished by adjusting
+ the offset parameter of the
+ mmap() call. To map the memory of mapping N, you
+ have to use N times the page size as your offset:
+
+
+offset = N * getpagesize();
+
+
+
+
+
+
+
+Using uio_dummy
+
+ Well, there is no real use for uio_dummy. Its only purpose is
+ to test most parts of the UIO system (everything except
+ hardware interrupts), and to serve as an example for the
+ kernel module that you will have to write yourself.
+
+
+
+What uio_dummy does
+
+ The kernel module uio_dummy.ko creates a
+ device that uses a timer to generate periodic interrupts. The
+ interrupt handler does nothing but increment a counter. The
+ driver adds two custom attributes, count
+ and freq, that appear under
+ /sys/devices/platform/uio_dummy/.
+
+
+
+ The attribute count can be read and
+ written. The associated file
+ /sys/devices/platform/uio_dummy/count
+ appears as a normal text file and contains the total number of
+ timer interrupts. If you look at it (e.g. using
+ cat), you'll notice it is slowly counting
+ up.
+
+
+
+ The attribute freq can be read and written.
+ The content of
+ /sys/devices/platform/uio_dummy/freq
+ represents the number of system timer ticks between two timer
+ interrupts. The default value of freq is
+ the value of the kernel variable HZ, which
+ gives you an interval of one second. Lower values will
+ increase the frequency. Try the following:
+
+
+cd /sys/devices/platform/uio_dummy/
+echo 100 > freq
+
+
+ Use cat count to see how the interrupt
+ frequency changes.
+
+
+
+
+
+
+Writing your own kernel module
+
+ Please have a look at uio_dummy.c as an
+ example. The following paragraphs explain the different
+ sections of this file.
+
+
+
+struct uio_info
+
+ This structure tells the framework the details of your driver,
+ Some of the members are required, others are optional.
+
+
+
+
+char *name: Required. The name of your driver as
+it will appear in sysfs. I recommend using the name of your module for this.
+
+
+
+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 mmap(). For each
+mapping you need to fill one of the uio_mem 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. The
+uio_dummy module does this as it triggers the event mechanism in a timer
+routine. 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 request_irq().
+
+
+
+int (*mmap)(struct uio_info *info, struct vm_area_struct
+*vma): Optional. If you need a special
+mmap() function, you can set it here. If this
+pointer is not NULL, your 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
+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
+open(), you will probably also want a custom
+release() function.
+
+
+
+
+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:
+
+
+
+
+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 kmalloc()). There's also
+UIO_MEM_VIRTUAL for virtual memory.
+
+
+
+unsigned long addr: Required if the mapping is used.
+Fill in the address of your memory block. This address is the one that
+appears in sysfs.
+
+
+
+unsigned long 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 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 kobj element of
+struct uio_mem! It is used by the UIO framework
+to set up sysfs files for this mapping. Simply leave it alone.
+
+
+
+
+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.
+
+
+
+
+
+
+
+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 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/
+
+
+ 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
+
+ After you made sure you've got the right device with the
+ memory mappings you need, all you have to do is to call
+ mmap() to map the device's memory
+ to userspace.
+
+
+ The parameter offset of the
+ 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:
+
+
+ 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.
+
+
+
+
+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 occured.
+
+
+ /dev/uioX is a read-only file. A
+ read() will always block until an
+ interrupt occurs. There is only one legal value for the
+ count parameter of
+ read(), and that is the size of a
+ signed 32 bit integer (4). Any other value for
+ count causes 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 select() on
+ /dev/uioX.
+
+
+
+
+
+
+Further information
+
+
+
+ OSADL homepage.
+
+
+
+ Linutronix homepage.
+
+
+
+
+