summaryrefslogtreecommitdiffstats
path: root/Documentation
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-15 01:55:58 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-15 01:55:58 +0000
commit53b3988d474435254a3b053a68bb24ce9e439295 (patch)
treef8da8e40f01f4ad02bbd76b8c9920749b118235f /Documentation
parentb0cb48abe83d1a4389ea938bf624f8baa82c5047 (diff)
Merge with 2.3.99-pre9.
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/Configure.help18
-rw-r--r--Documentation/DocBook/Makefile17
-rw-r--r--Documentation/DocBook/kernel-api.tmpl5
-rw-r--r--Documentation/DocBook/kernel-hacking.tmpl1316
-rw-r--r--Documentation/DocBook/kernel-locking.tmpl1221
-rw-r--r--Documentation/DocBook/parportbook.tmpl3446
-rw-r--r--Documentation/filesystems/cramfs.txt4
-rw-r--r--Documentation/kbuild/config-language.txt2
-rw-r--r--Documentation/kernel-doc-nano-HOWTO.txt128
-rw-r--r--Documentation/networking/8139too.txt33
-rw-r--r--Documentation/pci.txt10
-rw-r--r--Documentation/s390/DASD2
-rw-r--r--Documentation/usb/ov511.txt52
-rw-r--r--Documentation/usb/usb-serial.txt25
-rw-r--r--Documentation/video4linux/bttv/CARDLIST4
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-&gt;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>&num;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(&amp;__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 -&gt; OK</entry>
+ <entry>Grab lock B -&gt; OK</entry>
+ </row>
+ <row>
+ <entry>Grab lock B -&gt; spin</entry>
+ <entry>Grab lock A -&gt; 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-&gt;next = i-&gt;next;
+ i-&gt;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-&gt;next = i-&gt;next;
+ wmb();
+ i-&gt;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-&gt;status &amp; IPS_CONFIRMED)) {
+ spin_lock_bh(&amp;ip_conntrack_lock);
+ if (!(ctrack-&gt;status &amp; IPS_CONFIRMED)) {
+ clean_from_lists(h-&gt;ctrack);
+ h-&gt;ctrack-&gt;status |= IPS_CONFIRMED;
+ }
+ spin_unlock_bh(&amp;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(&amp;x-&gt;use, 1);
+ spin_lock_bh(&amp;list_lock);
+ ... insert in list ...
+ spin_unlock_bh(&amp;list_lock);
+ }
+
+ struct foo *get_foo(int desc)
+ {
+ struct foo *ret;
+
+ spin_lock_bh(&amp;list_lock);
+ ... find in list ...
+ if (ret) atomic_inc(&amp;ret-&gt;use);
+ spin_unlock_bh(&amp;list_lock);
+
+ return ret;
+ }
+
+ void put_foo(struct foo *x)
+ {
+ if (atomic_dec_and_test(&amp;x-&gt;use))
+ kfree(foo);
+ }
+
+ void destroy_foo(struct foo *x)
+ {
+ spin_lock_bh(&amp;list_lock);
+ ... remove from list ...
+ spin_unlock_bh(&amp;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(&amp;list_lock);
+
+ while (list) {
+ struct foo *next = list-&gt;next;
+ del_timer(&amp;list-&gt;timer);
+ kfree(list);
+ list = next;
+ }
+
+ spin_unlock_bh(&amp;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(&amp;list_lock);
+
+ while (list) {
+ struct foo *next = list-&gt;next;
+ if (!del_timer(&amp;list-&gt;timer)) {
+ /* Give timer a chance to delete this */
+ spin_unlock_bh(&amp;list_lock);
+ goto retry;
+ }
+ kfree(list);
+ list = next;
+ }
+
+ spin_unlock_bh(&amp;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 &lt;parport.h&gt;
+ </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 &lt;parport.h&gt;
+ </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 &lt;parport.h&gt;
-</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 &lt;parport.h&gt;
+ </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 &lt;parport.h&gt;
+ </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 &lt;parport.h&gt;
+ </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 &lt;parport.h&gt;
+ </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 &lt;parport.h&gt;
+ </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 &lt;parport.h&gt;
+ </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 &lt;parport.h&gt;
+ </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