* [PATCH 2/3] UIO: Documentation
2007-04-27 22:50 ` [PATCH 1/3] UIO: Add the User IO core code Greg Kroah-Hartman
@ 2007-04-27 22:50 ` Greg Kroah-Hartman
2007-05-01 23:42 ` Randy Dunlap
0 siblings, 1 reply; 32+ messages in thread
From: Greg Kroah-Hartman @ 2007-04-27 22:50 UTC (permalink / raw)
To: linux-kernel; +Cc: torvalds, Greg Kroah-Hartman
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 18214 bytes --]
From: Hans J. Koch <hjk@linutronix.de>
Documentation for the UIO interface
From: Hans J. Koch <hjk@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
Documentation/DocBook/kernel-api.tmpl | 4 +
Documentation/DocBook/uio-howto.tmpl | 498 +++++++++++++++++++++++++++++++++
2 files changed, 502 insertions(+), 0 deletions(-)
create mode 100644 Documentation/DocBook/uio-howto.tmpl
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 0bb9023..40e968d 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -396,6 +396,10 @@ X!Edrivers/pnp/system.c
!Edrivers/pnp/manager.c
!Edrivers/pnp/support.c
</sect1>
+ <sect1><title>Userspace IO devices</title>
+!Edrivers/uio/uio.c
+!Iinclude/linux/uio_driver.h
+ </sect1>
</chapter>
<chapter id="blkdev">
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
new file mode 100644
index 0000000..bd2209f
--- /dev/null
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -0,0 +1,498 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<article id="index">
+<articleinfo>
+<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@linutronix.de</email>
+ </address>
+ </affiliation>
+</author>
+
+<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.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>
+</articleinfo>
+
+<sect1 id="aboutthisdoc">
+<?dbhtml filename="about.html"?>
+<title>About this document</title>
+
+<sect2 id="copyright">
+<?dbhtml filename="copyright.html"?>
+<title>Copyright and License</title>
+<para>
+ Copyright (c) 2006 by Hans-Jürgen Koch.</para>
+<para>
+This documentation is Free Software licensed under the terms of the
+GPL version 2.
+</para>
+</sect2>
+
+<sect2 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@linutronix.de</email>.
+</para>
+</sect2>
+
+<sect2 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>
+</sect2>
+
+<sect2 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>
+</sect2>
+
+<sect2 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@linutronix.de</email>.</para>
+</sect2>
+</sect1>
+
+<sect1 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>
+<listitem>
+ <para>if you need to keep some parts of your driver closed source,
+ you can do so without violating the GPL license on the kernel.</para>
+</listitem>
+</itemizedlist>
+
+<sect2 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>
+ 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.
+ See <filename>drivers/uio/uio_dummy.c</filename> for an
+ example of this technique.
+ </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 two read-only files
+ that show start address and size of the memory:
+</para>
+<itemizedlist>
+<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>
+</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>
+
+</sect2>
+</sect1>
+
+<sect1 id="using-uio_dummy" xreflabel="Using uio_dummy">
+<?dbhtml filename="using-uio_dummy.html"?>
+<title>Using uio_dummy</title>
+ <para>
+ 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.
+ </para>
+
+<sect2 id="what_uio_dummy_does">
+<title>What uio_dummy does</title>
+ <para>
+ The kernel module <filename>uio_dummy.ko</filename> 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, <varname>count</varname>
+ and <varname>freq</varname>, that appear under
+ <filename>/sys/devices/platform/uio_dummy/</filename>.
+ </para>
+
+ <para>
+ The attribute <varname>count</varname> can be read and
+ written. The associated file
+ <filename>/sys/devices/platform/uio_dummy/count</filename>
+ appears as a normal text file and contains the total number of
+ timer interrupts. If you look at it (e.g. using
+ <function>cat</function>), you'll notice it is slowly counting
+ up.
+ </para>
+
+ <para>
+ The attribute <varname>freq</varname> can be read and written.
+ The content of
+ <filename>/sys/devices/platform/uio_dummy/freq</filename>
+ represents the number of system timer ticks between two timer
+ interrupts. The default value of <varname>freq</varname> is
+ the value of the kernel variable <varname>HZ</varname>, which
+ gives you an interval of one second. Lower values will
+ increase the frequency. Try the following:
+ </para>
+<programlisting format="linespecific">
+cd /sys/devices/platform/uio_dummy/
+echo 100 > freq
+</programlisting>
+ <para>
+ Use <function>cat count</function> to see how the interrupt
+ frequency changes.
+ </para>
+</sect2>
+</sect1>
+
+<sect1 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_dummy.c</filename> as an
+ example. The following paragraphs explain the different
+ sections of this file.
+ </para>
+
+<sect2 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>
+<varname>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.
+</listitem>
+
+<listitem>
+<varname>char *version</varname>: Required. This string appears in
+<filename>/sys/class/uio/uioX/version</filename>.
+</listitem>
+
+<listitem>
+<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.
+</listitem>
+
+<listitem>
+<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>. 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
+<varname>irq</varname> to <varname>UIO_IRQ_NONE</varname>, though this
+rarely makes sense.
+</listitem>
+
+<listitem>
+<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>.
+</listitem>
+
+<listitem>
+<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.
+</listitem>
+
+<listitem>
+<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.
+</listitem>
+
+<listitem>
+<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.
+</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>
+<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.
+</listitem>
+
+<listitem>
+<varname>unsigned long 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.
+</listitem>
+
+<listitem>
+<varname>unsigned long 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.
+</listitem>
+
+<listitem>
+<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_nocache()</function>. Addresses
+returned by this function can not 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.
+</listitem>
+</itemizedlist>
+
+<para>
+Please do not touch the <varname>kobj</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>
+</sect2>
+
+<sect2 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>
+</sect2>
+
+</sect1>
+
+<appendix id="app1">
+<title>Further information</title>
+<itemizedlist>
+ <listitem><para>
+ <ulink url="http://www.linutronix.de">
+ Linutronix homepage.</ulink>
+ </para></listitem>
+ <listitem><para>...</para></listitem>
+</itemizedlist>
+</appendix>
+
+</article>
--
1.5.1.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-04-27 22:50 ` [PATCH 2/3] UIO: Documentation Greg Kroah-Hartman
@ 2007-05-01 23:42 ` Randy Dunlap
2007-05-02 8:41 ` Hans-Jürgen Koch
0 siblings, 1 reply; 32+ messages in thread
From: Randy Dunlap @ 2007-05-01 23:42 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-kernel, torvalds, hjk
On Fri, 27 Apr 2007 15:50:57 -0700 Greg Kroah-Hartman wrote:
> From: Hans J. Koch <hjk@linutronix.de>
>
> Documentation for the UIO interface
>
> From: Hans J. Koch <hjk@linutronix.de>
> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
> ---
> Documentation/DocBook/kernel-api.tmpl | 4 +
> Documentation/DocBook/uio-howto.tmpl | 498 +++++++++++++++++++++++++++++++++
> 2 files changed, 502 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/DocBook/uio-howto.tmpl
> diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
> new file mode 100644
> index 0000000..bd2209f
> --- /dev/null
> +++ b/Documentation/DocBook/uio-howto.tmpl
> @@ -0,0 +1,498 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
> +"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
> +
> +<article id="index">
> +<articleinfo>
> +<title>The Userspace I/O HOWTO</title>
Most of this reads well. Thanks.
A few typo corrections are below...
But it doesn't build for me with 'make htmldocs'.
Did you test it?
Warning(/tester/linsrc/linux-2.6.21-rc7-mm2//drivers/uio/uio.c:240): No description found for parameter 'info'
Warning(/tester/linsrc/linux-2.6.21-rc7-mm2//drivers/uio/uio.c:594): No description found for parameter 'owner'
Warning(/tester/linsrc/linux-2.6.21-rc7-mm2//drivers/uio/uio.c:594): No description found for parameter 'info'
Warning(/tester/linsrc/linux-2.6.21-rc7-mm2//drivers/uio/uio.c:667): No description found for parameter 'info'
Error(/tester/linsrc/linux-2.6.21-rc7-mm2//include/linux/uio_driver.h:29): cannot understand prototype: 'struct uio_mem '
Error(/tester/linsrc/linux-2.6.21-rc7-mm2//include/linux/uio_driver.h:55): cannot understand prototype: 'struct uio_info '
Warning(/tester/linsrc/linux-2.6.21-rc7-mm2//include/linux/uio_driver.h): no structured comments found
Patch below for all of is these (including typos).
However, it still fails 'make htmldocs' for me.
What am I missing? How did it work for you?
My DTD doesn't like to see <varname> inside a <listitem>:
linux-2.6.21-rc7-mm2/Documentation/DocBook/uio-howto.xml:333: element listitem: validity error : Element listitem content does not follow the DTD, expecting (calloutlist | glosslist | itemizedlist | orderedlist | segmentedlist | simplelist | variablelist | caution | important | note | tip | warning | literallayout | programlisting | programlistingco | screen | screenco | screenshot | synopsis | cmdsynopsis | funcsynopsis | classsynopsis | fieldsynopsis | constructorsynopsis | destructorsynopsis | methodsynopsis | formalpara | para | simpara | address | blockquote | graphic | graphicco | mediaobject | mediaobjectco | informalequation | informalexample | informalfigure | informaltable | equation | example | figure | table | msgset | procedure | sidebar | qandaset | anchor | bridgehead | remark | highlights | abstract | authorblurb | epigraph | indexterm | beginpage)+, got (varname CDATA)
so I removed most of the <varname>s and still had errors.
Any suggestions?
...
> + <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
Period at end of sentence.
> + </para>
> +
> + <para>
> + The following standard attributes are provided by the UIO
> + framework:
> + </para>
> <listitem>
> +<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_nocache()</function>. Addresses
> +returned by this function can not be mapped to user space, so you must not
cannot
> +store it in <varname>addr</varname>. Use <varname>internal_addr</varname>
> +instead to remember such an address.
> +</listitem>
> +</itemizedlist>
> +<sect2 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
. Your
> + userspace program can terminate at any time, possibly leaving
> + your hardware in a state where proper interrupt handling is
> + still required.
> + </para>
Some fixes:
From: Randy Dunlap <randy.dunlap@oracle.com>
Fix UIO kernel-doc typos and warnings.
Include uio-howto in list of docbook files.
Change DOCTYPE version to same as all other docbook files.
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
---
Documentation/DocBook/Makefile | 2 +-
Documentation/DocBook/uio-howto.tmpl | 10 +++++-----
drivers/uio/uio.c | 10 +++++-----
include/linux/uio_driver.h | 8 ++++----
4 files changed, 15 insertions(+), 15 deletions(-)
--- linux-2.6.21-rc7-mm2.orig/include/linux/uio_driver.h
+++ linux-2.6.21-rc7-mm2/include/linux/uio_driver.h
@@ -19,7 +19,7 @@
#include <linux/interrupt.h>
/**
- * uio_mem - description of a UIO memory region
+ * struct uio_mem - description of a UIO memory region
* @kobj: kobject for this mapping
* @addr: address of the device's memory
* @size: size of IO
@@ -39,13 +39,13 @@ struct uio_mem {
struct uio_device;
/**
- * uio_info - UIO device capabilities
+ * struct uio_info - UIO device capabilities
* @uio_dev: the UIO device this info belongs to
* @name: device name
* @version: device driver version
* @mem: list of mappable memory regions, size==0 for end of list
* @irq: interrupt number or UIO_IRQ_CUSTOM
- * @irq_flags flags for request_irq()
+ * @irq_flags: flags for request_irq()
* @priv: optional private data
* @handler: the device's irq handler
* @mmap: mmap operation for this uio device
@@ -56,7 +56,7 @@ struct uio_info {
struct uio_device *uio_dev;
char *name;
char *version;
- struct uio_mem mem[ MAX_UIO_MAPS ];
+ struct uio_mem mem[MAX_UIO_MAPS];
long irq;
unsigned long irq_flags;
void *priv;
--- linux-2.6.21-rc7-mm2.orig/drivers/uio/uio.c
+++ linux-2.6.21-rc7-mm2/drivers/uio/uio.c
@@ -234,7 +234,7 @@ static void uio_free_minor(struct uio_de
/**
* uio_event_notify - trigger an interrupt event
- * @idev: UIO device where the event occured
+ * @info: UIO device capabilities
*/
void uio_event_notify(struct uio_info *info)
{
@@ -582,9 +582,9 @@ static void uio_class_destroy(void)
/**
* uio_register_device - register a new userspace IO device
- *
+ * @owner: module pointer
* @parent: parent device
- * @idev: device capabilities
+ * @info: device capabilities
*
* returns zero on success or a negative error code.
*/
@@ -658,8 +658,8 @@ err_kzalloc:
EXPORT_SYMBOL_GPL(__uio_register_device);
/**
- * uio_unregister_device - unregister a industrial IO device
- * @uiodev: UIO device driver identifier
+ * uio_unregister_device - unregister an industrial IO device
+ * @info: UIO device driver capabilities
*
* returns 0 on success
*/
--- linux-2.6.21-rc7-mm2.orig/Documentation/DocBook/uio-howto.tmpl
+++ linux-2.6.21-rc7-mm2/Documentation/DocBook/uio-howto.tmpl
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
<article id="index">
<articleinfo>
@@ -182,7 +182,7 @@ interested in translating it, please ema
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
+ future if it would be found to be useful.
</para>
<para>
@@ -422,7 +422,7 @@ all unused mappings.
<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_nocache()</function>. Addresses
-returned by this function can not be mapped to user space, so you must not
+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.
</listitem>
@@ -447,7 +447,7 @@ to set up sysfs files for this mapping.
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
+ 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.
--- linux-2.6.21-rc7-mm2.orig/Documentation/DocBook/Makefile
+++ linux-2.6.21-rc7-mm2/Documentation/DocBook/Makefile
@@ -11,7 +11,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mc
procfs-guide.xml writing_usb_driver.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
- genericirq.xml
+ genericirq.xml uio-howto.xml
###
# The build process is as follows (targets):
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-05-01 23:42 ` Randy Dunlap
@ 2007-05-02 8:41 ` Hans-Jürgen Koch
2007-05-02 20:52 ` Randy Dunlap
0 siblings, 1 reply; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-05-02 8:41 UTC (permalink / raw)
To: Randy Dunlap; +Cc: Greg Kroah-Hartman, linux-kernel, torvalds, tglx
Am Mittwoch 02 Mai 2007 01:42 schrieb Randy Dunlap:
> > +<title>The Userspace I/O HOWTO</title>
>
> Most of this reads well. Thanks.
> A few typo corrections are below...
Thank you for your work. I generated a new patch that includes all your
suggestions and also fixes the build problems.
[...]
>
> However, it still fails 'make htmldocs' for me.
> What am I missing? How did it work for you?
> My DTD doesn't like to see <varname> inside a <listitem>:
>
>
> linux-2.6.21-rc7-mm2/Documentation/DocBook/uio-howto.xml:333: element listitem: validity error : Element listitem content does not follow the DTD, expecting (calloutlist | glosslist | itemizedlist | orderedlist | segmentedlist | simplelist | variablelist | caution | important | note | tip | warning | literallayout | programlisting | programlistingco | screen | screenco | screenshot | synopsis | cmdsynopsis | funcsynopsis | classsynopsis | fieldsynopsis | constructorsynopsis | destructorsynopsis | methodsynopsis | formalpara | para | simpara | address | blockquote | graphic | graphicco | mediaobject | mediaobjectco | informalequation | informalexample | informalfigure | informaltable | equation | example | figure | table | msgset | procedure | sidebar | qandaset | anchor | bridgehead | remark | highlights | abstract | authorblurb | epigraph | indexterm | beginpage)+, got (varname CDATA)
>
>
> so I removed most of the <varname>s and still had errors.
> Any suggestions?
Yes, this only occurs when the <listitem> content is not surrounded by
<para></para>. I fixed that. I also changed the whole thing from
"article" to "book" as all the other *.tmpl files are books.
[...]
> > <listitem>
> > +<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_nocache()</function>. Addresses
> > +returned by this function can not be mapped to user space, so you must not
>
> cannot
Here I also replaced ioremap_nocache() by ioremap(). I just fixed that in
uio_cif.c and don't want to encourage other people to write the same nonsense.
Here's my patch, as I said, it should include your fixes as well:
Index: linux-2.6.22-rc/drivers/uio/uio.c
===================================================================
--- linux-2.6.22-rc.orig/drivers/uio/uio.c 2007-05-02 08:32:19.000000000 +0200
+++ linux-2.6.22-rc/drivers/uio/uio.c 2007-05-02 09:10:40.000000000 +0200
@@ -234,7 +234,7 @@
/**
* uio_event_notify - trigger an interrupt event
- * @idev: UIO device where the event occured
+ * @info: UIO device capabilities
*/
void uio_event_notify(struct uio_info *info)
{
@@ -583,8 +583,9 @@
/**
* uio_register_device - register a new userspace IO device
*
+ * @owner: module that creates the new device
* @parent: parent device
- * @idev: device capabilities
+ * @info: UIO device capabilities
*
* returns zero on success or a negative error code.
*/
@@ -660,9 +661,8 @@
/**
* uio_unregister_device - unregister a industrial IO device
- * @uiodev: UIO device driver identifier
+ * @info: UIO device capabilities
*
- * returns 0 on success
*/
void uio_unregister_device(struct uio_info *info)
{
Index: linux-2.6.22-rc/include/linux/uio_driver.h
===================================================================
--- linux-2.6.22-rc.orig/include/linux/uio_driver.h 2007-05-02 08:24:38.000000000 +0200
+++ linux-2.6.22-rc/include/linux/uio_driver.h 2007-05-02 08:42:42.000000000 +0200
@@ -19,7 +19,7 @@
#include <linux/interrupt.h>
/**
- * uio_mem - description of a UIO memory region
+ * struct uio_mem - description of a UIO memory region
* @kobj: kobject for this mapping
* @addr: address of the device's memory
* @size: size of IO
@@ -39,13 +39,13 @@
struct uio_device;
/**
- * uio_info - UIO device capabilities
+ * struct uio_info - UIO device capabilities
* @uio_dev: the UIO device this info belongs to
* @name: device name
* @version: device driver version
* @mem: list of mappable memory regions, size==0 for end of list
* @irq: interrupt number or UIO_IRQ_CUSTOM
- * @irq_flags flags for request_irq()
+ * @irq_flags: flags for request_irq()
* @priv: optional private data
* @handler: the device's irq handler
* @mmap: mmap operation for this uio device
@@ -56,7 +56,7 @@
struct uio_device *uio_dev;
char *name;
char *version;
- struct uio_mem mem[ MAX_UIO_MAPS ];
+ struct uio_mem mem[MAX_UIO_MAPS];
long irq;
unsigned long irq_flags;
void *priv;
Index: linux-2.6.22-rc/Documentation/DocBook/Makefile
===================================================================
--- linux-2.6.22-rc.orig/Documentation/DocBook/Makefile 2007-05-02 09:00:32.000000000 +0200
+++ linux-2.6.22-rc/Documentation/DocBook/Makefile 2007-05-02 09:43:06.000000000 +0200
@@ -11,7 +11,7 @@
procfs-guide.xml writing_usb_driver.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
- genericirq.xml
+ genericirq.xml uio-howto.xml
###
# The build process is as follows (targets):
Index: linux-2.6.22-rc/Documentation/DocBook/uio-howto.tmpl
===================================================================
--- linux-2.6.22-rc.orig/Documentation/DocBook/uio-howto.tmpl 2007-05-02 08:54:24.000000000 +0200
+++ linux-2.6.22-rc/Documentation/DocBook/uio-howto.tmpl 2007-05-02 10:24:18.000000000 +0200
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []>
-<article id="index">
-<articleinfo>
+<book id="index">
+<bookinfo>
<title>The Userspace I/O HOWTO</title>
<author>
@@ -48,13 +48,13 @@
<revremark>First draft.</revremark>
</revision>
</revhistory>
-</articleinfo>
+</bookinfo>
-<sect1 id="aboutthisdoc">
+<chapter id="aboutthisdoc">
<?dbhtml filename="about.html"?>
<title>About this document</title>
-<sect2 id="copyright">
+<sect1 id="copyright">
<?dbhtml filename="copyright.html"?>
<title>Copyright and License</title>
<para>
@@ -63,9 +63,9 @@
This documentation is Free Software licensed under the terms of the
GPL version 2.
</para>
-</sect2>
+</sect1>
-<sect2 id="translations">
+<sect1 id="translations">
<?dbhtml filename="translations.html"?>
<title>Translations</title>
@@ -73,9 +73,9 @@
interested in translating it, please email me
<email>hjk@linutronix.de</email>.
</para>
-</sect2>
+</sect1>
-<sect2 id="preface">
+<sect1 id="preface">
<title>Preface</title>
<para>
For many types of devices, creating a Linux kernel driver is
@@ -94,25 +94,25 @@
user space. This simplifies development and reduces the risk of
serious bugs within a kernel module.
</para>
-</sect2>
+</sect1>
-<sect2 id="thanks">
+<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>
-</sect2>
+</sect1>
-<sect2 id="feedback">
+<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@linutronix.de</email>.</para>
-</sect2>
</sect1>
+</chapter>
-<sect1 id="about">
+<chapter id="about">
<?dbhtml filename="about.html"?>
<title>About UIO</title>
@@ -139,7 +139,7 @@
</listitem>
</itemizedlist>
-<sect2 id="how_uio_works">
+<sect1 id="how_uio_works">
<title>How UIO works</title>
<para>
Each UIO device is accessed through a device file and several
@@ -188,7 +188,7 @@
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
+ future if it would be found to be useful.
</para>
<para>
@@ -264,10 +264,10 @@
offset = N * getpagesize();
</programlisting>
-</sect2>
</sect1>
+</chapter>
-<sect1 id="using-uio_dummy" xreflabel="Using uio_dummy">
+<chapter id="using-uio_dummy" xreflabel="Using uio_dummy">
<?dbhtml filename="using-uio_dummy.html"?>
<title>Using uio_dummy</title>
<para>
@@ -277,7 +277,7 @@
kernel module that you will have to write yourself.
</para>
-<sect2 id="what_uio_dummy_does">
+<sect1 id="what_uio_dummy_does">
<title>What uio_dummy does</title>
<para>
The kernel module <filename>uio_dummy.ko</filename> creates a
@@ -316,10 +316,10 @@
Use <function>cat count</function> to see how the interrupt
frequency changes.
</para>
-</sect2>
</sect1>
+</chapter>
-<sect1 id="custom_kernel_module" xreflabel="Writing your own kernel module">
+<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>
@@ -328,7 +328,7 @@
sections of this file.
</para>
-<sect2 id="uio_info">
+<sect1 id="uio_info">
<title>struct uio_info</title>
<para>
This structure tells the framework the details of your driver,
@@ -336,24 +336,24 @@
</para>
<itemizedlist>
-<listitem>
+<listitem><para>
<varname>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.
-</listitem>
+</para></listitem>
-<listitem>
+<listitem><para>
<varname>char *version</varname>: Required. This string appears in
<filename>/sys/class/uio/uioX/version</filename>.
-</listitem>
+</para></listitem>
-<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.
-</listitem>
+</para></listitem>
-<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
@@ -363,35 +363,35 @@
routine. If you had no interrupt at all, you could set
<varname>irq</varname> to <varname>UIO_IRQ_NONE</varname>, though this
rarely makes sense.
-</listitem>
+</para></listitem>
-<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>.
-</listitem>
+</para></listitem>
-<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.
-</listitem>
+</para></listitem>
-<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.
-</listitem>
+</para></listitem>
-<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.
-</listitem>
+</para></listitem>
</itemizedlist>
<para>
@@ -402,36 +402,36 @@
</para>
<itemizedlist>
-<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.
-</listitem>
+</para></listitem>
-<listitem>
+<listitem><para>
<varname>unsigned long 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.
-</listitem>
+</para></listitem>
-<listitem>
+<listitem><para>
<varname>unsigned long 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.
-</listitem>
+</para></listitem>
-<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_nocache()</function>. Addresses
-returned by this function can not be mapped to user space, so you must not
+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.
-</listitem>
+</para></listitem>
</itemizedlist>
<para>
@@ -439,9 +439,9 @@
<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>
-</sect2>
+</sect1>
-<sect2 id="adding_irq_handler">
+<sect1 id="adding_irq_handler">
<title>Adding an interrupt handler</title>
<para>
What you need to do in your interrupt handler depends on your
@@ -453,7 +453,7 @@
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
+ 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.
@@ -486,11 +486,11 @@
frequently happens on the PC platform, you can save yourself a
lot of trouble by supporting interrupt sharing.
</para>
-</sect2>
-
</sect1>
-<sect1 id="userspace_driver" xreflabel="Writing a driver in user space">
+</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>
@@ -502,7 +502,7 @@
userspace application.
</para>
-<sect2 id="getting_uio_information">
+<sect1 id="getting_uio_information">
<title>Getting information about your UIO device</title>
<para>
Information about all UIO devices is available in sysfs. The
@@ -534,9 +534,9 @@
The file <filename>uio_helper.c</filename> contains a lot of
functions you could use in your userspace driver code.
</para>
-</sect2>
+</sect1>
-<sect2 id="mmap_device_memory">
+<sect1 id="mmap_device_memory">
<title>mmap() device memory</title>
<para>
After you made sure you've got the right device with the
@@ -561,9 +561,9 @@
A drawback of this technique is that memory is always
mapped beginning with its start address.
</para>
-</sect2>
+</sect1>
-<sect2 id="wait_for_interrupts">
+<sect1 id="wait_for_interrupts">
<title>Waiting for interrupts</title>
<para>
After you successfully mapped your devices memory, you
@@ -590,10 +590,10 @@
You can also use <function>select()</function> on
<filename>/dev/uioX</filename>.
</para>
-</sect2>
-
</sect1>
+</chapter>
+
<appendix id="app1">
<title>Further information</title>
<itemizedlist>
@@ -608,4 +608,4 @@
</itemizedlist>
</appendix>
-</article>
+</book>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-05-02 8:41 ` Hans-Jürgen Koch
@ 2007-05-02 20:52 ` Randy Dunlap
2007-05-02 22:00 ` Hans-Jürgen Koch
0 siblings, 1 reply; 32+ messages in thread
From: Randy Dunlap @ 2007-05-02 20:52 UTC (permalink / raw)
To: Hans-Jürgen Koch; +Cc: Greg Kroah-Hartman, linux-kernel, torvalds, tglx
On Wed, 2 May 2007 10:41:35 +0200 Hans-Jürgen Koch wrote:
> Am Mittwoch 02 Mai 2007 01:42 schrieb Randy Dunlap:
>
> > > +<title>The Userspace I/O HOWTO</title>
> >
> > Most of this reads well. Thanks.
> > A few typo corrections are below...
>
> Thank you for your work. I generated a new patch that includes all your
> suggestions and also fixes the build problems.
Hi,
What does your patch apply to, please? I get patch errors with it.
> [...]
> >
> > However, it still fails 'make htmldocs' for me.
> > What am I missing? How did it work for you?
> > My DTD doesn't like to see <varname> inside a <listitem>:
> >
> >
> > linux-2.6.21-rc7-mm2/Documentation/DocBook/uio-howto.xml:333: element listitem: validity error : Element listitem content does not follow the DTD, expecting (calloutlist | glosslist | itemizedlist | orderedlist | segmentedlist | simplelist | variablelist | caution | important | note | tip | warning | literallayout | programlisting | programlistingco | screen | screenco | screenshot | synopsis | cmdsynopsis | funcsynopsis | classsynopsis | fieldsynopsis | constructorsynopsis | destructorsynopsis | methodsynopsis | formalpara | para | simpara | address | blockquote | graphic | graphicco | mediaobject | mediaobjectco | informalequation | informalexample | informalfigure | informaltable | equation | example | figure | table | msgset | procedure | sidebar | qandaset | anchor | bridgehead | remark | highlights | abstract | authorblurb | epigraph | indexterm | beginpage)+, got (varname CDATA)
> >
> >
> > so I removed most of the <varname>s and still had errors.
> > Any suggestions?
>
> Yes, this only occurs when the <listitem> content is not surrounded by
> <para></para>. I fixed that. I also changed the whole thing from
> "article" to "book" as all the other *.tmpl files are books.
>
>
> [...]
> > > <listitem>
> > > +<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_nocache()</function>. Addresses
> > > +returned by this function can not be mapped to user space, so you must not
> >
> > cannot
>
> Here I also replaced ioremap_nocache() by ioremap(). I just fixed that in
> uio_cif.c and don't want to encourage other people to write the same nonsense.
>
> Here's my patch, as I said, it should include your fixes as well:
>
> Index: linux-2.6.22-rc/drivers/uio/uio.c
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-05-02 20:52 ` Randy Dunlap
@ 2007-05-02 22:00 ` Hans-Jürgen Koch
2007-05-02 23:37 ` Randy Dunlap
0 siblings, 1 reply; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-05-02 22:00 UTC (permalink / raw)
To: Randy Dunlap; +Cc: Greg Kroah-Hartman, linux-kernel, torvalds, tglx
Am Mittwoch 02 Mai 2007 schrieb Randy Dunlap:
> On Wed, 2 May 2007 10:41:35 +0200 Hans-Jürgen Koch wrote:
> > Am Mittwoch 02 Mai 2007 01:42 schrieb Randy Dunlap:
> > > > +<title>The Userspace I/O HOWTO</title>
> > >
> > > Most of this reads well. Thanks.
> > > A few typo corrections are below...
> >
> > Thank you for your work. I generated a new patch that includes all your
> > suggestions and also fixes the build problems.
>
> Hi,
> What does your patch apply to, please? I get patch errors with it.
>
The patch goes on top of Greg's original patch plus the one I recently
sent (adding the chapter about the userspace driver part).
If you haven't got it handy, I mean this one:
http://marc.info/?l=linux-kernel&m=117788526325956&w=2
Thanks,
Hans
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-05-02 22:00 ` Hans-Jürgen Koch
@ 2007-05-02 23:37 ` Randy Dunlap
2007-05-03 5:37 ` Greg KH
0 siblings, 1 reply; 32+ messages in thread
From: Randy Dunlap @ 2007-05-02 23:37 UTC (permalink / raw)
To: Hans-Jürgen Koch; +Cc: Greg Kroah-Hartman, linux-kernel, torvalds, tglx
On Thu, 3 May 2007 00:00:28 +0200 Hans-Jürgen Koch wrote:
> Am Mittwoch 02 Mai 2007 schrieb Randy Dunlap:
> > On Wed, 2 May 2007 10:41:35 +0200 Hans-Jürgen Koch wrote:
> > > Am Mittwoch 02 Mai 2007 01:42 schrieb Randy Dunlap:
> > > > > +<title>The Userspace I/O HOWTO</title>
> > > >
> > > > Most of this reads well. Thanks.
> > > > A few typo corrections are below...
> > >
> > > Thank you for your work. I generated a new patch that includes all your
> > > suggestions and also fixes the build problems.
OK, your fixes all look good, but still needs one minor fix (below).
Acked-by: Randy Dunlap <randy.dunlap@oracle.com>
---
From: Randy Dunlap <randy.dunlap@oracle.com>
Fix last UIO kernel-doc problem.
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
---
drivers/uio/uio.c | 1 -
1 file changed, 1 deletion(-)
--- linux-2.6.21-git4.orig/drivers/uio/uio.c
+++ linux-2.6.21-git4/drivers/uio/uio.c
@@ -582,7 +582,6 @@ static void uio_class_destroy(void)
/**
* uio_register_device - register a new userspace IO device
- *
* @owner: module that creates the new device
* @parent: parent device
* @info: UIO device capabilities
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-05-02 23:37 ` Randy Dunlap
@ 2007-05-03 5:37 ` Greg KH
2007-05-03 6:39 ` Hans-Jürgen Koch
0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-05-03 5:37 UTC (permalink / raw)
To: Randy Dunlap
Cc: Hans-J?rgen Koch, Greg Kroah-Hartman, linux-kernel, torvalds,
tglx
On Wed, May 02, 2007 at 04:37:34PM -0700, Randy Dunlap wrote:
> On Thu, 3 May 2007 00:00:28 +0200 Hans-J?rgen Koch wrote:
>
> > Am Mittwoch 02 Mai 2007 schrieb Randy Dunlap:
> > > On Wed, 2 May 2007 10:41:35 +0200 Hans-J?rgen Koch wrote:
> > > > Am Mittwoch 02 Mai 2007 01:42 schrieb Randy Dunlap:
> > > > > > +<title>The Userspace I/O HOWTO</title>
> > > > >
> > > > > Most of this reads well. Thanks.
> > > > > A few typo corrections are below...
> > > >
> > > > Thank you for your work. I generated a new patch that includes all your
> > > > suggestions and also fixes the build problems.
>
> OK, your fixes all look good, but still needs one minor fix (below).
>
> Acked-by: Randy Dunlap <randy.dunlap@oracle.com>
Hm, I have about 3 different patches here now, all dependant on each
other, yet I can't tell which goes first :(
Can someone just send me 1, or 3 with the correct order in which to
apply them?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-05-03 5:37 ` Greg KH
@ 2007-05-03 6:39 ` Hans-Jürgen Koch
2007-05-04 9:37 ` Hans-Jürgen Koch
0 siblings, 1 reply; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-05-03 6:39 UTC (permalink / raw)
To: Greg KH
Cc: Randy Dunlap, Greg Kroah-Hartman, linux-kernel, torvalds, tglx,
Benedikt Spranger
[-- Attachment #1: Type: text/plain, Size: 1683 bytes --]
Am Donnerstag 03 Mai 2007 07:37 schrieb Greg KH:
> On Wed, May 02, 2007 at 04:37:34PM -0700, Randy Dunlap wrote:
> > On Thu, 3 May 2007 00:00:28 +0200 Hans-J?rgen Koch wrote:
> >
> > > Am Mittwoch 02 Mai 2007 schrieb Randy Dunlap:
> > > > On Wed, 2 May 2007 10:41:35 +0200 Hans-J?rgen Koch wrote:
> > > > > Am Mittwoch 02 Mai 2007 01:42 schrieb Randy Dunlap:
> > > > > > > +<title>The Userspace I/O HOWTO</title>
> > > > > >
> > > > > > Most of this reads well. Thanks.
> > > > > > A few typo corrections are below...
> > > > >
> > > > > Thank you for your work. I generated a new patch that includes all your
> > > > > suggestions and also fixes the build problems.
> >
> > OK, your fixes all look good, but still needs one minor fix (below).
> >
> > Acked-by: Randy Dunlap <randy.dunlap@oracle.com>
>
> Hm, I have about 3 different patches here now, all dependant on each
> other, yet I can't tell which goes first :(
>
> Can someone just send me 1, or 3 with the correct order in which to
> apply them?
>
> thanks,
>
> greg k-h
>
Hi Greg,
I attached all the UIO patches I collected so far. This is my series file:
uio.patch
fix-early-irq-problem-in-uio.patch
uio-documentation.patch
fix-uio_read-type-problem.patch
uio-dummy.patch
uio-hilscher-cif-card-driver.patch
ioremap-in-uio-hilscher-cif.patch
add-userspace-howto-to-uio-doc.patch
fix-uio-doc-build-problems.patch
It should also work without uio-dummy.patch.
I added Randy's last one-line patch to fix-uio-doc-build-problems.patch.
All patches are
Signed-off-by: Hans J. Koch <hjk@linutronix.de>
fix-uio-doc-build-problems.patch is also
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Thanks,
Hans
[-- Attachment #2: fix-uio-doc-build-problems.patch --]
[-- Type: text/x-diff, Size: 13835 bytes --]
Index: linux-2.6.22-rc/drivers/uio/uio.c
===================================================================
--- linux-2.6.22-rc.orig/drivers/uio/uio.c 2007-05-02 08:32:19.000000000 +0200
+++ linux-2.6.22-rc/drivers/uio/uio.c 2007-05-03 08:21:39.000000000 +0200
@@ -234,7 +234,7 @@
/**
* uio_event_notify - trigger an interrupt event
- * @idev: UIO device where the event occured
+ * @info: UIO device capabilities
*/
void uio_event_notify(struct uio_info *info)
{
@@ -582,9 +582,9 @@
/**
* uio_register_device - register a new userspace IO device
- *
+ * @owner: module that creates the new device
* @parent: parent device
- * @idev: device capabilities
+ * @info: UIO device capabilities
*
* returns zero on success or a negative error code.
*/
@@ -660,9 +660,8 @@
/**
* uio_unregister_device - unregister a industrial IO device
- * @uiodev: UIO device driver identifier
+ * @info: UIO device capabilities
*
- * returns 0 on success
*/
void uio_unregister_device(struct uio_info *info)
{
Index: linux-2.6.22-rc/include/linux/uio_driver.h
===================================================================
--- linux-2.6.22-rc.orig/include/linux/uio_driver.h 2007-05-02 08:24:38.000000000 +0200
+++ linux-2.6.22-rc/include/linux/uio_driver.h 2007-05-02 08:42:42.000000000 +0200
@@ -19,7 +19,7 @@
#include <linux/interrupt.h>
/**
- * uio_mem - description of a UIO memory region
+ * struct uio_mem - description of a UIO memory region
* @kobj: kobject for this mapping
* @addr: address of the device's memory
* @size: size of IO
@@ -39,13 +39,13 @@
struct uio_device;
/**
- * uio_info - UIO device capabilities
+ * struct uio_info - UIO device capabilities
* @uio_dev: the UIO device this info belongs to
* @name: device name
* @version: device driver version
* @mem: list of mappable memory regions, size==0 for end of list
* @irq: interrupt number or UIO_IRQ_CUSTOM
- * @irq_flags flags for request_irq()
+ * @irq_flags: flags for request_irq()
* @priv: optional private data
* @handler: the device's irq handler
* @mmap: mmap operation for this uio device
@@ -56,7 +56,7 @@
struct uio_device *uio_dev;
char *name;
char *version;
- struct uio_mem mem[ MAX_UIO_MAPS ];
+ struct uio_mem mem[MAX_UIO_MAPS];
long irq;
unsigned long irq_flags;
void *priv;
Index: linux-2.6.22-rc/Documentation/DocBook/Makefile
===================================================================
--- linux-2.6.22-rc.orig/Documentation/DocBook/Makefile 2007-05-02 09:00:32.000000000 +0200
+++ linux-2.6.22-rc/Documentation/DocBook/Makefile 2007-05-02 09:43:06.000000000 +0200
@@ -11,7 +11,7 @@
procfs-guide.xml writing_usb_driver.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
- genericirq.xml
+ genericirq.xml uio-howto.xml
###
# The build process is as follows (targets):
Index: linux-2.6.22-rc/Documentation/DocBook/uio-howto.tmpl
===================================================================
--- linux-2.6.22-rc.orig/Documentation/DocBook/uio-howto.tmpl 2007-05-02 08:54:24.000000000 +0200
+++ linux-2.6.22-rc/Documentation/DocBook/uio-howto.tmpl 2007-05-02 10:24:18.000000000 +0200
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []>
-<article id="index">
-<articleinfo>
+<book id="index">
+<bookinfo>
<title>The Userspace I/O HOWTO</title>
<author>
@@ -48,13 +48,13 @@
<revremark>First draft.</revremark>
</revision>
</revhistory>
-</articleinfo>
+</bookinfo>
-<sect1 id="aboutthisdoc">
+<chapter id="aboutthisdoc">
<?dbhtml filename="about.html"?>
<title>About this document</title>
-<sect2 id="copyright">
+<sect1 id="copyright">
<?dbhtml filename="copyright.html"?>
<title>Copyright and License</title>
<para>
@@ -63,9 +63,9 @@
This documentation is Free Software licensed under the terms of the
GPL version 2.
</para>
-</sect2>
+</sect1>
-<sect2 id="translations">
+<sect1 id="translations">
<?dbhtml filename="translations.html"?>
<title>Translations</title>
@@ -73,9 +73,9 @@
interested in translating it, please email me
<email>hjk@linutronix.de</email>.
</para>
-</sect2>
+</sect1>
-<sect2 id="preface">
+<sect1 id="preface">
<title>Preface</title>
<para>
For many types of devices, creating a Linux kernel driver is
@@ -94,25 +94,25 @@
user space. This simplifies development and reduces the risk of
serious bugs within a kernel module.
</para>
-</sect2>
+</sect1>
-<sect2 id="thanks">
+<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>
-</sect2>
+</sect1>
-<sect2 id="feedback">
+<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@linutronix.de</email>.</para>
-</sect2>
</sect1>
+</chapter>
-<sect1 id="about">
+<chapter id="about">
<?dbhtml filename="about.html"?>
<title>About UIO</title>
@@ -139,7 +139,7 @@
</listitem>
</itemizedlist>
-<sect2 id="how_uio_works">
+<sect1 id="how_uio_works">
<title>How UIO works</title>
<para>
Each UIO device is accessed through a device file and several
@@ -188,7 +188,7 @@
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
+ future if it would be found to be useful.
</para>
<para>
@@ -264,10 +264,10 @@
offset = N * getpagesize();
</programlisting>
-</sect2>
</sect1>
+</chapter>
-<sect1 id="using-uio_dummy" xreflabel="Using uio_dummy">
+<chapter id="using-uio_dummy" xreflabel="Using uio_dummy">
<?dbhtml filename="using-uio_dummy.html"?>
<title>Using uio_dummy</title>
<para>
@@ -277,7 +277,7 @@
kernel module that you will have to write yourself.
</para>
-<sect2 id="what_uio_dummy_does">
+<sect1 id="what_uio_dummy_does">
<title>What uio_dummy does</title>
<para>
The kernel module <filename>uio_dummy.ko</filename> creates a
@@ -316,10 +316,10 @@
Use <function>cat count</function> to see how the interrupt
frequency changes.
</para>
-</sect2>
</sect1>
+</chapter>
-<sect1 id="custom_kernel_module" xreflabel="Writing your own kernel module">
+<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>
@@ -328,7 +328,7 @@
sections of this file.
</para>
-<sect2 id="uio_info">
+<sect1 id="uio_info">
<title>struct uio_info</title>
<para>
This structure tells the framework the details of your driver,
@@ -336,24 +336,24 @@
</para>
<itemizedlist>
-<listitem>
+<listitem><para>
<varname>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.
-</listitem>
+</para></listitem>
-<listitem>
+<listitem><para>
<varname>char *version</varname>: Required. This string appears in
<filename>/sys/class/uio/uioX/version</filename>.
-</listitem>
+</para></listitem>
-<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.
-</listitem>
+</para></listitem>
-<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
@@ -363,35 +363,35 @@
routine. If you had no interrupt at all, you could set
<varname>irq</varname> to <varname>UIO_IRQ_NONE</varname>, though this
rarely makes sense.
-</listitem>
+</para></listitem>
-<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>.
-</listitem>
+</para></listitem>
-<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.
-</listitem>
+</para></listitem>
-<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.
-</listitem>
+</para></listitem>
-<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.
-</listitem>
+</para></listitem>
</itemizedlist>
<para>
@@ -402,36 +402,36 @@
</para>
<itemizedlist>
-<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.
-</listitem>
+</para></listitem>
-<listitem>
+<listitem><para>
<varname>unsigned long 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.
-</listitem>
+</para></listitem>
-<listitem>
+<listitem><para>
<varname>unsigned long 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.
-</listitem>
+</para></listitem>
-<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_nocache()</function>. Addresses
-returned by this function can not be mapped to user space, so you must not
+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.
-</listitem>
+</para></listitem>
</itemizedlist>
<para>
@@ -439,9 +439,9 @@
<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>
-</sect2>
+</sect1>
-<sect2 id="adding_irq_handler">
+<sect1 id="adding_irq_handler">
<title>Adding an interrupt handler</title>
<para>
What you need to do in your interrupt handler depends on your
@@ -453,7 +453,7 @@
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
+ 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.
@@ -486,11 +486,11 @@
frequently happens on the PC platform, you can save yourself a
lot of trouble by supporting interrupt sharing.
</para>
-</sect2>
-
</sect1>
-<sect1 id="userspace_driver" xreflabel="Writing a driver in user space">
+</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>
@@ -502,7 +502,7 @@
userspace application.
</para>
-<sect2 id="getting_uio_information">
+<sect1 id="getting_uio_information">
<title>Getting information about your UIO device</title>
<para>
Information about all UIO devices is available in sysfs. The
@@ -534,9 +534,9 @@
The file <filename>uio_helper.c</filename> contains a lot of
functions you could use in your userspace driver code.
</para>
-</sect2>
+</sect1>
-<sect2 id="mmap_device_memory">
+<sect1 id="mmap_device_memory">
<title>mmap() device memory</title>
<para>
After you made sure you've got the right device with the
@@ -561,9 +561,9 @@
A drawback of this technique is that memory is always
mapped beginning with its start address.
</para>
-</sect2>
+</sect1>
-<sect2 id="wait_for_interrupts">
+<sect1 id="wait_for_interrupts">
<title>Waiting for interrupts</title>
<para>
After you successfully mapped your devices memory, you
@@ -590,10 +590,10 @@
You can also use <function>select()</function> on
<filename>/dev/uioX</filename>.
</para>
-</sect2>
-
</sect1>
+</chapter>
+
<appendix id="app1">
<title>Further information</title>
<itemizedlist>
@@ -608,4 +608,4 @@
</itemizedlist>
</appendix>
-</article>
+</book>
[-- Attachment #3: fix-early-irq-problem-in-uio.patch --]
[-- Type: text/x-diff, Size: 603 bytes --]
Index: linux-2.6.22-rc/drivers/uio/uio.c
===================================================================
--- linux-2.6.22-rc.orig/drivers/uio/uio.c 2007-04-28 20:01:02.000000000 +0200
+++ linux-2.6.22-rc/drivers/uio/uio.c 2007-04-28 20:15:00.000000000 +0200
@@ -633,6 +633,8 @@
if (ret)
goto err_uio_dev_add_attributes;
+ info->uio_dev = idev;
+
if (idev->info->irq >= 0) {
ret = request_irq(idev->info->irq, uio_interrupt,
idev->info->irq_flags, idev->info->name, idev);
@@ -640,7 +642,6 @@
goto err_request_irq;
}
- info->uio_dev = idev;
return 0;
err_request_irq:
[-- Attachment #4: add-userspace-howto-to-uio-doc.patch --]
[-- Type: text/x-diff, Size: 4929 bytes --]
Index: linux-2.6.22-rc/Documentation/DocBook/uio-howto.tmpl
===================================================================
--- linux-2.6.22-rc.orig/Documentation/DocBook/uio-howto.tmpl 2007-04-29 22:17:45.000000000 +0200
+++ linux-2.6.22-rc/Documentation/DocBook/uio-howto.tmpl 2007-04-30 00:15:38.000000000 +0200
@@ -30,6 +30,12 @@
<revhistory>
<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>
@@ -484,14 +490,121 @@
</sect1>
+<sect1 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>
+
+<sect2 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>
+</sect2>
+
+<sect2 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>
+</sect2>
+
+<sect2 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 occured.
+ </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>
+</sect2>
+
+</sect1>
+
<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>
- <listitem><para>...</para></listitem>
</itemizedlist>
</appendix>
[-- Attachment #5: ioremap-in-uio-hilscher-cif.patch --]
[-- Type: text/x-diff, Size: 671 bytes --]
Index: linux-2.6.22-rc/drivers/uio/uio_cif.c
===================================================================
--- linux-2.6.22-rc.orig/drivers/uio/uio_cif.c 2007-04-29 21:34:45.000000000 +0200
+++ linux-2.6.22-rc/drivers/uio/uio_cif.c 2007-04-29 21:36:31.000000000 +0200
@@ -64,9 +64,8 @@
info->mem[0].addr = pci_resource_start(dev, 0);
if (!info->mem[0].addr)
goto out_release;
- info->mem[0].internal_addr = ioremap_nocache(
- pci_resource_start(dev, 0),
- pci_resource_len(dev, 0) );
+ info->mem[0].internal_addr = ioremap(pci_resource_start(dev, 0),
+ pci_resource_len(dev, 0) );
if (!info->mem[0].internal_addr)
goto out_release;
[-- Attachment #6: fix-uio_read-type-problem.patch --]
[-- Type: text/x-diff, Size: 770 bytes --]
Index: linux-2.6.22-rc/drivers/uio/uio.c
===================================================================
--- linux-2.6.22-rc.orig/drivers/uio/uio.c 2007-04-28 22:46:34.000000000 +0200
+++ linux-2.6.22-rc/drivers/uio/uio.c 2007-04-28 22:59:40.000000000 +0200
@@ -264,7 +264,7 @@
struct uio_listener {
struct uio_device *dev;
- int event_count;
+ s32 event_count;
};
static int uio_open(struct inode *inode, struct file *filep)
@@ -345,12 +345,12 @@
struct uio_device *idev = listener->dev;
DECLARE_WAITQUEUE(wait, current);
ssize_t retval;
- int event_count;
+ s32 event_count;
if (idev->info->irq == UIO_IRQ_NONE)
return -EIO;
- if (count != sizeof(int))
+ if (count != sizeof(s32))
return -EINVAL;
add_wait_queue(&idev->wait, &wait);
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-05-03 6:39 ` Hans-Jürgen Koch
@ 2007-05-04 9:37 ` Hans-Jürgen Koch
2007-05-07 17:46 ` Randy Dunlap
0 siblings, 1 reply; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-05-04 9:37 UTC (permalink / raw)
To: Greg KH
Cc: Randy Dunlap, Greg Kroah-Hartman, linux-kernel, torvalds, tglx,
Benedikt Spranger
Am Donnerstag 03 Mai 2007 08:39 schrieb Hans-Jürgen Koch:
> >
> > Hm, I have about 3 different patches here now, all dependant on each
> > other, yet I can't tell which goes first :(
> >
> > Can someone just send me 1, or 3 with the correct order in which to
> > apply them?
> >
> > thanks,
> >
> > greg k-h
> >
>
> Hi Greg,
> I attached all the UIO patches I collected so far. This is my series file:
>
> uio.patch
> fix-early-irq-problem-in-uio.patch
> uio-documentation.patch
> fix-uio_read-type-problem.patch
> uio-dummy.patch
> uio-hilscher-cif-card-driver.patch
> ioremap-in-uio-hilscher-cif.patch
> add-userspace-howto-to-uio-doc.patch
> fix-uio-doc-build-problems.patch
>
> It should also work without uio-dummy.patch.
> I added Randy's last one-line patch to fix-uio-doc-build-problems.patch.
>
> All patches are
> Signed-off-by: Hans J. Koch <hjk@linutronix.de>
>
> fix-uio-doc-build-problems.patch is also
> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
>
I also updated the original patch set with all these changes. They can be
found here:
http://www.osadl.org/projects/downloads/UIO/kernel/
Thanks,
Hans
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-05-04 9:37 ` Hans-Jürgen Koch
@ 2007-05-07 17:46 ` Randy Dunlap
2007-05-07 20:01 ` Hans-Jürgen Koch
0 siblings, 1 reply; 32+ messages in thread
From: Randy Dunlap @ 2007-05-07 17:46 UTC (permalink / raw)
To: Hans-Jürgen Koch, akpm
Cc: Greg KH, Greg Kroah-Hartman, linux-kernel, torvalds, tglx,
Benedikt Spranger
On Fri, 4 May 2007 11:37:09 +0200 Hans-Jürgen Koch wrote:
> Am Donnerstag 03 Mai 2007 08:39 schrieb Hans-Jürgen Koch:
> > >
> > > Hm, I have about 3 different patches here now, all dependant on each
> > > other, yet I can't tell which goes first :(
> > >
> > > Can someone just send me 1, or 3 with the correct order in which to
> > > apply them?
> > >
> > > thanks,
> > >
> > > greg k-h
> > >
> >
> > Hi Greg,
> > I attached all the UIO patches I collected so far. This is my series file:
> >
> > uio.patch
> > fix-early-irq-problem-in-uio.patch
> > uio-documentation.patch
> > fix-uio_read-type-problem.patch
> > uio-dummy.patch
> > uio-hilscher-cif-card-driver.patch
> > ioremap-in-uio-hilscher-cif.patch
> > add-userspace-howto-to-uio-doc.patch
> > fix-uio-doc-build-problems.patch
> >
> > It should also work without uio-dummy.patch.
> > I added Randy's last one-line patch to fix-uio-doc-build-problems.patch.
> >
> > All patches are
> > Signed-off-by: Hans J. Koch <hjk@linutronix.de>
> >
> > fix-uio-doc-build-problems.patch is also
> > Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
> >
>
> I also updated the original patch set with all these changes. They can be
> found here:
>
> http://www.osadl.org/projects/downloads/UIO/kernel/
Can one of you make sure that Andrew has a version in -mm that
will build without bombing? Current 2.6.21-mm1 does this on UIO docs,
but all of these have been fixed via email AFAIK:
Warning(/tester/linsrc/linux-2621-mm1//drivers/uio/uio.c:240): No description found for parameter 'info'
Warning(/tester/linsrc/linux-2621-mm1//drivers/uio/uio.c:594): No description found for parameter 'owner'
Warning(/tester/linsrc/linux-2621-mm1//drivers/uio/uio.c:594): No description found for parameter 'info'
Warning(/tester/linsrc/linux-2621-mm1//drivers/uio/uio.c:667): No description found for parameter 'info'
Error(/tester/linsrc/linux-2621-mm1//include/linux/uio_driver.h:29): cannot understand prototype: 'struct uio_mem '
Error(/tester/linsrc/linux-2621-mm1//include/linux/uio_driver.h:55): cannot understand prototype: 'struct uio_info '
Warning(/tester/linsrc/linux-2621-mm1//include/linux/uio_driver.h): no structured comments found
make[1]: *** [Documentation/DocBook/kernel-api.xml] Error 2
make: *** [mandocs] Error 2
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-05-07 17:46 ` Randy Dunlap
@ 2007-05-07 20:01 ` Hans-Jürgen Koch
0 siblings, 0 replies; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-05-07 20:01 UTC (permalink / raw)
To: Randy Dunlap
Cc: akpm, Greg KH, Greg Kroah-Hartman, linux-kernel, torvalds, tglx,
Benedikt Spranger
Am Montag 07 Mai 2007 19:46 schrieb Randy Dunlap:
> On Fri, 4 May 2007 11:37:09 +0200 Hans-Jürgen Koch wrote:
>
> > Am Donnerstag 03 Mai 2007 08:39 schrieb Hans-Jürgen Koch:
> > > >
> > > > Hm, I have about 3 different patches here now, all dependant on each
> > > > other, yet I can't tell which goes first :(
> > > >
> > > > Can someone just send me 1, or 3 with the correct order in which to
> > > > apply them?
> > > >
> > > > thanks,
> > > >
> > > > greg k-h
> > > >
> > >
> > > Hi Greg,
> > > I attached all the UIO patches I collected so far. This is my series file:
> > >
> > > uio.patch
> > > fix-early-irq-problem-in-uio.patch
> > > uio-documentation.patch
> > > fix-uio_read-type-problem.patch
> > > uio-dummy.patch
> > > uio-hilscher-cif-card-driver.patch
> > > ioremap-in-uio-hilscher-cif.patch
> > > add-userspace-howto-to-uio-doc.patch
> > > fix-uio-doc-build-problems.patch
> > >
> > > It should also work without uio-dummy.patch.
> > > I added Randy's last one-line patch to fix-uio-doc-build-problems.patch.
> > >
> > > All patches are
> > > Signed-off-by: Hans J. Koch <hjk@linutronix.de>
> > >
> > > fix-uio-doc-build-problems.patch is also
> > > Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
> > >
> >
> > I also updated the original patch set with all these changes. They can be
> > found here:
> >
> > http://www.osadl.org/projects/downloads/UIO/kernel/
>
> Can one of you make sure that Andrew has a version in -mm that
> will build without bombing?
Andrew usually takes Greg's patches AFAIK. The patches in
http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/driver/
are definitely out of date. Greg, could you update them?
> Current 2.6.21-mm1 does this on UIO docs,
> but all of these have been fixed via email AFAIK:
>
> Warning(/tester/linsrc/linux-2621-mm1//drivers/uio/uio.c:240): No description found for parameter 'info'
> Warning(/tester/linsrc/linux-2621-mm1//drivers/uio/uio.c:594): No description found for parameter 'owner'
> Warning(/tester/linsrc/linux-2621-mm1//drivers/uio/uio.c:594): No description found for parameter 'info'
> Warning(/tester/linsrc/linux-2621-mm1//drivers/uio/uio.c:667): No description found for parameter 'info'
> Error(/tester/linsrc/linux-2621-mm1//include/linux/uio_driver.h:29): cannot understand prototype: 'struct uio_mem '
> Error(/tester/linsrc/linux-2621-mm1//include/linux/uio_driver.h:55): cannot understand prototype: 'struct uio_info '
> Warning(/tester/linsrc/linux-2621-mm1//include/linux/uio_driver.h): no structured comments found
> make[1]: *** [Documentation/DocBook/kernel-api.xml] Error 2
> make: *** [mandocs] Error 2
Yes, all of these are fixed in the patches I sent.
Thanks,
Hans
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 2/3] UIO: Documentation
2007-05-08 14:08 ` [PATCH 1/3] UIO: Add the User IO core code Greg Kroah-Hartman
@ 2007-05-08 14:08 ` Greg Kroah-Hartman
0 siblings, 0 replies; 32+ messages in thread
From: Greg Kroah-Hartman @ 2007-05-08 14:08 UTC (permalink / raw)
To: linux-kernel; +Cc: Hans J. Koch, Greg Kroah-Hartman
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 22500 bytes --]
From: Hans J. Koch <hjk@linutronix.de>
Documentation for the UIO interface
From: Hans J. Koch <hjk@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
Documentation/DocBook/kernel-api.tmpl | 4 +
Documentation/DocBook/uio-howto.tmpl | 611 +++++++++++++++++++++++++++++++++
2 files changed, 615 insertions(+), 0 deletions(-)
create mode 100644 Documentation/DocBook/uio-howto.tmpl
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index b61dfc7..4b7b2fd 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -402,6 +402,10 @@ X!Edrivers/pnp/system.c
!Edrivers/pnp/manager.c
!Edrivers/pnp/support.c
</sect1>
+ <sect1><title>Userspace IO devices</title>
+!Edrivers/uio/uio.c
+!Iinclude/linux/uio_driver.h
+ </sect1>
</chapter>
<chapter id="blkdev">
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
new file mode 100644
index 0000000..e3bb29a
--- /dev/null
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -0,0 +1,611 @@
+<?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@linutronix.de</email>
+ </address>
+ </affiliation>
+</author>
+
+<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.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="about.html"?>
+<title>About this document</title>
+
+<sect1 id="copyright">
+<?dbhtml filename="copyright.html"?>
+<title>Copyright and License</title>
+<para>
+ Copyright (c) 2006 by Hans-Jürgen Koch.</para>
+<para>
+This documentation is Free Software licensed under the terms of the
+GPL version 2.
+</para>
+</sect1>
+
+<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@linutronix.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>
+</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@linutronix.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>
+<listitem>
+ <para>if you need to keep some parts of your driver closed source,
+ you can do so without violating the GPL license on 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>
+ 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.
+ See <filename>drivers/uio/uio_dummy.c</filename> for an
+ example of this technique.
+ </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 two read-only files
+ that show start address and size of the memory:
+</para>
+<itemizedlist>
+<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>
+</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>
+
+</sect1>
+</chapter>
+
+<chapter id="using-uio_dummy" xreflabel="Using uio_dummy">
+<?dbhtml filename="using-uio_dummy.html"?>
+<title>Using uio_dummy</title>
+ <para>
+ 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.
+ </para>
+
+<sect1 id="what_uio_dummy_does">
+<title>What uio_dummy does</title>
+ <para>
+ The kernel module <filename>uio_dummy.ko</filename> 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, <varname>count</varname>
+ and <varname>freq</varname>, that appear under
+ <filename>/sys/devices/platform/uio_dummy/</filename>.
+ </para>
+
+ <para>
+ The attribute <varname>count</varname> can be read and
+ written. The associated file
+ <filename>/sys/devices/platform/uio_dummy/count</filename>
+ appears as a normal text file and contains the total number of
+ timer interrupts. If you look at it (e.g. using
+ <function>cat</function>), you'll notice it is slowly counting
+ up.
+ </para>
+
+ <para>
+ The attribute <varname>freq</varname> can be read and written.
+ The content of
+ <filename>/sys/devices/platform/uio_dummy/freq</filename>
+ represents the number of system timer ticks between two timer
+ interrupts. The default value of <varname>freq</varname> is
+ the value of the kernel variable <varname>HZ</varname>, which
+ gives you an interval of one second. Lower values will
+ increase the frequency. Try the following:
+ </para>
+<programlisting format="linespecific">
+cd /sys/devices/platform/uio_dummy/
+echo 100 > freq
+</programlisting>
+ <para>
+ Use <function>cat count</function> to see how the interrupt
+ frequency changes.
+ </para>
+</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_dummy.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>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>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>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>. 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
+<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>
+</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>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>unsigned long 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>unsigned long 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>kobj</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>
+</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>
+
+</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 occured.
+ </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>
+
+<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>
--
1.5.1.3
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [GIT PATCH] UIO patches for 2.6.22
@ 2007-07-18 23:23 Greg KH
2007-07-18 23:26 ` [PATCH 1/3] UIO: Add the User IO core code Greg Kroah-Hartman
0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-07-18 23:23 UTC (permalink / raw)
To: Linus Torvalds, Andrew Morton
Cc: linux-kernel, tglx, Benedikt Spranger, Hans J. Koch
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=unknown-8bit, Size: 1827 bytes --]
Here are the UIO (Userspace I/O driver framework) patches for 2.6.22
They have been revamped from the last time you have seen them, and they
include a real driver, the Hilscher CIF DeviceNet and Profibus card
controller, which is being used in production systems with this driver
framework right now. The kernel driver they replaced was a total mess,
with over 60+ ioctls to try to control the different aspects of the
device. See the last patch in this series for more details on this
driver.
These patches include full documentation, are self-contained from the
rest of the kernel, and have been in the -mm tree for the past few
months with no complaints.
Please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/gregkh/uio-2.6.git/
Patches will be sent as a follow-on to this message to lkml for people
to see.
thanks,
greg k-h
Documentation/DocBook/kernel-api.tmpl | 4 +
Documentation/DocBook/uio-howto.tmpl | 611 ++++++++++++++++++++++++++++
drivers/Kconfig | 1 +
drivers/Makefile | 1 +
drivers/uio/Kconfig | 29 ++
drivers/uio/Makefile | 2 +
drivers/uio/uio.c | 701 +++++++++++++++++++++++++++++++++
drivers/uio/uio_cif.c | 156 ++++++++
include/linux/uio_driver.h | 91 +++++
9 files changed, 1596 insertions(+), 0 deletions(-)
create mode 100644 Documentation/DocBook/uio-howto.tmpl
create mode 100644 drivers/uio/Kconfig
create mode 100644 drivers/uio/Makefile
create mode 100644 drivers/uio/uio.c
create mode 100644 drivers/uio/uio_cif.c
create mode 100644 include/linux/uio_driver.h
---------------
Hans J. Koch (2):
UIO: Add the User IO core code
UIO: Documentation
Hans-Jürgen Koch (1):
UIO: Hilscher CIF card driver
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 1/3] UIO: Add the User IO core code
2007-07-18 23:23 [GIT PATCH] UIO patches for 2.6.22 Greg KH
@ 2007-07-18 23:26 ` Greg Kroah-Hartman
2007-07-18 23:26 ` [PATCH 2/3] UIO: Documentation Greg Kroah-Hartman
0 siblings, 1 reply; 32+ messages in thread
From: Greg Kroah-Hartman @ 2007-07-18 23:26 UTC (permalink / raw)
To: linux-kernel
Cc: Hans J. Koch, Thomas Gleixner, Benedikt Spranger,
Greg Kroah-Hartman
From: Hans J. Koch <hjk@linutronix.de>
This interface allows the ability to write the majority of a driver in
userspace with only a very small shell of a driver in the kernel itself.
It uses a char device and sysfs to interact with a userspace process to
process interrupts and control memory accesses.
See the docbook documentation for more details on how to use this
interface.
From: Hans J. Koch <hjk@linutronix.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/Kconfig | 1 +
drivers/Makefile | 1 +
drivers/uio/Kconfig | 16 +
drivers/uio/Makefile | 1 +
drivers/uio/uio.c | 701 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/uio_driver.h | 91 ++++++
6 files changed, 811 insertions(+), 0 deletions(-)
create mode 100644 drivers/uio/Kconfig
create mode 100644 drivers/uio/Makefile
create mode 100644 drivers/uio/uio.c
create mode 100644 include/linux/uio_driver.h
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 7916f4b..ae01d86 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -84,4 +84,5 @@ source "drivers/auxdisplay/Kconfig"
source "drivers/kvm/Kconfig"
+source "drivers/uio/Kconfig"
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 6d9d7fa..c34c8ef 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_ATA) += ata/
obj-$(CONFIG_FUSION) += message/
obj-$(CONFIG_FIREWIRE) += firewire/
obj-$(CONFIG_IEEE1394) += ieee1394/
+obj-$(CONFIG_UIO) += uio/
obj-y += cdrom/
obj-y += auxdisplay/
obj-$(CONFIG_MTD) += mtd/
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
new file mode 100644
index 0000000..6b1a62d
--- /dev/null
+++ b/drivers/uio/Kconfig
@@ -0,0 +1,16 @@
+menu "Userspace I/O"
+ depends on !S390
+
+config UIO
+ tristate "Userspace I/O drivers"
+ default n
+ help
+ Enable this to allow the userspace driver core code to be
+ built. This code allows userspace programs easy access to
+ kernel interrupts and memory locations, allowing some drivers
+ to be written in userspace. Note that a small kernel driver
+ is also required for interrupt handling to work properly.
+
+ If you don't know what to do here, say N.
+
+endmenu
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
new file mode 100644
index 0000000..9b7c830
--- /dev/null
+++ b/drivers/uio/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_UIO) += uio.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
new file mode 100644
index 0000000..865f32b
--- /dev/null
+++ b/drivers/uio/uio.c
@@ -0,0 +1,701 @@
+/*
+ * drivers/uio/uio.c
+ *
+ * Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de>
+ * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2006, Hans J. Koch <hjk@linutronix.de>
+ * Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com>
+ *
+ * Userspace IO
+ *
+ * Base Functions
+ *
+ * Licensed under the GPLv2 only.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/idr.h>
+#include <linux/string.h>
+#include <linux/kobject.h>
+#include <linux/uio_driver.h>
+
+#define UIO_MAX_DEVICES 255
+
+struct uio_device {
+ struct module *owner;
+ struct device *dev;
+ int minor;
+ atomic_t event;
+ struct fasync_struct *async_queue;
+ wait_queue_head_t wait;
+ int vma_count;
+ struct uio_info *info;
+ struct kset map_attr_kset;
+};
+
+static int uio_major;
+static DEFINE_IDR(uio_idr);
+static struct file_operations uio_fops;
+
+/* UIO class infrastructure */
+static struct uio_class {
+ struct kref kref;
+ struct class *class;
+} *uio_class;
+
+/*
+ * attributes
+ */
+
+static struct attribute attr_addr = {
+ .name = "addr",
+ .mode = S_IRUGO,
+};
+
+static struct attribute attr_size = {
+ .name = "size",
+ .mode = S_IRUGO,
+};
+
+static struct attribute* map_attrs[] = {
+ &attr_addr, &attr_size, NULL
+};
+
+static ssize_t map_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct uio_mem *mem = container_of(kobj, struct uio_mem, kobj);
+
+ if (strncmp(attr->name,"addr",4) == 0)
+ return sprintf(buf, "0x%lx\n", mem->addr);
+
+ if (strncmp(attr->name,"size",4) == 0)
+ return sprintf(buf, "0x%lx\n", mem->size);
+
+ return -ENODEV;
+}
+
+static void map_attr_release(struct kobject *kobj)
+{
+ /* TODO ??? */
+}
+
+static struct sysfs_ops map_attr_ops = {
+ .show = map_attr_show,
+};
+
+static struct kobj_type map_attr_type = {
+ .release = map_attr_release,
+ .sysfs_ops = &map_attr_ops,
+ .default_attrs = map_attrs,
+};
+
+static ssize_t show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct uio_device *idev = dev_get_drvdata(dev);
+ if (idev)
+ return sprintf(buf, "%s\n", idev->info->name);
+ else
+ return -ENODEV;
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static ssize_t show_version(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct uio_device *idev = dev_get_drvdata(dev);
+ if (idev)
+ return sprintf(buf, "%s\n", idev->info->version);
+ else
+ return -ENODEV;
+}
+static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
+
+static ssize_t show_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct uio_device *idev = dev_get_drvdata(dev);
+ if (idev)
+ return sprintf(buf, "%u\n",
+ (unsigned int)atomic_read(&idev->event));
+ else
+ return -ENODEV;
+}
+static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
+
+static struct attribute *uio_attrs[] = {
+ &dev_attr_name.attr,
+ &dev_attr_version.attr,
+ &dev_attr_event.attr,
+ NULL,
+};
+
+static struct attribute_group uio_attr_grp = {
+ .attrs = uio_attrs,
+};
+
+/*
+ * device functions
+ */
+static int uio_dev_add_attributes(struct uio_device *idev)
+{
+ int ret;
+ int mi;
+ int map_found = 0;
+ struct uio_mem *mem;
+
+ ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp);
+ if (ret)
+ goto err_group;
+
+ for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
+ mem = &idev->info->mem[mi];
+ if (mem->size == 0)
+ break;
+ if (!map_found) {
+ map_found = 1;
+ kobject_set_name(&idev->map_attr_kset.kobj,"maps");
+ idev->map_attr_kset.ktype = &map_attr_type;
+ idev->map_attr_kset.kobj.parent = &idev->dev->kobj;
+ ret = kset_register(&idev->map_attr_kset);
+ if (ret)
+ goto err_remove_group;
+ }
+ kobject_init(&mem->kobj);
+ kobject_set_name(&mem->kobj,"map%d",mi);
+ mem->kobj.parent = &idev->map_attr_kset.kobj;
+ mem->kobj.kset = &idev->map_attr_kset;
+ ret = kobject_add(&mem->kobj);
+ if (ret)
+ goto err_remove_maps;
+ }
+
+ return 0;
+
+err_remove_maps:
+ for (mi--; mi>=0; mi--) {
+ mem = &idev->info->mem[mi];
+ kobject_unregister(&mem->kobj);
+ }
+ kset_unregister(&idev->map_attr_kset); /* Needed ? */
+err_remove_group:
+ sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
+err_group:
+ dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);
+ return ret;
+}
+
+static void uio_dev_del_attributes(struct uio_device *idev)
+{
+ int mi;
+ struct uio_mem *mem;
+ for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
+ mem = &idev->info->mem[mi];
+ if (mem->size == 0)
+ break;
+ kobject_unregister(&mem->kobj);
+ }
+ kset_unregister(&idev->map_attr_kset);
+ sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
+}
+
+static int uio_get_minor(struct uio_device *idev)
+{
+ static DEFINE_MUTEX(minor_lock);
+ int retval = -ENOMEM;
+ int id;
+
+ mutex_lock(&minor_lock);
+ if (idr_pre_get(&uio_idr, GFP_KERNEL) == 0)
+ goto exit;
+
+ retval = idr_get_new(&uio_idr, idev, &id);
+ if (retval < 0) {
+ if (retval == -EAGAIN)
+ retval = -ENOMEM;
+ goto exit;
+ }
+ idev->minor = id & MAX_ID_MASK;
+exit:
+ mutex_unlock(&minor_lock);
+ return retval;
+}
+
+static void uio_free_minor(struct uio_device *idev)
+{
+ idr_remove(&uio_idr, idev->minor);
+}
+
+/**
+ * uio_event_notify - trigger an interrupt event
+ * @info: UIO device capabilities
+ */
+void uio_event_notify(struct uio_info *info)
+{
+ struct uio_device *idev = info->uio_dev;
+
+ atomic_inc(&idev->event);
+ wake_up_interruptible(&idev->wait);
+ kill_fasync(&idev->async_queue, SIGIO, POLL_IN);
+}
+EXPORT_SYMBOL_GPL(uio_event_notify);
+
+/**
+ * uio_interrupt - hardware interrupt handler
+ * @irq: IRQ number, can be UIO_IRQ_CYCLIC for cyclic timer
+ * @dev_id: Pointer to the devices uio_device structure
+ */
+static irqreturn_t uio_interrupt(int irq, void *dev_id)
+{
+ struct uio_device *idev = (struct uio_device *)dev_id;
+ irqreturn_t ret = idev->info->handler(irq, idev->info);
+
+ if (ret == IRQ_HANDLED)
+ uio_event_notify(idev->info);
+
+ return ret;
+}
+
+struct uio_listener {
+ struct uio_device *dev;
+ s32 event_count;
+};
+
+static int uio_open(struct inode *inode, struct file *filep)
+{
+ struct uio_device *idev;
+ struct uio_listener *listener;
+ int ret = 0;
+
+ idev = idr_find(&uio_idr, iminor(inode));
+ if (!idev)
+ return -ENODEV;
+
+ listener = kmalloc(sizeof(*listener), GFP_KERNEL);
+ if (!listener)
+ return -ENOMEM;
+
+ listener->dev = idev;
+ listener->event_count = atomic_read(&idev->event);
+ filep->private_data = listener;
+
+ if (idev->info->open) {
+ if (!try_module_get(idev->owner))
+ return -ENODEV;
+ ret = idev->info->open(idev->info, inode);
+ module_put(idev->owner);
+ }
+
+ if (ret)
+ kfree(listener);
+
+ return ret;
+}
+
+static int uio_fasync(int fd, struct file *filep, int on)
+{
+ struct uio_listener *listener = filep->private_data;
+ struct uio_device *idev = listener->dev;
+
+ return fasync_helper(fd, filep, on, &idev->async_queue);
+}
+
+static int uio_release(struct inode *inode, struct file *filep)
+{
+ int ret = 0;
+ struct uio_listener *listener = filep->private_data;
+ struct uio_device *idev = listener->dev;
+
+ if (idev->info->release) {
+ if (!try_module_get(idev->owner))
+ return -ENODEV;
+ ret = idev->info->release(idev->info, inode);
+ module_put(idev->owner);
+ }
+ if (filep->f_flags & FASYNC)
+ ret = uio_fasync(-1, filep, 0);
+ kfree(listener);
+ return ret;
+}
+
+static unsigned int uio_poll(struct file *filep, poll_table *wait)
+{
+ struct uio_listener *listener = filep->private_data;
+ struct uio_device *idev = listener->dev;
+
+ if (idev->info->irq == UIO_IRQ_NONE)
+ return -EIO;
+
+ poll_wait(filep, &idev->wait, wait);
+ if (listener->event_count != atomic_read(&idev->event))
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+static ssize_t uio_read(struct file *filep, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct uio_listener *listener = filep->private_data;
+ struct uio_device *idev = listener->dev;
+ DECLARE_WAITQUEUE(wait, current);
+ ssize_t retval;
+ s32 event_count;
+
+ if (idev->info->irq == UIO_IRQ_NONE)
+ return -EIO;
+
+ if (count != sizeof(s32))
+ return -EINVAL;
+
+ add_wait_queue(&idev->wait, &wait);
+
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ event_count = atomic_read(&idev->event);
+ if (event_count != listener->event_count) {
+ if (copy_to_user(buf, &event_count, count))
+ retval = -EFAULT;
+ else {
+ listener->event_count = event_count;
+ retval = count;
+ }
+ break;
+ }
+
+ if (filep->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ schedule();
+ } while (1);
+
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&idev->wait, &wait);
+
+ return retval;
+}
+
+static int uio_find_mem_index(struct vm_area_struct *vma)
+{
+ int mi;
+ struct uio_device *idev = vma->vm_private_data;
+
+ for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
+ if (idev->info->mem[mi].size == 0)
+ return -1;
+ if (vma->vm_pgoff == mi)
+ return mi;
+ }
+ return -1;
+}
+
+static void uio_vma_open(struct vm_area_struct *vma)
+{
+ struct uio_device *idev = vma->vm_private_data;
+ idev->vma_count++;
+}
+
+static void uio_vma_close(struct vm_area_struct *vma)
+{
+ struct uio_device *idev = vma->vm_private_data;
+ idev->vma_count--;
+}
+
+static struct page *uio_vma_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ struct uio_device *idev = vma->vm_private_data;
+ struct page* page = NOPAGE_SIGBUS;
+
+ int mi = uio_find_mem_index(vma);
+ if (mi < 0)
+ return page;
+
+ if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
+ page = virt_to_page(idev->info->mem[mi].addr);
+ else
+ page = vmalloc_to_page((void*)idev->info->mem[mi].addr);
+ get_page(page);
+ if (type)
+ *type = VM_FAULT_MINOR;
+ return page;
+}
+
+static struct vm_operations_struct uio_vm_ops = {
+ .open = uio_vma_open,
+ .close = uio_vma_close,
+ .nopage = uio_vma_nopage,
+};
+
+static int uio_mmap_physical(struct vm_area_struct *vma)
+{
+ struct uio_device *idev = vma->vm_private_data;
+ int mi = uio_find_mem_index(vma);
+ if (mi < 0)
+ return -EINVAL;
+
+ vma->vm_flags |= VM_IO | VM_RESERVED;
+
+ return remap_pfn_range(vma,
+ vma->vm_start,
+ idev->info->mem[mi].addr >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+}
+
+static int uio_mmap_logical(struct vm_area_struct *vma)
+{
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_ops = &uio_vm_ops;
+ uio_vma_open(vma);
+ return 0;
+}
+
+static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
+{
+ struct uio_listener *listener = filep->private_data;
+ struct uio_device *idev = listener->dev;
+ int mi;
+ unsigned long requested_pages, actual_pages;
+ int ret = 0;
+
+ if (vma->vm_end < vma->vm_start)
+ return -EINVAL;
+
+ vma->vm_private_data = idev;
+
+ mi = uio_find_mem_index(vma);
+ if (mi < 0)
+ return -EINVAL;
+
+ requested_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ actual_pages = (idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT;
+ if (requested_pages > actual_pages)
+ return -EINVAL;
+
+ if (idev->info->mmap) {
+ if (!try_module_get(idev->owner))
+ return -ENODEV;
+ ret = idev->info->mmap(idev->info, vma);
+ module_put(idev->owner);
+ return ret;
+ }
+
+ switch (idev->info->mem[mi].memtype) {
+ case UIO_MEM_PHYS:
+ return uio_mmap_physical(vma);
+ case UIO_MEM_LOGICAL:
+ case UIO_MEM_VIRTUAL:
+ return uio_mmap_logical(vma);
+ default:
+ return -EINVAL;
+ }
+}
+
+static struct file_operations uio_fops = {
+ .owner = THIS_MODULE,
+ .open = uio_open,
+ .release = uio_release,
+ .read = uio_read,
+ .mmap = uio_mmap,
+ .poll = uio_poll,
+ .fasync = uio_fasync,
+};
+
+static int uio_major_init(void)
+{
+ uio_major = register_chrdev(0, "uio", &uio_fops);
+ if (uio_major < 0)
+ return uio_major;
+ return 0;
+}
+
+static void uio_major_cleanup(void)
+{
+ unregister_chrdev(uio_major, "uio");
+}
+
+static int init_uio_class(void)
+{
+ int ret = 0;
+
+ if (uio_class != NULL) {
+ kref_get(&uio_class->kref);
+ goto exit;
+ }
+
+ /* This is the first time in here, set everything up properly */
+ ret = uio_major_init();
+ if (ret)
+ goto exit;
+
+ uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL);
+ if (!uio_class) {
+ ret = -ENOMEM;
+ goto err_kzalloc;
+ }
+
+ kref_init(&uio_class->kref);
+ uio_class->class = class_create(THIS_MODULE, "uio");
+ if (IS_ERR(uio_class->class)) {
+ ret = IS_ERR(uio_class->class);
+ printk(KERN_ERR "class_create failed for uio\n");
+ goto err_class_create;
+ }
+ return 0;
+
+err_class_create:
+ kfree(uio_class);
+ uio_class = NULL;
+err_kzalloc:
+ uio_major_cleanup();
+exit:
+ return ret;
+}
+
+static void release_uio_class(struct kref *kref)
+{
+ /* Ok, we cheat as we know we only have one uio_class */
+ class_destroy(uio_class->class);
+ kfree(uio_class);
+ uio_major_cleanup();
+ uio_class = NULL;
+}
+
+static void uio_class_destroy(void)
+{
+ if (uio_class)
+ kref_put(&uio_class->kref, release_uio_class);
+}
+
+/**
+ * uio_register_device - register a new userspace IO device
+ * @owner: module that creates the new device
+ * @parent: parent device
+ * @info: UIO device capabilities
+ *
+ * returns zero on success or a negative error code.
+ */
+int __uio_register_device(struct module *owner,
+ struct device *parent,
+ struct uio_info *info)
+{
+ struct uio_device *idev;
+ int ret = 0;
+
+ if (!parent || !info || !info->name || !info->version)
+ return -EINVAL;
+
+ info->uio_dev = NULL;
+
+ ret = init_uio_class();
+ if (ret)
+ return ret;
+
+ idev = kzalloc(sizeof(*idev), GFP_KERNEL);
+ if (!idev) {
+ ret = -ENOMEM;
+ goto err_kzalloc;
+ }
+
+ idev->owner = owner;
+ idev->info = info;
+ init_waitqueue_head(&idev->wait);
+ atomic_set(&idev->event, 0);
+
+ ret = uio_get_minor(idev);
+ if (ret)
+ goto err_get_minor;
+
+ idev->dev = device_create(uio_class->class, parent,
+ MKDEV(uio_major, idev->minor),
+ "uio%d", idev->minor);
+ if (IS_ERR(idev->dev)) {
+ printk(KERN_ERR "UIO: device register failed\n");
+ ret = PTR_ERR(idev->dev);
+ goto err_device_create;
+ }
+ dev_set_drvdata(idev->dev, idev);
+
+ ret = uio_dev_add_attributes(idev);
+ if (ret)
+ goto err_uio_dev_add_attributes;
+
+ info->uio_dev = idev;
+
+ if (idev->info->irq >= 0) {
+ ret = request_irq(idev->info->irq, uio_interrupt,
+ idev->info->irq_flags, idev->info->name, idev);
+ if (ret)
+ goto err_request_irq;
+ }
+
+ return 0;
+
+err_request_irq:
+ uio_dev_del_attributes(idev);
+err_uio_dev_add_attributes:
+ device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
+err_device_create:
+ uio_free_minor(idev);
+err_get_minor:
+ kfree(idev);
+err_kzalloc:
+ uio_class_destroy();
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__uio_register_device);
+
+/**
+ * uio_unregister_device - unregister a industrial IO device
+ * @info: UIO device capabilities
+ *
+ */
+void uio_unregister_device(struct uio_info *info)
+{
+ struct uio_device *idev;
+
+ if (!info || !info->uio_dev)
+ return;
+
+ idev = info->uio_dev;
+
+ uio_free_minor(idev);
+
+ if (info->irq >= 0)
+ free_irq(info->irq, idev);
+
+ uio_dev_del_attributes(idev);
+
+ dev_set_drvdata(idev->dev, NULL);
+ device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
+ kfree(idev);
+ uio_class_destroy();
+
+ return;
+}
+EXPORT_SYMBOL_GPL(uio_unregister_device);
+
+static int __init uio_init(void)
+{
+ return 0;
+}
+
+static void __exit uio_exit(void)
+{
+}
+
+module_init(uio_init)
+module_exit(uio_exit)
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h
new file mode 100644
index 0000000..44c28e9
--- /dev/null
+++ b/include/linux/uio_driver.h
@@ -0,0 +1,91 @@
+/*
+ * include/linux/uio_driver.h
+ *
+ * Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de>
+ * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2006, Hans J. Koch <hjk@linutronix.de>
+ * Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com>
+ *
+ * Userspace IO driver.
+ *
+ * Licensed under the GPLv2 only.
+ */
+
+#ifndef _UIO_DRIVER_H_
+#define _UIO_DRIVER_H_
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+
+/**
+ * struct uio_mem - description of a UIO memory region
+ * @kobj: kobject for this mapping
+ * @addr: address of the device's memory
+ * @size: size of IO
+ * @memtype: type of memory addr points to
+ * @internal_addr: ioremap-ped version of addr, for driver internal use
+ */
+struct uio_mem {
+ struct kobject kobj;
+ unsigned long addr;
+ unsigned long size;
+ int memtype;
+ void __iomem *internal_addr;
+};
+
+#define MAX_UIO_MAPS 5
+
+struct uio_device;
+
+/**
+ * struct uio_info - UIO device capabilities
+ * @uio_dev: the UIO device this info belongs to
+ * @name: device name
+ * @version: device driver version
+ * @mem: list of mappable memory regions, size==0 for end of list
+ * @irq: interrupt number or UIO_IRQ_CUSTOM
+ * @irq_flags: flags for request_irq()
+ * @priv: optional private data
+ * @handler: the device's irq handler
+ * @mmap: mmap operation for this uio device
+ * @open: open operation for this uio device
+ * @release: release operation for this uio device
+ */
+struct uio_info {
+ struct uio_device *uio_dev;
+ char *name;
+ char *version;
+ struct uio_mem mem[MAX_UIO_MAPS];
+ long irq;
+ unsigned long irq_flags;
+ void *priv;
+ irqreturn_t (*handler)(int irq, struct uio_info *dev_info);
+ int (*mmap)(struct uio_info *info, struct vm_area_struct *vma);
+ int (*open)(struct uio_info *info, struct inode *inode);
+ int (*release)(struct uio_info *info, struct inode *inode);
+};
+
+extern int __must_check
+ __uio_register_device(struct module *owner,
+ struct device *parent,
+ struct uio_info *info);
+static inline int __must_check
+ uio_register_device(struct device *parent, struct uio_info *info)
+{
+ return __uio_register_device(THIS_MODULE, parent, info);
+}
+extern void uio_unregister_device(struct uio_info *info);
+extern void uio_event_notify(struct uio_info *info);
+
+/* defines for uio_device->irq */
+#define UIO_IRQ_CUSTOM -1
+#define UIO_IRQ_NONE -2
+
+/* defines for uio_device->memtype */
+#define UIO_MEM_NONE 0
+#define UIO_MEM_PHYS 1
+#define UIO_MEM_LOGICAL 2
+#define UIO_MEM_VIRTUAL 3
+
+#endif /* _LINUX_UIO_DRIVER_H_ */
--
1.5.2.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH 2/3] UIO: Documentation
2007-07-18 23:26 ` [PATCH 1/3] UIO: Add the User IO core code Greg Kroah-Hartman
@ 2007-07-18 23:26 ` Greg Kroah-Hartman
2007-07-18 23:26 ` [PATCH 3/3] UIO: Hilscher CIF card driver Greg Kroah-Hartman
2007-08-08 21:36 ` [PATCH 2/3] UIO: Documentation Jesper Juhl
0 siblings, 2 replies; 32+ messages in thread
From: Greg Kroah-Hartman @ 2007-07-18 23:26 UTC (permalink / raw)
To: linux-kernel; +Cc: Hans J. Koch, Greg Kroah-Hartman
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 22500 bytes --]
From: Hans J. Koch <hjk@linutronix.de>
Documentation for the UIO interface
From: Hans J. Koch <hjk@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
Documentation/DocBook/kernel-api.tmpl | 4 +
Documentation/DocBook/uio-howto.tmpl | 611 +++++++++++++++++++++++++++++++++
2 files changed, 615 insertions(+), 0 deletions(-)
create mode 100644 Documentation/DocBook/uio-howto.tmpl
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index fd2ef4d..a0af560 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
</sect1>
+ <sect1><title>Userspace IO devices</title>
+!Edrivers/uio/uio.c
+!Iinclude/linux/uio_driver.h
+ </sect1>
</chapter>
<chapter id="blkdev">
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
new file mode 100644
index 0000000..e3bb29a
--- /dev/null
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -0,0 +1,611 @@
+<?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@linutronix.de</email>
+ </address>
+ </affiliation>
+</author>
+
+<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.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="about.html"?>
+<title>About this document</title>
+
+<sect1 id="copyright">
+<?dbhtml filename="copyright.html"?>
+<title>Copyright and License</title>
+<para>
+ Copyright (c) 2006 by Hans-Jürgen Koch.</para>
+<para>
+This documentation is Free Software licensed under the terms of the
+GPL version 2.
+</para>
+</sect1>
+
+<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@linutronix.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>
+</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@linutronix.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>
+<listitem>
+ <para>if you need to keep some parts of your driver closed source,
+ you can do so without violating the GPL license on 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>
+ 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.
+ See <filename>drivers/uio/uio_dummy.c</filename> for an
+ example of this technique.
+ </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 two read-only files
+ that show start address and size of the memory:
+</para>
+<itemizedlist>
+<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>
+</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>
+
+</sect1>
+</chapter>
+
+<chapter id="using-uio_dummy" xreflabel="Using uio_dummy">
+<?dbhtml filename="using-uio_dummy.html"?>
+<title>Using uio_dummy</title>
+ <para>
+ 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.
+ </para>
+
+<sect1 id="what_uio_dummy_does">
+<title>What uio_dummy does</title>
+ <para>
+ The kernel module <filename>uio_dummy.ko</filename> 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, <varname>count</varname>
+ and <varname>freq</varname>, that appear under
+ <filename>/sys/devices/platform/uio_dummy/</filename>.
+ </para>
+
+ <para>
+ The attribute <varname>count</varname> can be read and
+ written. The associated file
+ <filename>/sys/devices/platform/uio_dummy/count</filename>
+ appears as a normal text file and contains the total number of
+ timer interrupts. If you look at it (e.g. using
+ <function>cat</function>), you'll notice it is slowly counting
+ up.
+ </para>
+
+ <para>
+ The attribute <varname>freq</varname> can be read and written.
+ The content of
+ <filename>/sys/devices/platform/uio_dummy/freq</filename>
+ represents the number of system timer ticks between two timer
+ interrupts. The default value of <varname>freq</varname> is
+ the value of the kernel variable <varname>HZ</varname>, which
+ gives you an interval of one second. Lower values will
+ increase the frequency. Try the following:
+ </para>
+<programlisting format="linespecific">
+cd /sys/devices/platform/uio_dummy/
+echo 100 > freq
+</programlisting>
+ <para>
+ Use <function>cat count</function> to see how the interrupt
+ frequency changes.
+ </para>
+</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_dummy.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>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>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>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>. 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
+<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>
+</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>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>unsigned long 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>unsigned long 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>kobj</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>
+</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>
+
+</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 occured.
+ </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>
+
+<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>
--
1.5.2.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH 3/3] UIO: Hilscher CIF card driver
2007-07-18 23:26 ` [PATCH 2/3] UIO: Documentation Greg Kroah-Hartman
@ 2007-07-18 23:26 ` Greg Kroah-Hartman
2007-07-19 16:33 ` Jan Engelhardt
2007-08-08 21:36 ` [PATCH 2/3] UIO: Documentation Jesper Juhl
1 sibling, 1 reply; 32+ messages in thread
From: Greg Kroah-Hartman @ 2007-07-18 23:26 UTC (permalink / raw)
To: linux-kernel; +Cc: Hans-Jürgen Koch, Greg Kroah-Hartman
From: Hans-Jürgen Koch <hjk@linutronix.de>
this is a patch that adds support for Hilscher CIF DeviceNet and
Profibus cards. I tested it on a Kontron CPX board, and Thomas reviewed
it.
You can find the user space part here:
http://www.osadl.org/projects/downloads/UIO/user/cif-0.1.0.tar.gz
Notes: cif_api.c is the main file you want to look at. It contains the
functions to open, close, mmap and so on. cif_dps.c adds functions
specific to Profibus cards, and cif_dn.c contains functions for
DeviceNet cards. cif.c is a universal playground, it's just a small
test program. The user space part of this UIO driver is still work in
progress, and not everything is tested yet. At the moment, the thread in
cif_api.c contains some code that artificially makes the card generate
interrupts, this was added for testing and will be removed later. But
the driver already contains all the functions needed for useful
operation, so it gives a good idea of how such a thing looks like.
For comparison, here's what you get from the manufacturer
(www.hilscher.com) when you ask for a Linux 2.6 driver:
http://www.tglx.de/private/hjk/cif-orig-2.6.tar.bz2
WARNING: Don't look at the code for too long, you might become sick :-)
Signed-off-by: Hans-Jürgen Koch <hjk@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/uio/Kconfig | 13 ++++
drivers/uio/Makefile | 3 +-
drivers/uio/uio_cif.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 171 insertions(+), 1 deletions(-)
create mode 100644 drivers/uio/uio_cif.c
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 6b1a62d..b778ed7 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -13,4 +13,17 @@ config UIO
If you don't know what to do here, say N.
+config UIO_CIF
+ tristate "generic Hilscher CIF Card driver"
+ depends on UIO && PCI
+ default n
+ help
+ Driver for Hilscher CIF DeviceNet and Profibus cards. This
+ driver requires a userspace component that handles all of the
+ heavy lifting and can be found at:
+ http://www.osadl.org/projects/downloads/UIO/user/cif-*
+
+ To compile this driver as a module, choose M here: the module
+ will be called uio_cif.
+
endmenu
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 9b7c830..7fecfb4 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -1 +1,2 @@
-obj-$(CONFIG_UIO) += uio.o
+obj-$(CONFIG_UIO) += uio.o
+obj-$(CONFIG_UIO_CIF) += uio_cif.o
diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
new file mode 100644
index 0000000..838bae4
--- /dev/null
+++ b/drivers/uio/uio_cif.c
@@ -0,0 +1,156 @@
+/*
+ * UIO Hilscher CIF card driver
+ *
+ * (C) 2007 Hans J. Koch <hjk@linutronix.de>
+ * Original code (C) 2005 Benedikt Spranger <b.spranger@linutronix.de>
+ *
+ * Licensed under GPL version 2 only.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/uio_driver.h>
+
+#include <asm/io.h>
+
+#ifndef PCI_DEVICE_ID_PLX_9030
+#define PCI_DEVICE_ID_PLX_9030 0x9030
+#endif
+
+#define PLX9030_INTCSR 0x4C
+#define INTSCR_INT1_ENABLE 0x01
+#define INTSCR_INT1_STATUS 0x04
+#define INT1_ENABLED_AND_ACTIVE (INTSCR_INT1_ENABLE | INTSCR_INT1_STATUS)
+
+#define PCI_SUBVENDOR_ID_PEP 0x1518
+#define CIF_SUBDEVICE_PROFIBUS 0x430
+#define CIF_SUBDEVICE_DEVICENET 0x432
+
+
+static irqreturn_t hilscher_handler(int irq, struct uio_info *dev_info)
+{
+ void __iomem *plx_intscr = dev_info->mem[0].internal_addr
+ + PLX9030_INTCSR;
+
+ if ((ioread8(plx_intscr) & INT1_ENABLED_AND_ACTIVE)
+ != INT1_ENABLED_AND_ACTIVE)
+ return IRQ_NONE;
+
+ /* Disable interrupt */
+ iowrite8(ioread8(plx_intscr) & ~INTSCR_INT1_ENABLE, plx_intscr);
+ return IRQ_HANDLED;
+}
+
+static int __devinit hilscher_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ struct uio_info *info;
+
+ info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ if (pci_enable_device(dev))
+ goto out_free;
+
+ if (pci_request_regions(dev, "hilscher"))
+ goto out_disable;
+
+ info->mem[0].addr = pci_resource_start(dev, 0);
+ if (!info->mem[0].addr)
+ goto out_release;
+ info->mem[0].internal_addr = ioremap(pci_resource_start(dev, 0),
+ pci_resource_len(dev, 0));
+ if (!info->mem[0].internal_addr)
+ goto out_release;
+
+ info->mem[0].size = pci_resource_len(dev, 0);
+ info->mem[0].memtype = UIO_MEM_PHYS;
+ info->mem[1].addr = pci_resource_start(dev, 2);
+ info->mem[1].size = pci_resource_len(dev, 2);
+ info->mem[1].memtype = UIO_MEM_PHYS;
+ switch (id->subdevice) {
+ case CIF_SUBDEVICE_PROFIBUS:
+ info->name = "CIF_Profibus";
+ break;
+ case CIF_SUBDEVICE_DEVICENET:
+ info->name = "CIF_Devicenet";
+ break;
+ default:
+ info->name = "CIF_???";
+ }
+ info->version = "0.0.1";
+ info->irq = dev->irq;
+ info->irq_flags = IRQF_DISABLED | IRQF_SHARED;
+ info->handler = hilscher_handler;
+
+ if (uio_register_device(&dev->dev, info))
+ goto out_unmap;
+
+ pci_set_drvdata(dev, info);
+
+ return 0;
+out_unmap:
+ iounmap(info->mem[0].internal_addr);
+out_release:
+ pci_release_regions(dev);
+out_disable:
+ pci_disable_device(dev);
+out_free:
+ kfree (info);
+ return -ENODEV;
+}
+
+static void hilscher_pci_remove(struct pci_dev *dev)
+{
+ struct uio_info *info = pci_get_drvdata(dev);
+
+ uio_unregister_device(info);
+ pci_release_regions(dev);
+ pci_disable_device(dev);
+ pci_set_drvdata(dev, NULL);
+ iounmap(info->mem[0].internal_addr);
+
+ kfree (info);
+}
+
+static struct pci_device_id hilscher_pci_ids[] = {
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9030,
+ .subvendor = PCI_SUBVENDOR_ID_PEP,
+ .subdevice = CIF_SUBDEVICE_PROFIBUS,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9030,
+ .subvendor = PCI_SUBVENDOR_ID_PEP,
+ .subdevice = CIF_SUBDEVICE_DEVICENET,
+ },
+ { 0, }
+};
+
+static struct pci_driver hilscher_pci_driver = {
+ .name = "hilscher",
+ .id_table = hilscher_pci_ids,
+ .probe = hilscher_pci_probe,
+ .remove = hilscher_pci_remove,
+};
+
+static int __init hilscher_init_module(void)
+{
+ return pci_register_driver(&hilscher_pci_driver);
+}
+
+static void __exit hilscher_exit_module(void)
+{
+ pci_unregister_driver(&hilscher_pci_driver);
+}
+
+module_init(hilscher_init_module);
+module_exit(hilscher_exit_module);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");
--
1.5.2.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 3/3] UIO: Hilscher CIF card driver
2007-07-18 23:26 ` [PATCH 3/3] UIO: Hilscher CIF card driver Greg Kroah-Hartman
@ 2007-07-19 16:33 ` Jan Engelhardt
2007-07-19 19:28 ` Hans-Jürgen Koch
0 siblings, 1 reply; 32+ messages in thread
From: Jan Engelhardt @ 2007-07-19 16:33 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-kernel, Hans-Jürgen Koch
On Jul 18 2007 16:26, Greg Kroah-Hartman wrote:
>
>http://www.tglx.de/private/hjk/cif-orig-2.6.tar.bz2
>
>WARNING: Don't look at the code for too long, you might become sick :-)
Taking precautions for people? I get a 404...
Jan
--
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 3/3] UIO: Hilscher CIF card driver
2007-07-19 16:33 ` Jan Engelhardt
@ 2007-07-19 19:28 ` Hans-Jürgen Koch
2007-07-19 20:02 ` Jan Engelhardt
0 siblings, 1 reply; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-07-19 19:28 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Greg Kroah-Hartman, linux-kernel
Am Donnerstag 19 Juli 2007 18:33 schrieb Jan Engelhardt:
>
> On Jul 18 2007 16:26, Greg Kroah-Hartman wrote:
> >
> >http://www.tglx.de/private/hjk/cif-orig-2.6.tar.bz2
> >
> >WARNING: Don't look at the code for too long, you might become sick :-)
>
> Taking precautions for people? I get a 404...
Now it's there.
Thanks,
Hans
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 3/3] UIO: Hilscher CIF card driver
2007-07-19 19:28 ` Hans-Jürgen Koch
@ 2007-07-19 20:02 ` Jan Engelhardt
2007-07-19 20:24 ` Hans-Jürgen Koch
0 siblings, 1 reply; 32+ messages in thread
From: Jan Engelhardt @ 2007-07-19 20:02 UTC (permalink / raw)
To: Hans-Jürgen Koch; +Cc: Greg Kroah-Hartman, linux-kernel
[-- Attachment #1: Type: TEXT/PLAIN, Size: 455 bytes --]
On Jul 19 2007 21:28, Hans-Jürgen Koch wrote:
>Am Donnerstag 19 Juli 2007 18:33 schrieb Jan Engelhardt:
>> On Jul 18 2007 16:26, Greg Kroah-Hartman wrote:
>> >
>> >http://www.tglx.de/private/hjk/cif-orig-2.6.tar.bz2
>> >
>> >WARNING: Don't look at the code for too long, you might become sick :-)
>>
>> Taking precautions for people? I get a 404...
>
>Now it's there.
aaaa, my eyes... ("Microsoft" is a good summary of the codingstyle...)
:)
Jan
--
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 3/3] UIO: Hilscher CIF card driver
2007-07-19 20:02 ` Jan Engelhardt
@ 2007-07-19 20:24 ` Hans-Jürgen Koch
0 siblings, 0 replies; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-07-19 20:24 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Greg Kroah-Hartman, linux-kernel
Am Donnerstag 19 Juli 2007 22:02 schrieb Jan Engelhardt:
>
> On Jul 19 2007 21:28, Hans-Jürgen Koch wrote:
> >Am Donnerstag 19 Juli 2007 18:33 schrieb Jan Engelhardt:
> >> On Jul 18 2007 16:26, Greg Kroah-Hartman wrote:
> >> >
> >> >http://www.tglx.de/private/hjk/cif-orig-2.6.tar.bz2
> >> >
> >> >WARNING: Don't look at the code for too long, you might become sick :-)
> >>
> >> Taking precautions for people? I get a 404...
> >
> >Now it's there.
>
> aaaa, my eyes... ("Microsoft" is a good summary of the codingstyle...)
It's not just coding style, it's also concept. This was written with
the only goal to get a card working at one particular time. What happens
in future is not important. Would you like to port this driver to 2.6.22?
Would you like to post it on lkml, signed-off by you?
The concept is bad because the authors of that driver never tried to
find out how a driver should look like and what has to be done to get
it into mainline. Allright, with such a big driver for a relatively
unknown card(?) it's not easy to include that in mainline. That's
why we now have UIO... It greatly simplifies tasks like that.
I really hope that UIO will soon be used for industrial cards like
this one, and that we can fill drivers/uio/ with lots of small
kernel modules. And yes, these programmers in industry who wrote
drivers like the above, they will still be doing what they want and
what they're able to. But, hopefully, they'll now do it in userspace.
Thanks,
Hans
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-07-18 23:26 ` [PATCH 2/3] UIO: Documentation Greg Kroah-Hartman
2007-07-18 23:26 ` [PATCH 3/3] UIO: Hilscher CIF card driver Greg Kroah-Hartman
@ 2007-08-08 21:36 ` Jesper Juhl
2007-08-08 22:12 ` Valdis.Kletnieks
2007-08-09 7:41 ` Hans-Jürgen Koch
1 sibling, 2 replies; 32+ messages in thread
From: Jesper Juhl @ 2007-08-08 21:36 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-kernel, Hans J. Koch
On 19/07/2007, Greg Kroah-Hartman <gregkh@suse.de> wrote:
> From: Hans J. Koch <hjk@linutronix.de>
>
> Documentation for the UIO interface
>
...
> +<para>If you use UIO for your card's driver, here's what you get:</para>
> +
...
> +<listitem>
> + <para>if you need to keep some parts of your driver closed source,
> + you can do so without violating the GPL license on the kernel.</para>
> +</listitem>
> +</itemizedlist>
> +
...
Do we really want this?
In my oppinion we run the risk here of encouraging behaviour akin to
what NVidia is doing - release a small kernel "glue" module and then
keep the driver proper in a binary blob (in userspace, but still a
binary blob).
If the company goes out of business and take their driver source with
them then users are left with a useless, un-debugable, un-maintainable
binary blob.
Don't we instead want to encourage/pressure people to release specs
and/or source code for their hardware/drivers so open, modifiable
drivers can be written?
This opens the door for people to start writing closed drivers. In the
long run that seems to me like a bad deal for our users.
--
Jesper Juhl <jesper.juhl@gmail.com>
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-08 21:36 ` [PATCH 2/3] UIO: Documentation Jesper Juhl
@ 2007-08-08 22:12 ` Valdis.Kletnieks
2007-08-08 23:03 ` Jesper Juhl
` (2 more replies)
2007-08-09 7:41 ` Hans-Jürgen Koch
1 sibling, 3 replies; 32+ messages in thread
From: Valdis.Kletnieks @ 2007-08-08 22:12 UTC (permalink / raw)
To: Jesper Juhl; +Cc: Greg Kroah-Hartman, linux-kernel, Hans J. Koch
[-- Attachment #1: Type: text/plain, Size: 1173 bytes --]
On Wed, 08 Aug 2007 23:36:00 +0200, Jesper Juhl said:
> Do we really want this?
>
> In my oppinion we run the risk here of encouraging behaviour akin to
> what NVidia is doing - release a small kernel "glue" module and then
> keep the driver proper in a binary blob (in userspace, but still a
> binary blob).
> If the company goes out of business and take their driver source with
> them then users are left with a useless, un-debugable, un-maintainable
> binary blob.
> Don't we instead want to encourage/pressure people to release specs
> and/or source code for their hardware/drivers so open, modifiable
> drivers can be written?
>
> This opens the door for people to start writing closed drivers. In the
> long run that seems to me like a bad deal for our users.
On the other hand, given that we've always said that closed-source stuff in
userspace is OK, the only way to not let *that* horse out of the barn is to
not merge UIO at all.
If you have UIO in the kernel talking to stuff in userspace, you're going to
have to deal with closed-source stuff at the userspace end of the pipe.
Unless somebody can come up with some great feat of sophistry to avoid that?
[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-08 22:12 ` Valdis.Kletnieks
@ 2007-08-08 23:03 ` Jesper Juhl
2007-08-09 7:19 ` Greg KH
2007-08-08 23:40 ` Alan Cox
2007-08-09 13:02 ` Hans-Jürgen Koch
2 siblings, 1 reply; 32+ messages in thread
From: Jesper Juhl @ 2007-08-08 23:03 UTC (permalink / raw)
To: Valdis.Kletnieks@vt.edu; +Cc: Greg Kroah-Hartman, linux-kernel, Hans J. Koch
On 09/08/2007, Valdis.Kletnieks@vt.edu <Valdis.Kletnieks@vt.edu> wrote:
> On Wed, 08 Aug 2007 23:36:00 +0200, Jesper Juhl said:
>
> > Do we really want this?
> >
> > In my oppinion we run the risk here of encouraging behaviour akin to
> > what NVidia is doing - release a small kernel "glue" module and then
> > keep the driver proper in a binary blob (in userspace, but still a
> > binary blob).
> > If the company goes out of business and take their driver source with
> > them then users are left with a useless, un-debugable, un-maintainable
> > binary blob.
> > Don't we instead want to encourage/pressure people to release specs
> > and/or source code for their hardware/drivers so open, modifiable
> > drivers can be written?
> >
> > This opens the door for people to start writing closed drivers. In the
> > long run that seems to me like a bad deal for our users.
>
> On the other hand, given that we've always said that closed-source stuff in
> userspace is OK, the only way to not let *that* horse out of the barn is to
> not merge UIO at all.
>
Exactely.
> If you have UIO in the kernel talking to stuff in userspace, you're going to
> have to deal with closed-source stuff at the userspace end of the pipe.
>
Naturally.
I just wanted to get people to think about whether or not this is
something that we are willing to accept for device drivers - I guess
it is since UIO is already merged - I just think it's a potential step
back in terms of encouraging open source drivers for Linux, that's
all.
> Unless somebody can come up with some great feat of sophistry to avoid that?
>
I think the only way to avoid it is to not provide something like UIO.
--
Jesper Juhl <jesper.juhl@gmail.com>
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-08 22:12 ` Valdis.Kletnieks
2007-08-08 23:03 ` Jesper Juhl
@ 2007-08-08 23:40 ` Alan Cox
2007-08-09 12:29 ` Hans-Jürgen Koch
2007-08-09 13:02 ` Hans-Jürgen Koch
2 siblings, 1 reply; 32+ messages in thread
From: Alan Cox @ 2007-08-08 23:40 UTC (permalink / raw)
To: Valdis.Kletnieks
Cc: Jesper Juhl, Greg Kroah-Hartman, linux-kernel, Hans J. Koch
> On the other hand, given that we've always said that closed-source stuff in
> userspace is OK, the only way to not let *that* horse out of the barn is to
> not merge UIO at all.
It really makes no difference whether it is merged or not. The test is
"derivative work" and not 'linking'.
A user space driver that is unusuable without a specific GPL kernel chunk
is quite likely to be a derived work of the GPL kernel module so the
documentation is giving poor advice however
Alan
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-08 23:03 ` Jesper Juhl
@ 2007-08-09 7:19 ` Greg KH
2007-08-09 16:50 ` Jesper Juhl
0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-08-09 7:19 UTC (permalink / raw)
To: Jesper Juhl; +Cc: Valdis.Kletnieks@vt.edu, linux-kernel, Hans J. Koch
On Thu, Aug 09, 2007 at 01:03:39AM +0200, Jesper Juhl wrote:
> >
> I think the only way to avoid it is to not provide something like UIO.
Problem is, things like UIO provide a real solution for a wide range of
different types of devices. Like the one provided in the kernel right
now, and a bunch of others that I am currently discussing with different
manufacturers (think high-speed DSPs that just want to give userspace
direct access to the card and have the kernel get the hell out of the
way so data can be read and processed as fast as possible.)
And also realize that some types of systems have been doing this very
same kind of kernel/userspace interface for many years, namely X :)
As for the legalities of using closed source userspace code with the UIO
interface, consult a lawyer if you have questions, and be sure to bring
up Alan's comments about derivative works :)
thanks,
greg k-h
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-08 21:36 ` [PATCH 2/3] UIO: Documentation Jesper Juhl
2007-08-08 22:12 ` Valdis.Kletnieks
@ 2007-08-09 7:41 ` Hans-Jürgen Koch
1 sibling, 0 replies; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-08-09 7:41 UTC (permalink / raw)
To: Jesper Juhl; +Cc: Greg Kroah-Hartman, linux-kernel
Am Mittwoch 08 August 2007 23:36 schrieb Jesper Juhl:
> On 19/07/2007, Greg Kroah-Hartman <gregkh@suse.de> wrote:
> > From: Hans J. Koch <hjk@linutronix.de>
> >
> > Documentation for the UIO interface
> >
> ...
> > +<para>If you use UIO for your card's driver, here's what you get:</para>
> > +
> ...
> > +<listitem>
> > + <para>if you need to keep some parts of your driver closed source,
> > + you can do so without violating the GPL license on the kernel.</para>
> > +</listitem>
> > +</itemizedlist>
> > +
> ...
>
> Do we really want this?
Yes. Please remember that UIO is for industrial I/O cards, not mainstream
PC hardware. You'll never see an UIO driver for an USB Scanner or a TV card.
Just try to write one. You will see that an UIO kernel driver for a device
that has to interact with lots of kernel subsystems will become almost as
big as a normal kernel driver. Not much left for user space.
Typical industrial IO cards are simple PCI cards with loads of
functions that don't fit in any kernel subsystem. A pure kernel driver
is usually _big_ and ugly and introduces 50 new ioctls and will never
make it into mainline.
>
> In my oppinion we run the risk here of encouraging behaviour akin to
> what NVidia is doing - release a small kernel "glue" module and then
> keep the driver proper in a binary blob (in userspace, but still a
> binary blob).
If a company wants to do that, they'll do it, with or without UIO.
> If the company goes out of business and take their driver source with
> them then users are left with a useless, un-debugable, un-maintainable
> binary blob.
> Don't we instead want to encourage/pressure people to release specs
> and/or source code for their hardware/drivers so open, modifiable
> drivers can be written?
No. Please note that there _are_ reasons to keep code closed. I agree
with you when it comes to mass market hardware like graphics cards.
But in embedded systems with custom hardware for military or other
critical applications, you can't force a manufacturer to show you
his concepts. Usually, he's not allowed to.
UIO offers a legal way for these people to implement their driver.
Without it, they'll violate the GPL or don't use Linux at all.
>
> This opens the door for people to start writing closed drivers.
No. UIO doesn't change anything. You were always free to choose
your license for userspace stuff.
What we want to achieve is that IO cards, for which you get a
driver with 5000 lines of unreadable code for 2.6.12 from the
manufacturer at the moment, can get a sensible driver with
mainline support. That's all. We will see if that encourages
manufacturers to make drivers closed source.
Thanks,
Hans
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-08 23:40 ` Alan Cox
@ 2007-08-09 12:29 ` Hans-Jürgen Koch
2007-08-09 14:09 ` Alan Cox
0 siblings, 1 reply; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-08-09 12:29 UTC (permalink / raw)
To: Alan Cox; +Cc: Valdis.Kletnieks, Jesper Juhl, Greg Kroah-Hartman, linux-kernel
Am Donnerstag 09 August 2007 01:40 schrieb Alan Cox:
> > On the other hand, given that we've always said that closed-source stuff in
> > userspace is OK, the only way to not let *that* horse out of the barn is to
> > not merge UIO at all.
>
> It really makes no difference whether it is merged or not. The test is
> "derivative work" and not 'linking'.
>
> A user space driver that is unusuable without a specific GPL kernel chunk
> is quite likely to be a derived work of the GPL kernel module
I disagree. UIO is a documented kernel<->userspace interface, like sysfs
or proc. Using your argument, we would also have to say that a userspace
software that is unusable without sysfs is a derived work of the kernel.
But IANAL, tell me if I missed an important point.
> so the
> documentation is giving poor advice however
I guess you mean this sentence:
"if you need to keep some parts of your driver closed source, you can do so
without violating the GPL license on the kernel."
What would you write instead?
Thanks,
Hans
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-08 22:12 ` Valdis.Kletnieks
2007-08-08 23:03 ` Jesper Juhl
2007-08-08 23:40 ` Alan Cox
@ 2007-08-09 13:02 ` Hans-Jürgen Koch
2007-08-09 14:12 ` Alan Cox
2 siblings, 1 reply; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-08-09 13:02 UTC (permalink / raw)
To: Valdis.Kletnieks; +Cc: Jesper Juhl, Greg Kroah-Hartman, linux-kernel
Am Donnerstag 09 August 2007 00:12 schrieb Valdis.Kletnieks@vt.edu:
>
> If you have UIO in the kernel talking to stuff in userspace, you're going to
> have to deal with closed-source stuff at the userspace end of the pipe.
That's no UIO invention. Userspace software that uses kernel interfaces like
syscall, device files, sysfs, and so on, is by definition _not_ a derived work
of the kernel and can be distributed under any license.
If you ask a manufacturer of an industrial IO card for a Linux driver today,
you either get nothing at all, or you get an unmaintainable and buggy piece
of crap for an ancient kernel. The alternative is a binary kernel module that
really violates the GPL.
With UIO, you have a kernel module that is so small, that even somebody who
hasn't got the hardware can easily review it and tell if the code is OK or not.
It is easy to maintain and doesn't reveal any secrets about the hardware.
The kernel remains clean, which further improves maintenance and debugging.
People frequently use /dev/mem to access hardware from userspace, that's
nothing new. UIO really improves this, making it safer and more user friendly.
And it prevents people from inventing dirty tricks to do some sort of
interrupt handling in user space (which is simply not possible).
Furthermore, drivers for this kind of hardware are written by programmers in
industry, who often don't have kernel experience, reviews, time for tests,
and so on. I really prefer it if they do their stuff in userspace. And they
prefer it, too, because they can use all the nice tools and libraries they're
used to.
There might be a small possibility that a manufacturer now writes a closed
source UIO driver, and would have written an open source kernel driver if
UIO didn't exist. But, honestly, I doubt that we'll find many such cases.
Thanks,
Hans
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-09 12:29 ` Hans-Jürgen Koch
@ 2007-08-09 14:09 ` Alan Cox
0 siblings, 0 replies; 32+ messages in thread
From: Alan Cox @ 2007-08-09 14:09 UTC (permalink / raw)
To: Hans-Jürgen Koch
Cc: Valdis.Kletnieks, Jesper Juhl, Greg Kroah-Hartman, linux-kernel
O> I disagree. UIO is a documented kernel<->userspace interface, like sysfs
> or proc. Using your argument, we would also have to say that a userspace
> software that is unusable without sysfs is a derived work of the kernel.
> But IANAL, tell me if I missed an important point.
It depends how closely the bits are tied. As far as I can ascertain there
is no simple yes/no answer and whether you can do so depends a great deal
upon how tightly bound the two are (consider the difference between the
intel ipw daemon which is integrated very tightly into the old ipw3945
driver and a script monitoring CPU temperature via a sysfs file)
> > so the
> > documentation is giving poor advice however
>
> I guess you mean this sentence:
>
> "if you need to keep some parts of your driver closed source, you can do so
> without violating the GPL license on the kernel."
>
> What would you write instead?
I would simply remove the statement. Leave it to the lawyers.
Alan
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-09 13:02 ` Hans-Jürgen Koch
@ 2007-08-09 14:12 ` Alan Cox
2007-08-09 15:23 ` Hans-Jürgen Koch
0 siblings, 1 reply; 32+ messages in thread
From: Alan Cox @ 2007-08-09 14:12 UTC (permalink / raw)
To: Hans-Jürgen Koch
Cc: Valdis.Kletnieks, Jesper Juhl, Greg Kroah-Hartman, linux-kernel
> That's no UIO invention. Userspace software that uses kernel interfaces like
> syscall, device files, sysfs, and so on, is by definition _not_ a derived work
> of the kernel and can be distributed under any license.
This I believe incorrect. Please cite caselaw if you know better.
> With UIO, you have a kernel module that is so small, that even somebody who
> hasn't got the hardware can easily review it and tell if the code is OK or not.
> It is easy to maintain and doesn't reveal any secrets about the hardware.
False
Because you have no idea if the interface is correct or the userspace is
doing stuff like triggering DMA to arbitary addresses via the interface
or mmap functions. If it does so then even if its root only you've blown
your security model.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-09 14:12 ` Alan Cox
@ 2007-08-09 15:23 ` Hans-Jürgen Koch
0 siblings, 0 replies; 32+ messages in thread
From: Hans-Jürgen Koch @ 2007-08-09 15:23 UTC (permalink / raw)
To: Alan Cox; +Cc: Valdis.Kletnieks, Jesper Juhl, Greg Kroah-Hartman, linux-kernel
Am Donnerstag 09 August 2007 16:12 schrieb Alan Cox:
> > That's no UIO invention. Userspace software that uses kernel interfaces like
> > syscall, device files, sysfs, and so on, is by definition _not_ a derived work
> > of the kernel and can be distributed under any license.
>
> This I believe incorrect. Please cite caselaw if you know better.
What about the statement at the top of COPYING in the top level kernel source
directory?
I know, you've got examples in mind where a kernel module and a userspace
program are dependent on each other and none of them can be used without the
other. Of course, we've got such a case for a UIO kernel module and userspace
driver. But if the degree of dependency between kernel and userspace can
constitute a different legal situation, then we have a _very_ large legal
grayzone.
>
> > With UIO, you have a kernel module that is so small, that even somebody who
> > hasn't got the hardware can easily review it and tell if the code is OK or not.
> > It is easy to maintain and doesn't reveal any secrets about the hardware.
>
> False
>
> Because you have no idea if the interface is correct or the userspace is
> doing stuff like triggering DMA to arbitary addresses via the interface
> or mmap functions. If it does so then even if its root only you've blown
> your security model.
OK, I agree. But in comparison to using /dev/mem for these tasks, I still
consider UIO an improvement.
Thanks,
Hans
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/3] UIO: Documentation
2007-08-09 7:19 ` Greg KH
@ 2007-08-09 16:50 ` Jesper Juhl
0 siblings, 0 replies; 32+ messages in thread
From: Jesper Juhl @ 2007-08-09 16:50 UTC (permalink / raw)
To: Greg KH; +Cc: Valdis.Kletnieks@vt.edu, linux-kernel, Hans J. Koch
On 09/08/07, Greg KH <gregkh@suse.de> wrote:
> On Thu, Aug 09, 2007 at 01:03:39AM +0200, Jesper Juhl wrote:
> > >
> > I think the only way to avoid it is to not provide something like UIO.
>
> Problem is, things like UIO provide a real solution for a wide range of
> different types of devices. Like the one provided in the kernel right
> now, and a bunch of others that I am currently discussing with different
> manufacturers (think high-speed DSPs that just want to give userspace
> direct access to the card and have the kernel get the hell out of the
> way so data can be read and processed as fast as possible.)
>
Please understand that I'm not saying UIO isn't potentially useful,
nor am I saying that it won't potentially give us support for a bunch
of new hardware. All I'm trying to say is that, to me at least, it is
trying to buy us those new drivers in a way that encourages creating
those drivers as closed source software- *that* is all I'm having
issues with - that is what I think is a step backwards - something
that may give us a short-term gain but will make us lose out
long-term.
> And also realize that some types of systems have been doing this very
> same kind of kernel/userspace interface for many years, namely X :)
>
That something has been going on for years doesn't in itself make it a
good argument for that model. ;-)
> As for the legalities of using closed source userspace code with the UIO
> interface, consult a lawyer if you have questions, and be sure to bring
> up Alan's comments about derivative works :)
>
I'm not arguing against closed source applications in userspace. That
is of course OK. What I'm arguing about is a kernel interface that
encourages closed source (userspace) *drivers*.
--
Jesper Juhl <jesper.juhl@gmail.com>
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2007-08-09 16:50 UTC | newest]
Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-18 23:23 [GIT PATCH] UIO patches for 2.6.22 Greg KH
2007-07-18 23:26 ` [PATCH 1/3] UIO: Add the User IO core code Greg Kroah-Hartman
2007-07-18 23:26 ` [PATCH 2/3] UIO: Documentation Greg Kroah-Hartman
2007-07-18 23:26 ` [PATCH 3/3] UIO: Hilscher CIF card driver Greg Kroah-Hartman
2007-07-19 16:33 ` Jan Engelhardt
2007-07-19 19:28 ` Hans-Jürgen Koch
2007-07-19 20:02 ` Jan Engelhardt
2007-07-19 20:24 ` Hans-Jürgen Koch
2007-08-08 21:36 ` [PATCH 2/3] UIO: Documentation Jesper Juhl
2007-08-08 22:12 ` Valdis.Kletnieks
2007-08-08 23:03 ` Jesper Juhl
2007-08-09 7:19 ` Greg KH
2007-08-09 16:50 ` Jesper Juhl
2007-08-08 23:40 ` Alan Cox
2007-08-09 12:29 ` Hans-Jürgen Koch
2007-08-09 14:09 ` Alan Cox
2007-08-09 13:02 ` Hans-Jürgen Koch
2007-08-09 14:12 ` Alan Cox
2007-08-09 15:23 ` Hans-Jürgen Koch
2007-08-09 7:41 ` Hans-Jürgen Koch
-- strict thread matches above, loose matches on Subject: below --
2007-05-08 14:04 [GIT PATCH] UIO patches for 2.6.21 Greg KH
2007-05-08 14:08 ` [PATCH 1/3] UIO: Add the User IO core code Greg Kroah-Hartman
2007-05-08 14:08 ` [PATCH 2/3] UIO: Documentation Greg Kroah-Hartman
2007-04-27 22:49 [GIT PATCH] UIO patches for 2.6.21 Greg KH
2007-04-27 22:50 ` [PATCH 1/3] UIO: Add the User IO core code Greg Kroah-Hartman
2007-04-27 22:50 ` [PATCH 2/3] UIO: Documentation Greg Kroah-Hartman
2007-05-01 23:42 ` Randy Dunlap
2007-05-02 8:41 ` Hans-Jürgen Koch
2007-05-02 20:52 ` Randy Dunlap
2007-05-02 22:00 ` Hans-Jürgen Koch
2007-05-02 23:37 ` Randy Dunlap
2007-05-03 5:37 ` Greg KH
2007-05-03 6:39 ` Hans-Jürgen Koch
2007-05-04 9:37 ` Hans-Jürgen Koch
2007-05-07 17:46 ` Randy Dunlap
2007-05-07 20:01 ` Hans-Jürgen Koch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).