1<html><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968"><title>Chapter 2. About UIO</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><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="feedback.html" title="Feedback"><link rel="next" href="custom_kernel_module.html" title="Chapter 3. Writing your own kernel module"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 2. About UIO</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="feedback.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="custom_kernel_module.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="about"></a>Chapter 2. About UIO</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="sect1"><a href="about.html#how_uio_works">How UIO works</a></span></dt></dl></div><p>If you use UIO for your card's driver, here's what you get:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>only one small kernel module to write and maintain.</p></li><li class="listitem"><p>develop the main part of your driver in user space, 2 with all the tools and libraries you're used to.</p></li><li class="listitem"><p>bugs in your driver won't crash the kernel.</p></li><li class="listitem"><p>updates of your driver can take place without recompiling 3 the kernel.</p></li></ul></div><div class="sect1"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="how_uio_works"></a>How UIO works</h2></div></div></div><p> 4 Each UIO device is accessed through a device file and several 5 sysfs attribute files. The device file will be called 6 <code class="filename">/dev/uio0</code> for the first device, and 7 <code class="filename">/dev/uio1</code>, <code class="filename">/dev/uio2</code> 8 and so on for subsequent devices. 9 </p><p><code class="filename">/dev/uioX</code> is used to access the 10 address space of the card. Just use 11 <code class="function">mmap()</code> to access registers or RAM 12 locations of your card. 13 </p><p> 14 Interrupts are handled by reading from 15 <code class="filename">/dev/uioX</code>. A blocking 16 <code class="function">read()</code> from 17 <code class="filename">/dev/uioX</code> will return as soon as an 18 interrupt occurs. You can also use 19 <code class="function">select()</code> on 20 <code class="filename">/dev/uioX</code> to wait for an interrupt. The 21 integer value read from <code class="filename">/dev/uioX</code> 22 represents the total interrupt count. You can use this number 23 to figure out if you missed some interrupts. 24 </p><p> 25 For some hardware that has more than one interrupt source internally, 26 but not separate IRQ mask and status registers, there might be 27 situations where userspace cannot determine what the interrupt source 28 was if the kernel handler disables them by writing to the chip's IRQ 29 register. In such a case, the kernel has to disable the IRQ completely 30 to leave the chip's register untouched. Now the userspace part can 31 determine the cause of the interrupt, but it cannot re-enable 32 interrupts. Another cornercase is chips where re-enabling interrupts 33 is a read-modify-write operation to a combined IRQ status/acknowledge 34 register. This would be racy if a new interrupt occurred 35 simultaneously. 36 </p><p> 37 To address these problems, UIO also implements a write() function. It 38 is normally not used and can be ignored for hardware that has only a 39 single interrupt source or has separate IRQ mask and status registers. 40 If you need it, however, a write to <code class="filename">/dev/uioX</code> 41 will call the <code class="function">irqcontrol()</code> function implemented 42 by the driver. You have to write a 32-bit value that is usually either 43 0 or 1 to disable or enable interrupts. If a driver does not implement 44 <code class="function">irqcontrol()</code>, <code class="function">write()</code> will 45 return with <code class="varname">-ENOSYS</code>. 46 </p><p> 47 To handle interrupts properly, your custom kernel module can 48 provide its own interrupt handler. It will automatically be 49 called by the built-in handler. 50 </p><p> 51 For cards that don't generate interrupts but need to be 52 polled, there is the possibility to set up a timer that 53 triggers the interrupt handler at configurable time intervals. 54 This interrupt simulation is done by calling 55 <code class="function">uio_event_notify()</code> 56 from the timer's event handler. 57 </p><p> 58 Each driver provides attributes that are used to read or write 59 variables. These attributes are accessible through sysfs 60 files. A custom kernel driver module can add its own 61 attributes to the device owned by the uio driver, but not added 62 to the UIO device itself at this time. This might change in the 63 future if it would be found to be useful. 64 </p><p> 65 The following standard attributes are provided by the UIO 66 framework: 67 </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p> 68 <code class="filename">name</code>: The name of your device. It is 69 recommended to use the name of your kernel module for this. 70 </p></li><li class="listitem"><p> 71 <code class="filename">version</code>: A version string defined by your 72 driver. This allows the user space part of your driver to deal 73 with different versions of the kernel module. 74 </p></li><li class="listitem"><p> 75 <code class="filename">event</code>: The total number of interrupts 76 handled by the driver since the last time the device node was 77 read. 78 </p></li></ul></div><p> 79 These attributes appear under the 80 <code class="filename">/sys/class/uio/uioX</code> directory. Please 81 note that this directory might be a symlink, and not a real 82 directory. Any userspace code that accesses it must be able 83 to handle this. 84</p><p> 85 Each UIO device can make one or more memory regions available for 86 memory mapping. This is necessary because some industrial I/O cards 87 require access to more than one PCI memory region in a driver. 88</p><p> 89 Each mapping has its own directory in sysfs, the first mapping 90 appears as <code class="filename">/sys/class/uio/uioX/maps/map0/</code>. 91 Subsequent mappings create directories <code class="filename">map1/</code>, 92 <code class="filename">map2/</code>, and so on. These directories will only 93 appear if the size of the mapping is not 0. 94</p><p> 95 Each <code class="filename">mapX/</code> directory contains four read-only files 96 that show attributes of the memory: 97</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p> 98 <code class="filename">name</code>: A string identifier for this mapping. This 99 is optional, the string can be empty. Drivers can set this to make it 100 easier for userspace to find the correct mapping. 101 </p></li><li class="listitem"><p> 102 <code class="filename">addr</code>: The address of memory that can be mapped. 103 </p></li><li class="listitem"><p> 104 <code class="filename">size</code>: The size, in bytes, of the memory 105 pointed to by addr. 106 </p></li><li class="listitem"><p> 107 <code class="filename">offset</code>: The offset, in bytes, that has to be 108 added to the pointer returned by <code class="function">mmap()</code> to get 109 to the actual device memory. This is important if the device's memory 110 is not page aligned. Remember that pointers returned by 111 <code class="function">mmap()</code> are always page aligned, so it is good 112 style to always add this offset. 113 </p></li></ul></div><p> 114 From userspace, the different mappings are distinguished by adjusting 115 the <code class="varname">offset</code> parameter of the 116 <code class="function">mmap()</code> call. To map the memory of mapping N, you 117 have to use N times the page size as your offset: 118</p><pre class="programlisting"> 119offset = N * getpagesize(); 120</pre><p> 121 Sometimes there is hardware with memory-like regions that can not be 122 mapped with the technique described here, but there are still ways to 123 access them from userspace. The most common example are x86 ioports. 124 On x86 systems, userspace can access these ioports using 125 <code class="function">ioperm()</code>, <code class="function">iopl()</code>, 126 <code class="function">inb()</code>, <code class="function">outb()</code>, and similar 127 functions. 128</p><p> 129 Since these ioport regions can not be mapped, they will not appear under 130 <code class="filename">/sys/class/uio/uioX/maps/</code> like the normal memory 131 described above. Without information about the port regions a hardware 132 has to offer, it becomes difficult for the userspace part of the 133 driver to find out which ports belong to which UIO device. 134</p><p> 135 To address this situation, the new directory 136 <code class="filename">/sys/class/uio/uioX/portio/</code> was added. It only 137 exists if the driver wants to pass information about one or more port 138 regions to userspace. If that is the case, subdirectories named 139 <code class="filename">port0</code>, <code class="filename">port1</code>, and so on, 140 will appear underneath 141 <code class="filename">/sys/class/uio/uioX/portio/</code>. 142</p><p> 143 Each <code class="filename">portX/</code> directory contains four read-only 144 files that show name, start, size, and type of the port region: 145</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p> 146 <code class="filename">name</code>: A string identifier for this port region. 147 The string is optional and can be empty. Drivers can set it to make it 148 easier for userspace to find a certain port region. 149 </p></li><li class="listitem"><p> 150 <code class="filename">start</code>: The first port of this region. 151 </p></li><li class="listitem"><p> 152 <code class="filename">size</code>: The number of ports in this region. 153 </p></li><li class="listitem"><p> 154 <code class="filename">porttype</code>: A string describing the type of port. 155 </p></li></ul></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="feedback.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="custom_kernel_module.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Feedback </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 3. Writing your own kernel module</td></tr></table></div></body></html> 156