Sophie

Sophie

distrib > CentOS > 6 > i386 > by-pkgid > 2c51d8eb79f8810ada971ee8c30ce1e5 > files > 3750

kernel-doc-2.6.32-71.14.1.el6.noarch.rpm

<?xml version="1.0" encoding="ANSI_X3.4-1968" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968" /><title>Chapter&#160;3.&#160;Writing your own kernel module</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2" /><link rel="home" href="index.html" title="The Userspace I/O HOWTO" /><link rel="up" href="index.html" title="The Userspace I/O HOWTO" /><link rel="prev" href="about.html" title="Chapter&#160;2.&#160;About UIO" /><link rel="next" href="ch03s02.html" title="Adding an interrupt handler" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter&#160;3.&#160;Writing your own kernel module</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="about.html">Prev</a>&#160;</td><th width="60%" align="center">&#160;</th><td width="20%" align="right">&#160;<a accesskey="n" href="ch03s02.html">Next</a></td></tr></table><hr /></div><div class="chapter" title="Chapter&#160;3.&#160;Writing your own kernel module"><div class="titlepage"><div><div><h2 class="title"><a id="custom_kernel_module"></a>Chapter&#160;3.&#160;Writing your own kernel module</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="custom_kernel_module.html#uio_info">struct uio_info</a></span></dt><dt><span class="sect1"><a href="ch03s02.html">Adding an interrupt handler</a></span></dt><dt><span class="sect1"><a href="ch03s03.html">Using uio_pdrv for platform devices</a></span></dt><dt><span class="sect1"><a href="ch03s04.html">Using uio_pdrv_genirq for platform devices</a></span></dt></dl></div><p>
	Please have a look at <code class="filename">uio_cif.c</code> as an
	example. The following paragraphs explain the different
	sections of this file.
	</p><div class="sect1" title="struct uio_info"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="uio_info"></a>struct uio_info</h2></div></div></div><p>
	This structure tells the framework the details of your driver,
	Some of the members are required, others are optional.
	</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>
<code class="varname">const char *name</code>: Required. The name of your driver as
it will appear in sysfs. I recommend using the name of your module for this.
</p></li><li class="listitem"><p>
<code class="varname">const char *version</code>: Required. This string appears in
<code class="filename">/sys/class/uio/uioX/version</code>.
</p></li><li class="listitem"><p>
<code class="varname">struct uio_mem mem[ MAX_UIO_MAPS ]</code>: Required if you
have memory that can be mapped with <code class="function">mmap()</code>. For each
mapping you need to fill one of the <code class="varname">uio_mem</code> structures.
See the description below for details.
</p></li><li class="listitem"><p>
<code class="varname">struct uio_port port[ MAX_UIO_PORTS_REGIONS ]</code>: Required
if you want to pass information about ioports to userspace. For each port
region you need to fill one of the <code class="varname">uio_port</code> structures.
See the description below for details.
</p></li><li class="listitem"><p>
<code class="varname">long irq</code>: 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
<code class="varname">irq</code> to <code class="varname">UIO_IRQ_CUSTOM</code>.
If you had no interrupt at all, you could set
<code class="varname">irq</code> to <code class="varname">UIO_IRQ_NONE</code>, though this
rarely makes sense.
</p></li><li class="listitem"><p>
<code class="varname">unsigned long irq_flags</code>: Required if you've set
<code class="varname">irq</code> to a hardware interrupt number. The flags given
here will be used in the call to <code class="function">request_irq()</code>.
</p></li><li class="listitem"><p>
<code class="varname">int (*mmap)(struct uio_info *info, struct vm_area_struct
*vma)</code>: Optional. If you need a special
<code class="function">mmap()</code> function, you can set it here. If this
pointer is not NULL, your <code class="function">mmap()</code> will be called
instead of the built-in one.
</p></li><li class="listitem"><p>
<code class="varname">int (*open)(struct uio_info *info, struct inode *inode)
</code>: Optional. You might want to have your own
<code class="function">open()</code>, e.g. to enable interrupts only when your
device is actually used.
</p></li><li class="listitem"><p>
<code class="varname">int (*release)(struct uio_info *info, struct inode *inode)
</code>: Optional. If you define your own
<code class="function">open()</code>, you will probably also want a custom
<code class="function">release()</code> function.
</p></li><li class="listitem"><p>
<code class="varname">int (*irqcontrol)(struct uio_info *info, s32 irq_on)
</code>: Optional. If you need to be able to enable or disable
interrupts from userspace by writing to <code class="filename">/dev/uioX</code>,
you can implement this function. The parameter <code class="varname">irq_on</code>
will be 0 to disable interrupts and 1 to enable them.
</p></li></ul></div><p>
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
<code class="varname">struct uio_mem</code> in the <code class="varname">mem[]</code> array.
Here's a description of the fields of <code class="varname">struct uio_mem</code>:
</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>
<code class="varname">int memtype</code>: Required if the mapping is used. Set this to
<code class="varname">UIO_MEM_PHYS</code> if you you have physical memory on your
card to be mapped. Use <code class="varname">UIO_MEM_LOGICAL</code> for logical
memory (e.g. allocated with <code class="function">kmalloc()</code>). There's also
<code class="varname">UIO_MEM_VIRTUAL</code> for virtual memory.
</p></li><li class="listitem"><p>
<code class="varname">unsigned long addr</code>: Required if the mapping is used.
Fill in the address of your memory block. This address is the one that
appears in sysfs.
</p></li><li class="listitem"><p>
<code class="varname">unsigned long size</code>: Fill in the size of the
memory block that <code class="varname">addr</code> points to. If <code class="varname">size</code>
is zero, the mapping is considered unused. Note that you
<span class="emphasis"><em>must</em></span> initialize <code class="varname">size</code> with zero for
all unused mappings.
</p></li><li class="listitem"><p>
<code class="varname">void *internal_addr</code>: If you have to access this memory
region from within your kernel module, you will want to map it internally by
using something like <code class="function">ioremap()</code>. Addresses
returned by this function cannot be mapped to user space, so you must not
store it in <code class="varname">addr</code>. Use <code class="varname">internal_addr</code>
instead to remember such an address.
</p></li></ul></div><p>
Please do not touch the <code class="varname">kobj</code> element of
<code class="varname">struct uio_mem</code>! It is used by the UIO framework
to set up sysfs files for this mapping. Simply leave it alone.
</p><p>
Sometimes, your device can have one or more port regions which can not be
mapped to userspace. But if there are other possibilities for userspace to
access these ports, it makes sense to make information about the ports
available in sysfs. For each region, you have to set up a
<code class="varname">struct uio_port</code> in the <code class="varname">port[]</code> array.
Here's a description of the fields of <code class="varname">struct uio_port</code>:
</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>
<code class="varname">char *porttype</code>: Required. Set this to one of the predefined
constants. Use <code class="varname">UIO_PORT_X86</code> for the ioports found in x86
architectures.
</p></li><li class="listitem"><p>
<code class="varname">unsigned long start</code>: Required if the port region is used.
Fill in the number of the first port of this region.
</p></li><li class="listitem"><p>
<code class="varname">unsigned long size</code>: Fill in the number of ports in this
region. If <code class="varname">size</code> is zero, the region is considered unused.
Note that you <span class="emphasis"><em>must</em></span> initialize <code class="varname">size</code>
with zero for all unused regions.
</p></li></ul></div><p>
Please do not touch the <code class="varname">portio</code> element of
<code class="varname">struct uio_port</code>! It is used internally by the UIO
framework to set up sysfs files for this region. Simply leave it alone.
</p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="about.html">Prev</a>&#160;</td><td width="20%" align="center">&#160;</td><td width="40%" align="right">&#160;<a accesskey="n" href="ch03s02.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter&#160;2.&#160;About UIO&#160;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&#160;Adding an interrupt handler</td></tr></table></div></body></html>