<?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 3. 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 2. 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 3. Writing your own kernel module</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="about.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ch03s02.html">Next</a></td></tr></table><hr /></div><div class="chapter" title="Chapter 3. Writing your own kernel module"><div class="titlepage"><div><div><h2 class="title"><a id="custom_kernel_module"></a>Chapter 3. 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> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="ch03s02.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 2. About UIO </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Adding an interrupt handler</td></tr></table></div></body></html>