diff options
Diffstat (limited to 'Documentation')
-rw-r--r-- | Documentation/Configure.help | 18 | ||||
-rw-r--r-- | Documentation/DocBook/Makefile | 17 | ||||
-rw-r--r-- | Documentation/DocBook/kernel-api.tmpl | 5 | ||||
-rw-r--r-- | Documentation/DocBook/kernel-hacking.tmpl | 1316 | ||||
-rw-r--r-- | Documentation/DocBook/kernel-locking.tmpl | 1221 | ||||
-rw-r--r-- | Documentation/DocBook/parportbook.tmpl | 3446 | ||||
-rw-r--r-- | Documentation/filesystems/cramfs.txt | 4 | ||||
-rw-r--r-- | Documentation/kbuild/config-language.txt | 2 | ||||
-rw-r--r-- | Documentation/kernel-doc-nano-HOWTO.txt | 128 | ||||
-rw-r--r-- | Documentation/networking/8139too.txt | 33 | ||||
-rw-r--r-- | Documentation/pci.txt | 10 | ||||
-rw-r--r-- | Documentation/s390/DASD | 2 | ||||
-rw-r--r-- | Documentation/usb/ov511.txt | 52 | ||||
-rw-r--r-- | Documentation/usb/usb-serial.txt | 25 | ||||
-rw-r--r-- | Documentation/video4linux/bttv/CARDLIST | 4 |
15 files changed, 4815 insertions, 1468 deletions
diff --git a/Documentation/Configure.help b/Documentation/Configure.help index f65e265dc..4d7b936a3 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -1496,7 +1496,7 @@ CONFIG_MD_RAID0 If unsure, say Y. -DANGEROUS! RAID-1/RAID-5 code +RAID-1/RAID-5 code (DANGEROUS) CONFIG_RAID15_DANGEROUS This new RAID1/RAID5 code has been freshly merged, and has not seen enough testing yet. While there are no known bugs in it, it might @@ -9779,6 +9779,12 @@ USB ZyXEL omni.net LCD Plus Driver CONFIG_USB_SERIAL_OMNINET Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA. +USB Digi International AccelePort USB Serial Driver +CONFIG_USB_SERIAL_DIGI_ACCELEPORT + Say Y here if you want to use a Digi AccelePort USB 4 device, + a 4 port USB serial converter. The Digi Acceleport USB 2 and + 8 are not yet supported by this driver. + USB Printer support CONFIG_USB_PRINTER Say Y here if you want to connect a USB printer to your computer's @@ -10430,7 +10436,7 @@ CONFIG_NFSD Provide NFSv3 server support CONFIG_NFSD_V3 If you would like to include the NFSv3 server as well as the NFSv2 - server, say Y here. In unsure, say Y. + server, say Y here. If unsure, say Y. OS/2 HPFS file system support CONFIG_HPFS_FS @@ -12462,14 +12468,6 @@ CONFIG_APM_DISPLAY_BLANK backlight at all, or it might print a lot of errors to the console, especially if you are using gpm. -Ignore multiple suspend/standby events -CONFIG_APM_IGNORE_MULTIPLE_SUSPEND - This option is necessary on the IBM Thinkpad 560, but should work on - all other laptops. When the APM BIOS returns multiple suspend or - standby events while one is already being processed they will be - ignored. Without this the Thinkpad 560 has troubles with the user - level daemon apmd, and with the PCMCIA package pcmcia-cs. - Ignore multiple suspend/resume cycles CONFIG_APM_IGNORE_SUSPEND_BOUNCE This option is necessary on the Dell Inspiron 3200 and others, but diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 2079bae18..8a40bfade 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -1,4 +1,4 @@ -BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml kernel-api.sgml parportbook.sgml +BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml kernel-api.sgml parportbook.sgml kernel-hacking.sgml kernel-locking.sgml PS := $(patsubst %.sgml, %.ps, $(BOOKS)) PDF := $(patsubst %.sgml, %.pdf, $(BOOKS)) @@ -18,6 +18,9 @@ db2ps db2pdf: (echo "*** You need to install DocBook stylesheets ***"; \ exit 1) +%.eps: %.fig + -fig2dev -Leps $< $@ + $(TOPDIR)/scripts/docproc: $(MAKE) -C $(TOPDIR)/scripts docproc @@ -51,6 +54,7 @@ kernel-api.sgml: kernel-api.tmpl $(TOPDIR)/drivers/sound/sound_firmware.c \ $(TOPDIR)/drivers/net/wan/syncppp.c \ $(TOPDIR)/drivers/net/wan/z85230.c \ + $(TOPDIR)/fs/devfs/base.c \ $(TOPDIR)/kernel/pm.c \ $(TOPDIR)/kernel/ksyms.c \ $(TOPDIR)/net/netsyms.c \ @@ -66,12 +70,15 @@ TEX := $(patsubst %.sgml, %.tex, $(BOOKS)) LOG := $(patsubst %.sgml, %.log, $(BOOKS)) clean: - $(RM) core *~ - $(RM) $(BOOKS) - $(RM) $(DVI) $(AUX) $(TEX) $(LOG) + -$(RM) core *~ + -$(RM) $(BOOKS) + -$(RM) $(DVI) $(AUX) $(TEX) $(LOG) + -$(RM) parport-share.eps parport-multi.eps parport-structure.eps mrproper: clean - $(RM) $(PS) $(PDF) + -$(RM) $(PS) $(PDF) + +parportbook.ps: parport-share.eps parport-multi.eps parport-structure.eps %.ps : %.sgml db2ps db2ps $< diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 3f886e702..688cdf351 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -101,6 +101,11 @@ </sect1> </chapter> + <chapter id="devfs"> + <title>The Device File System</title> +!Efs/devfs/base.c + </chapter> + <chapter id="pmfuncs"> <title>Power Management</title> !Ekernel/pm.c diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl new file mode 100644 index 000000000..8d87787ad --- /dev/null +++ b/Documentation/DocBook/kernel-hacking.tmpl @@ -0,0 +1,1316 @@ +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]> + +<book id="lk-hacking-guide"> + <bookinfo> + <title>Unreliable Guide To Hacking The Linux Kernel</title> + + <authorgroup> + <author> + <firstname>Paul</firstname> + <othername>Rusty</othername> + <surname>Russell</surname> + <affiliation> + <address> + <email>rusty@linuxcare.com</email> + </address> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2000</year> + <holder>Paul Russell</holder> + </copyright> + + <legalnotice> + <para> + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + </para> + + <para> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + </para> + + <para> + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + </para> + + <para> + For more details see the file COPYING in the source + distribution of Linux. + </para> + </legalnotice> + + <releaseinfo> + This is the first release of this document as part of the kernel tarball. + </releaseinfo> + + </bookinfo> + + <toc></toc> + + <chapter id="introduction"> + <title>Introduction</title> + <para> + Welcome, gentle reader, to Rusty's Unreliable Guide to Linux + Kernel Hacking. This document describes the common routines and + general requirements for kernel code: its goal is to serve as a + primer for Linux kernel development for experienced C + programmers. I avoid implementation details: that's what the + code is for, and I ignore whole tracts of useful routines. + </para> + <para> + Before you read this, please understand that I never wanted to + write this document, being grossly under-qualified, but I always + wanted to read it, and this was the only way. I hope it will + grow into a compendium of best practice, common starting points + and random information. + </para> + </chapter> + + <chapter id="basic-players"> + <title>The Players</title> + + <para> + At any time each of the CPUs in a system can be: + </para> + + <itemizedlist> + <listitem> + <para> + not associated with any process, serving a hardware interrupt; + </para> + </listitem> + + <listitem> + <para> + not associated with any process, serving a softirq, tasklet or bh; + </para> + </listitem> + + <listitem> + <para> + running in kernel space, associated with a process; + </para> + </listitem> + + <listitem> + <para> + running a process in user space. + </para> + </listitem> + </itemizedlist> + + <para> + There is a strict ordering between these: other than the last + category (userspace) each can only be pre-empted by those above. + For example, while a softirq is running on a CPU, no other + softirq will pre-empt it, but a hardware interrupt can. However, + any other CPUs in the system execute independently. + </para> + + <para> + We'll see a number of ways that the user context can block + interrupts, to become truly non-preemptable. + </para> + + <sect1 id="basics-usercontext"> + <title>User Context</title> + + <para> + User context is when you are coming in from a system call or + other trap: you can sleep, and you own the CPU (except for + interrupts) until you call <function>schedule()</function>. + In other words, user context (unlike userspace) is not pre-emptable. + </para> + + <note> + <para> + You are always in user context on module load and unload, + and on operations on the block device layer. + </para> + </note> + + <para> + In user context, the <varname>current</varname> pointer (indicating + the task we are currently executing) is valid, and + <function>in_interrupt()</function> + (<filename>include/asm/hardirq.h</filename>) is <returnvalue>false + </returnvalue>. + </para> + + <caution> + <para> + Beware that if you have interrupts or bottom halves disabled + (see below), <function>in_interrupt()</function> will return a + false positive. + </para> + </caution> + </sect1> + + <sect1 id="basics-hardirqs"> + <title>Hardware Interrupts (Hard IRQs)</title> + + <para> + Timer ticks, <hardware>network cards</hardware> and + <hardware>keyboard</hardware> are examples of real + hardware which produce interrupts at any time. The kernel runs + interrupt handlers, which services the hardware. The kernel + guarantees that this handler is never re-entered: if another + interrupt arrives, it is queued (or dropped). Because it + disables interrupts, this handler has to be fast: frequently it + simply acknowledges the interrupt, marks a `software interrupt' + for execution and exits. + </para> + + <para> + You can tell you are in a hardware interrupt, because + <function>in_irq()</function> returns <returnvalue>true</returnvalue>. + </para> + <caution> + <para> + Beware that this will return a false positive if interrupts are disabled + (see below). + </para> + </caution> + </sect1> + + <sect1 id="basics-softirqs"> + <title>Software Interrupt Context: Bottom Halves, Tasklets, softirqs</title> + + <para> + Whenever a system call is about to return to userspace, or a + hardware interrupt handler exits, any `software interrupts' + which are marked pending (usually by hardware interrupts) are + run (<filename>kernel/softirq.c</filename>). + </para> + + <para> + Much of the real interrupt handling work is done here. Early in + the transition to <acronym>SMP</acronym>, there were only `bottom + halves' (BHs), which didn't take advantage of multiple CPUs. Shortly + after we switched from wind-up computers made of match-sticks and snot, + we abandoned this limitation. + </para> + + <para> + <filename class=headerfile>include/linux/interrupt.h</filename> lists the + different BH's. No matter how many CPUs you have, no two BHs will run at + the same time. This made the transition to SMP simpler, but sucks hard for + scalable performance. A very important bottom half is the timer + BH (<filename class=headerfile>include/linux/timer.h</filename>): you + can register to have it call functions for you in a given length of time. + </para> + + <para> + 2.3.43 introduced softirqs, and re-implemented the (now + deprecated) BHs underneath them. Softirqs are fully-SMP + versions of BHs: they can run on as many CPUs at once as + required. This means they need to deal with any races in shared + data using their own locks. A bitmask is used to keep track of + which are enabled, so the 32 available softirqs should not be + used up lightly. (<emphasis>Yes</emphasis>, people will + notice). + </para> + + <para> + tasklets (<filename class=headerfile>include/linux/interrupt.h</filename>) + are like softirqs, except they are dynamically-registrable (meaning you + can have as many as you want), and they also guarantee that any tasklet + will only run on one CPU at any time, although different tasklets can + run simultaneously (unlike different BHs). + </para> + <caution> + <para> + The name `tasklet' is misleading: they have nothing to do with `tasks', + and probably more to do with some bad vodka Alexey Kuznetsov had at the + time. + </para> + </caution> + + <para> + You can tell you are in a softirq (or bottom half, or tasklet) + using the <function>in_softirq()</function> macro + (<filename class=headerfile>include/asm/softirq.h</filename>). + </para> + <caution> + <para> + Beware that this will return a false positive if a bh lock (see below) + is held. + </para> + </caution> + </sect1> + </chapter> + + <chapter id="basic-rules"> + <title>Some Basic Rules</title> + + <variablelist> + <varlistentry> + <term>No memory protection</term> + <listitem> + <para> + If you corrupt memory, whether in user context or + interrupt context, the whole machine will crash. Are you + sure you can't do what you want in userspace? + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>No floating point or <acronym>MMX</acronym></term> + <listitem> + <para> + The <acronym>FPU</acronym> context is not saved; even in user + context the <acronym>FPU</acronym> state probably won't + correspond with the current process: you would mess with some + user process' <acronym>FPU</acronym> state. If you really want + to do this, you would have to explicitly save/restore the full + <acronym>FPU</acronym> state (and avoid context switches). It + is generally a bad idea; use fixed point arithmetic first. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>A rigid stack limit</term> + <listitem> + <para> + The kernel stack is about 6K in 2.2 (for most + architectures: it's about 14K on the Alpha), and shared + with interrupts so you can't use it all. Avoid deep + recursion and huge local arrays on the stack (allocate + them dynamically instead). + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>The Linux kernel is portable</term> + <listitem> + <para> + Let's keep it that way. Your code should be 64-bit clean, + and endian-independent. You should also minimize CPU + specific stuff, e.g. inline assembly should be cleanly + encapsulated and minimized to ease porting. Generally it + should be restricted to the architecture-dependent part of + the kernel tree. + </para> + </listitem> + </varlistentry> + </variablelist> + </chapter> + + <chapter id="ioctls"> + <title>ioctls: Not writing a new system call</title> + + <para> + A system call generally looks like this + </para> + + <programlisting> +asmlinkage int sys_mycall(int arg) +{ + return 0; +} + </programlisting> + + <para> + First, in most cases you don't want to create a new system call. + You create a character device and implement an appropriate ioctl + for it. This is much more flexible than system calls, doesn't have + to be entered in every architecture's + <filename class=headerfile>include/asm/unistd.h</filename> and + <filename>arch/kernel/entry.S</filename> file, and is much more + likely to be accepted by Linus. + </para> + + <para> + Inside the ioctl you're in user context to a process. When a + error occurs you return a negated errno (see + <filename class=headerfile>include/linux/errno.h</filename>), + otherwise you return <returnvalue>0</returnvalue>. + </para> + + <para> + After you slept you should check if a signal occurred: the + Unix/Linux way of handling signals is to temporarily exit the + system call with the <constant>-ERESTARTSYS</constant> error. The + system call entry code will switch back to user context, process + the signal handler and then your system call will be restarted + (unless the user disabled that). So you should be prepared to + process the restart, e.g. if you're in the middle of manipulating + some data structure. + </para> + + <programlisting> +if (signal_pending()) + return -ERESTARTSYS; + </programlisting> + + <para> + If you're doing longer computations: first think userspace. If you + <emphasis>really</emphasis> want to do it in kernel you should + regularly check if you need to give up the CPU (remember there is + cooperative multitasking per CPU). Idiom: + </para> + + <programlisting> +if (current->need_resched) + schedule(); /* Will sleep */ + </programlisting> + + <para> + A short note on interface design: the UNIX system call motto is + "Provide mechanism not policy". + </para> + </chapter> + + <chapter id="deadlock-recipes"> + <title>Recipes for Deadlock</title> + + <para> + You cannot call any routines which may sleep, unless: + </para> + <itemizedlist> + <listitem> + <para> + You are in user context. + </para> + </listitem> + + <listitem> + <para> + You do not own any spinlocks. + </para> + </listitem> + + <listitem> + <para> + You have interrupts enabled (actually, Andi Kleen says + that the scheduling code will enable them for you, but + that's probably not what you wanted). + </para> + </listitem> + </itemizedlist> + + <para> + Note that some functions may sleep implicitly: common ones are + the user space access functions (*_user) and memory allocation + functions without GFP_ATOMIC. + </para> + + <para> + You will eventually lock up your box if you break these rules. + </para> + + <para> + Really. + </para> + </chapter> + + <chapter id="common-routines"> + <title>Common Routines</title> + + <sect1 id="routines-printk"> + <title> + <function>printk()</function> + <filename class=headerfile>include/linux/kernel.h</filename> + </title> + + <para> + <function>printk()</function> feeds kernel messages to the + console, dmesg, and the syslog daemon. It is useful for debugging + and reporting errors, and can be used inside interrupt context, + but use with caution: a machine which has its console flooded with + printk messages is unusable. It uses a format string mostly + compatible with ANSI C printf, and C string concatenation to give + it a first "priority" argument: + </para> + + <programlisting> +printk(KERN_INFO "i = %u\n", i); + </programlisting> + + <para> + See <filename class=headerfile>include/linux/kernel.h</filename>; + for other KERN_ values; these are interpreted by syslog as the + level. Special case: for printing an IP address use + </para> + + <programlisting> +__u32 ipaddress; +printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress)); + </programlisting> + + <para> + <function>printk()</function> internally uses a 1K buffer and does + not catch overruns. Make sure that will be enough. + </para> + + <note> + <para> + You will know when you are a real kernel hacker + when you start typoing printf as printk in your user programs :) + </para> + </note> + + <!--- From the Lions book reader department --> + + <note> + <para> + Another sidenote: the original Unix Version 6 sources had a + comment on top of its printf function: "Printf should not be + used for chit-chat". You should follow that advice. + </para> + </note> + </sect1> + + <sect1 id="routines-copy"> + <title> + <function>copy_[to/from]_user()</function> + / + <function>get_user()</function> + / + <function>put_user()</function> + <filename class=headerfile>include/asm/uaccess.h</filename> + </title> + + <para> + <emphasis>[SLEEPS]</emphasis> + </para> + + <para> + <function>put_user()</function> and <function>get_user()</function> + are used to get and put single values (such as an int, char, or + long) from and to userspace. A pointer into userspace should + never be simply dereferenced: data should be copied using these + routines. Both return <constant>-EFAULT</constant> or 0. + </para> + <para> + <function>copy_to_user()</function> and + <function>copy_from_user()</function> are more general: they copy + an arbitrary amount of data to and from userspace. + <caution> + <para> + Unlike <function>put_user()</function> and + <function>get_user()</function>, they return the amount of + uncopied data (ie. <returnvalue>0</returnvalue> still means + success). + </para> + </caution> + [Yes, this moronic interface makes me cringe. Please submit a + patch and become my hero --RR.] + </para> + <para> + The functions may sleep implicitly. This should never be called + outside user context (it makes no sense), with interrupts + disabled, or a spinlock held. + </para> + </sect1> + + <sect1 id="routines-kmalloc"> + <title><function>kmalloc()</function>/<function>kfree()</function> + <filename class=headerfile>include/linux/slab.h</filename></title> + + <para> + <emphasis>[MAY SLEEP: SEE BELOW]</emphasis> + </para> + + <para> + These routines are used to dynamically request pointer-aligned + chunks of memory, like malloc and free do in userspace, but + <function>kmalloc()</function> takes an extra flag word. + Important values: + </para> + + <variablelist> + <varlistentry> + <term> + <constant> + GFP_KERNEL + </constant> + </term> + <listitem> + <para> + May sleep and swap to free memory. Only allowed in user + context, but is the most reliable way to allocate memory. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <constant> + GFP_ATOMIC + </constant> + </term> + <listitem> + <para> + Don't sleep. Less reliable than <constant>GFP_KERNEL</constant>, + but may be called from interrupt context. You should + <emphasis>really</emphasis> have a good out-of-memory + error-handling strategy. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <constant> + GFP_DMA + </constant> + </term> + <listitem> + <para> + Allocate ISA DMA lower than 16MB. If you don't know what that + is you don't need it. Very unreliable. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + If you see a <errorname>kmem_grow: Called nonatomically from int + </errorname> warning message you called a memory allocation function + from interrupt context without <constant>GFP_ATOMIC</constant>. + You should really fix that. Run, don't walk. + </para> + + <para> + If you are allocating at least <constant>PAGE_SIZE</constant> + (<filename class=headerfile>include/asm/page.h</filename>) bytes, + consider using <function>__get_free_pages()</function> + + (<filename class=headerfile>include/linux/mm.h</filename>). It + takes an order argument (0 for page sized, 1 for double page, 2 + for four pages etc.) and the same memory priority flag word as + above. + </para> + + <para> + If you are allocating more than a page worth of bytes you can use + <function>vmalloc()</function>. It'll allocate virtual memory in + the kernel map. This block is not contiguous in physical memory, + but the <acronym>MMU</acronym> makes it look like it is for you + (so it'll only look contiguous to the CPUs, not to external device + drivers). If you really need large physically contiguous memory + for some weird device, you have a problem: it is poorly supported + in Linux because after some time memory fragmentation in a running + kernel makes it hard. The best way is to allocate the block early + in the boot process. + </para> + + <para> + Before inventing your own cache of often-used objects consider + using a slab cache in + <filename class=headerfile>include/linux/slab.h</filename> + </para> + </sect1> + + <sect1 id="routines-current"> + <title><function>current</function> + <filename class=headerfile>include/asm/current.h</filename></title> + + <para> + This global variable (really a macro) contains a pointer to + the current task structure, so is only valid in user context. + For example, when a process makes a system call, this will + point to the task structure of the calling process. It is + <emphasis>not NULL</emphasis> in interrupt context. + </para> + </sect1> + + <sect1 id="routines-local-irqs"> + <title><function>local_irq_save()</function>/<function>local_irq_restore()</function> + <filename class=headerfile>include/asm/system.h</filename> + </title> + + <para> + These routines disable hard interrupts on the local CPU, and + restore them. They are reentrant; saving the previous state in + their one <varname>unsigned long flags</varname> argument. If you + know that interrupts are enabled, you can simply use + <function>local_irq_disable()</function> and + <function>local_irq_enable()</function>. + </para> + </sect1> + + <sect1 id="routines-softirqs"> + <title><function>local_bh_disable()</function>/<function>local_bh_enable()</function> + <filename class=headerfile>include/asm/softirq.h</filename></title> + + <para> + These routines disable soft interrupts on the local CPU, and + restore them. They are reentrant; if soft interrupts were + disabled before, they will still be disabled after this pair + of functions has been called. They prevent softirqs, tasklets + and bottom halves from running on the current CPU. + </para> + </sect1> + + <sect1 id="routines-processorids"> + <title><function>smp_processor_id</function>()/<function>cpu_[number/logical]_map()</function> + <filename class=headerfile>include/asm/smp.h</filename></title> + + <para> + <function>smp_processor_id()</function> returns the current + processor number, between 0 and <symbol>NR_CPUS</symbol> (the + maximum number of CPUs supported by Linux, currently 32). These + values are not necessarily continuous: to get a number between 0 + and <function>smp_num_cpus()</function> (the number of actual + processors in this machine), the + <function>cpu_number_map()</function> function is used to map the + processor id to a logical number. + <function>cpu_logical_map()</function> does the reverse. + </para> + </sect1> + + <sect1 id="routines-init"> + <title><type>__init</type>/<type>__exit</type>/<type>__initdata</type> + <filename class=headerfile>include/linux/init.h</filename></title> + + <para> + After boot, the kernel frees up a special section; functions + marked with <type>__init</type> and data structures marked with + <type>__initdata</type> are dropped after boot is complete (within + modules this directive is currently ignored). <type>__exit</type> + is used to declare a function which is only required on exit: the + function will be dropped if this file is not compiled as a module. + See the header file for use. + </para> + + </sect1> + + <sect1 id="routines-init-again"> + <title><function>__initcall()</function>/<function>module_init()</function> + <filename class=headerfile>include/linux/init.h</filename></title> + <para> + Many parts of the kernel are well served as a module + (dynamically-loadable parts of the kernel). Using the + <function>module_init()</function> and + <function>module_exit()</function> macros it is easy to write code + without #ifdefs which can operate both as a module or built into + the kernel. + </para> + + <para> + The <function>module_init()</function> macro defines which + function is to be called at module insertion time (if the file is + compiled as a module), or at boot time: if the file is not + compiled as a module the <function>module_init()</function> macro + becomes equivalent to <function>__initcall()</function>, which + through linker magic ensures that the function is called on boot. + </para> + + <para> + The function can return a negative error number to cause + module loading to fail (unfortunately, this has no effect if + the module is compiled into the kernel). For modules, this is + called in user context, with interrupts enabled, and the + kernel lock held, so it can sleep. + </para> + </sect1> + + <sect1 id="routines-moduleexit"> + <title> <function>module_exit()</function> + <filename class=headerfile>include/linux/init.h</filename> </title> + + <para> + This macro defines the function to be called at module removal + time (or never, in the case of the file compiled into the + kernel). It will only be called if the module usage count has + reached zero. This function can also sleep, but cannot fail: + everything must be cleaned up by the time it returns. + </para> + </sect1> + + <sect1 id="routines-module-use-counters"> + <title> <function>MOD_INC_USE_COUNT</function>/<function>MOD_DEC_USE_COUNT</function> + <filename class=headerfile>include/linux/module.h</filename></title> + + <para> + These manipulate the module usage count, to protect against + removal (a module also can't be removed if another module uses + one of its exported symbols: see below). Every reference to + the module from user context should be reflected by this + counter (e.g. for every data structure or socket) before the + function sleeps. To quote Tim Waugh: + </para> + + <programlisting> +/* THIS IS BAD */ +foo_open (...) +{ + stuff.. + if (fail) + return -EBUSY; + sleep.. (might get unloaded here) + stuff.. + MOD_INC_USE_COUNT; + return 0; +} + +/* THIS IS GOOD / +foo_open (...) +{ + MOD_INC_USE_COUNT; + stuff.. + if (fail) { + MOD_DEC_USE_COUNT; + return -EBUSY; + } + sleep.. (safe now) + stuff.. + return 0; +} + </programlisting> + </sect1> + </chapter> + + <chapter id="queues"> + <title>Wait Queues + <filename class=headerfile>include/linux/wait.h</filename> + </title> + <para> + <emphasis>[SLEEPS]</emphasis> + </para> + + <para> + A wait queue is used to wait for someone to wake you up when a + certain condition is true. They must be used carefully to ensure + there is no race condition. You declare a + <type>wait_queue_head_t</type>, and then processes which want to + wait for that condition declare a <type>wait_queue_t</type> + referring to themselves, and place that in the queue. + </para> + + <sect1 id="queue-declaring"> + <title>Declaring</title> + + <para> + You declare a <type>wait_queue_head_t</type> using the + <function>DECLARE_WAIT_QUEUE_HEAD()</function> macro, or using the + <function>init_waitqueue_head()</function> routine in your + initialization code. + </para> + </sect1> + + <sect1 id="queue-waitqueue"> + <title>Queuing</title> + + <para> + Placing yourself in the waitqueue is fairly complex, because you + must put yourself in the queue before checking the condition. + There is a macro to do this: + <function>wait_event_interruptible()</function> + + <filename class=headerfile>include/linux/sched.h</filename> The + first argument is the wait queue head, and the second is an + expression which is evaluated; the macro returns + <returnvalue>0</returnvalue> when this expression is true, or + <returnvalue>-ERESTARTSYS</returnvalue> if a signal is received. + The <function>wait_event()</function> version ignores signals. + </para> + </sect1> + + <sect1 id="queue-waking"> + <title>Waking Up Queued Tasks</title> + + <para> + Call <function>wake_up()</function> + + <filename class=headerfile>include/linux/sched.h</filename>;, + which will wake up every process in the queue. The exception is + if one has <constant>TASK_EXCLUSIVE</constant> set, in which case + the remainder of the queue will not be woken. + </para> + </sect1> + </chapter> + + <chapter id="atomic-ops"> + <title>Atomic Operations</title> + + <para> + Certain operations are guaranteed atomic on all platforms. The + first class of operations work on <type>atomic_t</type> + + <filename class=headerfile>include/asm/atomic.h</filename>; this + contains a signed integer (at least 32 bits long), and you must use + these functions to manipulate or read atomic_t variables. + <function>atomic_read()</function> and + <function>atomic_set()</function> get and set the counter, + <function>atomic_add()</function>, + <function>atomic_sub()</function>, + <function>atomic_inc()</function>, + <function>atomic_dec()</function>, and + <function>atomic_dec_and_test()</function> (returns + <returnvalue>true</returnvalue> if it was decremented to zero). + </para> + + <para> + Yes. It returns <returnvalue>true</returnvalue> (i.e. != 0) if the + atomic variable is zero. + </para> + + <para> + Note that these functions are slower than normal arithmetic, and + so should not be used unnecessarily. On some platforms they + are much slower, like 32-bit Sparc where they use a spinlock. + </para> + + <para> + The second class of atomic operations is atomic bit operations, + defined in + + <filename class=headerfile>include/asm/bitops.h</filename>. These + operations generally take a pointer to the bit pattern, and a bit + number: 0 is the least significant bit. + <function>set_bit()</function>, <function>clear_bit()</function> + and <function>change_bit()</function> set, clear, and flip the + given bit. <function>test_and_set_bit()</function>, + <function>test_and_clear_bit()</function> and + <function>test_and_change_bit()</function> do the same thing, + except return true if the bit was previously set; these are + particularly useful for very simple locking. + </para> + + <para> + It is possible to call these operations with bit indices greater + than 31. The resulting behavior is strange on big-endian + platforms though so it is a good idea not to do this. + </para> + </chapter> + + <chapter id="symbols"> + <title>Symbols</title> + + <para> + Within the kernel proper, the normal linking rules apply + (ie. unless a symbol is declared to be file scope with the + <type>static</type> keyword, it can be used anywhere in the + kernel). However, for modules, a special exported symbol table is + kept which limits the entry points to the kernel proper. Modules + can also export symbols. + </para> + + <sect1 id="sym-exportsymbols"> + <title><function>EXPORT_SYMBOL()</function> + <filename class=headerfile>include/linux/module.h</filename></title> + + <para> + This is the classic method of exporting a symbol, and it works + for both modules and non-modules. In the kernel all these + declarations are often bundled into a single file to help + genksyms (which searches source files for these declarations). + See the comment on genksyms and Makefiles below. + </para> + </sect1> + + <sect1 id="sym-exportsymtab"> + <title><function>EXPORT_SYMTAB</function></title> + + <para> + For convenience, a module usually exports all non-file-scope + symbols (ie. all those not declared <type>static</type>). If this + is defined before + + <filename class=headerfile>include/linux/module.h</filename> is + included, then only symbols explicit exported with + <function>EXPORT_SYMBOL()</function> will be exported. + </para> + </sect1> + </chapter> + + <chapter id="conventions"> + <title>Routines and Conventions</title> + + <sect1 id="conventions-doublelinkedlist"> + <title>Double-linked lists + <filename class=headerfile>include/linux/list.h</filename></title> + + <para> + There are three sets of linked-list routines in the kernel + headers, but this one seems to be winning out (and Linus has + used it). If you don't have some particular pressing need for + a single list, it's a good choice. In fact, I don't care + whether it's a good choice or not, just use it so we can get + rid of the others. + </para> + </sect1> + + <sect1 id="convention-returns"> + <title>Return Conventions</title> + + <para> + For code called in user context, it's very common to defy C + convention, and return <returnvalue>0</returnvalue> for success, + and a negative error number + (eg. <returnvalue>-EFAULT</returnvalue>) for failure. This can be + unintuitive at first, but it's fairly widespread in the networking + code, for example. + </para> + + <para> + The filesystem code uses <function>ERR_PTR()</function> + + <filename class=headerfile>include/linux/fs.h</filename>; to + encode a negative error number into a pointer, and + <function>IS_ERR()</function> and <function>PTR_ERR()</function> + to get it back out again: avoids a separate pointer parameter for + the error number. Icky, but in a good way. + </para> + </sect1> + + <sect1 id="conventions-borkedcompile"> + <title>Breaking Compilation</title> + + <para> + Linus and the other developers sometimes change function or + structure names in development kernels; this is not done just to + keep everyone on their toes: it reflects a fundamental change + (eg. can no longer be called with interrupts on, or does extra + checks, or doesn't do checks which were caught before). Usually + this is accompanied by a fairly complete note to the linux-kernel + mailing list; search the archive. Simply doing a global replace + on the file usually makes things <emphasis>worse</emphasis>. + </para> + </sect1> + + <sect1 id="conventions-initialising"> + <title>Initializing structure members</title> + + <para> + The preferred method of initializing structures is to use the + gcc Labeled Elements extension, eg: + </para> + <programlisting> +static struct block_device_operations opt_fops = { + open: opt_open, + release: opt_release, + ioctl: opt_ioctl, + check_media_change: opt_media_change, +}; + </programlisting> + + <para> + This makes it easy to grep for, and makes it clear which + structure fields are set. You should do this because it looks + cool. + </para> + </sect1> + + <sect1 id="conventions-gnu-extns"> + <title>GNU Extensions</title> + + <para> + GNU Extensions are explicitly allowed in the Linux kernel. + Note that some of the more complex ones are not very well + supported, due to lack of general use, but the following are + considered standard (see the GCC info page section "C + Extensions" for more details - Yes, really the info page, the + man page is only a short summary of the stuff in info): + </para> + <itemizedlist> + <listitem> + <para> + Inline functions + </para> + </listitem> + <listitem> + <para> + Statement expressions (ie. the ({ and }) constructs). + </para> + </listitem> + <listitem> + <para> + Declaring attributes of a function / variable / type + (__attribute__) + </para> + </listitem> + <listitem> + <para> + Labeled elements + </para> + </listitem> + <listitem> + <para> + typeof + </para> + </listitem> + <listitem> + <para> + Zero length arrays + </para> + </listitem> + <listitem> + <para> + Macro varargs + </para> + </listitem> + <listitem> + <para> + Arithmetic on void pointers + </para> + </listitem> + <listitem> + <para> + Non-Constant initializers + </para> + </listitem> + <listitem> + <para> + Assembler Instructions (not outside arch/ and include/asm/) + </para> + </listitem> + <listitem> + <para> + Function names as strings (__FUNCTION__) + </para> + </listitem> + <listitem> + <para> + __builtin_constant_p() + </para> + </listitem> + </itemizedlist> + + <para> + Be wary when using long long in the kernel, the code gcc generates for + it is horrible and worse: division and multiplication does not work + on i386 because the GCC runtime functions for it are missing from + the kernel environment. + </para> + + <!-- FIXME: add a note about ANSI aliasing cleanness --> + </sect1> + + <sect1 id="conventions-cplusplus"> + <title>C++</title> + + <para> + Using C++ in the kernel is usually a bad idea, because the + kernel does not provide the necessary runtime environment + and the include files are not tested for it. It is still + possible, but not recommended. If you really want to do + this, forget about exceptions at least. + </para> + </sect1> + + <sect1 id="conventions-ifdef"> + <title>#if</title> + + <para> + It is generally considered cleaner to use macros in header files + (or at the top of .c files) to abstract away functions rather than + using `#if' pre-processor statements throughout the source code. + </para> + </sect1> + </chapter> + + <chapter id="submitting"> + <title>Putting Your Stuff in the Kernel</title> + + <para> + In order to get your stuff into shape for official inclusion, or + even to make a neat patch, there's administrative work to be + done: + </para> + <itemizedlist> + <listitem> + <para> + Figure out whose pond you've been pissing in. Look at the top of + the source files, inside the <filename>MAINTAINERS</filename> + file, and last of all in the <filename>CREDITS</filename> file. + You should coordinate with this person to make sure you're not + duplicating effort, or trying something that's already been + rejected. + </para> + + <para> + Make sure you put your name and EMail address at the top of + any files you create or mangle significantly. This is the + first place people will look when they find a bug, or when + <emphasis>they</emphasis> want to make a change. + </para> + </listitem> + + <listitem> + <para> + Usually you want a configuration option for your kernel hack. + Edit <filename>Config.in</filename> in the appropriate directory + (but under <filename>arch/</filename> it's called + <filename>config.in</filename>). The Config Language used is not + bash, even though it looks like bash; the safe way is to use only + the constructs that you already see in + <filename>Config.in</filename> files (see + <filename>Documentation/kbuild/config-language.txt</filename>). + It's good to run "make xconfig" at least once to test (because + it's the only one with a static parser). + </para> + + <para> + Variables which can be Y or N use <type>bool</type> followed by a + tagline and the config define name (which must start with + CONFIG_). The <type>tristate</type> function is the same, but + allows the answer M (which defines + <symbol>CONFIG_foo_MODULE</symbol> in your source, instead of + <symbol>CONFIG_FOO</symbol>) if <symbol>CONFIG_MODULES</symbol> + is enabled. + </para> + + <para> + You may well want to make your CONFIG option only visible if + <symbol>CONFIG_EXPERIMENTAL</symbol> is enabled: this serves as a + warning to users. There many other fancy things you can do: see + the the various <filename>Config.in</filename> files for ideas. + </para> + </listitem> + + <listitem> + <para> + Edit the <filename>Makefile</filename>: the CONFIG variables are + exported here so you can conditionalize compilation with `ifeq'. + If your file exports symbols then add the names to + <varname>MX_OBJS</varname> or <varname>OX_OBJS</varname> instead + of <varname>M_OBJS</varname> or <varname>O_OBJS</varname>, so + that genksyms will find them. + </para> + </listitem> + + <listitem> + <para> + Document your option in Documentation/Configure.help. Mention + incompatibilities and issues here. <emphasis> Definitely + </emphasis> end your description with <quote> if in doubt, say N + </quote> (or, occasionally, `Y'); this is for people who have no + idea what you are talking about. + </para> + </listitem> + + <listitem> + <para> + Put yourself in <filename>CREDITS</filename> if you've done + something noteworthy, usually beyond a single file (your name + should be at the top of the source files anyway). + <filename>MAINTAINERS</filename> means you want to be consulted + when changes are made to a subsystem, and hear about bugs; it + implies a more-than-passing commitment to some part of the code. + </para> + </listitem> + </itemizedlist> + </chapter> + + <chapter id="cantrips"> + <title>Kernel Cantrips</title> + + <para> + Some favorites from browsing the source. Feel free to add to this + list. + </para> + + <para> + <filename>include/linux/brlock.h:</filename> + </para> + <programlisting> +extern inline void br_read_lock (enum brlock_indices idx) +{ + /* + * This causes a link-time bug message if an + * invalid index is used: + */ + if (idx >= __BR_END) + __br_lock_usage_bug(); + + read_lock(&__brlock_array[smp_processor_id()][idx]); +} + </programlisting> + + <para> + <filename>include/linux/fs.h</filename>: + </para> + <programlisting> +/* + * Kernel pointers have redundant information, so we can use a + * scheme where we can return either an error code or a dentry + * pointer with the same return value. + * + * This should be a per-architecture thing, to allow different + * error and pointer decisions. + */ + #define ERR_PTR(err) ((void *)((long)(err))) + #define PTR_ERR(ptr) ((long)(ptr)) + #define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) +</programlisting> + + <para> + <filename>include/asm-i386/uaccess.h:</filename> + </para> + + <programlisting> +#define copy_to_user(to,from,n) \ + (__builtin_constant_p(n) ? \ + __constant_copy_to_user((to),(from),(n)) : \ + __generic_copy_to_user((to),(from),(n))) + </programlisting> + + <para> + <filename>arch/sparc/kernel/head.S:</filename> + </para> + + <programlisting> +/* + * Sun people can't spell worth damn. "compatability" indeed. + * At least we *know* we can't spell, and use a spell-checker. + */ + +/* Uh, actually Linus it is I who cannot spell. Too much murky + * Sparc assembly will do this to ya. + */ +C_LABEL(cputypvar): + .asciz "compatability" + +/* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */ + .align 4 +C_LABEL(cputypvar_sun4m): + .asciz "compatible" + </programlisting> + + <para> + <filename>arch/sparc/lib/checksum.S:</filename> + </para> + + <programlisting> + /* Sun, you just can't beat me, you just can't. Stop trying, + * give up. I'm serious, I am going to kick the living shit + * out of you, game over, lights out. + */ + </programlisting> + </chapter> + + <chapter id="credits"> + <title>Thanks</title> + + <para> + Thanks to Andi Kleen for the idea, answering my questions, fixing + my mistakes, filling content, etc. Philipp Rumpf for more spelling + and clarity fixes, and some excellent non-obvious points. Werner + Almesberger for giving me a great summary of + <function>disable_irq()</function>, and Jes Sorensen and Andrea + Arcangeli added caveats. Michael Elizabeth Chastain for checking + and adding to the Configure section. <!-- Rusty insisted on this + bit; I didn't do it! --> Telsa Gwynne for teaching me DocBook. + </para> + </chapter> +</book> + diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl new file mode 100644 index 000000000..397e7e954 --- /dev/null +++ b/Documentation/DocBook/kernel-locking.tmpl @@ -0,0 +1,1221 @@ +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]> + +<book id="LKLockingGuide"> + <bookinfo> + <title>Unreliable Guide To Locking</title> + + <authorgroup> + <author> + <firstname>Paul</firstname> + <othername>Rusty</othername> + <surname>Russell</surname> + <affiliation> + <address> + <email>rusty@linuxcare.com</email> + </address> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2000</year> + <holder>Paul Russell</holder> + </copyright> + + <legalnotice> + <para> + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + </para> + + <para> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + </para> + + <para> + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + </para> + + <para> + For more details see the file COPYING in the source + distribution of Linux. + </para> + </legalnotice> + </bookinfo> + + <toc></toc> + <chapter id="intro"> + <title>Introduction</title> + <para> + Welcome, to Rusty's Remarkably Unreliable Guide to Kernel + Locking issues. This document describes the locking systems in + the Linux Kernel as we approach 2.4. + </para> + <para> + It looks like <firstterm linkend="gloss-smp"><acronym>SMP</acronym> + </firstterm> is here to stay; so everyone hacking on the kernel + these days needs to know the fundamentals of concurrency and locking + for SMP. + </para> + + <sect1 id="races"> + <title>The Problem With Concurrency</title> + <para> + (Skip this if you know what a Race Condition is). + </para> + <para> + In a normal program, you can increment a counter like so: + </para> + <programlisting> + very_important_count++; + </programlisting> + + <para> + This is what they would expect to happen: + </para> + + <table> + <title>Expected Results</title> + + <tgroup cols=2 align=left> + + <thead> + <row> + <entry>Instance 1</entry> + <entry>Instance 2</entry> + </row> + </thead> + + <tbody> + <row> + <entry>read very_important_count (5)</entry> + <entry></entry> + </row> + <row> + <entry>add 1 (6)</entry> + <entry></entry> + </row> + <row> + <entry>write very_important_count (6)</entry> + <entry></entry> + </row> + <row> + <entry></entry> + <entry>read very_important_count (6)</entry> + </row> + <row> + <entry></entry> + <entry>add 1 (7)</entry> + </row> + <row> + <entry></entry> + <entry>write very_important_count (7)</entry> + </row> + </tbody> + + </tgroup> + </table> + + <para> + This is what might happen: + </para> + + <table> + <title>Possible Results</title> + + <tgroup cols=2 align=left> + <thead> + <row> + <entry>Instance 1</entry> + <entry>Instance 2</entry> + </row> + </thead> + + <tbody> + <row> + <entry>read very_important_count (5)</entry> + <entry></entry> + </row> + <row> + <entry></entry> + <entry>read very_important_count (5)</entry> + </row> + <row> + <entry>add 1 (6)</entry> + <entry></entry> + </row> + <row> + <entry></entry> + <entry>add 1 (5)</entry> + </row> + <row> + <entry>write very_important_count (6)</entry> + <entry></entry> + </row> + <row> + <entry></entry> + <entry>write very_important_count (6)</entry> + </row> + </tbody> + </tgroup> + </table> + + <para> + This overlap, where what actually happens depends on the + relative timing of multiple tasks, is called a race condition. + The piece of code containing the concurrency issue is called a + critical region. And especially since Linux starting running + on SMP machines, they became one of the major issues in kernel + design and implementation. + </para> + <para> + The solution is to recognize when these simultaneous accesses + occur, and use locks to make sure that only one instance can + enter the critical region at any time. There are many + friendly primitives in the Linux kernel to help you do this. + And then there are the unfriendly primitives, but I'll pretend + they don't exist. + </para> + </sect1> + </chapter> + + <chapter id="locks"> + <title>Two Main Types of Kernel Locks: Spinlocks and Semaphores</title> + + <para> + There are two main types of kernel locks. The fundamental type + is the spinlock + (<filename class=headerfile>include/asm/spinlock.h</filename>), + which is a very simple single-holder lock: if you can't get the + spinlock, you keep trying (spinning) until you can. Spinlocks are + very small and fast, and can be used anywhere. + </para> + <para> + The second type is a semaphore + (<filename class=headerfile>include/asm/semaphore.h</filename>): it + can have more than one holder at any time (the number decided at + initialization time), although it is most commonly used as a + single-holder lock (a mutex). If you can't get a semaphore, + your task will put itself on the queue, and be woken up when the + semaphore is released. This means the CPU will do something + else while you are waiting, but there are many cases when you + simply can't sleep, and so have to use a spinlock instead. + </para> + + <sect1 id="uniprocessor"> + <title>Locks and Uniprocessor Kernels</title> + + <para> + For kernels compiled without <symbol>CONFIG_SMP</symbol>, spinlocks + do not exist at all. This is an excellent design decision: when + no-one else can run at the same time, there is no reason to + have a lock at all. + </para> + + <para> + You should always test your locking code with <symbol>CONFIG_SMP</symbol> + enabled, even if you don't have an SMP test box, because it + will still catch some (simple) kinds of deadlock. + </para> + + <para> + Semaphores still exist, because they are required for + synchronization between <firstterm linkend="gloss-usercontext">user + contexts</firstterm>, as we will see below. + </para> + </sect1> + + <sect1 id="rwlocks"> + <title>Read/Write Lock Variants</title> + + <para> + Both spinlocks and semaphores have read/write variants: + <type>rwlock_t</type> and <structname>struct rw_semaphore</structname>. + These divide users into two classes: the readers and the writers. If + you are only reading the data, you can get a read lock, but to write to + the data you need the write lock. Many people can hold a read lock, + but a writer must be sole holder. + </para> + + <para> + This means much smoother locking if your code divides up + neatly along reader/writer lines. All the discussions below + also apply to read/write variants. + </para> + </sect1> + + <sect1 id="usercontextlocking"> + <title>Locking Only In User Context</title> + + <para> + If you have a data structure which is only ever accessed from + user context, then you can use a simple semaphore + (<filename>linux/asm/semaphore.h</filename>) to protect it. This + is the most trivial case: you initialize the semaphore to the number + of resources available (usually 1), and call + <function>down_interruptible()</function> to grab the semaphore, and + <function>up()</function> to release it. There is also a + <function>down()</function>, which should be avoided, because it + will not return if a signal is received. + </para> + + <para> + Example: <filename>linux/net/core/netfilter.c</filename> allows + registration of new <function>setsockopt()</function> and + <function>getsockopt()</function> calls, with + <function>nf_register_sockopt()</function>. Registration and + de-registration are only done on module load and unload (and boot + time, where there is no concurrency), and the list of registrations + is only consulted for an unknown <function>setsockopt()</function> + or <function>getsockopt()</function> system call. The + <varname>nf_sockopt_mutex</varname> is perfect to protect this, + especially since the setsockopt and getsockopt calls may well + sleep. + </para> + </sect1> + + <sect1 id="lock-user-bh"> + <title>Locking Between User Context and BHs</title> + + <para> + If a <firstterm linkend="gloss-bh">bottom half</firstterm> shares + data with user context, you have two problems. Firstly, the current + user context can be interrupted by a bottom half, and secondly, the + critical region could be entered from another CPU. This is where + <function>spin_lock_bh()</function> + (<filename class=headerfile>include/linux/spinlock.h</filename>) is + used. It disables bottom halves on that CPU, then grabs the lock. + <function>spin_unlock_bh()</function> does the reverse. + </para> + + <para> + This works perfectly for <firstterm linkend="gloss-up"><acronym>UP + </acronym></firstterm> as well: the spin lock vanishes, and this macro + simply becomes <function>local_bh_disable()</function> + (<filename class=headerfile>include/asm/softirq.h</filename>), which + protects you from the bottom half being run. + </para> + </sect1> + + <sect1 id="lock-user-tasklet"> + <title>Locking Between User Context and Tasklets/Soft IRQs</title> + + <para> + This is exactly the same as above, because + <function>local_bh_disable()</function> actually disables all + softirqs and <firstterm linkend="gloss-tasklet">tasklets</firstterm> + on that CPU as well. It should really be + called `local_softirq_disable()', but the name has been preserved + for historical reasons. Similarly, + <function>spin_lock_bh()</function> would now be called + spin_lock_softirq() in a perfect world. + </para> + </sect1> + + <sect1 id="lock-bh"> + <title>Locking Between Bottom Halves</title> + + <para> + Sometimes a bottom half might want to share data with + another bottom half (especially remember that timers are run + off a bottom half). + </para> + + <sect2 id="lock-bh-same"> + <title>The Same BH</title> + + <para> + Since a bottom half is never run on two CPUs at once, you + don't need to worry about your bottom half being run twice + at once, even on SMP. + </para> + </sect2> + + <sect2 id="lock-bh-different"> + <title>Different BHs</title> + + <para> + Since only one bottom half ever runs at a time once, you + don't need to worry about race conditions with other bottom + halves. Beware that things might change under you, however, + if someone changes your bottom half to a tasklet. If you + want to make your code future-proof, pretend you're already + running from a tasklet (see below), and doing the extra + locking. Of course, if it's five years before that happens, + you're gonna look like a damn fool. + </para> + </sect2> + </sect1> + + <sect1 id="lock-tasklets"> + <title>Locking Between Tasklets</title> + + <para> + Sometimes a tasklet might want to share data with another + tasklet, or a bottom half. + </para> + + <sect2 id="lock-tasklets-same"> + <title>The Same Tasklet</title> + <para> + Since a tasklet is never run on two CPUs at once, you don't + need to worry about your tasklet being reentrant (running + twice at once), even on SMP. + </para> + </sect2> + + <sect2 id="lock-tasklets-different"> + <title>Different Tasklets</title> + <para> + If another tasklet (or bottom half, such as a timer) wants + to share data with your tasklet, you will both need to use + <function>spin_lock()</function> and + <function>spin_unlock()</function> calls. + <function>spin_lock_bh()</function> is + unnecessary here, as you are already in a a tasklet, and + none will be run on the same CPU. + </para> + </sect2> + </sect1> + + <sect1 id="lock-softirqs"> + <title>Locking Between Softirqs</title> + + <para> + Often a <firstterm linkend="gloss-softirq">softirq</firstterm> might + want to share data with itself, a tasklet, or a bottom half. + </para> + + <sect2 id="lock-softirqs-same"> + <title>The Same Softirq</title> + + <para> + The same softirq can run on the other CPUs: you can use a + per-CPU array (see <xref linkend="per-cpu">) for better + performance. If you're going so far as to use a softirq, + you probably care about scalable performance enough + to justify the extra complexity. + </para> + + <para> + You'll need to use <function>spin_lock()</function> and + <function>spin_unlock()</function> for shared data. + </para> + </sect2> + + <sect2 id="lock-softirqs-different"> + <title>Different Softirqs</title> + + <para> + You'll need to use <function>spin_lock()</function> and + <function>spin_unlock()</function> for shared data, whether it + be a timer (which can be running on a different CPU), bottom half, + tasklet or the same or another softirq. + </para> + </sect2> + </sect1> + </chapter> + + <chapter id="hardirq-context"> + <title>Hard IRQ Context</title> + + <para> + Hardware interrupts usually communicate with a bottom half, + tasklet or softirq. Frequently this involved putting work in a + queue, which the BH/softirq will take out. + </para> + + <sect1 id="hardirq-softirq"> + <title>Locking Between Hard IRQ and Softirqs/Tasklets/BHs</title> + + <para> + If a hardware irq handler shares data with a softirq, you have + two concerns. Firstly, the softirq processing can be + interrupted by a hardware interrupt, and secondly, the + critical region could be entered by a hardware interrupt on + another CPU. This is where <function>spin_lock_irq()</function> is + used. It is defined to disable interrupts on that cpu, then grab + the lock. <function>spin_unlock_irq()</function> does the reverse. + </para> + + <para> + This works perfectly for UP as well: the spin lock vanishes, + and this macro simply becomes <function>local_irq_disable()</function> + (<filename class=headerfile>include/asm/smp.h</filename>), which + protects you from the softirq/tasklet/BH being run. + </para> + + <para> + <function>spin_lock_irqsave()</function> + (<filename>include/linux/spinlock.h</filename>) is a variant + which saves whether interrupts were on or off in a flags word, + which is passed to <function>spin_lock_irqrestore()</function>. This + means that the same code can be used inside an hard irq handler (where + interrupts are already off) and in softirqs (where the irq + disabling is required). + </para> + </sect1> + </chapter> + + <chapter id="common-techniques"> + <title>Common Techniques</title> + + <para> + This section lists some common dilemmas and the standard + solutions used in the Linux kernel code. If you use these, + people will find your code simpler to understand. + </para> + + <para> + If I could give you one piece of advice: never sleep with anyone + crazier than yourself. But if I had to give you advice on + locking: <emphasis>keep it simple</emphasis>. + </para> + + <para> + Lock data, not code. + </para> + + <para> + Be reluctant to introduce new locks. + </para> + + <para> + Strangely enough, this is the exact reverse of my advice when + you <emphasis>have</emphasis> slept with someone crazier than yourself. + </para> + + <sect1 id="techniques-no-writers"> + <title>No Writers in Interrupt Context</title> + + <para> + There is a fairly common case where an interrupt handler needs + access to a critical region, but does not need write access. + In this case, you do not need to use + <function>read_lock_irq()</function>, but only + <function>read_lock()</function> everywhere (since if an interrupt + occurs, the irq handler will only try to grab a read lock, which + won't deadlock). You will still need to use + <function>write_lock_irq()</function>. + </para> + + <para> + Similar logic applies to locking between softirqs/tasklets/BHs + which never need a write lock, and user context: + <function>read_lock()</function> and + <function>write_lock_bh()</function>. + </para> + </sect1> + + <sect1 id="techniques-deadlocks"> + <title>Deadlock: Simple and Advanced</title> + + <para> + There is a coding bug where a piece of code tries to grab a + spinlock twice: it will spin forever, waiting for the lock to + be released (spinlocks and writelocks are not re-entrant in + Linux). This is trivial to diagnose: not a + stay-up-five-nights-talk-to-fluffy-code-bunnies kind of + problem. + </para> + + <para> + For a slightly more complex case, imagine you have a region + shared by a bottom half and user context. If you use a + <function>spin_lock()</function> call to protect it, it is + possible that the user context will be interrupted by the bottom + half while it holds the lock, and the bottom half will then spin + forever trying to get the same lock. + </para> + + <para> + Both of these are called deadlock, and as shown above, it can + occur even with a single CPU (although not on UP compiles, + since spinlocks vanish on kernel compiles with + <symbol>CONFIG_SMP</symbol>=n. You'll still get data corruption + in the second example). + </para> + + <para> + This complete lockup is easy to diagnose: on SMP boxes the + watchdog timer or compiling with <symbol>DEBUG_SPINLOCKS</symbol> set + (<filename>include/linux/spinlock.h</filename>) will show this up + immediately when it happens. + </para> + + <para> + A more complex problem is the so-called `deadly embrace', + involving two or more locks. Say you have a hash table: each + entry in the table is a spinlock, and a chain of hashed + objects. Inside a softirq handler, you sometimes want to + alter an object from one place in the hash to another: you + grab the spinlock of the old hash chain and the spinlock of + the new hash chain, and delete the object from the old one, + and insert it in the new one. + </para> + + <para> + There are two problems here. First, if your code ever + tries to move the object to the same chain, it will deadlock + with itself as it tries to lock it twice. Secondly, if the + same softirq on another CPU is trying to move another object + in the reverse direction, the following could happen: + </para> + + <table> + <title>Consequences</title> + + <tgroup cols=2 align=left> + + <thead> + <row> + <entry>CPU 1</entry> + <entry>CPU 2</entry> + </row> + </thead> + + <tbody> + <row> + <entry>Grab lock A -> OK</entry> + <entry>Grab lock B -> OK</entry> + </row> + <row> + <entry>Grab lock B -> spin</entry> + <entry>Grab lock A -> spin</entry> + </row> + </tbody> + </tgroup> + </table> + + <para> + The two CPUs will spin forever, waiting for the other to give up + their lock. It will look, smell, and feel like a crash. + </para> + + <sect2 id="techs-deadlock-prevent"> + <title>Preventing Deadlock</title> + + <para> + Textbooks will tell you that if you always lock in the same + order, you will never get this kind of deadlock. Practice + will tell you that this approach doesn't scale: when I + create a new lock, I don't understand enough of the kernel + to figure out where in the 5000 lock hierarchy it will fit. + </para> + + <para> + The best locks are encapsulated: they never get exposed in + headers, and are never held around calls to non-trivial + functions outside the same file. You can read through this + code and see that it will never deadlock, because it never + tries to grab another lock while it has that one. People + using your code don't even need to know you are using a + lock. + </para> + + <para> + A classic problem here is when you provide callbacks or + hooks: if you call these with the lock held, you risk simple + deadlock, or a deadly embrace (who knows what the callback + will do?). Remember, the other programmers are out to get + you, so don't do this. + </para> + </sect2> + + <sect2 id="techs-deadlock-overprevent"> + <title>Overzealous Prevention Of Deadlocks</title> + + <para> + Deadlocks are problematic, but not as bad as data + corruption. Code which grabs a read lock, searches a list, + fails to find what it wants, drops the read lock, grabs a + write lock and inserts the object has a race condition. + </para> + + <para> + If you don't see why, please stay the fuck away from my code. + </para> + </sect2> + </sect1> + + <sect1 id="per-cpu"> + <title>Per-CPU Data</title> + + <para> + A great technique for avoiding locking which is used fairly + widely is to duplicate information for each CPU. For example, + if you wanted to keep a count of a common condition, you could + use a spin lock and a single counter. Nice and simple. + </para> + + <para> + If that was too slow [it's probably not], you could instead + use a counter for each CPU [don't], then none of them need an + exclusive lock [you're wasting your time here]. To make sure + the CPUs don't have to synchronize caches all the time, align + the counters to cache boundaries by appending + `__cacheline_aligned' to the declaration + (<filename class=headerfile>include/linux/cache.h</filename>). + [Can't you think of anything better to do?] + </para> + + <para> + They will need a read lock to access their own counters, + however. That way you can use a write lock to grant exclusive + access to all of them at once, to tally them up. + </para> + </sect1> + + <sect1 id="brlock"> + <title>Big Reader Locks</title> + + <para> + A classic example of per-CPU information is Ingo's `big + reader' locks + (<filename class=headerfile>linux/include/brlock.h</filename>). These + use the Per-CPU Data techniques described above to create a lock which + is very fast to get a read lock, but agonizingly slow for a write + lock. + </para> + + <para> + Fortunately, there are a limited number of these locks + available: you have to go through a strict interview process + to get one. + </para> + </sect1> + + <sect1 id="lock-avoidance-rw"> + <title>Avoiding Locks: Read And Write Ordering</title> + + <para> + Sometimes it is possible to avoid locking. Consider the + following case from the 2.2 firewall code, which inserted an + element into a single linked list in user context: + </para> + + <programlisting> + new->next = i->next; + i->next = new; + </programlisting> + + <para> + Here the author (Alan Cox, who knows what he's doing) assumes + that the pointer assignments are atomic. This is important, + because networking packets would traverse this list on bottom + halves without a lock. Depending on their exact timing, they + would either see the new element in the list with a valid + <structfield>next</structfield> pointer, or it would not be in the + list yet. + </para> + + <para> + Of course, the writes <emphasis>must</emphasis> be in this + order, otherwise the new element appears in the list with an + invalid <structfield>next</structfield> pointer, and any other + CPU iterating at the wrong time will jump through it into garbage. + Because modern CPUs reorder, Alan's code actually read as follows: + </para> + + <programlisting> + new->next = i->next; + wmb(); + i->next = new; + </programlisting> + + <para> + The <function>wmb()</function> is a write memory barrier + (<filename class=headerfile>include/asm/system.h</filename>): neither + the compiler nor the CPU will allow any writes to memory after the + <function>wmb()</function> to be visible to other hardware + before any of the writes before the <function>wmb()</function>. + </para> + + <para> + As i386 does not do write reordering, this bug would never + show up on that platform. On other SMP platforms, however, it + will. + </para> + + <para> + There is also <function>rmb()</function> for read ordering: to ensure + any previous variable reads occur before following reads. The simple + <function>mb()</function> macro combines both + <function>rmb()</function> and <function>wmb()</function>. + </para> + + <para> + Dropping or gaining a spinlock, and any atomic operation are + all defined to act as memory barriers (ie. as per the + <function>mb()</function> macro). + </para> + + <para> + There is a similar, but unrelated, problem with code like the + following: + </para> + + <programlisting> + if (!(ctrack->status & IPS_CONFIRMED)) { + spin_lock_bh(&ip_conntrack_lock); + if (!(ctrack->status & IPS_CONFIRMED)) { + clean_from_lists(h->ctrack); + h->ctrack->status |= IPS_CONFIRMED; + } + spin_unlock_bh(&ip_conntrack_lock); + } + </programlisting> + + <para> + In this case, the author has tried to be tricky: knowing that + the CONFIRMED bit is set and never reset in the status word, + you can test it outside the lock, and frequently avoid + grabbing the lock at all. However, the compiler could cache + the value in a register, rather than rereading it once the + lock is obtained, creating a subtle race. The way to get + around this is to declare the status field `volatile', or use + a temporary volatile pointer to achieve the same effect in + this one place. + </para> + </sect1> + + <sect1 id="lock-avoidance-atomic-ops"> + <title>Avoiding Locks: Atomic Operations</title> + + <para> + There are a number of atomic operations defined in + <filename class=headerfile>include/asm/atomic.h</filename>: these + are guaranteed to be seen atomically from all CPUs in the system, thus + avoiding races. If your shared data consists of a single counter, say, + these operations might be simpler than using spinlocks (although for + anything non-trivial using spinlocks is clearer). + </para> + + <para> + Note that the atomic operations are defined to act as both + read and write barriers on all platforms. + </para> + </sect1> + + <sect1 id="ref-counts"> + <title>Protecting A Collection of Objects: Reference Counts</title> + + <para> + Locking a collection of objects is fairly easy: you get a + single spinlock, and you make sure you grab it before + searching, adding or deleting an object. + </para> + + <para> + The purpose of this lock is not to protect the individual + objects: you might have a separate lock inside each one for + that. It is to protect the <emphasis>data structure + containing the objects</emphasis> from race conditions. Often + the same lock is used to protect the contents of all the + objects as well, for simplicity, but they are inherently + orthogonal (and many other big words designed to confuse). + </para> + + <para> + Changing this to a read-write lock will often help markedly if + reads are far more common that writes. If not, there is + another approach you can use to reduce the time the lock is + held: reference counts. + </para> + + <para> + In this approach, an object has an owner, who sets the + reference count to one. Whenever you get a pointer to the + object, you increment the reference count (a `get' operation). + Whenever you relinquish a pointer, you decrement the reference + count (a `put' operation). When the owner wants to destroy + it, they mark it dead, and do a put. + </para> + + <para> + Whoever drops the reference count to zero (usually implemented + with <function>atomic_dec_and_test()</function>) actually cleans + up and frees the object. + </para> + + <para> + This means that you are guaranteed that the object won't + vanish underneath you, even though you no longer have a lock + for the collection. + </para> + + <para> + Here's some skeleton code: + </para> + + <programlisting> + void create_foo(struct foo *x) + { + atomic_set(&x->use, 1); + spin_lock_bh(&list_lock); + ... insert in list ... + spin_unlock_bh(&list_lock); + } + + struct foo *get_foo(int desc) + { + struct foo *ret; + + spin_lock_bh(&list_lock); + ... find in list ... + if (ret) atomic_inc(&ret->use); + spin_unlock_bh(&list_lock); + + return ret; + } + + void put_foo(struct foo *x) + { + if (atomic_dec_and_test(&x->use)) + kfree(foo); + } + + void destroy_foo(struct foo *x) + { + spin_lock_bh(&list_lock); + ... remove from list ... + spin_unlock_bh(&list_lock); + + put_foo(x); + } + </programlisting> + + <sect2 id="helpful-macros"> + <title>Macros To Help You</title> + <para> + There are a set of debugging macros tucked inside + <filename class=headerfile>include/linux/netfilter_ipv4/lockhelp.h</filename> + and <filename class=headerfile>listhelp.h</filename>: these are very + useful for ensuring that locks are held in the right places to protect + infrastructure. + </para> + </sect2> + </sect1> + + <sect1 id="sleeping-things"> + <title>Things Which Sleep</title> + + <para> + You can never call the following routines while holding a + spinlock, as they may sleep: + </para> + + <itemizedlist> + <listitem> + <para> + Accesses to + <firstterm linkend="gloss-userspace">userspace</firstterm>: + </para> + <itemizedlist> + <listitem> + <para> + <function>copy_from_user()</function> + </para> + </listitem> + <listitem> + <para> + <function>copy_to_user()</function> + </para> + </listitem> + <listitem> + <para> + <function>get_user()</function> + </para> + </listitem> + <listitem> + <para> + <function> put_user()</function> + </para> + </listitem> + </itemizedlist> + </listitem> + + <listitem> + <para> + <function>kmalloc(GFP_KERNEL)</function> + </para> + </listitem> + + <listitem> + <para> + <function>printk()</function>, which can be called from + user context, interestingly enough. + </para> + </listitem> + </itemizedlist> + </sect1> + + <sect1 id="sparc"> + <title>The Fucked Up Sparc</title> + + <para> + Alan Cox says <quote>the irq disable/enable is in the register + window on a sparc</quote>. Andi Kleen says <quote>when you do + restore_flags in a different function you mess up all the + register windows</quote>. + </para> + + <para> + So never pass the flags word set by + <function>spin_lock_irqsave()</function> and brethren to another + function (unless it's declared <type>inline</type>. Usually no-one + does this, but now you've been warned. Dave Miller can never do + anything in a straightforward manner (I can say that, because I have + pictures of him and a certain PowerPC maintainer in a compromising + position). + </para> + </sect1> + + <sect1 id="racing-timers"> + <title>Racing Timers: A Kernel Pastime</title> + + <para> + Timers can produce their own special problems with races. + Consider a collection of objects (list, hash, etc) where each + object has a timer which is due to destroy it. + </para> + + <para> + If you want to destroy the entire collection (say on module + removal), you might do the following: + </para> + + <programlisting> + /* THIS CODE BAD BAD BAD BAD: IF IT WAS ANY WORSE IT WOULD USE + HUNGARIAN NOTATION */ + spin_lock_bh(&list_lock); + + while (list) { + struct foo *next = list->next; + del_timer(&list->timer); + kfree(list); + list = next; + } + + spin_unlock_bh(&list_lock); + </programlisting> + + <para> + Sooner or later, this will crash on SMP, because a timer can + have just gone off before the <function>spin_lock_bh()</function>, + and it will only get the lock after we + <function>spin_unlock_bh()</function>, and then try to free + the element (which has already been freed!). + </para> + + <para> + This can be avoided by checking the result of + <function>del_timer()</function>: if it returns + <returnvalue>1</returnvalue>, the timer has been deleted. + If <returnvalue>0</returnvalue>, it means (in this + case) that it is currently running, so we can do: + </para> + + <programlisting> + retry: + spin_lock_bh(&list_lock); + + while (list) { + struct foo *next = list->next; + if (!del_timer(&list->timer)) { + /* Give timer a chance to delete this */ + spin_unlock_bh(&list_lock); + goto retry; + } + kfree(list); + list = next; + } + + spin_unlock_bh(&list_lock); + </programlisting> + + <para> + Another common problem is deleting timers which restart + themselves (by calling <function>add_timer()</function> at the end + of their timer function). Because this is a fairly common case + which is prone to races, the function <function>del_timer_sync()</function> + (<filename class=headerfile>include/linux/timer.h</filename>) is + provided to handle this case. It returns the number of times the timer + had to be deleted before we finally stopped it from adding itself back + in. + </para> + </sect1> + </chapter> + + <chapter id="references"> + <title>Further reading</title> + + <itemizedlist> + <listitem> + <para> + <filename>Documentation/spinlocks.txt</filename>: + Linus Torvalds' spinlocking tutorial in the kernel sources. + </para> + </listitem> + + <listitem> + <para> + Unix Systems for Modern Architectures: Symmetric + Multiprocessing and Caching for Kernel Programmers: + </para> + + <para> + Curt Schimmel's very good introduction to kernel level + locking (not written for Linux, but nearly everything + applies). The book is expensive, but really worth every + penny to understand SMP locking. [ISBN: 0201633388] + </para> + </listitem> + </itemizedlist> + </chapter> + + <chapter id="thanks"> + <title>Thanks</title> + + <para> + Thanks to Telsa Gwynne for DocBooking, neatening and adding + style. + </para> + + <para> + Thanks to Martin Pool, Philipp Rumpf, Stephen Rothwell, Paul + Mackerras, Ruedi Aschwanden, Alan Cox for proofreading, + correcting, flaming, commenting. + </para> + + <para> + Thanks to the cabal for having no influence on this document. + </para> + </chapter> + + <glossary id="glossary"> + <title>Glossary</title> + + <glossentry id="gloss-bh"> + <glossterm>bh</glossterm> + <glossdef> + <para> + Bottom Half: for historical reasons, functions with + `_bh' in them often now refer to any software interrupt, e.g. + <function>spin_lock_bh()</function> blocks any software interrupt + on the current CPU. Bottom halves are deprecated, and will + eventually be replaced by tasklets. Only one bottom half will be + running at any time. + </para> + </glossdef> + </glossentry> + + <glossentry id="gloss-hwinterrupt"> + <glossterm>Hardware Interrupt / Hardware IRQ</glossterm> + <glossdef> + <para> + Hardware interrupt request. <function>in_irq()</function> returns + <returnvalue>true</returnvalue> in a hardware interrupt handler (it + also returns true when interrupts are blocked). + </para> + </glossdef> + </glossentry> + + <glossentry id="gloss-interruptcontext"> + <glossterm>Interrupt Context</glossterm> + <glossdef> + <para> + Not user context: processing a hardware irq or software irq. + Indicated by the <function>in_interrupt()</function> macro + returning <returnvalue>true</returnvalue> (although it also + returns true when interrupts or BHs are blocked). + </para> + </glossdef> + </glossentry> + + <glossentry id="gloss-smp"> + <glossterm><acronym>SMP</acronym></glossterm> + <glossdef> + <para> + Symmetric Multi-Processor: kernels compiled for multiple-CPU + machines. (CONFIG_SMP=y). + </para> + </glossdef> + </glossentry> + + <glossentry id="gloss-softirq"> + <glossterm>softirq</glossterm> + <glossdef> + <para> + Strictly speaking, one of up to 32 enumerated software + interrupts which can run on multiple CPUs at once. + Sometimes used to refer to tasklets and bottom halves as + well (ie. all software interrupts). + </para> + </glossdef> + </glossentry> + + <glossentry id="gloss-swinterrupt"> + <glossterm>Software Interrupt / Software IRQ</glossterm> + <glossdef> + <para> + Software interrupt handler. <function>in_irq()</function> returns + <returnvalue>false</returnvalue>; <function>in_softirq()</function> + returns <returnvalue>true</returnvalue>. Tasklets, softirqs and + bottom halves all fall into the category of `software interrupts'. + </para> + </glossdef> + </glossentry> + + <glossentry id="gloss-tasklet"> + <glossterm>tasklet</glossterm> + <glossdef> + <para> + A dynamically-registrable software interrupt, + which is guaranteed to only run on one CPU at a time. + </para> + </glossdef> + </glossentry> + + <glossentry id="gloss-up"> + <glossterm><acronym>UP</acronym></glossterm> + <glossdef> + <para> + Uni-Processor: Non-SMP. (CONFIG_SMP=n). + </para> + </glossdef> + </glossentry> + + <glossentry id="gloss-usercontext"> + <glossterm>User Context</glossterm> + <glossdef> + <para> + The kernel executing on behalf of a particular + process or kernel thread (given by the <function>current()</function> + macro.) Not to be confused with userspace. Can be interrupted by + software or hardware interrupts. + </para> + </glossdef> + </glossentry> + + <glossentry id="gloss-userspace"> + <glossterm>Userspace</glossterm> + <glossdef> + <para> + A process executing its own code outside the kernel. + </para> + </glossdef> + </glossentry> + + </glossary> +</book> + diff --git a/Documentation/DocBook/parportbook.tmpl b/Documentation/DocBook/parportbook.tmpl index 1644748ad..bf4d77873 100644 --- a/Documentation/DocBook/parportbook.tmpl +++ b/Documentation/DocBook/parportbook.tmpl @@ -1,8 +1,9 @@ +<!-- -*- sgml -*- --> <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]> <book id="ParportGuide"> <bookinfo> - <title>The Parallel Port Subsystem</title> + <title>The Linux 2.4 Parallel Port Subsystem</title> <authorgroup> <author> @@ -51,90 +52,97 @@ </legalnotice> </bookinfo> -<toc></toc> + <toc></toc> -<chapter id="design"> -<title>Design goals</title> + <chapter id="design"> + <title>Design goals</title> -<sect1> -<title>The problems</title> + <sect1> + <title>The problems</title> -<!-- Short-comings --> -<!-- How they are addressed --> + <para> + The first parallel port support for Linux came with the line + printer driver, <literal>lp</literal>. The printer driver is a + character special device, and (in Linux 2.0) had support for + writing, via <function>write</function>, and configuration and + statistics reporting via <function>ioctl</function>. + </para> -<!-- Short-comings - - simplistic lp driver - - platform differences - - no support for Zip drive pass-through - - no support for readback? When did Carsten add it? - - more parallel port devices. Figures? - - IEEE 1284 transfer modes: no advanced modes - --> + <para> + The printer driver could be used on any computer that had an IBM + PC-compatible parallel port. Because some architectures have + parallel ports that aren't really the same as PC-style ports, + other variants of the printer driver were written in order to + support Amiga and Atari parallel ports. + </para> -<para>The first parallel port support for Linux came with the line -printer driver, <filename>lp</filename>. The printer driver is a -character special device, and (in Linux 2.0) had support for writing, -via <function>write</function>, and configuration and statistics -reporting via <function>ioctl</function>.</para> - -<para>The printer driver could be used on any computer that had an IBM -PC-compatible parallel port. Because some architectures have parallel -ports that aren't really the same as PC-style ports, other variants of -the printer driver were written in order to support Amiga and Atari -parallel ports.</para> - -<para>When the Iomega Zip drive was released, and a driver written for -it, a problem became apparent. The Zip drive is a parallel port -device that provides a parallel port of its own---it is designed to -sit between a computer and an attached printer, with the printer -plugged into the Zip drive, and the Zip drive plugged into the -computer.</para> - -<para>The problem was that, although printers and Zip drives were both -supported, for any given port only one could be used at a time. Only -one of the two drivers could be present in the kernel at once. This -was because of the fact that both drivers wanted to drive the same -hardware---the parallel port. When the printer driver initialised, it -would call the <function>check_region</function> function to make sure -that the IO region associated with the parallel port was free, and -then it would call <function>request_region</function> to allocate it. -The Zip drive used the same mechanism. Whichever driver initialised -first would gain exclusive control of the parallel port.</para> - -<para>The only way around this problem at the time was to make sure -that both drivers were available as loadable kernel modules. To use -the printer, load the printer driver module; then for the Zip drive, -unload the printer driver module and load the Zip driver -module.</para> - -<para>The net effect was that printing a document that was stored on a Zip -drive was a bit of an ordeal, at least if the Zip drive and printer -shared a parallel port. A better solution was needed.</para> - -<para>Zip drives are not the only devices that presented problems for -Linux. There are other devices with pass-through ports, for example -parallel port CD-ROM drives. There are also printers that report -their status textually rather than using simple error pins: sending a -command to the printer can cause it to report the number of pages that -it has ever printed, or how much free memory it has, or whether it is -running out of toner, and so on. The printer driver didn't originally -offer any facility for reading back this information (although Carsten -Gross added nibble mode readback support for kernel 2.2).</para> - -<!-- IEEE 1284 transfer modes: no advanced modes --> - -<para>The IEEE has issued a standards document called IEEE 1284, which -documents existing practice for parallel port communications in a -variety of modes. Those modes are: <quote>compatibility</quote>, -reverse nibble, reverse byte, ECP and EPP. Newer devices often use -the more advanced modes of transfer (ECP and EPP). In Linux 2.0, the -printer driver only supported <quote>compatibility mode</quote> -(i.e. normal printer protocol) and reverse nibble mode.</para> - -</sect1> - -<sect1> -<title>The solutions</title> + <para> + When the Iomega Zip drive was released, and a driver written for + it, a problem became apparent. The Zip drive is a parallel port + device that provides a parallel port of its own---it is designed + to sit between a computer and an attached printer, with the + printer plugged into the Zip drive, and the Zip drive plugged into + the computer. + </para> + + <para> + The problem was that, although printers and Zip drives were both + supported, for any given port only one could be used at a time. + Only one of the two drivers could be present in the kernel at + once. This was because of the fact that both drivers wanted to + drive the same hardware---the parallel port. When the printer + driver initialised, it would call the + <function>check_region</function> function to make sure that the + IO region associated with the parallel port was free, and then it + would call <function>request_region</function> to allocate it. + The Zip drive used the same mechanism. Whichever driver + initialised first would gain exclusive control of the parallel + port. + </para> + + <para> + The only way around this problem at the time was to make sure that + both drivers were available as loadable kernel modules. To use + the printer, load the printer driver module; then for the Zip + drive, unload the printer driver module and load the Zip driver + module. + </para> + + <para> + The net effect was that printing a document that was stored on a + Zip drive was a bit of an ordeal, at least if the Zip drive and + printer shared a parallel port. A better solution was + needed. + </para> + + <para> + Zip drives are not the only devices that presented problems for + Linux. There are other devices with pass-through ports, for + example parallel port CD-ROM drives. There are also printers that + report their status textually rather than using simple error pins: + sending a command to the printer can cause it to report the number + of pages that it has ever printed, or how much free memory it has, + or whether it is running out of toner, and so on. The printer + driver didn't originally offer any facility for reading back this + information (although Carsten Gross added nibble mode readback + support for kernel 2.2). + </para> + + <para> + The IEEE has issued a standards document called IEEE 1284, which + documents existing practice for parallel port communications in a + variety of modes. Those modes are: <quote>compatibility</quote>, + reverse nibble, reverse byte, ECP and EPP. Newer devices often + use the more advanced modes of transfer (ECP and EPP). In Linux + 2.0, the printer driver only supported <quote>compatibility + mode</quote> (i.e. normal printer protocol) and reverse nibble + mode. + </para> + + </sect1> + + <sect1> + <title>The solutions</title> <!-- How they are addressed - sharing model @@ -143,1396 +151,1798 @@ printer driver only supported <quote>compatibility mode</quote> - whether or not 'platform independence' goal was met --> -<para>The <filename>parport</filename> code in Linux 2.2 was designed -to meet these problems of architectural differences in parallel ports, -of port-sharing between devices with pass-through ports, and of lack -of support for IEEE 1284 transfer modes.</para> - -<!-- platform differences --> - -<para>There are two layers to the -<filename>parport</filename> subsystem, only one of which deals -directly with the hardware. The other layer deals with sharing and -IEEE 1284 transfer modes. In this way, parallel support for a -particular architecture comes in the form of a module which registers -itself with the generic sharing layer.</para> - -<!-- sharing model --> - -<para>The sharing model provided by the <filename>parport</filename> -subsystem is one of exclusive access. A device driver, such as the -printer driver, must ask the <filename>parport</filename> layer for -access to the port, and can only use the port once access has been -granted. When it has finished a <quote>transaction</quote>, it can -tell the <filename>parport</filename> layer that it may release the -port for other device drivers to use.</para> - -<!-- talk a bit about how drivers can share devices on the same port --> - -<para>Devices with pass-through ports all manage to share a parallel -port with other devices in generally the same way. The device has a -latch for each of the pins on its pass-through port. The normal state -of affairs is pass-through mode, with the device copying the signal -lines between its host port and its pass-through port. When the -device sees a special signal from the host port, it latches the -pass-through port so that devices further downstream don't get -confused by the pass-through device's conversation with the host -parallel port: the device connected to the pass-through port (and any -devices connected in turn to it) are effectively cut off from the -computer. When the pass-through device has completed its transaction -with the computer, it enables the pass-through port again.</para> - -<mediaobject> -<imageobject> -<imagedata Align=center scalefit=1 fileref="parport-share.eps"> -</imageobject> -</mediaobject> - -<para>This technique relies on certain <quote>special signals</quote> -being invisible to devices that aren't watching for them. This tends -to mean only changing the data signals and leaving the control signals -alone. IEEE 1284.3 documents a standard protocol for daisy-chaining -devices together with parallel ports.</para> - -<!-- transfer modes --> - -<para>Support for standard transfer modes are provided as operations -that can be performed on a port, along with operations for setting the -data lines, or the control lines, or reading the status lines. These -operations appear to the device driver as function pointers; more -later.</para> - -</sect1> - -</chapter> - -<chapter id="transfermodes"> -<title>Standard transfer modes</title> - -<!-- Defined by IEEE, but in common use (even though there are widely --> -<!-- varying implementations). --> - -<para>The <quote>standard</quote> transfer modes in use over the -parallel port are <quote>defined</quote> by a document called IEEE -1284. It really just codifies existing practice and documents -protocols (and variations on protocols) that have been in common use -for quite some time.</para> - -<para>The original definitions of which pin did what were set out by -Centronics Data Computer Corporation, but only the printer-side -interface signals were specified.</para> - -<para>By the early 1980s, IBM's host-side implementation had become -the most widely used. New printers emerged that claimed Centronics -compatibility, but although compatible with Centronics they differed -from one another in a number of ways.</para> - -<para>As a result of this, when IEEE 1284 was published in 1994, all -that it could really do was document the various protocols that are -used for printers (there are about six variations on a theme).</para> - -<para>In addition to the protocol used to talk to -Centronics-compatible printers, IEEE 1284 defined other protocols that -are used for unidirectional peripheral-to-host transfers (reverse -nibble and reverse byte) and for fast bidirectional transfers (ECP and -EPP).</para> - -</chapter> - -<chapter id="structure"> -<title>Structure</title> + <para> + The <literal>parport</literal> code in Linux 2.2 was designed to + meet these problems of architectural differences in parallel + ports, of port-sharing between devices with pass-through ports, + and of lack of support for IEEE 1284 transfer modes. + </para> -<!-- Main structure - - sharing core - - parports and their IEEE 1284 overrides - - IEEE 1284 transfer modes for generic ports - - maybe mention muxes here - - pardevices - - IEEE 1284.3 API - --> + <!-- platform differences --> -<!-- Diagram --> - -<mediaobject> -<imageobject> -<imagedata Align=Center ScaleFit=1 fileref="parport-structure.eps"> -</imageobject> -</mediaobject> - -<sect1> -<title>Sharing core</title> - -<!-- sharing core --> - -<para>At the core of the <filename>parport</filename> subsystem is the -sharing mechanism (see <filename>drivers/parport/share.c</filename>). -This module, <filename>parport</filename>, is responsible for -keeping track of which ports there are in the system, which device -drivers might be interested in new ports, and whether or not each port -is available for use (or if not, which driver is currently using -it).</para> - -</sect1> - -<sect1> -<title>Parports and their overrides</title> -<!-- parports and their overrides --> - -<para>The generic <filename>parport</filename> sharing code doesn't -directly handle the parallel port hardware. That is done instead by -<quote>low-level</quote> <filename>parport</filename> drivers. The -function of a low-level <filename>parport</filename> driver is to -detect parallel ports, register them with the sharing code, and -provide a list of access functions for each port.</para> - -<para>The most basic access functions that must be provided are ones -for examining the status lines, for setting the control lines, and for -setting the data lines. There are also access functions for setting -the direction of the data lines; normally they are in the -<quote>forward</quote> direction (that is, the computer drives them), -but some ports allow switching to <quote>reverse</quote> mode (driven -by the peripheral). There is an access function for examining the -data lines once in reverse mode.</para> - -</sect1> - -<sect1> -<title>IEEE 1284 transfer modes</title> -<!-- IEEE 1284 transfer modes --> - -<para>Stacked on top of the sharing mechanism, but still in the -<filename>parport</filename> module, are functions for transferring -data. They are provided for the device drivers to use, and are very -much like library routines. Since these transfer functions are -provided by the generic <filename>parport</filename> core they must -use the <quote>lowest common denominator</quote> set of access -functions: they can set the control lines, examine the status lines, -and use the data lines. With some parallel ports the data lines can -only be set and not examined, and with other ports accessing the data -register causes control line activity; with these types of situations, -the IEEE 1284 transfer functions make a best effort attempt to do the -right thing. In some cases, it is not physically possible to use -particular IEEE 1284 transfer modes.</para> - -<para>The low-level <filename>parport</filename> drivers also provide -IEEE 1284 transfer functions, as names in the access function list. -The low-level driver can just name the generic IEEE 1284 transfer -functions for this. Some parallel ports can do IEEE 1284 transfers in -hardware; for those ports, the low-level driver can provide functions -to utilise that feature.</para> - -</sect1> - -<!-- muxes? --> - -<!-- pardevices and pardrivers --> - -<sect1> -<title>Pardevices and parport_drivers</title> - -<para>When a parallel port device driver (such as -<filename>lp</filename>) initialises it tells the sharing layer about -itself using <function>parport_register_driver</function>. The -information is put into a <structname>struct -parport_driver</structname>, which is put into a linked list. The -information in a <structname>struct parport_driver</structname> really -just amounts to some function pointers to callbacks in the parallel -port device driver.</para> - -<para>During its initialisation, a low-level port driver tells the -sharing layer about all the ports that it has found (using -<function>parport_register_port</function>), and the sharing layer -creates a <structname>struct parport</structname> for each of them. -Each <structname>struct parport</structname> contains (among other -things) a pointer to a <structname>struct -parport_operations</structname>, which is a list of function pointers -for the various operations that can be performed on a port. You can -think of a <structname>struct parport</structname> as a parallel port -<quote>object</quote>, if <quote>object-orientated</quote> programming -is your thing. The <structname>parport</structname> structures are -chained in a linked list, whose head is <varname>portlist</varname> -(in <filename>drivers/parport/share.c</filename>).</para> - -<para>Once the port has been registered, the low-level port driver -announces it. The <function>parport_announce_port</function> function -walks down the list of parallel port device drivers -(<structname>struct parport_driver</structname>s) calling the -<function>attach</function> function of each.</para> - -<para>Similarly, a low-level port driver can undo the effect of -registering a port with the -<function>parport_unregister_port</function> function, and device -drivers are notified using the <function>detach</function> -callback.</para> - -<para>Device drivers can undo the effect of registering themselves -with the <function>parport_unregister_driver</function> -function.</para> - -</sect1> - -<!-- IEEE 1284.3 API --> - -<sect1> -<title>The IEEE 1284.3 API</title> - -<para>The ability to daisy-chain devices is very useful, but if every -device does it in a different way it could lead to lots of -complications for device driver writers. Fortunately, the IEEE are -standardising it in IEEE 1284.3, which covers daisy-chain devices and -port multiplexors.</para> - -<para>At the time of writing, IEEE 1284.3 has not been published, but -the draft specifies the on-the-wire protocol for daisy-chaining and -multiplexing, and also suggests a programming interface for using it. -That interface (or most of it) has been implemented in the -<filename>parport</filename> code in Linux.</para> - -<para>At initialisation of the parallel port <quote>bus</quote>, daisy-chained -devices are assigned addresses starting from zero. There can only be -four devices with daisy-chain addresses, plus one device on the end -that doesn't know about daisy-chaining and thinks it's connected -directly to a computer.</para> - -<para>Another way of connecting more parallel port devices is to use a -multiplexor. The idea is to have a device that is connected directly -to a parallel port on a computer, but has a number of parallel ports -on the other side for other peripherals to connect to (two or four -ports are allowed). The multiplexor switches control to different -ports under software control---it is, in effect, a programmable -printer switch.</para> - -<para>Combining the ability of daisy-chaining five devices together -with the ability to multiplex one parallel port between four gives the -potential to have twenty peripherals connected to the same parallel -port!</para> - -<para>In addition, of course, a single computer can have multiple -parallel ports. So, each parallel port peripheral in the system can -be identified with three numbers, or co-ordinates: the parallel port, -the multiplexed port, and the daisy-chain address.</para> - -<mediaobject> -<imageobject> -<imagedata align=center scalefit=1 fileref="parport-multi.eps"> -</imageobject> -</mediaobject> - -<!-- x parport_open --> -<!-- x parport_close --> -<!-- x parport_device_id --> -<!-- x parport_device_num --> -<!-- x parport_device_coords --> -<!-- x parport_find_device --> -<!-- x parport_find_class --> - -<para>Each device in the system is numbered at initialisation (by -<function>parport_daisy_init</function>). You can convert between -this device number and its co-ordinates with -<function>parport_device_num</function> and -<function>parport_device_coords</function>.</para> - -<funcsynopsis><funcprototype> - <funcdef>int <function>parport_device_num</function></funcdef> - <paramdef>int <parameter>parport</parameter></paramdef> - <paramdef>int <parameter>mux</parameter></paramdef> - <paramdef>int <parameter>daisy</parameter></paramdef> -</funcprototype></funcsynopsis> - -<funcsynopsis><funcprototype> - <funcdef>int <function>parport_device_coords</function></funcdef> - <paramdef>int <parameter>devnum</parameter></paramdef> - <paramdef>int *<parameter>parport</parameter></paramdef> - <paramdef>int *<parameter>mux</parameter></paramdef> - <paramdef>int *<parameter>daisy</parameter></paramdef> -</funcprototype></funcsynopsis> - -<para>Any parallel port peripheral will be connected directly or -indirectly to a parallel port on the system, but it won't have a -daisy-chain address if it does not know about daisy-chaining, and it -won't be connected through a multiplexor port if there is no -multiplexor. The special co-ordinate value <constant>-1</constant> is -used to indicate these cases.</para> - -<para>Two functions are provided for finding devices based on their -IEEE 1284 Device ID: <function>parport_find_device</function> and -<function>parport_find_class</function>.</para> - -<funcsynopsis><funcprototype> - <funcdef>int <function>parport_find_device</function></funcdef> - <paramdef>const char *<parameter>mfg</parameter></paramdef> - <paramdef>const char *<parameter>mdl</parameter></paramdef> - <paramdef>int <parameter>from</parameter></paramdef> -</funcprototype></funcsynopsis> - -<funcsynopsis><funcprototype> - <funcdef>int <function>parport_find_class</function></funcdef> - <paramdef>parport_device_class <parameter>cls</parameter></paramdef> - <paramdef>int <parameter>from</parameter></paramdef> -</funcprototype></funcsynopsis> - -<para>These functions take a device number (in addition to some other -things), and return another device number. They walk through the list -of detected devices until they find one that matches the requirements, -and then return that device number (or <constant>-1</constant> if -there are no more such devices). They start their search at the -device after the one in the list with the number given (at -<parameter>from</parameter>+1, in other words).</para> - -</sect1> - -</chapter> - -<chapter id="drivers"> -<title>Device driver's view</title> + <para> + There are two layers to the <literal>parport</literal> + subsystem, only one of which deals directly with the hardware. + The other layer deals with sharing and IEEE 1284 transfer modes. + In this way, parallel support for a particular architecture comes + in the form of a module which registers itself with the generic + sharing layer. + </para> -<!-- Cover: - - sharing interface, preemption, interrupts, wakeups... - - IEEE 1284.3 interface - - port operations - - why can read data but ctr is faked, etc. - --> + <!-- sharing model --> -<!-- I should take a look at the kernel hackers' guide bit I wrote, --> -<!-- as that deals with a lot of this. The main complaint with it --> -<!-- was that there weren't enough examples, but 'The printer --> -<!-- driver' should deal with that later; might be worth mentioning --> -<!-- in the text. --> + <para> + The sharing model provided by the <literal>parport</literal> + subsystem is one of exclusive access. A device driver, such as + the printer driver, must ask the <literal>parport</literal> + layer for access to the port, and can only use the port once + access has been granted. When it has finished a + <quote>transaction</quote>, it can tell the + <literal>parport</literal> layer that it may release the port + for other device drivers to use. + </para> -<para>This section is written from the point of view of the device -driver programmer, who might be writing a driver for a printer or a -scanner or else anything that plugs into the parallel port. It -explains how to use the <filename>parport</filename> interface to find -parallel ports, use them, and share them with other device -drivers.</para> - -<para>We'll start out with a description of the various functions that -can be called, and then look at a reasonably simple example of their -use: the printer driver.</para> - -<para>The interactions between the device driver and the -<filename>parport</filename> layer are as follows. First, the device -driver registers its existence with <filename>parport</filename>, in -order to get told about any parallel ports that have been (or will be) -detected. When it gets told about a parallel port, it then tells -<filename>parport</filename> that it wants to drive a device on that -port. Thereafter it can claim exclusive access to the port in order -to talk to its device.</para> - -<para>So, the first thing for the device driver to do is tell -<filename>parport</filename> that it wants to know what parallel ports -are on the system. To do this, it uses the -<function>parport_register_device</function> function:</para> + <!-- talk a bit about how drivers can share devices on the same port --> -<programlisting> -<![CDATA[ -struct parport_driver { - const char *name; - void (*attach) (struct parport *); - void (*detach) (struct parport *); - struct parport_driver *next; -}; -]]></programlisting> + <para> + Devices with pass-through ports all manage to share a parallel + port with other devices in generally the same way. The device has + a latch for each of the pins on its pass-through port. The normal + state of affairs is pass-through mode, with the device copying the + signal lines between its host port and its pass-through port. + When the device sees a special signal from the host port, it + latches the pass-through port so that devices further downstream + don't get confused by the pass-through device's conversation with + the host parallel port: the device connected to the pass-through + port (and any devices connected in turn to it) are effectively cut + off from the computer. When the pass-through device has completed + its transaction with the computer, it enables the pass-through + port again. + </para> -<funcsynopsis><funcprototype> - <funcdef>int <function>parport_register_driver</function></funcdef> - <paramdef>struct parport_driver *<parameter>driver</parameter></paramdef> -</funcprototype></funcsynopsis> - -<para>In other words, the device driver passes pointers to a couple of -functions to <filename>parport</filename>, and -<filename>parport</filename> calls <function>attach</function> for -each port that's detected (and <function>detach</function> for each -port that disappears -- yes, this can happen).</para> - -<para>The next thing that happens is that the device driver tells -<filename>parport</filename> that it thinks there's a device on the -port that it can drive. This typically will happen in the driver's -<function>attach</function> function, and is done with -<function>parport_register_device</function>:</para> - -<funcsynopsis><funcprototype> - <funcdef>struct pardevice *<function>parport_register_device</function></funcdef> - <paramdef>struct parport *<parameter>port</parameter></paramdef> - <paramdef>const char *<parameter>name</parameter></paramdef> - <paramdef>int <parameter>(*pf)</parameter> - <funcparams>void *</funcparams></paramdef> - <paramdef>void <parameter>(*kf)</parameter> - <funcparams>void *</funcparams></paramdef> - <paramdef>void <parameter>(*irq_func)</parameter> - <funcparams>int, void *, struct pt_regs *</funcparams></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - <paramdef>void *<parameter>handle</parameter></paramdef> -</funcprototype></funcsynopsis> - -<para>The <parameter>port</parameter> comes from the parameter supplied -to the <function>attach</function> function when it is called, or -alternatively can be found from the list of detected parallel ports -directly with the (now deprecated) -<function>parport_enumerate</function> function.</para> - -<para>The next three parameters, <parameter>pf</parameter>, -<parameter>kf</parameter>, and <parameter>irq_func</parameter>, are -more function pointers. These callback functions get called under -various circumstances, and are always given the -<parameter>handle</parameter> as one of their parameters.</para> - -<para>The preemption callback, <parameter>pf</parameter>, is called -when the driver has claimed access to the port but another device -driver wants access. If the driver is willing to let the port go, it -should return zero and the port will be released on its behalf. There -is no need to call <function>parport_release</function>. If -<parameter>pf</parameter> gets called at a bad time for letting the -port go, it should return non-zero and no action will be taken. It is -good manners for the driver to try to release the port at the earliest -opportunity after its preemption callback is called.</para> - -<para>The <quote>kick</quote> callback, <parameter>kf</parameter>, is -called when the port can be claimed for exclusive access; that is, -<function>parport_claim</function> is guaranteed to succeed inside the -<quote>kick</quote> callback. If the driver wants to claim the port -it should do so; otherwise, it need not take any action.</para> - -<para>The <parameter>irq_func</parameter> callback is called, -predictably, when a parallel port interrupt is generated. But it is -not the only code that hooks on the interrupt. The sequence is this: -the lowlevel driver is the one that has done -<function>request_irq</function>; it then does whatever -hardware-specific things it needs to do to the parallel port hardware -(for PC-style ports, there is nothing special to do); it then tells -the IEEE 1284 code about the interrupt, which may involve reacting to -an IEEE 1284 event, depending on the current IEEE 1284 phase; and -finally the <parameter>irq_func</parameter> function is called.</para> - -<para>None of the callback functions are allowed to block.</para> - -<para>The <parameter>flags</parameter> are for telling -<filename>parport</filename> any requirements or hints that are -useful. The only useful value here (other than -<constant>0</constant>, which is the usual value) is -<constant>PARPORT_DEV_EXCL</constant>. The point of that flag is to -request exclusive access at all times---once a driver has successfully -called <function>parport_register_device</function> with that flag, no -other device drivers will be able to register devices on that port -(until the successful driver deregisters its device, of -course).</para> - -<para>The <constant>PARPORT_DEV_EXCL</constant> flag is for preventing -port sharing, and so should only be used when sharing the port with -other device drivers is impossible and would lead to incorrect -behaviour. Use it sparingly!</para> - -<para>Devices can also be registered by device drivers based on their -device numbers (the same device numbers as in the previous -section).</para> - -<para>The <function>parport_open</function> function is similar to -<function>parport_register_device</function>, and -<function>parport_close</function> is the equivalent of -<function>parport_unregister_device</function>. The difference is -that <function>parport_open</function> takes a device number rather -than a pointer to a <structname>struct parport</structname>.</para> - -<funcsynopsis><funcprototype> - <funcdef>struct pardevice *<function>parport_open</function></funcdef> - <paramdef>int <parameter>devnum</parameter></paramdef> - <paramdef>int <parameter>(*pf)</parameter> - <funcparams>void *</funcparams></paramdef> - <paramdef>int <parameter>(*kf)</parameter> - <funcparams>void *</funcparams></paramdef> - <paramdef>int <parameter>(*irqf)</parameter> - <funcparams>int, void *, struct pt_regs *</funcparams></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - <paramdef>void *<parameter>handle</parameter></paramdef> -</funcprototype></funcsynopsis> - -<funcsynopsis><funcprototype> - <funcdef>void <function>parport_close</function></funcdef> - <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> -</funcprototype></funcsynopsis> - -<funcsynopsis><funcprototype> - <funcdef>struct pardevice *<function>parport_register_device</function></funcdef> - <paramdef>struct parport *<parameter>port</parameter></paramdef> - <paramdef>const char *<parameter>name</parameter></paramdef> - <paramdef>int <parameter>(*pf)</parameter> - <funcparams>void *</funcparams></paramdef> - <paramdef>int <parameter>(*kf)</parameter> - <funcparams>void *</funcparams></paramdef> - <paramdef>int <parameter>(*irqf)</parameter> - <funcparams>int, void *, struct pt_regs *</funcparams></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - <paramdef>void *<parameter>handle</parameter></paramdef> -</funcprototype></funcsynopsis> - -<funcsynopsis><funcprototype> - <funcdef>void <function>parport_unregister_device</function></funcdef> - <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> -</funcprototype></funcsynopsis> - -<para>The intended use of these functions is during driver -initialisation while the driver looks for devices that it supports, as -demonstrated by the following code fragment:</para> + <mediaobject> + <imageobject> + <imagedata fileref="parport-share.eps" format=ps> + </imageobject> + <imageobject> + <imagedata fileref="parport-share.jpeg" format=jpeg> + </imageobject> + </mediaobject> -<programlisting> -<![CDATA[ -int devnum = -1; -while ((devnum = parport_find_class (PARPORT_CLASS_DIGCAM, - devnum)) != -1) { - struct pardevice *dev = parport_open (devnum, ...); - ... -} -]]></programlisting> + <para> + This technique relies on certain <quote>special signals</quote> + being invisible to devices that aren't watching for them. This + tends to mean only changing the data signals and leaving the + control signals alone. IEEE 1284.3 documents a standard protocol + for daisy-chaining devices together with parallel ports. + </para> -<para>Once your device driver has registered its device and been -handed a pointer to a <structname>struct pardevice</structname>, the -next thing you are likely to want to do is communicate with the device -you think is there. To do that you'll need to claim access to the -port.</para> - -<funcsynopsis><funcprototype> - <funcdef>int <function>parport_claim</function></funcdef> - <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> -</funcprototype></funcsynopsis> - -<funcsynopsis><funcprototype> - <funcdef>int <function>parport_claim_or_block</function></funcdef> - <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> -</funcprototype></funcsynopsis> - -<funcsynopsis><funcprototype> - <funcdef>void <function>parport_release</function></funcdef> - <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> -</funcprototype></funcsynopsis> - -<para>To claim access to the port, use -<function>parport_claim</function> or -<function>parport_claim_or_block</function>. The first of these will -not block, and so can be used from interrupt context. If -<function>parport_claim</function> succeeds it will return zero and -the port is available to use. It may fail (returning non-zero) if the -port is in use by another driver and that driver is not willing to -relinquish control of the port.</para> - -<para>The other function, <function>parport_claim_or_block</function>, -will block if necessary to wait for the port to be free. If it slept, -it returns <constant>1</constant>; if it succeeded without needing to -sleep it returns <constant>0</constant>. If it fails it will return a -negative error code.</para> - -<para>When you have finished communicating with the device, you can -give up access to the port so that other drivers can communicate with -their devices. The <function>parport_release</function> function -cannot fail, but it should not be called without the port claimed. -Similarly, you should not try to claim the port if you already have it -claimed.</para> - -<para>You may find that although there are convenient points for your -driver to relinquish the parallel port and allow other drivers to talk -to their devices, it would be preferable to keep hold of the port. -The printer driver only needs the port when there is data to print, -for example, but a network driver (such as PLIP) could be sent a -remote packet at any time. With PLIP, it is no huge catastrophe if a -network packet is dropped, since it will likely be sent again, so it -is possible for that kind of driver to share the port with other -(pass-through) devices.</para> - -<para>The <function>parport_yield</function> and -<function>parport_yield_blocking</function> functions are for marking -points in the driver at which other drivers may claim the port and use -their devices. Yielding the port is similar to releasing it and -reclaiming it, but it more efficient because nothing is done if there -are no other devices needing the port. In fact, nothing is done even -if there are other devices waiting but the current device is still -within its <quote>timeslice</quote>. The default timeslice is half a -second, but it can be adjusted via a <filename>/proc</filename> -entry.</para> - -<funcsynopsis><funcprototype> - <funcdef>int <function>parport_yield</function></funcdef> - <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> -</funcprototype></funcsynopsis> - -<funcsynopsis><funcprototype> - <funcdef>int <function>parport_yield_blocking</function></funcdef> - <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> -</funcprototype></funcsynopsis> - -<para>The first of these, <function>parport_yield</function>, will not -block but as a result may fail. The return value for -<function>parport_yield</function> is the same as for -<function>parport_claim</function>. The blocking version, -<function>parport_yield_blocking</function>, has the same return code -as <function>parport_claim_or_block</function>.</para> - -<para>Once the port has been claimed, the device driver can use the -functions in the <structname>struct parport_operations</structname> -pointer in the <structname>struct parport</structname> it has a -pointer to. For example:</para> + <!-- transfer modes --> -<programlisting> -<![CDATA[ -port->ops->write_data (port, d); -]]></programlisting> + <para> + Support for standard transfer modes are provided as operations + that can be performed on a port, along with operations for setting + the data lines, or the control lines, or reading the status lines. + These operations appear to the device driver as function pointers; + more later. + </para> -<para>Some of these operations have <quote>shortcuts</quote>. For -instance, <function>parport_write_data</function> is equivalent to the -above, but may be a little bit faster (it's a macro that in some cases -can avoid needing to indirect through <varname>port</varname> and -<varname>ops</varname>).</para> - -</chapter> - -<chapter id="portdrivers"> -<title>Port drivers</title> - -<!-- What port drivers are for (i.e. implementing parport objects). --> - -<para>To recap, then:</para> - -<itemizedlist spacing=compact> - -<listitem> -<para> -The device driver registers itself with <filename>parport</filename>. -</para> -</listitem> - -<listitem> -<para> -A low-level driver finds a parallel port and registers it with -<filename>parport</filename> (these first two things can happen in -either order). This registration creates a <structname>struct -parport</structname> which is linked onto a list of known ports. -</para> -</listitem> - -<listitem> -<para> -<filename>parport</filename> calls the <function>attach</function> -function of each registered device driver, passing it the pointer to -the new <structname>struct parport</structname>. -</para> -</listitem> - -<listitem> -<para> -The device driver gets a handle from <filename>parport</filename>, for -use with -<function>parport_claim</function>/<function>release</function>. This -handle takes the form of a pointer to a <structname>struct -pardevice</structname>, representing a particular device on the -parallel port, and is acquired using -<function>parport_register_device</function>. -</para> -</listitem> - -<listitem> -<para> -The device driver claims the port using -<function>parport_claim</function> (or -<function>function_claim_or_block</function>). -</para> -</listitem> - -<listitem> -<para> -Then it goes ahead and uses the port. When finished it releases the -port. -</para> -</listitem> - -</itemizedlist> - -<para>The purpose of the low-level drivers, then, is to detect -parallel ports and provide methods of accessing them -(i.e. implementing the operations in <structname>struct -parport_operations</structname>).</para> - -<!-- Interaction with sharing engine; port state --> -<!-- What did I mean by that? --> - -<!-- Talk about parport_pc implementation, and contrast with e.g. amiga --> - -<para>A more complete description of which operation is supposed to do -what is available in -<filename>Documentation/parport-lowlevel.txt</filename>.</para> - -</chapter> - -<chapter id="lp"> -<title>The printer driver</title> - -<!-- Talk the reader through the printer driver. --> -<!-- Could even talk about parallel port console here. --> - -<para>The printer driver, <filename>lp</filename> is a character -special device driver and a <filename>parport</filename> client. As a -character special device driver it registers a <structname>struct -file_operations</structname> using -<function>register_chrdev</function>, with pointers filled in for -<structfield>write</structfield>, <structfield>ioctl</structfield>, -<structfield>open</structfield> and -<structfield>release</structfield>. As a client of -<filename>parport</filename>, it registers a <structname>struct -parport_driver</structname> using -<function>parport_register_driver</function>, so that -<filename>parport</filename> knows to call -<function>lp_attach</function> when a new parallel port is discovered -(and <function>lp_detach</function> when it goes away).</para> - -<para>The parallel port console functionality is also implemented in -<filename>lp.c</filename>, but that won't be covered here (it's quite -simple though).</para> - -<para>The initialisation of the driver is quite easy to understand -(see <function>lp_init</function>). The <varname>lp_table</varname> -is an array of structures that contain information about a specific -device (the <structname>struct pardevice</structname> associated with -it, for example). That array is initialised to sensible values first -of all.</para> - -<para>Next, the printer driver calls -<function>register_chrdev</function> passing it a pointer to -<varname>lp_fops</varname>, which contains function pointers for the -printer driver's implementation of <function>open</function>, -<function>write</function>, and so on. This part is the same as for -any character special device driver.</para> - -<para>After successfully registering itself as a character special -device driver, the printer driver registers itself as a -<filename>parport</filename> client using -<function>parport_register_driver</function>. It passes a pointer to -this structure:</para> + </sect1> -<programlisting> -<![CDATA[ -static struct parport_driver lp_driver = { - "lp", - lp_attach, - lp_detach, - NULL -}; -]]></programlisting> + </chapter> -<para>The <function>lp_detach</function> function is not very -interesting (it does nothing); the interesting bit is -<function>lp_attach</function>. What goes on here depends on whether -the user supplied any parameters. The possibilities are: no -parameters supplied, in which case the printer driver uses every port -that is detected; the user supplied the parameter <quote>auto</quote>, -in which case only ports on which the device ID string indicates a -printer is present are used; or the user supplied a list of parallel -port numbers to try, in which case only those are used.</para> - -<para>For each port that the printer driver wants to use (see -<function>lp_register</function>), it calls -<function>parport_register_device</function> and stores the resulting -<structname>struct pardevice</structname> pointer in the -<varname>lp_table</varname>. If the user told it to do so, it then -resets the printer.</para> - -<para>The other interesting piece of the printer driver, from the -point of view of <filename>parport</filename>, is -<function>lp_write</function>. In this function, the user space -process has data that it wants printed, and the printer driver hands -it off to the <filename>parport</filename> code to deal with.</para> - -<para>The <filename>parport</filename> functions it uses that we have -not seen yet are <function>parport_negotiate</function>, -<function>parport_set_timeout</function>, and -<function>parport_write</function>. These functions are part of the -IEEE 1284 implementation.</para> - -<para>The way the IEEE 1284 protocol works is that the host tells the -peripheral what transfer mode it would like to use, and the peripheral -either accepts that mode or rejects it; if the mode is rejected, the -host can try again with a different mode. This is the negotation -phase. Once the peripheral has accepted a particular transfer mode, -data transfer can begin that mode.</para> - -<para>The particular transfer mode that the printer driver wants to -use is named in IEEE 1284 as <quote>compatibility</quote> mode, and -the function to request a particular mode is called -<function>parport_negotiate</function>.</para> - -<funcsynopsis><funcprototype> - <funcdef>int <function>parport_negotiate</function></funcdef> - <paramdef>struct parport *<parameter>port</parameter></paramdef> - <paramdef>int <parameter>mode</parameter></paramdef> -</funcprototype></funcsynopsis> - -<para>The <parameter>modes</parameter> parameter is a symbolic -constant representing an IEEE 1284 mode; in this instance, it is -<constant>IEEE1284_MODE_COMPAT</constant>. (Compatibility mode is -slightly different to the other modes---rather than being specifically -requested, it is the default until another mode is selected.)</para> - -<para>Back to <function>lp_write</function> then. First, access to -the parallel port is secured with -<function>parport_claim_or_block</function>. At this point the driver -might sleep, waiting for another driver (perhaps a Zip drive driver, -for instance) to let the port go. Next, it goes to compatibility mode -using <function>parport_negotiate</function>.</para> - -<para>The main work is done in the write-loop. In particular, the -line that hands the data over to <filename>parport</filename> -reads:</para> + <chapter id="transfermodes"> + <title>Standard transfer modes</title> -<programlisting> -<![CDATA[ - written = parport_write (port, kbuf, copy_size); -]]></programlisting> + <!-- Defined by IEEE, but in common use (even though there are widely --> + <!-- varying implementations). --> -<para>The <function>parport_write</function> function writes data to -the peripheral using the currently selected transfer mode -(compatibility mode, in this case). It returns the number of bytes -successfully written:</para> - -<funcsynopsis><funcprototype> - <funcdef>ssize_t <function>parport_write</function></funcdef> - <paramdef>struct parport *<parameter>port</parameter></paramdef> - <paramdef>const void *<parameter>buf</parameter></paramdef> - <paramdef>size_t <parameter>len</parameter></paramdef> -</funcprototype></funcsynopsis> - -<funcsynopsis><funcprototype> - <funcdef>ssize_t <function>parport_read</function></funcdef> - <paramdef>struct parport *<parameter>port</parameter></paramdef> - <paramdef>void *<parameter>buf</parameter></paramdef> - <paramdef>size_t <parameter>len</parameter></paramdef> -</funcprototype></funcsynopsis> - -<para>(<function>parport_read</function> does what it sounds like, but -only works for modes in which reverse transfer is possible. Of -course, <function>parport_write</function> only works in modes in -which forward transfer is possible, too.)</para> - -<para>The <parameter>buf</parameter> pointer should be to kernel space -memory, and obviously the <parameter>len</parameter> parameter -specifies the amount of data to transfer.</para> - -<para>In fact what <function>parport_write</function> does is call the -appropriate block transfer function from the <structname>struct -parport_operations</structname>:</para> + <para> + The <quote>standard</quote> transfer modes in use over the parallel + port are <quote>defined</quote> by a document called IEEE 1284. It + really just codifies existing practice and documents protocols (and + variations on protocols) that have been in common use for quite + some time. + </para> -<programlisting> -<![CDATA[ -struct parport_operations { - [...] + <para> + The original definitions of which pin did what were set out by + Centronics Data Computer Corporation, but only the printer-side + interface signals were specified. + </para> - /* Block read/write */ - size_t (*epp_write_data) (struct parport *port, const void *buf, - size_t len, int flags); - size_t (*epp_read_data) (struct parport *port, void *buf, size_t len, - int flags); - size_t (*epp_write_addr) (struct parport *port, const void *buf, - size_t len, int flags); - size_t (*epp_read_addr) (struct parport *port, void *buf, size_t len, - int flags); + <para> + By the early 1980s, IBM's host-side implementation had become the + most widely used. New printers emerged that claimed Centronics + compatibility, but although compatible with Centronics they + differed from one another in a number of ways. + </para> - size_t (*ecp_write_data) (struct parport *port, const void *buf, - size_t len, int flags); - size_t (*ecp_read_data) (struct parport *port, void *buf, size_t len, - int flags); - size_t (*ecp_write_addr) (struct parport *port, const void *buf, - size_t len, int flags); + <para> + As a result of this, when IEEE 1284 was published in 1994, all that + it could really do was document the various protocols that are used + for printers (there are about six variations on a theme). + </para> - size_t (*compat_write_data) (struct parport *port, const void *buf, - size_t len, int flags); - size_t (*nibble_read_data) (struct parport *port, void *buf, - size_t len, int flags); - size_t (*byte_read_data) (struct parport *port, void *buf, - size_t len, int flags); -}; -]]></programlisting> + <para> + In addition to the protocol used to talk to Centronics-compatible + printers, IEEE 1284 defined other protocols that are used for + unidirectional peripheral-to-host transfers (reverse nibble and + reverse byte) and for fast bidirectional transfers (ECP and + EPP). + </para> -<para>The transfer code in <filename>parport</filename> will tolerate -a data transfer stall only for so long, and this timeout can be -specified with <function>parport_set_timeout</function>, which returns -the previous timeout:</para> - -<funcsynopsis><funcprototype> - <funcdef>long <function>parport_set_timeout</function></funcdef> - <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> - <paramdef>long <parameter>inactivity</parameter></paramdef> -</funcprototype></funcsynopsis> - -<para>This timeout is specific to the device, and is restored on -<function>parport_claim</function>.</para> - -</chapter> - -<chapter id="ppdev"> -<title>User-level device drivers</title> - -<!-- ppdev --> -<sect1> -<title>Introduction to ppdev</title> - -<para>The printer is accessible through <filename>/dev/lp0</filename>; -in the same way, the parallel port itself is accessible through -<filename>/dev/parport0</filename>. The difference is in the level of -control that you have over the wires in the parallel port -cable.</para> - -<para>With the printer driver, a user-space program (such as the -printer spooler) can send bytes in <quote>printer protocol</quote>. -Briefly, this means that for each byte, the eight data lines are set -up, then a <quote>strobe</quote> line tells the printer to look at the -data lines, and the printer sets an <quote>acknowledgement</quote> -line to say that it got the byte. The printer driver also allows the -user-space program to read bytes in <quote>nibble mode</quote>, which -is a way of transferring data from the peripheral to the computer half -a byte at a time (and so it's quite slow).</para> - -<para>In contrast, the <filename>ppdev</filename> driver (accessed via -<filename>/dev/parport0</filename>) allows you to:</para> - -<itemizedlist spacing=compact> - -<listitem> -<para> -examine status lines, -</para> -</listitem> - -<listitem> -<para> -set control lines, -</para> -</listitem> - -<listitem> -<para> -set/examine data lines (and control the direction of the data lines), -</para> -</listitem> - -<listitem> -<para> -wait for an interrupt (triggered by one of the status lines), -</para> -</listitem> - -<listitem> -<para> -find out how many new interrupts have occurred, -</para> -</listitem> - -<listitem> -<para> -set up a response to an interrupt, -</para> -</listitem> - -<listitem> -<para> -use IEEE 1284 negotiation (for telling peripheral which transfer mode, -to use) -</para> -</listitem> - -<listitem> -<para> -transfer data using a specified IEEE 1284 mode. -</para> -</listitem> - -</itemizedlist> - -</sect1> - -<sect1> -<title>User-level or kernel-level driver?</title> - -<para>The decision of whether to choose to write a kernel-level device -driver or a user-level device driver depends on several factors. One -of the main ones from a practical point of view is speed: kernel-level -device drivers get to run faster because they are not preemptable, -unlike user-level applications.</para> - -<para>Another factor is ease of development. It is in general easier -to write a user-level driver because (a) one wrong move does not -result in a crashed machine, (b) you have access to user libraries -(such as the C library), and (c) debugging is easier.</para> - -</sect1> - -<sect1> -<title>Programming interface</title> - -<para>The <filename>ppdev</filename> interface is largely the same as -that of other character special devices, in that it supports -<function>open</function>, <function>close</function>, -<function>read</function>, <function>write</function>, and -<function>ioctl</function>.</para> - -<sect2> -<title>Starting and stopping: <function>open</function> and -<function>close</function></title> - -<para>The device node <filename>/dev/parport0</filename> represents -any device that is connected to <filename>parport0</filename>, the -first parallel port in the system. Each time the device node is -opened, it represents (to the process doing the opening) a different -device. It can be opened more than once, but only one instance can -actually be in control of the parallel port at any time. A process -that has opened <filename>/dev/parport0</filename> shares the parallel -port in the same way as any other device driver. A user-land driver -may be sharing the parallel port with in-kernel device drivers as well -as other user-land drivers.</para> -</sect2> - -<sect2> -<title>Control: <function>ioctl</function></title> - -<para>Most of the control is done, naturally enough, via the -<function>ioctl</function> call. Using <function>ioctl</function>, -the user-land driver can control both the <filename>ppdev</filename> -driver in the kernel and the physical parallel port itself. The -<function>ioctl</function> call takes as parameters a file descriptor -(the one returned from opening the device node), a command, and -optionally (a pointer to) some data.</para> - -<variablelist> -<varlistentry><term><constant>PPCLAIM</constant></term> -<listitem> - -<para>Claims access to the port. As a user-land device driver writer, -you will need to do this before you are able to actually change the -state of the parallel port in any way. Note that some operations only -affect the <filename>ppdev</filename> driver and not the port, such as -<constant>PPSETMODE</constant>; they can be performed while access to -the port is not claimed.</para> - -</listitem></varlistentry> - -<varlistentry><term><constant>PPEXCL</constant></term> -<listitem> - -<para>Instructs the kernel driver to forbid any sharing of the port -with other drivers, i.e. it requests exclusivity. The -<constant>PPEXCL</constant> command is only valid when the port is not -already claimed for use, and it may mean that the next -<constant>PPCLAIM</constant> <function>ioctl</function> will fail: -some other driver may already have registered itself on that -port.</para> - -<para>Most device drivers don't need exclusive access to the port. -It's only provided in case it is really needed, for example for -devices where access to the port is required for extensive periods of -time (many seconds).</para> - -<para>Note that the <constant>PPEXCL</constant> -<function>ioctl</function> doesn't actually claim the port there and -then---action is deferred until the <constant>PPCLAIM</constant> -<function>ioctl</function> is performed.</para> - -</listitem></varlistentry> - -<varlistentry><term><constant>PPRELEASE</constant></term> -<listitem> - -<para>Releases the port. Releasing the port undoes the effect of -claiming the port. It allows other device drivers to talk to their -devices (assuming that there are any).</para> + </chapter> -</listitem></varlistentry> - -<varlistentry><term><constant>PPYIELD</constant></term> -<listitem> - -<para>Yields the port to another driver. This -<function>ioctl</function> is a kind of short-hand for releasing the -port and immediately reclaiming it. It gives other drivers a chance -to talk to their devices, but afterwards claims the port back. An -example of using this would be in a user-land printer driver: once a -few characters have been written we could give the port to another -device driver for a while, but if we still have characters to send to -the printer we would want the port back as soon as possible.</para> - -<para>It is important not to claim the parallel port for too long, as -other device drivers will have no time to service their devices. If -your device does not allow for parallel port sharing at all, it is -better to claim the parallel port exclusively (see -<constant>PPEXCL</constant>).</para> - -</listitem></varlistentry> - -<varlistentry><term><constant>PPNEGOT</constant></term> -<listitem> - -<para>Performs IEEE 1284 negotiation into a particular mode. Briefly, -negotiation is the method by which the host and the peripheral decide -on a protocol to use when transferring data.</para> - -<para>An IEEE 1284 compliant device will start out in compatibility -mode, and then the host can negotiate to another mode (such as -ECP).</para> - -<para>The <function>ioctl</function> parameter should be a pointer to -an <type>int</type>; values for this are in -<filename>parport.h</filename> and include:</para> - -<itemizedlist spacing=compact> -<listitem><para><constant>IEEE1284_MODE_COMPAT</constant></para></listitem> -<listitem><para><constant>IEEE1284_MODE_NIBBLE</constant></para></listitem> -<listitem><para><constant>IEEE1284_MODE_BYTE</constant></para></listitem> -<listitem><para><constant>IEEE1284_MODE_EPP</constant></para></listitem> -<listitem><para><constant>IEEE1284_MODE_ECP</constant></para></listitem> -</itemizedlist> - -<para>The <constant>PPNEGOT</constant> <function>ioctl</function> -actually does two things: it performs the on-the-wire negotiation, and -it sets the behaviour of subsequent -<function>read</function>/<function>write</function> calls so that -they use that mode (but see <constant>PPSETMODE</constant>).</para> - -</listitem></varlistentry> - -<varlistentry><term><constant>PPSETMODE</constant></term> -<listitem> + <chapter id="structure"> + <title>Structure</title> -<para>Sets which IEEE 1284 protocol to use for the -<function>read</function> and <function>write</function> calls.</para> +<!-- Main structure + - sharing core + - parports and their IEEE 1284 overrides + - IEEE 1284 transfer modes for generic ports + - maybe mention muxes here + - pardevices + - IEEE 1284.3 API + --> -<para>The <function>ioctl</function> parameter should be a pointer to -an <type>int</type>.</para> - -</listitem></varlistentry> + <mediaobject> + <imageobject> + <imagedata format=eps fileref="parport-structure.eps"> + </imageobject> + <imageobject> + <imagedata format=jpeg fileref="parport-structure.jpeg"> + </imageobject> + </mediaobject> -<varlistentry><term><constant>PPGETTIME</constant></term> -<listitem> + <sect1> + <title>Sharing core</title> -<para>Retrieves the time-out value. The <function>read</function> and -<function>write</function> calls will time out if the peripheral -doesn't respond quickly enough. The <constant>PPGETTIME</constant> -<function>ioctl</function> retrieves the length of time that the -peripheral is allowed to have before giving up.</para> + <para> + At the core of the <literal>parport</literal> subsystem is the + sharing mechanism (see + <filename>drivers/parport/share.c</filename>). This module, + <literal>parport</literal>, is responsible for keeping track of + which ports there are in the system, which device drivers might be + interested in new ports, and whether or not each port is available + for use (or if not, which driver is currently using it). + </para> -<para>The <function>ioctl</function> parameter should be a pointer to -a <structname>struct timeval</structname>.</para> + </sect1> -</listitem></varlistentry> + <sect1> + <title>Parports and their overrides</title> -<varlistentry><term><constant>PPSETTIME</constant></term> -<listitem> + <para> + The generic <literal>parport</literal> sharing code doesn't + directly handle the parallel port hardware. That is done instead + by <quote>low-level</quote> <literal>parport</literal> drivers. + The function of a low-level <literal>parport</literal> driver is + to detect parallel ports, register them with the sharing code, and + provide a list of access functions for each port. + </para> -<para>Sets the time-out. The <function>ioctl</function> parameter -should be a pointer to a <structname>struct -timeval</structname>.</para> + <para> + The most basic access functions that must be provided are ones for + examining the status lines, for setting the control lines, and for + setting the data lines. There are also access functions for + setting the direction of the data lines; normally they are in the + <quote>forward</quote> direction (that is, the computer drives + them), but some ports allow switching to <quote>reverse</quote> + mode (driven by the peripheral). There is an access function for + examining the data lines once in reverse mode. + </para> -</listitem></varlistentry> + </sect1> -<varlistentry><term><constant>PPWCONTROL</constant></term> -<listitem> + <sect1> + <title>IEEE 1284 transfer modes</title> -<para>Sets the control lines. The <function>ioctl</function> -parameter is a pointer to an <type>unsigned char</type>, the bitwise -OR of the control line values in -<filename>parport.h</filename>.</para> + <para> + Stacked on top of the sharing mechanism, but still in the + <literal>parport</literal> module, are functions for + transferring data. They are provided for the device drivers to + use, and are very much like library routines. Since these + transfer functions are provided by the generic + <literal>parport</literal> core they must use the <quote>lowest + common denominator</quote> set of access functions: they can set + the control lines, examine the status lines, and use the data + lines. With some parallel ports the data lines can only be set + and not examined, and with other ports accessing the data register + causes control line activity; with these types of situations, the + IEEE 1284 transfer functions make a best effort attempt to do the + right thing. In some cases, it is not physically possible to use + particular IEEE 1284 transfer modes. + </para> -</listitem></varlistentry> + <para> + The low-level <literal>parport</literal> drivers also provide + IEEE 1284 transfer functions, as names in the access function + list. The low-level driver can just name the generic IEEE 1284 + transfer functions for this. Some parallel ports can do IEEE 1284 + transfers in hardware; for those ports, the low-level driver can + provide functions to utilise that feature. + </para> -<varlistentry><term><constant>PPRCONTROL</constant></term> -<listitem> + </sect1> -<para>Returns the last value written to the control register, in the -form of an <type>unsigned char</type>: each bit corresponds to a -control line (although some are unused). The -<function>ioctl</function> parameter should be a pointer to an -<type>unsigned char</type>.</para> - -<para>This doesn't actually touch the hardware; the last value written -is remembered in software. This is because some parallel port -hardware does not offer read access to the control register.</para> + <!-- muxes? --> -<para>The control lines bits are defined in -<filename>parport.h</filename>:</para> + <sect1> + <title>Pardevices and parport_drivers</title> -<itemizedlist spacing=compact> -<listitem><para><constant>PARPORT_CONTROL_STROBE</constant></para></listitem> -<listitem><para><constant>PARPORT_CONTROL_AUTOFD</constant></para></listitem> -<listitem><para><constant>PARPORT_CONTROL_SELECT</constant></para></listitem> -<listitem><para><constant>PARPORT_CONTROL_INIT</constant></para></listitem> -</itemizedlist> + <para> + When a parallel port device driver (such as + <literal>lp</literal>) initialises it tells the sharing layer + about itself using <function>parport_register_driver</function>. + The information is put into a <structname>struct + parport_driver</structname>, which is put into a linked list. The + information in a <structname>struct parport_driver</structname> + really just amounts to some function pointers to callbacks in the + parallel port device driver. + </para> -</listitem></varlistentry> + <para> + During its initialisation, a low-level port driver tells the + sharing layer about all the ports that it has found (using + <function>parport_register_port</function>), and the sharing layer + creates a <structname>struct parport</structname> for each of + them. Each <structname>struct parport</structname> contains + (among other things) a pointer to a <structname>struct + parport_operations</structname>, which is a list of function + pointers for the various operations that can be performed on a + port. You can think of a <structname>struct parport</structname> + as a parallel port <quote>object</quote>, if + <quote>object-orientated</quote> programming is your thing. The + <structname>parport</structname> structures are chained in a + linked list, whose head is <varname>portlist</varname> (in + <filename>drivers/parport/share.c</filename>). + </para> -<varlistentry><term><constant>PPFCONTROL</constant></term> -<listitem> + <para> + Once the port has been registered, the low-level port driver + announces it. The <function>parport_announce_port</function> + function walks down the list of parallel port device drivers + (<structname>struct parport_driver</structname>s) calling the + <function>attach</function> function of each. + </para> -<para>Frobs the control lines. Since a common operation is to change -one of the control signals while leaving the others alone, it would be -quite inefficient for the user-land driver to have to use -<constant>PPRCONTROL</constant>, make the change, and then use -<constant>PPWCONTROL</constant>. Of course, each driver could -remember what state the control lines are supposed to be in (they are -never changed by anything else), but in order to provide -<constant>PPRCONTROL</constant>, <filename>ppdev</filename> must -remember the state of the control lines anyway.</para> + <para> + Similarly, a low-level port driver can undo the effect of + registering a port with the + <function>parport_unregister_port</function> function, and device + drivers are notified using the <function>detach</function> + callback. + </para> -<para>The <constant>PPFCONTROL</constant> <function>ioctl</function> -is for <quote>frobbing</quote> control lines, and is like -<constant>PPWCONTROL</constant> but acts on a restricted set of -control lines. The <function>ioctl</function> parameter is a pointer -to a <structname>struct ppdev_frob_struct</structname>:</para> + <para> + Device drivers can undo the effect of registering themselves with + the <function>parport_unregister_driver</function> + function. + </para> -<programlisting> -<![CDATA[ -struct ppdev_frob_struct { - unsigned char mask; - unsigned char val; -}; -]]> -</programlisting> + </sect1> -<para>The <structfield>mask</structfield> and -<structfield>val</structfield> fields are bitwise ORs of control line -names (such as in <constant>PPWCONTROL</constant>). The operation -performed by <constant>PPFCONTROL</constant> is:</para> + <!-- IEEE 1284.3 API --> -<programlisting> -<![CDATA[new_ctr = (old_ctr & ~mask) | val;]]> -</programlisting> + <sect1> + <title>The IEEE 1284.3 API</title> -<para>In other words, the signals named in -<structfield>mask</structfield> are set to the values in -<structfield>val</structfield>.</para> + <para> + The ability to daisy-chain devices is very useful, but if every + device does it in a different way it could lead to lots of + complications for device driver writers. Fortunately, the IEEE + are standardising it in IEEE 1284.3, which covers daisy-chain + devices and port multiplexors. + </para> -</listitem></varlistentry> + <para> + At the time of writing, IEEE 1284.3 has not been published, but + the draft specifies the on-the-wire protocol for daisy-chaining + and multiplexing, and also suggests a programming interface for + using it. That interface (or most of it) has been implemented in + the <literal>parport</literal> code in Linux. + </para> -<varlistentry><term><constant>PPRSTATUS</constant></term> -<listitem> + <para> + At initialisation of the parallel port <quote>bus</quote>, + daisy-chained devices are assigned addresses starting from zero. + There can only be four devices with daisy-chain addresses, plus + one device on the end that doesn't know about daisy-chaining and + thinks it's connected directly to a computer. + </para> -<para>Returns an <type>unsigned char</type> containing bits set for -each status line that is set (for instance, -<constant>PARPORT_STATUS_BUSY</constant>). The -<function>ioctl</function> parameter should be a pointer to an -<type>unsigned char</type>.</para> + <para> + Another way of connecting more parallel port devices is to use a + multiplexor. The idea is to have a device that is connected + directly to a parallel port on a computer, but has a number of + parallel ports on the other side for other peripherals to connect + to (two or four ports are allowed). The multiplexor switches + control to different ports under software control---it is, in + effect, a programmable printer switch. + </para> -</listitem></varlistentry> + <para> + Combining the ability of daisy-chaining five devices together with + the ability to multiplex one parallel port between four gives the + potential to have twenty peripherals connected to the same + parallel port! + </para> -<varlistentry><term><constant>PPDATADIR</constant></term> -<listitem> + <para> + In addition, of course, a single computer can have multiple + parallel ports. So, each parallel port peripheral in the system + can be identified with three numbers, or co-ordinates: the + parallel port, the multiplexed port, and the daisy-chain + address. + </para> -<para>Controls the data line drivers. Normally the computer's -parallel port will drive the data lines, but for byte-wide transfers -from the peripheral to the host it is useful to turn off those drivers -and let the peripheral drive the signals. (If the drivers on the -computer's parallel port are left on when this happens, the port might -be damaged.)</para> + <mediaobject> + <imageobject> + <imagedata format=eps fileref="parport-multi.eps"> + </imageobject> + <imageobject> + <imagedata format=jpeg fileref="parport-multi.jpeg"> + </imageobject> + </mediaobject> -<para>This is only needed in conjunction with -<constant>PPWDATA</constant> or <constant>PPRDATA</constant>.</para> + <para> + Each device in the system is numbered at initialisation (by + <function>parport_daisy_init</function>). You can convert between + this device number and its co-ordinates with + <function>parport_device_num</function> and + <function>parport_device_coords</function>. + </para> -<para>The <function>ioctl</function> parameter is a pointer to an -<type>int</type>. If the <type>int</type> is zero, the drivers are -turned on (forward direction); if non-zero, the drivers are turned off -(reverse direction).</para> + <funcsynopsis> + <funcsynopsisinfo> +#include <parport.h> + </funcsynopsisinfo> + <funcprototype> + <funcdef>int <function>parport_device_num</function></funcdef> + <paramdef>int <parameter>parport</parameter></paramdef> + <paramdef>int <parameter>mux</parameter></paramdef> + <paramdef>int <parameter>daisy</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <funcsynopsis> + <funcprototype> + <funcdef>int <function>parport_device_coords</function></funcdef> + <paramdef>int <parameter>devnum</parameter></paramdef> + <paramdef>int *<parameter>parport</parameter></paramdef> + <paramdef>int *<parameter>mux</parameter></paramdef> + <paramdef>int *<parameter>daisy</parameter></paramdef> + </funcprototype> + </funcsynopsis> -</listitem></varlistentry> + <para> + Any parallel port peripheral will be connected directly or + indirectly to a parallel port on the system, but it won't have a + daisy-chain address if it does not know about daisy-chaining, and + it won't be connected through a multiplexor port if there is no + multiplexor. The special co-ordinate value + <constant>-1</constant> is used to indicate these cases. + </para> -<varlistentry><term><constant>PPWDATA</constant></term> -<listitem> + <para> + Two functions are provided for finding devices based on their IEEE + 1284 Device ID: <function>parport_find_device</function> and + <function>parport_find_class</function>. + </para> -<para>Sets the data lines (if in forward mode). The -<function>ioctl</function> parameter is a pointer to an <type>unsigned -char</type>.</para> + <funcsynopsis> + <funcsynopsisinfo> +#include <parport.h> + </funcsynopsisinfo> + <funcprototype> + <funcdef>int <function>parport_find_device</function></funcdef> + <paramdef>const char *<parameter>mfg</parameter></paramdef> + <paramdef>const char *<parameter>mdl</parameter></paramdef> + <paramdef>int <parameter>from</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <funcsynopsis> + <funcprototype> + <funcdef>int <function>parport_find_class</function></funcdef> + <paramdef>parport_device_class <parameter>cls</parameter></paramdef> + <paramdef>int <parameter>from</parameter></paramdef> + </funcprototype> + </funcsynopsis> -</listitem></varlistentry> + <para> + These functions take a device number (in addition to some other + things), and return another device number. They walk through the + list of detected devices until they find one that matches the + requirements, and then return that device number (or + <constant>-1</constant> if there are no more such devices). They + start their search at the device after the one in the list with + the number given (at <parameter>from</parameter>+1, in other + words). + </para> -<varlistentry><term><constant>PPRDATA</constant></term> -<listitem> + </sect1> -<para>Reads the data lines (if in reverse mode). The -<function>ioctl</function> parameter is a pointer to an <type>unsigned -char</type>.</para> + </chapter> -</listitem></varlistentry> + <chapter id="drivers"> + <title>Device driver's view</title> -<varlistentry><term><constant>PPCLRIRQ</constant></term> -<listitem> +<!-- Cover: + - sharing interface, preemption, interrupts, wakeups... + - IEEE 1284.3 interface + - port operations + - why can read data but ctr is faked, etc. + --> -<para>Clears the interrupt count. The <filename>ppdev</filename> -driver keeps a count of interrupts as they are triggered. -<constant>PPCLRIRQ</constant> stores this count in an -<type>int</type>, a pointer to which is passed in as the -<function>ioctl</function> parameter.</para> +<!-- I should take a look at the kernel hackers' guide bit I wrote, --> +<!-- as that deals with a lot of this. The main complaint with it --> +<!-- was that there weren't enough examples, but 'The printer --> +<!-- driver' should deal with that later; might be worth mentioning --> +<!-- in the text. --> -<para>In addition, the interrupt count is reset to zero.</para> + <para> + This section is written from the point of view of the device driver + programmer, who might be writing a driver for a printer or a + scanner or else anything that plugs into the parallel port. It + explains how to use the <literal>parport</literal> interface to + find parallel ports, use them, and share them with other device + drivers. + </para> + + <para> + We'll start out with a description of the various functions that + can be called, and then look at a reasonably simple example of + their use: the printer driver. + </para> + + <para> + The interactions between the device driver and the + <literal>parport</literal> layer are as follows. First, the + device driver registers its existence with + <literal>parport</literal>, in order to get told about any + parallel ports that have been (or will be) detected. When it gets + told about a parallel port, it then tells + <literal>parport</literal> that it wants to drive a device on + that port. Thereafter it can claim exclusive access to the port in + order to talk to its device. + </para> + + <para> + So, the first thing for the device driver to do is tell + <literal>parport</literal> that it wants to know what parallel + ports are on the system. To do this, it uses the + <function>parport_register_device</function> function: + </para> + + <funcsynopsis> + <funcsynopsisinfo> +#include <parport.h> -</listitem></varlistentry> +struct parport_driver { + const char *name; + void (*attach) (struct parport *); + void (*detach) (struct parport *); + struct parport_driver *next; +}; + </funcsynopsisinfo> + + <funcprototype> + <funcdef>int <function>parport_register_driver</function></funcdef> + <paramdef>struct parport_driver *<parameter>driver</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <para> + In other words, the device driver passes pointers to a couple of + functions to <literal>parport</literal>, and + <literal>parport</literal> calls <function>attach</function> for + each port that's detected (and <function>detach</function> for each + port that disappears---yes, this can happen). + </para> + + <para> + The next thing that happens is that the device driver tells + <literal>parport</literal> that it thinks there's a device on the + port that it can drive. This typically will happen in the driver's + <function>attach</function> function, and is done with + <function>parport_register_device</function>: + </para> + + <funcsynopsis> + <funcsynopsisinfo> +#include <parport.h> + </funcsynopsisinfo> + <funcprototype> + <funcdef>struct pardevice *<function>parport_register_device</function></funcdef> + <paramdef>struct parport *<parameter>port</parameter></paramdef> + <paramdef>const char *<parameter>name</parameter></paramdef> + <paramdef>int <parameter>(*pf)</parameter> + <funcparams>void *</funcparams></paramdef> + <paramdef>void <parameter>(*kf)</parameter> + <funcparams>void *</funcparams></paramdef> + <paramdef>void <parameter>(*irq_func)</parameter> + <funcparams>int, void *, struct pt_regs *</funcparams></paramdef> + <paramdef>int <parameter>flags</parameter></paramdef> + <paramdef>void *<parameter>handle</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <para> + The <parameter>port</parameter> comes from the parameter supplied + to the <function>attach</function> function when it is called, or + alternatively can be found from the list of detected parallel ports + directly with the (now deprecated) + <function>parport_enumerate</function> function. + </para> + + <para> + The next three parameters, <parameter>pf</parameter>, + <parameter>kf</parameter>, and <parameter>irq_func</parameter>, are + more function pointers. These callback functions get called under + various circumstances, and are always given the + <parameter>handle</parameter> as one of their parameters. + </para> + + <para> + The preemption callback, <parameter>pf</parameter>, is called when + the driver has claimed access to the port but another device driver + wants access. If the driver is willing to let the port go, it + should return zero and the port will be released on its behalf. + There is no need to call <function>parport_release</function>. If + <parameter>pf</parameter> gets called at a bad time for letting the + port go, it should return non-zero and no action will be taken. It + is good manners for the driver to try to release the port at the + earliest opportunity after its preemption callback is + called. + </para> + + <para> + The <quote>kick</quote> callback, <parameter>kf</parameter>, is + called when the port can be claimed for exclusive access; that is, + <function>parport_claim</function> is guaranteed to succeed inside + the <quote>kick</quote> callback. If the driver wants to claim the + port it should do so; otherwise, it need not take any + action. + </para> + + <para> + The <parameter>irq_func</parameter> callback is called, + predictably, when a parallel port interrupt is generated. But it + is not the only code that hooks on the interrupt. The sequence is + this: the lowlevel driver is the one that has done + <function>request_irq</function>; it then does whatever + hardware-specific things it needs to do to the parallel port + hardware (for PC-style ports, there is nothing special to do); it + then tells the IEEE 1284 code about the interrupt, which may + involve reacting to an IEEE 1284 event, depending on the current + IEEE 1284 phase; and finally the <parameter>irq_func</parameter> + function is called. + </para> + + <para> + None of the callback functions are allowed to block. + </para> + + <para> + The <parameter>flags</parameter> are for telling + <literal>parport</literal> any requirements or hints that are + useful. The only useful value here (other than + <constant>0</constant>, which is the usual value) is + <constant>PARPORT_DEV_EXCL</constant>. The point of that flag is + to request exclusive access at all times---once a driver has + successfully called <function>parport_register_device</function> + with that flag, no other device drivers will be able to register + devices on that port (until the successful driver deregisters its + device, of course). + </para> + + <para> + The <constant>PARPORT_DEV_EXCL</constant> flag is for preventing + port sharing, and so should only be used when sharing the port with + other device drivers is impossible and would lead to incorrect + behaviour. Use it sparingly! + </para> + + <para> + Devices can also be registered by device drivers based on their + device numbers (the same device numbers as in the previous + section). + </para> + + <para> + The <function>parport_open</function> function is similar to + <function>parport_register_device</function>, and + <function>parport_close</function> is the equivalent of + <function>parport_unregister_device</function>. The difference is + that <function>parport_open</function> takes a device number rather + than a pointer to a <structname>struct parport</structname>. + </para> + + <funcsynopsis> + <funcsynopsisinfo> +#include <parport.h> + </funcsynopsisinfo> + <funcprototype> + <funcdef>struct pardevice *<function>parport_open</function></funcdef> + <paramdef>int <parameter>devnum</parameter></paramdef> + <paramdef>int <parameter>(*pf)</parameter> + <funcparams>void *</funcparams></paramdef> + <paramdef>int <parameter>(*kf)</parameter> + <funcparams>void *</funcparams></paramdef> + <paramdef>int <parameter>(*irqf)</parameter> + <funcparams>int, void *, struct pt_regs *</funcparams></paramdef> + <paramdef>int <parameter>flags</parameter></paramdef> + <paramdef>void *<parameter>handle</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <funcsynopsis> + <funcprototype> + <funcdef>void <function>parport_close</function></funcdef> + <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <funcsynopsis> + <funcprototype> + <funcdef>struct pardevice *<function>parport_register_device</function></funcdef> + <paramdef>struct parport *<parameter>port</parameter></paramdef> + <paramdef>const char *<parameter>name</parameter></paramdef> + <paramdef>int <parameter>(*pf)</parameter> + <funcparams>void *</funcparams></paramdef> + <paramdef>int <parameter>(*kf)</parameter> + <funcparams>void *</funcparams></paramdef> + <paramdef>int <parameter>(*irqf)</parameter> + <funcparams>int, void *, struct pt_regs *</funcparams></paramdef> + <paramdef>int <parameter>flags</parameter></paramdef> + <paramdef>void *<parameter>handle</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <funcsynopsis> + <funcprototype> + <funcdef>void <function>parport_unregister_device</function></funcdef> + <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <para> + The intended use of these functions is during driver initialisation + while the driver looks for devices that it supports, as + demonstrated by the following code fragment: + </para> + + <programlisting> + <![CDATA[ +int devnum = -1; +while ((devnum = parport_find_class (PARPORT_CLASS_DIGCAM, + devnum)) != -1) { + struct pardevice *dev = parport_open (devnum, ...); + ... +} + ]]></programlisting> + + <para> + Once your device driver has registered its device and been handed a + pointer to a <structname>struct pardevice</structname>, the next + thing you are likely to want to do is communicate with the device + you think is there. To do that you'll need to claim access to the + port. + </para> + + <funcsynopsis> + <funcsynopsisinfo> +#include <parport.h> + </funcsynopsisinfo> + <funcprototype> + <funcdef>int <function>parport_claim</function></funcdef> + <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <funcsynopsis> + <funcprototype> + <funcdef>int <function>parport_claim_or_block</function></funcdef> + <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <funcsynopsis> + <funcprototype> + <funcdef>void <function>parport_release</function></funcdef> + <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <para> + To claim access to the port, use <function>parport_claim</function> + or <function>parport_claim_or_block</function>. The first of these + will not block, and so can be used from interrupt context. If + <function>parport_claim</function> succeeds it will return zero and + the port is available to use. It may fail (returning non-zero) if + the port is in use by another driver and that driver is not willing + to relinquish control of the port. + </para> + + <para> + The other function, <function>parport_claim_or_block</function>, + will block if necessary to wait for the port to be free. If it + slept, it returns <constant>1</constant>; if it succeeded without + needing to sleep it returns <constant>0</constant>. If it fails it + will return a negative error code. + </para> + + <para> + When you have finished communicating with the device, you can give + up access to the port so that other drivers can communicate with + their devices. The <function>parport_release</function> function + cannot fail, but it should not be called without the port claimed. + Similarly, you should not try to claim the port if you already have + it claimed. + </para> + + <para> + You may find that although there are convenient points for your + driver to relinquish the parallel port and allow other drivers to + talk to their devices, it would be preferable to keep hold of the + port. The printer driver only needs the port when there is data to + print, for example, but a network driver (such as PLIP) could be + sent a remote packet at any time. With PLIP, it is no huge + catastrophe if a network packet is dropped, since it will likely be + sent again, so it is possible for that kind of driver to share the + port with other (pass-through) devices. + </para> + + <para> + The <function>parport_yield</function> and + <function>parport_yield_blocking</function> functions are for + marking points in the driver at which other drivers may claim the + port and use their devices. Yielding the port is similar to + releasing it and reclaiming it, but is more efficient because + nothing is done if there are no other devices needing the port. In + fact, nothing is done even if there are other devices waiting but + the current device is still within its <quote>timeslice</quote>. + The default timeslice is half a second, but it can be adjusted via + a <filename>/proc</filename> entry. + </para> + + <funcsynopsis> + <funcsynopsisinfo> +#include <parport.h> + </funcsynopsisinfo> + <funcprototype> + <funcdef>int <function>parport_yield</function></funcdef> + <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <funcsynopsis> + <funcprototype> + <funcdef>int <function>parport_yield_blocking</function></funcdef> + <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <para> + The first of these, <function>parport_yield</function>, will not + block but as a result may fail. The return value for + <function>parport_yield</function> is the same as for + <function>parport_claim</function>. The blocking version, + <function>parport_yield_blocking</function>, has the same return + code as <function>parport_claim_or_block</function>. + </para> + + <para> + Once the port has been claimed, the device driver can use the + functions in the <structname>struct parport_operations</structname> + pointer in the <structname>struct parport</structname> it has a + pointer to. For example: + </para> + + <programlisting> + <![CDATA[ +port->ops->write_data (port, d); + ]]></programlisting> + + <para> + Some of these operations have <quote>shortcuts</quote>. For + instance, <function>parport_write_data</function> is equivalent to + the above, but may be a little bit faster (it's a macro that in + some cases can avoid needing to indirect through + <varname>port</varname> and <varname>ops</varname>). + </para> + + </chapter> + + <chapter id="portdrivers"> + <title>Port drivers</title> + + <!-- What port drivers are for (i.e. implementing parport objects). --> + + <para> + To recap, then:</para> + + <itemizedlist spacing=compact> + + <listitem> + <para> + The device driver registers itself with <literal>parport</literal>. + </para> + </listitem> + + <listitem> + <para> + A low-level driver finds a parallel port and registers it with + <literal>parport</literal> (these first two things can happen + in either order). This registration creates a <structname>struct + parport</structname> which is linked onto a list of known ports. + </para> + </listitem> + + <listitem> + <para> + <literal>parport</literal> calls the + <function>attach</function> function of each registered device + driver, passing it the pointer to the new <structname>struct + parport</structname>. + </para> + </listitem> + + <listitem> + <para> + The device driver gets a handle from + <literal>parport</literal>, for use with + <function>parport_claim</function>/<function>release</function>. + This handle takes the form of a pointer to a <structname>struct + pardevice</structname>, representing a particular device on the + parallel port, and is acquired using + <function>parport_register_device</function>. + </para> + </listitem> + + <listitem> + <para> + The device driver claims the port using + <function>parport_claim</function> (or + <function>function_claim_or_block</function>). + </para> + </listitem> + + <listitem> + <para> + Then it goes ahead and uses the port. When finished it releases + the port. + </para> + </listitem> + + </itemizedlist> + + <para> + The purpose of the low-level drivers, then, is to detect parallel + ports and provide methods of accessing them (i.e. implementing the + operations in <structname>struct + parport_operations</structname>). + </para> + + <!-- Should DocBookise this --> + <para> + A more complete description of which operation is supposed to do + what is available in + <filename>Documentation/parport-lowlevel.txt</filename>. + </para> + + </chapter> + + <chapter id="lp"> + <title>The printer driver</title> + + <!-- Talk the reader through the printer driver. --> + <!-- Could even talk about parallel port console here. --> + + <para> + The printer driver, <literal>lp</literal> is a character special + device driver and a <literal>parport</literal> client. As a + character special device driver it registers a <structname>struct + file_operations</structname> using + <function>register_chrdev</function>, with pointers filled in for + <structfield>write</structfield>, <structfield>ioctl</structfield>, + <structfield>open</structfield> and + <structfield>release</structfield>. As a client of + <literal>parport</literal>, it registers a <structname>struct + parport_driver</structname> using + <function>parport_register_driver</function>, so that + <literal>parport</literal> knows to call + <function>lp_attach</function> when a new parallel port is + discovered (and <function>lp_detach</function> when it goes + away). + </para> + + <para> + The parallel port console functionality is also implemented in + <filename>drivers/char/lp.c</filename>, but that won't be covered + here (it's quite simple though). + </para> + + <para> + The initialisation of the driver is quite easy to understand (see + <function>lp_init</function>). The <varname>lp_table</varname> is + an array of structures that contain information about a specific + device (the <structname>struct pardevice</structname> associated + with it, for example). That array is initialised to sensible + values first of all. + </para> + + <para> + Next, the printer driver calls <function>register_chrdev</function> + passing it a pointer to <varname>lp_fops</varname>, which contains + function pointers for the printer driver's implementation of + <function>open</function>, <function>write</function>, and so on. + This part is the same as for any character special device + driver. + </para> + + <para> + After successfully registering itself as a character special device + driver, the printer driver registers itself as a + <literal>parport</literal> client using + <function>parport_register_driver</function>. It passes a pointer + to this structure: + </para> + + <programlisting> + <![CDATA[ +static struct parport_driver lp_driver = { + "lp", + lp_attach, + lp_detach, + NULL +}; + ]]></programlisting> + + <para> + The <function>lp_detach</function> function is not very interesting + (it does nothing); the interesting bit is + <function>lp_attach</function>. What goes on here depends on + whether the user supplied any parameters. The possibilities are: + no parameters supplied, in which case the printer driver uses every + port that is detected; the user supplied the parameter + <quote>auto</quote>, in which case only ports on which the device + ID string indicates a printer is present are used; or the user + supplied a list of parallel port numbers to try, in which case only + those are used. + </para> + + <para> + For each port that the printer driver wants to use (see + <function>lp_register</function>), it calls + <function>parport_register_device</function> and stores the + resulting <structname>struct pardevice</structname> pointer in the + <varname>lp_table</varname>. If the user told it to do so, it then + resets the printer. + </para> + + <para> + The other interesting piece of the printer driver, from the point + of view of <literal>parport</literal>, is + <function>lp_write</function>. In this function, the user space + process has data that it wants printed, and the printer driver + hands it off to the <literal>parport</literal> code to deal with. + </para> + + <para> + The <literal>parport</literal> functions it uses that we have not + seen yet are <function>parport_negotiate</function>, + <function>parport_set_timeout</function>, and + <function>parport_write</function>. These functions are part of + the IEEE 1284 implementation. + </para> + + <para> + The way the IEEE 1284 protocol works is that the host tells the + peripheral what transfer mode it would like to use, and the + peripheral either accepts that mode or rejects it; if the mode is + rejected, the host can try again with a different mode. This is + the negotation phase. Once the peripheral has accepted a + particular transfer mode, data transfer can begin that mode. + </para> + + <para> + The particular transfer mode that the printer driver wants to use + is named in IEEE 1284 as <quote>compatibility</quote> mode, and the + function to request a particular mode is called + <function>parport_negotiate</function>. + </para> + + <funcsynopsis> + <funcsynopsisinfo> +#include <parport.h> + </funcsynopsisinfo> + <funcprototype> + <funcdef>int <function>parport_negotiate</function></funcdef> + <paramdef>struct parport *<parameter>port</parameter></paramdef> + <paramdef>int <parameter>mode</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <para> + The <parameter>modes</parameter> parameter is a symbolic constant + representing an IEEE 1284 mode; in this instance, it is + <constant>IEEE1284_MODE_COMPAT</constant>. (Compatibility mode is + slightly different to the other modes---rather than being + specifically requested, it is the default until another mode is + selected.) + </para> + + <para> + Back to <function>lp_write</function> then. First, access to the + parallel port is secured with + <function>parport_claim_or_block</function>. At this point the + driver might sleep, waiting for another driver (perhaps a Zip drive + driver, for instance) to let the port go. Next, it goes to + compatibility mode using <function>parport_negotiate</function>. + </para> + + <para> + The main work is done in the write-loop. In particular, the line + that hands the data over to <literal>parport</literal> reads: + </para> -<varlistentry><term><constant>PPWCTLONIRQ</constant></term> -<listitem> +<programlisting> +<![CDATA[ + written = parport_write (port, kbuf, copy_size); +]]></programlisting> -<para>Set a trigger response. Afterwards when an interrupt is -triggered, the interrupt handler will set the control lines as -requested. The <function>ioctl</function> parameter is a pointer to -an <type>unsigned char</type>, which is interpreted in the same way as -for <constant>PPWCONTROL</constant>.</para> + <para> + The <function>parport_write</function> function writes data to the + peripheral using the currently selected transfer mode + (compatibility mode, in this case). It returns the number of bytes + successfully written: + </para> + + <funcsynopsis> + <funcsynopsisinfo> +#include <parport.h> + </funcsynopsisinfo> + <funcprototype> + <funcdef>ssize_t <function>parport_write</function></funcdef> + <paramdef>struct parport *<parameter>port</parameter></paramdef> + <paramdef>const void *<parameter>buf</parameter></paramdef> + <paramdef>size_t <parameter>len</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <funcsynopsis> + <funcprototype> + <funcdef>ssize_t <function>parport_read</function></funcdef> + <paramdef>struct parport *<parameter>port</parameter></paramdef> + <paramdef>void *<parameter>buf</parameter></paramdef> + <paramdef>size_t <parameter>len</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <para> + (<function>parport_read</function> does what it sounds like, but + only works for modes in which reverse transfer is possible. Of + course, <function>parport_write</function> only works in modes in + which forward transfer is possible, too.) + </para> + + <para> + The <parameter>buf</parameter> pointer should be to kernel space + memory, and obviously the <parameter>len</parameter> parameter + specifies the amount of data to transfer. + </para> + + <para> + In fact what <function>parport_write</function> does is call the + appropriate block transfer function from the <structname>struct + parport_operations</structname>: + </para> + + <programlisting> + <![CDATA[ +struct parport_operations { + [...] -<para>The reason for this <function>ioctl</function> is simply speed. -Without this <function>ioctl</function>, responding to an interrupt -would start in the interrupt handler, switch context to the user-land -driver via <function>poll</function> or <function>select</function>, -and then switch context back to the kernel in order to handle -<constant>PPWCONTROL</constant>. Doing the whole lot in the interrupt -handler is a lot faster.</para> + /* Block read/write */ + size_t (*epp_write_data) (struct parport *port, + const void *buf, + size_t len, int flags); + size_t (*epp_read_data) (struct parport *port, + void *buf, size_t len, + int flags); + size_t (*epp_write_addr) (struct parport *port, + const void *buf, + size_t len, int flags); + size_t (*epp_read_addr) (struct parport *port, + void *buf, size_t len, + int flags); -</listitem></varlistentry> + size_t (*ecp_write_data) (struct parport *port, + const void *buf, + size_t len, int flags); + size_t (*ecp_read_data) (struct parport *port, + void *buf, size_t len, + int flags); + size_t (*ecp_write_addr) (struct parport *port, + const void *buf, + size_t len, int flags); -<!-- PPSETPHASE? --> + size_t (*compat_write_data) (struct parport *port, + const void *buf, + size_t len, int flags); + size_t (*nibble_read_data) (struct parport *port, + void *buf, size_t len, + int flags); + size_t (*byte_read_data) (struct parport *port, + void *buf, size_t len, + int flags); +}; + ]]></programlisting> + + <para> + The transfer code in <literal>parport</literal> will tolerate a + data transfer stall only for so long, and this timeout can be + specified with <function>parport_set_timeout</function>, which + returns the previous timeout: + </para> + + <funcsynopsis> + <funcsynopsisinfo> +#include <parport.h> + </funcsynopsisinfo> + <funcprototype> + <funcdef>long <function>parport_set_timeout</function></funcdef> + <paramdef>struct pardevice *<parameter>dev</parameter></paramdef> + <paramdef>long <parameter>inactivity</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <para> + This timeout is specific to the device, and is restored on + <function>parport_claim</function>. + </para> + + <para> + The next function to look at is the one that allows processes to + read from <filename>/dev/lp0</filename>: + <function>lp_read</function>. It's short, like + <function>lp_write</function>. + </para> + + <para> + The semantics of reading from a line printer device are as follows: + </para> + + <itemizedlist> + <listitem> + <para> + Switch to reverse nibble mode. + </para> + </listitem> + + <listitem> + <para> + Try to read data from the peripheral using reverse nibble mode, + until either the user-provided buffer is full or the peripheral + indicates that there is no more data. + </para> + </listitem> + + <listitem> + <para> + If there was data, stop, and return it. + </para> + </listitem> + + <listitem> + <para> + Otherwise, we tried to read data and there was none. If the user + opened the device node with the <constant>O_NONBLOCK</constant> + flag, return. Otherwise wait until an interrupt occurs on the + port (or a timeout elapses). + </para> + </listitem> + </itemizedlist> + + </chapter> + + <chapter id="ppdev"> + <title>User-level device drivers</title> + + <!-- ppdev --> + <sect1> + <title>Introduction to ppdev</title> -</variablelist> + <para> + The printer is accessible through <filename>/dev/lp0</filename>; + in the same way, the parallel port itself is accessible through + <filename>/dev/parport0</filename>. The difference is in the + level of control that you have over the wires in the parallel port + cable. + </para> -</sect2> + <para> + With the printer driver, a user-space program (such as the printer + spooler) can send bytes in <quote>printer protocol</quote>. + Briefly, this means that for each byte, the eight data lines are + set up, then a <quote>strobe</quote> line tells the printer to + look at the data lines, and the printer sets an + <quote>acknowledgement</quote> line to say that it got the byte. + The printer driver also allows the user-space program to read + bytes in <quote>nibble mode</quote>, which is a way of + transferring data from the peripheral to the computer half a byte + at a time (and so it's quite slow). + </para> -<sect2> -<title>Transferring data: <function>read</function> and -<function>write</function></title> + <para> + In contrast, the <literal>ppdev</literal> driver (accessed via + <filename>/dev/parport0</filename>) allows you to: + </para> -<para>Transferring data using <function>read</function> and -<function>write</function> is straightforward. The data is -transferring using the current IEEE 1284 mode (see the -<constant>PPSETMODE</constant> <function>ioctl</function>). For modes -which can only transfer data in one direction, only the appropriate -function will work, of course.</para> -</sect2> + <itemizedlist spacing=compact> + + <listitem> + <para> + examine status lines, + </para> + </listitem> + + <listitem> + <para> + set control lines, + </para> + </listitem> + + <listitem> + <para> + set/examine data lines (and control the direction of the data + lines), + </para> + </listitem> + + <listitem> + <para> + wait for an interrupt (triggered by one of the status lines), + </para> + </listitem> + + <listitem> + <para> + find out how many new interrupts have occurred, + </para> + </listitem> + + <listitem> + <para> + set up a response to an interrupt, + </para> + </listitem> + + <listitem> + <para> + use IEEE 1284 negotiation (for telling peripheral which transfer + mode, to use) + </para> + </listitem> + + <listitem> + <para> + transfer data using a specified IEEE 1284 mode. + </para> + </listitem> + + </itemizedlist> + + </sect1> + + <sect1> + <title>User-level or kernel-level driver?</title> -<sect2> -<title>Waiting for events: <function>poll</function> and -<function>select</function></title> + <para> + The decision of whether to choose to write a kernel-level device + driver or a user-level device driver depends on several factors. + One of the main ones from a practical point of view is speed: + kernel-level device drivers get to run faster because they are not + preemptable, unlike user-level applications. + </para> -<para>The <filename>ppdev</filename> driver provides user-land device -drivers with the ability to wait for interrupts, and this is done -using <function>poll</function> (and <function>select</function>, -which is implemented in terms of <function>poll</function>).</para> + <para> + Another factor is ease of development. It is in general easier to + write a user-level driver because (a) one wrong move does not + result in a crashed machine, (b) you have access to user libraries + (such as the C library), and (c) debugging is easier. + </para> -<para>When a user-land device driver wants to wait for an interrupt, -it sleeps with <function>poll</function>. When the interrupt arrives, -<filename>ppdev</filename> wakes it up (with a <quote>read</quote> -event, although strictly speaking there is nothing to actually -<function>read</function>).</para> + </sect1> -</sect2> + <sect1> + <title>Programming interface</title> -</sect1> + <para> + The <literal>ppdev</literal> interface is largely the same as that + of other character special devices, in that it supports + <function>open</function>, <function>close</function>, + <function>read</function>, <function>write</function>, and + <function>ioctl</function>. The constants for the + <function>ioctl</function> commands are in + <filename>include/linux/ppdev.h</filename>. + </para> -<sect1> -<title>Examples</title> + <sect2> + <title> + Starting and stopping: <function>open</function> and + <function>close</function> + </title> + + <para> + The device node <filename>/dev/parport0</filename> represents any + device that is connected to <filename>parport0</filename>, the + first parallel port in the system. Each time the device node is + opened, it represents (to the process doing the opening) a + different device. It can be opened more than once, but only one + instance can actually be in control of the parallel port at any + time. A process that has opened + <filename>/dev/parport0</filename> shares the parallel port in + the same way as any other device driver. A user-land driver may + be sharing the parallel port with in-kernel device drivers as + well as other user-land drivers. + </para> + </sect2> + + <sect2> + <title>Control: <function>ioctl</function></title> + + <para> + Most of the control is done, naturally enough, via the + <function>ioctl</function> call. Using + <function>ioctl</function>, the user-land driver can control both + the <literal>ppdev</literal> driver in the kernel and the + physical parallel port itself. The <function>ioctl</function> + call takes as parameters a file descriptor (the one returned from + opening the device node), a command, and optionally (a pointer + to) some data. + </para> + + <variablelist> + <varlistentry><term><constant>PPCLAIM</constant></term> + <listitem> + + <para> + Claims access to the port. As a user-land device driver + writer, you will need to do this before you are able to + actually change the state of the parallel port in any way. + Note that some operations only affect the + <literal>ppdev</literal> driver and not the port, such as + <constant>PPSETMODE</constant>; they can be performed while + access to the port is not claimed. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPEXCL</constant></term> + <listitem> + + <para> + Instructs the kernel driver to forbid any sharing of the port + with other drivers, i.e. it requests exclusivity. The + <constant>PPEXCL</constant> command is only valid when the + port is not already claimed for use, and it may mean that the + next <constant>PPCLAIM</constant> <function>ioctl</function> + will fail: some other driver may already have registered + itself on that port. + </para> + + <para> + Most device drivers don't need exclusive access to the port. + It's only provided in case it is really needed, for example + for devices where access to the port is required for extensive + periods of time (many seconds). + </para> + + <para> + Note that the <constant>PPEXCL</constant> + <function>ioctl</function> doesn't actually claim the port + there and then---action is deferred until the + <constant>PPCLAIM</constant> <function>ioctl</function> is + performed. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPRELEASE</constant></term> + <listitem> + + <para> + Releases the port. Releasing the port undoes the effect of + claiming the port. It allows other device drivers to talk to + their devices (assuming that there are any). + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPYIELD</constant></term> + <listitem> + + <para> + Yields the port to another driver. This + <function>ioctl</function> is a kind of short-hand for + releasing the port and immediately reclaiming it. It gives + other drivers a chance to talk to their devices, but + afterwards claims the port back. An example of using this + would be in a user-land printer driver: once a few characters + have been written we could give the port to another device + driver for a while, but if we still have characters to send to + the printer we would want the port back as soon as possible. + </para> + + <para> + It is important not to claim the parallel port for too long, + as other device drivers will have no time to service their + devices. If your device does not allow for parallel port + sharing at all, it is better to claim the parallel port + exclusively (see <constant>PPEXCL</constant>). + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPNEGOT</constant></term> + <listitem> + + <para> + Performs IEEE 1284 negotiation into a particular mode. + Briefly, negotiation is the method by which the host and the + peripheral decide on a protocol to use when transferring data. + </para> + + <para> + An IEEE 1284 compliant device will start out in compatibility + mode, and then the host can negotiate to another mode (such as + ECP). + </para> + + <para> + The <function>ioctl</function> parameter should be a pointer + to an <type>int</type>; values for this are in + <filename>incluce/linux/parport.h</filename> and include: + </para> + + <itemizedlist spacing=compact> + <listitem><para> + <constant>IEEE1284_MODE_COMPAT</constant></para></listitem> + <listitem><para> + <constant>IEEE1284_MODE_NIBBLE</constant></para></listitem> + <listitem><para> + <constant>IEEE1284_MODE_BYTE</constant></para></listitem> + <listitem><para> + <constant>IEEE1284_MODE_EPP</constant></para></listitem> + <listitem><para> + <constant>IEEE1284_MODE_ECP</constant></para></listitem> + </itemizedlist> + + <para> + The <constant>PPNEGOT</constant> <function>ioctl</function> + actually does two things: it performs the on-the-wire + negotiation, and it sets the behaviour of subsequent + <function>read</function>/<function>write</function> calls so + that they use that mode (but see + <constant>PPSETMODE</constant>). + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPSETMODE</constant></term> + <listitem> + + <para> + Sets which IEEE 1284 protocol to use for the + <function>read</function> and <function>write</function> + calls. + </para> + + <para> + The <function>ioctl</function> parameter should be a pointer + to an <type>int</type>. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPGETTIME</constant></term> + <listitem> + + <para> + Retrieves the time-out value. The <function>read</function> + and <function>write</function> calls will time out if the + peripheral doesn't respond quickly enough. The + <constant>PPGETTIME</constant> <function>ioctl</function> + retrieves the length of time that the peripheral is allowed to + have before giving up. + </para> + + <para> + The <function>ioctl</function> parameter should be a pointer + to a <structname>struct timeval</structname>. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPSETTIME</constant></term> + <listitem> + + <para> + Sets the time-out. The <function>ioctl</function> parameter + should be a pointer to a <structname>struct + timeval</structname>. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPWCONTROL</constant></term> + <listitem> + + <para> + Sets the control lines. The <function>ioctl</function> + parameter is a pointer to an <type>unsigned char</type>, the + bitwise OR of the control line values in + <filename>include/linux/parport.h</filename>. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPRCONTROL</constant></term> + <listitem> + + <para> + Returns the last value written to the control register, in the + form of an <type>unsigned char</type>: each bit corresponds to + a control line (although some are unused). The + <function>ioctl</function> parameter should be a pointer to an + <type>unsigned char</type>. + </para> + + <para> + This doesn't actually touch the hardware; the last value + written is remembered in software. This is because some + parallel port hardware does not offer read access to the + control register. + </para> + + <para> + The control lines bits are defined in + <filename>include/linux/parport.h</filename>: + </para> + + <itemizedlist spacing=compact> + <listitem><para> + <constant>PARPORT_CONTROL_STROBE</constant></para></listitem> + <listitem><para> + <constant>PARPORT_CONTROL_AUTOFD</constant></para></listitem> + <listitem><para> + <constant>PARPORT_CONTROL_SELECT</constant></para></listitem> + <listitem><para> + <constant>PARPORT_CONTROL_INIT</constant></para></listitem> + </itemizedlist> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPFCONTROL</constant></term> + <listitem> + + <para> + Frobs the control lines. Since a common operation is to + change one of the control signals while leaving the others + alone, it would be quite inefficient for the user-land driver + to have to use <constant>PPRCONTROL</constant>, make the + change, and then use <constant>PPWCONTROL</constant>. Of + course, each driver could remember what state the control + lines are supposed to be in (they are never changed by + anything else), but in order to provide + <constant>PPRCONTROL</constant>, <literal>ppdev</literal> + must remember the state of the control lines anyway. + </para> + + <para> + The <constant>PPFCONTROL</constant> <function>ioctl</function> + is for <quote>frobbing</quote> control lines, and is like + <constant>PPWCONTROL</constant> but acts on a restricted set + of control lines. The <function>ioctl</function> parameter is + a pointer to a <structname>struct + ppdev_frob_struct</structname>: + </para> + + <programlisting> + <![CDATA[ +struct ppdev_frob_struct { + unsigned char mask; + unsigned char val; +}; + ]]> + </programlisting> + + <para> + The <structfield>mask</structfield> and + <structfield>val</structfield> fields are bitwise ORs of + control line names (such as in + <constant>PPWCONTROL</constant>). The operation performed by + <constant>PPFCONTROL</constant> is: + </para> + + <programlisting> + <![CDATA[ + new_ctr = (old_ctr & ~mask) | val;]]> + </programlisting> + + <para> + In other words, the signals named in + <structfield>mask</structfield> are set to the values in + <structfield>val</structfield>. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPRSTATUS</constant></term> + <listitem> + + <para> + Returns an <type>unsigned char</type> containing bits set for + each status line that is set (for instance, + <constant>PARPORT_STATUS_BUSY</constant>). The + <function>ioctl</function> parameter should be a pointer to an + <type>unsigned char</type>. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPDATADIR</constant></term> + <listitem> + + <para> + Controls the data line drivers. Normally the computer's + parallel port will drive the data lines, but for byte-wide + transfers from the peripheral to the host it is useful to turn + off those drivers and let the peripheral drive the + signals. (If the drivers on the computer's parallel port are + left on when this happens, the port might be damaged.) + </para> + + <para> + This is only needed in conjunction with + <constant>PPWDATA</constant> or + <constant>PPRDATA</constant>. + </para> + + <para> + The <function>ioctl</function> parameter is a pointer to an + <type>int</type>. If the <type>int</type> is zero, the + drivers are turned on (forward direction); if non-zero, the + drivers are turned off (reverse direction). + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPWDATA</constant></term> + <listitem> + + <para> + Sets the data lines (if in forward mode). The + <function>ioctl</function> parameter is a pointer to an + <type>unsigned char</type>. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPRDATA</constant></term> + <listitem> + + <para> + Reads the data lines (if in reverse mode). The + <function>ioctl</function> parameter is a pointer to an + <type>unsigned char</type>. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPCLRIRQ</constant></term> + <listitem> + + <para> + Clears the interrupt count. The <literal>ppdev</literal> + driver keeps a count of interrupts as they are triggered. + <constant>PPCLRIRQ</constant> stores this count in an + <type>int</type>, a pointer to which is passed in as the + <function>ioctl</function> parameter. + </para> + + <para> + In addition, the interrupt count is reset to zero. + </para> + + </listitem></varlistentry> + + <varlistentry><term><constant>PPWCTLONIRQ</constant></term> + <listitem> + + <para> + Set a trigger response. Afterwards when an interrupt is + triggered, the interrupt handler will set the control lines as + requested. The <function>ioctl</function> parameter is a + pointer to an <type>unsigned char</type>, which is interpreted + in the same way as for <constant>PPWCONTROL</constant>. + </para> + + <para> + The reason for this <function>ioctl</function> is simply + speed. Without this <function>ioctl</function>, responding to + an interrupt would start in the interrupt handler, switch + context to the user-land driver via <function>poll</function> + or <function>select</function>, and then switch context back + to the kernel in order to handle + <constant>PPWCONTROL</constant>. Doing the whole lot in the + interrupt handler is a lot faster. + </para> + + </listitem></varlistentry> + + <!-- PPSETPHASE? --> + + </variablelist> + + </sect2> + + <sect2> + <title>Transferring data: <function>read</function> and + <function>write</function></title> + + <para> + Transferring data using <function>read</function> and + <function>write</function> is straightforward. The data is + transferring using the current IEEE 1284 mode (see the + <constant>PPSETMODE</constant> <function>ioctl</function>). For + modes which can only transfer data in one direction, only the + appropriate function will work, of course. + </para> + </sect2> + + <sect2> + <title>Waiting for events: <function>poll</function> and + <function>select</function></title> + + <para> + The <literal>ppdev</literal> driver provides user-land device + drivers with the ability to wait for interrupts, and this is done + using <function>poll</function> (and <function>select</function>, + which is implemented in terms of <function>poll</function>). + </para> + + <para> + When a user-land device driver wants to wait for an interrupt, it + sleeps with <function>poll</function>. When the interrupt + arrives, <literal>ppdev</literal> wakes it up (with a + <quote>read</quote> event, although strictly speaking there is + nothing to actually <function>read</function>). + </para> + + </sect2> + + </sect1> + + <sect1> + <title>Examples</title> -<para>Presented here are two demonstrations of how to write a simple -printer driver for <filename>ppdev</filename>. Firstly we will use -the <function>write</function> function, and after that we will drive -the control and data lines directly.</para> + <para> + Presented here are two demonstrations of how to write a simple + printer driver for <literal>ppdev</literal>. Firstly we will + use the <function>write</function> function, and after that we + will drive the control and data lines directly. + </para> -<para>The first thing to do is to actually open the device.</para> + <para> + The first thing to do is to actually open the device. + </para> -<programlisting><![CDATA[ + <programlisting><![CDATA[ int drive_printer (const char *name) { int fd; @@ -1543,32 +1953,39 @@ int drive_printer (const char *name) perror ("open"); return 1; } -]]></programlisting> + ]]></programlisting> -<para>Here <varname>name</varname> should be something along the lines -of <filename>"/dev/parport0"</filename>. (If you don't have any -<filename>/dev/parport</filename> files, you can make them with -<command>mknod</command>; they are character special device nodes with -major 99.)</para> + <para> + Here <varname>name</varname> should be something along the lines + of <filename>"/dev/parport0"</filename>. (If you don't have any + <filename>/dev/parport</filename> files, you can make them with + <command>mknod</command>; they are character special device nodes + with major 99.) + </para> -<para>In order to do anything with the port we need to claim access to -it.</para> + <para> + In order to do anything with the port we need to claim access to + it. + </para> -<programlisting><![CDATA[ + <programlisting><![CDATA[ if (ioctl (fd, PPCLAIM)) { perror ("PPCLAIM"); close (fd); return 1; } -]]></programlisting> + ]]></programlisting> -<para>Our printer driver will copy its input (from -<varname>stdin</varname>) to the printer, and it can do that it one of -two ways. The first way is to hand it all off to the kernel driver, -with the knowledge that the protocol that the printer speaks is IEEE -1284's <quote>compatibility</quote> mode.</para> + <para> + Our printer driver will copy its input (from + <varname>stdin</varname>) to the printer, and it can do that it + one of two ways. The first way is to hand it all off to the + kernel driver, with the knowledge that the protocol that the + printer speaks is IEEE 1284's <quote>compatibility</quote> + mode. + </para> -<programlisting><![CDATA[ + <programlisting><![CDATA[ /* Switch to compatibility mode. (In fact we don't need * to do this, since we start off in compatibility mode * anyway, but this demonstrates PPNEGOT.) @@ -1608,38 +2025,46 @@ with the knowledge that the protocol that the printer speaks is IEEE got -= written; } } -]]></programlisting> + ]]></programlisting> -<para>The <function>write_printer</function> function is not pictured -above. This is because the main loop that is shown can be used for -both methods of driving the printer. Here is one implementation of -<function>write_printer</function>:</para> + <para> + The <function>write_printer</function> function is not pictured + above. This is because the main loop that is shown can be used + for both methods of driving the printer. Here is one + implementation of <function>write_printer</function>: + </para> -<programlisting><![CDATA[ + <programlisting><![CDATA[ ssize_t write_printer (int fd, const void *ptr, size_t count) { return write (fd, ptr, count); } -]]></programlisting> + ]]></programlisting> -<para>We hand the data to the kernel-level driver (using -<function>write</function>) and it handles the printer -protocol.</para> + <para> + We hand the data to the kernel-level driver (using + <function>write</function>) and it handles the printer + protocol. + </para> -<para>Now let's do it the hard way! In this particular example there -is no practical reason to do anything other than just call -<function>write</function>, because we know that the printer talks an -IEEE 1284 protocol. On the other hand, this particular example does -not even need a user-land driver since there is already a kernel-level -one; for the purpose of this discussion, try to imagine that the -printer speaks a protocol that is not already implemented under -Linux.</para> + <para> + Now let's do it the hard way! In this particular example there is + no practical reason to do anything other than just call + <function>write</function>, because we know that the printer talks + an IEEE 1284 protocol. On the other hand, this particular example + does not even need a user-land driver since there is already a + kernel-level one; for the purpose of this discussion, try to + imagine that the printer speaks a protocol that is not already + implemented under Linux. + </para> -<para>So, here is the alternative implementation of -<function>write_printer</function> (for brevity, error checking has -been omitted):</para> + <para> + So, here is the alternative implementation of + <function>write_printer</function> (for brevity, error checking + has been omitted): + </para> -<programlisting><![CDATA[ + <programlisting><![CDATA[ ssize_t write_printer (int fd, const void *ptr, size_t count) { ssize_t wrote = 0; @@ -1690,13 +2115,15 @@ ssize_t write_printer (int fd, const void *ptr, size_t count) return wrote; } -]]></programlisting> + ]]></programlisting> -<para>To show a bit more of the <filename>ppdev</filename> interface, -here is a small piece of code that is intended to mimic the printer's -side of printer protocol.</para> + <para> + To show a bit more of the <literal>ppdev</literal> interface, + here is a small piece of code that is intended to mimic the + printer's side of printer protocol. + </para> -<programlisting><![CDATA[ + <programlisting><![CDATA[ for (;;) { int irqc; @@ -1739,9 +2166,158 @@ side of printer protocol.</para> putchar (ch); } -]]></programlisting> + ]]></programlisting> + + <para> + And here is an example (with no error checking at all) to show how + to read data from the port, using ECP mode, with optional + negotiation to ECP mode first. + </para> + + <programlisting><![CDATA[ + { + int fd, mode; + fd = open ("/dev/parport0", O_RDONLY | O_NOCTTY); + ioctl (fd, PPCLAIM); + mode = IEEE1284_MODE_ECP; + if (negotiate_first) { + ioctl (fd, PPNEGOT, &mode); + /* no need for PPSETMODE */ + } else { + ioctl (fd, PPSETMODE, &mode); + } + + /* Now do whatever we want with fd */ + close (0); + dup2 (fd, 0); + if (!fork()) { + /* child */ + execlp ("cat", "cat", NULL); + exit (1); + } else { + /* parent */ + wait (NULL); + } -</sect1> + /* Okay, finished */ + ioctl (fd, PPRELEASE); + close (fd); + } + ]]></programlisting> + + </sect1> + + </chapter> + + <appendix> + <title> + API reference + </title> + +!Fdrivers/parport/daisy.c parport_device_num +!Fdrivers/parport/daisy.c parport_device_coords +!Fdrivers/parport/daisy.c parport_find_device +!Fdrivers/parport/daisy.c parport_find_class +!Fdrivers/parport/share.c parport_register_driver +!Fdrivers/parport/share.c parport_unregister_driver +!Fdrivers/parport/share.c parport_register_device +!Fdrivers/parport/share.c parport_unregister_device +!Fdrivers/parport/daisy.c parport_open +!Fdrivers/parport/daisy.c parport_close +!Fdrivers/parport/share.c parport_claim +!Fdrivers/parport/share.c parport_claim_or_block +!Fdrivers/parport/share.c parport_release +!Finclude/linux/parport.h parport_yield +!Finclude/linux/parport.h parport_yield_blocking +!Fdrivers/parport/ieee1284.c parport_negotiate +!Fdrivers/parport/ieee1284.c parport_write +!Fdrivers/parport/ieee1284.c parport_read +!Fdrivers/parport/ieee1284.c parport_set_timeout + + </appendix> + + <appendix> + <title> + The Linux 2.2 Parallel Port Subsystem + </title> + + <para> + Although the interface described in this document is largely new + with the 2.4 kernel, the sharing mechanism is available in the 2.2 + kernel as well. The functions available in 2.2 are: + </para> + + <itemizedlist> + <listitem> + <para> + <function>parport_register_device</function> + </para> + </listitem> + + <listitem> + <para> + <function>parport_unregister_device</function> + </para> + </listitem> + + <listitem> + <para> + <function>parport_claim</function> + </para> + </listitem> + + <listitem> + <para> + <function>parport_claim_or_block</function> + </para> + </listitem> + + <listitem> + <para> + <function>parport_release</function> + </para> + </listitem> + + <listitem> + <para> + <function>parport_yield</function> + </para> + </listitem> + + <listitem> + <para> + <function>parport_yield_blocking</function> + </para> + </listitem> + </itemizedlist> + + <para> + In addition, negotiation to reverse nibble mode is supported: + </para> + + <funcsynopsis> + <funcprototype> + <funcdef>int <function>parport_ieee1284_nibble_mode_ok</function></funcdef> + <paramdef>struct parport *<parameter>port</parameter></paramdef> + <paramdef>unsigned char <parameter>mode</parameter></paramdef> + </funcprototype> + </funcsynopsis> + + <para> + The only valid values for <parameter>mode</parameter> are 0 (for + reverse nibble mode) and 4 (for Device ID in reverse nibble mode). + </para> + + <para> + This function is obsoleted by + <function>parport_negotiate</function> in Linux 2.4, and has been + removed. + </para> + </appendix> +</book> + +<!-- Local Variables: --> +<!-- sgml-indent-step: 1 --> +<!-- sgml-indent-data: 1 --> +<!-- End: --> -</chapter> -</book>
\ No newline at end of file diff --git a/Documentation/filesystems/cramfs.txt b/Documentation/filesystems/cramfs.txt index 9bbee1613..2bac03313 100644 --- a/Documentation/filesystems/cramfs.txt +++ b/Documentation/filesystems/cramfs.txt @@ -27,8 +27,8 @@ Only the low 8 bits of gid are stored. The current version of mkcramfs simply truncates to 8 bits, which is a potential security issue. -Hard links are not supported, but symlinks are. (See also the TODO -comment in mkcramfs.c at the nlink test.) +Hard links are supported, but hard linked files +will still have a link count of 1 in the cramfs image. Cramfs directories have no `.' or `..' entries. Directories (like every other file on cramfs) always have a link count of 1. (There's diff --git a/Documentation/kbuild/config-language.txt b/Documentation/kbuild/config-language.txt index c446e7ac3..b37dafb7e 100644 --- a/Documentation/kbuild/config-language.txt +++ b/Documentation/kbuild/config-language.txt @@ -193,7 +193,7 @@ output files. Configure: implemented Menuconfig: implemented -Xconfig: does not display, but writes to output files +Xconfig: implemented mconfig: implemented Example: diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt new file mode 100644 index 000000000..585d557ab --- /dev/null +++ b/Documentation/kernel-doc-nano-HOWTO.txt @@ -0,0 +1,128 @@ +kernel-doc nano-HOWTO +===================== + +Many places in the source tree have extractable documentation in the +form of block comments above functions. The components of this system +are: + +- scripts/kernel-doc + + This is a perl script that hunts for the block comments and can mark + them up directly into DocBook, man, text, and HTML. (No, not + texinfo.) + +- Documentation/DocBook/*.tmpl + + These are SGML template files, which are normal SGML files with + special place-holders for where the extracted documentation should + go. + +- scripts/docproc.c + + This is a program for converting SGML template files into SGML + files. It invokes kernel-doc, giving it the list of functions that + are to be documented. + +- scripts/gen-all-syms + + This is a script that lists the EXPORT_SYMBOL symbols in a list of C + files. + +- scripts/docgen + + This script invokes docproc, telling it which functions are to be + documented (this list comes from gen-all-syms). + +- Makefile + + The targets 'sgmldocs', 'psdocs', and 'pdfdocs' are used to build + DocBook files, PostScript files, and PDF files in + Documentation/DocBook. + +- Documentation/DocBook/Makefile + + This is where C files are associated with SGML templates. + + +How to extract the documentation +-------------------------------- + +If you just want to read the ready-made books on the various +subsystems (see Documentation/DocBook/*.tmpl), just type 'make +psdocs', or 'make pdfdocs', depending on your preference. If you +would rather read a different format, you can type 'make sgmldocs' and +then use DocBook tools to convert Documentation/DocBook/*.sgml to a +format of your choice (for example, 'db2html ...'). + +If you want to see man pages instead, you can do this: + +$ cd linux +$ scripts/kernel-doc -man $(find -name '*.c') | split-man.pl /tmp/man + +Here is split-man.pl: + +--> +#!/usr/bin/perl + +if ($#ARGV < 0) { + die "where do I put the results?\n"; +} + +mkdir $ARGV[0],0777 or die "Can't create $ARGV[0]: $!\n"; +$state = 0; +while (<STDIN>) { + if (/^\.TH \"[^\"]*\" 4 \"([^\"]*)\"/) { + if ($state == 1) { close OUT } + $state = 1; + $fn = "$ARGV[0]/$1.4"; + print STDERR "Creating $fn\n"; + open OUT, ">$fn" or die "can't open $fn: $!\n"; + print OUT $_; + } elsif ($state != 0) { + print OUT $_; + } +} + +close OUT; +<-- + +If you just want to view the documentation for one function in one +file, you can do this: + +$ scripts/kernel-doc -man -function fn file | nroff -man | less + +or this: + +$ scripts/kernel-doc -text -function fn file + + +How to add extractable documentation to your source files +--------------------------------------------------------- + +The format of the block comment is like this: + +/** + * function_name(:)? (- short description)? +(* @parameterx: (description of parameter x)?)* +(* a blank line)? + * (Description:)? (Description of function)? + * (section header: (section description)? )* +(*)?*/ + +The short function description cannot be multiline, but the other +descriptions can be. + +All descriptive text is further processed, scanning for the following special +patterns, which are highlighted appropriately. + +'funcname()' - function +'$ENVVAR' - environment variable +'&struct_name' - name of a structure (up to two words including 'struct') +'@parameter' - name of a parameter +'%CONST' - name of a constant. + +Take a look around the source tree for examples. + +Tim. +*/ <twaugh@redhat.com> + diff --git a/Documentation/networking/8139too.txt b/Documentation/networking/8139too.txt index 92427b679..879bf6d2f 100644 --- a/Documentation/networking/8139too.txt +++ b/Documentation/networking/8139too.txt @@ -132,6 +132,20 @@ And thanks to every supporter free software. +Submitting Bug Reports +---------------------- +Obtain and compile the modified rtl8139-diag source code from the +8139too driver Web site. This diagnostics programs, originally +from Donald Becker, has been modified to display all registers +on your RTL8139 chip, not just the first 0x80. + +If possible, send the output of a working and broken driver with + rtl8139-diag -mmmaaavvveefN > my-output-file.txt + +Send "lspci -vvv" or "cat /proc/pci" output for PCI information. + + + Known Bugs / Errata / To-Do --------------------------- The following issues are known, and are actively being pursued. Patches @@ -149,7 +163,7 @@ It is included only for enterprising hackers willing to help fix it. 4) Sparc64 platform not tested at all. -5) Identify and fix "rx wedge" when ping flooded. +5) Identify and fix "rx wedge" when ping flooded. (WIP) 7) N-Way auto-negotiation is known to fail in some cases. This problem also occurs in the rtl8139 driver in kernels 2.2.x/2.3.x. Solution: @@ -158,17 +172,30 @@ manually perform autonegotiation in case the network or card cannot do it automatically. (patches welcome) 8) Much improved command line / module parameter setup. (patches and -suggestions welcome) +suggestions welcome) (WIP) 9) Better documentation. (patches welcome) -10) User-mode (or maybe optional /proc) diagnostics program. +10) (rtl8139-diag modified from Becker version, DONE) +User-mode (or maybe optional /proc) diagnostics program. + +11) RTL8139C support untested. Change History -------------- +Version 0.9.5 - May 17, 2000 + +* Improved chip version recognition +* Continue banging away at receiver hang problem +* Use spin_lock_irq in another spot +* Don't print anything on pci_enable_device, it does so for us +* Disable buggy NWay code +* Define TxConfig bitmasks + + Version 0.9.4.1 - April 27, 2000 - third public beta release * Replace several "magic numbers" with symbolic constants diff --git a/Documentation/pci.txt b/Documentation/pci.txt index 63e035a93..b96f6c48f 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt @@ -89,6 +89,16 @@ Please mark the initialization and cleanup functions where appropriate function otherwise. __devexit The same for __exit. +Tips: + The module_init()/module_exit() functions (and all initialization + functions called only from these) should be marked __init/exit. + The struct pci_driver shouldn't be marked with any of these tags. + The ID table array should be marked __devinitdata. + The probe() and remove() functions (and all initialization + functions called only from these) should be marked __devinit/exit. + If you are sure the driver is not a hotplug driver then use only + __init/exit __initdata/exitdata. + 2. How to find PCI devices manually (the old style) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Documentation/s390/DASD b/Documentation/s390/DASD index b1cd0558a..6f8f9b527 100644 --- a/Documentation/s390/DASD +++ b/Documentation/s390/DASD @@ -22,7 +22,7 @@ The driver currently supports ECKD-devices and there are stubs for support of the FBA and CKD architectures. For the FBA architecture only some smart data structures are missing to make the support complete. -We performed our testing on 3380 and 3390 type disksof different +We performed our testing on 3380 and 3390 type disks of different sizes, under VM and on the bare hardware (LPAR), using internal disks of the multiprise as well as a RAMAC virtual array. Disks exported by an Enterprise Storage Server (Seascape) should work fine as well. diff --git a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt index 58efa7ccf..d57cc2e23 100644 --- a/Documentation/usb/ov511.txt +++ b/Documentation/usb/ov511.txt @@ -6,11 +6,8 @@ Author: Mark McClelland Homepage: http://alpha.dyndns.org/ov511 NEW IN THIS VERSION: - o Improvements to sensor detection code - o Added "i2c_detect_tries" and "aperture" parameters - o proc filesystem status support - o read() fixed partially - o code cleanups and minor fixes + o 352x288 mode + o force_rgb parameter for apps that expect RGB instead of BGR INTRODUCTION: @@ -139,7 +136,7 @@ MODULE PARAMETERS: or so lines higher than the red component. This is only apparent in images with white objects on black backgrounds at 640x480. Setting this to 1 will realign the color planes correctly. NOTE: This is still - experimental and very buggy. + experimental and very buggy. You will likely need a fast (500 Mhz) CPU. NAME: snapshot TYPE: integer (boolean) @@ -148,8 +145,41 @@ MODULE PARAMETERS: button is pressed. Note that this does not yet work with most apps, including xawtv and vidcat. NOTE: See the section "TODO" for more info. + NAME: sensor + TYPE: integer ([0, 1, 3]) + DEFAULT: [varies] + DESC: If you know that your camera sensor is not detected correctly, set this + parameter. This is a global option for all attached OV511 cameras. You + will probably never need to set this, but if you do, valid values are: + 0 for OV7620 + 1 for OV7620AE + 3 for OV7610 + + NAME: i2c_detect_tries + TYPE: integer (don't set it insanely high!) + DEFAULT: 5 + DESC: This is the number of times the driver will try to sync and detect the + internal i2c bus (which connects the OV511 and sensor). If you are + getting intermittant detection failures ("Failed to read sensor ID...") + you should increase this by a modest amount. If setting it to 20 or so + doesn't fix things, look elsewhere for the cause of the problem. + + NAME: aperture + TYPE: integer (0 - 15) + DEFAULT: [varies by sensor] + DESC: For legal values, see the OV7610/7620 specs under register Common F. + This setting affects the upper nybble of that reg (bits 4-7). This is + for if you want to play with the camera's pixel saturation. + + NAME: force_rgb + TYPE: integer (boolean) + DEFAULT: 0 + DESC: Force image to be read in RGB instead of BGR. This option allow + programs that expect RGB data (e.g. gqcam) to work with this driver. If + your colors look VERY wrong, you may want to change this. + WORKING FEATURES: - o Color streaming/capture at 640x480 and 320x240 + o Color streaming/capture at 640x480, 352x288, and 320x240 o YUV420 color o Monochrome o Setting/getting of saturation, contrast and brightness (no hue yet; only @@ -158,7 +188,7 @@ WORKING FEATURES: EXPERIMENTAL FEATURES: o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and - corrupted frames. + corrupted frames. If you have a very fast CPU, you can try it. o Snapshot mode (only works with some read() based apps; see below for more) o read() support @@ -197,6 +227,6 @@ CREDITS: The code is based in no small part on the CPiA driver by Johannes Erdfelt, Randy Dunlap, and others. Big thanks to them for their pioneering work on that -and the USB stack. Thanks to Bret Wallach for getting camera reg IO , ISOC, and -image capture working. Thanks to Orion Sky Lawlor and Kevin Moore for their -work as well. +and the USB stack. Thanks to Bret Wallach for getting camera reg IO, ISOC, and +image capture working. Thanks to Orion Sky Lawlor, Kevin Moore, and Claudio +Matsuoka for their work as well. diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt index 193ab6ddc..00248f36e 100644 --- a/Documentation/usb/usb-serial.txt +++ b/Documentation/usb/usb-serial.txt @@ -59,6 +59,13 @@ Current status: properly enumerated, assigned a port, and then communication _should_ be possible. The driver cleans up properly when the device is removed, or the connection is canceled on the Visor. + + NOTE: + This means that in order to talk to the Visor, the sync button must be + pressed BEFORE trying to get any program to communicate to the Visor. + This goes against the current documentation for pilot-xfer and other + packages, but is the only way that it will work due to the hardware + in the Visor. When the device is connected, try talking to it on the second port (this is usually /dev/ttyUSB1 if you do not have any other usb-serial @@ -107,6 +114,24 @@ ZyXEL omni.net lcd plus ISDN TA author at omninet@kroah.com +Digi AccelePort Driver + + This driver supports the Digi AccelePort USB 4 device, a 4 port + USB serial converter. The driver does NOT yet support the Digi + AccelePort USB 2 or 8. + + The driver supports open, close, read, write, termios settings (baud + rate, word size, parity, stop bits, hardware/software flow control, + CREAD), DTR/RTS, and TIOCMGET/SET/BIS/BIC ioctls. It has not been + thoroughly tested, but it seems to be working reasonable well. There + is more work to do, including flow control, ioctls, and support for + the Digi AccelePort USB 2 and 8. + + Please contact Peter Berger (pberger@brimson.com) or Al Borchers + (alborchers@steinerpoint.com) for questions or problems with this + driver. + + Generic Serial driver If your device is not one of the above listed devices, compatible with diff --git a/Documentation/video4linux/bttv/CARDLIST b/Documentation/video4linux/bttv/CARDLIST index e41e60edf..02ec58baa 100644 --- a/Documentation/video4linux/bttv/CARDLIST +++ b/Documentation/video4linux/bttv/CARDLIST @@ -38,6 +38,10 @@ bttv.o card=36 - Typhoon TView TV/FM Tuner card=37 - PixelView PlayTV pro card=38 - TView99 CPH063 + card=39 - Pinnacle PCTV Rave + card=40 - STB2 + card=41 - AVerMedia TVPhone 98 + card=42 - ProVideo PV951 tuner.o type=0 - Temic PAL |