aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-04-26 09:03:46 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-04-26 09:03:46 -0700
commitf13fcc318ff7dbc3738420d145ca353bd8ebada7 (patch)
treee9cd1eb1318c67b9c983a515996c5cc6715e2a7a /Documentation
parentc44d197447c984b4e008e2683a5c6885a9169742 (diff)
downloadhistory-f13fcc318ff7dbc3738420d145ca353bd8ebada7.tar.gz
[PATCH] remove Documentation/DocBook/parportbook.tmpl
From: Christoph Hellwig <hch@lst.de> The partportbook is licensed under the GFDL and Linus agreed to remove all GFDL licensed files in http://www.ussg.iu.edu/hypermail/linux/kernel/0306.1/1968.html. I pinged the author the first time on the 2nd of april but still didn't get a reply, then send a patch to Linus to remove it last week but linus ignored it. Here's the patch again:
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/DocBook/Makefile21
-rw-r--r--Documentation/DocBook/parport-multi.fig59
-rw-r--r--Documentation/DocBook/parport-share.fig154
-rw-r--r--Documentation/DocBook/parport-structure.fig60
-rw-r--r--Documentation/DocBook/parportbook.tmpl2735
5 files changed, 4 insertions, 3025 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 90957636b4c83d..bf212c0211c9ec 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -7,11 +7,10 @@
# list of DOCBOOKS.
DOCBOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \
- parportbook.sgml kernel-hacking.sgml \
- kernel-locking.sgml via-audio.sgml mousedrivers.sgml \
- deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \
- writing_usb_driver.sgml scsidrivers.sgml sis900.sgml \
- kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml \
+ kernel-hacking.sgml kernel-locking.sgml via-audio.sgml \
+ mousedrivers.sgml deviceiobook.sgml procfs-guide.sgml \
+ tulip-user.sgml writing_usb_driver.sgml scsidrivers.sgml \
+ sis900.sgml kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml \
gadget.sgml libata.sgml
###
@@ -93,16 +92,6 @@ C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example))
$(obj)/procfs-guide.sgml: $(C-procfs-example2)
###
-# The parportbook includes a few images.
-# Force them to be build before the books
-IMG-parportbook := parport-share.fig parport-multi.fig parport-structure.fig
-IMG-parportbook2 := $(addprefix $(obj)/,$(IMG-parportbook))
-EPS-parportbook := $(patsubst %.fig,%.eps, $(IMG-parportbook2))
-PNG-parportbook := $(patsubst %.fig,%.png, $(IMG-parportbook2))
-$(obj)/parportbook.html: $(PNG-parportbook)
-$(obj)/parportbook.ps $(obj)/parportbook.pdf: $(EPS-parportbook) $(PNG-parportbook)
-
-###
# Rules to generate postscript, PDF and HTML
# db2html creates a directory. Generate a html file used for timestamp
@@ -194,8 +183,6 @@ clean-files := $(DOCBOOKS) \
$(patsubst %.sgml, %.pdf, $(DOCBOOKS)) \
$(patsubst %.sgml, %.html, $(DOCBOOKS)) \
$(patsubst %.sgml, %.9, $(DOCBOOKS)) \
- $(patsubst %.fig,%.eps, $(IMG-parportbook)) \
- $(patsubst %.fig,%.png, $(IMG-parportbook)) \
$(C-procfs-example)
ifneq ($(wildcard $(patsubst %.html,%,$(HTML))),)
diff --git a/Documentation/DocBook/parport-multi.fig b/Documentation/DocBook/parport-multi.fig
deleted file mode 100644
index e0517b36fe804d..00000000000000
--- a/Documentation/DocBook/parport-multi.fig
+++ /dev/null
@@ -1,59 +0,0 @@
-#FIG 3.2
-Landscape
-Center
-Inches
-Letter
-100.00
-Single
--2
-1200 2
-6 1425 4350 5175 5475
-6 3450 5100 4425 5475
-2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
- 4425 5475 4425 5100 3450 5100 3450 5475 4425 5475
-4 0 0 50 0 0 12 0.0000 4 135 510 3600 5400 Printer\001
--6
-6 3375 4350 5175 4725
-2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
- 5175 4725 5175 4350 3375 4350 3375 4725 5175 4725
-4 0 0 50 0 0 12 0.0000 4 180 870 3825 4650 Multiplexor\001
--6
-6 1425 4650 2775 5475
-6 1425 4650 2775 5475
-2 4 0 1 0 7 50 0 -1 0.000 0 0 6 0 0 5
- 2757 5475 2757 4650 1425 4650 1425 5475 2757 5475
-4 0 0 50 0 0 12 0.0000 4 180 735 1725 5100 Computer\001
--6
-2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
- 2775 4875 2700 4875 2700 5025 2775 5025 2775 4875
-2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
- 2775 5175 2700 5175 2700 5325 2775 5325 2775 5175
--6
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
- 2775 4950 3600 4725
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
- 2775 5250 3450 5325
--6
-6 3150 2625 4125 3525
-2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
- 4125 3075 4125 2625 3150 2625 3150 3075 4125 3075
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
- 3675 3075 3675 3525
-4 0 0 50 0 0 12 0.0000 4 135 510 3300 2925 Printer\001
--6
-6 4275 3450 5250 4350
-2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
- 5250 3900 5250 3450 4275 3450 4275 3900 5250 3900
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
- 4800 3900 4800 4350
-4 0 0 50 0 0 12 0.0000 4 135 510 4425 3750 Printer\001
--6
-2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
- 3900 4050 3900 3525 3375 3525 3375 4050 3900 4050
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
- 3675 4050 3675 4350
-2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
- 3600 4350 3750 4350 3750 4425 3600 4425 3600 4350
-2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
- 4725 4350 4875 4350 4875 4425 4725 4425 4725 4350
-4 0 0 50 0 0 12 0.0000 4 135 285 3450 3900 ZIP\001
diff --git a/Documentation/DocBook/parport-share.fig b/Documentation/DocBook/parport-share.fig
deleted file mode 100644
index fe4f37322bcfb8..00000000000000
--- a/Documentation/DocBook/parport-share.fig
+++ /dev/null
@@ -1,154 +0,0 @@
-#FIG 3.2
-Landscape
-Center
-Inches
-Letter
-100.00
-Single
--2
-1200 2
-0 32 #8e8e8e
-0 33 #8e8e8e
-0 34 #aeaaae
-0 35 #515551
-0 36 #414141
-0 37 #868286
-0 38 #8e8e8e
-0 39 #414141
-0 40 #868286
-0 41 #c7c3c7
-0 42 #e7e3e7
-0 43 #414141
-0 44 #868286
-0 45 #c7c3c7
-0 46 #e7e3e7
-0 47 #868286
-0 48 #c7c3c7
-0 49 #e7e3e7
-6 1200 3000 2250 4950
-6 1275 3150 2175 3675
-6 1312 3487 1837 3637
-2 1 0 1 40 -1 19 0 -1 0.000 2 0 -1 0 0 5
- 1312 3562 1312 3524 1474 3524 1474 3487 1675 3487
-2 1 0 1 40 -1 19 0 -1 0.000 2 0 -1 0 0 3
- 1474 3637 1474 3562 1675 3562
-2 1 0 1 40 -1 19 0 -1 0.000 2 0 -1 0 0 2
- 1675 3524 1837 3524
-2 1 0 1 7 -1 19 0 -1 0.000 2 0 -1 0 0 2
- 1675 3487 1675 3524
-2 1 0 1 7 -1 19 0 -1 0.000 2 0 -1 0 0 2
- 1312 3562 1474 3562
-2 1 0 1 7 -1 19 0 -1 0.000 2 0 -1 0 0 5
- 1474 3637 1675 3637 1675 3562 1837 3562 1837 3524
-2 1 0 1 40 -1 19 0 -1 0.000 2 0 -1 0 0 3
- 1716 3637 1797 3637 1797 3600
-2 1 0 1 7 -1 19 0 -1 0.000 2 0 -1 0 0 3
- 1716 3637 1716 3600 1797 3600
--6
-6 1413 3345 2070 3397
-6 1994 3352 2070 3390
-2 1 0 1 7 40 19 0 -1 0.000 2 0 -1 0 0 3
- 1994 3390 1994 3352 2070 3352
-2 1 0 1 40 -1 19 0 -1 0.000 2 0 -1 0 0 3
- 1994 3390 2070 3390 2070 3352
--6
-6 1531 3353 1643 3389
-2 2 0 0 40 41 19 0 20 0.000 2 0 -1 0 0 5
- 1568 3353 1606 3353 1606 3389 1568 3389 1568 3353
-2 2 0 0 40 39 19 0 20 0.000 2 0 -1 0 0 5
- 1606 3353 1643 3353 1643 3389 1606 3389 1606 3353
-2 2 0 0 40 41 19 0 20 0.000 2 0 -1 0 0 5
- 1568 3353 1531 3353 1531 3389 1568 3389 1568 3353
--6
-6 1413 3345 1465 3397
-1 3 0 0 0 39 18 0 20 0.000 1 0.0000 1439 3371 26 26 1439 3371 1439 3397
-1 3 0 0 40 41 18 0 20 0.000 1 0.0000 1439 3371 15 15 1439 3371 1443 3385
--6
-2 2 0 0 40 7 19 0 20 0.000 2 0 -1 0 0 3
- 1950 3371 1875 3371 1950 3371
-2 2 0 0 40 41 19 0 20 0.000 2 0 -1 0 0 5
- 1945 3384 1896 3384 1896 3357 1945 3357 1945 3384
--6
-6 1350 3183 2100 3300
-2 1 0 1 7 40 19 0 -1 0.000 2 0 -1 0 0 3
- 1350 3300 1350 3183 2100 3183
-2 1 0 1 40 -1 19 0 -1 0.000 2 0 -1 0 0 3
- 1350 3300 2100 3300 2100 3183
--6
-2 1 0 1 7 7 19 0 -1 0.000 2 0 -1 0 0 5
- 1275 3675 1875 3675 1875 3450 2175 3450 2175 3150
-2 1 0 1 40 7 19 0 -1 0.000 2 0 -1 0 0 3
- 1275 3675 1275 3150 2175 3150
--6
-6 1950 3750 2175 3975
-5 1 0 1 7 7 19 0 -1 0.000 0 0 0 0 2038.000 3900.000 1985 3953 1985 3847 2091 3847
-5 1 0 1 40 7 19 0 -1 0.000 0 1 0 0 2038.000 3900.000 1985 3953 2091 3953 2091 3847
--6
-6 1200 4050 1800 4800
-2 1 0 2 40 7 19 0 -1 0.000 2 1 -1 0 0 2
- 1275 4125 1725 4125
-2 1 0 2 40 7 19 0 -1 0.000 2 1 -1 0 0 2
- 1275 4200 1725 4200
-2 1 0 2 40 7 19 0 -1 0.000 2 1 -1 0 0 2
- 1275 4275 1725 4275
-2 1 0 2 40 7 19 0 -1 0.000 2 1 -1 0 0 2
- 1275 4350 1725 4350
-2 1 0 2 40 7 19 0 -1 0.000 2 1 -1 0 0 2
- 1275 4425 1725 4425
-2 1 0 2 40 7 19 0 -1 0.000 2 1 -1 0 0 2
- 1275 4500 1725 4500
-2 1 0 2 40 7 19 0 -1 0.000 2 1 -1 0 0 2
- 1275 4575 1725 4575
-2 1 0 2 40 7 19 0 -1 0.000 2 1 -1 0 0 2
- 1275 4650 1725 4650
-2 1 0 2 40 7 19 0 -1 0.000 2 1 -1 0 0 2
- 1275 4725 1725 4725
--6
-2 2 0 1 0 39 20 0 20 0.000 2 0 -1 0 0 5
- 1200 4950 1425 4950 1425 4911 1200 4911 1200 4950
-2 2 0 1 0 39 20 0 20 0.000 2 0 -1 0 0 5
- 2025 4950 2250 4950 2250 4911 2025 4911 2025 4950
-2 2 0 1 0 42 20 0 20 0.000 2 0 -1 0 0 5
- 1200 4907 2250 4907 2250 3000 1200 3000 1200 4907
--6
-6 2374 3225 3375 4050
-3 2 0 1 0 37 50 0 -1 0.000 0 0 0 3
- 2374 3402 3139 3402 3257 4050
- 0.000 -1.000 0.000
-3 2 0 1 0 37 50 0 -1 0.000 0 0 0 3
- 2374 3461 3096 3437 3198 4050
- 0.000 -1.000 0.000
--6
-2 2 0 1 0 1 50 0 20 0.000 0 0 -1 0 0 5
- 2925 4575 4050 4575 4050 4875 2925 4875 2925 4575
-2 3 0 1 0 32 50 0 20 0.000 0 0 -1 0 0 5
- 1200 3000 1575 2475 2400 2475 2250 3000 1200 3000
-2 3 0 1 0 8 50 0 20 0.000 0 0 -1 0 0 5
- 2925 4575 3000 4200 4050 4200 4050 4575 2925 4575
-2 2 0 1 0 0 50 0 20 0.000 0 0 -1 0 0 5
- 3075 4725 3900 4725 3900 4800 3075 4800 3075 4725
-2 2 0 1 0 46 50 0 20 0.000 0 0 -1 0 0 5
- 4800 3975 6450 3975 6450 4875 4800 4875 4800 3975
-2 2 0 1 0 36 50 0 20 0.000 0 0 -1 0 0 5
- 5025 4575 6225 4575 6225 4725 5025 4725 5025 4575
-2 2 0 1 0 36 50 0 20 0.000 0 0 -1 0 0 5
- 5025 3975 6225 3975 6225 3300 5025 3300 5025 3975
-2 3 0 1 0 37 50 0 20 0.000 0 0 -1 0 0 5
- 4800 3975 4800 3825 5025 3825 5025 3975 4800 3975
-2 3 0 1 0 37 50 0 20 0.000 0 0 -1 0 0 5
- 6225 3825 6375 3825 6450 3975 6225 3975 6225 3825
-2 3 0 1 0 32 50 0 20 0.000 0 0 -1 0 0 5
- 2400 2475 2250 3000 2250 4875 2400 4350 2400 2475
-2 3 0 1 0 37 50 0 -1 0.000 0 0 -1 0 0 6
- 3075 4200 3075 4050 3300 4050 3375 4050 3375 4200 3075 4200
-2 3 0 1 0 37 50 0 -1 0.000 0 0 -1 0 0 6
- 3900 4200 3900 4050 3675 4050 3600 4050 3600 4200 3900 4200
-3 2 0 1 0 37 50 0 -1 0.000 0 0 0 5
- 3705 4050 3825 3675 4185 3390 4590 3615 4800 4035
- 0.000 -1.000 -1.000 -1.000 0.000
-3 2 0 1 0 37 50 0 -1 0.000 0 0 0 5
- 3765 4050 3874 3708 4202 3449 4571 3654 4800 4185
- 0.000 -1.000 -1.000 -1.000 0.000
-4 0 0 50 0 0 12 0.0000 4 180 735 1350 5400 Computer\001
-4 0 0 50 0 0 12 0.0000 4 180 675 3150 5400 Zip drive\001
-4 0 0 50 0 0 12 0.0000 4 135 510 5325 5400 Printer\001
diff --git a/Documentation/DocBook/parport-structure.fig b/Documentation/DocBook/parport-structure.fig
deleted file mode 100644
index 4299ce68717e61..00000000000000
--- a/Documentation/DocBook/parport-structure.fig
+++ /dev/null
@@ -1,60 +0,0 @@
-#FIG 3.2
-Landscape
-Center
-Inches
-Letter
-100.00
-Single
--2
-1200 2
-0 32 #414541
-0 33 #8e8e8e
-0 34 #414541
-0 35 #8e8e8e
-0 36 #414541
-0 37 #8e8e8e
-0 38 #414541
-0 39 #8e8e8e
-0 40 #414541
-0 41 #8e8e8e
-0 42 #414541
-0 43 #8e8e8e
-0 44 #414141
-0 45 #868286
-0 46 #c7c3c7
-0 47 #8e8e8e
-0 48 #414141
-0 49 #868286
-0 50 #c7c3c7
-0 51 #e7e3e7
-6 2025 1800 3075 2250
-2 4 0 1 0 7 50 0 -1 0.000 0 0 3 0 0 5
- 3045 2250 3045 1800 2025 1800 2025 2250 3045 2250
-4 0 0 50 0 14 12 0.0000 4 180 210 2400 2100 lp\001
--6
-6 4125 1800 5175 2250
-2 4 0 1 0 7 50 0 -1 0.000 0 0 3 0 0 5
- 5145 2250 5145 1800 4125 1800 4125 2250 5145 2250
-4 0 0 50 0 14 12 0.0000 4 135 315 4425 2100 ppa\001
--6
-6 3225 3075 4275 3525
-6 3375 3225 4125 3450
-4 0 0 50 0 14 12 0.0000 4 165 735 3375 3375 parport\001
--6
-2 4 0 1 0 7 50 0 -1 0.000 0 0 3 0 0 5
- 4245 3525 4245 3075 3225 3075 3225 3525 4245 3525
--6
-6 3000 4350 4500 4800
-2 4 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
- 4500 4800 4500 4350 3000 4350 3000 4800 4500 4800
-4 0 0 50 0 14 12 0.0000 4 165 1050 3225 4650 parport_pc\001
--6
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 2550 2250 3600 3075
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 4650 2250 3825 3075
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 3750 3525 3750 4350
diff --git a/Documentation/DocBook/parportbook.tmpl b/Documentation/DocBook/parportbook.tmpl
deleted file mode 100644
index 8e22b018cd27e4..00000000000000
--- a/Documentation/DocBook/parportbook.tmpl
+++ /dev/null
@@ -1,2735 +0,0 @@
-<!-- -*- sgml -*- -->
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN"[]>
-
-<book id="ParportGuide">
- <bookinfo>
- <title>The Linux 2.4 Parallel Port Subsystem</title>
-
- <authorgroup>
- <author>
- <firstname>Tim</firstname>
- <surname>Waugh</surname>
- <affiliation>
- <address>
- <email>twaugh@redhat.com</email>
- </address>
- </affiliation>
- </author>
- </authorgroup>
-
- <copyright>
- <year>1999-2000</year>
- <holder>Tim Waugh</holder>
- </copyright>
-
- <legalnotice>
- <para>
- Permission is granted to copy, distribute and/or modify this
- document under the terms of the GNU Free Documentation License,
- Version 1.1 or any later version published by the Free Software
- Foundation; with no Invariant Sections, with no Front-Cover Texts,
- and with no Back-Cover Texts. A copy of the license is included
- in the section entitled "GNU Free Documentation License".
- </para>
- </legalnotice>
- </bookinfo>
-
- <toc></toc>
-
- <chapter id="design">
- <title>Design goals</title>
-
- <sect1>
- <title>The problems</title>
-
- <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>
-
- <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>
-
- <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
- - overview of structure (i.e. port drivers) in 2.2 and 2.3.
- - IEEE 1284 stuff
- - whether or not 'platform independence' goal was met
- -->
-
- <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>
-
- <!-- platform differences -->
-
- <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>
-
- <!-- sharing model -->
-
- <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>
-
- <!-- 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 fileref="parport-share" format="eps">
- </imageobject>
- <imageobject>
- <imagedata fileref="parport-share.png" format="png">
- </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>
-
-<!-- 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
- -->
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="parport-structure" format="eps">
- </imageobject>
- <imageobject>
- <imagedata fileref="parport-structure.png" format="png">
- </imageobject>
- </mediaobject>
-
- <sect1>
- <title>Sharing core</title>
-
- <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>
-
- </sect1>
-
- <sect1>
- <title>Parports and their overrides</title>
-
- <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>
- 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>
-
- <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>
-
- <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>
-
- </sect1>
-
- <!-- muxes? -->
-
- <sect1>
- <title>Pardevices and parport_drivers</title>
-
- <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>
-
- <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 (which may block).
- </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 (which may not block).
- </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 <literal>parport</literal> 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 fileref="parport-multi" format="eps">
- </imageobject>
- <imageobject>
- <imagedata fileref="parport-multi.png" format="png">
- </imageobject>
- </mediaobject>
-
- <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>
- <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>
-
- <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>
- <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>
-
- <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>
-
-<!-- Cover:
- - sharing interface, preemption, interrupts, wakeups...
- - IEEE 1284.3 interface
- - port operations
- - why can read data but ctr is faked, etc.
- -->
-
-<!-- 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>
- 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_driver</function> function:
- </para>
-
- <funcsynopsis>
- <funcsynopsisinfo>
-#include &lt;parport.h&gt;
-
-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. A better way of
- doing this is with <function>parport_find_number</function> or
- <function>parport_find_base</function> functions, which find ports
- by number and by base I/O address respectively.
- </para>
-
- <funcsynopsis>
- <funcsynopsisinfo>
-#include &lt;parport.h&gt;
- </funcsynopsisinfo>
- <funcprototype>
- <funcdef>struct parport *<function>parport_find_number</function></funcdef>
- <paramdef>int <parameter>number</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcsynopsisinfo>
-#include &lt;parport.h&gt;
- </funcsynopsisinfo>
- <funcprototype>
- <funcdef>struct parport *<function>parport_find_base</function></funcdef>
- <paramdef>unsigned long <parameter>base</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <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>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_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 negotiation 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>
-
-<programlisting>
-<![CDATA[
- written = parport_write (port, kbuf, copy_size);
-]]></programlisting>
-
- <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 {
- [...]
-
- /* 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);
-
- 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);
-
- 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>
-
- <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 <literal>ppdev</literal> 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 <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>
-
- <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>PPGETMODE</constant></term>
- <listitem>
-
- <para>
- Retrieves the current IEEE 1284 mode to use for
- <function>read</function> and <function>write</function>.
- </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>PPGETMODES</constant></term>
- <listitem>
-
- <para>
- Retrieves the capabilities of the hardware (i.e. the
- <structfield>modes</structfield> field of the
- <structname>parport</structname> structure).
- </para>
-
- </listitem></varlistentry>
-
- <varlistentry><term><constant>PPSETFLAGS</constant></term>
- <listitem>
-
- <para>
- Sets flags on the <literal>ppdev</literal> device which can
- affect future I/O operations. Available flags are:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem><para>
- <constant>PP_FASTWRITE</constant></para></listitem>
- <listitem><para>
- <constant>PP_FASTREAD</constant></para></listitem>
- <listitem><para>
- <constant>PP_W91284PIC</constant></para></listitem>
- </itemizedlist>
-
- </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 <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>
-
- <programlisting><![CDATA[
-int drive_printer (const char *name)
-{
- int fd;
- int mode; /* We'll need this later. */
-
- fd = open (name, O_RDWR);
- if (fd == -1) {
- perror ("open");
- return 1;
- }
- ]]></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>
- In order to do anything with the port we need to claim access to
- it.
- </para>
-
- <programlisting><![CDATA[
- if (ioctl (fd, PPCLAIM)) {
- perror ("PPCLAIM");
- close (fd);
- return 1;
- }
- ]]></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>
-
- <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.)
- mode = IEEE1284_MODE_COMPAT;
- if (ioctl (fd, PPNEGOT, &mode)) {
- perror ("PPNEGOT");
- close (fd);
- return 1;
- }
-
- for (;;) {
- char buffer[1000];
- char *ptr = buffer;
- size_t got;
-
- got = read (0 /* stdin */, buffer, 1000);
- if (got < 0) {
- perror ("read");
- close (fd);
- return 1;
- }
-
- if (got == 0)
- /* End of input */
- break;
-
- while (got > 0) {
- int written = write_printer (fd, ptr, got);
-
- if (written < 0) {
- perror ("write");
- close (fd);
- return 1;
- }
-
- ptr += written;
- got -= written;
- }
- }
- ]]></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>
-
- <programlisting><![CDATA[
-ssize_t write_printer (int fd, const void *ptr, size_t count)
-{
- return write (fd, ptr, count);
-}
- ]]></programlisting>
-
- <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>
- So, here is the alternative implementation of
- <function>write_printer</function> (for brevity, error checking
- has been omitted):
- </para>
-
- <programlisting><![CDATA[
-ssize_t write_printer (int fd, const void *ptr, size_t count)
-{
- ssize_t wrote = 0;
-
- while (wrote < count) {
- unsigned char status, control, data;
- unsigned char mask = (PARPORT_STATUS_ERROR
- | PARPORT_STATUS_BUSY);
- unsigned char val = (PARPORT_STATUS_ERROR
- | PARPORT_STATUS_BUSY);
- struct ppdev_frob_struct frob;
- struct timespec ts;
-
- /* Wait for printer to be ready */
- for (;;) {
- ioctl (fd, PPRSTATUS, &status);
-
- if ((status & mask) == val)
- break;
-
- ioctl (fd, PPRELEASE);
- sleep (1);
- ioctl (fd, PPCLAIM);
- }
-
- /* Set the data lines */
- data = * ((char *) ptr)++;
- ioctl (fd, PPWDATA, &data);
-
- /* Delay for a bit */
- ts.tv_sec = 0;
- ts.tv_nsec = 1000;
- nanosleep (&ts, NULL);
-
- /* Pulse strobe */
- frob.mask = PARPORT_CONTROL_STROBE;
- frob.val = PARPORT_CONTROL_STROBE;
- ioctl (fd, PPFCONTROL, &frob);
- nanosleep (&ts, NULL);
-
- /* End the pulse */
- frob.val = 0;
- ioctl (fd, PPFCONTROL, &frob);
- nanosleep (&ts, NULL);
-
- wrote++;
- }
-
- return wrote;
-}
- ]]></programlisting>
-
- <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[
- for (;;)
- {
- int irqc;
- int busy = nAck | nFault;
- int acking = nFault;
- int ready = Busy | nAck | nFault;
- char ch;
-
- /* Set up the control lines when an interrupt happens. */
- ioctl (fd, PPWCTLONIRQ, &busy);
-
- /* Now we're ready. */
- ioctl (fd, PPWCONTROL, &ready);
-
- /* Wait for an interrupt. */
- {
- fd_set rfds;
- FD_ZERO (&rfds);
- FD_SET (fd, &rfds);
- if (!select (fd + 1, &rfds, NULL, NULL, NULL))
- /* Caught a signal? */
- continue;
- }
-
- /* We are now marked as busy. */
-
- /* Fetch the data. */
- ioctl (fd, PPRDATA, &ch);
-
- /* Clear the interrupt. */
- ioctl (fd, PPCLRIRQ, &irqc);
- if (irqc > 1)
- fprintf (stderr, "Arghh! Missed %d interrupt%s!\n",
- irqc - 1, irqc == 2 ? "s" : "");
-
- /* Ack it. */
- ioctl (fd, PPWCONTROL, &acking);
- usleep (2);
- ioctl (fd, PPWCONTROL, &busy);
-
- putchar (ch);
- }
- ]]></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);
- }
-
- /* Okay, finished */
- ioctl (fd, PPRELEASE);
- close (fd);
- }
- ]]></programlisting>
-
- </sect1>
-
- </chapter>
-
- <appendix id="api">
- <title>
- Linux parallel port driver 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_get_port
-!Fdrivers/parport/share.c parport_put_port
-!Fdrivers/parport/share.c parport_find_number parport_find_base
-!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>
-
- <appendix id="fdl">
- <title>
- GNU Free Documentation License
- </title>
-
- <literallayout class="monospaced">
- GNU Free Documentation License
- Version 1.1, March 2000
-
- Copyright (C) 2000 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
-0. PREAMBLE
-
-The purpose of this License is to make a manual, textbook, or other
-written document "free" in the sense of freedom: to assure everyone
-the effective freedom to copy and redistribute it, with or without
-modifying it, either commercially or noncommercially. Secondarily,
-this License preserves for the author and publisher a way to get
-credit for their work, while not being considered responsible for
-modifications made by others.
-
-This License is a kind of "copyleft", which means that derivative
-works of the document must themselves be free in the same sense. It
-complements the GNU General Public License, which is a copyleft
-license designed for free software.
-
-We have designed this License in order to use it for manuals for free
-software, because free software needs free documentation: a free
-program should come with manuals providing the same freedoms that the
-software does. But this License is not limited to software manuals;
-it can be used for any textual work, regardless of subject matter or
-whether it is published as a printed book. We recommend this License
-principally for works whose purpose is instruction or reference.
-
-
-1. APPLICABILITY AND DEFINITIONS
-
-This License applies to any manual or other work that contains a
-notice placed by the copyright holder saying it can be distributed
-under the terms of this License. The "Document", below, refers to any
-such manual or work. Any member of the public is a licensee, and is
-addressed as "you".
-
-A "Modified Version" of the Document means any work containing the
-Document or a portion of it, either copied verbatim, or with
-modifications and/or translated into another language.
-
-A "Secondary Section" is a named appendix or a front-matter section of
-the Document that deals exclusively with the relationship of the
-publishers or authors of the Document to the Document's overall subject
-(or to related matters) and contains nothing that could fall directly
-within that overall subject. (For example, if the Document is in part a
-textbook of mathematics, a Secondary Section may not explain any
-mathematics.) The relationship could be a matter of historical
-connection with the subject or with related matters, or of legal,
-commercial, philosophical, ethical or political position regarding
-them.
-
-The "Invariant Sections" are certain Secondary Sections whose titles
-are designated, as being those of Invariant Sections, in the notice
-that says that the Document is released under this License.
-
-The "Cover Texts" are certain short passages of text that are listed,
-as Front-Cover Texts or Back-Cover Texts, in the notice that says that
-the Document is released under this License.
-
-A "Transparent" copy of the Document means a machine-readable copy,
-represented in a format whose specification is available to the
-general public, whose contents can be viewed and edited directly and
-straightforwardly with generic text editors or (for images composed of
-pixels) generic paint programs or (for drawings) some widely available
-drawing editor, and that is suitable for input to text formatters or
-for automatic translation to a variety of formats suitable for input
-to text formatters. A copy made in an otherwise Transparent file
-format whose markup has been designed to thwart or discourage
-subsequent modification by readers is not Transparent. A copy that is
-not "Transparent" is called "Opaque".
-
-Examples of suitable formats for Transparent copies include plain
-ASCII without markup, Texinfo input format, LaTeX input format, SGML
-or XML using a publicly available DTD, and standard-conforming simple
-HTML designed for human modification. Opaque formats include
-PostScript, PDF, proprietary formats that can be read and edited only
-by proprietary word processors, SGML or XML for which the DTD and/or
-processing tools are not generally available, and the
-machine-generated HTML produced by some word processors for output
-purposes only.
-
-The "Title Page" means, for a printed book, the title page itself,
-plus such following pages as are needed to hold, legibly, the material
-this License requires to appear in the title page. For works in
-formats which do not have any title page as such, "Title Page" means
-the text near the most prominent appearance of the work's title,
-preceding the beginning of the body of the text.
-
-
-2. VERBATIM COPYING
-
-You may copy and distribute the Document in any medium, either
-commercially or noncommercially, provided that this License, the
-copyright notices, and the license notice saying this License applies
-to the Document are reproduced in all copies, and that you add no other
-conditions whatsoever to those of this License. You may not use
-technical measures to obstruct or control the reading or further
-copying of the copies you make or distribute. However, you may accept
-compensation in exchange for copies. If you distribute a large enough
-number of copies you must also follow the conditions in section 3.
-
-You may also lend copies, under the same conditions stated above, and
-you may publicly display copies.
-
-
-3. COPYING IN QUANTITY
-
-If you publish printed copies of the Document numbering more than 100,
-and the Document's license notice requires Cover Texts, you must enclose
-the copies in covers that carry, clearly and legibly, all these Cover
-Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
-the back cover. Both covers must also clearly and legibly identify
-you as the publisher of these copies. The front cover must present
-the full title with all words of the title equally prominent and
-visible. You may add other material on the covers in addition.
-Copying with changes limited to the covers, as long as they preserve
-the title of the Document and satisfy these conditions, can be treated
-as verbatim copying in other respects.
-
-If the required texts for either cover are too voluminous to fit
-legibly, you should put the first ones listed (as many as fit
-reasonably) on the actual cover, and continue the rest onto adjacent
-pages.
-
-If you publish or distribute Opaque copies of the Document numbering
-more than 100, you must either include a machine-readable Transparent
-copy along with each Opaque copy, or state in or with each Opaque copy
-a publicly-accessible computer-network location containing a complete
-Transparent copy of the Document, free of added material, which the
-general network-using public has access to download anonymously at no
-charge using public-standard network protocols. If you use the latter
-option, you must take reasonably prudent steps, when you begin
-distribution of Opaque copies in quantity, to ensure that this
-Transparent copy will remain thus accessible at the stated location
-until at least one year after the last time you distribute an Opaque
-copy (directly or through your agents or retailers) of that edition to
-the public.
-
-It is requested, but not required, that you contact the authors of the
-Document well before redistributing any large number of copies, to give
-them a chance to provide you with an updated version of the Document.
-
-
-4. MODIFICATIONS
-
-You may copy and distribute a Modified Version of the Document under
-the conditions of sections 2 and 3 above, provided that you release
-the Modified Version under precisely this License, with the Modified
-Version filling the role of the Document, thus licensing distribution
-and modification of the Modified Version to whoever possesses a copy
-of it. In addition, you must do these things in the Modified Version:
-
-A. Use in the Title Page (and on the covers, if any) a title distinct
- from that of the Document, and from those of previous versions
- (which should, if there were any, be listed in the History section
- of the Document). You may use the same title as a previous version
- if the original publisher of that version gives permission.
-B. List on the Title Page, as authors, one or more persons or entities
- responsible for authorship of the modifications in the Modified
- Version, together with at least five of the principal authors of the
- Document (all of its principal authors, if it has less than five).
-C. State on the Title page the name of the publisher of the
- Modified Version, as the publisher.
-D. Preserve all the copyright notices of the Document.
-E. Add an appropriate copyright notice for your modifications
- adjacent to the other copyright notices.
-F. Include, immediately after the copyright notices, a license notice
- giving the public permission to use the Modified Version under the
- terms of this License, in the form shown in the Addendum below.
-G. Preserve in that license notice the full lists of Invariant Sections
- and required Cover Texts given in the Document's license notice.
-H. Include an unaltered copy of this License.
-I. Preserve the section entitled "History", and its title, and add to
- it an item stating at least the title, year, new authors, and
- publisher of the Modified Version as given on the Title Page. If
- there is no section entitled "History" in the Document, create one
- stating the title, year, authors, and publisher of the Document as
- given on its Title Page, then add an item describing the Modified
- Version as stated in the previous sentence.
-J. Preserve the network location, if any, given in the Document for
- public access to a Transparent copy of the Document, and likewise
- the network locations given in the Document for previous versions
- it was based on. These may be placed in the "History" section.
- You may omit a network location for a work that was published at
- least four years before the Document itself, or if the original
- publisher of the version it refers to gives permission.
-K. In any section entitled "Acknowledgements" or "Dedications",
- preserve the section's title, and preserve in the section all the
- substance and tone of each of the contributor acknowledgements
- and/or dedications given therein.
-L. Preserve all the Invariant Sections of the Document,
- unaltered in their text and in their titles. Section numbers
- or the equivalent are not considered part of the section titles.
-M. Delete any section entitled "Endorsements". Such a section
- may not be included in the Modified Version.
-N. Do not retitle any existing section as "Endorsements"
- or to conflict in title with any Invariant Section.
-
-If the Modified Version includes new front-matter sections or
-appendices that qualify as Secondary Sections and contain no material
-copied from the Document, you may at your option designate some or all
-of these sections as invariant. To do this, add their titles to the
-list of Invariant Sections in the Modified Version's license notice.
-These titles must be distinct from any other section titles.
-
-You may add a section entitled "Endorsements", provided it contains
-nothing but endorsements of your Modified Version by various
-parties--for example, statements of peer review or that the text has
-been approved by an organization as the authoritative definition of a
-standard.
-
-You may add a passage of up to five words as a Front-Cover Text, and a
-passage of up to 25 words as a Back-Cover Text, to the end of the list
-of Cover Texts in the Modified Version. Only one passage of
-Front-Cover Text and one of Back-Cover Text may be added by (or
-through arrangements made by) any one entity. If the Document already
-includes a cover text for the same cover, previously added by you or
-by arrangement made by the same entity you are acting on behalf of,
-you may not add another; but you may replace the old one, on explicit
-permission from the previous publisher that added the old one.
-
-The author(s) and publisher(s) of the Document do not by this License
-give permission to use their names for publicity for or to assert or
-imply endorsement of any Modified Version.
-
-
-5. COMBINING DOCUMENTS
-
-You may combine the Document with other documents released under this
-License, under the terms defined in section 4 above for modified
-versions, provided that you include in the combination all of the
-Invariant Sections of all of the original documents, unmodified, and
-list them all as Invariant Sections of your combined work in its
-license notice.
-
-The combined work need only contain one copy of this License, and
-multiple identical Invariant Sections may be replaced with a single
-copy. If there are multiple Invariant Sections with the same name but
-different contents, make the title of each such section unique by
-adding at the end of it, in parentheses, the name of the original
-author or publisher of that section if known, or else a unique number.
-Make the same adjustment to the section titles in the list of
-Invariant Sections in the license notice of the combined work.
-
-In the combination, you must combine any sections entitled "History"
-in the various original documents, forming one section entitled
-"History"; likewise combine any sections entitled "Acknowledgements",
-and any sections entitled "Dedications". You must delete all sections
-entitled "Endorsements."
-
-
-6. COLLECTIONS OF DOCUMENTS
-
-You may make a collection consisting of the Document and other documents
-released under this License, and replace the individual copies of this
-License in the various documents with a single copy that is included in
-the collection, provided that you follow the rules of this License for
-verbatim copying of each of the documents in all other respects.
-
-You may extract a single document from such a collection, and distribute
-it individually under this License, provided you insert a copy of this
-License into the extracted document, and follow this License in all
-other respects regarding verbatim copying of that document.
-
-
-
-7. AGGREGATION WITH INDEPENDENT WORKS
-
-A compilation of the Document or its derivatives with other separate
-and independent documents or works, in or on a volume of a storage or
-distribution medium, does not as a whole count as a Modified Version
-of the Document, provided no compilation copyright is claimed for the
-compilation. Such a compilation is called an "aggregate", and this
-License does not apply to the other self-contained works thus compiled
-with the Document, on account of their being thus compiled, if they
-are not themselves derivative works of the Document.
-
-If the Cover Text requirement of section 3 is applicable to these
-copies of the Document, then if the Document is less than one quarter
-of the entire aggregate, the Document's Cover Texts may be placed on
-covers that surround only the Document within the aggregate.
-Otherwise they must appear on covers around the whole aggregate.
-
-
-8. TRANSLATION
-
-Translation is considered a kind of modification, so you may
-distribute translations of the Document under the terms of section 4.
-Replacing Invariant Sections with translations requires special
-permission from their copyright holders, but you may include
-translations of some or all Invariant Sections in addition to the
-original versions of these Invariant Sections. You may include a
-translation of this License provided that you also include the
-original English version of this License. In case of a disagreement
-between the translation and the original English version of this
-License, the original English version will prevail.
-
-
-9. TERMINATION
-
-You may not copy, modify, sublicense, or distribute the Document except
-as expressly provided for under this License. Any other attempt to
-copy, modify, sublicense or distribute the Document is void, and will
-automatically terminate your rights under this License. However,
-parties who have received copies, or rights, from you under this
-License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-
-10. FUTURE REVISIONS OF THIS LICENSE
-
-The Free Software Foundation may publish new, revised versions
-of the GNU Free Documentation License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns. See
-http:///www.gnu.org/copyleft/.
-
-Each version of the License is given a distinguishing version number.
-If the Document specifies that a particular numbered version of this
-License "or any later version" applies to it, you have the option of
-following the terms and conditions either of that specified version or
-of any later version that has been published (not as a draft) by the
-Free Software Foundation. If the Document does not specify a version
-number of this License, you may choose any version ever published (not
-as a draft) by the Free Software Foundation.
-
-
-ADDENDUM: How to use this License for your documents
-
-To use this License in a document you have written, include a copy of
-the License in the document and put the following copyright and
-license notices just after the title page:
-
- Copyright (c) YEAR YOUR NAME.
- Permission is granted to copy, distribute and/or modify this document
- under the terms of the GNU Free Documentation License, Version 1.1
- or any later version published by the Free Software Foundation;
- with the Invariant Sections being LIST THEIR TITLES, with the
- Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
- A copy of the license is included in the section entitled "GNU
- Free Documentation License".
-
-If you have no Invariant Sections, write "with no Invariant Sections"
-instead of saying which ones are invariant. If you have no
-Front-Cover Texts, write "no Front-Cover Texts" instead of
-"Front-Cover Texts being LIST"; likewise for Back-Cover Texts.
-
-If your document contains nontrivial examples of program code, we
-recommend releasing these examples in parallel under your choice of
-free software license, such as the GNU General Public License,
-to permit their use in free software.
- </literallayout>
- </appendix>
-
-</book>
-<!-- Local Variables: -->
-<!-- sgml-indent-step: 1 -->
-<!-- sgml-indent-data: 1 -->
-<!-- End: -->