Merge branch 'master' of /home/cbou/linux-2.6
[pandora-kernel.git] / Documentation / DocBook / uio-howto.tmpl
index e3bb29a..df87d1b 100644 (file)
     </affiliation>
 </author>
 
+<copyright>
+       <year>2006-2008</year>
+       <holder>Hans-Jürgen Koch.</holder>
+</copyright>
+
+<legalnotice>
+<para>
+This documentation is Free Software licensed under the terms of the
+GPL version 2.
+</para>
+</legalnotice>
+
 <pubdate>2006-12-11</pubdate>
 
 <abstract>
 </abstract>
 
 <revhistory>
+       <revision>
+       <revnumber>0.5</revnumber>
+       <date>2008-05-22</date>
+       <authorinitials>hjk</authorinitials>
+       <revremark>Added description of write() function.</revremark>
+       </revision>
+       <revision>
+       <revnumber>0.4</revnumber>
+       <date>2007-11-26</date>
+       <authorinitials>hjk</authorinitials>
+       <revremark>Removed section about uio_dummy.</revremark>
+       </revision>
        <revision>
        <revnumber>0.3</revnumber>
        <date>2007-04-29</date>
 </bookinfo>
 
 <chapter id="aboutthisdoc">
-<?dbhtml filename="about.html"?>
+<?dbhtml filename="aboutthis.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>
@@ -94,6 +107,26 @@ interested in translating it, please email me
        user space. This simplifies development and reduces the risk of
        serious bugs within a kernel module.
        </para>
+       <para>
+       Please note that UIO is not an universal driver interface. Devices
+       that are already handled well by other kernel subsystems (like
+       networking or serial or USB) are no candidates for an UIO driver.
+       Hardware that is ideally suited for an UIO driver fulfills all of
+       the following:
+       </para>
+<itemizedlist>
+<listitem>
+       <para>The device has memory that can be mapped. The device can be
+       controlled completely by writing to this memory.</para>
+</listitem>
+<listitem>
+       <para>The device usually generates interrupts.</para>
+</listitem>
+<listitem>
+       <para>The device does not fit into one of the standard kernel
+       subsystems.</para>
+</listitem>
+</itemizedlist>
 </sect1>
 
 <sect1 id="thanks">
@@ -133,10 +166,6 @@ interested in translating it, please email me
        <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">
@@ -167,6 +196,30 @@ interested in translating it, please email me
        represents the total interrupt count. You can use this number
        to figure out if you missed some interrupts.
        </para>
+       <para>
+       For some hardware that has more than one interrupt source internally,
+       but not separate IRQ mask and status registers, there might be
+       situations where userspace cannot determine what the interrupt source
+       was if the kernel handler disables them by writing to the chip's IRQ
+       register. In such a case, the kernel has to disable the IRQ completely
+       to leave the chip's register untouched. Now the userspace part can
+       determine the cause of the interrupt, but it cannot re-enable
+       interrupts. Another cornercase is chips where re-enabling interrupts
+       is a read-modify-write operation to a combined IRQ status/acknowledge
+       register. This would be racy if a new interrupt occurred
+       simultaneously.
+       </para>
+       <para>
+       To address these problems, UIO also implements a write() function. It
+       is normally not used and can be ignored for hardware that has only a
+       single interrupt source or has separate IRQ mask and status registers.
+       If you need it, however, a write to <filename>/dev/uioX</filename>
+       will call the <function>irqcontrol()</function> function implemented
+       by the driver. You have to write a 32-bit value that is usually either
+       0 or 1 to disable or enable interrupts. If a driver does not implement
+       <function>irqcontrol()</function>, <function>write()</function> will
+       return with <varname>-ENOSYS</varname>.
+       </para>
 
        <para>
        To handle interrupts properly, your custom kernel module can
@@ -178,8 +231,9 @@ interested in translating it, please email me
        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.
+       This interrupt simulation is done by calling
+       <function>uio_event_notify()</function>
+       from the timer's event handler.
        </para>
 
        <para>
@@ -267,63 +321,11 @@ offset = N * getpagesize();
 </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
+       Please have a look at <filename>uio_cif.c</filename> as an
        example. The following paragraphs explain the different
        sections of this file.
        </para>
@@ -358,9 +360,8 @@ See the description below for details.
 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_CUSTOM</varname>.
+If you had no interrupt at all, you could set
 <varname>irq</varname> to <varname>UIO_IRQ_NONE</varname>, though this
 rarely makes sense.
 </para></listitem>
@@ -392,6 +393,14 @@ device is actually used.
 <function>open()</function>, you will probably also want a custom
 <function>release()</function> function.
 </para></listitem>
+
+<listitem><para>
+<varname>int (*irqcontrol)(struct uio_info *info, s32 irq_on)
+</varname>: Optional. If you need to be able to enable or disable
+interrupts from userspace by writing to <filename>/dev/uioX</filename>,
+you can implement this function. The parameter <varname>irq_on</varname>
+will be 0 to disable interrupts and 1 to enable them.
+</para></listitem>
 </itemizedlist>
 
 <para>