Various cleanups for uio-howto.tmpl: * grammar/spelling cleanups * improved sentence structure * proper font for function/file names Signed-off-by: Robert P. J. Day <rpjday@xxxxxxxxxxxxxx> --- is that the proper subject format for patches going into Documentation/? and if you have any more suggestions for changes to this file, let me know, i can submit a revised patch. diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index cd0e452..63353fd 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -126,28 +126,29 @@ interested in translating it, please email me 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. + not need to take advantage of any of the other resources that + the kernel provides. One such common class of devices that are + like this are 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 + kernel module is needed; the main part of the driver will run in + userspace. 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: + Please note that UIO is not a universal driver interface. Devices + that are already handled well by other kernel subsystems (such as + networking, serial or USB) are not candidates for a UIO driver. + Hardware that is ideally suited for a UIO driver typically satisfies + the following properties: </para> <itemizedlist> <listitem> - <para>The device has memory that can be mapped. The device can be - controlled completely by writing to this memory.</para> + <para>The device has memory that can be mapped to userspace, + and the device can be controlled completely by writing to this + memory.</para> </listitem> <listitem> <para>The device usually generates interrupts.</para> @@ -183,17 +184,17 @@ interested in translating it, please email me <itemizedlist> <listitem> - <para>only one small kernel module to write and maintain.</para> + <para>There is only one small kernel module to write and maintain.</para> </listitem> <listitem> - <para>develop the main part of your driver in user space, + <para>You can develop the main part of your driver in userspace, with all the tools and libraries you're used to.</para> </listitem> <listitem> - <para>bugs in your driver won't crash the kernel.</para> + <para>Bugs in your driver (typically) won't crash the kernel.</para> </listitem> <listitem> - <para>updates of your driver can take place without recompiling + <para>Updates of your driver can take place without recompiling the kernel.</para> </listitem> </itemizedlist> @@ -202,10 +203,10 @@ interested in translating it, please email me <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. + sysfs attribute files. The device files will be named + <filename>/dev/uio0</filename> for the first device, + <filename>/dev/uio1</filename> for the second device, + and so on. </para> <para><filename>/dev/uioX</filename> is used to access the @@ -240,7 +241,8 @@ interested in translating it, please email me simultaneously. </para> <para> - To address these problems, UIO also implements a write() function. It + To address these problems, UIO also implements a + <function>write()</function> 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> @@ -289,7 +291,7 @@ interested in translating it, please email me <listitem> <para> <filename>version</filename>: A version string defined by your - driver. This allows the user space part of your driver to deal + driver. This allows the userspace part of your driver to deal with different versions of the kernel module. </para> </listitem> @@ -302,7 +304,8 @@ interested in translating it, please email me </listitem> </itemizedlist> <para> - These attributes appear under the + Attributes for the UIO device file <filename>/dev/uioX</filename> + appear under the corresponding <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 @@ -314,7 +317,7 @@ interested in translating it, please email me 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 + 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 @@ -340,7 +343,7 @@ interested in translating it, please email me <listitem> <para> <filename>size</filename>: The size, in bytes, of the memory - pointed to by addr. + pointed to by <filename>addr</filename>. </para> </listitem> <listitem> @@ -348,8 +351,8 @@ interested in translating it, please email me <filename>offset</filename>: The offset, in bytes, that has to be added to the pointer returned by <function>mmap()</function> to get to the actual device memory. This is important if the device's memory - is not page aligned. Remember that pointers returned by - <function>mmap()</function> are always page aligned, so it is good + is not page-aligned. Remember that pointers returned by + <function>mmap()</function> are always page-aligned, so it is good style to always add this offset. </para> </listitem> @@ -362,11 +365,21 @@ interested in translating it, please email me have to use N times the page size as your offset: </para> <programlisting format="linespecific"> -offset = N * getpagesize(); + offset = N * getpagesize(); </programlisting> <para> - Sometimes there is hardware with memory-like regions that can not be + Note that, in SuSv2, the <function>getpagesize()</function> routine + is labeled as LEGACY and, for portability, you are encouraged to use + the newer form: +</para> +<programlisting format="linespecific"> + #include <unistd.h> + long sz = sysconf(_SC_PAGESIZE); +</programlisting> + +<para> + Sometimes there is hardware with memory-like regions that cannot be mapped with the technique described here, but there are still ways to access them from userspace. The most common example are x86 ioports. On x86 systems, userspace can access these ioports using @@ -375,7 +388,7 @@ offset = N * getpagesize(); functions. </para> <para> - Since these ioport regions can not be mapped, they will not appear under + Since these ioport regions cannot be mapped, they will not appear under <filename>/sys/class/uio/uioX/maps/</filename> like the normal memory described above. Without information about the port regions a hardware has to offer, it becomes difficult for the userspace part of the @@ -386,7 +399,7 @@ offset = N * getpagesize(); <filename>/sys/class/uio/uioX/portio/</filename> was added. It only exists if the driver wants to pass information about one or more port regions to userspace. If that is the case, subdirectories named - <filename>port0</filename>, <filename>port1</filename>, and so on, + <filename>port0/</filename>, <filename>port1/</filename>, and so on, will appear underneath <filename>/sys/class/uio/uioX/portio/</filename>. </para> @@ -414,7 +427,8 @@ offset = N * getpagesize(); </listitem> <listitem> <para> - <filename>porttype</filename>: A string describing the type of port. + <filename>porttype</filename>: A string describing the type of port; + current valid values are "none", "x86", "gpio" and "other". </para> </listitem> </itemizedlist> @@ -427,15 +441,15 @@ offset = N * getpagesize(); <?dbhtml filename="custom_kernel_module.html"?> <title>Writing your own kernel module</title> <para> - Please have a look at <filename>uio_cif.c</filename> as an - example. The following paragraphs explain the different - sections of this file. + Please have a look at <filename>drivers/uio/uio_cif.c</filename> + as an example of a simple UIO device. 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, + This structure tells the UIO framework the details of your driver. Some of the members are required, others are optional. </para> @@ -451,14 +465,14 @@ it will appear in sysfs. I recommend using the name of your module for this. </para></listitem> <listitem><para> -<varname>struct uio_mem mem[ MAX_UIO_MAPS ]</varname>: Required if you +<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>struct uio_port port[ MAX_UIO_PORTS_REGIONS ]</varname>: Required +<varname>struct uio_port port[MAX_UIO_PORT_REGIONS]</varname>: Required if you want to pass information about ioports to userspace. For each port region you need to fill one of the <varname>uio_port</varname> structures. See the description below for details. @@ -466,8 +480,8 @@ See the description below for details. <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 +interrupt, it's your module's 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>. If you had no interrupt at all, you could set @@ -514,7 +528,7 @@ will be 0 to disable interrupts and 1 to enable them. <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 +to userspace. 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> @@ -527,7 +541,7 @@ the memory region, it will show up in the corresponding sysfs node. <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 +<varname>UIO_MEM_PHYS</varname> if 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. @@ -548,10 +562,10 @@ all unused mappings. </para></listitem> <listitem><para> -<varname>void *internal_addr</varname>: If you have to access this memory +<varname>void __iomem *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 +returned by this function cannot be mapped to userspace, so you must not store it in <varname>addr</varname>. Use <varname>internal_addr</varname> instead to remember such an address. </para></listitem> @@ -564,7 +578,7 @@ to set up sysfs files for this mapping. Simply leave it alone. </para> <para> -Sometimes, your device can have one or more port regions which can not be +Sometimes, your device can have one or more port regions which cannot 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 @@ -574,9 +588,8 @@ Here's a description of the fields of <varname>struct uio_port</varname>: <itemizedlist> <listitem><para> -<varname>char *porttype</varname>: Required. Set this to one of the predefined -constants. Use <varname>UIO_PORT_X86</varname> for the ioports found in x86 -architectures. +<varname>const char *name</varname>: Name of the port region for +identification. </para></listitem> <listitem><para> @@ -590,6 +603,12 @@ region. If <varname>size</varname> is zero, the region is considered unused. Note that you <emphasis>must</emphasis> initialize <varname>size</varname> with zero for all unused regions. </para></listitem> + +<listitem><para> +<varname>int porttype</varname>: Required. Set this to one of the predefined +constants. Use <varname>UIO_PORT_X86</varname> for the ioports found in x86 +architectures. +</para></listitem> </itemizedlist> <para> @@ -722,22 +741,22 @@ framework to set up sysfs files for this region. Simply leave it alone. <sect1 id="using-uio_dmem_genirq"> <title>Using uio_dmem_genirq for platform devices</title> <para> - In addition to statically allocated memory ranges, they may also be - a desire to use dynamically allocated regions in a user space driver. + In addition to statically-allocated memory ranges, there may also be + a desire to use dynamically-allocated regions in a userspace driver. In particular, being able to access memory made available through the - dma-mapping API, may be particularly useful. The + dma-mapping API may be particularly useful. The <varname>uio_dmem_genirq</varname> driver provides a way to accomplish this. </para> <para> This driver is used in a similar manner to the - <varname>"uio_pdrv_genirq"</varname> driver with respect to interrupt + <varname>uio_pdrv_genirq</varname> driver with respect to interrupt configuration and handling. </para> <para> Set the <varname>.name</varname> element of <varname>struct platform_device</varname> to - <varname>"uio_dmem_genirq"</varname> to use this driver. + <varname>uio_dmem_genirq</varname> to use this driver. </para> <para> When using this driver, fill in the <varname>.platform_data</varname> @@ -751,7 +770,7 @@ framework to set up sysfs files for this region. Simply leave it alone. data</para></listitem> <listitem><para><varname>unsigned int *dynamic_region_sizes</varname>: Pointer to list of sizes of dynamic memory regions to be mapped into - user space. + userspace. </para></listitem> <listitem><para><varname>unsigned int num_dynamic_regions</varname>: Number of elements in <varname>dynamic_region_sizes</varname> array. @@ -777,7 +796,7 @@ framework to set up sysfs files for this region. Simply leave it alone. </chapter> -<chapter id="userspace_driver" xreflabel="Writing a driver in user space"> +<chapter id="userspace_driver" xreflabel="Writing a driver in userspace"> <?dbhtml filename="userspace_driver.html"?> <title>Writing a driver in userspace</title> <para> @@ -795,7 +814,7 @@ framework to set up sysfs files for this region. Simply leave it alone. 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 + make sure you're talking to the right device and that its kernel driver has the version you expect. </para> <para> @@ -817,7 +836,7 @@ framework to set up sysfs files for this region. Simply leave it alone. </para> <para> The source code of <varname>lsuio</varname> can serve as an - example for getting information about an UIO device. + example for getting information about a UIO device. The file <filename>uio_helper.c</filename> contains a lot of functions you could use in your userspace driver code. </para> @@ -840,7 +859,7 @@ framework to set up sysfs files for this region. Simply leave it alone. your offset: </para> <programlisting format="linespecific"> - offset = N * getpagesize(); + offset = N * sysconf(_SC_PAGESIZE); </programlisting> <para> N starts from zero, so if you've got only one memory @@ -853,7 +872,7 @@ framework to set up sysfs files for this region. Simply leave it alone. <sect1 id="wait_for_interrupts"> <title>Waiting for interrupts</title> <para> - After you successfully mapped your devices memory, you + After you successfully mapped your device's 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 @@ -928,7 +947,7 @@ If binding the device failed, run the following command: <programlisting> dmesg </programlisting> -and look in the output for failure reasons +and look in the output for failure reasons. </para> </sect1> @@ -951,9 +970,9 @@ bit before blocking and waiting for more interrupts. <sect1 id="uio_pci_generic_userspace"> <title>Writing userspace driver using uio_pci_generic</title> <para> -Userspace driver can use pci sysfs interface, or the -libpci libray that wraps it, to talk to the device and to -re-enable interrupts by writing to the command register. +The <filename>uio_pci_generic</filename> userspace driver can use the +PCI sysfs interface, or the libpci library that wraps it, to talk to +the device and to re-enable interrupts by writing to the command register. </para> </sect1> <sect1 id="uio_pci_generic_example"> rday -- ======================================================================== Robert P. J. Day Ottawa, Ontario, CANADA http://crashcourse.ca Twitter: http://twitter.com/rpjday LinkedIn: http://ca.linkedin.com/in/rpjday ======================================================================== -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html