Browse Source

Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
Linus Torvalds 20 năm trước cách đây
commit
1da177e4c3
100 tập tin đã thay đổi với 27989 bổ sung0 xóa
  1. 356 0
      COPYING
  2. 3743 0
      CREDITS
  3. 294 0
      Documentation/00-INDEX
  4. 51 0
      Documentation/BK-usage/00-INDEX
  5. 283 0
      Documentation/BK-usage/bk-kernel-howto.txt
  6. 34 0
      Documentation/BK-usage/bk-make-sum
  7. 36 0
      Documentation/BK-usage/bksend
  8. 41 0
      Documentation/BK-usage/bz64wrap
  9. 36 0
      Documentation/BK-usage/cpcset
  10. 49 0
      Documentation/BK-usage/cset-to-linus
  11. 44 0
      Documentation/BK-usage/csets-to-patches
  12. 8 0
      Documentation/BK-usage/gcapatch
  13. 25 0
      Documentation/BK-usage/unbz64wrap
  14. 92 0
      Documentation/BUG-HUNTING
  15. 410 0
      Documentation/Changes
  16. 431 0
      Documentation/CodingStyle
  17. 526 0
      Documentation/DMA-API.txt
  18. 881 0
      Documentation/DMA-mapping.txt
  19. 195 0
      Documentation/DocBook/Makefile
  20. 341 0
      Documentation/DocBook/deviceiobook.tmpl
  21. 752 0
      Documentation/DocBook/gadget.tmpl
  22. 333 0
      Documentation/DocBook/journal-api.tmpl
  23. 342 0
      Documentation/DocBook/kernel-api.tmpl
  24. 1349 0
      Documentation/DocBook/kernel-hacking.tmpl
  25. 2088 0
      Documentation/DocBook/kernel-locking.tmpl
  26. 282 0
      Documentation/DocBook/libata.tmpl
  27. 289 0
      Documentation/DocBook/librs.tmpl
  28. 265 0
      Documentation/DocBook/lsm.tmpl
  29. 3 0
      Documentation/DocBook/man/Makefile
  30. 107 0
      Documentation/DocBook/mcabook.tmpl
  31. 1320 0
      Documentation/DocBook/mtdnand.tmpl
  32. 591 0
      Documentation/DocBook/procfs-guide.tmpl
  33. 224 0
      Documentation/DocBook/procfs_example.c
  34. 193 0
      Documentation/DocBook/scsidrivers.tmpl
  35. 585 0
      Documentation/DocBook/sis900.tmpl
  36. 327 0
      Documentation/DocBook/tulip-user.tmpl
  37. 979 0
      Documentation/DocBook/usb.tmpl
  38. 597 0
      Documentation/DocBook/via-audio.tmpl
  39. 1663 0
      Documentation/DocBook/videobook.tmpl
  40. 99 0
      Documentation/DocBook/wanbook.tmpl
  41. 419 0
      Documentation/DocBook/writing_usb_driver.tmpl
  42. 385 0
      Documentation/DocBook/z8530book.tmpl
  43. 208 0
      Documentation/IO-mapping.txt
  44. 534 0
      Documentation/IPMI.txt
  45. 37 0
      Documentation/IRQ-affinity.txt
  46. 503 0
      Documentation/MSI-HOWTO.txt
  47. 276 0
      Documentation/ManagementStyle
  48. 217 0
      Documentation/PCIEBUS-HOWTO.txt
  49. 387 0
      Documentation/RCU/RTFP.txt
  50. 64 0
      Documentation/RCU/UP.txt
  51. 141 0
      Documentation/RCU/arrayRCU.txt
  52. 157 0
      Documentation/RCU/checklist.txt
  53. 307 0
      Documentation/RCU/listRCU.txt
  54. 67 0
      Documentation/RCU/rcu.txt
  55. 756 0
      Documentation/README.DAC960
  56. 8 0
      Documentation/README.cycladesZ
  57. 88 0
      Documentation/SAK.txt
  58. 38 0
      Documentation/SecurityBugs
  59. 145 0
      Documentation/SubmittingDrivers
  60. 374 0
      Documentation/SubmittingPatches
  61. 39 0
      Documentation/VGA-softcursor.txt
  62. 91 0
      Documentation/aoe/aoe.txt
  63. 17 0
      Documentation/aoe/autoload.sh
  64. 36 0
      Documentation/aoe/mkdevs.sh
  65. 25 0
      Documentation/aoe/mkshelf.sh
  66. 31 0
      Documentation/aoe/status.sh
  67. 26 0
      Documentation/aoe/udev-install.sh
  68. 23 0
      Documentation/aoe/udev.txt
  69. 20 0
      Documentation/arm/00-INDEX
  70. 141 0
      Documentation/arm/Booting
  71. 69 0
      Documentation/arm/IXP2000
  72. 174 0
      Documentation/arm/IXP4xx
  73. 173 0
      Documentation/arm/Interrupts
  74. 78 0
      Documentation/arm/Netwinder
  75. 135 0
      Documentation/arm/Porting
  76. 198 0
      Documentation/arm/README
  77. 43 0
      Documentation/arm/SA1100/ADSBitsy
  78. 301 0
      Documentation/arm/SA1100/Assabet
  79. 66 0
      Documentation/arm/SA1100/Brutus
  80. 29 0
      Documentation/arm/SA1100/CERF
  81. 21 0
      Documentation/arm/SA1100/FreeBird
  82. 98 0
      Documentation/arm/SA1100/GraphicsClient
  83. 53 0
      Documentation/arm/SA1100/GraphicsMaster
  84. 17 0
      Documentation/arm/SA1100/HUW_WEBPANEL
  85. 39 0
      Documentation/arm/SA1100/Itsy
  86. 14 0
      Documentation/arm/SA1100/LART
  87. 11 0
      Documentation/arm/SA1100/PLEB
  88. 23 0
      Documentation/arm/SA1100/Pangolin
  89. 7 0
      Documentation/arm/SA1100/Tifon
  90. 16 0
      Documentation/arm/SA1100/Victor
  91. 2 0
      Documentation/arm/SA1100/Yopy
  92. 2 0
      Documentation/arm/SA1100/empeg
  93. 11 0
      Documentation/arm/SA1100/nanoEngine
  94. 47 0
      Documentation/arm/SA1100/serial_UART
  95. 58 0
      Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt
  96. 122 0
      Documentation/arm/Samsung-S3C24XX/GPIO.txt
  97. 40 0
      Documentation/arm/Samsung-S3C24XX/H1940.txt
  98. 156 0
      Documentation/arm/Samsung-S3C24XX/Overview.txt
  99. 56 0
      Documentation/arm/Samsung-S3C24XX/SMDK2440.txt
  100. 106 0
      Documentation/arm/Samsung-S3C24XX/Suspend.txt

+ 356 - 0
COPYING

@@ -0,0 +1,356 @@
+
+   NOTE! This copyright does *not* cover user programs that use kernel
+ services by normal system calls - this is merely considered normal use
+ of the kernel, and does *not* fall under the heading of "derived work".
+ Also note that the GPL below is copyrighted by the Free Software
+ Foundation, but the instance of code that it refers to (the Linux
+ kernel) is copyrighted by me and others who actually wrote it.
+
+ Also note that the only valid version of the GPL as far as the kernel
+ is concerned is _this_ particular version of the license (ie v2, not
+ v2.2 or v3.x or whatever), unless explicitly otherwise stated.
+
+			Linus Torvalds
+
+----------------------------------------
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 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.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program 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.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public 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.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

+ 3743 - 0
CREDITS

@@ -0,0 +1,3743 @@
+	This is at least a partial credits-file of people that have
+	contributed to the Linux project.  It is sorted by name and
+	formatted to allow easy grepping and beautification by
+	scripts.  The fields are: name (N), email (E), web-address
+	(W), PGP key ID and fingerprint (P), description (D), and
+	snail-mail address (S).
+	Thanks,
+
+			Linus
+----------
+
+N: Matti Aarnio
+E: mea@nic.funet.fi
+D: Alpha systems hacking, IPv6 and other network related stuff
+D: One of assisting postmasters for vger.kernel.org's lists
+S: (ask for current address)
+S: Finland
+
+N: Dragos Acostachioaie
+E: dragos@iname.com
+W: http://www.arbornet.org/~dragos
+D: /proc/sysvipc
+S: C. Negri 6, bl. D3
+S: Iasi 6600
+S: Romania
+
+N: Monalisa Agrawal
+E: magrawal@nortelnetworks.com
+D: Basic Interphase 5575 driver with UBR and ABR support.
+S: 75 Donald St, Apt 42
+S: Weymouth, MA 02188
+
+N: Dave Airlie
+E: airlied@linux.ie
+W: http://www.csn.ul.ie/~airlied
+D: NFS over TCP patches
+D: in-kernel DRM Maintainer
+S: Longford, Ireland
+S: Sydney, Australia
+
+N: Tigran A. Aivazian
+E: tigran@veritas.com
+W: http://www.moses.uklinux.net/patches
+D: BFS filesystem
+D: Intel IA32 CPU microcode update support
+D: Various kernel patches
+S: United Kingdom
+
+N: Werner Almesberger
+E: werner@almesberger.net
+W: http://www.almesberger.net/
+D: dosfs, LILO, some fd features, ATM, various other hacks here and there
+S: Buenos Aires
+S: Argentina
+
+N: Tim Alpaerts
+E: tim_alpaerts@toyota-motor-europe.com
+D: 802.2 class II logical link control layer,
+D: the humble start of an opening towards the IBM SNA protocols
+S: Klaproosstraat 72 c 10
+S: B-2610 Wilrijk-Antwerpen
+S: Belgium
+
+N: Anton Altaparmakov
+E: aia21@cantab.net
+W: http://www-stu.christs.cam.ac.uk/~aia21/
+D: Author of new NTFS driver, various other kernel hacks.
+S: Christ's College
+S: Cambridge CB2 3BU
+S: United Kingdom
+
+N: C. Scott Ananian
+E: cananian@alumni.princeton.edu
+W: http://www.pdos.lcs.mit.edu/~cananian
+P: 1024/85AD9EED AD C0 49 08 91 67 DF D7  FA 04 1A EE 09 E8 44 B0
+D: Unix98 pty support.
+D: APM update to 1.2 spec.
+D: /devfs hacking.
+S: 7 Kiwi Loop
+S: Howell, NJ 07731
+S: USA
+
+N: Erik Andersen
+E: andersen@codepoet.org
+W: http://www.codepoet.org/
+P: 1024D/30D39057 1BC4 2742 E885 E4DE 9301  0C82 5F9B 643E 30D3 9057
+D: Maintainer of ide-cd and Uniform CD-ROM driver, 
+D: ATAPI CD-Changer support, Major 2.1.x CD-ROM update.
+S: 352 North 525 East
+S: Springville, Utah 84663
+S: USA
+
+N: Michael Ang
+E: mang@subcarrier.org
+W: http://www.subcarrier.org/mang
+D: Linux/PA-RISC hacker
+S: 85 Frank St.
+S: Ottawa, Ontario
+S: Canada K2P 0X3
+
+N: H. Peter Anvin
+E: hpa@zytor.com
+W: http://www.zytor.com/~hpa/
+P: 2047/2A960705 BA 03 D3 2C 14 A8 A8 BD  1E DF FE 69 EE 35 BD 74
+D: Author of the SYSLINUX boot loader, maintainer of the linux.* news
+D: hierarchy and the Linux Device List; various kernel hacks
+S: 4390 Albany Drive #46
+S: San Jose, California 95129
+S: USA
+
+N: Andrea Arcangeli
+E: andrea@suse.de
+W: http://www.kernel.org/pub/linux/kernel/people/andrea/
+P: 1024D/68B9CB43 13D9 8355 295F 4823 7C49  C012 DFA1 686E 68B9 CB43
+P: 1024R/CB4660B9 CC A0 71 81 F4 A0 63 AC  C0 4B 81 1D 8C 15 C8 E5
+D: Parport hacker
+D: Implemented a workaround for some interrupt buggy printers
+D: Author of pscan that helps to fix lp/parport bugs
+D: Author of lil (Linux Interrupt Latency benchmark)
+D: Fixed the shm swap deallocation at swapoff time (try_to_unuse message)
+D: VM hacker
+D: Various other kernel hacks
+S: Via Cicalini 26
+S: Imola 40026
+S: Italy
+
+N: Derek Atkins
+E: warlord@MIT.EDU
+D: Linux-AFS Port, random kernel hacker,
+D: VFS fixes (new notify_change in particular)
+D: Moving all VFS access checks into the file systems
+S: MIT Room E15-341
+S: 20 Ames Street
+S: Cambridge, Massachusetts 02139
+S: USA
+
+N: Michel Aubry
+E: giovanni <giovanni@sudfr.com>
+D: Aladdin 1533/1543(C) chipset IDE
+D: VIA MVP-3/TX Pro III chipset IDE
+
+N: Jens Axboe
+E: axboe@suse.de
+D: Linux CD-ROM maintainer, DVD support
+D: elevator + block layer rewrites
+D: highmem I/O support
+D: misc hacking on IDE, SCSI, block drivers, etc
+S: Peter Bangs Vej 258, 2TH
+S: 2500 Valby
+S: Denmark
+
+N: John Aycock
+E: aycock@cpsc.ucalgary.ca
+D: Adaptec 274x driver
+S: Department of Computer Science
+S: University of Calgary
+S: Calgary, Alberta
+S: Canada
+
+N: Miles Bader
+E: miles@gnu.org
+D: v850 port (uClinux)
+S: NEC Corporation
+S: 1753 Shimonumabe, Nakahara-ku
+S: Kawasaki 211-8666
+S: Japan
+
+N: Ralf Baechle
+E: ralf@gnu.org
+P: 1024/AF7B30C1 CF 97 C2 CC 6D AE A7 FE  C8 BA 9C FC 88 DE 32 C3
+D: Linux/MIPS port
+D: Linux/68k hacker
+S: Hauptstrasse 19
+S: 79837 St. Blasien
+S: Germany
+
+N: Krishna Balasubramanian
+E: balasub@cis.ohio-state.edu
+D: Wrote SYS V IPC (part of standard kernel since 0.99.10)
+
+N: Dario Ballabio
+E: ballabio_dario@emc.com
+E: dario.ballabio@tiscalinet.it
+E: dario.ballabio@inwind.it
+D: Author and maintainer of the Ultrastor 14F/34F SCSI driver
+D: Author and maintainer of the EATA ISA/EISA/PCI SCSI driver
+S: EMC Corporation
+S: Milano
+S: Italy
+
+N: Paul Bame
+E: bame@debian.org
+E: bame@puffin.external.hp.com
+E: paul_bame@hp.com
+W: http://www.parisc-linux.org
+D: PA-RISC 32 and 64-bit early boot, firmware interface, interrupts, misc
+S: MS42
+S: Hewlett-Packard
+S: 3404 E Harmony Rd
+S: Fort Collins, CO 80525
+
+N: Arindam Banerji
+E: axb@cse.nd.edu
+D: Contributed ESDI driver routines needed to port LINUX to the PS/2 MCA.
+S: Department of Computer Science & Eng.
+S: University of Notre Dame
+S: Notre Dame, Indiana
+S: USA
+
+N: Greg Banks
+E: gnb@alphalink.com.au
+D: IDT77105 ATM network driver
+D: some SuperH port work
+D: some trivial futzing with kconfig
+
+N: James Banks
+E: james@sovereign.org
+D: TLAN network driver
+D: Logitech Busmouse driver
+
+N: Krzysztof G. Baranowski
+E: kgb@manjak.knm.org.pl
+P: 1024/FA6F16D1 96 D1 1A CF 5F CA 69 EC  F9 4F 36 1F 6D 60 7B DA
+D: Maintainer of the System V file system.
+D: System V fs update for 2.1.x dcache.
+D: Forward ported a couple of SCSI drivers.
+D: Various bugfixes.
+S: ul. Koscielna 12a
+S: 62-300 Wrzesnia
+S: Poland
+
+N: Fred Barnes
+E: frmb2@ukc.ac.uk
+D: Various parport/ppdev hacks and fixes
+S: Computing Lab, The University
+S: Canterbury, KENT
+S: CT2 7NF
+S: England
+
+N: Paul Barton-Davis
+E: pbd@op.net
+D: Driver for WaveFront soundcards (Turtle Beach Maui, Tropez, Tropez+)
+D: Various bugfixes and changes to sound drivers
+S: USA 
+
+N: Carlos Henrique Bauer
+E: chbauer@acm.org
+E: bauer@atlas.unisinos.br
+D: Some new sysctl entries for the parport driver.
+D: New sysctl function for handling unsigned longs
+S: Universidade do Vale do Rio dos Sinos - UNISINOS
+S: DSI/IDASI
+S: Av. Unisinos, 950
+S: 93022000 Sao Leopoldo RS
+S: Brazil
+
+N: Peter Bauer
+E: 100136.3530@compuserve.com
+D: Driver for depca-ethernet-board
+S: 69259 Wilhemsfeld
+S: Rainweg 15
+S: Germany
+
+N: Fred Baumgarten
+E: dc6iq@insl1.etec.uni-karlsruhe.de
+E: dc6iq@adacom.org
+E: dc6iq@db0ais.#hes.deu.eu (packet radio)
+D: NET-2 & netstat(8)
+S: Soevener Strasse 11
+S: 53773 Hennef
+S: Germany
+
+N: Donald Becker
+E: becker@cesdis.gsfc.nasa.gov
+D: General low-level networking hacker
+D: Most of the ethercard drivers
+D: Original author of the NFS server
+S: USRA Center of Excellence in Space Data and Information Sciences
+S: Code 930.5, Goddard Space Flight Center
+S: Greenbelt, Maryland 20771
+S: USA
+
+N: Adam Belay
+E: ambx1@neo.rr.com
+D: Linux Plug and Play Support
+S: USA
+
+N: Daniele Bellucci
+E: bellucda@tiscali.it
+D: Various Janitor work.
+W: http://web.tiscali.it/bellucda
+S: Via Delle Palme, 9
+S: Terni 05100
+S: Italy
+
+N: Krzysztof Benedyczak
+E: golbi@mat.uni.torun.pl
+W: http://www.mat.uni.torun.pl/~golbi
+D: POSIX message queues fs (with M. Wronski)
+S: ul. Podmiejska 52
+S: Radunica
+S: 83-000 Pruszcz Gdanski
+S: Poland
+
+N: Randolph Bentson
+E: bentson@grieg.seaslug.org
+W: http://www.aa.net/~bentson/
+P: 1024/39ED5729 5C A8 7A F4 B2 7A D1 3E  B5 3B 81 CF 47 30 11 71
+D: Author of driver for Cyclom-Y and Cyclades-Z async mux
+S: 2322 37th Ave SW
+S: Seattle, Washington 98126-2010
+S: USA
+
+N: Stephen R. van den Berg (AKA BuGless)
+E: berg@pool.informatik.rwth-aachen.de
+D: General kernel, gcc, and libc hacker
+D: Specialisation: tweaking, ensuring portability, tweaking, cleaning,
+D: tweaking and occasionally debugging :-)
+S: Bouwensstraat 22
+S: 6369 BG Simpelveld
+S: The Netherlands
+
+N: Peter Berger
+E: pberger@brimson.com
+W: http://www.brimson.com
+D: Author/maintainer of Digi AccelePort USB driver
+S: 1549 Hiironen Rd.
+S: Brimson, MN  55602
+S: USA
+
+N: Hennus Bergman
+P: 1024/77D50909 76 99 FD 31 91 E1 96 1C  90 BB 22 80 62 F6 BD 63
+D: Author and maintainer of the QIC-02 tape driver
+S: The Netherlands
+
+N: Tomas Berndtsson
+E: tomas@nocrew.org
+W: http://tomas.nocrew.org/
+D: dsp56k device driver
+
+N: Ross Biro
+E: bir7@leland.Stanford.Edu
+D: Original author of the Linux networking code
+
+N: Anton Blanchard
+E: anton@samba.org
+W: http://samba.org/~anton/
+P: 1024/8462A731 4C 55 86 34 44 59 A7 99  2B 97 88 4A 88 9A 0D 97
+D: sun4 port, Sparc hacker
+
+N: Hugh Blemings
+E: hugh@misc.nu
+W: http://misc.nu/hugh/
+D: Author and maintainer of the Keyspan USB to Serial drivers
+S: Po Box 234
+S: Belconnen ACT 2616
+S: Australia
+
+N: Philip Blundell
+E: philb@gnu.org
+D: Linux/ARM hacker
+D: Device driver hacker (eexpress, 3c505, c-qcam, ...)
+D: m68k port to HP9000/300
+D: AUN network protocols
+D: Co-architect of the parallel port sharing system
+D: IPv6 netfilter
+S: FutureTV Labs Ltd
+S: Brunswick House, 61-69 Newmarket Rd, Cambridge CB5 8EG
+S: United Kingdom
+
+N: Thomas Bogendörfer
+E: tsbogend@alpha.franken.de
+D: PCnet32 driver, SONIC driver, JAZZ_ESP driver
+D: newport abscon driver, g364 framebuffer driver
+D: strace for Linux/Alpha
+D: Linux/MIPS hacker
+S: Schafhofstr. 40
+S: 90556 Cadolzburg
+S: Germany
+
+N: Bill Bogstad
+E: bogstad@pobox.com
+D: wrote /proc/self hack, minor samba & dosemu patches
+
+N: Axel Boldt
+E: axel@uni-paderborn.de
+W: http://math-www.uni-paderborn.de/~axel/
+D: Configuration help text support
+D: Linux CD and Support Giveaway List
+
+N: Erik Inge Bolsø
+E: knan@mo.himolde.no
+D: Misc kernel hacks
+
+N: Andreas E. Bombe
+E: andreas.bombe@munich.netsurf.de
+W: http://home.pages.de/~andreas.bombe/
+P: 1024/04880A44 72E5 7031 4414 2EB6 F6B4  4CBD 1181 7032 0488 0A44
+D: IEEE 1394 subsystem rewrite and maintainer
+D: Texas Instruments PCILynx IEEE 1394 driver
+
+N: Al Borchers
+E: alborchers@steinerpoint.com
+D: Author/maintainer of Digi AccelePort USB driver
+D: work on usbserial and keyspan_pda drivers
+S: 4912 Zenith Ave. S.
+S: Minneapolis, MN  55410
+S: USA
+
+N: Marc Boucher
+E: marc@mbsi.ca
+P: CA 67 A5 1A 38 CE B6 F2  D5 83 51 03 D2 9C 30 9E  CE D2 DD 65
+D: Netfilter core
+D: IP policy routing by mark
+D: Various fixes (mostly networking)
+S: Montreal, Quebec
+S: Canada
+
+N: Zoltán Böszörményi
+E: zboszor@mail.externet.hu
+D: MTRR emulation with Cyrix style ARR registers, Athlon MTRR support
+
+N: John Boyd
+E: boyd@cis.ohio-state.edu
+D: Co-author of wd7000 SCSI driver
+S: 101 Curl Drive #591
+S: Columbus, Ohio 43210
+S: USA
+
+N: Peter Braam
+E: braam@clusterfs.com
+W: http://www.clusterfs.com/
+D: Coda & InterMezzo filesystems
+S: 181 McNeil
+S: Canmore, AB
+S: Canada, T1W 2R9
+
+N: Ryan Bradetich
+E: rbradetich@uswest.net
+D: Linux/PA-RISC hacker
+S: 1200 Goldenrod Dr.
+S: Nampa, Idaho 83686
+
+N: Derrick J. Brashear
+E: shadow@dementia.org
+W: http://www.dementia.org/~shadow
+P: 512/71EC9367 C5 29 0F BC 83 51 B9 F0  BC 05 89 A0 4F 1F 30 05
+D: Author of Sparc CS4231 audio driver, random Sparc work
+S: 403 Gilmore Avenue
+S: Trafford, Pennsylvania 15085
+S: USA
+
+N: Dag Brattli
+E: dagb@cs.uit.no
+W: http://www.cs.uit.no/~dagb
+D: IrDA Subsystem
+S: 19. Wellington Road
+S: Lancaster, LA1 4DN
+S: UK, England
+
+N: Lars Brinkhoff
+E: lars@nocrew.org
+W: http://lars.nocrew.org/
+D: dsp56k device driver
+D: ptrace proxy in user mode kernel port
+S: Kopmansg 2
+S: 411 13  Goteborg
+S: Sweden
+
+N: Dominik Brodowski
+E: linux@brodo.de
+W: http://www.brodo.de/
+P: 1024D/725B37C6  190F 3E77 9C89 3B6D BECD  46EE 67C3 0308 725B 37C6
+D: parts of CPUFreq code, ACPI bugfixes
+S: Tuebingen, Germany
+
+N: Andries Brouwer
+E: aeb@cwi.nl
+D: random Linux hacker
+S: Bessemerstraat 21
+S: Amsterdam
+S: The Netherlands
+
+N: Zach Brown
+E: zab@zabbo.net
+D: maestro pci sound
+
+N: Gary Brubaker
+E: xavyer@ix.netcom.com
+D: USB Serial Empeg Empeg-car Mark I/II Driver
+
+N: Matthias Bruestle
+E: m@mbsks.franken.de
+D: REINER SCT cyberJack pinpad/e-com USB chipcard reader driver
+S: Germany
+
+N: Adrian Bunk
+E: bunk@stusta.de
+P: 1024D/4F12B400  B29C E71E FE19 6755 5C8A  84D4 99FC EA98 4F12 B400
+D: misc kernel hacking and testing
+S: Grasmeierstrasse 11
+S: 80805 Muenchen
+S: Germany
+
+N: Ray Burr
+E: ryb@nightmare.com
+D: Original author of Amiga FFS filesystem
+S: Orlando, Florida
+S: USA
+
+N: Lennert Buytenhek
+E: buytenh@gnu.org
+D: Rewrite of the ethernet bridging code
+S: Ravenhorst 58B
+S: 2317 AK Leiden
+S: The Netherlands
+
+N: Michael Callahan
+E: callahan@maths.ox.ac.uk
+D: PPP for Linux
+S: The Mathematical Institute
+S: 25-29 St Giles
+S: Oxford
+S: United Kingdom
+
+N: Luiz Fernando N. Capitulino
+E: lcapitulino@terra.com.br
+E: lcapitulino@prefeitura.sp.gov.br
+W: http://www.telecentros.sp.gov.br
+D: Little fixes and a lot of janitorial work
+S: E-GOV Telecentros SP
+S: Brazil
+
+N: Remy Card
+E: Remy.Card@masi.ibp.fr
+E: Remy.Card@linux.org
+D: Extended file system [defunct] designer and developer
+D: Second extended file system designer and developer
+S: Institut Blaise Pascal
+S: 4 Place Jussieu
+S: 75252 Paris Cedex 05
+S: France
+
+N: Ulf Carlsson
+D: SGI Indy audio (HAL2) drivers
+E: ulfc@bun.falkenberg.se
+
+N: Ed Carp
+E: ecarp@netcom.com
+D: uucp, elm, pine, pico port
+D: cron, at(1) developer
+S: 48287 Sawleaf
+S: Fremont, California 94539
+S: USA
+
+N: Florent Chabaud
+E: florent.chabaud@polytechnique.org
+D: software suspend
+S: SGDN/DCSSI/SDS/LTI
+S: 58, Bd Latour-Maubourg
+S: 75700 Paris 07 SP
+S: France
+
+N: Gordon Chaffee
+E: chaffee@cs.berkeley.edu
+W: http://bmrc.berkeley.edu/people/chaffee/
+D: vfat, fat32, joliet, native language support
+S: 3700 Warwick Road
+S: Fremont, California 94555
+S: USA
+
+N: Chih-Jen Chang
+E: chihjenc@scf.usc.edu
+E: chihjen@iis.sinica.edu.tw
+D: IGMP(Internet Group Management Protocol) version 2
+S: 3F, 65 Tajen street
+S: Tamsui town, Taipei county,
+S: Taiwan 251
+S: Republic of China
+
+N: Michael Elizabeth Chastain
+E: mec@shout.net
+D: Configure, Menuconfig, xconfig
+
+N: Raymond Chen
+E: raymondc@microsoft.com
+D: Author of Configure script
+S: 14509 NE 39th Street #1096
+S: Bellevue, Washington 98007
+S: USA
+
+N: Christopher L. Cheney
+E: ccheney@debian.org
+E: ccheney@cheney.cx
+W: http://www.cheney.cx
+P: 1024D/8E384AF2 2D31 1927 87D7 1F24 9FF9  1BC5 D106 5AB3 8E38 4AF2
+D: Vista Imaging usb webcam driver
+S: 314 Prince of Wales
+S: Conroe, TX 77304
+S: USA
+
+N: Stuart Cheshire
+E: cheshire@cs.stanford.edu
+D: Author of Starmode Radio IP (STRIP) driver
+D: Originator of design for new combined interrupt handlers
+S: William Gates Department
+S: Stanford University
+S: Stanford, California 94305
+S: USA
+
+N: Randolph Chung
+E: tausq@debian.org
+D: Linux/PA-RISC hacker
+S: Los Altos, CA 94022
+S: USA
+
+N: Juan Jose Ciarlante
+W: http://juanjox.kernelnotes.org/
+E: jjciarla@raiz.uncu.edu.ar
+E: jjo@mendoza.gov.ar
+D: Network driver alias support
+D: IP masq hashing and app modules
+D: IP masq 2.1 features and bugs
+S: Las Cuevas 2385 - Bo Guemes
+S: Las Heras, Mendoza CP 5539
+S: Argentina
+
+N: Steven P. Cole
+E: scole@lanl.gov
+E: elenstev@mesatop.com
+D: Various build fixes and kernel documentation.
+S: Los Alamos, New Mexico
+
+N: Hamish Coleman
+E: hamish@zot.apana.org.au
+D: SEEQ8005 network driver
+S: 98 Paxton Street
+S: East Malvern, Victoria, 3145
+S: Australia
+
+N: Neil Conway
+E: nconway.list@ukaea.org.uk
+D: Assorted sched/mm titbits
+S: Oxfordshire, UK.
+
+N: Kees Cook
+E: kees@outflux.net
+W: http://outflux.net/
+P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30  1975 1FFF 4BA9 1706 3E6D
+D: Minor updates to SCSI code for the Communications type
+S: (ask for current address)
+S: USA
+
+N: Mark Corner
+E: mcorner@umich.edu
+W: http://www.eecs.umich.edu/~mcorner/
+D: USB Bluetooth Driver
+S: University of Michigan
+S: Ann Arbor, MI
+
+N: Michael Cornwell
+E: cornwell@acm.org
+D: Original designer and co-author of ATA Taskfile
+D: Kernel module SMART utilities
+S: Santa Cruz, California
+S: USA
+
+N: Alan Cox
+W: http://www.linux.org.uk/diary/
+D: Linux Networking (0.99.10->2.0.29)
+D: Original Appletalk, AX.25, and IPX code
+D: 3c501 hacker
+D: Watchdog timer drivers
+D: Linux/SMP x86 (up to 2.0 only)
+D: Initial Mac68K port
+D: Video4Linux design, bw-qcam and PMS driver ports.
+D: IDE modularisation work
+D: Z85230 driver
+D: Former security contact point (please use vendor-sec@lst.de)
+D: ex 2.2 maintainer
+D: 2.1.x modular sound
+S: c/o Red Hat UK Ltd
+S: Alexandra House
+S: Alexandra Terrace
+S: Guildford, GU1 3DA
+S: United Kingdom
+
+N: Cristian Mihail Craciunescu
+W: http://www.dnt.ro/~cristi/
+E: cristi@dnt.ro
+D: Support for Xircom PGSDB9 (firmware and host driver)
+S: Bucharest
+S: Romania
+
+N: Laurence Culhane
+E: loz@holmes.demon.co.uk
+D: Wrote the initial alpha SLIP code
+S: 81 Hood Street
+S: Northampton
+S: NN1 3QT
+S: United Kingdom
+
+N: Uwe Dannowski
+E: Uwe.Dannowski@ira.uka.de
+W: http://i30www.ira.uka.de/~dannowsk/
+D: FORE PCA-200E driver
+S: University of Karlsruhe
+S: Germany
+
+N: Ray Dassen
+E: jdassen@wi.LeidenUniv.nl
+W: http://www.wi.leidenuniv.nl/~jdassen/
+P: 1024/672D05C1 DD 60 32 60 F7 90 64 80  E7 6F D4 E4 F8 C9 4A 58
+D: Debian GNU/Linux: www.debian.org maintainer, FAQ co-maintainer,
+D: packages testing, nit-picking & fixing. Enjoying BugFree (TM) kernels.
+S: Zuidsingel 10A
+S: 2312 SB  Leiden
+S: The Netherlands
+
+N: David Davies
+E: davies@wanton.lkg.dec.com
+D: Network driver author - depca, ewrk3 and de4x5
+D: Wrote shared interrupt support
+S: Digital Equipment Corporation
+S: 550 King Street
+S: Littleton, Massachusetts 01460
+S: USA
+
+N: Frank Davis
+E: fdavis@si.rr.com
+E: fdavis112@juno.com
+D: Various kernel patches
+S: 8 Lakeview Terr.
+S: Kerhonkson, NY 12446
+S: USA
+
+N: Wayne Davison
+E: davison@borland.com
+D: Second extended file system co-designer
+
+N: Terry Dawson
+E: terry@perf.no.itg.telecom.com.au
+E: terry@albert.vk2ktj.ampr.org (Amateur Radio use only)
+D: trivial hack to add variable address length routing to Rose.
+D: AX25-HOWTO, HAM-HOWTO, IPX-HOWTO, NET-2-HOWTO
+D: ax25-utils maintainer.
+
+N: Helge Deller
+E: deller@gmx.de
+E: hdeller@redhat.de
+D: PA-RISC Linux hacker, LASI-, ASP-, WAX-, LCD/LED-driver
+S: Schimmelsrain 1
+S: D-69231 Rauenberg
+S: Germany
+
+N: Jean Delvare
+E: khali@linux-fr.org
+W: http://khali.linux-fr.org/
+D: Several hardware monitoring drivers
+S: France
+
+N: Peter Denison
+E: peterd@pnd-pc.demon.co.uk
+W: http://www.pnd-pc.demon.co.uk/promise/
+D: Promise DC4030VL caching HD controller drivers
+
+N: Todd J. Derr
+E: tjd@fore.com
+W: http://www.wordsmith.org/~tjd
+D: Random console hacks and other miscellaneous stuff
+S: 3000 FORE Drive
+S: Warrendale, Pennsylvania 15086
+S: USA
+
+N: Martin Devera
+E: devik@cdi.cz
+W: http://luxik.cdi.cz/~devik/qos/
+D: HTB qdisc and random networking hacks
+
+N: Alex deVries
+E: alex@onefishtwo.ca
+D: Various SGI parts, bits of HAL2 and Newport, PA-RISC Linux.
+S: 41.5 William Street
+S: Ottawa, Ontario
+S: K1N 6Z9
+S: CANADA
+
+N: Jeff Dike
+E: jdike@karaya.com
+W: http://user-mode-linux.sourceforge.net
+D: User mode kernel port
+S: 375 Tubbs Hill Rd
+S: Deering NH 03244
+S: USA
+
+N: Matt Domsch
+E: Matt_Domsch@dell.com
+W: http://www.dell.com/linux
+W: http://domsch.com/linux
+D: Linux/IA-64
+D: Dell PowerEdge server, SCSI layer, misc drivers, and other patches
+S: Dell Inc.
+S: One Dell Way
+S: Round Rock, TX  78682
+S: USA
+
+N: Ben Dooks
+E: ben-linux@fluff.org
+E: ben@simtec.co.uk
+W: http://www.fluff.org/ben/
+W: http://www.simtec.co.uk/
+D: Samsung S3C2410/S3C2440 support, general ARM support
+D: Maintaining Simtec Electronics development boards
+S: Simtec Electronics
+S: Avondale Drive
+S: Tarleton
+S: Preston
+S: Lancs
+S: PR4 6AX
+S: United Kingdom
+
+N: John G Dorsey
+E: john+@cs.cmu.edu
+D: ARM Linux ports to Assabet/Neponset, Spot
+S: Department of Electrical and Computer Engineering
+S: Carnegie Mellon University
+S: Pittsburgh, PA  15213
+S: USA
+
+N: Eddie C. Dost
+E: ecd@skynet.be
+D: Linux/Sparc kernel hacker
+D: Linux/Sparc maintainer
+S: Rue de la Chapelle 51
+S: 4850 Moresnet
+S: Belgium
+
+N: Cort Dougan
+E: cort@fsmlabs.com
+W: http://www.fsmlabs.com/linuxppcbk.html
+D: PowerPC
+
+N: Daniel Drake
+E: dsd@gentoo.org
+D: USBAT02 CompactFlash support in usb-storage
+S: UK
+
+N: Oleg Drokin
+E: green@ccssu.crimea.ua
+W: http://www.ccssu.crimea.ua/~green
+D: Cleaning up sound drivers, SA1100 Watchdog.
+S: Skvoznoy per., 14a
+S: Evpatoria
+S: Crimea
+S: UKRAINE, 334320
+
+N: Walt Drummond
+E: drummond@valinux.com
+D: Linux/IA-64
+S: 1382 Bordeaux Drive
+S: Sunnyvale, CA 94087
+S: USA
+
+N: Bruno Ducrot
+E: ducrot@poupinou.org
+D: CPUFreq and ACPI bugfixes.
+S: Mougin, France
+
+N: Don Dugger
+E: n0ano@valinux.com
+D: Linux/IA-64
+S: 1209 Pearl Street, #12
+S: Boulder, CO 80302
+S: USA
+
+N: Thomas Dunbar
+E: tdunbar@vt.edu
+D: TeX & METAFONT hacking/maintenance
+S: Virginia Tech Computing Center
+S: 1700 Pratt Drive
+S: Blacksburg, Virginia 24061
+S: USA
+
+N: Randy Dunlap
+E: rddunlap@osdl.org
+W: http://www.xenotime.net/linux/linux.html
+W: http://www.linux-usb.org
+D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers
+D: x86 SMP, ACPI, bootflag hacking
+S: 12725 SW Millikan Way, Suite 400
+S: Beaverton, Oregon 97005
+S: USA
+
+N: Bob Dunlop
+E: rjd@xyzzy.clara.co.uk
+E: bob.dunlop@farsite.co.uk
+W: www.farsite.co.uk
+D: FarSync card device driver
+S: FarSite Communications Ltd
+S: Tempus Business Centre
+S: 60 Kingsclere Road
+S: Basingstoke       RG21 6XG
+S: UK
+
+N: Cyrus Durgin
+E: cider@speakeasy.org
+W: http://www.speakeasy.org/~cider/
+D: implemented kmod
+
+N: Torsten Duwe
+E: Torsten.Duwe@informatik.uni-erlangen.de
+D: Part-time kernel hacker
+D: The Linux Support Team Erlangen
+S: Grevenbroicher Str. 17
+S: 47807 Krefeld
+S: Germany
+
+N: Tom Dyas
+E: tdyas@eden.rutgers.edu
+D: minor hacks and some sparc port stuff
+S: New Jersey
+S: USA
+
+N: Drew Eckhardt
+E: drew@PoohSticks.ORG
+D: SCSI code
+D: Assorted snippets elsewhere
+D: Boot sector "..." printing
+S: 2037 Walnut #6
+S: Boulder, Colorado 80302
+S: USA
+
+N: Heiko Eissfeldt
+E: heiko@colossus.escape.de heiko@unifix.de
+D: verify_area stuff, generic SCSI fixes
+D: SCSI Programming HOWTO
+D: POSIX.1 compliance testing
+S: Unifix Software GmbH
+S: Bueltenweg 27a
+S: D-38106 Braunschweig
+S: Germany
+
+N: Bjorn Ekwall
+E: bj0rn@blox.se
+W: http://www.pi.se/blox/
+D: Extended support for loadable modules
+D: D-Link pocket adapter drivers
+S: Brevia 1043
+S: S-114 79 Stockholm
+S: Sweden
+
+N: David Engebretsen
+E: engebret@us.ibm.com
+D: Linux port to 64-bit PowerPC architecture
+
+N: Michael Engel
+E: engel@unix-ag.org
+D: DECstation framebuffer drivers
+S: Germany
+
+N: Paal-Kristian Engstad
+E: engstad@intermetrics.com
+D: Kernel smbfs (to mount WfW, NT and OS/2 network drives.)
+S: 17101 Springdale Street #225
+S: Huntington Beach, California 92649
+S: USA
+
+N: Stephane Eranian
+E: eranian@hpl.hp.com
+D: Linux/ia64
+S: 1501 Page Mill Rd, MS 1U17
+S: Palo Alto, CA 94304
+S: USA
+
+N: Johannes Erdfelt
+E: johannes@erdfelt.com
+D: Linux/IA-64 bootloader and kernel goop, USB
+S: 6350 Stoneridge Mall Road
+S: Pleasanton, CA 94588
+S: USA
+
+N: Doug Evans
+E: dje@cygnus.com
+D: Wrote Xenix FS (part of standard kernel since 0.99.15)
+
+N: Riccardo Facchetti
+E: fizban@tin.it
+P: 1024/6E657BB5 AF 22 90 33 78 76 04 8B  AF F9 97 1E B5 E2 65 30
+D: Audio Excel DSP 16 init driver author
+D: libmodem author
+D: Yet Another Micro Monitor port and current maintainer
+D: First ELF-HOWTO author
+D: random kernel hacker
+S: Via Paolo VI n.29
+S: 23900 - LECCO (Lc)
+S: Italy
+
+N: Nils Faerber
+E: nils@kernelconcepts.de
+D: i810 TCO watchdog driver author
+D: Mitsumi LU005 tests and fixes
+D: port and fixes of cs46xx sounddriver
+S: Dreisbachstrasse 24
+S: D-57250 Netphen
+S: Germany
+
+N: Rik Faith
+E: faith@acm.org
+D: Future Domain TMC-16x0 SCSI driver (author)
+D: APM driver (early port)
+D: DRM drivers (author of several)
+
+N: János Farkas
+E: chexum@shadow.banki.hu
+D: romfs, various (mostly networking) fixes
+P: 1024/F81FB2E1 41 B7 E4 E6 3E D4 A6 71  6D 9C F3 9F F2 BF DF 6E
+S: Madarász Viktor utca 25
+S: 1131 Budapest
+S: Hungary
+
+N: Ben Fennema
+E: bfennema@falcon.csc.calpoly.edu
+W: http://www.csc.calpoly.edu/~bfennema
+D: UDF filesystem
+S: (ask for current address)
+S: USA
+
+N: Jürgen Fischer
+E: fischer@norbit.de (=?iso-8859-1?q?J=FCrgen?= Fischer)
+D: Author of Adaptec AHA-152x SCSI driver
+S: Schulstraße 18
+S: 26506 Norden
+S: Germany
+
+N: Jeremy Fitzhardinge
+E: jeremy@goop.org
+W: http://www.goop.org/~jeremy
+D: author of userfs filesystem
+D: Improved mmap and munmap handling
+D: General mm minor tidyups
+D: autofs v4 maintainer
+S: 987 Alabama St
+S: San Francisco
+S: CA, 94110
+S: USA
+
+N: Ralf Flaxa
+E: rfflaxa@immd4.informatik.uni-erlangen.de
+D: The Linux Support Team Erlangen
+D: Creator of LST distribution
+D: Author of installation tool LISA
+S: Pfitznerweg 6
+S: 74523 Schwaebisch Hall
+S: Germany
+
+N: Lawrence Foard
+E: entropy@world.std.com
+D: Floppy track reading, fs code
+S: 217 Park Avenue, Suite 108
+S: Worcester, Massachusetts 01609
+S: USA
+
+N: Karl Fogel
+E: kfogel@cs.oberlin.edu
+D: Contributor, Linux User's Guide
+S: 1123 North Oak Park Avenue
+S: Oak Park, Illinois 60302
+S: USA
+
+N: Daniel J. Frasnelli
+E: dfrasnel@alphalinux.org
+W: http://www.alphalinux.org/
+P: 1024/3EF87611 B9 F1 44 50 D3 E8 C2 80  DA E5 55 AA 56 7C 42 DA
+D: DEC Alpha hacker 
+D: Miscellaneous bug squisher
+
+N: Jim Freeman
+E: jfree@sovereign.org
+W: http://www.sovereign.org/
+D: Initial GPL'd Frame Relay driver
+D: Dynamic PPP devices
+D: Sundry modularizations (PPP, IPX, ...) and fixes
+
+N: Bob Frey
+E: bobf@advansys.com
+D: AdvanSys SCSI driver
+S: 1150 Ringwood Court
+S: San Jose, California 95131
+S: USA
+
+N: Fernando Fuganti
+E: fuganti@conectiva.com.br
+E: fuganti@netbank.com.br
+D: random kernel hacker, ZF MachZ Watchdog driver
+S: Conectiva S.A.
+S: R. Tocantins, 89 - Cristo Rei
+S: 80050-430 - Curitiba - Paraná
+S: Brazil
+
+N: Kumar Gala
+E: kumar.gala@freescale.com
+D: Embedded PowerPC 6xx/7xx/74xx/82xx/83xx/85xx support
+S: Austin, Texas 78729
+S: USA
+
+N: Nigel Gamble
+E: nigel@nrg.org
+D: Interrupt-driven printer driver
+D: Preemptible kernel
+S: 120 Alley Way
+S: Mountain View, California 94040
+S: USA
+
+N: Jeff Garzik
+E: jgarzik@pobox.com
+
+N: Jacques Gelinas
+E: jacques@solucorp.qc.ca
+D: Author of the Umsdos file system
+S: 1326 De Val-Brillant
+S: Laval, Quebec
+S: Canada H7Y 1V9
+
+N: David Gentzel
+E: gentzel@telerama.lm.com
+D: Original BusLogic driver and original UltraStor driver
+S: Whitfield Software Services
+S: 600 North Bell Avenue, Suite 160
+S: Carnegie, Pennsylvania 15106-4304
+S: USA
+
+N: Philip Gladstone
+E: philip@raptor.com
+D: Kernel / timekeeping stuff
+  
+N: Jan-Benedict Glaw
+E: jbglaw@lug-owl.de
+D: SRM environment driver (for Alpha systems)
+P: 1024D/8399E1BB 250D 3BCF 7127 0D8C A444  A961 1DBD 5E75 8399 E1BB
+
+N: Thomas Gleixner
+E: tglx@linutronix.de
+D: NAND flash hardware support, JFFS2 on NAND flash
+
+N: Richard E. Gooch
+E: rgooch@atnf.csiro.au
+D: parent process death signal to children
+D: prctl() syscall
+D: /proc/mtrr support to manipulate MTRRs on Intel P6 family
+D: Device FileSystem (devfs)
+S: CSIRO Australia Telescope National Facility
+S: P.O. Box 76, Epping
+S: New South Wales, 2121
+S: Australia
+
+N: Carlos E. Gorges 
+E: carlos@techlinux.com.br
+D: fix smp support on cmpci driver
+P: 2048G/EA3C4B19 FF31 33A6 0362 4915 B7EB  E541 17D0 0379 EA3C 4B19
+S: Brazil
+
+N: Dmitry S. Gorodchanin
+E: pgmdsg@ibi.com
+D: RISCom/8 driver, misc kernel fixes.
+S: 4 Main Street
+S: Woodbridge, Connecticut 06525
+S: USA
+
+N: Paul Gortmaker
+E: p_gortmaker@yahoo.com
+D: Author of RTC driver & several net drivers, Ethernet & BootPrompt Howto.
+D: Made support for modules, ramdisk, generic-serial, etc. optional.
+D: Transformed old user space bdflush into 1st kernel thread - kflushd.
+D: Many other patches, documentation files, mini kernels, utilities, ...
+
+N: Masanori GOTO
+E: gotom@debian.or.jp
+D: Workbit NinjaSCSI-32Bi/UDE driver
+S: Japan
+
+N: John E. Gotts
+E: jgotts@linuxsavvy.com
+D: kernel hacker
+S: 8124 Constitution Apt. 7
+S: Sterling Heights, Michigan 48313
+S: USA
+
+N: William Greathouse
+E: wgreathouse@smva.com
+E: wgreathouse@myfavoritei.com
+D: Current Belkin USB Serial Adapter F5U103 hacker
+D: Kernel hacker, embedded systems
+S: 7802 Fitzwater Road   
+S: Brecksville, OH  44141-1334
+S: USA
+
+N: Tristan Greaves
+E: Tristan.Greaves@icl.com
+E: tmg296@ecs.soton.ac.uk
+W: http://www.ecs.soton.ac.uk/~tmg296
+D: Miscellaneous ipv4 sysctl patches
+S: 15 Little Mead
+S: Denmead
+S: Hampshire
+S: PO7 6HS
+S: United Kingdom
+
+N: Michael A. Griffith
+E: grif@cs.ucr.edu
+W: http://www.cs.ucr.edu/~grif
+D: Loopback speedup, qlogic SCSI hacking, VT_LOCKSWITCH
+S: Department of Computer Science
+S: University of California, Riverside
+S: Riverside, California 92521-0304
+S: USA
+
+N: Hans Grobler
+E: grobh@sun.ac.za
+D: Various AX.25/ROSE/NETROM + hamradio driver patches
+D: Various X.25/LABP + driver patches
+D: Misc kernel fixes and updates
+S: Department of Electronic Engineering
+S: University of Stellenbosch
+S: Stellenbosch, Western Cape
+S: South Africa
+
+N: Grant Grundler
+E: grundler@parisc-linux.org
+W: http://obmouse.sourceforge.net/
+W: http://www.parisc-linux.org/
+D: obmouse - rewrote Olivier Florent's Omnibook 600 "pop-up" mouse driver
+D: PA-RISC - Interrupt/PCI HBA/IOMMU author and architect
+S: Mountain View, California
+S: USA
+
+N: Grant Guenther
+E: grant@torque.net
+W: http://www.torque.net/linux-pp.html
+D: original author of ppa driver for parallel port ZIP drive
+D: original architect of the parallel-port sharing scheme 
+D: PARIDE subsystem: drivers for parallel port IDE & ATAPI devices
+S: 44 St. Joseph Street, Suite 506
+S: Toronto, Ontario, M4Y 2W4
+S: Canada
+
+N: Richard Günther
+E: rguenth@tat.physik.uni-tuebingen.de
+W: http://www.tat.physik.uni-tuebingen.de/~rguenth
+P: 2048/2E829319 2F 83 FC 93 E9 E4 19 E2  93 7A 32 42 45 37 23 57
+D: binfmt_misc
+S: 72074 Tübingen
+S: Germany
+
+N: Justin Guyett
+E: jguyett@andrew.cmu.edu
+D: via-rhine net driver hacking
+
+N: Danny ter Haar
+E: dth@cistron.nl
+D: /proc/cpuinfo, reboot on panic , kernel pre-patch tester ;)
+S: Cistron
+S: PO-Box 297
+S: 2400 AG, Alphen aan den Rijn
+S: The Netherlands
+
+N: Enver Haase
+E: ehaase@inf.fu-berlin.de
+W: http://www.inf.fu-berlin.de/~ehaase
+D: Driver for the Commodore A2232 serial board
+
+N: Bruno Haible
+E: haible@ma2s2.mathematik.uni-karlsruhe.de
+D: SysV FS, shm swapping, memory management fixes
+S: 17 rue Danton
+S: F - 94270 Le Kremlin-Bicêtre
+S: France
+
+N: Greg Hankins
+E: gregh@cc.gatech.edu
+D: fixed keyboard driver to separate LED and locking status
+S: 25360 Georgia Tech Station
+S: Atlanta, Georgia 30332
+S: USA
+
+N: Brad Hards
+E: bradh@frogmouth.net
+D: Various USB bits, other minor patches
+
+N: Angelo Haritsis
+E: ah@computer.org
+D: kernel patches (serial, watchdog)
+D: xringd, vuzkern, greekXfonts
+S: 77 Clarence Mews
+S: London SE16 1GD
+S: United Kingdom
+
+N: Jan Harkes
+E: jaharkes@cs.cmu.edu
+W: http://www.coda.cs.cmu.edu/
+D: Coda file system
+S: Computer Science Department
+S: Carnegie Mellon University
+S: 5000 Forbes Avenue
+S: Pittsburgh, Pennsylvania 15213
+S: USA
+
+N: Kai Harrekilde-Petersen
+E: kai.harrekilde@get2net.dk
+D: Original author of the ftape-HOWTO, i82078 fdc detection code.
+
+N: Bart Hartgers
+E: bart@etpmod.phys.tue.nl
+D: MTRR emulation with Centaur MCRs
+S: Gen Stedmanstraat 212
+S: 5623 HZ Eindhoven
+S: The Netherlands
+
+N: Andrew Haylett
+E: ajh@primag.co.uk
+D: Selection mechanism
+
+N: Andre Hedrick
+E: andre@linux-ide.org
+E: andre@linuxdiskcert.org
+W: http://www.linux-ide.org/
+W: http://www.linuxdiskcert.org/
+D: Random SMP kernel hacker...
+D: Uniform Multi-Platform E-IDE driver
+D: Active-ATA-Chipset maddness..........
+D: Ultra DMA 133/100/66/33 w/48-bit Addressing
+D: ATA-Disconnect, ATA-TCQ
+D: ATA-Smart Kernel Daemon
+D: Serial ATA
+D: ATA Command Block and Taskfile
+S: Linux ATA Development (LAD)
+S: Concord, CA
+
+N: Jochen Hein
+E: jochen@jochen.org
+P: 1024/4A27F015 25 72 FB E3 85 9F DE 3B  CB 0A DA DA 40 77 05 6C
+P: 1024D/77D4FC9B F5C5 1C20 1DFC DEC3 3107  54A4 2332 ADFC 77D4 FC9B
+D: National Language Support
+D: Linux Internationalization Project
+D: German Localization for Linux and GNU software
+S: Kriemhildring 12a
+S: 65795 Hattersheim am Main
+S: Germany
+
+N: Christoph Hellwig
+E: hch@infradead.org
+D: all kinds of driver, filesystem & core kernel hacking
+D: freevxfs driver
+D: sysvfs maintainer
+D: chief codingstyle nitpicker
+S: Ampferstr. 50 / 4
+S: 6020 Innsbruck
+S: Austria
+
+N: Richard Henderson
+E: rth@twiddle.net
+E: rth@cygnus.com
+D: Alpha hacker, kernel and userland
+S: 1668 California St.
+S: Mountain View, California 94041
+S: USA
+
+N: Benjamin Herrenschmidt
+E: benh@kernel.crashing.org
+D: Various parts of PPC/PPC64 & PowerMac
+S: 312/107 Canberra Avenue
+S: Griffith, ACT 2603 
+S: Australia
+
+N: Sebastian Hetze
+E: she@lunetix.de
+D: German Linux Documentation,
+D: Organization of German Linux Conferences
+S: Danckelmannstr. 48
+S: 14059 Berlin
+S: Germany
+
+N: David Hinds
+E: dahinds@users.sourceforge.net
+W: http://tao.stanford.edu/~dhinds
+D: PCMCIA and CardBus stuff, PCMCIA-HOWTO, PCMCIA client drivers
+S: 2019 W. Middlefield Rd #1
+S: Mountain View, CA  94043
+S: USA
+
+N: Michael Hipp
+E: hippm@informatik.uni-tuebingen.de
+D: drivers for the racal ni5210 & ni6510 Ethernet-boards
+S: Talstr. 1
+S: D - 72072 Tuebingen
+S: Germany
+
+N: Richard Hirst
+E: richard@sleepie.demon.co.uk
+E: rhirst@linuxcare.com
+W: http://www.sleepie.demon.co.uk/
+D: linux-m68k VME support
+D: PA-RISC port, scsi and network drivers
+D: 53c700/53c710 driver author, 82596 driver maintainer
+S: United Kingdom
+
+N: Jauder Ho
+E: jauderho@carumba.com
+W: http://www.carumba.com/
+D: bug toaster (A1 sauce makes all the difference)
+D: Random linux hacker
+
+N: Tim Hockin
+E: thockin@hockin.org
+W: http://www.hockin.org/~thockin
+D: Natsemi ethernet
+D: Cobalt Networks (x86) support
+D: This-and-That
+
+N: Dirk Hohndel
+E: hohndel@suse.de
+D: The XFree86[tm] Project
+D: USB mouse maintainer
+S: SuSE Rhein/Main AG
+S: Mergenthalerallee 45-47
+S: 65760 Eschborn
+S: Germany
+
+N: Kenji Hollis
+E: kenji@bitgate.com
+W: http://www.bitgate.com/
+D: Berkshire PC Watchdog Driver
+D: Small/Industrial Driver Project
+
+N: Nick Holloway
+E: Nick.Holloway@pyrites.org.uk
+W: http://www.pyrites.org.uk/
+P: 1024/36115A04 F4E1 3384 FCFD C055 15D6  BA4C AB03 FBF8 3611 5A04
+D: Occasional Linux hacker...
+S: (ask for current address)
+S: United Kingdom
+
+N: Ron Holt
+E: ron@holt.org
+E: rholt@netcom.com
+W: http://www.holt.org/
+W: http://www.ronholt.com/
+D: Kernel development
+D: Kernel LDT modifications to support Wabi and Wine
+S: Holtron Internetics, Inc.
+S: 998 East 900 South, Suite 26
+S: Provo, Utah 84606-5607
+S: USA
+
+N: Marcel Holtmann
+E: marcel@holtmann.org
+W: http://www.holtmann.org
+D: Maintainer of the Linux Bluetooth Subsystem
+D: Author and maintainer of the various Bluetooth HCI drivers
+D: Author and maintainer of the CAPI message transport protocol driver
+D: Author and maintainer of the Bluetooth HID protocol driver
+D: Various other Bluetooth related patches, cleanups and fixes
+S: Germany
+
+N: Rob W. W. Hooft
+E: hooft@EMBL-Heidelberg.DE
+D: Shared libs for graphics-tools and for the f2c compiler
+D: Some kernel programming on the floppy and sound drivers in early days
+D: Some other hacks to get different kinds of programs to work for linux
+S: Panoramastrasse 18
+S: D-69126 Heidelberg
+S: Germany
+
+N: Christopher Horn
+E: chorn@warwick.net
+D: Miscellaneous sysctl hacks
+S: 36 Mudtown Road
+S: Wantage, New Jersey 07461
+S: USA
+
+N: Harald Hoyer
+E: harald.hoyer@parzelle.de
+W: http://parzelle.de/
+D: ip_masq_quake
+D: md boot support
+S: Hohe Strasse 30
+S: D-70176 Stuttgart
+S: Germany
+
+N: Jan Hubicka
+E: hubicka@freesoft.cz
+E: hubicka@suse.cz
+W: http://www.paru.cas.cz/~hubicka/
+D: Random kernel tweaks and fixes.
+S: Dukelskych bojovniku 1944
+S: Tabor 390 03
+S: Czech Republic
+
+N: David Huggins-Daines
+E: dhd@debian.org
+E: dhd@eradicator.org
+E: dhd@cepstral.com
+D: PA-RISC port
+D: Nubus subsystem
+D: Generic 68k Macintosh framebuffer driver
+D: STI framebuffer tweaks
+D: LTPC driver tweaks
+S: 110 S. 12th St., Apt. A
+S: Pittsburgh, PA 15203-1250
+S: USA
+
+N: Gareth Hughes
+E: gareth.hughes@acm.org
+D: Pentium III FXSR, SSE support
+D: Author/maintainer of most DRM drivers (especially ATI, MGA)
+D: Core DRM templates, general DRM and 3D-related hacking
+S: No fixed address
+
+N: Kenn Humborg
+E: kenn@wombat.ie
+D: Mods to loop device to support sparse backing files
+S: Ballinagard
+S: Roscommon
+S: Ireland
+
+N: Michael Hunold
+E: michael@mihu.de
+W: http://www.mihu.de/linux/
+D: Generic saa7146 video4linux-2 driver core,
+D: Driver for the "Multimedia eXtension Board", "dpc7146",
+D: "Hexium Orion", "Hexium Gemini"
+
+N: Miguel de Icaza Amozurrutia
+E: miguel@nuclecu.unam.mx
+D: Linux/SPARC team, Midnight Commander maintainer
+S: Avenida Copilco 162, 22-1003
+S: Mexico, DF
+S: Mexico
+
+N: Ian Jackson
+E: iwj10@cus.cam.ac.uk
+E: ijackson@nyx.cs.du.edu
+D: FAQ maintainer and poster of the daily postings
+D: FSSTND group member
+D: Debian core team member and maintainer of several Debian packages
+S: 2 Lexington Close
+S: Cambridge
+S: CB3 0DS
+S: United Kingdom
+
+N: Andreas Jaeger
+E: aj@suse.de
+D: Various smaller kernel fixes
+D: glibc developer
+S: Gottfried-Kinkel-Str. 18
+S: D 67659 Kaiserslautern
+S: Germany
+
+N: Mike Jagdis
+E: jaggy@purplet.demon.co.uk
+E: Mike.Jagdis@purplet.demon.co.uk
+D: iBCS personalities, socket and X interfaces, x.out loader, syscalls...
+D: Purple Distribution maintainer
+D: UK FidoNet support
+D: ISODE && PP
+D: Kernel and device driver hacking
+S: 280 Silverdale Road
+S: Earley
+S: Reading
+S: RG6 2NU
+S: United Kingdom
+
+N: Jakub Jelinek
+E: jakub@redhat.com
+W: http://sunsite.mff.cuni.cz/~jj
+P: 1024/0F7623C5 53 95 71 3C EB 73 99 97  02 49 40 47 F9 19 68 20
+D: Sparc hacker, SILO, mc
+D: Maintain sunsite.mff.cuni.cz
+S: K osmidomkum 723
+S: 160 00 Praha 6
+S: Czech Republic
+
+N: Niels Kristian Bech Jensen
+E: nkbj@image.dk
+W: http://www.image.dk/~nkbj
+D: Miscellaneous kernel updates and fixes.
+S: Dr. Holsts Vej 34, lejl. 164
+S: DK-8230 Åbyhøj
+S: Denmark
+
+N: Michael K. Johnson
+E: johnsonm@redhat.com
+W: http://www.redhat.com/~johnsonm
+P: 1024/4536A8DD 2A EC 88 08 40 64 CE D8  DD F8 12 2B 61 43 83 15
+D: The Linux Documentation Project
+D: Kernel Hackers' Guide
+D: Procps
+D: Proc filesystem
+D: Maintain tsx-11.mit.edu
+D: LP driver
+S: 201 Howell Street, Apartment 1C
+S: Chapel Hill, North Carolina 27514-4818
+S: USA
+
+N: Dave Jones
+E: davej@codemonkey.org.uk
+W: http://www.codemonkey.org.uk
+D: x86 errata/setup maintenance.
+D: AGPGART driver.
+D: CPUFREQ maintenance.
+D: Backport/Forwardport merge monkey.
+D: Various Janitor work.
+S: United Kingdom
+
+N: Martin Josfsson
+E: gandalf@wlug.westbo.se
+P: 1024D/F6B6D3B1 7610 7CED 5C34 4AA6 DBA2  8BE1 5A6D AF95 F6B6 D3B1
+D: netfilter: SAME target
+D: netfilter: helper target
+D: netfilter: various other hacks
+S: Ronneby
+S: Sweden
+
+N: Ani Joshi
+E: ajoshi@shell.unixbox.com
+D: fbdev hacking
+
+N: Jesper Juhl
+E: juhl-lkml@dif.dk
+D: Various small janitor fixes, cleanups etc.
+S: Lemnosvej 1, 3.tv
+S: 2300 Copenhagen S
+S: Denmark
+
+N: Jozsef Kadlecsik
+E: kadlec@blackhole.kfki.hu
+P: 1024D/470DB964 4CB3 1A05 713E 9BF7 FAC5  5809 DD8C B7B1 470D B964
+D: netfilter: TCP window tracking code
+D: netfilter: raw table
+D: netfilter: iprange match
+D: netfilter: new logging interfaces
+D: netfilter: various other hacks
+S: Tata
+S: Hungary
+
+N: Bernhard Kaindl
+E: bkaindl@netway.at
+E: edv@bartelt.via.at
+D: Author of a menu based configuration tool, kmenu, which 
+D: is the predecessor of 'make menuconfig' and 'make xconfig'.
+D: digiboard driver update(modularisation work and 2.1.x upd)
+S: Tallak 95
+S: 8103 Rein
+S: Austria
+
+N: Mitsuru Kanda
+E: mk@linux-ipv6.org
+E: mk@isl.rdc.toshiba.co.jp
+E: mk@karaba.org
+W: http://www.karaba.org/~mk/
+P: 1024D/2EC7E30D 4DC3 949B 5A6C F0D6 375F  4472 8888 A8E1 2EC7 E30D
+D: IPsec, IPv6
+D: USAGI/WIDE Project, TOSHIBA CORPORATION
+S: 2-47-8, Takinogawa,
+S: Kita, Tokyo 114-0023
+S: Japan
+
+N: Jan Kara
+E: jack@atrey.karlin.mff.cuni.cz
+E: jack@suse.cz
+D: Quota fixes for 2.2 kernel
+D: Quota fixes for 2.3 kernel
+D: Few other fixes in filesystem area (buffer cache, isofs, loopback)
+W: http://atrey.karlin.mff.cuni.cz/~jack/
+S: Krosenska' 543
+S: 181 00 Praha 8
+S: Czech Republic
+
+N: Jan "Yenya" Kasprzak
+E: kas@fi.muni.cz
+D: Author of the COSA/SRP sync serial board driver.
+D: Port of the syncppp.c from the 2.0 to the 2.1 kernel.
+P: 1024/D3498839 0D 99 A7 FB 20 66 05 D7  8B 35 FC DE 05 B1 8A 5E
+W: http://www.fi.muni.cz/~kas/
+S: c/o Faculty of Informatics, Masaryk University
+S: Botanicka' 68a
+S: 602 00 Brno
+S: Czech Republic
+
+N: Jakob Kemi
+E: jakob.kemi@telia.com
+D: V4L W9966 Webcam driver
+S: Forsbyvägen 33
+S: 74143 Knivsta
+S: Sweden
+
+N: Fred N. van Kempen
+E: waltje@linux.com
+D: NET-2
+D: Drivers
+D: Kernel cleanups
+S: Korte Heul 95
+S: 1403 ND  BUSSUM
+S: The Netherlands
+
+N: Karl Keyte
+E: karl@koft.com
+D: Disk usage statistics and modifications to line printer driver
+S: 26a Sheen Road
+S: Richmond
+S: Surrey
+S: TW9 1AE
+S: United Kingdom
+
+N: Marko Kiiskila
+E: marko@iprg.nokia.com
+D: Author of ATM Lan Emulation
+S: 660 Harvard Ave. #7
+S: Santa Clara, CA 95051
+S: USA
+
+N: Russell King
+E: rmk@arm.linux.org.uk
+D: Linux/arm integrator, maintainer & hacker
+D: Acornfb, Cyber2000fb author
+S: Burgh Heath, Tadworth, Surrey.
+S: England
+
+N: Olaf Kirch
+E: okir@monad.swb.de
+D: Author of the Linux Network Administrators' Guide
+S: Kattreinstr 38
+S: D-64295
+S: Germany
+
+N: Andi Kleen
+E: ak@muc.de
+D: network hacker, syncookies
+S: Schwalbenstr. 96
+S: 85551 Ottobrunn
+S: Germany
+
+N: Ian Kluft
+E: ikluft@thunder.sbay.org
+W: http://www.kluft.com/~ikluft/
+D: NET-1 beta testing & minor patches, original Smail binary packages for
+D: Slackware and Debian, vote-taker for 2nd comp.os.linux reorganization
+S: Post Office Box 611311
+S: San Jose, California 95161-1311
+S: USA
+
+N: Thorsten Knabe
+E: Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
+E: Thorsten Knabe <tek01@hrzpub.tu-darmstadt.de>
+W: http://www.student.informatik.tu-darmstadt.de/~tek
+W: http://www.tu-darmstadt.de/~tek01
+P: 1024/3BC8D885 8C 29 C5 0A C0 D1 D6 F4  20 D4 2D AB 29 F6 D0 60
+D: AD1816 sound driver
+S: Am Bergfried 10
+S: 63225 Langen
+S: Germany
+
+N: Alain L. Knaff
+E: Alain.Knaff@lll.lu
+D: floppy driver
+S: 19, rue Jean l'Aveugle
+S: L-1148 Luxembourg-City
+S: Luxembourg
+
+N: Gerd Knorr
+W: http://bytesex.org
+E: kraxel@bytesex.org
+E: kraxel@suse.de
+D: video4linux, bttv, vesafb, some scsi, misc fixes
+
+N: Harald Koenig
+E: koenig@tat.physik.uni-tuebingen.de
+D: XFree86 (S3), DCF77, some kernel hacks and fixes
+S: Koenigsberger Str. 90
+S: D-72336 Balingen
+S: Germany
+
+N: Rudolf Koenig
+E: rfkoenig@immd4.informatik.uni-erlangen.de
+D: The Linux Support Team Erlangen
+
+N: Andreas Koensgen
+E: ajk@iehk.rwth-aachen.de
+D: 6pack driver for AX.25
+
+N: Harald Koerfgen
+E: hkoerfg@web.de
+D: Linux/MIPS kernel hacks and fixes,
+D: DECstation port, Sharp Mobilon port
+S: D-50931 Koeln
+S: Germany
+
+N: Willy Konynenberg
+E: willy@xos.nl
+W: http://www.xos.nl/
+D: IP transparent proxy support
+S: X/OS Experts in Open Systems BV
+S: Kruislaan 419
+S: 1098 VA Amsterdam 
+S: The Netherlands
+
+N: Gene Kozin
+E: 74604.152@compuserve.com
+W: http://www.sangoma.com
+D: WAN Router & Sangoma WAN drivers
+S: Sangoma Technologies Inc.
+S: 7170 Warden Avenue, Unit 2
+S: Markham, Ontario
+S: L3R 8B2
+S: Canada
+
+N: Maxim Krasnyansky
+E: maxk@qualcomm.com
+W: http://vtun.sf.net
+W: http://bluez.sf.net
+D: Author of the Universal TUN/TAP driver
+D: Author of the Linux Bluetooth Subsystem (BlueZ)
+D: Various other kernel patches, cleanups and fixes
+S: 2213 La Terrace Circle
+S: San Jose, CA 95123
+S: USA
+
+N: Andreas S. Krebs
+E: akrebs@altavista.net
+D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards
+
+N: Greg Kroah-Hartman
+E: greg@kroah.com
+E: gregkh@suse.de
+W: http://www.kroah.com/linux/
+D: USB Serial Converter driver framework, USB Handspring Visor driver
+D: ConnectTech WHITEHeat USB driver, Generic USB Serial driver
+D: USB I/O Edgeport driver, USB Serial IrDA driver
+D: USB Bluetooth driver, USB Skeleton driver
+D: bits and pieces of USB core code.
+D: PCI Hotplug core, PCI Hotplug Compaq driver modifications
+D: portions of the Linux Security Module (LSM) framework
+D: parts of the driver core, debugfs.
+
+N: Russell Kroll
+E: rkroll@exploits.org
+W: http://www.exploits.org/
+D: V4L radio cards: radio-aztech (new), others (bugfixes/features)
+D: Loopback block device: dynamic sizing ("max_loop" as module)
+S: Post Office Box 691886
+S: San Antonio, Texas 78269-1886
+S: USA
+
+N: Denis O. Kropp
+E: dok@directfb.org
+D: NeoMagic framebuffer driver
+S: Badensche Str. 46
+S: 10715 Berlin
+S: Germany
+
+N: Andrzej M. Krzysztofowicz
+E: ankry@mif.pg.gda.pl
+D: Some 8-bit XT disk driver and devfs hacking 
+D: Aladdin 1533/1543(C) chipset IDE
+D: PIIX chipset IDE
+S: ul. Matemblewska 1B/10
+S: 80-283 Gdansk
+S: Poland
+
+N: Gero Kuhlmann
+E: gero@gkminix.han.de
+D: mounting root via NFS
+S: Donarweg 4
+S: D-30657 Hannover
+S: Germany
+
+N: Markus Kuhn
+E: mskuhn@cip.informatik.uni-erlangen.de
+W: http://wwwcip.informatik.uni-erlangen.de/user/mskuhn
+D: Unicode, real-time, time, standards
+S: Schlehenweg 9
+S: D-91080 Uttenreuth
+S: Germany
+
+N: Gabor Kuti
+M: seasons@falcon.sch.bme.hu
+M: seasons@makosteszta.sote.hu
+D: Original author of software suspend
+
+N: Jaroslav Kysela
+E: perex@suse.cz
+W: http://www.perex.cz
+D: Original Author and Maintainer for HP 10/100 Mbit Network Adapters
+D: ISA PnP
+S: Sindlovy Dvory 117
+S: 370 01  Ceske Budejovice
+S: Czech Republic
+
+N: Bas Laarhoven
+E: sjml@xs4all.nl
+D: Loadable modules and ftape driver
+S: J. Obrechtstr 23
+S: NL-5216 GP 's-Hertogenbosch
+S: The Netherlands
+
+N: Savio Lam
+E: lam836@cs.cuhk.hk
+D: Author of the dialog utility, foundation
+D: for Menuconfig's lxdialog.
+
+N: Christoph Lameter
+E: christoph@lameter.com
+D: Digiboard PC/Xe and PC/Xi, Digiboard EPCA
+D: Early protocol filter for bridging code
+D: Bug fixes
+
+N: Paul Laufer
+E: paul@laufernet.com
+D: Soundblaster driver fixes, ISAPnP quirk
+S: California, USA
+
+N: Tom Lees
+E: tom@lpsg.demon.co.uk
+W: http://www.lpsg.demon.co.uk/
+P: 1024/87D4D065 2A 66 86 9D 02 4D A6 1E  B8 A2 17 9D 4F 9B 89 D6
+D: Original author and current maintainer of
+D: PnP code.
+
+N: David van Leeuwen
+E: david@tm.tno.nl
+D: Philips/LMS cm206 cdrom driver, generic cdrom driver
+S: Scheltemalaan 14
+S: 3817 KS Amersfoort
+S: The Netherlands
+
+N: Volker Lendecke
+E: vl@kki.org
+D: Kernel smbfs (to mount WfW, NT and OS/2 network drives.)
+D: NCP filesystem support (to mount NetWare volumes)
+S: Von Ossietzky Str. 12
+S: 37085 Goettingen
+S: Germany
+
+N: Kevin Lentin
+E: kevinl@cs.monash.edu.au
+D: NCR53C400/T130B SCSI extension to NCR5380 driver.
+S: 18 Board Street
+S: Doncaster VIC 3108
+S: Australia
+
+N: Hans Lermen
+E: lermen@elserv.ffm.fgan.de
+D: Author of the LOADLIN Linux loader, hacking on boot stuff
+D: Coordinator of DOSEMU releases
+S: Am Muehlenweg 38
+S: D53424 Remagen
+S: Germany
+
+N: Colin Leroy
+E: colin@colino.net
+W: http://www.geekounet.org/
+D: PowerMac adt7467 fan driver
+S: Toulouse
+S: France
+
+N: Achim Leubner
+E: achim_leubner@adaptec.com
+D: GDT Disk Array Controller/Storage RAID controller driver
+S: ICP vortex GmbH
+S: Neckarsulm
+S: Germany
+
+N: Phil Lewis
+E: beans@bucket.ualr.edu
+D: Promised to send money if I would put his name in the source tree.
+S: Post Office Box 371
+S: North Little Rock, Arkansas 72115
+S: USA
+
+N: Stephan Linz
+E: linz@mazet.de
+E: Stephan.Linz@gmx.de
+W: http://www.crosswinds.net/~tuxer
+D: PCILynx patch to work with 1394a PHY and without local RAM
+S: (ask for current address)
+S: Germany
+
+N: Christophe Lizzi
+E: lizzi@cnam.fr
+W: http://cedric.cnam.fr/personne/lizzi
+D: FORE Systems 200E-series ATM network driver, sparc64 port of ATM
+S: CNAM, Laboratoire CEDRIC
+S: 292, rue St-Martin
+S: 75141 Paris Cedex 03
+S: France
+
+N: Siegfried "Frieder" Loeffler (dg1sek)
+E: floeff@tunix.mathematik.uni-stuttgart.de, fl@LF.net
+W: http://www.mathematik.uni-stuttgart.de/~floeff
+D: Busmaster driver for HP 10/100 Mbit Network Adapters
+S: University of Stuttgart, Germany and
+S: Ecole Nationale Superieure des Telecommunications, Paris
+
+N: Jamie Lokier
+E: jamie@imbolc.ucc.ie
+D: Reboot-through-BIOS for broken 486 motherboards
+D: Some parport fixes
+S: 11 Goodson Walk
+S: Marston
+S: Oxford
+S: OX3 0HX
+S: United Kingdom
+
+N: Mark Lord
+E: mlord@pobox.com
+D: EIDE driver, hd.c support
+D: EIDE PCI and bus-master DMA support
+D: Hard Disk Parameter (hdparm) utility
+S: 33 Ridgefield Cr
+S: Nepean, Ontario
+S: Canada K2H 6S3
+
+N: Warner Losh
+E: imp@village.org
+D: Linux/MIPS Deskstation support, Provided OI/OB for Linux
+S: 8786 Niwot Road
+S: Niwot, Colorado 80503
+S: USA
+
+N: Robert M. Love
+E: rml@tech9.net
+E: rml@novell.com
+D: misc. kernel hacking and debugging
+S: Cambridge, MA 02139
+S: USA
+
+N: Martin von Löwis
+E: loewis@informatik.hu-berlin.de
+D: script binary format
+D: NTFS driver
+
+N: H.J. Lu
+E: hjl@gnu.ai.mit.edu
+D: GCC + libraries hacker
+
+N: Michal Ludvig
+E: michal@logix.cz
+E: michal.ludvig@asterisk.co.nz
+W: http://www.logix.cz/michal
+P: 1024D/C45B2218 1162 6471 D391 76E0 9F99  29DA 0C3A 2509 C45B 2218
+D: VIA PadLock driver
+D: Netfilter pkttype module
+S: Asterisk Ltd.
+S: Auckland
+S: New Zealand
+
+N: Tuomas J. Lukka
+E: Tuomas.Lukka@Helsinki.FI
+D: Original dual-monitor patches
+D: Console-mouse-tracking patches
+S: Puistokaari 1 E 18
+S: 00200 Helsinki
+S: Finland
+
+N: Daniel J. Maas
+E: dmaas@dcine.com
+W: http://www.maasdigital.com
+D: dv1394
+
+N: Hamish Macdonald
+E: hamishm@lucent.com
+D: Linux/68k port
+S: 32 Clydesdale Avenue
+S: Kanata, Ontario
+S: Canada K2M-2G7
+
+N: Peter MacDonald
+D: SLS distribution
+D: Initial implementation of VC's, pty's and select()
+
+N: Pavel Machek
+E: pavel@ucw.cz
+E: pavel@suse.cz
+D: Softcursor for vga, hypertech cdrom support, vcsa bugfix, nbd
+D: sun4/330 port, capabilities for elf, speedup for rm on ext2, USB,
+D: work on suspend-to-ram/disk, killing duplicates from ioctl32
+S: Volkova 1131
+S: 198 00 Praha 9
+S: Czech Republic
+
+N: Paul Mackerras
+E: paulus@samba.org
+D: PPP driver
+D: Linux for PowerPC
+D: Linux port for PCI Power Macintosh
+
+N: Pat Mackinlay
+E: pat@it.com.au
+D: 8 bit XT hard disk driver
+D: Miscellaneous ST0x, TMC-8xx and other SCSI hacking
+S: 25 McMillan Street
+S: Victoria Park 6100
+S: Australia
+
+N: James B. MacLean
+E: macleajb@ednet.ns.ca
+W: http://www.ednet.ns.ca/~macleajb/dosemu.html
+D: Former Coordinator of DOSEMU releases
+D: Program in DOSEMU
+S: PO BOX 220, HFX. CENTRAL
+S: Halifax, Nova Scotia
+S: Canada B3J 3C8
+
+N: Kai Mäkisara
+E: Kai.Makisara@kolumbus.fi
+D: SCSI Tape Driver
+
+N: Asit Mallick
+E: asit.k.mallick@intel.com
+D: Linux/IA-64
+S: 2200 Mission College Blvd
+S: Santa Clara, CA 95052
+S: USA
+
+N: Petko Manolov
+E: petkan@users.sourceforge.net
+D: USB ethernet pegasus/pegasus-II driver
+D: USB ethernet rtl8150 driver
+D: optimizing i[45]86 string routines
+D: i386 task switching hacks
+S: 482 Shadowgraph Dr.
+S: San Jose, CA  95110
+S: USA
+
+N: Martin Mares
+E: mj@ucw.cz
+W: http://www.ucw.cz/~mj/
+D: BIOS video mode handling code
+D: MOXA C-218 serial board driver
+D: Network autoconfiguration
+D: PCI subsystem
+D: Random kernel hacking
+S: Kankovskeho 1241
+S: 182 00 Praha 8
+S: Czech Republic
+
+N: John A. Martin
+E: jam@acm.org
+W: http://www.tux.org/~jam/
+P: 1024/04456D53 9D A3 6C 6B 88 80 8A 61  D7 06 22 4F 95 40 CE D2
+P: 1024/3B986635 5A61 7EE6 9E20 51FB 59FB  2DA5 3E18 DD55 3B98 6635
+D: FSSTND contributor
+D: Credit file compilator
+
+N: Kevin E. Martin
+E: martin@cs.unc.edu
+D: Developed original accelerated X servers included in XFree86
+D: XF86_Mach64
+D: XF86_Mach32
+D: XF86_Mach8
+D: XF86_8514
+D: cfdisk (curses based disk partitioning program)
+
+N: John S. Marvin
+E: jsm@fc.hp.com
+D: PA-RISC port
+S: Hewlett Packard
+S: MS 42
+S: 3404 E. Harmony Road
+S: Fort Collins, CO 80528
+
+N: Torben Mathiasen
+E: torben.mathiasen@compaq.com
+E: torben@kernel.dk
+W: http://tlan.kernel.dk
+D: ThunderLAN maintainer
+D: ThunderLAN updates and other kernel fixes.
+S: Bremensgade 29, st.th
+S: 2300 Copenhagen S
+S: Denmark
+
+N: Claudio S. Matsuoka
+E: claudio@conectiva.com
+E: claudio@helllabs.org
+W: http://helllabs.org/~claudio
+D: V4L, OV511 driver hacks
+S: Conectiva S.A.
+S: R. Tocantins 89
+S: 80050-430  Curitiba PR
+S: Brazil
+
+N: Heinz Mauelshagen
+E: mge@EZ-Darmstadt.Telekom.de
+D: Logical Volume Manager
+S: Bartningstr. 12
+S: 64289 Darmstadt
+S: Germany 
+
+N: Mark W. McClelland
+E: mmcclell@bigfoot.com
+E: mark@alpha.dyndns.org
+W: http://alpha.dyndns.org/ov511/
+P: 1024D/357375CC 317C 58AC 1B39 2AB0 AB96  EB38 0B6F 731F 3573 75CC
+D: OV511 driver
+S: (address available on request)
+S: USA
+
+N: Patrick McHardy
+E: kaber@trash.net
+P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE  AB4C C9D4 964E 1215 5E80
+D: netfilter: endless number of bugfixes
+D: netfilter: CLASSIFY target
+D: netfilter: addrtype match
+D: tc: HFSC scheduler
+S: Freiburg
+S: Germany
+
+N: Mike McLagan
+E: mike.mclagan@linux.org
+W: http://www.invlogic.com/~mmclagan
+D: DLCI/FRAD drivers for Sangoma SDLAs
+S: Innovative Logic Corp
+S: Post Office Box 1068
+S: Laurel, Maryland 20732
+S: USA
+
+N: Bradley McLean
+E: brad@bradpc.gaylord.com
+D: Device driver hacker
+D: General kernel debugger
+S: 249 Nichols Avenue
+S: Syracuse, New York 13206
+S: USA
+
+N: Dirk Melchers
+E: dirk@merlin.nbg.sub.org
+D: 8 bit XT hard disk driver for OMTI5520
+S: Schloessleinsgasse 31
+S: D-90453 Nuernberg
+S: Germany
+
+N: Arnaldo Carvalho de Melo
+E: acme@conectiva.com.br
+E: acme@kernel.org
+E: acme@gnu.org
+W: http://bazar2.conectiva.com.br/~acme
+W: http://advogato.org/person/acme
+P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD  841A B6AB 4681 9224 DF01
+D: wanrouter hacking
+D: misc Makefile, Config.in, drivers and network stacks fixes
+D: IPX & LLC network stacks maintainer
+D: Cyclom 2X synchronous card driver
+D: wl3501 PCMCIA wireless card driver
+D: i18n for minicom, net-tools, util-linux, fetchmail, etc
+S: Conectiva S.A.
+S: R. Tocantins, 89 - Cristo Rei
+S: 80050-430 - Curitiba - Paraná
+S: Brazil
+
+N: Karsten Merker
+E: merker@linuxtag.org
+D: DECstation framebuffer drivers
+S: Germany
+
+N: Michael Meskes
+E: meskes@debian.org
+P: 1024/04B6E8F5 6C 77 33 CA CC D6 22 03  AB AB 15 A3 AE AD 39 7D
+D: Kernel hacker. PostgreSQL hacker. Software watchdog daemon.
+D: Maintainer of several Debian packages
+S: Th.-Heuss-Str. 61 
+S: D-41812 Erkelenz
+S: Germany
+
+N: Nigel Metheringham
+E: Nigel.Metheringham@ThePLAnet.net
+P: 1024/31455639 B7 99 BD B8 00 17 BD 46  C1 15 B8 AB 87 BC 25 FA
+D: IP Masquerading work and minor fixes
+S: Planet Online
+S: The White House, Melbourne Street, LEEDS
+S: LS2 7PS, United Kingdom
+
+N: Craig Metz
+E: cmetz@inner.net
+D: Some of PAS 16 mixer & PCM support, inet6-apps
+
+N: William (Bill) Metzenthen
+E: billm@suburbia.net
+D: Author of the FPU emulator.
+D: Minor kernel hacker for other lost causes (Hercules mono, etc).
+S: 22 Parker Street
+S: Ormond
+S: Victoria 3163
+S: Australia
+
+N: Pauline Middelink
+E: middelin@polyware.nl
+D: General low-level bug fixes, /proc fixes, identd support
+D: Author of IP masquerading
+D: Zoran ZR36120 Video For Linux driver
+S: Boterkorfhoek 34
+S: 7546 JA  Enschede
+S: Netherlands
+
+N: David S. Miller
+E: davem@davemloft.net
+D: Sparc and blue box hacker
+D: Vger Linux mailing list co-maintainer
+D: Linux Emacs elf/qmagic support + other libc/gcc things
+D: Yee bore de yee bore! ;-)
+S: 575 Harrison St. #103
+S: San Francisco, CA 94105
+S: USA
+
+N: Rick Miller
+E: rdmiller@execpc.com
+W: http://www.execpc.com/~rdmiller/
+D: Original Linux Device Registrar (Major/minor numbers)
+D: au-play, bwBASIC
+S: S78 W16203 Woods Road
+S: Muskego, Wisconsin 53150
+S: USA
+
+N: Harald Milz
+E: hm@seneca.linux.de
+D: Linux Projects Map, Linux Commercial-HOWTO
+D: general Linux publicity in Germany, vacation port
+D: UUCP and CNEWS binary packages for LST
+S: Editorial Board iX Mag
+S: Helstorfer Str. 7
+S: D-30625 Hannover
+S: Germany
+
+N: Corey Minyard
+E: minyard@wf-rch.cirr.com
+E: minyard@mvista.com
+W: http://home.attbi.com/~minyard
+D: Sony CDU31A CDROM Driver
+D: IPMI driver
+D: Various networking fixes long ago
+D: Original ppc_md work
+D: Shared zlib
+S: 7406 Wheat Field Rd
+S: Garland, Texas 75044
+S: USA
+
+N: Kazunori Miyazawa
+E: miyazawa@linux-ipv6.org
+E: Kazunori.Miyazawa@jp.yokogawa.com
+E: kazunori@miyazawa.org
+W: http://www.miyazawa.org/~kazunori/
+D: IPsec, IPv6
+D: USAGI/WIDE Project, Yokogawa Electric Corporation
+S: 2-20-4-203, Nakacho,
+S: Musashino, Tokyo 180-0006
+S: Japan
+
+N: Patrick Mochel
+E: mochel@osdl.org
+E: mochelp@infinity.powertie.org
+D: PCI Power Management, ACPI work
+S: 12725 SW Millikan Way, Suite 400
+S: Beaverton, Oregon 97005
+S: USA
+
+N: Eberhard Moenkeberg
+E: emoenke@gwdg.de
+D: CDROM driver "sbpcd" (Matsushita/Panasonic/Soundblaster)
+S: Ruhstrathoehe 2 b.
+S: D-37085 Goettingen
+S: Germany
+
+N: Thomas Molina
+E: tmolina@cablespeed.com
+D: bug fixes, documentation, minor hackery
+
+N: James Morris
+E: jmorris@intercode.com.au
+W: http://www.intercode.com.au/jmorris/
+D: Netfilter, Linux Security Modules (LSM).
+S: PO Box 707
+S: Spit Junction NSW 2088
+S: Australia
+
+N: David Mosberger-Tang
+E: davidm@hpl.hp.com if IA-64 related, else David.Mosberger@acm.org
+D: Linux/Alpha and Linux/ia64
+S: 35706 Runckel Lane
+S: Fremont, California 94536
+S: USA
+
+N: Sam Mosel
+E: sam.mosel@computer.org
+D: Wacom Intuos USB Support
+S: 22 Seaview St
+S: Fullarton 5063
+S: South Australia
+
+N. Wolfgang Muees
+E: wolfgang@iksw-muees.de
+D: Auerswald USB driver
+
+N: Ian A. Murdock
+E: imurdock@gnu.ai.mit.edu
+D: Creator of Debian distribution
+S: 30 White Tail Lane
+S: Lafayette, Indiana 47905
+S: USA
+
+N: Scott Murray
+E: scottm@somanetworks.com
+E: scott@spiteful.org
+D: OPL3-SA2, OPL3-SA3 sound driver
+D: CompactPCI hotplug core
+D: Ziatech ZT5550 and generic CompactPCI hotplug drivers
+S: Toronto, Ontario
+S: Canada
+
+N: Zwane Mwaikambo
+E: zwane@linuxpower.ca
+W: http://function.linuxpower.ca
+D: Various driver hacking
+D: Lowlevel x86 kernel hacking
+D: General debugging
+S: (ask for current address)
+S: Tanzania
+
+N: Trond Myklebust
+E: trond.myklebust@fys.uio.no
+D: current NFS client hacker.
+S: Dagaliveien 31e
+S: N-0391 Oslo
+S: Norway
+
+N: Johan Myreen
+E: jem@iki.fi
+D: PS/2 mouse driver writer etc.
+S: Dragonvagen 1 A 13
+S: FIN-00330 Helsingfors
+S: Finland
+
+N: Matija Nalis
+E: mnalis@jagor.srce.hr
+E: mnalis@voyager.hr
+D: Maintainer of the Umsdos file system
+S: Listopadska 7
+S: 10000 Zagreb
+S: Croatia
+
+N: Jonathan Naylor
+E: g4klx@g4klx.demon.co.uk
+E: g4klx@amsat.org
+W: http://zone.pspt.fi/~jsn/
+D: AX.25, NET/ROM and ROSE amateur radio protocol suites
+D: CCITT X.25 PLP and LAPB.
+S: 24 Castle View Drive
+S: Cromford
+S: Matlock
+S: Derbyshire DE4 3RL
+S: United Kingdom
+
+N: Ian S. Nelson
+E: ian.nelson@echostar.com
+D: Minor mmap and ide hacks
+S: 1370 Atlantis Ave.
+S: Lafayette CO, 80026
+S: USA
+
+N: Russell Nelson
+E: nelson@crynwr.com
+W: http://www.crynwr.com/~nelson
+P: 1024/83942741 FF 68 EE 27 A0 5A AA C3  F5 DC 05 62 BD 5B 20 2F
+D: Author of cs89x0, maintainer of kernel changelog through 1.3.3
+D: Wrote many packet drivers, from which some Ethernet drivers are derived.
+S: 521 Pleasant Valley Road
+S: Potsdam, New York 13676
+S: USA
+
+N: Dave Neuer
+E: dneuer@innovation-charter.com
+E: mr_fred_smoothie@yahoo.com
+D: Helped implement support for Compaq's H31xx series iPAQs
+D: Other mostly minor tweaks & bugfixes
+S: 325 E. Main St., Suite 3
+S: Carnegie, PA 15105
+S: USA
+
+N: Michael Neuffer
+E: mike@i-Connect.Net
+E: neuffer@goofy.zdv.uni-mainz.de
+W: http://www.i-Connect.Net/~mike/
+D: Developer and maintainer of the EATA-DMA SCSI driver
+D: Co-developer EATA-PIO SCSI driver
+D: /proc/scsi and assorted other snippets 
+S: Zum Schiersteiner Grund 2
+S: 55127 Mainz
+S: Germany
+
+N: Gustavo Niemeyer
+E: niemeyer@conectiva.com
+W: https://moin.conectiva.com.br/GustavoNiemeyer
+D: wl3501 PCMCIA wireless card initial support for wireless extensions in 2.4
+S: Conectiva S.A.
+S: R. Tocantins 89
+S: 80050-430  Curitiba PR
+S: Brazil
+
+N: David C. Niemi
+E: niemi@tux.org
+W: http://www.tux.org/~niemi/
+D: Assistant maintainer of Mtools, fdutils, and floppy driver
+D: Administrator of Tux.Org Linux Server, http://www.tux.org
+S: 2364 Old Trail Drive
+S: Reston, Virginia 20191
+S: USA
+
+N: Fredrik Noring
+E: noring@nocrew.org
+W: http://www.lysator.liu.se/~noring/
+D: dsp56k device driver
+
+N: Michael O'Reilly
+E: michael@iinet.com.au
+E: oreillym@tartarus.uwa.edu.au
+D: Wrote the original dynamic sized disk cache stuff. I think the only
+D: part that remains is the GFP_KERNEL et al #defines. :)
+S: 192 Nichsolson Road
+S: Subiaco, 6008
+S: Perth, Western Australia
+S: Australia
+
+N: Greg Page
+E: gpage@sovereign.org
+D: IPX development and support
+
+N: David Parsons
+E: orc@pell.chi.il.us
+D: improved memory detection code.
+
+N: Ivan Passos
+E: ivan@cyclades.com
+D: Author of the Cyclades-PC300 synchronous card driver
+D: Maintainer of the Cyclom-Y/Cyclades-Z asynchronous card driver
+S: Cyclades Corp
+S: 41934 Christy St
+S: Fremont, CA 94538
+S: USA
+
+N: Mikulas Patocka
+E: mikulas@artax.karlin.mff.cuni.cz
+W: http://artax.karlin.mff.cuni.cz/~mikulas/
+P: 1024/BB11D2D5 A0 F1 28 4A C4 14 1E CF  92 58 7A 8F 69 BC A4 D3
+D: Read/write HPFS filesystem
+S: Weissova 8
+S: 644 00 Brno
+S: Czech Republic
+
+N: Vojtech Pavlik
+E: vojtech@suse.cz
+D: Joystick driver
+D: arcnet-hardware readme
+D: Minor ARCnet hacking
+D: USB (HID, ACM, Printer ...)
+S: Ucitelska 1576
+S: Prague 8
+S: 182 00 Czech Republic
+
+N: Barak A. Pearlmutter
+E: bap@cs.unm.edu
+W: http://www.cs.unm.edu/~bap/
+P: 512/602D785D 9B A1 83 CD EE CB AD 93  20 C6 4C B7 F5 E9 60 D4
+D: Author of mark-and-sweep GC integrated by Alan Cox
+S: Computer Science Department
+S: FEC 313
+S: University of New Mexico
+S: Albuquerque, New Mexico 87131
+S: USA
+
+N: Avery Pennarun
+E: apenwarr@worldvisions.ca
+W: http://www.worldvisions.ca/~apenwarr/
+D: ARCnet driver
+D: "make xconfig" improvements
+D: Various minor hacking
+S: RR #5, 497 Pole Line Road
+S: Thunder Bay, Ontario
+S: CANADA P7C 5M9
+
+N: Yuri Per
+E: yuri@pts.mipt.ru
+D: Some smbfs fixes
+S: Demonstratsii 8-382
+S: Tula 300000
+S: Russia
+
+N: Gordon Peters
+E: GordPeters@smarttech.com
+D: Isochronous receive for IEEE 1394 driver (OHCI module).
+D: Bugfixes for the aforementioned.
+S: Calgary, Alberta
+S: Canada
+
+N: Johnnie Peters
+E: jpeters@phx.mcd.mot.com
+D: Motorola PowerPC changes for PReP
+S: 2900 S. Diable Way
+S: Tempe, Arizona 85282
+S: USA
+
+N: Kirk Petersen
+E: kirk@speakeasy.org
+W: http://www.speakeasy.org/~kirk/
+D: implemented kmod
+D: modularized BSD Unix domain sockets
+
+N: Martin Kasper Petersen
+E: mkp@mkp.net
+D: PA-RISC port
+D: XFS file system
+D: kiobuf based block I/O work
+S: 314 Frank St.
+S: Ottawa, Ontario
+S: Canada K2P 0X8
+
+N: Mikael Pettersson
+E: mikpe@csd.uu.se
+W: http://www.csd.uu.se/~mikpe/
+D: Miscellaneous fixes
+
+N: Reed H. Petty
+E: rhp@draper.net
+W: http://www.draper.net
+D: Loop device driver extensions
+D: Encryption transfer modules (no export)
+S: Post Office Box 1815
+S: Harrison, Arkansas  72602-1815
+S: USA
+
+N: Kai Petzke
+E: petzke@teltarif.de
+W: http://www.teltarif.de/
+P: 1024/B42868C1 D9 59 B9 98 BB 93 05 38  2E 3E 31 79 C3 65 5D E1
+D: Driver for Laser Magnetic Storage CD-ROM
+D: Some kernel bug fixes
+D: Port of the database Postgres
+D: Book: "Linux verstehen und anwenden" (Hanser-Verlag)
+S: Triftstra=DFe 55
+S: 13353 Berlin
+S: Germany
+
+N: Emanuel Pirker
+E: epirker@edu.uni-klu.ac.at
+D: AIC5800 IEEE 1394, RAW I/O on 1394
+D: Starter of Linux1394 effort
+S: ask per mail for current address
+
+N: Nicolas Pitre
+E: nico@cam.org
+D: StrongARM SA1100 support integrator & hacker
+D: Xscale PXA architecture
+D: unified SMC 91C9x/91C11x ethernet driver (smc91x)
+S: Montreal, Quebec, Canada
+
+N: Ken Pizzini
+E: ken@halcyon.com
+D: CDROM driver "sonycd535" (Sony CDU-535/531)
+
+N: Stelian Pop
+E: stelian@popies.net
+P: 1024D/EDBB6147 7B36 0E07 04BC 11DC A7A0  D3F7 7185 9E7A EDBB 6147
+D: sonypi, meye drivers, mct_u232 usb serial hacks
+S: Paris, France
+
+N: Pete Popov
+E: pete_popov@yahoo.com
+D: Linux/MIPS AMD/Alchemy Port and mips hacking and debugging
+S: San Jose, CA 95134
+S: USA
+
+N: Matt Porter
+E: mporter@kernel.crashing.org
+D: Motorola PowerPC PReP support
+D: cPCI PowerPC support
+D: Embedded PowerPC 4xx/6xx/7xx/74xx support
+S: Chandler, Arizona 85249
+S: USA
+
+N: Frederic Potter 
+E: fpotter@cirpack.com
+D: Some PCI kernel support
+
+N: Rui Prior
+E: rprior@inescn.pt
+D: ATM device driver for NICStAR based cards
+
+N: Stefan Probst
+E: sp@caldera.de
+D: The Linux Support Team Erlangen, 1993-97
+S: Caldera (Deutschland) GmbH
+S: Lazarettstrasse 8
+S: 91054 Erlangen
+S: Germany
+
+N: Giuliano Procida
+E: myxie@debian.org,gprocida@madge.com
+D: Madge Ambassador driver (Collage 155 Server ATM adapter)
+D: Madge Horizon driver (Collage 25 and 155 Client ATM adapters)
+P: 1024/93898735 D3 9E F4 F7 6D 8D 2F 3A  38 BA 06 7C 2B 33 43 7D
+S: Madge Networks
+S: Framewood Road
+S: Wexham SL3 6PJ
+S: United Kingdom
+
+N: Daniel Quinlan
+E: quinlan@pathname.com
+W: http://www.pathname.com/~quinlan/
+D: FSSTND coordinator; FHS editor
+D: random Linux documentation, patches, and hacks
+S: 4390 Albany Drive #41A
+S: San Jose, California 95129
+S: USA
+
+N: Juan Quintela
+E: quintela@fi.udc.es
+D: Memory Management hacking
+S: LFCIA
+S: Departamento de Computación
+S: Universidade da Coruña
+S: E-15071
+S: A Coruña
+S: Spain
+
+N: Augusto Cesar Radtke
+E: bishop@sekure.org
+W: http://bishop.sekure.org
+D: {copy,get,put}_user calls updates
+D: Miscellaneous hacks
+S: R. Otto Marquardt, 226 - Garcia
+S: 89020-350 Blumenau - Santa Catarina
+S: Brazil
+
+N: Goutham Rao
+E: goutham.rao@intel.com
+D: Linux/IA-64
+S: 2200 Mission College Blvd
+S: Santa Clara, CA 95052
+S: USA
+
+N: Eric S. Raymond
+E: esr@thyrsus.com
+W: http://www.tuxedo.org/~esr/
+D: terminfo master file maintainer
+D: Editor: Installation HOWTO, Distributions HOWTO, XFree86 HOWTO
+D: Author: fetchmail, Emacs VC mode, Emacs GUD mode
+S: 6 Karen Drive
+S: Malvern, Pennsylvania 19355
+S: USA
+
+N: Stefan Reinauer
+E: stepan@linux.de
+W: http://www.freiburg.linux.de/~stepan/
+D: Modularization of some filesystems
+D: /proc/sound, minor fixes
+S: Schlossbergring 9
+S: 79098 Freiburg
+S: Germany
+
+N: Joerg Reuter
+E: jreuter@yaina.de
+W: http://yaina.de/jreuter/
+W: http://www.qsl.net/dl1bke/
+D: Generic Z8530 driver, AX.25 DAMA slave implementation
+D: Several AX.25 hacks
+
+N: Francois-Rene Rideau
+E: fare@tunes.org
+W: http://www.tunes.org/~fare
+D: petty kernel janitor (byteorder, ufs)
+S: 6, rue Augustin Thierry
+S: 75019 Paris
+S: France
+
+N: Rik van Riel
+E: riel@redhat.com
+W: http://www.surriel.com/
+D: Linux-MM site, Documentation/sysctl/*, swap/mm readaround
+D: kswapd fixes, random kernel hacker, rmap VM,
+D: nl.linux.org administrator, minor scheduler additions
+S: Red Hat Boston
+S: 3 Lan Drive
+S: Westford, MA 01886
+S: USA
+
+N: Pekka Riikonen
+E: priikone@poseidon.pspt.fi
+E: priikone@ssh.com
+D: Random kernel hacking and bug fixes
+D: International kernel patch project
+S: Kasarmikatu 11 A4
+S: 70110 Kuopio
+S: Finland
+
+N: Luca Risolia
+E: luca.risolia@studio.unibo.it
+P: 1024D/FCE635A4 88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4
+D: V4L driver for W996[87]CF JPEG USB Dual Mode Camera Chips
+D: V4L2 driver for SN9C10x PC Camera Controllers
+S: Via Liberta' 41/A
+S: Osio Sotto, 24046, Bergamo
+S: Italy
+
+N: William E. Roadcap
+E: roadcapw@cfw.com
+W: http://www.cfw.com/~roadcapw
+D: Author of menu based configuration tool, Menuconfig.
+S: 1407 Broad Street
+S: Waynesboro, Virginia 22980
+S: USA
+
+N: Andrew J. Robinson
+E: arobinso@nyx.net
+W: http://www.nyx.net/~arobinso
+D: Hayes ESP serial port driver
+
+N: Florian La Roche
+E: rzsfl@rz.uni-sb.de
+E: flla@stud.uni-sb.de
+D: Net programs and kernel net hacker
+S: Gaildorfer Str. 27
+S: 7000 Stuttgart 50
+S: Germany
+
+N: Christoph Rohland
+E: hans-christoph.rohland@sap.com
+E: ch.rohland@gmx.net
+D: shm fs, SYSV semaphores, af_unix
+S: Neue Heimat Str. 8
+S: D-68789 St.Leon-Rot
+S: Germany
+
+N: Thiago Berlitz Rondon
+E: maluco@mileniumnet.com.br
+W: http://vivaldi.linuxms.com.br/~maluco
+D: Miscellaneous kernel hacker
+S: R. Anhanguera, 1487 - Ipiranga
+S: 79080-740 - Campo Grande - Mato Grosso do Sul
+S: Brazil
+
+N: Stephen Rothwell
+E: sfr@canb.auug.org.au
+W: http://www.canb.auug.org.au/~sfr
+P: 1024/BD8C7805 CD A4 9D 01 10 6E 7E 3B  91 88 FA D9 C8 40 AA 02
+D: Boot/setup/build work for setup > 2K
+D: Author, APM driver
+D: Directory notification
+S: 66 Maltby Circuit
+S: Wanniassa ACT 2903
+S: Australia
+
+N: Gerard Roudier
+E: groudier@free.fr
+D: Contributed to asynchronous read-ahead improvement
+S: 21 Rue Carnot
+S: 95170 Deuil La Barre
+S: France
+
+N: Sebastien Rougeaux
+E: Sebastien.Rougeaux@syseng.anu.edu.au
+D: IEEE 1394 OHCI module
+S: Research School of Information Science and Engineering
+S: The Australian National University, ACT 0200
+S: Australia
+
+N: Aristeu Sergio Rozanski Filho
+E: aris@cathedrallabs.org
+D: Support for EtherExpress 10 ISA (i82595) in eepro driver
+D: User level driver support for input
+S: R. Jose Serrato, 130 - Santa Candida
+S: 82640-320 - Curitiba - Paraná
+S: Brazil
+
+N: Alessandro Rubini
+E: rubini@ipvvis.unipv.it
+D: the gpm mouse server and kernel support for it
+
+N: Philipp Rumpf
+E: prumpf@tux.org
+D: random bugfixes
+S: Drausnickstrasse 29
+S: 91052 Erlangen
+S: Germany
+
+N: Paul `Rusty' Russell
+E: rusty@rustcorp.com.au
+W: http://ozlabs.org/~rusty
+D: Ruggedly handsome.
+D: netfilter, ipchains with Michael Neuling.
+S: 52 Moore St
+S: Turner ACT 2612
+S: Australia
+
+N: Richard Russon (FlatCap)
+E: kernel@flatcap.org
+W: http://www.flatcap.org
+D: NTFS support
+D: LDM support (Win2000/XP Logical Disk Manager/Dynamic Disks)
+S: 50 Swansea Road
+S: Reading
+S: United Kingdom
+
+N: Bill Ryder
+E: bryder@sgi.com
+D: FTDI_SIO usb/serial converter driver
+W: http://reality.sgi.com/bryder_wellington/ftdi_sio
+S: I/3 Walter St
+S: Wellington
+S: New Zealand
+
+N: Sampo Saaristo
+E: sambo@cs.tut.fi
+D: Co-author of Multi-Protocol Over ATM (MPOA)
+S: Tampere University of Technology / Telecom lab
+S: Hermiankatu 12C
+S: FIN-33720 Tampere
+S: Finland
+
+N: Thomas Sailer
+E: t.sailer@alumni.ethz.ch
+E: HB9JNX@HB9W.CHE.EU (packet radio)
+D: Baycom driver
+S: Markusstrasse 18
+S: 8006 Zuerich
+S: Switzerland
+
+N: Manuel Estrada Sainz
+D: Firmware loader (request_firmware)
+
+N: Wayne Salamon
+E: wsalamon@tislabs.com
+E: wsalamon@nai.com
+D: portions of the Linux Security Module (LSM) framework and security modules
+
+N: Robert Sanders
+E: gt8134b@prism.gatech.edu
+D: Dosemu
+
+N: Duncan Sands
+E: duncan.sands@free.fr
+W: http://topo.math.u-psud.fr/~sands
+D: Alcatel SpeedTouch USB driver
+S: 69 rue Dunois
+S: 75013 Paris
+S: France
+
+N: Hannu Savolainen
+E: hannu@opensound.com
+D: Maintainer of the sound drivers until 2.1.x days.
+D: Original compressed boot image support.
+S: Valurink. 4A11
+S: 03600 Karkkila
+S: Finland
+
+N: Deepak Saxena
+E: dsaxena@plexity.net
+D: I2O kernel layer (config, block, core, pci, net). I2O disk support for LILO
+D: XScale(IOP, IXP) porting and other random ARM bits
+S: Portland, OR
+
+N: Eric Schenk
+E: Eric.Schenk@dna.lth.se
+D: Random kernel debugging.
+D: SYSV Semaphore code rewrite.
+D: Network layer debugging.
+D: Dial on demand facility (diald).
+S: Dag Hammerskjolds v. 3E
+S: S-226 64 LUND
+S: Sweden
+
+N: Henning P. Schmiedehausen
+E: hps@tanstaafl.de
+D: added PCI support to the serial driver
+S: Buckenhof, Germany
+
+N: Michael Schmitz
+E:
+D: Macintosh IDE Driver
+
+N: Peter De Schrijver
+E: stud11@cc4.kuleuven.ac.be
+D: Mitsumi CD-ROM driver patches March version
+S: Molenbaan 29
+S: B2240 Zandhoven
+S: Belgium
+
+N: Martin Schulze
+E: joey@linux.de
+W: http://home.pages.de/~joey/
+D: Random Linux Hacker, Linux Promoter
+D: CD-List, Books-List, Ex-FAQ
+D: Linux-Support, -Mailbox, -Stammtisch
+D: several improvements to system programs
+S: Oldenburg
+S: Germany
+
+N: Robert Schwebel
+E: robert@schwebel.de
+W: http://www.schwebel.de
+D: Embedded hacker and book author,
+D: AMD Elan support for Linux
+S: Pengutronix
+S: Braunschweiger Strasse 79
+S: 31134 Hildesheim
+S: Germany
+
+N: Darren Senn
+E: sinster@darkwater.com
+D: Whatever I notice needs doing (so far: itimers, /proc)
+S: Post Office Box 64132
+S: Sunnyvale, California 94088-4132
+S: USA
+
+N: Simon Shapiro
+E: shimon@i-Connect.Net
+W: http://www.-i-Connect.Net/~shimon
+D: SCSI debugging
+D: Maintainer of the Debian Kernel packages
+S: 14355 SW Allen Blvd., Suite #140
+S: Beaverton, Oregon 97008
+S: USA
+
+N: Mike Shaver
+E: shaver@hungry.org
+W: http://www.hungry.org/~shaver/
+D: MIPS work, /proc/sys/net, misc net hacking
+S: 149 Union St.
+S: Kingston, Ontario
+S: Canada K7L 2P4
+
+N: John Shifflett
+E: john@geolog.com
+E: jshiffle@netcom.com
+D: Always IN2000 SCSI driver
+D: wd33c93 SCSI driver (linux-m68k)
+S: San Jose, California
+S: USA
+
+N: Robert Siemer
+E: Robert.Siemer@gmx.de
+P: 2048/C99A4289 2F DC 17 2E 56 62 01 C8  3D F2 AC 09 F2 E5 DD EE
+D: miroSOUND PCM20 radio RDS driver, ACI rewrite
+S: Klosterweg 28 / i309
+S: 76131 Karlsruhe
+S: Germany
+
+N: James Simmons 
+E: jsimmons@infradead.org
+E: jsimmons@users.sf.net 
+D: Frame buffer device maintainer
+D: input layer developement 
+D: tty/console layer
+D: various mipsel devices 
+S: 115 Carmel Avenue 
+S: El Cerrito CA 94530
+S: USA 
+
+N: Jaspreet Singh
+E: jaspreet@sangoma.com
+W: www.sangoma.com
+D: WANPIPE drivers & API Support for Sangoma S508/FT1 cards 
+S: Sangoma Technologies Inc.,
+S: 1001 Denison Street
+S: Suite 101
+S: Markham, Ontario L3R 2Z6
+S: Canada
+
+N: Rick Sladkey
+E: jrs@world.std.com
+D: utility hacker: Emacs, NFS server, mount, kmem-ps, UPS debugger, strace, GDB
+D: library hacker: RPC, profil(3), realpath(3), regexp.h
+D: kernel hacker: unnamed block devs, NFS client, fast select, precision timer
+S: 24 Avon Place
+S: Arlington, Massachusetts 02174
+S: USA
+
+N: Craig Small
+E: csmall@triode.apana.org.au
+E: vk2xlz@gonzo.vk2xlz.ampr.org (packet radio)
+D: Gracilis PackeTwin device driver
+D: RSPF daemon 
+S: 10 Stockalls Place
+S: Minto, NSW, 2566
+S: Australia
+
+N: Stephen Smalley
+E: sds@epoch.ncsc.mil
+D: portions of the Linux Security Module (LSM) framework and security modules
+
+N: Chris Smith
+E: csmith@convex.com
+D: Read only HPFS filesystem
+S: Richardson, Texas
+S: USA
+
+N: Christopher Smith
+E: x@xman.org
+D: Tulip net driver hacker
+
+N: Mark Smith
+E: mark.smith@comdev.cc
+D: Multicast support in bonding driver
+
+N: Miquel van Smoorenburg
+E: miquels@cistron.nl
+D: Kernel and net hacker. Sysvinit, minicom. doing Debian stuff.
+S: Cistron Internet Services
+S: PO-Box 297
+S: 2400 AG, Alphen aan den Rijn
+S: The Netherlands
+
+N: Scott Snyder
+E: snyder@fnald0.fnal.gov
+D: ATAPI cdrom driver
+S: MS 352, Fermilab
+S: Post Office Box 500
+S: Batavia, Illinois 60510
+S: USA
+
+N: Leo Spiekman
+E: leo@netlabs.net
+W: http://www.netlabs.net/hp/leo/
+D: Optics Storage 8000AT cdrom driver
+S: Cliffwood, New Jersey 07721
+S: USA
+
+N: Manfred Spraul
+E: manfred@colorfullife.com
+W: http://www.colorfullife.com/~manfred
+D: Lots of tiny hacks. Larger improvments to SysV IPC msg,
+D: slab, pipe, select.
+S: 71701 Schwieberdingen
+S: Germany
+
+N: Andrew Stanley-Jones
+E: asj@lanmedia.com
+D: LanMedia Corp. Device WAN card device driver
+S: #102, 686 W. Maude Ave
+S: Sunyvale, CA 94086
+S: USA
+
+N: Michael Still
+E: mikal@stillhq.com
+W: http://www.stillhq.com
+D: Various janitorial patches
+D: mandocs and mandocs_install build targets
+S: (Email me and ask)
+S: Australia
+
+N: Henrik Storner
+E: storner@image.dk
+W: http://www.image.dk/~storner/
+W: http://www.sslug.dk/
+D: Configure script: Invented tristate for module-configuration
+D: vfat/msdos integration, kerneld docs, Linux promotion
+D: Miscellaneous bug-fixes
+S: Chr. Winthersvej 1 B, st.th.
+S: DK-1860 Frederiksberg C
+S: Denmark
+
+N: Drew Sullivan
+E: drew@ss.org
+W: http://www.ss.org/
+P: 1024/ACFFA969 5A 9C 42 AB E4 24 82 31  99 56 00 BF D3 2B 25 46
+D: iBCS2 developer
+S: 22 Irvington Cres.
+S: Willowdale, Ontario
+S: Canada M2N 2Z1
+
+N: Adam Sulmicki
+E: adam@cfar.umd.edu
+W: http://www.eax.com
+D: core networking fixes
+D: patch-kernel enhancements
+D: misc kernel fixes and updates
+
+N: Adrian Sun
+E: asun@cobaltnet.com
+D: hfs support
+D: alpha rtc port, random appletalk fixes
+S: Department of Zoology, University of Washington
+S: Seattle, WA  98195-1800
+S: USA
+
+N: Eugene Surovegin
+E: ebs@ebshome.net
+W: http://kernel.ebshome.net/
+P: 1024D/AE5467F1 FF22 39F1 6728 89F6 6E6C  2365 7602 F33D AE54 67F1
+D: Embedded PowerPC 4xx: I2C, PIC and random hacks/fixes
+S: Sunnyvale, California 94085
+S: USA
+
+N: Corey Thomas
+E: corey@world.std.com
+W: http://world.std.com/~corey/index.html
+D: Raylink/WebGear wireless LAN device driver (ray_cs) author
+S: 145 Howard St.
+S: Northborough, MA 01532
+S: USA
+
+N: Tommy Thorn
+E: Tommy.Thorn@irisa.fr
+W: http://www.irisa.fr/prive/thorn/index.html
+P: 512/B4AFC909 BC BF 6D B1 52 26 1E D6  E3 2F A3 24 2A 84 FE 21
+D: Device driver hacker (aha1542 & plip)
+S: IRISA
+S: Universit=E9 de Rennes I
+S: F-35042 Rennes Cedex
+S: France
+
+N: Jon Tombs
+E: jon@gte.esi.us.es
+W: http://www.esi.us.es/~jon
+D: NFS mmap()
+D: XF86_S3
+D: Kernel modules
+D: Parts of various other programs (xfig, open, ...)
+S: C/ Federico Garcia Lorca 1 10-A
+S: Sevilla 41005
+S: Spain
+
+N: Linus Torvalds
+E: torvalds@osdl.org
+D: Original kernel hacker
+S: 12725 SW Millikan Way, Suite 400
+S: Beaverton, Oregon 97005
+S: USA
+
+N: Marcelo W. Tosatti
+E: marcelo.tosatti@cyclades.com
+D: Miscellaneous kernel hacker
+D: v2.4 kernel maintainer
+D: Current pc300/cyclades maintainer
+S: Cyclades Corporation
+S: Av Cristovao Colombo, 462. Floresta.
+S: Porto Alegre
+S: Brazil
+
+N: Stefan Traby
+E: stefan@quant-x.com
+D: Minor Alpha kernel hacks
+S: Mitterlasznitzstr. 13
+S: 8302 Nestelbach
+S: Austria
+
+N: Jeff Tranter
+E: tranter@pobox.com
+D: Enhancements to Joystick driver
+D: Author of Sound HOWTO and CD-ROM HOWTO
+D: Author of several small utilities
+D: (bogomips, scope, eject, statserial)
+S: 1 Laurie Court
+S: Kanata, Ontario
+S: Canada K2L 1S2
+
+N: Andrew Tridgell
+E: tridge@samba.org
+W: http://samba.org/tridge/
+D: dosemu, networking, samba
+S: 3 Ballow Crescent
+S: MacGregor A.C.T 2615
+S: Australia
+
+N: Winfried Trümper
+E: winni@xpilot.org
+W: http://www.shop.de/~winni/
+D: German HOWTO, Crash-Kurs Linux (German, 100 comprehensive pages)
+D: CD-Writing HOWTO, various mini-HOWTOs
+D: One-week tutorials on Linux twice a year (free of charge)
+D: Linux-Workshop Köln (aka LUG Cologne, Germany), Installfests
+S: Tacitusstr. 6
+S: D-50968 Köln
+
+N: Tsu-Sheng Tsao
+E: tsusheng@scf.usc.edu
+D: IGMP(Internet Group Management Protocol) version 2
+S: 2F 14 ALY 31 LN 166 SEC 1 SHIH-PEI RD
+S: Taipei 
+S: Taiwan 112
+S: Republic of China
+S: 24335 Delta Drive
+S: Diamond Bar, California 91765
+S: USA
+
+N: Theodore Ts'o
+E: tytso@mit.edu
+D: Random Linux hacker
+D: Maintainer of tsx-11.mit.edu ftp archive
+D: Maintainer of c.o.l.* Usenet<->mail gateway
+D: Author of serial driver
+D: Author of the new e2fsck
+D: Author of job control and system call restart code
+D: Author of ramdisk device driver
+D: Author of loopback device driver
+S: MIT Room E40-343
+S: 1 Amherst Street
+S: Cambridge, Massachusetts 02139
+S: USA
+
+N: Simmule Turner
+E: sturner@tele-tv.com
+D: Added swapping to filesystem
+S: 4226 Landgreen Street
+S: Rockville, Maryland 20853
+S: USA
+
+N: Stephen Tweedie
+E: sct@redhat.com
+P: 1024/E7A417AD E2 FE A4 20 34 EC ED FC 7D 7E 67 8D E0 31 D1 69
+P: 1024D/43BE7544 D2A4 8556 08E6 90E7 076C  BA3F 243F 20A4 43BE 7544
+D: Second extended file system developer
+D: General filesystem hacker
+D: kswap vm management code
+S: 44 Campbell Park Crescent
+S: Edinburgh EH13 0HT
+S: United Kingdom
+
+N: Thomas Uhl
+E: uhl@sun1.rz.fh-heilbronn.de
+D: Application programmer
+D: Linux promoter
+D: Author of a German book on Linux
+S: Obere Heerbergstrasse 17
+S: 97078 Wuerzburg
+S: Germany
+
+N: Greg Ungerer
+E: gerg@snapgear.com
+D: uClinux kernel hacker
+D: Port uClinux to the Motorola ColdFire CPU
+D: Author of Stallion multiport serial drivers
+S: SnapGear Inc.
+S: 825 Stanley St
+S: Woolloongabba. QLD. 4102
+S: Australia
+
+N: Jeffrey A. Uphoff
+E: juphoff@transmeta.com
+E: jeff.uphoff@linux.org
+P: 1024/9ED505C5 D7 BB CA AA 10 45 40 1B  16 19 0A C0 38 A0 3E CB
+D: Linux Security/Alert mailing lists' moderator/maintainer.
+D: NSM (rpc.statd) developer.
+D: PAM S/Key module developer.
+D: 'dip' contributor.
+D: AIPS port, astronomical community support.
+S: Transmeta Corporation
+S: 2540 Mission College Blvd.
+S: Santa Clara, CA 95054
+S: USA
+
+N: Matthias Urlichs
+E: smurf@smurf.noris.de
+E: smurf@debian.org
+E: matthias@urlichs.de
+D: Consultant, developer, kernel hacker
+D: In a previous life, worked on Streams/ISDN/BSD networking code for Linux
+S: Schleiermacherstrasse 12
+S: 90491 Nuernberg
+S: Germany
+
+N: Geert Uytterhoeven
+E: geert@linux-m68k.org
+W: http://home.tvd.be/cr26864/
+P: 1024/862678A6 C51D 361C 0BD1 4C90 B275  C553 6EEA 11BA 8626 78A6
+D: m68k/Amiga and PPC/CHRP Longtrail coordinator
+D: Frame buffer device and XF68_FBDev maintainer
+D: m68k IDE maintainer
+D: Amiga Zorro maintainer
+D: Amiga Buddha and Catweasel chipset IDE
+D: Atari Falcon chipset IDE
+D: Amiga Gayle chipset IDE
+D: mipsel NEC DDB Vrc-5074
+S: Emiel Vlieberghlaan 2A/21
+S: B-3010 Kessel-Lo
+S: Belgium
+
+N: Chris Vance
+E: cvance@tislabs.com
+E: cvance@nai.com
+D: portions of the Linux Security Module (LSM) framework and security modules
+
+N: Petr Vandrovec
+E: vandrove@vc.cvut.cz
+D: Small contributions to ncpfs
+D: Matrox framebuffer driver
+S: Chudenicka 8
+S: 10200 Prague 10, Hostivar
+S: Czech Republic
+
+N: Heikki Vatiainen
+E: hessu@cs.tut.fi
+D: Co-author of Multi-Protocol Over ATM (MPOA), some LANE hacks
+S: Tampere University of Technology / Telecom lab
+S: Hermiankatu 12C
+S: FIN-33720 Tampere
+S: Finland
+
+N: Andrew Veliath
+E: andrewtv@usa.net
+D: Turtle Beach MultiSound sound driver
+S: USA
+
+N: Dirk Verworner
+D: Co-author of German book ``Linux-Kernel-Programmierung''
+D: Co-founder of Berlin Linux User Group
+
+N: Patrick Volkerding
+E: volkerdi@ftp.cdrom.com
+D: Produced the Slackware distribution, updated the SVGAlib
+D: patches for ghostscript, worked on color 'ls', etc.
+S: 301 15th Street S.
+S: Moorhead, Minnesota 56560
+S: USA 
+
+N: Jos Vos
+E: jos@xos.nl
+W: http://www.xos.nl/
+D: Various IP firewall updates, ipfwadm
+S: X/OS Experts in Open Systems BV
+S: Kruislaan 419
+S: 1098 VA Amsterdam 
+S: The Netherlands
+
+N: Jeroen Vreeken
+E: pe1rxq@amsat.org
+W: http://www.chello.nl/~j.vreeken/
+D: SE401 usb webcam driver
+D: ZD1201 usb wireless lan driver
+S: Maastrichterweg 63
+S: 5554 GG Valkenswaard
+S: The Netherlands
+
+N: Peter Shaobo Wang
+E: pwang@mmdcorp.com
+W: http://www.mmdcorp.com/pw/linux
+D: Driver for Interphase ATM (i)Chip SAR adapter card family (x575, x525, x531).
+S: 1513 Brewster Dr.
+S: Carrollton, TX 75010
+S: USA
+
+N: Tim Waugh
+E: tim@cyberelk.net
+D: Co-architect of the parallel-port sharing system
+S: 17 Curling Vale
+S: GUILDFORD
+S: Surrey
+S: GU2 7PJ
+S: United Kingdom
+
+N: Juergen Weigert
+E: jnweiger@immd4.informatik.uni-erlangen.de
+D: The Linux Support Team Erlangen
+
+N: David Weinehall
+E: tao@acc.umu.se
+W: http://www.acc.umu.se/~tao/
+W: http://www.acc.umu.se/~mcalinux/
+D: Fixes for the NE/2-driver
+D: Miscellaneous MCA-support
+D: Cleanup of the Config-files
+S: Axtorpsvagen 40:20
+S: S-903 37  UMEA
+S: Sweden
+
+N: Matt Welsh
+E: mdw@metalab.unc.edu
+W: http://www.cs.berkeley.edu/~mdw
+D: Original Linux Documentation Project coordinator
+D: Author, "Running Linux" (O'Reilly)
+D: Author, "Linux Installation and Getting Started" (LDP) and several HOWTOs
+D: Linuxdoc-SGML formatting system (now SGML-Tools)
+D: Device drivers for various high-speed network interfaces (Myrinet, ATM)
+D: Keithley DAS1200 device driver
+D: Original maintainer of sunsite WWW and FTP sites
+D: Original moderator of c.o.l.announce and c.o.l.answers
+S: Computer Science Division
+S: UC Berkeley
+S: Berkeley, CA 94720-1776
+S: USA
+
+N: Harald Welte
+E: laforge@netfilter.org
+P: 1024D/30F48BFF DBDE 6912 8831 9A53 879B  9190 5DA5 C655 30F4 8BFF
+W: http://gnumonks.org/users/laforge
+D: netfilter: new nat helper infrastructure
+D: netfilter: ULOG, ECN, DSCP target
+D: netfilter: TTL match
+D: netfilter: IPv6 mangle table
+D: netfilter: various other hacks
+S: Berlin
+S: Germany
+
+N: Bill Wendling
+E: wendling@ganymede.isdn.uiuc.edu
+W: http://www.ncsa.uiuc.edu/~wendling/
+D: Various random hacks. Mostly on poll/select logic.
+S: 605 E. Springfield Ave.
+S: Champaign, IL 61820
+S: USA
+
+N: Mike Westall
+D: IBM Turboways 25 ATM Device Driver
+E: westall@cs.clemson.edu
+S: Department of Computer Science
+S: Clemson University
+S: Clemson SC 29634 USA
+
+N: Greg Wettstein
+E: greg@wind.rmcc.com
+D: Filesystem valid flag for MINIX filesystem.
+D: Minor kernel debugging.
+D: Development and maintenance of sysklogd.
+D: Monitoring of development kernels for long-term stability.
+D: Early implementations of Linux in a commercial environment.
+S: Dr. Greg Wettstein, Ph.D.
+S: Oncology Research Division Computing Facility
+S: Roger Maris Cancer Center
+S: 820 4th St. N.
+S: Fargo, North Dakota 58122
+S: USA
+
+N: Steven Whitehouse
+E: SteveW@ACM.org
+W: http://www.chygwyn.com/~steve
+D: Linux DECnet project: http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html
+D: Minor debugging of other networking protocols.
+D: Misc bug fixes and filesystem development
+
+N: Hans-Joachim Widmaier
+E: hjw@zvw.de
+D: AFFS rewrite
+S: Eichenweg 16
+S: 73650 Winterbach
+S: Germany
+
+N: Urban Widmark
+E: urban@svenskatest.se
+D: via-rhine, misc net driver hacking
+
+N: Marco van Wieringen
+E: mvw@planets.elm.net
+D: Author of process accounting and diskquota
+S: Breeburgsingel 12
+S: 2135 CN Hoofddorp
+S: The Netherlands
+
+N: Matthew Wilcox
+E: matthew@wil.cx
+W: ftp://ftp.uk.linux.org/pub/linux/people/willy/
+D: Linux/PARISC hacker.  Filesystem hacker.  Random other hacking.  Custom
+D: PPC port hacking.
+
+N: G\"unter Windau
+E: gunter@mbfys.kun.nl
+D: Some bug fixes in the polling printer driver (lp.c)
+S: University of Nijmegen
+S: Geert-Grooteplein Noord 21
+S: 6525 EZ Nijmegen
+S: The Netherlands
+
+N: Ulrich Windl
+E: Ulrich.Windl@rz.uni-regensburg.de
+P: 1024/E843660D CF D7 43 A1 5A 49 14 25  7C 04 A0 6E 4C 3A AC 6D
+D: Supports NTP on Linux.  Added PPS code.  Fixed bugs in adjtimex().
+S: Alte Regensburger Str. 11a
+S: 93149 Nittenau
+S: Germany
+
+N: Lars Wirzenius
+E: liw@iki.fi
+D: Linux System Administrator's Guide, author, former maintainer
+D: comp.os.linux.announce, former moderator
+D: Linux Documentation Project, co-founder
+D: Original sprintf in kernel
+D: Original kernel README (for version 0.97)
+D: Linux News (electronic magazine, now dead), founder and former editor
+D: Meta-FAQ, originator, former maintainer
+D: INFO-SHEET, former maintainer
+D: Author of the longest-living linux bug
+
+N: Jonathan Woithe
+E: jwoithe@physics.adelaide.edu.au
+W: http://www.physics.adelaide.edu.au/~jwoithe
+D: ALS-007 sound card extensions to Sound Blaster driver
+S: 20 Jordan St
+S: Valley View, SA 5093
+S: Australia
+
+N: Clifford Wolf
+E: god@clifford.at
+W: http://www.clifford.at/
+D: Menuconfig/lxdialog improvement
+S: Foehrengasse 16
+S: A-2333 Leopoldsdorf b. Wien
+S: Austria
+
+N: Roger E. Wolff
+E: R.E.Wolff@BitWizard.nl
+D: Written kmalloc/kfree
+D: Written Specialix IO8+ driver
+D: Written Specialix SX driver
+S: van Bronckhorststraat 12
+S: 2612 XV Delft
+S: The Netherlands
+
+N: David Woodhouse
+E: dwmw2@infradead.org
+D: ARCnet stuff, Applicom board driver, SO_BINDTODEVICE,
+D: some Alpha platform porting from 2.0, Memory Technology Devices,
+D: Acquire watchdog timer, PC speaker driver maintenance,
+D: various other stuff that annoyed me by not working.
+S: c/o Red Hat Engineering
+S: Rustat House
+S: 60 Clifton Road
+S: Cambridge. CB1 7EG
+S: England
+
+N: Chris Wright
+E: chrisw@osdl.org
+D: hacking on LSM framework and security modules.
+S: c/o OSDL
+S: 12725 SW Millikan Way, Suite 400
+S: Beaverton, OR 97005
+S: USA
+
+N: Michal Wronski
+E: wrona@mat.uni.torun.pl
+W: http://www.mat.uni.torun.pl/~wrona
+D: POSIX message queues fs (with K. Benedyczak)
+S: ul. Teczowa 23/12
+S: 80-680 Gdansk-Sobieszewo
+S: Poland
+
+N: Frank Xia
+E: qx@math.columbia.edu
+D: Xiafs filesystem [defunct]
+S: 542 West 112th Street, 5N
+S: New York, New York 10025
+S: USA
+
+N: Victor Yodaiken
+E: yodaiken@fsmlabs.com
+D: RTLinux (RealTime Linux)
+S: POB 1822 
+S: Socorro NM, 87801
+S: USA
+
+N: Hiroshi YOKOTA
+E: yokota@netlab.is.tsukuba.ac.jp
+D: Workbit NinjaSCSI-3/32Bi PCMCIA driver
+D: Workbit NinjaSCSI-32Bi/UDE driver
+S: Japan
+
+N: Hideaki YOSHIFUJI
+E: hideaki@yoshifuji.org
+E: yoshfuji@linux-ipv6.org
+W: http://www.yoshifuji.org/~hideaki/
+P: 1024D/E0620EEA 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA
+D: IPv6 and other networking related stuff
+D: USAGI/WIDE Project, Keio University
+S: Jeunet Palace Kawasaki #1-201, 10-2, Furukawa-cho, Saiwai-ku
+S: Kawasaki, Kanagawa 212-0025
+S: Japan
+
+N: Eric Youngdale
+E: eric@andante.org
+W: http://www.andante.org
+D: General kernel hacker
+D: SCSI iso9660 and ELF
+S: 6389 Hawk View Lane
+S: Alexandria, Virginia 22312
+S: USA
+
+N: Niibe Yutaka
+E: gniibe@mri.co.jp
+D: PLIP driver
+D: Asynchronous socket I/O in the NET code
+S: Mitsubishi Research Institute, Inc.
+S: ARCO Tower 1-8-1 Shimomeguro Meguro-ku
+S: Tokyo 153
+S: Japan
+
+N: James R. Van Zandt
+E: jrv@vanzandt.mv.com
+P: 1024/E298966D F0 37 4F FD E5 7E C5 E6  F1 A0 1E 22 6F 46 DA 0C
+D: Author and maintainer of the Double Talk speech synthesizer driver
+S: 27 Spencer Drive
+S: Nashua, New Hampshire 03062
+S: USA
+
+N: Orest Zborowski
+E: orestz@eskimo.com
+D: XFree86 and kernel development
+S: 1507 145th Place SE #B5
+S: Bellevue, Washington 98007
+S: USA
+
+N: Richard Zidlicky
+E: rz@linux-m68k.org, rdzidlic@geocities.com
+W: http://www.geocities.com/rdzidlic
+D: Q40 port - see arch/m68k/q40/README
+D: various m68k hacks
+S: Germany
+
+N: Werner Zimmermann
+E: Werner.Zimmermann@fht-esslingen.de
+D: CDROM driver "aztcd" (Aztech/Okano/Orchid/Wearnes)
+S: Flandernstrasse 101
+S: D-73732 Esslingen
+S: Germany
+
+N: Leonard N. Zubkoff
+W: http://www.dandelion.com/Linux/
+D: BusLogic SCSI driver
+D: Mylex DAC960 PCI RAID driver
+D: Miscellaneous kernel fixes
+
+N: Alessandro Zummo
+E: azummo@ita.flashnet.it
+W: http://freepage.logicom.it/azummo/
+D: CMI8330 support is sb_card.c
+D: ISAPnP fixes in sb_card.c
+S: Italy
+
+N: Marc Zyngier
+E: maz@wild-wind.fr.eu.org
+W: http://www.misterjones.org
+D: MD driver
+D: EISA/sysfs subsystem
+S: France
+
+
+# Don't add your name here, unless you really _are_ after Marc
+# alphabetically. Leonard used to be very proud of being the 
+# last entry, and he'll get positively pissed if he can't even
+# be second-to-last.  (and this file really _is_ supposed to be
+# in alphabetic order)

+ 294 - 0
Documentation/00-INDEX

@@ -0,0 +1,294 @@
+
+This is a brief list of all the files in ./linux/Documentation and what
+they contain. If you add a documentation file, please list it here in
+alphabetical order as well, or risk being hunted down like a rabid dog.
+Please try and keep the descriptions small enough to fit on one line.
+							 Thanks -- Paul G.
+
+Following translations are available on the WWW:
+
+   - Japanese, maintained by the JF Project (JF@linux.or.jp), at
+     http://www.linux.or.jp/JF/
+
+00-INDEX
+	- this file.
+BK-usage/
+	- directory with info on BitKeeper.
+BUG-HUNTING
+	- brute force method of doing binary search of patches to find bug.
+Changes
+	- list of changes that break older software packages.
+CodingStyle
+	- how the boss likes the C code in the kernel to look.
+DMA-API.txt
+	- DMA API, pci_ API & extensions for non-consistent memory machines.
+DMA-mapping.txt
+	- info for PCI drivers using DMA portably across all platforms.
+DocBook/
+	- directory with DocBook templates etc. for kernel documentation.
+IO-mapping.txt
+	- how to access I/O mapped memory from within device drivers.
+IPMI.txt
+	- info on Linux Intelligent Platform Management Interface (IPMI) Driver.
+IRQ-affinity.txt
+	- how to select which CPU(s) handle which interrupt events on SMP.
+ManagementStyle
+	- how to (attempt to) manage kernel hackers.
+MSI-HOWTO.txt
+	- the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
+RCU/
+	- directory with info on RCU (read-copy update).
+README.DAC960
+	- info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux.
+SAK.txt
+	- info on Secure Attention Keys.
+SubmittingDrivers
+	- procedure to get a new driver source included into the kernel tree.
+SubmittingPatches
+	- procedure to get a source patch included into the kernel tree.
+VGA-softcursor.txt
+	- how to change your VGA cursor from a blinking underscore.
+arm/
+	- directory with info about Linux on the ARM architecture.
+basic_profiling.txt
+	- basic instructions for those who wants to profile Linux kernel.
+binfmt_misc.txt
+	- info on the kernel support for extra binary formats.
+block/
+	- info on the Block I/O (BIO) layer.
+cachetlb.txt
+	- describes the cache/TLB flushing interfaces Linux uses.
+cciss.txt
+	- info, major/minor #'s for Compaq's SMART Array Controllers.
+cdrom/
+	- directory with information on the CD-ROM drivers that Linux has.
+cli-sti-removal.txt
+	- cli()/sti() removal guide.
+computone.txt
+	- info on Computone Intelliport II/Plus Multiport Serial Driver.
+cpqarray.txt
+	- info on using Compaq's SMART2 Intelligent Disk Array Controllers.
+cpu-freq/
+	- info on CPU frequency and voltage scaling.
+cris/
+	- directory with info about Linux on CRIS architecture.
+crypto/
+	- directory with info on the Crypto API.
+debugging-modules.txt
+	- some notes on debugging modules after Linux 2.6.3.
+device-mapper/
+	- directory with info on Device Mapper.
+devices.txt
+	- plain ASCII listing of all the nodes in /dev/ with major minor #'s.
+digiepca.txt
+	- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
+dnotify.txt
+	- info about directory notification in Linux.
+driver-model/
+	- directory with info about Linux driver model.
+dvb/
+	- info on Linux Digital Video Broadcast (DVB) subsystem.
+early-userspace/
+	- info about initramfs, klibc, and userspace early during boot.
+eisa.txt
+	- info on EISA bus support.
+exception.txt
+	- how Linux v2.2 handles exceptions without verify_area etc.
+fb/
+	- directory with info on the frame buffer graphics abstraction layer.
+filesystems/
+	- directory with info on the various filesystems that Linux supports.
+firmware_class/
+	- request_firmware() hotplug interface info.
+floppy.txt
+	- notes and driver options for the floppy disk driver.
+ftape.txt
+	- notes about the floppy tape device driver.
+hayes-esp.txt
+	- info on using the Hayes ESP serial driver.
+highuid.txt
+	- notes on the change from 16 bit to 32 bit user/group IDs.
+hpet.txt
+	- High Precision Event Timer Driver for Linux.
+hw_random.txt
+	- info on Linux support for random number generator in i8xx chipsets.
+i2c/
+	- directory with info about the I2C bus/protocol (2 wire, kHz speed).
+i2o/
+	- directory with info about the Linux I2O subsystem.
+i386/
+	- directory with info about Linux on Intel 32 bit architecture.
+ia64/
+	- directory with info about Linux on Intel 64 bit architecture.
+ide.txt
+	- important info for users of ATA devices (IDE/EIDE disks and CD-ROMS).
+initrd.txt
+	- how to use the RAM disk as an initial/temporary root filesystem.
+input/
+	- info on Linux input device support.
+io_ordering.txt
+	- info on ordering I/O writes to memory-mapped addresses.
+ioctl-number.txt
+	- how to implement and register device/driver ioctl calls.
+iostats.txt
+	- info on I/O statistics Linux kernel provides.
+isapnp.txt
+	- info on Linux ISA Plug & Play support.
+isdn/
+	- directory with info on the Linux ISDN support, and supported cards.
+java.txt
+	- info on the in-kernel binary support for Java(tm).
+kbuild/
+	- directory with info about the kernel build process.
+kernel-doc-nano-HOWTO.txt
+	- mini HowTo on generation and location of kernel documentation files.
+kernel-docs.txt
+	- listing of various WWW + books that document kernel internals.
+kernel-parameters.txt
+	- summary listing of command line / boot prompt args for the kernel.
+kobject.txt
+	- info of the kobject infrastructure of the Linux kernel.
+laptop-mode.txt
+	- How to conserve battery power using laptop-mode.
+ldm.txt
+	- a brief description of LDM (Windows Dynamic Disks).
+locks.txt
+	- info on file locking implementations, flock() vs. fcntl(), etc.
+logo.gif
+	- Full colour GIF image of Linux logo (penguin).
+logo.txt
+	- Info on creator of above logo & site to get additional images from.
+m68k/
+	- directory with info about Linux on Motorola 68k architecture.
+magic-number.txt
+	- list of magic numbers used to mark/protect kernel data structures.
+mandatory.txt
+	- info on the Linux implementation of Sys V mandatory file locking.
+mca.txt
+	- info on supporting Micro Channel Architecture (e.g. PS/2) systems.
+md.txt
+	- info on boot arguments for the multiple devices driver.
+memory.txt
+	- info on typical Linux memory problems.
+mips/
+	- directory with info about Linux on MIPS architecture.
+mono.txt
+	- how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
+moxa-smartio
+	- info on installing/using Moxa multiport serial driver.
+mtrr.txt
+	- how to use PPro Memory Type Range Registers to increase performance.
+nbd.txt
+	- info on a TCP implementation of a network block device.
+networking/
+	- directory with info on various aspects of networking with Linux.
+nfsroot.txt
+	- short guide on setting up a diskless box with NFS root filesystem.
+nmi_watchdog.txt
+	- info on NMI watchdog for SMP systems.
+numastat.txt
+	- info on how to read Numa policy hit/miss statistics in sysfs.
+oops-tracing.txt
+	- how to decode those nasty internal kernel error dump messages.
+paride.txt
+	- information about the parallel port IDE subsystem.
+parisc/
+	- directory with info on using Linux on PA-RISC architecture.
+parport.txt
+	- how to use the parallel-port driver.
+parport-lowlevel.txt
+	- description and usage of the low level parallel port functions.
+pci.txt
+	- info on the PCI subsystem for device driver authors.
+pm.txt
+	- info on Linux power management support.
+pnp.txt
+	- Linux Plug and Play documentation.
+power/
+	- directory with info on Linux PCI power management.
+powerpc/
+	- directory with info on using Linux with the PowerPC.
+preempt-locking.txt
+	- info on locking under a preemptive kernel.
+ramdisk.txt
+	- short guide on how to set up and use the RAM disk.
+riscom8.txt
+	- notes on using the RISCom/8 multi-port serial driver.
+rocket.txt
+	- info on the Comtrol RocketPort multiport serial driver.
+rpc-cache.txt
+	- introduction to the caching mechanisms in the sunrpc layer.
+rtc.txt
+	- notes on how to use the Real Time Clock (aka CMOS clock) driver.
+s390/
+	- directory with info on using Linux on the IBM S390.
+sched-coding.txt
+	- reference for various scheduler-related methods in the O(1) scheduler.
+sched-design.txt
+	- goals, design and implementation of the Linux O(1) scheduler.
+sched-domains.txt
+	- information on scheduling domains.
+sched-stats.txt
+	- information on schedstats (Linux Scheduler Statistics).
+scsi/
+	- directory with info on Linux scsi support.
+serial/
+	- directory with info on the low level serial API.
+serial-console.txt
+	- how to set up Linux with a serial line console as the default.
+sgi-visws.txt
+	- short blurb on the SGI Visual Workstations.
+sh/
+	- directory with info on porting Linux to a new architecture.
+smart-config.txt
+	- description of the Smart Config makefile feature.
+smp.txt
+	- a few notes on symmetric multi-processing.
+sonypi.txt
+	- info on Linux Sony Programmable I/O Device support.
+sound/
+	- directory with info on sound card support.
+sparc/
+	- directory with info on using Linux on Sparc architecture.
+specialix.txt
+	- info on hardware/driver for specialix IO8+ multiport serial card.
+spinlocks.txt
+	- info on using spinlocks to provide exclusive access in kernel.
+stallion.txt
+	- info on using the Stallion multiport serial driver.
+svga.txt
+	- short guide on selecting video modes at boot via VGA BIOS.
+sx.txt
+	- info on the Specialix SX/SI multiport serial driver.
+sysctl/
+	- directory with info on the /proc/sys/* files.
+sysrq.txt
+	- info on the magic SysRq key.
+telephony/
+	- directory with info on telephony (e.g. voice over IP) support.
+time_interpolators.txt
+	- info on time interpolators.
+tipar.txt
+	- information about Parallel link cable for Texas Instruments handhelds.
+tty.txt
+	- guide to the locking policies of the tty layer.
+unicode.txt
+	- info on the Unicode character/font mapping used in Linux.
+uml/
+	- directory with infomation about User Mode Linux.
+usb/
+	- directory with info regarding the Universal Serial Bus.
+video4linux/
+	- directory with info regarding video/TV/radio cards and linux.
+vm/
+	- directory with info on the Linux vm code.
+voyager.txt
+	- guide to running Linux on the Voyager architecture.
+watchdog/
+	- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
+x86_64/
+	- directory with info on Linux support for AMD x86-64 (Hammer) machines.
+xterm-linux.xpm
+	- XPM image of penguin logo (see logo.txt) sitting on an xterm.
+zorro.txt
+	- info on writing drivers for Zorro bus devices found on Amigas.

+ 51 - 0
Documentation/BK-usage/00-INDEX

@@ -0,0 +1,51 @@
+bk-kernel-howto.txt: Description of kernel workflow under BitKeeper
+
+bk-make-sum: Create summary of changesets in one repository and not
+another, typically in preparation to be sent to an upstream maintainer.
+Typical usage:
+	cd my-updated-repo
+	bk-make-sum ~/repo/original-repo
+	mv /tmp/linus.txt ../original-repo.txt
+
+bksend: Create readable text output containing summary of changes, GNU
+patch of the changes, and BK metadata of changes (as needed for proper
+importing into BitKeeper by an upstream maintainer).  This output is
+suitable for emailing BitKeeper changes.  The recipient of this output
+may pipe it directly to 'bk receive'.
+
+bz64wrap: helper script. Uncompressed input is piped to this script,
+which compresses its input, and then outputs the uu-/base64-encoded
+version of the compressed input.
+
+cpcset: Copy changeset between unrelated repositories.
+Attempts to preserve changeset user, user address, description, in
+addition to the changeset (the patch) itself.
+Typical usage:
+	cd my-updated-repo
+	bk changes	# looking for a changeset...
+	cpcset 1.1511 . ../another-repo
+
+csets-to-patches: Produces a delta of two BK repositories, in the form
+of individual files, each containing a single cset as a GNU patch.
+Output is several files, each with the filename "/tmp/rev-$REV.patch"
+Typical usage:
+	cd my-updated-repo
+	bk changes -L ~/repo/original-repo 2>&1 | \
+		perl csets-to-patches
+
+cset-to-linus: Produces a delta of two BK repositories, in the form of
+changeset descriptions, with 'diffstat' output created for each
+individual changset.
+Typical usage:
+	cd my-updated-repo
+	bk changes -L ~/repo/original-repo 2>&1 | \
+		perl cset-to-linus > summary.txt
+
+gcapatch:  Generates patch containing changes in local repository.
+Typical usage:
+	cd my-updated-repo
+	gcapatch > foo.patch
+
+unbz64wrap: Reverse an encoded, compressed data stream created by
+bz64wrap into an uncompressed, typically text/plain output.
+

+ 283 - 0
Documentation/BK-usage/bk-kernel-howto.txt

@@ -0,0 +1,283 @@
+
+		   Doing the BK Thing, Penguin-Style
+
+
+
+
+This set of notes is intended mainly for kernel developers, occasional
+or full-time, but sysadmins and power users may find parts of it useful
+as well.  It assumes at least a basic familiarity with CVS, both at a
+user level (use on the cmd line) and at a higher level (client-server model).
+Due to the author's background, an operation may be described in terms
+of CVS, or in terms of how that operation differs from CVS.
+
+This is -not- intended to be BitKeeper documentation.  Always run
+"bk help <command>" or in X "bk helptool <command>" for reference
+documentation.
+
+
+BitKeeper Concepts
+------------------
+
+In the true nature of the Internet itself, BitKeeper is a distributed
+system.  When applied to revision control, this means doing away with
+client-server, and changing to a parent-child model... essentially
+peer-to-peer.  On the developer's end, this also represents a
+fundamental disruption in the standard workflow of changes, commits,
+and merges.  You will need to take a few minutes to think about
+how to best work under BitKeeper, and re-optimize things a bit.
+In some sense it is a bit radical, because it might described as
+tossing changes out into a maelstrom and having them magically
+land at the right destination... but I'm getting ahead of myself.
+
+Let's start with this progression:
+Each BitKeeper source tree on disk is a repository unto itself.
+Each repository has a parent (except the root/original, of course).
+Each repository contains a set of a changesets ("csets").
+Each cset is one or more changed files, bundled together.
+
+Each tree is a repository, so all changes are checked into the local
+tree.  When a change is checked in, all modified files are grouped
+into a logical unit, the changeset.  Internally, BK links these
+changesets in a tree, representing various converging and diverging
+lines of development.  These changesets are the bread and butter of
+the BK system.
+
+After the concept of changesets, the next thing you need to get used
+to is having multiple copies of source trees lying around.  This -really-
+takes some getting used to, for some people.  Separate source trees
+are the means in BitKeeper by which you delineate parallel lines
+of development, both minor and major.  What would be branches in
+CVS become separate source trees, or "clones" in BitKeeper [heh,
+or Star Wars] terminology.
+
+Clones and changesets are the tools from which most of the power of
+BitKeeper is derived.  As mentioned earlier, each clone has a parent,
+the tree used as the source when the new clone was created.  In a
+CVS-like setup, the parent would be a remote server on the Internet,
+and the child is your local clone of that tree.
+
+Once you have established a common baseline between two source trees --
+a common parent -- then you can merge changesets between those two
+trees with ease.  Merging changes into a tree is called a "pull", and
+is analagous to 'cvs update'.  A pull downloads all the changesets in
+the remote tree you do not have, and merges them.  Sending changes in
+one tree to another tree is called a "push".  Push sends all changes
+in the local tree the remote does not yet have, and merges them.
+
+From these concepts come some initial command examples:
+
+1) bk clone -q http://linux.bkbits.net/linux-2.5 linus-2.5
+Download a 2.5 stock kernel tree, naming it "linus-2.5" in the local dir.
+The "-q" disables listing every single file as it is downloaded.
+
+2) bk clone -ql linus-2.5 alpha-2.5
+Create a separate source tree for the Alpha AXP architecture.
+The "-l" uses hard links instead of copying data, since both trees are
+on the local disk.  You can also replace the above with "bk lclone -q ..."
+
+You only clone a tree -once-.  After cloning the tree lives a long time
+on disk, being updating by pushes and pulls.
+
+3) cd alpha-2.5 ; bk pull http://gkernel.bkbits.net/alpha-2.5
+Download changes in "alpha-2.5" repository which are not present
+in the local repository, and merge them into the source tree.
+
+4) bk -r co -q
+Because every tree is a repository, files must be checked out before
+they will be in their standard places in the source tree.
+
+5)	bk vi fs/inode.c				# example change...
+	bk citool					# checkin, using X tool
+	bk push bk://gkernel@bkbits.net/alpha-2.5	# upload change
+Typical example of a BK sequence that would replace the analagous CVS
+situation,
+	vi fs/inode.c
+	cvs commit
+
+As this is just supposed to be a quick BK intro, for more in-depth
+tutorials, live working demos, and docs, see http://www.bitkeeper.com/
+
+
+
+BK and Kernel Development Workflow
+----------------------------------
+Currently the latest 2.5 tree is available via "bk clone $URL"
+and "bk pull $URL" at http://linux.bkbits.net/linux-2.5
+This should change in a few weeks to a kernel.org URL.
+
+
+A big part of using BitKeeper is organizing the various trees you have
+on your local disk, and organizing the flow of changes among those
+trees, and remote trees.  If one were to graph the relationships between
+a desired BK setup, you are likely to see a few-many-few graph, like
+this:
+
+		    linux-2.5
+		        |
+	       merge-to-linus-2.5
+		 /    |      |
+	        /     |      |
+	vm-hacks  bugfixes  filesys   personal-hacks
+	      \	      |	     |		/
+	       \      |      |         /
+		\     |      |        /
+	         testing-and-validation
+
+Since a "bk push" sends all changes not in the target tree, and
+since a "bk pull" receives all changes not in the source tree, you want
+to make sure you are only pushing specific changes to the desired tree,
+not all changes from "peer parent" trees.  For example, pushing a change
+from the testing-and-validation tree would probably be a bad idea,
+because it will push all changes from vm-hacks, bugfixes, filesys, and
+personal-hacks trees into the target tree.
+
+One would typically work on only one "theme" at a time, either
+vm-hacks or bugfixes or filesys, keeping those changes isolated in
+their own tree during development, and only merge the isolated with
+other changes when going upstream (to Linus or other maintainers) or
+downstream (to your "union" trees, like testing-and-validation above).
+
+It should be noted that some of this separation is not just recommended
+practice, it's actually [for now] -enforced- by BitKeeper.  BitKeeper
+requires that changesets maintain a certain order, which is the reason
+that "bk push" sends all local changesets the remote doesn't have.  This
+separation may look like a lot of wasted disk space at first, but it
+helps when two unrelated changes may "pollute" the same area of code, or
+don't follow the same pace of development, or any other of the standard
+reasons why one creates a development branch.
+
+Small development branches (clones) will appear and disappear:
+
+	-------- A --------- B --------- C --------- D -------
+	          \                                 /
+		   -----short-term devel branch-----
+
+While long-term branches will parallel a tree (or trees), with period
+merge points.  In this first example, we pull from a tree (pulls,
+"\") periodically, such as what occurs when tracking changes in a
+vendor tree, never pushing changes back up the line:
+
+	-------- A --------- B --------- C --------- D -------
+	          \                       \           \
+	           ----long-term devel branch-----------------
+
+And then a more common case in Linux kernel development, a long term
+branch with periodic merges back into the tree (pushes, "/"):
+
+	-------- A --------- B --------- C --------- D -------
+	          \                       \         / \
+	           ----long-term devel branch-----------------
+
+
+
+
+
+Submitting Changes to Linus
+---------------------------
+There's a bit of an art, or style, of submitting changes to Linus.
+Since Linus's tree is now (you might say) fully integrated into the
+distributed BitKeeper system, there are several prerequisites to
+properly submitting a BitKeeper change.  All these prereq's are just
+general cleanliness of BK usage, so as people become experts at BK, feel
+free to optimize this process further (assuming Linus agrees, of
+course).
+
+
+
+0) Make sure your tree was originally cloned from the linux-2.5 tree
+created by Linus.  If your tree does not have this as its ancestor, it
+is impossible to reliably exchange changesets.
+
+
+
+1) Pay attention to your commit text.  The commit message that
+accompanies each changeset you submit will live on forever in history,
+and is used by Linus to accurately summarize the changes in each
+pre-patch.  Remember that there is no context, so
+	"fix for new scheduler changes"
+would be too vague, but
+	"fix mips64 arch for new scheduler switch_to(), TIF_xxx semantics"
+would be much better.
+
+You can and should use the command "bk comment -C<rev>" to update the
+commit text, and improve it after the fact.  This is very useful for
+development: poor, quick descriptions during development, which get
+cleaned up using "bk comment" before issuing the "bk push" to submit the
+changes.
+
+
+
+2) Include an Internet-available URL for Linus to pull from, such as
+
+	Pull from:  http://gkernel.bkbits.net/net-drivers-2.5
+
+
+
+3) Include a summary and "diffstat -p1" of each changeset that will be
+downloaded, when Linus issues a "bk pull".  The author auto-generates
+these summaries using "bk changes -L <parent>", to obtain a listing
+of all the pending-to-send changesets, and their commit messages.
+
+It is important to show Linus what he will be downloading when he issues
+a "bk pull", to reduce the time required to sift the changes once they
+are downloaded to Linus's local machine.
+
+IMPORTANT NOTE:  One of the features of BK is that your repository does
+not have to be up to date, in order for Linus to receive your changes.
+It is considered a courtesy to keep your repository fairly recent, to
+lessen any potential merge work Linus may need to do.
+
+
+4) Split up your changes.  Each maintainer<->Linus situation is likely
+to be slightly different here, so take this just as general advice.  The
+author splits up changes according to "themes" when merging with Linus.
+Simultaneous pushes from local development go to special trees which
+exist solely to house changes "queued" for Linus.  Example of the trees:
+
+	net-drivers-2.5 -- on-going net driver maintenance
+	vm-2.5 -- VM-related changes
+	fs-2.5 -- filesystem-related changes
+
+Linus then has much more freedom for pulling changes.  He could (for
+example) issue a "bk pull" on vm-2.5 and fs-2.5 trees, to merge their
+changes, but hold off net-drivers-2.5 because of a change that needs
+more discussion.
+
+Other maintainers may find that a single linus-pull-from tree is
+adequate for passing BK changesets to him.
+
+
+
+Frequently Answered Questions
+-----------------------------
+1) How do I change the e-mail address shown in the changelog?
+A. When you run "bk citool" or "bk commit", set environment
+   variables BK_USER and BK_HOST to the desired username
+   and host/domain name.
+
+
+2) How do I use tags / get a diff between two kernel versions?
+A. Pass the tags Linus uses to 'bk export'.
+
+ChangeSets are in a forward-progressing order, so it's pretty easy
+to get a snapshot starting and ending at any two points in time.
+Linus puts tags on each release and pre-release, so you could use
+these two examples:
+
+    bk export -tpatch -hdu -rv2.5.4,v2.5.5 | less
+        # creates patch-2.5.5 essentially
+    bk export -tpatch -du -rv2.5.5-pre1,v2.5.5 | less
+        # changes from pre1 to final
+
+A tag is just an alias for a specific changeset... and since changesets
+are ordered, a tag is thus a marker for a specific point in time (or
+specific state of the tree).
+
+
+3) Is there an easy way to generate One Big Patch versus mainline,
+   for my long-lived kernel branch?
+A. Yes.  This requires BK 3.x, though.
+
+	bk export -tpatch -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+
+

+ 34 - 0
Documentation/BK-usage/bk-make-sum

@@ -0,0 +1,34 @@
+#!/bin/sh -e
+# DIR=$HOME/BK/axp-2.5
+# cd $DIR
+
+LINUS_REPO=$1
+DIRBASE=`basename $PWD`
+
+{
+cat <<EOT
+Please do a
+
+	bk pull bk://gkernel.bkbits.net/$DIRBASE
+
+This will update the following files:
+
+EOT
+
+bk export -tpatch -hdu -r`bk repogca $LINUS_REPO`,+ | diffstat -p1 2>/dev/null
+
+cat <<EOT
+
+through these ChangeSets:
+
+EOT
+
+bk changes -L -d'$unless(:MERGE:){ChangeSet|:CSETREV:\n}' $LINUS_REPO |
+bk -R prs -h -d'$unless(:MERGE:){<:P:@:HOST:> (:D: :I:)\n$each(:C:){   (:C:)\n}\n}' -
+
+} > /tmp/linus.txt
+
+cat <<EOT
+Mail text in /tmp/linus.txt; please check and send using your favourite
+mailer.
+EOT

+ 36 - 0
Documentation/BK-usage/bksend

@@ -0,0 +1,36 @@
+#!/bin/sh
+# A script to format BK changeset output in a manner that is easy to read.
+# Andreas Dilger <adilger@turbolabs.com>  13/02/2002
+#
+# Add diffstat output after Changelog <adilger@turbolabs.com>   21/02/2002
+
+PROG=bksend
+
+usage() {
+	echo "usage: $PROG -r<rev>"
+	echo -e "\twhere <rev> is of the form '1.23', '1.23..', '1.23..1.27',"
+	echo -e "\tor '+' to indicate the most recent revision"
+
+	exit 1
+}
+
+case $1 in
+-r) REV=$2; shift ;;
+-r*) REV=`echo $1 | sed 's/^-r//'` ;;
+*) echo "$PROG: no revision given, you probably don't want that";;
+esac
+
+[ -z "$REV" ] && usage
+
+echo "You can import this changeset into BK by piping this whole message to:"
+echo "'| bk receive [path to repository]' or apply the patch as usual."
+
+SEP="\n===================================================================\n\n"
+echo -e $SEP
+env PAGER=/bin/cat bk changes -r$REV
+echo
+bk export -tpatch -du -h -r$REV | diffstat
+echo; echo
+bk export -tpatch -du -h -r$REV
+echo -e $SEP
+bk send -wgzip_uu -r$REV -

+ 41 - 0
Documentation/BK-usage/bz64wrap

@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# bz64wrap - the sending side of a bzip2 | base64 stream
+# Andreas Dilger <adilger@clusterfs.com>   Jan 2002
+
+
+PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin
+
+# A program to generate base64 encoding on stdout
+BASE64_ENCODE="uuencode -m /dev/stdout"
+BASE64_BEGIN=
+BASE64_END=
+
+BZIP=NO
+BASE64=NO
+
+# Test if we have the bzip program installed
+bzip2 -c /dev/null > /dev/null 2>&1 && BZIP=YES
+
+# Test if uuencode can handle the -m (MIME) encoding option
+$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES
+
+if [ $BASE64 = NO ]; then
+	BASE64_ENCODE=mimencode
+	BASE64_BEGIN="begin-base64 644 -"
+	BASE64_END="===="
+
+	$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES
+fi
+
+if [ $BZIP = NO -o $BASE64 = NO ]; then
+	echo "$0: can't use bz64 encoding: bzip2=$BZIP, $BASE64_ENCODE=$BASE64"
+	exit 1
+fi
+
+# Sadly, mimencode does not appear to have good "begin" and "end" markers
+# like uuencode does, and it is picky about getting the right start/end of
+# the base64 stream, so we handle this internally.
+echo "$BASE64_BEGIN"
+bzip2 -9 | $BASE64_ENCODE
+echo "$BASE64_END"

+ 36 - 0
Documentation/BK-usage/cpcset

@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Purpose: Copy changeset patch and description from one
+#	   repository to another, unrelated one.
+#
+# usage:  cpcset [revision] [from-repository] [to-repository]
+#
+
+REV=$1
+FROM=$2
+TO=$3
+TMPF=/tmp/cpcset.$$
+
+rm -f $TMPF*
+
+CWD_SAVE=`pwd`
+cd $FROM
+bk changes -r$REV			|	\
+	grep -v '^ChangeSet'		|	\
+	sed -e 's/^  //g' > $TMPF.log
+
+USERHOST=`bk changes -r$REV | grep '^ChangeSet' | awk '{print $4}'`
+export BK_USER=`echo $USERHOST | awk '-F@' '{print $1}'`
+export BK_HOST=`echo $USERHOST | awk '-F@' '{print $2}'`
+
+bk export -tpatch -hdu -r$REV > $TMPF.patch && \
+cd $CWD_SAVE && \
+cd $TO && \
+bk import -tpatch -CFR -y"`cat $TMPF.log`" $TMPF.patch . && \
+bk commit -y"`cat $TMPF.log`"
+
+rm -f $TMPF*
+
+echo changeset $REV copied.
+echo ""
+

+ 49 - 0
Documentation/BK-usage/cset-to-linus

@@ -0,0 +1,49 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+my ($lhs, $rev, $tmp, $rhs, $s);
+my @cset_text = ();
+my @pipe_text = ();
+my $have_cset = 0;
+
+while (<>) {
+	next if /^---/;
+
+	if (($lhs, $tmp, $rhs) = (/^(ChangeSet\@)([^,]+)(, .*)$/)) {
+		&cset_rev if ($have_cset);
+
+		$rev = $tmp;
+		$have_cset = 1;
+
+		push(@cset_text, $_);
+	}
+
+	elsif ($have_cset) {
+		push(@cset_text, $_);
+	}
+}
+&cset_rev if ($have_cset);
+exit(0);
+
+
+sub cset_rev {
+	my $empty_cset = 0;
+
+	open PIPE, "bk export -tpatch -hdu -r $rev | diffstat -p1 2>/dev/null |" or die;
+	while ($s = <PIPE>) {
+		$empty_cset = 1 if ($s =~ /0 files changed/);
+		push(@pipe_text, $s);
+	}
+	close(PIPE);
+
+	if (! $empty_cset) {
+		print @cset_text;
+		print @pipe_text;
+		print "\n\n";
+	}
+
+	@pipe_text = ();
+	@cset_text = ();
+}
+

+ 44 - 0
Documentation/BK-usage/csets-to-patches

@@ -0,0 +1,44 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+my ($lhs, $rev, $tmp, $rhs, $s);
+my @cset_text = ();
+my @pipe_text = ();
+my $have_cset = 0;
+
+while (<>) {
+	next if /^---/;
+
+	if (($lhs, $tmp, $rhs) = (/^(ChangeSet\@)([^,]+)(, .*)$/)) {
+		&cset_rev if ($have_cset);
+
+		$rev = $tmp;
+		$have_cset = 1;
+
+		push(@cset_text, $_);
+	}
+
+	elsif ($have_cset) {
+		push(@cset_text, $_);
+	}
+}
+&cset_rev if ($have_cset);
+exit(0);
+
+
+sub cset_rev {
+	my $empty_cset = 0;
+
+	system("bk export -tpatch -du -r $rev > /tmp/rev-$rev.patch");
+
+	if (! $empty_cset) {
+		print @cset_text;
+		print @pipe_text;
+		print "\n\n";
+	}
+
+	@pipe_text = ();
+	@cset_text = ();
+}
+

+ 8 - 0
Documentation/BK-usage/gcapatch

@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# Purpose: Generate GNU diff of local changes versus canonical top-of-tree
+#
+# Usage: gcapatch > foo.patch
+#
+
+bk export -tpatch -hdu -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+

+ 25 - 0
Documentation/BK-usage/unbz64wrap

@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# unbz64wrap - the receiving side of a bzip2 | base64 stream
+# Andreas Dilger <adilger@clusterfs.com>   Jan 2002
+
+# Sadly, mimencode does not appear to have good "begin" and "end" markers
+# like uuencode does, and it is picky about getting the right start/end of
+# the base64 stream, so we handle this explicitly here.
+
+PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin
+
+if mimencode -u < /dev/null > /dev/null 2>&1 ; then
+	SHOW=
+	while read LINE; do
+		case $LINE in
+		begin-base64*) SHOW=YES ;;
+		====) SHOW= ;;
+		*) [ "$SHOW" ] && echo "$LINE" ;;
+		esac
+	done | mimencode -u | bunzip2
+	exit $?
+else
+	cat - | uudecode -o /dev/stdout | bunzip2
+	exit $?
+fi

+ 92 - 0
Documentation/BUG-HUNTING

@@ -0,0 +1,92 @@
+[Sat Mar  2 10:32:33 PST 1996 KERNEL_BUG-HOWTO lm@sgi.com (Larry McVoy)]
+
+This is how to track down a bug if you know nothing about kernel hacking.  
+It's a brute force approach but it works pretty well.
+
+You need:
+
+        . A reproducible bug - it has to happen predictably (sorry)
+        . All the kernel tar files from a revision that worked to the
+          revision that doesn't
+
+You will then do:
+
+        . Rebuild a revision that you believe works, install, and verify that.
+        . Do a binary search over the kernels to figure out which one
+          introduced the bug.  I.e., suppose 1.3.28 didn't have the bug, but 
+          you know that 1.3.69 does.  Pick a kernel in the middle and build
+          that, like 1.3.50.  Build & test; if it works, pick the mid point
+          between .50 and .69, else the mid point between .28 and .50.
+        . You'll narrow it down to the kernel that introduced the bug.  You
+          can probably do better than this but it gets tricky.  
+
+        . Narrow it down to a subdirectory
+
+          - Copy kernel that works into "test".  Let's say that 3.62 works,
+            but 3.63 doesn't.  So you diff -r those two kernels and come
+            up with a list of directories that changed.  For each of those
+            directories:
+
+                Copy the non-working directory next to the working directory
+                as "dir.63".  
+                One directory at time, try moving the working directory to
+                "dir.62" and mv dir.63 dir"time, try 
+
+                        mv dir dir.62
+                        mv dir.63 dir
+                        find dir -name '*.[oa]' -print | xargs rm -f
+
+                And then rebuild and retest.  Assuming that all related
+                changes were contained in the sub directory, this should 
+                isolate the change to a directory.  
+
+                Problems: changes in header files may have occurred; I've
+                found in my case that they were self explanatory - you may 
+                or may not want to give up when that happens.
+
+        . Narrow it down to a file
+
+          - You can apply the same technique to each file in the directory,
+            hoping that the changes in that file are self contained.  
+            
+        . Narrow it down to a routine
+
+          - You can take the old file and the new file and manually create
+            a merged file that has
+
+                #ifdef VER62
+                routine()
+                {
+                        ...
+                }
+                #else
+                routine()
+                {
+                        ...
+                }
+                #endif
+
+            And then walk through that file, one routine at a time and
+            prefix it with
+
+                #define VER62
+                /* both routines here */
+                #undef VER62
+
+            Then recompile, retest, move the ifdefs until you find the one
+            that makes the difference.
+
+Finally, you take all the info that you have, kernel revisions, bug
+description, the extent to which you have narrowed it down, and pass 
+that off to whomever you believe is the maintainer of that section.
+A post to linux.dev.kernel isn't such a bad idea if you've done some
+work to narrow it down.
+
+If you get it down to a routine, you'll probably get a fix in 24 hours.
+
+My apologies to Linus and the other kernel hackers for describing this
+brute force approach, it's hardly what a kernel hacker would do.  However,
+it does work and it lets non-hackers help fix bugs.  And it is cool
+because Linux snapshots will let you do this - something that you can't
+do with vendor supplied releases.
+

+ 410 - 0
Documentation/Changes

@@ -0,0 +1,410 @@
+Intro
+=====
+
+This document is designed to provide a list of the minimum levels of
+software necessary to run the 2.6 kernels, as well as provide brief
+instructions regarding any other "Gotchas" users may encounter when
+trying life on the Bleeding Edge.  If upgrading from a pre-2.4.x
+kernel, please consult the Changes file included with 2.4.x kernels for
+additional information; most of that information will not be repeated
+here.  Basically, this document assumes that your system is already
+functional and running at least 2.4.x kernels.
+
+This document is originally based on my "Changes" file for 2.0.x kernels
+and therefore owes credit to the same people as that file (Jared Mauch,
+Axel Boldt, Alessandro Sigala, and countless other users all over the
+'net).
+
+The latest revision of this document, in various formats, can always
+be found at <http://cyberbuzz.gatech.edu/kaboom/linux/Changes-2.4/>.
+
+Feel free to translate this document.  If you do so, please send me a
+URL to your translation for inclusion in future revisions of this
+document.
+
+Smotrite file <http://oblom.rnc.ru/linux/kernel/Changes.ru>, yavlyaushisya
+russkim perevodom dannogo documenta.
+
+Visite <http://www2.adi.uam.es/~ender/tecnico/> para obtener la traducción
+al español de este documento en varios formatos.
+
+Eine deutsche Version dieser Datei finden Sie unter
+<http://www.stefan-winter.de/Changes-2.4.0.txt>.
+
+Last updated: October 29th, 2002
+
+Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu).
+
+Current Minimal Requirements
+============================
+
+Upgrade to at *least* these software revisions before thinking you've
+encountered a bug!  If you're unsure what version you're currently
+running, the suggested command should tell you.
+
+Again, keep in mind that this list assumes you are already
+functionally running a Linux 2.4 kernel.  Also, not all tools are
+necessary on all systems; obviously, if you don't have any PCMCIA (PC
+Card) hardware, for example, you probably needn't concern yourself
+with pcmcia-cs.
+
+o  Gnu C                  2.95.3                  # gcc --version
+o  Gnu make               3.79.1                  # make --version
+o  binutils               2.12                    # ld -v
+o  util-linux             2.10o                   # fdformat --version
+o  module-init-tools      0.9.10                  # depmod -V
+o  e2fsprogs              1.29                    # tune2fs
+o  jfsutils               1.1.3                   # fsck.jfs -V
+o  reiserfsprogs          3.6.3                   # reiserfsck -V 2>&1|grep reiserfsprogs
+o  xfsprogs               2.6.0                   # xfs_db -V
+o  pcmcia-cs              3.1.21                  # cardmgr -V
+o  quota-tools            3.09                    # quota -V
+o  PPP                    2.4.0                   # pppd --version
+o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
+o  nfs-utils              1.0.5                   # showmount --version
+o  procps                 3.2.0                   # ps --version
+o  oprofile               0.5.3                   # oprofiled --version
+
+Kernel compilation
+==================
+
+GCC
+---
+
+The gcc version requirements may vary depending on the type of CPU in your
+computer. The next paragraph applies to users of x86 CPUs, but not
+necessarily to users of other CPUs. Users of other CPUs should obtain
+information about their gcc version requirements from another source.
+
+The recommended compiler for the kernel is gcc 2.95.x (x >= 3), and it
+should be used when you need absolute stability. You may use gcc 3.0.x
+instead if you wish, although it may cause problems. Later versions of gcc 
+have not received much testing for Linux kernel compilation, and there are 
+almost certainly bugs (mainly, but not exclusively, in the kernel) that
+will need to be fixed in order to use these compilers. In any case, using
+pgcc instead of plain gcc is just asking for trouble.
+
+The Red Hat gcc 2.96 compiler subtree can also be used to build this tree.
+You should ensure you use gcc-2.96-74 or later. gcc-2.96-54 will not build
+the kernel correctly.
+
+In addition, please pay attention to compiler optimization.  Anything
+greater than -O2 may not be wise.  Similarly, if you choose to use gcc-2.95.x
+or derivatives, be sure not to use -fstrict-aliasing (which, depending on
+your version of gcc 2.95.x, may necessitate using -fno-strict-aliasing).
+
+Make
+----
+
+You will need Gnu make 3.79.1 or later to build the kernel.
+
+Binutils
+--------
+
+Linux on IA-32 has recently switched from using as86 to using gas for
+assembling the 16-bit boot code, removing the need for as86 to compile
+your kernel.  This change does, however, mean that you need a recent
+release of binutils.
+
+System utilities
+================
+
+Architectural changes
+---------------------
+
+DevFS has been obsoleted in favour of udev
+(http://www.kernel.org/pub/linux/utils/kernel/hotplug/)
+
+32-bit UID support is now in place.  Have fun!
+
+Linux documentation for functions is transitioning to inline
+documentation via specially-formatted comments near their
+definitions in the source.  These comments can be combined with the
+SGML templates in the Documentation/DocBook directory to make DocBook
+files, which can then be converted by DocBook stylesheets to PostScript,
+HTML, PDF files, and several other formats.  In order to convert from
+DocBook format to a format of your choice, you'll need to install Jade as
+well as the desired DocBook stylesheets.
+
+Util-linux
+----------
+
+New versions of util-linux provide *fdisk support for larger disks,
+support new options to mount, recognize more supported partition
+types, have a fdformat which works with 2.4 kernels, and similar goodies.
+You'll probably want to upgrade.
+
+Ksymoops
+--------
+
+If the unthinkable happens and your kernel oopses, you'll need a 2.4
+version of ksymoops to decode the report; see REPORTING-BUGS in the
+root of the Linux source for more information.
+
+Module-Init-Tools
+-----------------
+
+A new module loader is now in the kernel that requires module-init-tools
+to use.  It is backward compatible with the 2.4.x series kernels.
+
+Mkinitrd
+--------
+
+These changes to the /lib/modules file tree layout also require that
+mkinitrd be upgraded.
+
+E2fsprogs
+---------
+
+The latest version of e2fsprogs fixes several bugs in fsck and
+debugfs.  Obviously, it's a good idea to upgrade.
+
+JFSutils
+--------
+
+The jfsutils package contains the utilities for the file system.
+The following utilities are available:
+o fsck.jfs - initiate replay of the transaction log, and check
+  and repair a JFS formatted partition.
+o mkfs.jfs - create a JFS formatted partition.
+o other file system utilities are also available in this package.
+
+Reiserfsprogs
+-------------
+
+The reiserfsprogs package should be used for reiserfs-3.6.x
+(Linux kernels 2.4.x). It is a combined package and contains working
+versions of mkreiserfs, resize_reiserfs, debugreiserfs and
+reiserfsck. These utils work on both i386 and alpha platforms.
+
+Xfsprogs
+--------
+
+The latest version of xfsprogs contains mkfs.xfs, xfs_db, and the
+xfs_repair utilities, among others, for the XFS filesystem.  It is
+architecture independent and any version from 2.0.0 onward should
+work correctly with this version of the XFS kernel code (2.6.0 or
+later is recommended, due to some significant improvements).
+
+
+Pcmcia-cs
+---------
+
+PCMCIA (PC Card) support is now partially implemented in the main
+kernel source.  Pay attention when you recompile your kernel ;-).
+Also, be sure to upgrade to the latest pcmcia-cs release.
+
+Quota-tools
+-----------
+
+Support for 32 bit uid's and gid's is required if you want to use
+the newer version 2 quota format.  Quota-tools version 3.07 and
+newer has this support.  Use the recommended version or newer
+from the table above.
+
+Intel IA32 microcode
+--------------------
+
+A driver has been added to allow updating of Intel IA32 microcode,
+accessible as both a devfs regular file and as a normal (misc)
+character device.  If you are not using devfs you may need to:
+
+mkdir /dev/cpu
+mknod /dev/cpu/microcode c 10 184
+chmod 0644 /dev/cpu/microcode
+
+as root before you can use this.  You'll probably also want to
+get the user-space microcode_ctl utility to use with this.
+
+Powertweak
+----------
+
+If you are running v0.1.17 or earlier, you should upgrade to
+version v0.99.0 or higher. Running old versions may cause problems
+with programs using shared memory.
+
+udev
+----
+udev is a userspace application for populating /dev dynamically with
+only entries for devices actually present. udev replaces devfs.
+
+Networking
+==========
+
+General changes
+---------------
+
+If you have advanced network configuration needs, you should probably
+consider using the network tools from ip-route2.
+
+Packet Filter / NAT
+-------------------
+The packet filtering and NAT code uses the same tools like the previous 2.4.x
+kernel series (iptables).  It still includes backwards-compatibility modules
+for 2.2.x-style ipchains and 2.0.x-style ipfwadm.
+
+PPP
+---
+
+The PPP driver has been restructured to support multilink and to
+enable it to operate over diverse media layers.  If you use PPP,
+upgrade pppd to at least 2.4.0.
+
+If you are not using devfs, you must have the device file /dev/ppp
+which can be made by:
+
+mknod /dev/ppp c 108 0
+
+as root.
+
+If you use devfsd and build ppp support as modules, you will need
+the following in your /etc/devfsd.conf file:
+
+LOOKUP	PPP	MODLOAD
+
+Isdn4k-utils
+------------
+
+Due to changes in the length of the phone number field, isdn4k-utils
+needs to be recompiled or (preferably) upgraded.
+
+NFS-utils
+---------
+
+In 2.4 and earlier kernels, the nfs server needed to know about any
+client that expected to be able to access files via NFS.  This
+information would be given to the kernel by "mountd" when the client
+mounted the filesystem, or by "exportfs" at system startup.  exportfs
+would take information about active clients from /var/lib/nfs/rmtab.
+
+This approach is quite fragile as it depends on rmtab being correct
+which is not always easy, particularly when trying to implement
+fail-over.  Even when the system is working well, rmtab suffers from
+getting lots of old entries that never get removed.
+
+With 2.6 we have the option of having the kernel tell mountd when it
+gets a request from an unknown host, and mountd can give appropriate
+export information to the kernel.  This removes the dependency on
+rmtab and means that the kernel only needs to know about currently
+active clients.
+
+To enable this new functionality, you need to:
+
+  mount -t nfsd nfsd /proc/fs/nfs
+
+before running exportfs or mountd.  It is recommended that all NFS
+services be protected from the internet-at-large by a firewall where
+that is possible.
+
+Getting updated software
+========================
+
+Kernel compilation
+******************
+
+gcc 2.95.3
+----------
+o  <ftp://ftp.gnu.org/gnu/gcc/gcc-2.95.3.tar.gz>
+
+Make
+----
+o  <ftp://ftp.gnu.org/gnu/make/>
+
+Binutils
+--------
+o  <ftp://ftp.kernel.org/pub/linux/devel/binutils/>
+
+System utilities
+****************
+
+Util-linux
+----------
+o  <ftp://ftp.kernel.org/pub/linux/utils/util-linux/>
+
+Ksymoops
+--------
+o  <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/>
+
+Module-Init-Tools
+-----------------
+o  <ftp://ftp.kernel.org/pub/linux/kernel/people/rusty/modules/>
+
+Mkinitrd
+--------
+o  <ftp://rawhide.redhat.com/pub/rawhide/SRPMS/SRPMS/>
+
+E2fsprogs
+---------
+o  <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.29.tar.gz>
+
+JFSutils
+--------
+o  <http://jfs.sourceforge.net/>
+
+Reiserfsprogs
+-------------
+o  <http://www.namesys.com/pub/reiserfsprogs/reiserfsprogs-3.6.3.tar.gz>
+
+Xfsprogs
+--------
+o  <ftp://oss.sgi.com/projects/xfs/download/>
+
+Pcmcia-cs
+---------
+o  <ftp://pcmcia-cs.sourceforge.net/pub/pcmcia-cs/pcmcia-cs-3.1.21.tar.gz>
+
+Quota-tools
+----------
+o  <http://sourceforge.net/projects/linuxquota/>
+
+Jade
+----
+o  <ftp://ftp.jclark.com/pub/jade/jade-1.2.1.tar.gz>
+
+DocBook Stylesheets
+-------------------
+o  <http://nwalsh.com/docbook/dsssl/>
+
+Intel P6 microcode
+------------------
+o  <http://www.urbanmyth.org/microcode/>
+
+Powertweak
+----------
+o  <http://powertweak.sourceforge.net/>
+
+udev
+----
+o <http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html>
+
+Networking
+**********
+
+PPP
+---
+o  <ftp://ftp.samba.org/pub/ppp/ppp-2.4.0.tar.gz>
+
+Isdn4k-utils
+------------
+o  <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/isdn4k-utils.v3.1pre1.tar.gz>
+
+NFS-utils
+---------
+o  <http://sourceforge.net/project/showfiles.php?group_id=14>
+
+Iptables
+--------
+o  <http://www.iptables.org/downloads.html>
+
+Ip-route2
+---------
+o  <ftp://ftp.tux.org/pub/net/ip-routing/iproute2-2.2.4-now-ss991023.tar.gz>
+
+OProfile
+--------
+o  <http://oprofile.sf.net/download/>
+
+NFS-Utils
+---------
+o  <http://nfs.sourceforge.net/>
+

+ 431 - 0
Documentation/CodingStyle

@@ -0,0 +1,431 @@
+
+		Linux kernel coding style
+
+This is a short document describing the preferred coding style for the
+linux kernel.  Coding style is very personal, and I won't _force_ my
+views on anybody, but this is what goes for anything that I have to be
+able to maintain, and I'd prefer it for most other things too.  Please
+at least consider the points made here.
+
+First off, I'd suggest printing out a copy of the GNU coding standards,
+and NOT read it.  Burn them, it's a great symbolic gesture.
+
+Anyway, here goes:
+
+
+	 	Chapter 1: Indentation
+
+Tabs are 8 characters, and thus indentations are also 8 characters.
+There are heretic movements that try to make indentations 4 (or even 2!)
+characters deep, and that is akin to trying to define the value of PI to
+be 3.
+
+Rationale: The whole idea behind indentation is to clearly define where
+a block of control starts and ends.  Especially when you've been looking
+at your screen for 20 straight hours, you'll find it a lot easier to see
+how the indentation works if you have large indentations.
+
+Now, some people will claim that having 8-character indentations makes
+the code move too far to the right, and makes it hard to read on a
+80-character terminal screen.  The answer to that is that if you need
+more than 3 levels of indentation, you're screwed anyway, and should fix
+your program.
+
+In short, 8-char indents make things easier to read, and have the added
+benefit of warning you when you're nesting your functions too deep.
+Heed that warning.
+
+Don't put multiple statements on a single line unless you have
+something to hide:
+
+	if (condition) do_this;
+	  do_something_everytime;
+
+Outside of comments, documentation and except in Kconfig, spaces are never
+used for indentation, and the above example is deliberately broken.
+
+Get a decent editor and don't leave whitespace at the end of lines.
+
+
+		Chapter 2: Breaking long lines and strings
+
+Coding style is all about readability and maintainability using commonly
+available tools.
+
+The limit on the length of lines is 80 columns and this is a hard limit.
+
+Statements longer than 80 columns will be broken into sensible chunks.
+Descendants are always substantially shorter than the parent and are placed
+substantially to the right. The same applies to function headers with a long
+argument list. Long strings are as well broken into shorter strings.
+
+void fun(int a, int b, int c)
+{
+	if (condition)
+		printk(KERN_WARNING "Warning this is a long printk with "
+						"3 parameters a: %u b: %u "
+						"c: %u \n", a, b, c);
+	else
+		next_statement;
+}
+
+		Chapter 3: Placing Braces
+
+The other issue that always comes up in C styling is the placement of
+braces.  Unlike the indent size, there are few technical reasons to
+choose one placement strategy over the other, but the preferred way, as
+shown to us by the prophets Kernighan and Ritchie, is to put the opening
+brace last on the line, and put the closing brace first, thusly:
+
+	if (x is true) {
+		we do y
+	}
+
+However, there is one special case, namely functions: they have the
+opening brace at the beginning of the next line, thus:
+
+	int function(int x)
+	{
+		body of function
+	}
+
+Heretic people all over the world have claimed that this inconsistency
+is ...  well ...  inconsistent, but all right-thinking people know that
+(a) K&R are _right_ and (b) K&R are right.  Besides, functions are
+special anyway (you can't nest them in C).
+
+Note that the closing brace is empty on a line of its own, _except_ in
+the cases where it is followed by a continuation of the same statement,
+ie a "while" in a do-statement or an "else" in an if-statement, like
+this:
+
+	do {
+		body of do-loop
+	} while (condition);
+
+and
+
+	if (x == y) {
+		..
+	} else if (x > y) {
+		...
+	} else {
+		....
+	}
+
+Rationale: K&R.
+
+Also, note that this brace-placement also minimizes the number of empty
+(or almost empty) lines, without any loss of readability.  Thus, as the
+supply of new-lines on your screen is not a renewable resource (think
+25-line terminal screens here), you have more empty lines to put
+comments on.
+
+
+		Chapter 4: Naming
+
+C is a Spartan language, and so should your naming be.  Unlike Modula-2
+and Pascal programmers, C programmers do not use cute names like
+ThisVariableIsATemporaryCounter.  A C programmer would call that
+variable "tmp", which is much easier to write, and not the least more
+difficult to understand.
+
+HOWEVER, while mixed-case names are frowned upon, descriptive names for
+global variables are a must.  To call a global function "foo" is a
+shooting offense.
+
+GLOBAL variables (to be used only if you _really_ need them) need to
+have descriptive names, as do global functions.  If you have a function
+that counts the number of active users, you should call that
+"count_active_users()" or similar, you should _not_ call it "cntusr()".
+
+Encoding the type of a function into the name (so-called Hungarian
+notation) is brain damaged - the compiler knows the types anyway and can
+check those, and it only confuses the programmer.  No wonder MicroSoft
+makes buggy programs.
+
+LOCAL variable names should be short, and to the point.  If you have
+some random integer loop counter, it should probably be called "i".
+Calling it "loop_counter" is non-productive, if there is no chance of it
+being mis-understood.  Similarly, "tmp" can be just about any type of
+variable that is used to hold a temporary value.
+
+If you are afraid to mix up your local variable names, you have another
+problem, which is called the function-growth-hormone-imbalance syndrome.
+See next chapter.
+
+
+		Chapter 5: Functions
+
+Functions should be short and sweet, and do just one thing.  They should
+fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
+as we all know), and do one thing and do that well.
+
+The maximum length of a function is inversely proportional to the
+complexity and indentation level of that function.  So, if you have a
+conceptually simple function that is just one long (but simple)
+case-statement, where you have to do lots of small things for a lot of
+different cases, it's OK to have a longer function.
+
+However, if you have a complex function, and you suspect that a
+less-than-gifted first-year high-school student might not even
+understand what the function is all about, you should adhere to the
+maximum limits all the more closely.  Use helper functions with
+descriptive names (you can ask the compiler to in-line them if you think
+it's performance-critical, and it will probably do a better job of it
+than you would have done).
+
+Another measure of the function is the number of local variables.  They
+shouldn't exceed 5-10, or you're doing something wrong.  Re-think the
+function, and split it into smaller pieces.  A human brain can
+generally easily keep track of about 7 different things, anything more
+and it gets confused.  You know you're brilliant, but maybe you'd like
+to understand what you did 2 weeks from now.
+
+
+		Chapter 6: Centralized exiting of functions
+
+Albeit deprecated by some people, the equivalent of the goto statement is
+used frequently by compilers in form of the unconditional jump instruction.
+
+The goto statement comes in handy when a function exits from multiple
+locations and some common work such as cleanup has to be done.
+
+The rationale is:
+
+- unconditional statements are easier to understand and follow
+- nesting is reduced
+- errors by not updating individual exit points when making
+    modifications are prevented
+- saves the compiler work to optimize redundant code away ;)
+
+int fun(int )
+{
+	int result = 0;
+	char *buffer = kmalloc(SIZE);
+
+	if (buffer == NULL)
+		return -ENOMEM;
+
+	if (condition1) {
+		while (loop1) {
+			...
+		}
+		result = 1;
+		goto out;
+	}
+	...
+out:
+	kfree(buffer);
+	return result;
+}
+
+		Chapter 7: Commenting
+
+Comments are good, but there is also a danger of over-commenting.  NEVER
+try to explain HOW your code works in a comment: it's much better to
+write the code so that the _working_ is obvious, and it's a waste of
+time to explain badly written code.
+
+Generally, you want your comments to tell WHAT your code does, not HOW.
+Also, try to avoid putting comments inside a function body: if the
+function is so complex that you need to separately comment parts of it,
+you should probably go back to chapter 5 for a while.  You can make
+small comments to note or warn about something particularly clever (or
+ugly), but try to avoid excess.  Instead, put the comments at the head
+of the function, telling people what it does, and possibly WHY it does
+it.
+
+
+		Chapter 8: You've made a mess of it
+
+That's OK, we all do.  You've probably been told by your long-time Unix
+user helper that "GNU emacs" automatically formats the C sources for
+you, and you've noticed that yes, it does do that, but the defaults it
+uses are less than desirable (in fact, they are worse than random
+typing - an infinite number of monkeys typing into GNU emacs would never
+make a good program).
+
+So, you can either get rid of GNU emacs, or change it to use saner
+values.  To do the latter, you can stick the following in your .emacs file:
+
+(defun linux-c-mode ()
+  "C mode with adjusted defaults for use with the Linux kernel."
+  (interactive)
+  (c-mode)
+  (c-set-style "K&R")
+  (setq tab-width 8)
+  (setq indent-tabs-mode t)
+  (setq c-basic-offset 8))
+
+This will define the M-x linux-c-mode command.  When hacking on a
+module, if you put the string -*- linux-c -*- somewhere on the first
+two lines, this mode will be automatically invoked. Also, you may want
+to add
+
+(setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode)
+			auto-mode-alist))
+
+to your .emacs file if you want to have linux-c-mode switched on
+automagically when you edit source files under /usr/src/linux.
+
+But even if you fail in getting emacs to do sane formatting, not
+everything is lost: use "indent".
+
+Now, again, GNU indent has the same brain-dead settings that GNU emacs
+has, which is why you need to give it a few command line options.
+However, that's not too bad, because even the makers of GNU indent
+recognize the authority of K&R (the GNU people aren't evil, they are
+just severely misguided in this matter), so you just give indent the
+options "-kr -i8" (stands for "K&R, 8 character indents"), or use
+"scripts/Lindent", which indents in the latest style.
+
+"indent" has a lot of options, and especially when it comes to comment
+re-formatting you may want to take a look at the man page.  But
+remember: "indent" is not a fix for bad programming.
+
+
+		Chapter 9: Configuration-files
+
+For configuration options (arch/xxx/Kconfig, and all the Kconfig files),
+somewhat different indentation is used.
+
+Help text is indented with 2 spaces.
+
+if CONFIG_EXPERIMENTAL
+	tristate CONFIG_BOOM
+	default n
+	help
+	  Apply nitroglycerine inside the keyboard (DANGEROUS)
+	bool CONFIG_CHEER
+	depends on CONFIG_BOOM
+	default y
+	help
+	  Output nice messages when you explode
+endif
+
+Generally, CONFIG_EXPERIMENTAL should surround all options not considered
+stable. All options that are known to trash data (experimental write-
+support for file-systems, for instance) should be denoted (DANGEROUS), other
+experimental options should be denoted (EXPERIMENTAL).
+
+
+		Chapter 10: Data structures
+
+Data structures that have visibility outside the single-threaded
+environment they are created and destroyed in should always have
+reference counts.  In the kernel, garbage collection doesn't exist (and
+outside the kernel garbage collection is slow and inefficient), which
+means that you absolutely _have_ to reference count all your uses.
+
+Reference counting means that you can avoid locking, and allows multiple
+users to have access to the data structure in parallel - and not having
+to worry about the structure suddenly going away from under them just
+because they slept or did something else for a while.
+
+Note that locking is _not_ a replacement for reference counting.
+Locking is used to keep data structures coherent, while reference
+counting is a memory management technique.  Usually both are needed, and
+they are not to be confused with each other.
+
+Many data structures can indeed have two levels of reference counting,
+when there are users of different "classes".  The subclass count counts
+the number of subclass users, and decrements the global count just once
+when the subclass count goes to zero.
+
+Examples of this kind of "multi-level-reference-counting" can be found in
+memory management ("struct mm_struct": mm_users and mm_count), and in
+filesystem code ("struct super_block": s_count and s_active).
+
+Remember: if another thread can find your data structure, and you don't
+have a reference count on it, you almost certainly have a bug.
+
+
+		Chapter 11: Macros, Enums, Inline functions and RTL
+
+Names of macros defining constants and labels in enums are capitalized.
+
+#define CONSTANT 0x12345
+
+Enums are preferred when defining several related constants.
+
+CAPITALIZED macro names are appreciated but macros resembling functions
+may be named in lower case.
+
+Generally, inline functions are preferable to macros resembling functions.
+
+Macros with multiple statements should be enclosed in a do - while block:
+
+#define macrofun(a, b, c) 			\
+	do {					\
+		if (a == 5)			\
+			do_this(b, c);		\
+	} while (0)
+
+Things to avoid when using macros:
+
+1) macros that affect control flow:
+
+#define FOO(x)					\
+	do {					\
+		if (blah(x) < 0)		\
+			return -EBUGGERED;	\
+	} while(0)
+
+is a _very_ bad idea.  It looks like a function call but exits the "calling"
+function; don't break the internal parsers of those who will read the code.
+
+2) macros that depend on having a local variable with a magic name:
+
+#define FOO(val) bar(index, val)
+
+might look like a good thing, but it's confusing as hell when one reads the
+code and it's prone to breakage from seemingly innocent changes.
+
+3) macros with arguments that are used as l-values: FOO(x) = y; will
+bite you if somebody e.g. turns FOO into an inline function.
+
+4) forgetting about precedence: macros defining constants using expressions
+must enclose the expression in parentheses. Beware of similar issues with
+macros using parameters.
+
+#define CONSTANT 0x4000
+#define CONSTEXP (CONSTANT | 3)
+
+The cpp manual deals with macros exhaustively. The gcc internals manual also
+covers RTL which is used frequently with assembly language in the kernel.
+
+
+		Chapter 12: Printing kernel messages
+
+Kernel developers like to be seen as literate. Do mind the spelling
+of kernel messages to make a good impression. Do not use crippled
+words like "dont" and use "do not" or "don't" instead.
+
+Kernel messages do not have to be terminated with a period.
+
+Printing numbers in parentheses (%d) adds no value and should be avoided.
+
+
+		Chapter 13: References
+
+The C Programming Language, Second Edition
+by Brian W. Kernighan and Dennis M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback).
+URL: http://cm.bell-labs.com/cm/cs/cbook/
+
+The Practice of Programming
+by Brian W. Kernighan and Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+URL: http://cm.bell-labs.com/cm/cs/tpop/
+
+GNU manuals - where in compliance with K&R and this text - for cpp, gcc,
+gcc internals and indent, all available from http://www.gnu.org
+
+WG14 is the international standardization working group for the programming
+language C, URL: http://std.dkuug.dk/JTC1/SC22/WG14/
+
+--
+Last updated on 16 February 2004 by a community effort on LKML.

+ 526 - 0
Documentation/DMA-API.txt

@@ -0,0 +1,526 @@
+               Dynamic DMA mapping using the generic device
+               ============================================
+
+        James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
+
+This document describes the DMA API.  For a more gentle introduction
+phrased in terms of the pci_ equivalents (and actual examples) see
+DMA-mapping.txt
+
+This API is split into two pieces.  Part I describes the API and the
+corresponding pci_ API.  Part II describes the extensions to the API
+for supporting non-consistent memory machines.  Unless you know that
+your driver absolutely has to support non-consistent platforms (this
+is usually only legacy platforms) you should only use the API
+described in part I.
+
+Part I - pci_ and dma_ Equivalent API 
+-------------------------------------
+
+To get the pci_ API, you must #include <linux/pci.h>
+To get the dma_ API, you must #include <linux/dma-mapping.h>
+
+
+Part Ia - Using large dma-coherent buffers
+------------------------------------------
+
+void *
+dma_alloc_coherent(struct device *dev, size_t size,
+			     dma_addr_t *dma_handle, int flag)
+void *
+pci_alloc_consistent(struct pci_dev *dev, size_t size,
+			     dma_addr_t *dma_handle)
+
+Consistent memory is memory for which a write by either the device or
+the processor can immediately be read by the processor or device
+without having to worry about caching effects.
+
+This routine allocates a region of <size> bytes of consistent memory.
+it also returns a <dma_handle> which may be cast to an unsigned
+integer the same width as the bus and used as the physical address
+base of the region.
+
+Returns: a pointer to the allocated region (in the processor's virtual
+address space) or NULL if the allocation failed.
+
+Note: consistent memory can be expensive on some platforms, and the
+minimum allocation length may be as big as a page, so you should
+consolidate your requests for consistent memory as much as possible.
+The simplest way to do that is to use the dma_pool calls (see below).
+
+The flag parameter (dma_alloc_coherent only) allows the caller to
+specify the GFP_ flags (see kmalloc) for the allocation (the
+implementation may chose to ignore flags that affect the location of
+the returned memory, like GFP_DMA).  For pci_alloc_consistent, you
+must assume GFP_ATOMIC behaviour.
+
+void
+dma_free_coherent(struct device *dev, size_t size, void *cpu_addr
+			   dma_addr_t dma_handle)
+void
+pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr
+			   dma_addr_t dma_handle)
+
+Free the region of consistent memory you previously allocated.  dev,
+size and dma_handle must all be the same as those passed into the
+consistent allocate.  cpu_addr must be the virtual address returned by
+the consistent allocate
+
+
+Part Ib - Using small dma-coherent buffers
+------------------------------------------
+
+To get this part of the dma_ API, you must #include <linux/dmapool.h>
+
+Many drivers need lots of small dma-coherent memory regions for DMA
+descriptors or I/O buffers.  Rather than allocating in units of a page
+or more using dma_alloc_coherent(), you can use DMA pools.  These work
+much like a kmem_cache_t, except that they use the dma-coherent allocator
+not __get_free_pages().  Also, they understand common hardware constraints
+for alignment, like queue heads needing to be aligned on N byte boundaries.
+
+
+	struct dma_pool *
+	dma_pool_create(const char *name, struct device *dev,
+			size_t size, size_t align, size_t alloc);
+
+	struct pci_pool *
+	pci_pool_create(const char *name, struct pci_device *dev,
+			size_t size, size_t align, size_t alloc);
+
+The pool create() routines initialize a pool of dma-coherent buffers
+for use with a given device.  It must be called in a context which
+can sleep.
+
+The "name" is for diagnostics (like a kmem_cache_t name); dev and size
+are like what you'd pass to dma_alloc_coherent().  The device's hardware
+alignment requirement for this type of data is "align" (which is expressed
+in bytes, and must be a power of two).  If your device has no boundary
+crossing restrictions, pass 0 for alloc; passing 4096 says memory allocated
+from this pool must not cross 4KByte boundaries.
+
+
+	void *dma_pool_alloc(struct dma_pool *pool, int gfp_flags,
+			dma_addr_t *dma_handle);
+
+	void *pci_pool_alloc(struct pci_pool *pool, int gfp_flags,
+			dma_addr_t *dma_handle);
+
+This allocates memory from the pool; the returned memory will meet the size
+and alignment requirements specified at creation time.  Pass GFP_ATOMIC to
+prevent blocking, or if it's permitted (not in_interrupt, not holding SMP locks)
+pass GFP_KERNEL to allow blocking.  Like dma_alloc_coherent(), this returns
+two values:  an address usable by the cpu, and the dma address usable by the
+pool's device.
+
+
+	void dma_pool_free(struct dma_pool *pool, void *vaddr,
+			dma_addr_t addr);
+
+	void pci_pool_free(struct pci_pool *pool, void *vaddr,
+			dma_addr_t addr);
+
+This puts memory back into the pool.  The pool is what was passed to
+the the pool allocation routine; the cpu and dma addresses are what
+were returned when that routine allocated the memory being freed.
+
+
+	void dma_pool_destroy(struct dma_pool *pool);
+
+	void pci_pool_destroy(struct pci_pool *pool);
+
+The pool destroy() routines free the resources of the pool.  They must be
+called in a context which can sleep.  Make sure you've freed all allocated
+memory back to the pool before you destroy it.
+
+
+Part Ic - DMA addressing limitations
+------------------------------------
+
+int
+dma_supported(struct device *dev, u64 mask)
+int
+pci_dma_supported(struct device *dev, u64 mask)
+
+Checks to see if the device can support DMA to the memory described by
+mask.
+
+Returns: 1 if it can and 0 if it can't.
+
+Notes: This routine merely tests to see if the mask is possible.  It
+won't change the current mask settings.  It is more intended as an
+internal API for use by the platform than an external API for use by
+driver writers.
+
+int
+dma_set_mask(struct device *dev, u64 mask)
+int
+pci_set_dma_mask(struct pci_device *dev, u64 mask)
+
+Checks to see if the mask is possible and updates the device
+parameters if it is.
+
+Returns: 0 if successful and a negative error if not.
+
+u64
+dma_get_required_mask(struct device *dev)
+
+After setting the mask with dma_set_mask(), this API returns the
+actual mask (within that already set) that the platform actually
+requires to operate efficiently.  Usually this means the returned mask
+is the minimum required to cover all of memory.  Examining the
+required mask gives drivers with variable descriptor sizes the
+opportunity to use smaller descriptors as necessary.
+
+Requesting the required mask does not alter the current mask.  If you
+wish to take advantage of it, you should issue another dma_set_mask()
+call to lower the mask again.
+
+
+Part Id - Streaming DMA mappings
+--------------------------------
+
+dma_addr_t
+dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+		      enum dma_data_direction direction)
+dma_addr_t
+pci_map_single(struct device *dev, void *cpu_addr, size_t size,
+		      int direction)
+
+Maps a piece of processor virtual memory so it can be accessed by the
+device and returns the physical handle of the memory.
+
+The direction for both api's may be converted freely by casting.
+However the dma_ API uses a strongly typed enumerator for its
+direction:
+
+DMA_NONE		= PCI_DMA_NONE		no direction (used for
+						debugging)
+DMA_TO_DEVICE		= PCI_DMA_TODEVICE	data is going from the
+						memory to the device
+DMA_FROM_DEVICE		= PCI_DMA_FROMDEVICE	data is coming from
+						the device to the
+						memory
+DMA_BIDIRECTIONAL	= PCI_DMA_BIDIRECTIONAL	direction isn't known
+
+Notes:  Not all memory regions in a machine can be mapped by this
+API.  Further, regions that appear to be physically contiguous in
+kernel virtual space may not be contiguous as physical memory.  Since
+this API does not provide any scatter/gather capability, it will fail
+if the user tries to map a non physically contiguous piece of memory.
+For this reason, it is recommended that memory mapped by this API be
+obtained only from sources which guarantee to be physically contiguous
+(like kmalloc).
+
+Further, the physical address of the memory must be within the
+dma_mask of the device (the dma_mask represents a bit mask of the
+addressable region for the device.  i.e. if the physical address of
+the memory anded with the dma_mask is still equal to the physical
+address, then the device can perform DMA to the memory).  In order to
+ensure that the memory allocated by kmalloc is within the dma_mask,
+the driver may specify various platform dependent flags to restrict
+the physical memory range of the allocation (e.g. on x86, GFP_DMA
+guarantees to be within the first 16Mb of available physical memory,
+as required by ISA devices).
+
+Note also that the above constraints on physical contiguity and
+dma_mask may not apply if the platform has an IOMMU (a device which
+supplies a physical to virtual mapping between the I/O memory bus and
+the device).  However, to be portable, device driver writers may *not*
+assume that such an IOMMU exists.
+
+Warnings:  Memory coherency operates at a granularity called the cache
+line width.  In order for memory mapped by this API to operate
+correctly, the mapped region must begin exactly on a cache line
+boundary and end exactly on one (to prevent two separately mapped
+regions from sharing a single cache line).  Since the cache line size
+may not be known at compile time, the API will not enforce this
+requirement.  Therefore, it is recommended that driver writers who
+don't take special care to determine the cache line size at run time
+only map virtual regions that begin and end on page boundaries (which
+are guaranteed also to be cache line boundaries).
+
+DMA_TO_DEVICE synchronisation must be done after the last modification
+of the memory region by the software and before it is handed off to
+the driver.  Once this primitive is used.  Memory covered by this
+primitive should be treated as read only by the device.  If the device
+may write to it at any point, it should be DMA_BIDIRECTIONAL (see
+below).
+
+DMA_FROM_DEVICE synchronisation must be done before the driver
+accesses data that may be changed by the device.  This memory should
+be treated as read only by the driver.  If the driver needs to write
+to it at any point, it should be DMA_BIDIRECTIONAL (see below).
+
+DMA_BIDIRECTIONAL requires special handling: it means that the driver
+isn't sure if the memory was modified before being handed off to the
+device and also isn't sure if the device will also modify it.  Thus,
+you must always sync bidirectional memory twice: once before the
+memory is handed off to the device (to make sure all memory changes
+are flushed from the processor) and once before the data may be
+accessed after being used by the device (to make sure any processor
+cache lines are updated with data that the device may have changed.
+
+void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction direction)
+void
+pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+		 size_t size, int direction)
+
+Unmaps the region previously mapped.  All the parameters passed in
+must be identical to those passed in (and returned) by the mapping
+API.
+
+dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+		    unsigned long offset, size_t size,
+		    enum dma_data_direction direction)
+dma_addr_t
+pci_map_page(struct pci_dev *hwdev, struct page *page,
+		    unsigned long offset, size_t size, int direction)
+void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	       enum dma_data_direction direction)
+void
+pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
+	       size_t size, int direction)
+
+API for mapping and unmapping for pages.  All the notes and warnings
+for the other mapping APIs apply here.  Also, although the <offset>
+and <size> parameters are provided to do partial page mapping, it is
+recommended that you never use these unless you really know what the
+cache width is.
+
+int
+dma_mapping_error(dma_addr_t dma_addr)
+
+int
+pci_dma_mapping_error(dma_addr_t dma_addr)
+
+In some circumstances dma_map_single and dma_map_page will fail to create
+a mapping. A driver can check for these errors by testing the returned
+dma address with dma_mapping_error(). A non zero return value means the mapping
+could not be created and the driver should take appropriate action (eg
+reduce current DMA mapping usage or delay and try again later).
+
+int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	   enum dma_data_direction direction)
+int
+pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+	   int nents, int direction)
+
+Maps a scatter gather list from the block layer.
+
+Returns: the number of physical segments mapped (this may be shorted
+than <nents> passed in if the block layer determines that some
+elements of the scatter/gather list are physically adjacent and thus
+may be mapped with a single entry).
+
+Please note that the sg cannot be mapped again if it has been mapped once.
+The mapping process is allowed to destroy information in the sg.
+
+As with the other mapping interfaces, dma_map_sg can fail. When it
+does, 0 is returned and a driver must take appropriate action. It is
+critical that the driver do something, in the case of a block driver
+aborting the request or even oopsing is better than doing nothing and
+corrupting the filesystem.
+
+void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	     enum dma_data_direction direction)
+void
+pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+	     int nents, int direction)
+
+unmap the previously mapped scatter/gather list.  All the parameters
+must be the same as those and passed in to the scatter/gather mapping
+API.
+
+Note: <nents> must be the number you passed in, *not* the number of
+physical entries returned.
+
+void
+dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+		enum dma_data_direction direction)
+void
+pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle,
+			   size_t size, int direction)
+void
+dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+			  enum dma_data_direction direction)
+void
+pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+		       int nelems, int direction)
+
+synchronise a single contiguous or scatter/gather mapping.  All the
+parameters must be the same as those passed into the single mapping
+API.
+
+Notes:  You must do this:
+
+- Before reading values that have been written by DMA from the device
+  (use the DMA_FROM_DEVICE direction)
+- After writing values that will be written to the device using DMA
+  (use the DMA_TO_DEVICE) direction
+- before *and* after handing memory to the device if the memory is
+  DMA_BIDIRECTIONAL
+
+See also dma_map_single().
+
+
+Part II - Advanced dma_ usage
+-----------------------------
+
+Warning: These pieces of the DMA API have no PCI equivalent.  They
+should also not be used in the majority of cases, since they cater for
+unlikely corner cases that don't belong in usual drivers.
+
+If you don't understand how cache line coherency works between a
+processor and an I/O device, you should not be using this part of the
+API at all.
+
+void *
+dma_alloc_noncoherent(struct device *dev, size_t size,
+			       dma_addr_t *dma_handle, int flag)
+
+Identical to dma_alloc_coherent() except that the platform will
+choose to return either consistent or non-consistent memory as it sees
+fit.  By using this API, you are guaranteeing to the platform that you
+have all the correct and necessary sync points for this memory in the
+driver should it choose to return non-consistent memory.
+
+Note: where the platform can return consistent memory, it will
+guarantee that the sync points become nops.
+
+Warning:  Handling non-consistent memory is a real pain.  You should
+only ever use this API if you positively know your driver will be
+required to work on one of the rare (usually non-PCI) architectures
+that simply cannot make consistent memory.
+
+void
+dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
+			      dma_addr_t dma_handle)
+
+free memory allocated by the nonconsistent API.  All parameters must
+be identical to those passed in (and returned by
+dma_alloc_noncoherent()).
+
+int
+dma_is_consistent(dma_addr_t dma_handle)
+
+returns true if the memory pointed to by the dma_handle is actually
+consistent.
+
+int
+dma_get_cache_alignment(void)
+
+returns the processor cache alignment.  This is the absolute minimum
+alignment *and* width that you must observe when either mapping
+memory or doing partial flushes.
+
+Notes: This API may return a number *larger* than the actual cache
+line, but it will guarantee that one or more cache lines fit exactly
+into the width returned by this call.  It will also always be a power
+of two for easy alignment
+
+void
+dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
+		      unsigned long offset, size_t size,
+		      enum dma_data_direction direction)
+
+does a partial sync.  starting at offset and continuing for size.  You
+must be careful to observe the cache alignment and width when doing
+anything like this.  You must also be extra careful about accessing
+memory you intend to sync partially.
+
+void
+dma_cache_sync(void *vaddr, size_t size,
+	       enum dma_data_direction direction)
+
+Do a partial sync of memory that was allocated by
+dma_alloc_noncoherent(), starting at virtual address vaddr and
+continuing on for size.  Again, you *must* observe the cache line
+boundaries when doing this.
+
+int
+dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+			    dma_addr_t device_addr, size_t size, int
+			    flags)
+
+
+Declare region of memory to be handed out by dma_alloc_coherent when
+it's asked for coherent memory for this device.
+
+bus_addr is the physical address to which the memory is currently
+assigned in the bus responding region (this will be used by the
+platform to perform the mapping)
+
+device_addr is the physical address the device needs to be programmed
+with actually to address this memory (this will be handed out as the
+dma_addr_t in dma_alloc_coherent())
+
+size is the size of the area (must be multiples of PAGE_SIZE).
+
+flags can be or'd together and are
+
+DMA_MEMORY_MAP - request that the memory returned from
+dma_alloc_coherent() be directly writeable.
+
+DMA_MEMORY_IO - request that the memory returned from
+dma_alloc_coherent() be addressable using read/write/memcpy_toio etc.
+
+One or both of these flags must be present
+
+DMA_MEMORY_INCLUDES_CHILDREN - make the declared memory be allocated by
+dma_alloc_coherent of any child devices of this one (for memory residing
+on a bridge).
+
+DMA_MEMORY_EXCLUSIVE - only allocate memory from the declared regions. 
+Do not allow dma_alloc_coherent() to fall back to system memory when
+it's out of memory in the declared region.
+
+The return value will be either DMA_MEMORY_MAP or DMA_MEMORY_IO and
+must correspond to a passed in flag (i.e. no returning DMA_MEMORY_IO
+if only DMA_MEMORY_MAP were passed in) for success or zero for
+failure.
+
+Note, for DMA_MEMORY_IO returns, all subsequent memory returned by
+dma_alloc_coherent() may no longer be accessed directly, but instead
+must be accessed using the correct bus functions.  If your driver
+isn't prepared to handle this contingency, it should not specify
+DMA_MEMORY_IO in the input flags.
+
+As a simplification for the platforms, only *one* such region of
+memory may be declared per device.
+
+For reasons of efficiency, most platforms choose to track the declared
+region only at the granularity of a page.  For smaller allocations,
+you should use the dma_pool() API.
+
+void
+dma_release_declared_memory(struct device *dev)
+
+Remove the memory region previously declared from the system.  This
+API performs *no* in-use checking for this region and will return
+unconditionally having removed all the required structures.  It is the
+drivers job to ensure that no parts of this memory region are
+currently in use.
+
+void *
+dma_mark_declared_memory_occupied(struct device *dev,
+				  dma_addr_t device_addr, size_t size)
+
+This is used to occupy specific regions of the declared space
+(dma_alloc_coherent() will hand out the first free region it finds).
+
+device_addr is the *device* address of the region requested
+
+size is the size (and should be a page sized multiple).
+
+The return value will be either a pointer to the processor virtual
+address of the memory, or an error (via PTR_ERR()) if any part of the
+region is occupied.
+
+

+ 881 - 0
Documentation/DMA-mapping.txt

@@ -0,0 +1,881 @@
+			Dynamic DMA mapping
+			===================
+
+		 David S. Miller <davem@redhat.com>
+		 Richard Henderson <rth@cygnus.com>
+		  Jakub Jelinek <jakub@redhat.com>
+
+This document describes the DMA mapping system in terms of the pci_
+API.  For a similar API that works for generic devices, see
+DMA-API.txt.
+
+Most of the 64bit platforms have special hardware that translates bus
+addresses (DMA addresses) into physical addresses.  This is similar to
+how page tables and/or a TLB translates virtual addresses to physical
+addresses on a CPU.  This is needed so that e.g. PCI devices can
+access with a Single Address Cycle (32bit DMA address) any page in the
+64bit physical address space.  Previously in Linux those 64bit
+platforms had to set artificial limits on the maximum RAM size in the
+system, so that the virt_to_bus() static scheme works (the DMA address
+translation tables were simply filled on bootup to map each bus
+address to the physical page __pa(bus_to_virt())).
+
+So that Linux can use the dynamic DMA mapping, it needs some help from the
+drivers, namely it has to take into account that DMA addresses should be
+mapped only for the time they are actually used and unmapped after the DMA
+transfer.
+
+The following API will work of course even on platforms where no such
+hardware exists, see e.g. include/asm-i386/pci.h for how it is implemented on
+top of the virt_to_bus interface.
+
+First of all, you should make sure
+
+#include <linux/pci.h>
+
+is in your driver. This file will obtain for you the definition of the
+dma_addr_t (which can hold any valid DMA address for the platform)
+type which should be used everywhere you hold a DMA (bus) address
+returned from the DMA mapping functions.
+
+			 What memory is DMA'able?
+
+The first piece of information you must know is what kernel memory can
+be used with the DMA mapping facilities.  There has been an unwritten
+set of rules regarding this, and this text is an attempt to finally
+write them down.
+
+If you acquired your memory via the page allocator
+(i.e. __get_free_page*()) or the generic memory allocators
+(i.e. kmalloc() or kmem_cache_alloc()) then you may DMA to/from
+that memory using the addresses returned from those routines.
+
+This means specifically that you may _not_ use the memory/addresses
+returned from vmalloc() for DMA.  It is possible to DMA to the
+_underlying_ memory mapped into a vmalloc() area, but this requires
+walking page tables to get the physical addresses, and then
+translating each of those pages back to a kernel address using
+something like __va().  [ EDIT: Update this when we integrate
+Gerd Knorr's generic code which does this. ]
+
+This rule also means that you may not use kernel image addresses
+(ie. items in the kernel's data/text/bss segment, or your driver's)
+nor may you use kernel stack addresses for DMA.  Both of these items
+might be mapped somewhere entirely different than the rest of physical
+memory.
+
+Also, this means that you cannot take the return of a kmap()
+call and DMA to/from that.  This is similar to vmalloc().
+
+What about block I/O and networking buffers?  The block I/O and
+networking subsystems make sure that the buffers they use are valid
+for you to DMA from/to.
+
+			DMA addressing limitations
+
+Does your device have any DMA addressing limitations?  For example, is
+your device only capable of driving the low order 24-bits of address
+on the PCI bus for SAC DMA transfers?  If so, you need to inform the
+PCI layer of this fact.
+
+By default, the kernel assumes that your device can address the full
+32-bits in a SAC cycle.  For a 64-bit DAC capable device, this needs
+to be increased.  And for a device with limitations, as discussed in
+the previous paragraph, it needs to be decreased.
+
+pci_alloc_consistent() by default will return 32-bit DMA addresses.
+PCI-X specification requires PCI-X devices to support 64-bit
+addressing (DAC) for all transactions. And at least one platform (SGI
+SN2) requires 64-bit consistent allocations to operate correctly when
+the IO bus is in PCI-X mode. Therefore, like with pci_set_dma_mask(),
+it's good practice to call pci_set_consistent_dma_mask() to set the
+appropriate mask even if your device only supports 32-bit DMA
+(default) and especially if it's a PCI-X device.
+
+For correct operation, you must interrogate the PCI layer in your
+device probe routine to see if the PCI controller on the machine can
+properly support the DMA addressing limitation your device has.  It is
+good style to do this even if your device holds the default setting,
+because this shows that you did think about these issues wrt. your
+device.
+
+The query is performed via a call to pci_set_dma_mask():
+
+	int pci_set_dma_mask(struct pci_dev *pdev, u64 device_mask);
+
+The query for consistent allocations is performed via a a call to
+pci_set_consistent_dma_mask():
+
+	int pci_set_consistent_dma_mask(struct pci_dev *pdev, u64 device_mask);
+
+Here, pdev is a pointer to the PCI device struct of your device, and
+device_mask is a bit mask describing which bits of a PCI address your
+device supports.  It returns zero if your card can perform DMA
+properly on the machine given the address mask you provided.
+
+If it returns non-zero, your device can not perform DMA properly on
+this platform, and attempting to do so will result in undefined
+behavior.  You must either use a different mask, or not use DMA.
+
+This means that in the failure case, you have three options:
+
+1) Use another DMA mask, if possible (see below).
+2) Use some non-DMA mode for data transfer, if possible.
+3) Ignore this device and do not initialize it.
+
+It is recommended that your driver print a kernel KERN_WARNING message
+when you end up performing either #2 or #3.  In this manner, if a user
+of your driver reports that performance is bad or that the device is not
+even detected, you can ask them for the kernel messages to find out
+exactly why.
+
+The standard 32-bit addressing PCI device would do something like
+this:
+
+	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+		printk(KERN_WARNING
+		       "mydev: No suitable DMA available.\n");
+		goto ignore_this_device;
+	}
+
+Another common scenario is a 64-bit capable device.  The approach
+here is to try for 64-bit DAC addressing, but back down to a
+32-bit mask should that fail.  The PCI platform code may fail the
+64-bit mask not because the platform is not capable of 64-bit
+addressing.  Rather, it may fail in this case simply because
+32-bit SAC addressing is done more efficiently than DAC addressing.
+Sparc64 is one platform which behaves in this way.
+
+Here is how you would handle a 64-bit capable device which can drive
+all 64-bits when accessing streaming DMA:
+
+	int using_dac;
+
+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+		using_dac = 1;
+	} else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+		using_dac = 0;
+	} else {
+		printk(KERN_WARNING
+		       "mydev: No suitable DMA available.\n");
+		goto ignore_this_device;
+	}
+
+If a card is capable of using 64-bit consistent allocations as well,
+the case would look like this:
+
+	int using_dac, consistent_using_dac;
+
+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+		using_dac = 1;
+	   	consistent_using_dac = 1;
+		pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+	} else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+		using_dac = 0;
+		consistent_using_dac = 0;
+		pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+	} else {
+		printk(KERN_WARNING
+		       "mydev: No suitable DMA available.\n");
+		goto ignore_this_device;
+	}
+
+pci_set_consistent_dma_mask() will always be able to set the same or a
+smaller mask as pci_set_dma_mask(). However for the rare case that a
+device driver only uses consistent allocations, one would have to
+check the return value from pci_set_consistent_dma_mask().
+
+If your 64-bit device is going to be an enormous consumer of DMA
+mappings, this can be problematic since the DMA mappings are a
+finite resource on many platforms.  Please see the "DAC Addressing
+for Address Space Hungry Devices" section near the end of this
+document for how to handle this case.
+
+Finally, if your device can only drive the low 24-bits of
+address during PCI bus mastering you might do something like:
+
+	if (pci_set_dma_mask(pdev, 0x00ffffff)) {
+		printk(KERN_WARNING
+		       "mydev: 24-bit DMA addressing not available.\n");
+		goto ignore_this_device;
+	}
+
+When pci_set_dma_mask() is successful, and returns zero, the PCI layer
+saves away this mask you have provided.  The PCI layer will use this
+information later when you make DMA mappings.
+
+There is a case which we are aware of at this time, which is worth
+mentioning in this documentation.  If your device supports multiple
+functions (for example a sound card provides playback and record
+functions) and the various different functions have _different_
+DMA addressing limitations, you may wish to probe each mask and
+only provide the functionality which the machine can handle.  It
+is important that the last call to pci_set_dma_mask() be for the 
+most specific mask.
+
+Here is pseudo-code showing how this might be done:
+
+	#define PLAYBACK_ADDRESS_BITS	DMA_32BIT_MASK
+	#define RECORD_ADDRESS_BITS	0x00ffffff
+
+	struct my_sound_card *card;
+	struct pci_dev *pdev;
+
+	...
+	if (!pci_set_dma_mask(pdev, PLAYBACK_ADDRESS_BITS)) {
+		card->playback_enabled = 1;
+	} else {
+		card->playback_enabled = 0;
+		printk(KERN_WARN "%s: Playback disabled due to DMA limitations.\n",
+		       card->name);
+	}
+	if (!pci_set_dma_mask(pdev, RECORD_ADDRESS_BITS)) {
+		card->record_enabled = 1;
+	} else {
+		card->record_enabled = 0;
+		printk(KERN_WARN "%s: Record disabled due to DMA limitations.\n",
+		       card->name);
+	}
+
+A sound card was used as an example here because this genre of PCI
+devices seems to be littered with ISA chips given a PCI front end,
+and thus retaining the 16MB DMA addressing limitations of ISA.
+
+			Types of DMA mappings
+
+There are two types of DMA mappings:
+
+- Consistent DMA mappings which are usually mapped at driver
+  initialization, unmapped at the end and for which the hardware should
+  guarantee that the device and the CPU can access the data
+  in parallel and will see updates made by each other without any
+  explicit software flushing.
+
+  Think of "consistent" as "synchronous" or "coherent".
+
+  The current default is to return consistent memory in the low 32
+  bits of the PCI bus space.  However, for future compatibility you
+  should set the consistent mask even if this default is fine for your
+  driver.
+
+  Good examples of what to use consistent mappings for are:
+
+	- Network card DMA ring descriptors.
+	- SCSI adapter mailbox command data structures.
+	- Device firmware microcode executed out of
+	  main memory.
+
+  The invariant these examples all require is that any CPU store
+  to memory is immediately visible to the device, and vice
+  versa.  Consistent mappings guarantee this.
+
+  IMPORTANT: Consistent DMA memory does not preclude the usage of
+             proper memory barriers.  The CPU may reorder stores to
+	     consistent memory just as it may normal memory.  Example:
+	     if it is important for the device to see the first word
+	     of a descriptor updated before the second, you must do
+	     something like:
+
+		desc->word0 = address;
+		wmb();
+		desc->word1 = DESC_VALID;
+
+             in order to get correct behavior on all platforms.
+
+- Streaming DMA mappings which are usually mapped for one DMA transfer,
+  unmapped right after it (unless you use pci_dma_sync_* below) and for which
+  hardware can optimize for sequential accesses.
+
+  This of "streaming" as "asynchronous" or "outside the coherency
+  domain".
+
+  Good examples of what to use streaming mappings for are:
+
+	- Networking buffers transmitted/received by a device.
+	- Filesystem buffers written/read by a SCSI device.
+
+  The interfaces for using this type of mapping were designed in
+  such a way that an implementation can make whatever performance
+  optimizations the hardware allows.  To this end, when using
+  such mappings you must be explicit about what you want to happen.
+
+Neither type of DMA mapping has alignment restrictions that come
+from PCI, although some devices may have such restrictions.
+
+		 Using Consistent DMA mappings.
+
+To allocate and map large (PAGE_SIZE or so) consistent DMA regions,
+you should do:
+
+	dma_addr_t dma_handle;
+
+	cpu_addr = pci_alloc_consistent(dev, size, &dma_handle);
+
+where dev is a struct pci_dev *. You should pass NULL for PCI like buses
+where devices don't have struct pci_dev (like ISA, EISA).  This may be
+called in interrupt context. 
+
+This argument is needed because the DMA translations may be bus
+specific (and often is private to the bus which the device is attached
+to).
+
+Size is the length of the region you want to allocate, in bytes.
+
+This routine will allocate RAM for that region, so it acts similarly to
+__get_free_pages (but takes size instead of a page order).  If your
+driver needs regions sized smaller than a page, you may prefer using
+the pci_pool interface, described below.
+
+The consistent DMA mapping interfaces, for non-NULL dev, will by
+default return a DMA address which is SAC (Single Address Cycle)
+addressable.  Even if the device indicates (via PCI dma mask) that it
+may address the upper 32-bits and thus perform DAC cycles, consistent
+allocation will only return > 32-bit PCI addresses for DMA if the
+consistent dma mask has been explicitly changed via
+pci_set_consistent_dma_mask().  This is true of the pci_pool interface
+as well.
+
+pci_alloc_consistent returns two values: the virtual address which you
+can use to access it from the CPU and dma_handle which you pass to the
+card.
+
+The cpu return address and the DMA bus master address are both
+guaranteed to be aligned to the smallest PAGE_SIZE order which
+is greater than or equal to the requested size.  This invariant
+exists (for example) to guarantee that if you allocate a chunk
+which is smaller than or equal to 64 kilobytes, the extent of the
+buffer you receive will not cross a 64K boundary.
+
+To unmap and free such a DMA region, you call:
+
+	pci_free_consistent(dev, size, cpu_addr, dma_handle);
+
+where dev, size are the same as in the above call and cpu_addr and
+dma_handle are the values pci_alloc_consistent returned to you.
+This function may not be called in interrupt context.
+
+If your driver needs lots of smaller memory regions, you can write
+custom code to subdivide pages returned by pci_alloc_consistent,
+or you can use the pci_pool API to do that.  A pci_pool is like
+a kmem_cache, but it uses pci_alloc_consistent not __get_free_pages.
+Also, it understands common hardware constraints for alignment,
+like queue heads needing to be aligned on N byte boundaries.
+
+Create a pci_pool like this:
+
+	struct pci_pool *pool;
+
+	pool = pci_pool_create(name, dev, size, align, alloc);
+
+The "name" is for diagnostics (like a kmem_cache name); dev and size
+are as above.  The device's hardware alignment requirement for this
+type of data is "align" (which is expressed in bytes, and must be a
+power of two).  If your device has no boundary crossing restrictions,
+pass 0 for alloc; passing 4096 says memory allocated from this pool
+must not cross 4KByte boundaries (but at that time it may be better to
+go for pci_alloc_consistent directly instead).
+
+Allocate memory from a pci pool like this:
+
+	cpu_addr = pci_pool_alloc(pool, flags, &dma_handle);
+
+flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor
+holding SMP locks), SLAB_ATOMIC otherwise.  Like pci_alloc_consistent,
+this returns two values, cpu_addr and dma_handle.
+
+Free memory that was allocated from a pci_pool like this:
+
+	pci_pool_free(pool, cpu_addr, dma_handle);
+
+where pool is what you passed to pci_pool_alloc, and cpu_addr and
+dma_handle are the values pci_pool_alloc returned. This function
+may be called in interrupt context.
+
+Destroy a pci_pool by calling:
+
+	pci_pool_destroy(pool);
+
+Make sure you've called pci_pool_free for all memory allocated
+from a pool before you destroy the pool. This function may not
+be called in interrupt context.
+
+			DMA Direction
+
+The interfaces described in subsequent portions of this document
+take a DMA direction argument, which is an integer and takes on
+one of the following values:
+
+ PCI_DMA_BIDIRECTIONAL
+ PCI_DMA_TODEVICE
+ PCI_DMA_FROMDEVICE
+ PCI_DMA_NONE
+
+One should provide the exact DMA direction if you know it.
+
+PCI_DMA_TODEVICE means "from main memory to the PCI device"
+PCI_DMA_FROMDEVICE means "from the PCI device to main memory"
+It is the direction in which the data moves during the DMA
+transfer.
+
+You are _strongly_ encouraged to specify this as precisely
+as you possibly can.
+
+If you absolutely cannot know the direction of the DMA transfer,
+specify PCI_DMA_BIDIRECTIONAL.  It means that the DMA can go in
+either direction.  The platform guarantees that you may legally
+specify this, and that it will work, but this may be at the
+cost of performance for example.
+
+The value PCI_DMA_NONE is to be used for debugging.  One can
+hold this in a data structure before you come to know the
+precise direction, and this will help catch cases where your
+direction tracking logic has failed to set things up properly.
+
+Another advantage of specifying this value precisely (outside of
+potential platform-specific optimizations of such) is for debugging.
+Some platforms actually have a write permission boolean which DMA
+mappings can be marked with, much like page protections in the user
+program address space.  Such platforms can and do report errors in the
+kernel logs when the PCI controller hardware detects violation of the
+permission setting.
+
+Only streaming mappings specify a direction, consistent mappings
+implicitly have a direction attribute setting of
+PCI_DMA_BIDIRECTIONAL.
+
+The SCSI subsystem provides mechanisms for you to easily obtain
+the direction to use, in the SCSI command:
+
+	scsi_to_pci_dma_dir(SCSI_DIRECTION)
+
+Where SCSI_DIRECTION is obtained from the 'sc_data_direction'
+member of the SCSI command your driver is working on.  The
+mentioned interface above returns a value suitable for passing
+into the streaming DMA mapping interfaces below.
+
+For Networking drivers, it's a rather simple affair.  For transmit
+packets, map/unmap them with the PCI_DMA_TODEVICE direction
+specifier.  For receive packets, just the opposite, map/unmap them
+with the PCI_DMA_FROMDEVICE direction specifier.
+
+		  Using Streaming DMA mappings
+
+The streaming DMA mapping routines can be called from interrupt
+context.  There are two versions of each map/unmap, one which will
+map/unmap a single memory region, and one which will map/unmap a
+scatterlist.
+
+To map a single region, you do:
+
+	struct pci_dev *pdev = mydev->pdev;
+	dma_addr_t dma_handle;
+	void *addr = buffer->ptr;
+	size_t size = buffer->len;
+
+	dma_handle = pci_map_single(dev, addr, size, direction);
+
+and to unmap it:
+
+	pci_unmap_single(dev, dma_handle, size, direction);
+
+You should call pci_unmap_single when the DMA activity is finished, e.g.
+from the interrupt which told you that the DMA transfer is done.
+
+Using cpu pointers like this for single mappings has a disadvantage,
+you cannot reference HIGHMEM memory in this way.  Thus, there is a
+map/unmap interface pair akin to pci_{map,unmap}_single.  These
+interfaces deal with page/offset pairs instead of cpu pointers.
+Specifically:
+
+	struct pci_dev *pdev = mydev->pdev;
+	dma_addr_t dma_handle;
+	struct page *page = buffer->page;
+	unsigned long offset = buffer->offset;
+	size_t size = buffer->len;
+
+	dma_handle = pci_map_page(dev, page, offset, size, direction);
+
+	...
+
+	pci_unmap_page(dev, dma_handle, size, direction);
+
+Here, "offset" means byte offset within the given page.
+
+With scatterlists, you map a region gathered from several regions by:
+
+	int i, count = pci_map_sg(dev, sglist, nents, direction);
+	struct scatterlist *sg;
+
+	for (i = 0, sg = sglist; i < count; i++, sg++) {
+		hw_address[i] = sg_dma_address(sg);
+		hw_len[i] = sg_dma_len(sg);
+	}
+
+where nents is the number of entries in the sglist.
+
+The implementation is free to merge several consecutive sglist entries
+into one (e.g. if DMA mapping is done with PAGE_SIZE granularity, any
+consecutive sglist entries can be merged into one provided the first one
+ends and the second one starts on a page boundary - in fact this is a huge
+advantage for cards which either cannot do scatter-gather or have very
+limited number of scatter-gather entries) and returns the actual number
+of sg entries it mapped them to. On failure 0 is returned.
+
+Then you should loop count times (note: this can be less than nents times)
+and use sg_dma_address() and sg_dma_len() macros where you previously
+accessed sg->address and sg->length as shown above.
+
+To unmap a scatterlist, just call:
+
+	pci_unmap_sg(dev, sglist, nents, direction);
+
+Again, make sure DMA activity has already finished.
+
+PLEASE NOTE:  The 'nents' argument to the pci_unmap_sg call must be
+              the _same_ one you passed into the pci_map_sg call,
+	      it should _NOT_ be the 'count' value _returned_ from the
+              pci_map_sg call.
+
+Every pci_map_{single,sg} call should have its pci_unmap_{single,sg}
+counterpart, because the bus address space is a shared resource (although
+in some ports the mapping is per each BUS so less devices contend for the
+same bus address space) and you could render the machine unusable by eating
+all bus addresses.
+
+If you need to use the same streaming DMA region multiple times and touch
+the data in between the DMA transfers, the buffer needs to be synced
+properly in order for the cpu and device to see the most uptodate and
+correct copy of the DMA buffer.
+
+So, firstly, just map it with pci_map_{single,sg}, and after each DMA
+transfer call either:
+
+	pci_dma_sync_single_for_cpu(dev, dma_handle, size, direction);
+
+or:
+
+	pci_dma_sync_sg_for_cpu(dev, sglist, nents, direction);
+
+as appropriate.
+
+Then, if you wish to let the device get at the DMA area again,
+finish accessing the data with the cpu, and then before actually
+giving the buffer to the hardware call either:
+
+	pci_dma_sync_single_for_device(dev, dma_handle, size, direction);
+
+or:
+
+	pci_dma_sync_sg_for_device(dev, sglist, nents, direction);
+
+as appropriate.
+
+After the last DMA transfer call one of the DMA unmap routines
+pci_unmap_{single,sg}. If you don't touch the data from the first pci_map_*
+call till pci_unmap_*, then you don't have to call the pci_dma_sync_*
+routines at all.
+
+Here is pseudo code which shows a situation in which you would need
+to use the pci_dma_sync_*() interfaces.
+
+	my_card_setup_receive_buffer(struct my_card *cp, char *buffer, int len)
+	{
+		dma_addr_t mapping;
+
+		mapping = pci_map_single(cp->pdev, buffer, len, PCI_DMA_FROMDEVICE);
+
+		cp->rx_buf = buffer;
+		cp->rx_len = len;
+		cp->rx_dma = mapping;
+
+		give_rx_buf_to_card(cp);
+	}
+
+	...
+
+	my_card_interrupt_handler(int irq, void *devid, struct pt_regs *regs)
+	{
+		struct my_card *cp = devid;
+
+		...
+		if (read_card_status(cp) == RX_BUF_TRANSFERRED) {
+			struct my_card_header *hp;
+
+			/* Examine the header to see if we wish
+			 * to accept the data.  But synchronize
+			 * the DMA transfer with the CPU first
+			 * so that we see updated contents.
+			 */
+			pci_dma_sync_single_for_cpu(cp->pdev, cp->rx_dma,
+						    cp->rx_len,
+						    PCI_DMA_FROMDEVICE);
+
+			/* Now it is safe to examine the buffer. */
+			hp = (struct my_card_header *) cp->rx_buf;
+			if (header_is_ok(hp)) {
+				pci_unmap_single(cp->pdev, cp->rx_dma, cp->rx_len,
+						 PCI_DMA_FROMDEVICE);
+				pass_to_upper_layers(cp->rx_buf);
+				make_and_setup_new_rx_buf(cp);
+			} else {
+				/* Just sync the buffer and give it back
+				 * to the card.
+				 */
+				pci_dma_sync_single_for_device(cp->pdev,
+							       cp->rx_dma,
+							       cp->rx_len,
+							       PCI_DMA_FROMDEVICE);
+				give_rx_buf_to_card(cp);
+			}
+		}
+	}
+
+Drivers converted fully to this interface should not use virt_to_bus any
+longer, nor should they use bus_to_virt. Some drivers have to be changed a
+little bit, because there is no longer an equivalent to bus_to_virt in the
+dynamic DMA mapping scheme - you have to always store the DMA addresses
+returned by the pci_alloc_consistent, pci_pool_alloc, and pci_map_single
+calls (pci_map_sg stores them in the scatterlist itself if the platform
+supports dynamic DMA mapping in hardware) in your driver structures and/or
+in the card registers.
+
+All PCI drivers should be using these interfaces with no exceptions.
+It is planned to completely remove virt_to_bus() and bus_to_virt() as
+they are entirely deprecated.  Some ports already do not provide these
+as it is impossible to correctly support them.
+
+		64-bit DMA and DAC cycle support
+
+Do you understand all of the text above?  Great, then you already
+know how to use 64-bit DMA addressing under Linux.  Simply make
+the appropriate pci_set_dma_mask() calls based upon your cards
+capabilities, then use the mapping APIs above.
+
+It is that simple.
+
+Well, not for some odd devices.  See the next section for information
+about that.
+
+	DAC Addressing for Address Space Hungry Devices
+
+There exists a class of devices which do not mesh well with the PCI
+DMA mapping API.  By definition these "mappings" are a finite
+resource.  The number of total available mappings per bus is platform
+specific, but there will always be a reasonable amount.
+
+What is "reasonable"?  Reasonable means that networking and block I/O
+devices need not worry about using too many mappings.
+
+As an example of a problematic device, consider compute cluster cards.
+They can potentially need to access gigabytes of memory at once via
+DMA.  Dynamic mappings are unsuitable for this kind of access pattern.
+
+To this end we've provided a small API by which a device driver
+may use DAC cycles to directly address all of physical memory.
+Not all platforms support this, but most do.  It is easy to determine
+whether the platform will work properly at probe time.
+
+First, understand that there may be a SEVERE performance penalty for
+using these interfaces on some platforms.  Therefore, you MUST only
+use these interfaces if it is absolutely required.  %99 of devices can
+use the normal APIs without any problems.
+
+Note that for streaming type mappings you must either use these
+interfaces, or the dynamic mapping interfaces above.  You may not mix
+usage of both for the same device.  Such an act is illegal and is
+guaranteed to put a banana in your tailpipe.
+
+However, consistent mappings may in fact be used in conjunction with
+these interfaces.  Remember that, as defined, consistent mappings are
+always going to be SAC addressable.
+
+The first thing your driver needs to do is query the PCI platform
+layer with your devices DAC addressing capabilities:
+
+	int pci_dac_set_dma_mask(struct pci_dev *pdev, u64 mask);
+
+This routine behaves identically to pci_set_dma_mask.  You may not
+use the following interfaces if this routine fails.
+
+Next, DMA addresses using this API are kept track of using the
+dma64_addr_t type.  It is guaranteed to be big enough to hold any
+DAC address the platform layer will give to you from the following
+routines.  If you have consistent mappings as well, you still
+use plain dma_addr_t to keep track of those.
+
+All mappings obtained here will be direct.  The mappings are not
+translated, and this is the purpose of this dialect of the DMA API.
+
+All routines work with page/offset pairs.  This is the _ONLY_ way to 
+portably refer to any piece of memory.  If you have a cpu pointer
+(which may be validly DMA'd too) you may easily obtain the page
+and offset using something like this:
+
+	struct page *page = virt_to_page(ptr);
+	unsigned long offset = offset_in_page(ptr);
+
+Here are the interfaces:
+
+	dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+					 struct page *page,
+					 unsigned long offset,
+					 int direction);
+
+The DAC address for the tuple PAGE/OFFSET are returned.  The direction
+argument is the same as for pci_{map,unmap}_single().  The same rules
+for cpu/device access apply here as for the streaming mapping
+interfaces.  To reiterate:
+
+	The cpu may touch the buffer before pci_dac_page_to_dma.
+	The device may touch the buffer after pci_dac_page_to_dma
+	is made, but the cpu may NOT.
+
+When the DMA transfer is complete, invoke:
+
+	void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
+					     dma64_addr_t dma_addr,
+					     size_t len, int direction);
+
+This must be done before the CPU looks at the buffer again.
+This interface behaves identically to pci_dma_sync_{single,sg}_for_cpu().
+
+And likewise, if you wish to let the device get back at the buffer after
+the cpu has read/written it, invoke:
+
+	void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
+						dma64_addr_t dma_addr,
+						size_t len, int direction);
+
+before letting the device access the DMA area again.
+
+If you need to get back to the PAGE/OFFSET tuple from a dma64_addr_t
+the following interfaces are provided:
+
+	struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+					 dma64_addr_t dma_addr);
+	unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+					    dma64_addr_t dma_addr);
+
+This is possible with the DAC interfaces purely because they are
+not translated in any way.
+
+		Optimizing Unmap State Space Consumption
+
+On many platforms, pci_unmap_{single,page}() is simply a nop.
+Therefore, keeping track of the mapping address and length is a waste
+of space.  Instead of filling your drivers up with ifdefs and the like
+to "work around" this (which would defeat the whole purpose of a
+portable API) the following facilities are provided.
+
+Actually, instead of describing the macros one by one, we'll
+transform some example code.
+
+1) Use DECLARE_PCI_UNMAP_{ADDR,LEN} in state saving structures.
+   Example, before:
+
+	struct ring_state {
+		struct sk_buff *skb;
+		dma_addr_t mapping;
+		__u32 len;
+	};
+
+   after:
+
+	struct ring_state {
+		struct sk_buff *skb;
+		DECLARE_PCI_UNMAP_ADDR(mapping)
+		DECLARE_PCI_UNMAP_LEN(len)
+	};
+
+   NOTE: DO NOT put a semicolon at the end of the DECLARE_*()
+         macro.
+
+2) Use pci_unmap_{addr,len}_set to set these values.
+   Example, before:
+
+	ringp->mapping = FOO;
+	ringp->len = BAR;
+
+   after:
+
+	pci_unmap_addr_set(ringp, mapping, FOO);
+	pci_unmap_len_set(ringp, len, BAR);
+
+3) Use pci_unmap_{addr,len} to access these values.
+   Example, before:
+
+	pci_unmap_single(pdev, ringp->mapping, ringp->len,
+			 PCI_DMA_FROMDEVICE);
+
+   after:
+
+	pci_unmap_single(pdev,
+			 pci_unmap_addr(ringp, mapping),
+			 pci_unmap_len(ringp, len),
+			 PCI_DMA_FROMDEVICE);
+
+It really should be self-explanatory.  We treat the ADDR and LEN
+separately, because it is possible for an implementation to only
+need the address in order to perform the unmap operation.
+
+			Platform Issues
+
+If you are just writing drivers for Linux and do not maintain
+an architecture port for the kernel, you can safely skip down
+to "Closing".
+
+1) Struct scatterlist requirements.
+
+   Struct scatterlist must contain, at a minimum, the following
+   members:
+
+	struct page *page;
+	unsigned int offset;
+	unsigned int length;
+
+   The base address is specified by a "page+offset" pair.
+
+   Previous versions of struct scatterlist contained a "void *address"
+   field that was sometimes used instead of page+offset.  As of Linux
+   2.5., page+offset is always used, and the "address" field has been
+   deleted.
+
+2) More to come...
+
+			Handling Errors
+
+DMA address space is limited on some architectures and an allocation
+failure can be determined by:
+
+- checking if pci_alloc_consistent returns NULL or pci_map_sg returns 0
+
+- checking the returned dma_addr_t of pci_map_single and pci_map_page
+  by using pci_dma_mapping_error():
+
+	dma_addr_t dma_handle;
+
+	dma_handle = pci_map_single(dev, addr, size, direction);
+	if (pci_dma_mapping_error(dma_handle)) {
+		/*
+		 * reduce current DMA mapping usage,
+		 * delay and try again later or
+		 * reset driver.
+		 */
+	}
+
+			   Closing
+
+This document, and the API itself, would not be in it's current
+form without the feedback and suggestions from numerous individuals.
+We would like to specifically mention, in no particular order, the
+following people:
+
+	Russell King <rmk@arm.linux.org.uk>
+	Leo Dagum <dagum@barrel.engr.sgi.com>
+	Ralf Baechle <ralf@oss.sgi.com>
+	Grant Grundler <grundler@cup.hp.com>
+	Jay Estabrook <Jay.Estabrook@compaq.com>
+	Thomas Sailer <sailer@ife.ee.ethz.ch>
+	Andrea Arcangeli <andrea@suse.de>
+	Jens Axboe <axboe@suse.de>
+	David Mosberger-Tang <davidm@hpl.hp.com>

+ 195 - 0
Documentation/DocBook/Makefile

@@ -0,0 +1,195 @@
+###
+# This makefile is used to generate the kernel documentation,
+# primarily based on in-line comments in various source files.
+# See Documentation/kernel-doc-nano-HOWTO.txt for instruction in how
+# to ducument the SRC - and how to read it.
+# To add a new book the only step required is to add the book to the
+# list of DOCBOOKS.
+
+DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
+	    kernel-hacking.xml kernel-locking.xml via-audio.xml \
+	    deviceiobook.xml procfs-guide.xml tulip-user.xml \
+	    writing_usb_driver.xml scsidrivers.xml sis900.xml \
+	    kernel-api.xml journal-api.xml lsm.xml usb.xml \
+	    gadget.xml libata.xml mtdnand.xml librs.xml
+
+###
+# The build process is as follows (targets):
+#              (xmldocs)
+# file.tmpl --> file.xml +--> file.ps   (psdocs)
+#                        +--> file.pdf  (pdfdocs)
+#                        +--> DIR=file  (htmldocs)
+#                        +--> man/      (mandocs)
+
+###
+# The targets that may be used.
+.PHONY:	xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs
+
+BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
+xmldocs: $(BOOKS)
+sgmldocs: xmldocs
+
+PS := $(patsubst %.xml, %.ps, $(BOOKS))
+psdocs: $(PS)
+
+PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
+pdfdocs: $(PDF)
+
+HTML := $(patsubst %.xml, %.html, $(BOOKS))
+htmldocs: $(HTML)
+
+MAN := $(patsubst %.xml, %.9, $(BOOKS))
+mandocs: $(MAN)
+
+installmandocs: mandocs
+	$(MAKEMAN) install Documentation/DocBook/man
+
+###
+#External programs used
+KERNELDOC = scripts/kernel-doc
+DOCPROC   = scripts/basic/docproc
+SPLITMAN  = $(PERL) $(srctree)/scripts/split-man
+MAKEMAN   = $(PERL) $(srctree)/scripts/makeman
+
+###
+# DOCPROC is used for two purposes:
+# 1) To generate a dependency list for a .tmpl file
+# 2) To preprocess a .tmpl file and call kernel-doc with
+#     appropriate parameters.
+# The following rules are used to generate the .xml documentation
+# required to generate the final targets. (ps, pdf, html).
+quiet_cmd_docproc = DOCPROC $@
+      cmd_docproc = SRCTREE=$(srctree)/ $(DOCPROC) doc $< >$@
+define rule_docproc
+	set -e;								\
+        $(if $($(quiet)cmd_$(1)),echo '  $($(quiet)cmd_$(1))';) 	\
+        $(cmd_$(1)); 							\
+        ( 								\
+          echo 'cmd_$@ := $(cmd_$(1))'; 				\
+          echo $@: `SRCTREE=$(srctree) $(DOCPROC) depend $<`; 		\
+        ) > $(dir $@).$(notdir $@).cmd
+endef
+
+%.xml: %.tmpl FORCE
+	$(call if_changed_rule,docproc)
+
+###
+#Read in all saved dependency files 
+cmd_files := $(wildcard $(foreach f,$(BOOKS),$(dir $(f)).$(notdir $(f)).cmd))
+
+ifneq ($(cmd_files),)
+  include $(cmd_files)
+endif
+
+###
+# Changes in kernel-doc force a rebuild of all documentation
+$(BOOKS): $(KERNELDOC)
+
+###
+# procfs guide uses a .c file as example code.
+# This requires an explicit dependency
+C-procfs-example = procfs_example.xml
+C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example))
+$(obj)/procfs-guide.xml: $(C-procfs-example2)
+
+###
+# Rules to generate postscript, PDF and HTML
+# db2html creates a directory. Generate a html file used for timestamp
+
+quiet_cmd_db2ps = DB2PS   $@
+      cmd_db2ps = db2ps -o $(dir $@) $<
+%.ps : %.xml
+	@(which db2ps > /dev/null 2>&1) || \
+	 (echo "*** You need to install DocBook stylesheets ***"; \
+	  exit 1)
+	$(call cmd,db2ps)
+
+quiet_cmd_db2pdf = DB2PDF  $@
+      cmd_db2pdf = db2pdf -o $(dir $@) $<
+%.pdf : %.xml
+	@(which db2pdf > /dev/null 2>&1) || \
+	 (echo "*** You need to install DocBook stylesheets ***"; \
+	  exit 1)
+	$(call cmd,db2pdf)
+
+quiet_cmd_db2html = DB2HTML $@
+      cmd_db2html = db2html -o $(patsubst %.html,%,$@) $< &&		      \
+		echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/book1.html"> \
+         Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
+
+%.html:	%.xml
+	@(which db2html > /dev/null 2>&1) || \
+	 (echo "*** You need to install DocBook stylesheets ***"; \
+	  exit 1)
+	@rm -rf $@ $(patsubst %.html,%,$@)
+	$(call cmd,db2html)
+	@if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \
+            cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi
+
+###
+# Rule to generate man files - output is placed in the man subdirectory
+
+%.9:	%.xml
+ifneq ($(KBUILD_SRC),)
+	$(Q)mkdir -p $(objtree)/Documentation/DocBook/man
+endif
+	$(SPLITMAN) $< $(objtree)/Documentation/DocBook/man "$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)"
+	$(MAKEMAN) convert $(objtree)/Documentation/DocBook/man $<
+
+###
+# Rules to generate postscripts and PNG imgages from .fig format files
+quiet_cmd_fig2eps = FIG2EPS $@
+      cmd_fig2eps = fig2dev -Leps $< $@
+
+%.eps: %.fig
+	@(which fig2dev > /dev/null 2>&1) || \
+	 (echo "*** You need to install transfig ***"; \
+	  exit 1)
+	$(call cmd,fig2eps)
+
+quiet_cmd_fig2png = FIG2PNG $@
+      cmd_fig2png = fig2dev -Lpng $< $@
+
+%.png: %.fig
+	@(which fig2dev > /dev/null 2>&1) || \
+	 (echo "*** You need to install transfig ***"; \
+	  exit 1)
+	$(call cmd,fig2png)
+
+###
+# Rule to convert a .c file to inline XML documentation
+%.xml: %.c
+	@echo '  GEN     $@'
+	@(                            \
+	   echo "<programlisting>";   \
+	   expand --tabs=8 < $< |     \
+	   sed -e "s/&/\\&amp;/g"     \
+	       -e "s/</\\&lt;/g"      \
+	       -e "s/>/\\&gt;/g";     \
+	   echo "</programlisting>")  > $@
+
+###
+# Help targets as used by the top-level makefile
+dochelp:
+	@echo  '  Linux kernel internal documentation in different formats:'
+	@echo  '  xmldocs (XML DocBook), psdocs (Postscript), pdfdocs (PDF)'
+	@echo  '  htmldocs (HTML), mandocs (man pages, use installmandocs to install)'
+
+###
+# Temporary files left by various tools
+clean-files := $(DOCBOOKS) \
+	$(patsubst %.xml, %.dvi,  $(DOCBOOKS)) \
+	$(patsubst %.xml, %.aux,  $(DOCBOOKS)) \
+	$(patsubst %.xml, %.tex,  $(DOCBOOKS)) \
+	$(patsubst %.xml, %.log,  $(DOCBOOKS)) \
+	$(patsubst %.xml, %.out,  $(DOCBOOKS)) \
+	$(patsubst %.xml, %.ps,   $(DOCBOOKS)) \
+	$(patsubst %.xml, %.pdf,  $(DOCBOOKS)) \
+	$(patsubst %.xml, %.html, $(DOCBOOKS)) \
+	$(patsubst %.xml, %.9,    $(DOCBOOKS)) \
+	$(C-procfs-example)
+
+clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS))
+
+#man put files in man subdir - traverse down
+subdir- := man/

+ 341 - 0
Documentation/DocBook/deviceiobook.tmpl

@@ -0,0 +1,341 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="DoingIO">
+ <bookinfo>
+  <title>Bus-Independent Device Accesses</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Matthew</firstname>
+    <surname>Wilcox</surname>
+    <affiliation>
+     <address>
+      <email>matthew@wil.cx</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <authorgroup>
+   <author>
+    <firstname>Alan</firstname>
+    <surname>Cox</surname>
+    <affiliation>
+     <address>
+      <email>alan@redhat.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2001</year>
+   <holder>Matthew Wilcox</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+	Linux provides an API which abstracts performing IO across all busses
+	and devices, allowing device drivers to be written independently of
+	bus type.
+  </para>
+  </chapter>
+
+  <chapter id="bugs">
+     <title>Known Bugs And Assumptions</title>
+  <para>
+	None.	
+  </para>
+  </chapter>
+
+  <chapter id="mmio">
+    <title>Memory Mapped IO</title>
+    <sect1>
+      <title>Getting Access to the Device</title>
+      <para>
+	The most widely supported form of IO is memory mapped IO.
+	That is, a part of the CPU's address space is interpreted
+	not as accesses to memory, but as accesses to a device.  Some
+	architectures define devices to be at a fixed address, but most
+	have some method of discovering devices.  The PCI bus walk is a
+	good example of such a scheme.	This document does not cover how
+	to receive such an address, but assumes you are starting with one.
+	Physical addresses are of type unsigned long. 
+      </para>
+
+      <para>
+	This address should not be used directly.  Instead, to get an
+	address suitable for passing to the accessor functions described
+	below, you should call <function>ioremap</function>.
+	An address suitable for accessing the device will be returned to you.
+      </para>
+
+      <para>
+	After you've finished using the device (say, in your module's
+	exit routine), call <function>iounmap</function> in order to return
+	the address space to the kernel.  Most architectures allocate new
+	address space each time you call <function>ioremap</function>, and
+	they can run out unless you call <function>iounmap</function>.
+      </para>
+    </sect1>
+
+    <sect1>
+      <title>Accessing the device</title>
+      <para>
+	The part of the interface most used by drivers is reading and
+	writing memory-mapped registers on the device.	Linux provides
+	interfaces to read and write 8-bit, 16-bit, 32-bit and 64-bit
+	quantities.  Due to a historical accident, these are named byte,
+	word, long and quad accesses.  Both read and write accesses are
+	supported; there is no prefetch support at this time.
+      </para>
+
+      <para>
+	The functions are named <function>readb</function>,
+	<function>readw</function>, <function>readl</function>,
+	<function>readq</function>, <function>readb_relaxed</function>,
+	<function>readw_relaxed</function>, <function>readl_relaxed</function>,
+	<function>readq_relaxed</function>, <function>writeb</function>,
+	<function>writew</function>, <function>writel</function> and
+	<function>writeq</function>.
+      </para>
+
+      <para>
+	Some devices (such as framebuffers) would like to use larger
+	transfers than 8 bytes at a time.  For these devices, the
+	<function>memcpy_toio</function>, <function>memcpy_fromio</function>
+	and <function>memset_io</function> functions are provided.
+	Do not use memset or memcpy on IO addresses; they
+	are not guaranteed to copy data in order.
+      </para>
+
+      <para>
+	The read and write functions are defined to be ordered. That is the
+	compiler is not permitted to reorder the I/O sequence. When the 
+	ordering can be compiler optimised, you can use <function>
+	__readb</function> and friends to indicate the relaxed ordering. Use 
+	this with care.
+      </para>
+
+      <para>
+	While the basic functions are defined to be synchronous with respect
+	to each other and ordered with respect to each other the busses the
+	devices sit on may themselves have asynchronicity. In particular many
+	authors are burned by the fact that PCI bus writes are posted
+	asynchronously. A driver author must issue a read from the same
+	device to ensure that writes have occurred in the specific cases the
+	author cares. This kind of property cannot be hidden from driver
+	writers in the API.  In some cases, the read used to flush the device
+	may be expected to fail (if the card is resetting, for example).  In
+	that case, the read should be done from config space, which is
+	guaranteed to soft-fail if the card doesn't respond.
+      </para>
+
+      <para>
+	The following is an example of flushing a write to a device when
+	the driver would like to ensure the write's effects are visible prior
+	to continuing execution.
+      </para>
+
+<programlisting>
+static inline void
+qla1280_disable_intrs(struct scsi_qla_host *ha)
+{
+	struct device_reg *reg;
+
+	reg = ha->iobase;
+	/* disable risc and host interrupts */
+	WRT_REG_WORD(&amp;reg->ictrl, 0);
+	/*
+	 * The following read will ensure that the above write
+	 * has been received by the device before we return from this
+	 * function.
+	 */
+	RD_REG_WORD(&amp;reg->ictrl);
+	ha->flags.ints_enabled = 0;
+}
+</programlisting>
+
+      <para>
+	In addition to write posting, on some large multiprocessing systems
+	(e.g. SGI Challenge, Origin and Altix machines) posted writes won't
+	be strongly ordered coming from different CPUs.  Thus it's important
+	to properly protect parts of your driver that do memory-mapped writes
+	with locks and use the <function>mmiowb</function> to make sure they
+	arrive in the order intended.  Issuing a regular <function>readX
+	</function> will also ensure write ordering, but should only be used
+	when the driver has to be sure that the write has actually arrived
+	at the device (not that it's simply ordered with respect to other
+	writes), since a full <function>readX</function> is a relatively
+	expensive operation.
+      </para>
+
+      <para>
+	Generally, one should use <function>mmiowb</function> prior to
+	releasing a spinlock that protects regions using <function>writeb
+	</function> or similar functions that aren't surrounded by <function>
+	readb</function> calls, which will ensure ordering and flushing.  The
+	following pseudocode illustrates what might occur if write ordering
+	isn't guaranteed via <function>mmiowb</function> or one of the
+	<function>readX</function> functions.
+      </para>
+
+<programlisting>
+CPU A:  spin_lock_irqsave(&amp;dev_lock, flags)
+CPU A:  ...
+CPU A:  writel(newval, ring_ptr);
+CPU A:  spin_unlock_irqrestore(&amp;dev_lock, flags)
+        ...
+CPU B:  spin_lock_irqsave(&amp;dev_lock, flags)
+CPU B:  writel(newval2, ring_ptr);
+CPU B:  ...
+CPU B:  spin_unlock_irqrestore(&amp;dev_lock, flags)
+</programlisting>
+
+      <para>
+	In the case above, newval2 could be written to ring_ptr before
+	newval.  Fixing it is easy though:
+      </para>
+
+<programlisting>
+CPU A:  spin_lock_irqsave(&amp;dev_lock, flags)
+CPU A:  ...
+CPU A:  writel(newval, ring_ptr);
+CPU A:  mmiowb(); /* ensure no other writes beat us to the device */
+CPU A:  spin_unlock_irqrestore(&amp;dev_lock, flags)
+        ...
+CPU B:  spin_lock_irqsave(&amp;dev_lock, flags)
+CPU B:  writel(newval2, ring_ptr);
+CPU B:  ...
+CPU B:  mmiowb();
+CPU B:  spin_unlock_irqrestore(&amp;dev_lock, flags)
+</programlisting>
+
+      <para>
+	See tg3.c for a real world example of how to use <function>mmiowb
+	</function>
+      </para>
+
+      <para>
+	PCI ordering rules also guarantee that PIO read responses arrive
+	after any outstanding DMA writes from that bus, since for some devices
+	the result of a <function>readb</function> call may signal to the
+	driver that a DMA transaction is complete.  In many cases, however,
+	the driver may want to indicate that the next
+	<function>readb</function> call has no relation to any previous DMA
+	writes performed by the device.  The driver can use
+	<function>readb_relaxed</function> for these cases, although only
+	some platforms will honor the relaxed semantics.  Using the relaxed
+	read functions will provide significant performance benefits on
+	platforms that support it.  The qla2xxx driver provides examples
+	of how to use <function>readX_relaxed</function>.  In many cases,
+	a majority of the driver's <function>readX</function> calls can
+	safely be converted to <function>readX_relaxed</function> calls, since
+	only a few will indicate or depend on DMA completion.
+      </para>
+    </sect1>
+
+    <sect1>
+      <title>ISA legacy functions</title>
+      <para>
+	On older kernels (2.2 and earlier) the ISA bus could be read or
+	written with these functions and without ioremap being used. This is
+	no longer true in Linux 2.4. A set of equivalent functions exist for
+	easy legacy driver porting. The functions available are prefixed
+	with 'isa_' and are <function>isa_readb</function>,
+	<function>isa_writeb</function>, <function>isa_readw</function>, 
+	<function>isa_writew</function>, <function>isa_readl</function>,
+	<function>isa_writel</function>, <function>isa_memcpy_fromio</function>
+	and <function>isa_memcpy_toio</function>
+      </para>
+      <para>
+	These functions should not be used in new drivers, and will
+	eventually be going away.
+      </para>
+    </sect1>
+
+  </chapter>
+
+  <chapter>
+    <title>Port Space Accesses</title>
+    <sect1>
+      <title>Port Space Explained</title>
+
+      <para>
+	Another form of IO commonly supported is Port Space.  This is a
+	range of addresses separate to the normal memory address space.
+	Access to these addresses is generally not as fast as accesses
+	to the memory mapped addresses, and it also has a potentially
+	smaller address space.
+      </para>
+
+      <para>
+	Unlike memory mapped IO, no preparation is required
+	to access port space.
+      </para>
+
+    </sect1>
+    <sect1>
+      <title>Accessing Port Space</title>
+      <para>
+	Accesses to this space are provided through a set of functions
+	which allow 8-bit, 16-bit and 32-bit accesses; also
+	known as byte, word and long.  These functions are
+	<function>inb</function>, <function>inw</function>,
+	<function>inl</function>, <function>outb</function>,
+	<function>outw</function> and <function>outl</function>.
+      </para>
+
+      <para>
+	Some variants are provided for these functions.  Some devices
+	require that accesses to their ports are slowed down.  This
+	functionality is provided by appending a <function>_p</function>
+	to the end of the function.  There are also equivalents to memcpy.
+	The <function>ins</function> and <function>outs</function>
+	functions copy bytes, words or longs to the given port.
+      </para>
+    </sect1>
+
+  </chapter>
+
+  <chapter id="pubfunctions">
+     <title>Public Functions Provided</title>
+!Einclude/asm-i386/io.h
+  </chapter>
+
+</book>

+ 752 - 0
Documentation/DocBook/gadget.tmpl

@@ -0,0 +1,752 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="USB-Gadget-API">
+  <bookinfo>
+    <title>USB Gadget API for Linux</title>
+    <date>20 August 2004</date>
+    <edition>20 August 2004</edition>
+  
+    <legalnotice>
+       <para>
+	 This documentation is free software; you can redistribute
+	 it and/or modify it under the terms of the GNU General Public
+	 License as published by the Free Software Foundation; either
+	 version 2 of the License, or (at your option) any later
+	 version.
+       </para>
+	  
+       <para>
+	 This program is distributed in the hope that it will be
+	 useful, but WITHOUT ANY WARRANTY; without even the implied
+	 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+	 See the GNU General Public License for more details.
+       </para>
+	  
+       <para>
+	 You should have received a copy of the GNU General Public
+	 License along with this program; if not, write to the Free
+	 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+	 MA 02111-1307 USA
+       </para>
+	  
+       <para>
+	 For more details see the file COPYING in the source
+	 distribution of Linux.
+       </para>
+    </legalnotice>
+    <copyright>
+      <year>2003-2004</year>
+      <holder>David Brownell</holder>
+    </copyright>
+
+    <author>
+      <firstname>David</firstname> 
+      <surname>Brownell</surname>
+      <affiliation>
+        <address><email>dbrownell@users.sourceforge.net</email></address>
+      </affiliation>
+    </author>
+  </bookinfo>
+
+<toc></toc>
+
+<chapter><title>Introduction</title>
+
+<para>This document presents a Linux-USB "Gadget"
+kernel mode
+API, for use within peripherals and other USB devices
+that embed Linux.
+It provides an overview of the API structure,
+and shows how that fits into a system development project.
+This is the first such API released on Linux to address
+a number of important problems, including: </para>
+
+<itemizedlist>
+    <listitem><para>Supports USB 2.0, for high speed devices which
+	can stream data at several dozen megabytes per second.
+	</para></listitem>
+    <listitem><para>Handles devices with dozens of endpoints just as
+	well as ones with just two fixed-function ones.  Gadget drivers
+	can be written so they're easy to port to new hardware.
+	</para></listitem>
+    <listitem><para>Flexible enough to expose more complex USB device
+	capabilities such as multiple configurations, multiple interfaces,
+	composite devices,
+	and alternate interface settings.
+	</para></listitem>
+    <listitem><para>USB "On-The-Go" (OTG) support, in conjunction
+	with updates to the Linux-USB host side.
+	</para></listitem>
+    <listitem><para>Sharing data structures and API models with the
+	Linux-USB host side API.  This helps the OTG support, and
+	looks forward to more-symmetric frameworks (where the same
+	I/O model is used by both host and device side drivers).
+	</para></listitem>
+    <listitem><para>Minimalist, so it's easier to support new device
+	controller hardware.  I/O processing doesn't imply large
+	demands for memory or CPU resources.
+	</para></listitem>
+</itemizedlist>
+
+
+<para>Most Linux developers will not be able to use this API, since they
+have USB "host" hardware in a PC, workstation, or server.
+Linux users with embedded systems are more likely to
+have USB peripheral hardware.
+To distinguish drivers running inside such hardware from the
+more familiar Linux "USB device drivers",
+which are host side proxies for the real USB devices,
+a different term is used:
+the drivers inside the peripherals are "USB gadget drivers".
+In USB protocol interactions, the device driver is the master
+(or "client driver")
+and the gadget driver is the slave (or "function driver").
+</para>
+
+<para>The gadget API resembles the host side Linux-USB API in that both
+use queues of request objects to package I/O buffers, and those requests
+may be submitted or canceled.
+They share common definitions for the standard USB
+<emphasis>Chapter 9</emphasis> messages, structures, and constants.
+Also, both APIs bind and unbind drivers to devices.
+The APIs differ in detail, since the host side's current
+URB framework exposes a number of implementation details
+and assumptions that are inappropriate for a gadget API.
+While the model for control transfers and configuration
+management is necessarily different (one side is a hardware-neutral master,
+the other is a hardware-aware slave), the endpoint I/0 API used here
+should also be usable for an overhead-reduced host side API.
+</para>
+
+</chapter>
+
+<chapter id="structure"><title>Structure of Gadget Drivers</title>
+
+<para>A system running inside a USB peripheral
+normally has at least three layers inside the kernel to handle
+USB protocol processing, and may have additional layers in
+user space code.
+The "gadget" API is used by the middle layer to interact
+with the lowest level (which directly handles hardware).
+</para>
+
+<para>In Linux, from the bottom up, these layers are:
+</para>
+
+<variablelist>
+
+    <varlistentry>
+        <term><emphasis>USB Controller Driver</emphasis></term>
+
+	<listitem>
+	<para>This is the lowest software level.
+	It is the only layer that talks to hardware,
+	through registers, fifos, dma, irqs, and the like.
+	The <filename>&lt;linux/usb_gadget.h&gt;</filename> API abstracts
+	the peripheral controller endpoint hardware.
+	That hardware is exposed through endpoint objects, which accept
+	streams of IN/OUT buffers, and through callbacks that interact
+	with gadget drivers.
+	Since normal USB devices only have one upstream
+	port, they only have one of these drivers.
+	The controller driver can support any number of different
+	gadget drivers, but only one of them can be used at a time.
+	</para>
+
+	<para>Examples of such controller hardware include
+	the PCI-based NetChip 2280 USB 2.0 high speed controller,
+	the SA-11x0 or PXA-25x UDC (found within many PDAs),
+	and a variety of other products.
+	</para>
+
+	</listitem></varlistentry>
+
+    <varlistentry>
+	<term><emphasis>Gadget Driver</emphasis></term>
+
+	<listitem>
+	<para>The lower boundary of this driver implements hardware-neutral
+	USB functions, using calls to the controller driver.
+	Because such hardware varies widely in capabilities and restrictions,
+	and is used in embedded environments where space is at a premium,
+	the gadget driver is often configured at compile time
+	to work with endpoints supported by one particular controller.
+	Gadget drivers may be portable to several different controllers,
+	using conditional compilation.
+	(Recent kernels substantially simplify the work involved in
+	supporting new hardware, by <emphasis>autoconfiguring</emphasis>
+	endpoints automatically for many bulk-oriented drivers.)
+	Gadget driver responsibilities include:
+	</para>
+	<itemizedlist>
+	    <listitem><para>handling setup requests (ep0 protocol responses)
+		possibly including class-specific functionality
+		</para></listitem>
+	    <listitem><para>returning configuration and string descriptors
+		</para></listitem>
+	    <listitem><para>(re)setting configurations and interface
+		altsettings, including enabling and configuring endpoints
+		</para></listitem>
+	    <listitem><para>handling life cycle events, such as managing
+		bindings to hardware,
+		USB suspend/resume, remote wakeup,
+		and disconnection from the USB host.
+		</para></listitem>
+	    <listitem><para>managing IN and OUT transfers on all currently
+		enabled endpoints
+		</para></listitem>
+	</itemizedlist>
+
+	<para>
+	Such drivers may be modules of proprietary code, although
+	that approach is discouraged in the Linux community.
+	</para>
+	</listitem></varlistentry>
+
+    <varlistentry>
+	<term><emphasis>Upper Level</emphasis></term>
+
+	<listitem>
+	<para>Most gadget drivers have an upper boundary that connects
+	to some Linux driver or framework in Linux.
+	Through that boundary flows the data which the gadget driver
+	produces and/or consumes through protocol transfers over USB.
+	Examples include:
+	</para>
+	<itemizedlist>
+	    <listitem><para>user mode code, using generic (gadgetfs)
+	        or application specific files in
+		<filename>/dev</filename>
+		</para></listitem>
+	    <listitem><para>networking subsystem (for network gadgets,
+		like the CDC Ethernet Model gadget driver)
+		</para></listitem>
+	    <listitem><para>data capture drivers, perhaps video4Linux or
+		 a scanner driver; or test and measurement hardware.
+		 </para></listitem>
+	    <listitem><para>input subsystem (for HID gadgets)
+		</para></listitem>
+	    <listitem><para>sound subsystem (for audio gadgets)
+		</para></listitem>
+	    <listitem><para>file system (for PTP gadgets)
+		</para></listitem>
+	    <listitem><para>block i/o subsystem (for usb-storage gadgets)
+		</para></listitem>
+	    <listitem><para>... and more </para></listitem>
+	</itemizedlist>
+	</listitem></varlistentry>
+
+    <varlistentry>
+	<term><emphasis>Additional Layers</emphasis></term>
+
+	<listitem>
+	<para>Other layers may exist.
+	These could include kernel layers, such as network protocol stacks,
+	as well as user mode applications building on standard POSIX
+	system call APIs such as
+	<emphasis>open()</emphasis>, <emphasis>close()</emphasis>,
+	<emphasis>read()</emphasis> and <emphasis>write()</emphasis>.
+	On newer systems, POSIX Async I/O calls may be an option.
+	Such user mode code will not necessarily be subject to
+	the GNU General Public License (GPL).
+	</para>
+	</listitem></varlistentry>
+
+
+</variablelist>
+
+<para>OTG-capable systems will also need to include a standard Linux-USB
+host side stack,
+with <emphasis>usbcore</emphasis>,
+one or more <emphasis>Host Controller Drivers</emphasis> (HCDs),
+<emphasis>USB Device Drivers</emphasis> to support
+the OTG "Targeted Peripheral List",
+and so forth.
+There will also be an <emphasis>OTG Controller Driver</emphasis>,
+which is visible to gadget and device driver developers only indirectly.
+That helps the host and device side USB controllers implement the
+two new OTG protocols (HNP and SRP).
+Roles switch (host to peripheral, or vice versa) using HNP
+during USB suspend processing, and SRP can be viewed as a
+more battery-friendly kind of device wakeup protocol.
+</para>
+
+<para>Over time, reusable utilities are evolving to help make some
+gadget driver tasks simpler.
+For example, building configuration descriptors from vectors of
+descriptors for the configurations interfaces and endpoints is
+now automated, and many drivers now use autoconfiguration to
+choose hardware endpoints and initialize their descriptors.
+
+A potential example of particular interest
+is code implementing standard USB-IF protocols for
+HID, networking, storage, or audio classes.
+Some developers are interested in KDB or KGDB hooks, to let
+target hardware be remotely debugged.
+Most such USB protocol code doesn't need to be hardware-specific,
+any more than network protocols like X11, HTTP, or NFS are.
+Such gadget-side interface drivers should eventually be combined,
+to implement composite devices.
+</para>
+
+</chapter>
+
+
+<chapter id="api"><title>Kernel Mode Gadget API</title>
+
+<para>Gadget drivers declare themselves through a
+<emphasis>struct usb_gadget_driver</emphasis>, which is responsible for
+most parts of enumeration for a <emphasis>struct usb_gadget</emphasis>.
+The response to a set_configuration usually involves
+enabling one or more of the <emphasis>struct usb_ep</emphasis> objects
+exposed by the gadget, and submitting one or more
+<emphasis>struct usb_request</emphasis> buffers to transfer data.
+Understand those four data types, and their operations, and
+you will understand how this API works.
+</para> 
+
+<note><title>Incomplete Data Type Descriptions</title>
+
+<para>This documentation was prepared using the standard Linux
+kernel <filename>docproc</filename> tool, which turns text
+and in-code comments into SGML DocBook and then into usable
+formats such as HTML or PDF.
+Other than the "Chapter 9" data types, most of the significant
+data types and functions are described here.
+</para>
+
+<para>However, docproc does not understand all the C constructs
+that are used, so some relevant information is likely omitted from
+what you are reading.  
+One example of such information is endpoint autoconfiguration.
+You'll have to read the header file, and use example source
+code (such as that for "Gadget Zero"), to fully understand the API.
+</para>
+
+<para>The part of the API implementing some basic
+driver capabilities is specific to the version of the
+Linux kernel that's in use.
+The 2.6 kernel includes a <emphasis>driver model</emphasis>
+framework that has no analogue on earlier kernels;
+so those parts of the gadget API are not fully portable.
+(They are implemented on 2.4 kernels, but in a different way.)
+The driver model state is another part of this API that is
+ignored by the kerneldoc tools.
+</para>
+</note>
+
+<para>The core API does not expose
+every possible hardware feature, only the most widely available ones.
+There are significant hardware features, such as device-to-device DMA
+(without temporary storage in a memory buffer)
+that would be added using hardware-specific APIs.
+</para>
+
+<para>This API allows drivers to use conditional compilation to handle
+endpoint capabilities of different hardware, but doesn't require that.
+Hardware tends to have arbitrary restrictions, relating to
+transfer types, addressing, packet sizes, buffering, and availability.
+As a rule, such differences only matter for "endpoint zero" logic
+that handles device configuration and management.
+The API supports limited run-time
+detection of capabilities, through naming conventions for endpoints.
+Many drivers will be able to at least partially autoconfigure
+themselves.
+In particular, driver init sections will often have endpoint
+autoconfiguration logic that scans the hardware's list of endpoints
+to find ones matching the driver requirements
+(relying on those conventions), to eliminate some of the most
+common reasons for conditional compilation.
+</para>
+
+<para>Like the Linux-USB host side API, this API exposes
+the "chunky" nature of USB messages:  I/O requests are in terms
+of one or more "packets", and packet boundaries are visible to drivers.
+Compared to RS-232 serial protocols, USB resembles
+synchronous protocols like HDLC
+(N bytes per frame, multipoint addressing, host as the primary
+station and devices as secondary stations)
+more than asynchronous ones
+(tty style:  8 data bits per frame, no parity, one stop bit).
+So for example the controller drivers won't buffer
+two single byte writes into a single two-byte USB IN packet,
+although gadget drivers may do so when they implement
+protocols where packet boundaries (and "short packets")
+are not significant.
+</para>
+
+<sect1 id="lifecycle"><title>Driver Life Cycle</title>
+
+<para>Gadget drivers make endpoint I/O requests to hardware without
+needing to know many details of the hardware, but driver
+setup/configuration code needs to handle some differences.
+Use the API like this:
+</para>
+
+<orderedlist numeration='arabic'>
+
+<listitem><para>Register a driver for the particular device side
+usb controller hardware,
+such as the net2280 on PCI (USB 2.0),
+sa11x0 or pxa25x as found in Linux PDAs,
+and so on.
+At this point the device is logically in the USB ch9 initial state
+("attached"), drawing no power and not usable
+(since it does not yet support enumeration).
+Any host should not see the device, since it's not
+activated the data line pullup used by the host to
+detect a device, even if VBUS power is available.
+</para></listitem>
+
+<listitem><para>Register a gadget driver that implements some higher level
+device function.  That will then bind() to a usb_gadget, which
+activates the data line pullup sometime after detecting VBUS.
+</para></listitem>
+
+<listitem><para>The hardware driver can now start enumerating.
+The steps it handles are to accept USB power and set_address requests.
+Other steps are handled by the gadget driver.
+If the gadget driver module is unloaded before the host starts to
+enumerate, steps before step 7 are skipped.
+</para></listitem>
+
+<listitem><para>The gadget driver's setup() call returns usb descriptors,
+based both on what the bus interface hardware provides and on the
+functionality being implemented.
+That can involve alternate settings or configurations,
+unless the hardware prevents such operation.
+For OTG devices, each configuration descriptor includes
+an OTG descriptor.
+</para></listitem>
+
+<listitem><para>The gadget driver handles the last step of enumeration,
+when the USB host issues a set_configuration call.
+It enables all endpoints used in that configuration,
+with all interfaces in their default settings.
+That involves using a list of the hardware's endpoints, enabling each
+endpoint according to its descriptor.
+It may also involve using <function>usb_gadget_vbus_draw</function>
+to let more power be drawn from VBUS, as allowed by that configuration.
+For OTG devices, setting a configuration may also involve reporting
+HNP capabilities through a user interface.
+</para></listitem>
+
+<listitem><para>Do real work and perform data transfers, possibly involving
+changes to interface settings or switching to new configurations, until the
+device is disconnect()ed from the host.
+Queue any number of transfer requests to each endpoint.
+It may be suspended and resumed several times before being disconnected.
+On disconnect, the drivers go back to step 3 (above).
+</para></listitem>
+
+<listitem><para>When the gadget driver module is being unloaded,
+the driver unbind() callback is issued.  That lets the controller
+driver be unloaded.
+</para></listitem>
+
+</orderedlist>
+
+<para>Drivers will normally be arranged so that just loading the
+gadget driver module (or statically linking it into a Linux kernel)
+allows the peripheral device to be enumerated, but some drivers
+will defer enumeration until some higher level component (like
+a user mode daemon) enables it.
+Note that at this lowest level there are no policies about how
+ep0 configuration logic is implemented,
+except that it should obey USB specifications.
+Such issues are in the domain of gadget drivers,
+including knowing about implementation constraints
+imposed by some USB controllers
+or understanding that composite devices might happen to
+be built by integrating reusable components.
+</para>
+
+<para>Note that the lifecycle above can be slightly different
+for OTG devices.
+Other than providing an additional OTG descriptor in each
+configuration, only the HNP-related differences are particularly
+visible to driver code.
+They involve reporting requirements during the SET_CONFIGURATION
+request, and the option to invoke HNP during some suspend callbacks.
+Also, SRP changes the semantics of
+<function>usb_gadget_wakeup</function>
+slightly.
+</para>
+
+</sect1>
+
+<sect1 id="ch9"><title>USB 2.0 Chapter 9 Types and Constants</title>
+
+<para>Gadget drivers
+rely on common USB structures and constants
+defined in the
+<filename>&lt;linux/usb_ch9.h&gt;</filename>
+header file, which is standard in Linux 2.6 kernels.
+These are the same types and constants used by host
+side drivers (and usbcore).
+</para>
+
+!Iinclude/linux/usb_ch9.h
+</sect1>
+
+<sect1 id="core"><title>Core Objects and Methods</title>
+
+<para>These are declared in
+<filename>&lt;linux/usb_gadget.h&gt;</filename>,
+and are used by gadget drivers to interact with
+USB peripheral controller drivers.
+</para>
+
+	<!-- yeech, this is ugly in nsgmls PDF output.
+
+	     the PDF bookmark and refentry output nesting is wrong,
+	     and the member/argument documentation indents ugly.
+
+	     plus something (docproc?) adds whitespace before the
+	     descriptive paragraph text, so it can't line up right
+	     unless the explanations are trivial.
+	  -->
+
+!Iinclude/linux/usb_gadget.h
+</sect1>
+
+<sect1 id="utils"><title>Optional Utilities</title>
+
+<para>The core API is sufficient for writing a USB Gadget Driver,
+but some optional utilities are provided to simplify common tasks.
+These utilities include endpoint autoconfiguration.
+</para>
+
+!Edrivers/usb/gadget/usbstring.c
+!Edrivers/usb/gadget/config.c
+<!-- !Edrivers/usb/gadget/epautoconf.c -->
+</sect1>
+
+</chapter>
+
+<chapter id="controllers"><title>Peripheral Controller Drivers</title>
+
+<para>The first hardware supporting this API was the NetChip 2280
+controller, which supports USB 2.0 high speed and is based on PCI.
+This is the <filename>net2280</filename> driver module.
+The driver supports Linux kernel versions 2.4 and 2.6;
+contact NetChip Technologies for development boards and product
+information.
+</para> 
+
+<para>Other hardware working in the "gadget" framework includes:
+Intel's PXA 25x and IXP42x series processors
+(<filename>pxa2xx_udc</filename>),
+Toshiba TC86c001 "Goku-S" (<filename>goku_udc</filename>),
+Renesas SH7705/7727 (<filename>sh_udc</filename>),
+MediaQ 11xx (<filename>mq11xx_udc</filename>),
+Hynix HMS30C7202 (<filename>h7202_udc</filename>),
+National 9303/4 (<filename>n9604_udc</filename>),
+Texas Instruments OMAP (<filename>omap_udc</filename>),
+Sharp LH7A40x (<filename>lh7a40x_udc</filename>),
+and more.
+Most of those are full speed controllers.
+</para>
+
+<para>At this writing, there are people at work on drivers in
+this framework for several other USB device controllers,
+with plans to make many of them be widely available.
+</para>
+
+<!-- !Edrivers/usb/gadget/net2280.c -->
+
+<para>A partial USB simulator,
+the <filename>dummy_hcd</filename> driver, is available.
+It can act like a net2280, a pxa25x, or an sa11x0 in terms
+of available endpoints and device speeds; and it simulates
+control, bulk, and to some extent interrupt transfers.
+That lets you develop some parts of a gadget driver on a normal PC,
+without any special hardware, and perhaps with the assistance
+of tools such as GDB running with User Mode Linux.
+At least one person has expressed interest in adapting that
+approach, hooking it up to a simulator for a microcontroller.
+Such simulators can help debug subsystems where the runtime hardware
+is unfriendly to software development, or is not yet available.
+</para>
+
+<para>Support for other controllers is expected to be developed
+and contributed
+over time, as this driver framework evolves.
+</para>
+
+</chapter>
+
+<chapter id="gadget"><title>Gadget Drivers</title>
+
+<para>In addition to <emphasis>Gadget Zero</emphasis>
+(used primarily for testing and development with drivers
+for usb controller hardware), other gadget drivers exist.
+</para>
+
+<para>There's an <emphasis>ethernet</emphasis> gadget
+driver, which implements one of the most useful
+<emphasis>Communications Device Class</emphasis> (CDC) models.  
+One of the standards for cable modem interoperability even
+specifies the use of this ethernet model as one of two
+mandatory options.
+Gadgets using this code look to a USB host as if they're
+an Ethernet adapter.
+It provides access to a network where the gadget's CPU is one host,
+which could easily be bridging, routing, or firewalling
+access to other networks.
+Since some hardware can't fully implement the CDC Ethernet
+requirements, this driver also implements a "good parts only"
+subset of CDC Ethernet.
+(That subset doesn't advertise itself as CDC Ethernet,
+to avoid creating problems.)
+</para>
+
+<para>Support for Microsoft's <emphasis>RNDIS</emphasis>
+protocol has been contributed by Pengutronix and Auerswald GmbH.
+This is like CDC Ethernet, but it runs on more slightly USB hardware
+(but less than the CDC subset).
+However, its main claim to fame is being able to connect directly to
+recent versions of Windows, using drivers that Microsoft bundles
+and supports, making it much simpler to network with Windows.
+</para>
+
+<para>There is also support for user mode gadget drivers,
+using <emphasis>gadgetfs</emphasis>.
+This provides a <emphasis>User Mode API</emphasis> that presents
+each endpoint as a single file descriptor.  I/O is done using
+normal <emphasis>read()</emphasis> and <emphasis>read()</emphasis> calls.
+Familiar tools like GDB and pthreads can be used to
+develop and debug user mode drivers, so that once a robust
+controller driver is available many applications for it
+won't require new kernel mode software.
+Linux 2.6 <emphasis>Async I/O (AIO)</emphasis>
+support is available, so that user mode software
+can stream data with only slightly more overhead
+than a kernel driver.
+</para>
+
+<para>There's a USB Mass Storage class driver, which provides
+a different solution for interoperability with systems such
+as MS-Windows and MacOS.
+That <emphasis>File-backed Storage</emphasis> driver uses a
+file or block device as backing store for a drive,
+like the <filename>loop</filename> driver.
+The USB host uses the BBB, CB, or CBI versions of the mass
+storage class specification, using transparent SCSI commands
+to access the data from the backing store.
+</para>
+
+<para>There's a "serial line" driver, useful for TTY style
+operation over USB.
+The latest version of that driver supports CDC ACM style
+operation, like a USB modem, and so on most hardware it can
+interoperate easily with MS-Windows.
+One interesting use of that driver is in boot firmware (like a BIOS),
+which can sometimes use that model with very small systems without
+real serial lines.
+</para>
+
+<para>Support for other kinds of gadget is expected to
+be developed and contributed
+over time, as this driver framework evolves.
+</para>
+
+</chapter>
+
+<chapter id="otg"><title>USB On-The-GO (OTG)</title>
+
+<para>USB OTG support on Linux 2.6 was initially developed
+by Texas Instruments for
+<ulink url="http://www.omap.com">OMAP</ulink> 16xx and 17xx
+series processors.
+Other OTG systems should work in similar ways, but the
+hardware level details could be very different.
+</para> 
+
+<para>Systems need specialized hardware support to implement OTG,
+notably including a special <emphasis>Mini-AB</emphasis> jack
+and associated transciever to support <emphasis>Dual-Role</emphasis>
+operation:
+they can act either as a host, using the standard
+Linux-USB host side driver stack,
+or as a peripheral, using this "gadget" framework.
+To do that, the system software relies on small additions
+to those programming interfaces,
+and on a new internal component (here called an "OTG Controller")
+affecting which driver stack connects to the OTG port.
+In each role, the system can re-use the existing pool of
+hardware-neutral drivers, layered on top of the controller
+driver interfaces (<emphasis>usb_bus</emphasis> or
+<emphasis>usb_gadget</emphasis>).
+Such drivers need at most minor changes, and most of the calls
+added to support OTG can also benefit non-OTG products.
+</para>
+
+<itemizedlist>
+    <listitem><para>Gadget drivers test the <emphasis>is_otg</emphasis>
+	flag, and use it to determine whether or not to include
+	an OTG descriptor in each of their configurations.
+	</para></listitem>
+    <listitem><para>Gadget drivers may need changes to support the
+	two new OTG protocols, exposed in new gadget attributes
+	such as <emphasis>b_hnp_enable</emphasis> flag.
+	HNP support should be reported through a user interface
+	(two LEDs could suffice), and is triggered in some cases
+	when the host suspends the peripheral.
+	SRP support can be user-initiated just like remote wakeup,
+	probably by pressing the same button.
+	</para></listitem>
+    <listitem><para>On the host side, USB device drivers need
+	to be taught to trigger HNP at appropriate moments, using
+	<function>usb_suspend_device()</function>.
+	That also conserves battery power, which is useful even
+	for non-OTG configurations.
+	</para></listitem>
+    <listitem><para>Also on the host side, a driver must support the
+	OTG "Targeted Peripheral List".  That's just a whitelist,
+	used to reject peripherals not supported with a given
+	Linux OTG host.
+	<emphasis>This whitelist is product-specific;
+	each product must modify <filename>otg_whitelist.h</filename>
+	to match its interoperability specification.
+	</emphasis>
+	</para>
+	<para>Non-OTG Linux hosts, like PCs and workstations,
+	normally have some solution for adding drivers, so that
+	peripherals that aren't recognized can eventually be supported.
+	That approach is unreasonable for consumer products that may
+	never have their firmware upgraded, and where it's usually
+	unrealistic to expect traditional PC/workstation/server kinds
+	of support model to work.
+	For example, it's often impractical to change device firmware
+	once the product has been distributed, so driver bugs can't
+	normally be fixed if they're found after shipment.
+	</para></listitem>
+</itemizedlist>
+
+<para>
+Additional changes are needed below those hardware-neutral
+<emphasis>usb_bus</emphasis> and <emphasis>usb_gadget</emphasis>
+driver interfaces; those aren't discussed here in any detail.
+Those affect the hardware-specific code for each USB Host or Peripheral
+controller, and how the HCD initializes (since OTG can be active only
+on a single port).
+They also involve what may be called an <emphasis>OTG Controller
+Driver</emphasis>, managing the OTG transceiver and the OTG state
+machine logic as well as much of the root hub behavior for the
+OTG port.
+The OTG controller driver needs to activate and deactivate USB
+controllers depending on the relevant device role.
+Some related changes were needed inside usbcore, so that it
+can identify OTG-capable devices and respond appropriately
+to HNP or SRP protocols.
+</para> 
+
+</chapter>
+
+</book>
+<!--
+	vim:syntax=sgml:sw=4
+-->

+ 333 - 0
Documentation/DocBook/journal-api.tmpl

@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="LinuxJBDAPI">
+ <bookinfo>
+  <title>The Linux Journalling API</title>
+  <authorgroup>
+  <author>
+     <firstname>Roger</firstname>
+     <surname>Gammans</surname>
+     <affiliation>
+     <address>
+      <email>rgammans@computer-surgery.co.uk</email>
+     </address>
+    </affiliation>
+     </author> 
+  </authorgroup>
+  
+  <authorgroup>
+   <author>
+    <firstname>Stephen</firstname>
+    <surname>Tweedie</surname>
+    <affiliation>
+     <address>
+      <email>sct@redhat.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2002</year>
+   <holder>Roger Gammans</holder>
+  </copyright>
+
+<legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="Overview">
+     <title>Overview</title>
+  <sect1>
+     <title>Details</title>
+<para>
+The journalling layer is  easy to use. You need to 
+first of all create a journal_t data structure. There are
+two calls to do this dependent on how you decide to allocate the physical
+media on which the journal resides. The journal_init_inode() call 
+is for journals stored in filesystem inodes, or the journal_init_dev()
+call can be use for journal stored on a raw device (in a continuous range 
+of blocks). A journal_t is a typedef for a struct pointer, so when
+you are finally finished make sure you call journal_destroy() on it
+to free up any used kernel memory.
+</para>
+
+<para>
+Once you have got your journal_t object you need to 'mount' or load the journal
+file, unless of course you haven't initialised it yet - in which case you
+need to call journal_create().
+</para>
+
+<para>
+Most of the time however your journal file will already have been created, but
+before you load it you must call journal_wipe() to empty the journal file.
+Hang on, you say , what if the filesystem wasn't cleanly umount()'d . Well, it is the 
+job of the client file system to detect this and skip the call to journal_wipe().
+</para>
+
+<para>
+In either case the next call should be to journal_load() which prepares the
+journal file for use. Note that journal_wipe(..,0) calls journal_skip_recovery() 
+for you if it detects any outstanding transactions in the journal and similarly
+journal_load() will call journal_recover() if necessary.
+I would advise reading fs/ext3/super.c for examples on this stage.
+[RGG: Why is the journal_wipe() call necessary - doesn't this needlessly 
+complicate the API. Or isn't a good idea for the journal layer to hide 
+dirty mounts from the client fs]
+</para>
+
+<para>
+Now you can go ahead and start modifying the underlying 
+filesystem. Almost.
+</para>
+
+
+<para>
+
+You still need to actually journal your filesystem changes, this
+is done by wrapping them into transactions. Additionally you
+also need to wrap the modification of each of the the buffers
+with calls to the journal layer, so it knows what the modifications
+you are actually making are. To do this use  journal_start() which
+returns a transaction handle.
+</para>
+
+<para>
+journal_start()
+and its counterpart journal_stop(), which indicates the end of a transaction
+are nestable calls, so you can reenter a transaction if necessary,
+but remember you must call journal_stop() the same number of times as
+journal_start() before the transaction is completed (or more accurately
+leaves the the update phase). Ext3/VFS makes use of this feature to simplify 
+quota support.
+</para>
+
+<para>
+Inside each transaction you need to wrap the modifications to the
+individual buffers (blocks). Before you start to modify a buffer you
+need to call journal_get_{create,write,undo}_access() as appropriate,
+this allows the journalling layer to copy the unmodified data if it
+needs to. After all the buffer may be part of a previously uncommitted
+transaction. 
+At this point you are at last ready to modify a buffer, and once
+you are have done so you need to call journal_dirty_{meta,}data().
+Or if you've asked for access to a buffer you now know is now longer 
+required to be pushed back on the device you can call journal_forget()
+in much the same way as you might have used bforget() in the past.
+</para>
+
+<para>
+A journal_flush() may be called at any time to commit and checkpoint
+all your transactions.
+</para>
+
+<para>
+Then at umount time , in your put_super() (2.4) or write_super() (2.5)
+you can then call journal_destroy() to clean up your in-core journal object.
+</para>
+
+
+<para>
+Unfortunately there a couple of ways the journal layer can cause a deadlock.
+The first thing to note is that each task can only have
+a single outstanding transaction at any one time, remember nothing
+commits until the outermost journal_stop(). This means
+you must complete the transaction at the end of each file/inode/address
+etc. operation you perform, so that the journalling system isn't re-entered
+on another journal. Since transactions can't be nested/batched 
+across differing journals, and another filesystem other than
+yours (say ext3) may be modified in a later syscall.
+</para>
+
+<para>
+The second case to bear in mind is that journal_start() can 
+block if there isn't enough space in the journal for your transaction 
+(based on the passed nblocks param) - when it blocks it merely(!) needs to
+wait for transactions to complete and be committed from other tasks, 
+so essentially we are waiting for journal_stop(). So to avoid 
+deadlocks you must treat journal_start/stop() as if they
+were semaphores and include them in your semaphore ordering rules to prevent 
+deadlocks. Note that journal_extend() has similar blocking behaviour to
+journal_start() so you can deadlock here just as easily as on journal_start().
+</para>
+
+<para>
+Try to reserve the right number of blocks the first time. ;-). This will
+be the maximum number of blocks you are going to touch in this transaction.
+I advise having a look at at least ext3_jbd.h to see the basis on which 
+ext3 uses to make these decisions.
+</para>
+
+<para>
+Another wriggle to watch out for is your on-disk block allocation strategy.
+why? Because, if you undo a delete, you need to ensure you haven't reused any
+of the freed blocks in a later transaction. One simple way of doing this
+is make sure any blocks you allocate only have checkpointed transactions
+listed against them. Ext3 does this in ext3_test_allocatable(). 
+</para>
+
+<para>
+Lock is also providing through journal_{un,}lock_updates(),
+ext3 uses this when it wants a window with a clean and stable fs for a moment.
+eg. 
+</para>
+
+<programlisting>
+
+	journal_lock_updates() //stop new stuff happening..
+	journal_flush()        // checkpoint everything.
+	..do stuff on stable fs
+	journal_unlock_updates() // carry on with filesystem use.
+</programlisting>
+
+<para>
+The opportunities for abuse and DOS attacks with this should be obvious,
+if you allow unprivileged userspace to trigger codepaths containing these
+calls.
+</para>
+
+<para>
+A new feature of jbd since 2.5.25 is commit callbacks with the new
+journal_callback_set() function you can now ask the journalling layer
+to call you back when the transaction is finally committed to disk, so that
+you can do some of your own management. The key to this is the journal_callback
+struct, this maintains the internal callback information but you can
+extend it like this:-
+</para>
+<programlisting>
+	struct  myfs_callback_s {
+		//Data structure element required by jbd..
+		struct journal_callback for_jbd;
+		// Stuff for myfs allocated together.
+		myfs_inode*    i_commited;
+	
+	}
+</programlisting>
+
+<para>
+this would be useful if you needed to know when data was committed to a 
+particular inode.
+</para>
+
+</sect1>
+
+<sect1>
+<title>Summary</title>
+<para>
+Using the journal is a matter of wrapping the different context changes,
+being each mount, each modification (transaction) and each changed buffer
+to tell the journalling layer about them.
+</para>
+
+<para>
+Here is a some pseudo code to give you an idea of how it works, as
+an example.
+</para>
+
+<programlisting>
+  journal_t* my_jnrl = journal_create();
+  journal_init_{dev,inode}(jnrl,...)
+  if (clean) journal_wipe();
+  journal_load();
+
+   foreach(transaction) { /*transactions must be 
+                            completed before
+                            a syscall returns to 
+                            userspace*/
+
+          handle_t * xct=journal_start(my_jnrl);
+          foreach(bh) {
+                journal_get_{create,write,undo}_access(xact,bh);
+                if ( myfs_modify(bh) ) { /* returns true 
+                                        if makes changes */
+                           journal_dirty_{meta,}data(xact,bh);
+                } else {
+                           journal_forget(bh);
+                }
+          }
+          journal_stop(xct);
+   }
+   journal_destroy(my_jrnl);
+</programlisting>
+</sect1>
+
+</chapter>
+
+  <chapter id="adt">
+     <title>Data Types</title>
+     <para>	
+	The journalling layer uses typedefs to 'hide' the concrete definitions
+	of the structures used. As a client of the JBD layer you can
+	just rely on the using the pointer as a magic cookie  of some sort.
+	
+	Obviously the hiding is not enforced as this is 'C'.
+	</para>
+	<sect1><title>Structures</title>
+!Iinclude/linux/jbd.h
+	</sect1>
+</chapter>
+
+  <chapter id="calls">
+     <title>Functions</title>
+     <para>	
+	The functions here are split into two groups those that
+	affect a journal as a whole, and those which are used to
+	manage transactions
+</para>
+	<sect1><title>Journal Level</title>
+!Efs/jbd/journal.c
+!Efs/jbd/recovery.c
+	</sect1>
+	<sect1><title>Transasction Level</title>
+!Efs/jbd/transaction.c	
+	</sect1>
+</chapter>
+<chapter>
+     <title>See also</title>
+	<para>
+	<citation>
+	   <ulink url="ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/journal-design.ps.gz">
+	   	Journaling the Linux ext2fs Filesystem,LinuxExpo 98, Stephen Tweedie
+	   </ulink>
+	   </citation>
+	   </para>
+	   <para>
+	   <citation>
+	   <ulink url="http://olstrans.sourceforge.net/release/OLS2000-ext3/OLS2000-ext3.html">
+	   	Ext3 Journalling FileSystem , OLS 2000, Dr. Stephen Tweedie
+	   </ulink>
+	   </citation>
+	   </para>
+</chapter>
+
+</book>

+ 342 - 0
Documentation/DocBook/kernel-api.tmpl

@@ -0,0 +1,342 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="LinuxKernelAPI">
+ <bookinfo>
+  <title>The Linux Kernel API</title>
+  
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="Basics">
+     <title>Driver Basics</title>
+     <sect1><title>Driver Entry and Exit points</title>
+!Iinclude/linux/init.h
+     </sect1>
+
+     <sect1><title>Atomic and pointer manipulation</title>
+!Iinclude/asm-i386/atomic.h
+!Iinclude/asm-i386/unaligned.h
+     </sect1>
+
+<!-- FIXME:
+  kernel/sched.c has no docs, which stuffs up the sgml.  Comment
+  out until somebody adds docs.  KAO
+     <sect1><title>Delaying, scheduling, and timer routines</title>
+X!Ekernel/sched.c
+     </sect1>
+KAO -->
+  </chapter>
+
+  <chapter id="adt">
+     <title>Data Types</title>
+     <sect1><title>Doubly Linked Lists</title>
+!Iinclude/linux/list.h
+     </sect1>
+  </chapter>
+
+  <chapter id="libc">
+     <title>Basic C Library Functions</title>
+
+     <para>
+       When writing drivers, you cannot in general use routines which are
+       from the C Library.  Some of the functions have been found generally
+       useful and they are listed below.  The behaviour of these functions
+       may vary slightly from those defined by ANSI, and these deviations
+       are noted in the text.
+     </para>
+
+     <sect1><title>String Conversions</title>
+!Ilib/vsprintf.c
+!Elib/vsprintf.c
+     </sect1>
+     <sect1><title>String Manipulation</title>
+!Ilib/string.c
+!Elib/string.c
+     </sect1>
+     <sect1><title>Bit Operations</title>
+!Iinclude/asm-i386/bitops.h
+     </sect1>
+  </chapter>
+
+  <chapter id="mm">
+     <title>Memory Management in Linux</title>
+     <sect1><title>The Slab Cache</title>
+!Emm/slab.c
+     </sect1>
+     <sect1><title>User Space Memory Access</title>
+!Iinclude/asm-i386/uaccess.h
+!Iarch/i386/lib/usercopy.c
+     </sect1>
+  </chapter>
+
+  <chapter id="kfifo">
+     <title>FIFO Buffer</title>
+     <sect1><title>kfifo interface</title>
+!Iinclude/linux/kfifo.h
+!Ekernel/kfifo.c
+     </sect1>
+  </chapter>
+
+  <chapter id="proc">
+     <title>The proc filesystem</title>
+ 
+     <sect1><title>sysctl interface</title>
+!Ekernel/sysctl.c
+     </sect1>
+  </chapter>
+
+  <chapter id="debugfs">
+     <title>The debugfs filesystem</title>
+ 
+     <sect1><title>debugfs interface</title>
+!Efs/debugfs/inode.c
+!Efs/debugfs/file.c
+     </sect1>
+  </chapter>
+
+  <chapter id="vfs">
+     <title>The Linux VFS</title>
+     <sect1><title>The Directory Cache</title>
+!Efs/dcache.c
+!Iinclude/linux/dcache.h
+     </sect1>
+     <sect1><title>Inode Handling</title>
+!Efs/inode.c
+!Efs/bad_inode.c
+     </sect1>
+     <sect1><title>Registration and Superblocks</title>
+!Efs/super.c
+     </sect1>
+     <sect1><title>File Locks</title>
+!Efs/locks.c
+!Ifs/locks.c
+     </sect1>
+  </chapter>
+
+  <chapter id="netcore">
+     <title>Linux Networking</title>
+     <sect1><title>Socket Buffer Functions</title>
+!Iinclude/linux/skbuff.h
+!Enet/core/skbuff.c
+     </sect1>
+     <sect1><title>Socket Filter</title>
+!Enet/core/filter.c
+     </sect1>
+     <sect1><title>Generic Network Statistics</title>
+!Iinclude/linux/gen_stats.h
+!Enet/core/gen_stats.c
+!Enet/core/gen_estimator.c
+     </sect1>
+  </chapter>
+
+  <chapter id="netdev">
+     <title>Network device support</title>
+     <sect1><title>Driver Support</title>
+!Enet/core/dev.c
+     </sect1>
+     <sect1><title>8390 Based Network Cards</title>
+!Edrivers/net/8390.c
+     </sect1>
+     <sect1><title>Synchronous PPP</title>
+!Edrivers/net/wan/syncppp.c
+     </sect1>
+  </chapter>
+
+  <chapter id="modload">
+     <title>Module Support</title>
+     <sect1><title>Module Loading</title>
+!Ekernel/kmod.c
+     </sect1>
+     <sect1><title>Inter Module support</title>
+        <para>
+           Refer to the file kernel/module.c for more information.
+        </para>
+<!-- FIXME: Removed for now since no structured comments in source
+X!Ekernel/module.c
+-->
+     </sect1>
+  </chapter>
+
+  <chapter id="hardware">
+     <title>Hardware Interfaces</title>
+     <sect1><title>Interrupt Handling</title>
+!Iarch/i386/kernel/irq.c
+     </sect1>
+
+     <sect1><title>MTRR Handling</title>
+!Earch/i386/kernel/cpu/mtrr/main.c
+     </sect1>
+     <sect1><title>PCI Support Library</title>
+!Edrivers/pci/pci.c
+     </sect1>
+     <sect1><title>PCI Hotplug Support Library</title>
+!Edrivers/pci/hotplug/pci_hotplug_core.c
+     </sect1>
+     <sect1><title>MCA Architecture</title>
+	<sect2><title>MCA Device Functions</title>
+           <para>
+              Refer to the file arch/i386/kernel/mca.c for more information.
+           </para>
+<!-- FIXME: Removed for now since no structured comments in source
+X!Earch/i386/kernel/mca.c
+-->
+	</sect2>
+	<sect2><title>MCA Bus DMA</title>
+!Iinclude/asm-i386/mca_dma.h
+	</sect2>
+     </sect1>
+  </chapter>
+
+  <chapter id="devfs">
+     <title>The Device File System</title>
+!Efs/devfs/base.c
+  </chapter>
+
+  <chapter id="security">
+     <title>Security Framework</title>
+!Esecurity/security.c
+  </chapter>
+
+  <chapter id="pmfuncs">
+     <title>Power Management</title>
+!Ekernel/power/pm.c
+  </chapter>
+
+  <chapter id="blkdev">
+     <title>Block Devices</title>
+!Edrivers/block/ll_rw_blk.c
+  </chapter>
+
+  <chapter id="miscdev">
+     <title>Miscellaneous Devices</title>
+!Edrivers/char/misc.c
+  </chapter>
+
+  <chapter id="viddev">
+     <title>Video4Linux</title>
+!Edrivers/media/video/videodev.c
+  </chapter>
+
+  <chapter id="snddev">
+     <title>Sound Devices</title>
+!Esound/sound_core.c
+<!-- FIXME: Removed for now since no structured comments in source
+X!Isound/sound_firmware.c
+-->
+  </chapter>
+
+  <chapter id="uart16x50">
+     <title>16x50 UART Driver</title>
+!Edrivers/serial/serial_core.c
+!Edrivers/serial/8250.c
+  </chapter>
+
+  <chapter id="z85230">
+     <title>Z85230 Support Library</title>
+!Edrivers/net/wan/z85230.c
+  </chapter>
+
+  <chapter id="fbdev">
+     <title>Frame Buffer Library</title>
+
+     <para>
+       The frame buffer drivers depend heavily on four data structures.  
+       These structures are declared in include/linux/fb.h.  They are 
+       fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs. 
+       The last three can be made available to and from userland. 
+     </para>
+
+     <para>
+       fb_info defines the current state of a particular video card. 
+       Inside fb_info, there exists a fb_ops structure which is a 
+       collection of needed functions to make fbdev and fbcon work.
+       fb_info is only visible to the kernel.
+     </para>
+
+     <para>
+       fb_var_screeninfo is used to describe the features of a video card 
+       that are user defined.  With fb_var_screeninfo, things such as
+       depth and the resolution may be defined.
+     </para>
+
+     <para>
+       The next structure is fb_fix_screeninfo. This defines the 
+       properties of a card that are created when a mode is set and can't 
+       be changed otherwise.  A good example of this is the start of the 
+       frame buffer memory.  This "locks" the address of the frame buffer
+       memory, so that it cannot be changed or moved.
+     </para>
+
+     <para>
+       The last structure is fb_monospecs. In the old API, there was 
+       little importance for fb_monospecs. This allowed for forbidden things 
+       such as setting a mode of 800x600 on a fix frequency monitor. With 
+       the new API, fb_monospecs prevents such things, and if used 
+       correctly, can prevent a monitor from being cooked.  fb_monospecs
+       will not be useful until kernels 2.5.x.
+     </para>
+
+     <sect1><title>Frame Buffer Memory</title>
+!Edrivers/video/fbmem.c
+     </sect1>
+     <sect1><title>Frame Buffer Console</title>
+!Edrivers/video/console/fbcon.c
+     </sect1>
+     <sect1><title>Frame Buffer Colormap</title>
+!Edrivers/video/fbcmap.c
+     </sect1>
+<!-- FIXME:
+  drivers/video/fbgen.c has no docs, which stuffs up the sgml.  Comment
+  out until somebody adds docs.  KAO
+     <sect1><title>Frame Buffer Generic Functions</title>
+X!Idrivers/video/fbgen.c
+     </sect1>
+KAO -->
+     <sect1><title>Frame Buffer Video Mode Database</title>
+!Idrivers/video/modedb.c
+!Edrivers/video/modedb.c
+     </sect1>
+     <sect1><title>Frame Buffer Macintosh Video Mode Database</title>
+!Idrivers/video/macmodes.c
+     </sect1>
+     <sect1><title>Frame Buffer Fonts</title>
+        <para>
+           Refer to the file drivers/video/console/fonts.c for more information.
+        </para>
+<!-- FIXME: Removed for now since no structured comments in source
+X!Idrivers/video/console/fonts.c
+-->
+     </sect1>
+  </chapter>
+</book>

+ 1349 - 0
Documentation/DocBook/kernel-hacking.tmpl

@@ -0,0 +1,1349 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="lk-hacking-guide">
+ <bookinfo>
+  <title>Unreliable Guide To Hacking The Linux Kernel</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Paul</firstname>
+    <othername>Rusty</othername>
+    <surname>Russell</surname>
+    <affiliation>
+     <address>
+      <email>rusty@rustcorp.com.au</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2001</year>
+   <holder>Rusty Russell</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+    This documentation is free software; you can redistribute
+    it and/or modify it under the terms of the GNU General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later
+    version.
+   </para>
+   
+   <para>
+    This program is distributed in the hope that it will be
+    useful, but WITHOUT ANY WARRANTY; without even the implied
+    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    See the GNU General Public License for more details.
+   </para>
+   
+   <para>
+    You should have received a copy of the GNU General Public
+    License along with this program; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+    MA 02111-1307 USA
+   </para>
+   
+   <para>
+    For more details see the file COPYING in the source
+    distribution of Linux.
+   </para>
+  </legalnotice>
+
+  <releaseinfo>
+   This is the first release of this document as part of the kernel tarball.
+  </releaseinfo>
+
+ </bookinfo>
+
+ <toc></toc>
+
+ <chapter id="introduction">
+  <title>Introduction</title>
+  <para>
+   Welcome, gentle reader, to Rusty's Unreliable Guide to Linux
+   Kernel Hacking.  This document describes the common routines and
+   general requirements for kernel code: its goal is to serve as a
+   primer for Linux kernel development for experienced C
+   programmers.  I avoid implementation details: that's what the
+   code is for, and I ignore whole tracts of useful routines.
+  </para>
+  <para>
+   Before you read this, please understand that I never wanted to
+   write this document, being grossly under-qualified, but I always
+   wanted to read it, and this was the only way.  I hope it will
+   grow into a compendium of best practice, common starting points
+   and random information.
+  </para>
+ </chapter>
+
+ <chapter id="basic-players">
+  <title>The Players</title>
+
+  <para>
+   At any time each of the CPUs in a system can be:
+  </para>
+
+  <itemizedlist>
+   <listitem>
+    <para>
+     not associated with any process, serving a hardware interrupt;
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     not associated with any process, serving a softirq, tasklet or bh;
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     running in kernel space, associated with a process;
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     running a process in user space.
+    </para>
+   </listitem>
+  </itemizedlist>
+
+  <para>
+   There is a strict ordering between these: other than the last
+   category (userspace) each can only be pre-empted by those above.
+   For example, while a softirq is running on a CPU, no other
+   softirq will pre-empt it, but a hardware interrupt can.  However,
+   any other CPUs in the system execute independently.
+  </para>
+
+  <para>
+   We'll see a number of ways that the user context can block
+   interrupts, to become truly non-preemptable.
+  </para>
+  
+  <sect1 id="basics-usercontext">
+   <title>User Context</title>
+
+   <para>
+    User context is when you are coming in from a system call or
+    other trap: you can sleep, and you own the CPU (except for
+    interrupts) until you call <function>schedule()</function>.  
+    In other words, user context (unlike userspace) is not pre-emptable.
+   </para>
+
+   <note>
+    <para>
+     You are always in user context on module load and unload,
+     and on operations on the block device layer.
+    </para>
+   </note>
+
+   <para>
+    In user context, the <varname>current</varname> pointer (indicating 
+    the task we are currently executing) is valid, and
+    <function>in_interrupt()</function>
+    (<filename>include/linux/interrupt.h</filename>) is <returnvalue>false
+    </returnvalue>.  
+   </para>
+
+   <caution>
+    <para>
+     Beware that if you have interrupts or bottom halves disabled 
+     (see below), <function>in_interrupt()</function> will return a 
+     false positive.
+    </para>
+   </caution>
+  </sect1>
+
+  <sect1 id="basics-hardirqs">
+   <title>Hardware Interrupts (Hard IRQs)</title>
+
+   <para>
+    Timer ticks, <hardware>network cards</hardware> and 
+    <hardware>keyboard</hardware> are examples of real
+    hardware which produce interrupts at any time.  The kernel runs
+    interrupt handlers, which services the hardware.  The kernel
+    guarantees that this handler is never re-entered: if another
+    interrupt arrives, it is queued (or dropped).  Because it
+    disables interrupts, this handler has to be fast: frequently it
+    simply acknowledges the interrupt, marks a `software interrupt'
+    for execution and exits.
+   </para>
+
+   <para>
+    You can tell you are in a hardware interrupt, because 
+    <function>in_irq()</function> returns <returnvalue>true</returnvalue>.  
+   </para>
+   <caution>
+    <para>
+     Beware that this will return a false positive if interrupts are disabled 
+     (see below).
+    </para>
+   </caution>
+  </sect1>
+
+  <sect1 id="basics-softirqs">
+   <title>Software Interrupt Context: Bottom Halves, Tasklets, softirqs</title>
+
+   <para>
+    Whenever a system call is about to return to userspace, or a
+    hardware interrupt handler exits, any `software interrupts'
+    which are marked pending (usually by hardware interrupts) are
+    run (<filename>kernel/softirq.c</filename>).
+   </para>
+
+   <para>
+    Much of the real interrupt handling work is done here.  Early in
+    the transition to <acronym>SMP</acronym>, there were only `bottom 
+    halves' (BHs), which didn't take advantage of multiple CPUs.  Shortly 
+    after we switched from wind-up computers made of match-sticks and snot,
+    we abandoned this limitation.
+   </para>
+
+   <para>
+    <filename class="headerfile">include/linux/interrupt.h</filename> lists the
+    different BH's.  No matter how many CPUs you have, no two BHs will run at 
+    the same time. This made the transition to SMP simpler, but sucks hard for
+    scalable performance.  A very important bottom half is the timer
+    BH (<filename class="headerfile">include/linux/timer.h</filename>): you
+    can register to have it call functions for you in a given length of time.
+   </para>
+
+   <para>
+    2.3.43 introduced softirqs, and re-implemented the (now
+    deprecated) BHs underneath them.  Softirqs are fully-SMP
+    versions of BHs: they can run on as many CPUs at once as
+    required.  This means they need to deal with any races in shared
+    data using their own locks.  A bitmask is used to keep track of
+    which are enabled, so the 32 available softirqs should not be
+    used up lightly.  (<emphasis>Yes</emphasis>, people will
+    notice).
+   </para>
+
+   <para>
+    tasklets (<filename class="headerfile">include/linux/interrupt.h</filename>)
+    are like softirqs, except they are dynamically-registrable (meaning you 
+    can have as many as you want), and they also guarantee that any tasklet 
+    will only run on one CPU at any time, although different tasklets can 
+    run simultaneously (unlike different BHs).  
+   </para>
+   <caution>
+    <para>
+     The name `tasklet' is misleading: they have nothing to do with `tasks', 
+     and probably more to do with some bad vodka Alexey Kuznetsov had at the 
+     time.
+    </para>
+   </caution>
+
+   <para>
+    You can tell you are in a softirq (or bottom half, or tasklet)
+    using the <function>in_softirq()</function> macro 
+    (<filename class="headerfile">include/linux/interrupt.h</filename>).
+   </para>
+   <caution>
+    <para>
+     Beware that this will return a false positive if a bh lock (see below)
+     is held.
+    </para>
+   </caution>
+  </sect1>
+ </chapter>
+
+ <chapter id="basic-rules">
+  <title>Some Basic Rules</title>
+
+  <variablelist>
+   <varlistentry>
+    <term>No memory protection</term>
+    <listitem>
+     <para>
+      If you corrupt memory, whether in user context or
+      interrupt context, the whole machine will crash.  Are you
+      sure you can't do what you want in userspace?
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>No floating point or <acronym>MMX</acronym></term>
+    <listitem>
+     <para>
+      The <acronym>FPU</acronym> context is not saved; even in user
+      context the <acronym>FPU</acronym> state probably won't
+      correspond with the current process: you would mess with some
+      user process' <acronym>FPU</acronym> state.  If you really want
+      to do this, you would have to explicitly save/restore the full
+      <acronym>FPU</acronym> state (and avoid context switches).  It
+      is generally a bad idea; use fixed point arithmetic first.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>A rigid stack limit</term>
+    <listitem>
+     <para>
+      The kernel stack is about 6K in 2.2 (for most
+      architectures: it's about 14K on the Alpha), and shared
+      with interrupts so you can't use it all.  Avoid deep
+      recursion and huge local arrays on the stack (allocate
+      them dynamically instead).
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>The Linux kernel is portable</term>
+    <listitem>
+     <para>
+      Let's keep it that way.  Your code should be 64-bit clean,
+      and endian-independent.  You should also minimize CPU
+      specific stuff, e.g. inline assembly should be cleanly
+      encapsulated and minimized to ease porting.  Generally it
+      should be restricted to the architecture-dependent part of
+      the kernel tree.
+     </para>
+    </listitem>
+   </varlistentry>
+  </variablelist>
+ </chapter>
+
+ <chapter id="ioctls">
+  <title>ioctls: Not writing a new system call</title>
+
+  <para>
+   A system call generally looks like this
+  </para>
+
+  <programlisting>
+asmlinkage long sys_mycall(int arg)
+{
+        return 0; 
+}
+  </programlisting>
+
+  <para>
+   First, in most cases you don't want to create a new system call.
+   You create a character device and implement an appropriate ioctl
+   for it.  This is much more flexible than system calls, doesn't have
+   to be entered in every architecture's
+   <filename class="headerfile">include/asm/unistd.h</filename> and
+   <filename>arch/kernel/entry.S</filename> file, and is much more
+   likely to be accepted by Linus.
+  </para>
+
+  <para>
+   If all your routine does is read or write some parameter, consider
+   implementing a <function>sysctl</function> interface instead.
+  </para>
+
+  <para>
+   Inside the ioctl you're in user context to a process.  When a
+   error occurs you return a negated errno (see
+   <filename class="headerfile">include/linux/errno.h</filename>),
+   otherwise you return <returnvalue>0</returnvalue>.
+  </para>
+
+  <para>
+   After you slept you should check if a signal occurred: the
+   Unix/Linux way of handling signals is to temporarily exit the
+   system call with the <constant>-ERESTARTSYS</constant> error.  The
+   system call entry code will switch back to user context, process
+   the signal handler and then your system call will be restarted
+   (unless the user disabled that).  So you should be prepared to
+   process the restart, e.g. if you're in the middle of manipulating
+   some data structure.
+  </para>
+
+  <programlisting>
+if (signal_pending()) 
+        return -ERESTARTSYS;
+  </programlisting>
+
+  <para>
+   If you're doing longer computations: first think userspace. If you
+   <emphasis>really</emphasis> want to do it in kernel you should
+   regularly check if you need to give up the CPU (remember there is
+   cooperative multitasking per CPU).  Idiom:
+  </para>
+
+  <programlisting>
+cond_resched(); /* Will sleep */ 
+  </programlisting>
+
+  <para>
+   A short note on interface design: the UNIX system call motto is
+   "Provide mechanism not policy".
+  </para>
+ </chapter>
+
+ <chapter id="deadlock-recipes">
+  <title>Recipes for Deadlock</title>
+
+  <para>
+   You cannot call any routines which may sleep, unless:
+  </para>
+  <itemizedlist>
+   <listitem>
+    <para>
+     You are in user context.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     You do not own any spinlocks.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     You have interrupts enabled (actually, Andi Kleen says
+     that the scheduling code will enable them for you, but
+     that's probably not what you wanted).
+    </para>
+   </listitem>
+  </itemizedlist>
+
+  <para>
+   Note that some functions may sleep implicitly: common ones are
+   the user space access functions (*_user) and memory allocation
+   functions without <symbol>GFP_ATOMIC</symbol>.
+  </para>
+
+  <para>
+   You will eventually lock up your box if you break these rules.  
+  </para>
+
+  <para>
+   Really.
+  </para>
+ </chapter>
+
+ <chapter id="common-routines">
+  <title>Common Routines</title>
+
+  <sect1 id="routines-printk">
+   <title>
+    <function>printk()</function>
+    <filename class="headerfile">include/linux/kernel.h</filename>
+   </title>
+
+   <para>
+    <function>printk()</function> feeds kernel messages to the
+    console, dmesg, and the syslog daemon.  It is useful for debugging
+    and reporting errors, and can be used inside interrupt context,
+    but use with caution: a machine which has its console flooded with
+    printk messages is unusable.  It uses a format string mostly
+    compatible with ANSI C printf, and C string concatenation to give
+    it a first "priority" argument:
+   </para>
+
+   <programlisting>
+printk(KERN_INFO "i = %u\n", i);
+   </programlisting>
+
+   <para>
+    See <filename class="headerfile">include/linux/kernel.h</filename>;
+    for other KERN_ values; these are interpreted by syslog as the
+    level.  Special case: for printing an IP address use
+   </para>
+
+   <programlisting>
+__u32 ipaddress;
+printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
+   </programlisting>
+
+   <para>
+    <function>printk()</function> internally uses a 1K buffer and does
+    not catch overruns.  Make sure that will be enough.
+   </para>
+
+   <note>
+    <para>
+     You will know when you are a real kernel hacker
+     when you start typoing printf as printk in your user programs :)
+    </para>
+   </note>
+
+   <!--- From the Lions book reader department --> 
+
+   <note>
+    <para>
+     Another sidenote: the original Unix Version 6 sources had a
+     comment on top of its printf function: "Printf should not be
+     used for chit-chat".  You should follow that advice.
+    </para>
+   </note>
+  </sect1>
+
+  <sect1 id="routines-copy">
+   <title>
+    <function>copy_[to/from]_user()</function>
+    /
+    <function>get_user()</function>
+    /
+    <function>put_user()</function>
+    <filename class="headerfile">include/asm/uaccess.h</filename>
+   </title>  
+
+   <para>
+    <emphasis>[SLEEPS]</emphasis>
+   </para>
+
+   <para>
+    <function>put_user()</function> and <function>get_user()</function>
+    are used to get and put single values (such as an int, char, or
+    long) from and to userspace.  A pointer into userspace should
+    never be simply dereferenced: data should be copied using these
+    routines.  Both return <constant>-EFAULT</constant> or 0.
+   </para>
+   <para>
+    <function>copy_to_user()</function> and
+    <function>copy_from_user()</function> are more general: they copy
+    an arbitrary amount of data to and from userspace.
+    <caution>
+     <para>
+      Unlike <function>put_user()</function> and
+      <function>get_user()</function>, they return the amount of
+      uncopied data (ie. <returnvalue>0</returnvalue> still means
+      success).
+     </para>
+    </caution>
+    [Yes, this moronic interface makes me cringe.  Please submit a
+    patch and become my hero --RR.]
+   </para>
+   <para>
+    The functions may sleep implicitly. This should never be called
+    outside user context (it makes no sense), with interrupts
+    disabled, or a spinlock held.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-kmalloc">
+   <title><function>kmalloc()</function>/<function>kfree()</function>
+    <filename class="headerfile">include/linux/slab.h</filename></title>
+
+   <para>
+    <emphasis>[MAY SLEEP: SEE BELOW]</emphasis>
+   </para>
+
+   <para>
+    These routines are used to dynamically request pointer-aligned
+    chunks of memory, like malloc and free do in userspace, but
+    <function>kmalloc()</function> takes an extra flag word.
+    Important values:
+   </para>
+
+   <variablelist>
+    <varlistentry>
+     <term>
+      <constant>
+       GFP_KERNEL
+      </constant>
+     </term>
+     <listitem>
+      <para>
+       May sleep and swap to free memory. Only allowed in user
+       context, but is the most reliable way to allocate memory.
+      </para>
+     </listitem>
+    </varlistentry>
+    
+    <varlistentry>
+     <term>
+      <constant>
+       GFP_ATOMIC
+      </constant>
+     </term>
+     <listitem>
+      <para>
+       Don't sleep. Less reliable than <constant>GFP_KERNEL</constant>,
+       but may be called from interrupt context. You should
+       <emphasis>really</emphasis> have a good out-of-memory
+       error-handling strategy.
+      </para>
+     </listitem>
+    </varlistentry>
+    
+    <varlistentry>
+     <term>
+      <constant>
+       GFP_DMA
+      </constant>
+     </term>
+     <listitem>
+      <para>
+       Allocate ISA DMA lower than 16MB. If you don't know what that
+       is you don't need it.  Very unreliable.
+      </para>
+     </listitem>
+    </varlistentry>
+   </variablelist>
+
+   <para>
+    If you see a <errorname>kmem_grow: Called nonatomically from int
+    </errorname> warning message you called a memory allocation function
+    from interrupt context without <constant>GFP_ATOMIC</constant>.
+    You should really fix that.  Run, don't walk.
+   </para>
+
+   <para>
+    If you are allocating at least <constant>PAGE_SIZE</constant>
+    (<filename class="headerfile">include/asm/page.h</filename>) bytes,
+    consider using <function>__get_free_pages()</function>
+
+    (<filename class="headerfile">include/linux/mm.h</filename>).  It
+    takes an order argument (0 for page sized, 1 for double page, 2
+    for four pages etc.) and the same memory priority flag word as
+    above.
+   </para>
+
+   <para>
+    If you are allocating more than a page worth of bytes you can use
+    <function>vmalloc()</function>.  It'll allocate virtual memory in
+    the kernel map.  This block is not contiguous in physical memory,
+    but the <acronym>MMU</acronym> makes it look like it is for you
+    (so it'll only look contiguous to the CPUs, not to external device
+    drivers).  If you really need large physically contiguous memory
+    for some weird device, you have a problem: it is poorly supported
+    in Linux because after some time memory fragmentation in a running
+    kernel makes it hard.  The best way is to allocate the block early
+    in the boot process via the <function>alloc_bootmem()</function>
+    routine.
+   </para>
+
+   <para>
+    Before inventing your own cache of often-used objects consider
+    using a slab cache in
+    <filename class="headerfile">include/linux/slab.h</filename>
+   </para>
+  </sect1>
+
+  <sect1 id="routines-current">
+   <title><function>current</function>
+    <filename class="headerfile">include/asm/current.h</filename></title>
+
+   <para>
+    This global variable (really a macro) contains a pointer to
+    the current task structure, so is only valid in user context.
+    For example, when a process makes a system call, this will
+    point to the task structure of the calling process.  It is
+    <emphasis>not NULL</emphasis> in interrupt context.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-udelay">
+   <title><function>udelay()</function>/<function>mdelay()</function>
+     <filename class="headerfile">include/asm/delay.h</filename>
+     <filename class="headerfile">include/linux/delay.h</filename>
+   </title>
+
+   <para>
+    The <function>udelay()</function> function can be used for small pauses.
+    Do not use large values with <function>udelay()</function> as you risk
+    overflow - the helper function <function>mdelay()</function> is useful
+    here, or even consider <function>schedule_timeout()</function>.
+   </para> 
+  </sect1>
+ 
+  <sect1 id="routines-endian">
+   <title><function>cpu_to_be32()</function>/<function>be32_to_cpu()</function>/<function>cpu_to_le32()</function>/<function>le32_to_cpu()</function>
+     <filename class="headerfile">include/asm/byteorder.h</filename>
+   </title>
+
+   <para>
+    The <function>cpu_to_be32()</function> family (where the "32" can
+    be replaced by 64 or 16, and the "be" can be replaced by "le") are
+    the general way to do endian conversions in the kernel: they
+    return the converted value.  All variations supply the reverse as
+    well: <function>be32_to_cpu()</function>, etc.
+   </para>
+
+   <para>
+    There are two major variations of these functions: the pointer
+    variation, such as <function>cpu_to_be32p()</function>, which take
+    a pointer to the given type, and return the converted value.  The
+    other variation is the "in-situ" family, such as
+    <function>cpu_to_be32s()</function>, which convert value referred
+    to by the pointer, and return void.
+   </para> 
+  </sect1>
+
+  <sect1 id="routines-local-irqs">
+   <title><function>local_irq_save()</function>/<function>local_irq_restore()</function>
+    <filename class="headerfile">include/asm/system.h</filename>
+   </title>
+
+   <para>
+    These routines disable hard interrupts on the local CPU, and
+    restore them.  They are reentrant; saving the previous state in
+    their one <varname>unsigned long flags</varname> argument.  If you
+    know that interrupts are enabled, you can simply use
+    <function>local_irq_disable()</function> and
+    <function>local_irq_enable()</function>.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-softirqs">
+   <title><function>local_bh_disable()</function>/<function>local_bh_enable()</function>
+    <filename class="headerfile">include/linux/interrupt.h</filename></title>
+
+   <para>
+    These routines disable soft interrupts on the local CPU, and
+    restore them.  They are reentrant; if soft interrupts were
+    disabled before, they will still be disabled after this pair
+    of functions has been called.  They prevent softirqs, tasklets
+    and bottom halves from running on the current CPU.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-processorids">
+   <title><function>smp_processor_id</function>()
+    <filename class="headerfile">include/asm/smp.h</filename></title>
+   
+   <para>
+    <function>smp_processor_id()</function> returns the current
+    processor number, between 0 and <symbol>NR_CPUS</symbol> (the
+    maximum number of CPUs supported by Linux, currently 32).  These
+    values are not necessarily continuous.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-init">
+   <title><type>__init</type>/<type>__exit</type>/<type>__initdata</type>
+    <filename class="headerfile">include/linux/init.h</filename></title>
+
+   <para>
+    After boot, the kernel frees up a special section; functions
+    marked with <type>__init</type> and data structures marked with
+    <type>__initdata</type> are dropped after boot is complete (within
+    modules this directive is currently ignored).  <type>__exit</type>
+    is used to declare a function which is only required on exit: the
+    function will be dropped if this file is not compiled as a module.
+    See the header file for use. Note that it makes no sense for a function
+    marked with <type>__init</type> to be exported to modules with 
+    <function>EXPORT_SYMBOL()</function> - this will break.
+   </para>
+   <para>
+   Static data structures marked as <type>__initdata</type> must be initialised
+   (as opposed to ordinary static data which is zeroed BSS) and cannot be 
+   <type>const</type>.
+   </para> 
+
+  </sect1>
+
+  <sect1 id="routines-init-again">
+   <title><function>__initcall()</function>/<function>module_init()</function>
+    <filename class="headerfile">include/linux/init.h</filename></title>
+   <para>
+    Many parts of the kernel are well served as a module
+    (dynamically-loadable parts of the kernel).  Using the
+    <function>module_init()</function> and
+    <function>module_exit()</function> macros it is easy to write code
+    without #ifdefs which can operate both as a module or built into
+    the kernel.
+   </para>
+
+   <para>
+    The <function>module_init()</function> macro defines which
+    function is to be called at module insertion time (if the file is
+    compiled as a module), or at boot time: if the file is not
+    compiled as a module the <function>module_init()</function> macro
+    becomes equivalent to <function>__initcall()</function>, which
+    through linker magic ensures that the function is called on boot.
+   </para>
+
+   <para>
+    The function can return a negative error number to cause
+    module loading to fail (unfortunately, this has no effect if
+    the module is compiled into the kernel).  For modules, this is
+    called in user context, with interrupts enabled, and the
+    kernel lock held, so it can sleep.
+   </para>
+  </sect1>
+  
+  <sect1 id="routines-moduleexit">
+   <title> <function>module_exit()</function>
+    <filename class="headerfile">include/linux/init.h</filename> </title>
+
+   <para>
+    This macro defines the function to be called at module removal
+    time (or never, in the case of the file compiled into the
+    kernel).  It will only be called if the module usage count has
+    reached zero.  This function can also sleep, but cannot fail:
+    everything must be cleaned up by the time it returns.
+   </para>
+  </sect1>
+
+ <!-- add info on new-style module refcounting here -->
+ </chapter>
+
+ <chapter id="queues">
+  <title>Wait Queues
+   <filename class="headerfile">include/linux/wait.h</filename>
+  </title>
+  <para>
+   <emphasis>[SLEEPS]</emphasis>
+  </para>
+
+  <para>
+   A wait queue is used to wait for someone to wake you up when a
+   certain condition is true.  They must be used carefully to ensure
+   there is no race condition.  You declare a
+   <type>wait_queue_head_t</type>, and then processes which want to
+   wait for that condition declare a <type>wait_queue_t</type>
+   referring to themselves, and place that in the queue.
+  </para>
+
+  <sect1 id="queue-declaring">
+   <title>Declaring</title>
+   
+   <para>
+    You declare a <type>wait_queue_head_t</type> using the
+    <function>DECLARE_WAIT_QUEUE_HEAD()</function> macro, or using the
+    <function>init_waitqueue_head()</function> routine in your
+    initialization code.
+   </para>
+  </sect1>
+  
+  <sect1 id="queue-waitqueue">
+   <title>Queuing</title>
+   
+   <para>
+    Placing yourself in the waitqueue is fairly complex, because you
+    must put yourself in the queue before checking the condition.
+    There is a macro to do this:
+    <function>wait_event_interruptible()</function>
+
+    <filename class="headerfile">include/linux/sched.h</filename> The
+    first argument is the wait queue head, and the second is an
+    expression which is evaluated; the macro returns
+    <returnvalue>0</returnvalue> when this expression is true, or
+    <returnvalue>-ERESTARTSYS</returnvalue> if a signal is received.
+    The <function>wait_event()</function> version ignores signals.
+   </para>
+   <para>
+   Do not use the <function>sleep_on()</function> function family -
+   it is very easy to accidentally introduce races; almost certainly
+   one of the <function>wait_event()</function> family will do, or a
+   loop around <function>schedule_timeout()</function>. If you choose
+   to loop around <function>schedule_timeout()</function> remember
+   you must set the task state (with 
+   <function>set_current_state()</function>) on each iteration to avoid
+   busy-looping.
+   </para>
+ 
+  </sect1>
+
+  <sect1 id="queue-waking">
+   <title>Waking Up Queued Tasks</title>
+   
+   <para>
+    Call <function>wake_up()</function>
+
+    <filename class="headerfile">include/linux/sched.h</filename>;,
+    which will wake up every process in the queue.  The exception is
+    if one has <constant>TASK_EXCLUSIVE</constant> set, in which case
+    the remainder of the queue will not be woken.
+   </para>
+  </sect1>
+ </chapter>
+
+ <chapter id="atomic-ops">
+  <title>Atomic Operations</title>
+
+  <para>
+   Certain operations are guaranteed atomic on all platforms.  The
+   first class of operations work on <type>atomic_t</type>
+
+   <filename class="headerfile">include/asm/atomic.h</filename>; this
+   contains a signed integer (at least 24 bits long), and you must use
+   these functions to manipulate or read atomic_t variables.
+   <function>atomic_read()</function> and
+   <function>atomic_set()</function> get and set the counter,
+   <function>atomic_add()</function>,
+   <function>atomic_sub()</function>,
+   <function>atomic_inc()</function>,
+   <function>atomic_dec()</function>, and
+   <function>atomic_dec_and_test()</function> (returns
+   <returnvalue>true</returnvalue> if it was decremented to zero).
+  </para>
+
+  <para>
+   Yes.  It returns <returnvalue>true</returnvalue> (i.e. != 0) if the
+   atomic variable is zero.
+  </para>
+
+  <para>
+   Note that these functions are slower than normal arithmetic, and
+   so should not be used unnecessarily.  On some platforms they
+   are much slower, like 32-bit Sparc where they use a spinlock.
+  </para>
+
+  <para>
+   The second class of atomic operations is atomic bit operations on a
+   <type>long</type>, defined in
+
+   <filename class="headerfile">include/linux/bitops.h</filename>.  These
+   operations generally take a pointer to the bit pattern, and a bit
+   number: 0 is the least significant bit.
+   <function>set_bit()</function>, <function>clear_bit()</function>
+   and <function>change_bit()</function> set, clear, and flip the
+   given bit.  <function>test_and_set_bit()</function>,
+   <function>test_and_clear_bit()</function> and
+   <function>test_and_change_bit()</function> do the same thing,
+   except return true if the bit was previously set; these are
+   particularly useful for very simple locking.
+  </para>
+  
+  <para>
+   It is possible to call these operations with bit indices greater
+   than BITS_PER_LONG.  The resulting behavior is strange on big-endian
+   platforms though so it is a good idea not to do this.
+  </para>
+
+  <para>
+   Note that the order of bits depends on the architecture, and in
+   particular, the bitfield passed to these operations must be at
+   least as large as a <type>long</type>.
+  </para>
+ </chapter>
+
+ <chapter id="symbols">
+  <title>Symbols</title>
+
+  <para>
+   Within the kernel proper, the normal linking rules apply
+   (ie. unless a symbol is declared to be file scope with the
+   <type>static</type> keyword, it can be used anywhere in the
+   kernel).  However, for modules, a special exported symbol table is
+   kept which limits the entry points to the kernel proper.  Modules
+   can also export symbols.
+  </para>
+
+  <sect1 id="sym-exportsymbols">
+   <title><function>EXPORT_SYMBOL()</function>
+    <filename class="headerfile">include/linux/module.h</filename></title>
+
+   <para>
+    This is the classic method of exporting a symbol, and it works
+    for both modules and non-modules.  In the kernel all these
+    declarations are often bundled into a single file to help
+    genksyms (which searches source files for these declarations).
+    See the comment on genksyms and Makefiles below.
+   </para>
+  </sect1>
+
+  <sect1 id="sym-exportsymbols-gpl">
+   <title><function>EXPORT_SYMBOL_GPL()</function>
+    <filename class="headerfile">include/linux/module.h</filename></title>
+
+   <para>
+    Similar to <function>EXPORT_SYMBOL()</function> except that the
+    symbols exported by <function>EXPORT_SYMBOL_GPL()</function> can
+    only be seen by modules with a
+    <function>MODULE_LICENSE()</function> that specifies a GPL
+    compatible license.
+   </para>
+  </sect1>
+ </chapter>
+
+ <chapter id="conventions">
+  <title>Routines and Conventions</title>
+
+  <sect1 id="conventions-doublelinkedlist">
+   <title>Double-linked lists
+    <filename class="headerfile">include/linux/list.h</filename></title>
+
+   <para>
+    There are three sets of linked-list routines in the kernel
+    headers, but this one seems to be winning out (and Linus has
+    used it).  If you don't have some particular pressing need for
+    a single list, it's a good choice.  In fact, I don't care
+    whether it's a good choice or not, just use it so we can get
+    rid of the others.
+   </para>
+  </sect1>
+
+  <sect1 id="convention-returns">
+   <title>Return Conventions</title>
+
+   <para>
+    For code called in user context, it's very common to defy C
+    convention, and return <returnvalue>0</returnvalue> for success,
+    and a negative error number
+    (eg. <returnvalue>-EFAULT</returnvalue>) for failure.  This can be
+    unintuitive at first, but it's fairly widespread in the networking
+    code, for example.
+   </para>
+
+   <para>
+    The filesystem code uses <function>ERR_PTR()</function>
+
+    <filename class="headerfile">include/linux/fs.h</filename>; to
+    encode a negative error number into a pointer, and
+    <function>IS_ERR()</function> and <function>PTR_ERR()</function>
+    to get it back out again: avoids a separate pointer parameter for
+    the error number.  Icky, but in a good way.
+   </para>
+  </sect1>
+
+  <sect1 id="conventions-borkedcompile">
+   <title>Breaking Compilation</title>
+
+   <para>
+    Linus and the other developers sometimes change function or
+    structure names in development kernels; this is not done just to
+    keep everyone on their toes: it reflects a fundamental change
+    (eg. can no longer be called with interrupts on, or does extra
+    checks, or doesn't do checks which were caught before).  Usually
+    this is accompanied by a fairly complete note to the linux-kernel
+    mailing list; search the archive.  Simply doing a global replace
+    on the file usually makes things <emphasis>worse</emphasis>.
+   </para>
+  </sect1>
+
+  <sect1 id="conventions-initialising">
+   <title>Initializing structure members</title>
+
+   <para>
+    The preferred method of initializing structures is to use
+    designated initialisers, as defined by ISO C99, eg:
+   </para>
+   <programlisting>
+static struct block_device_operations opt_fops = {
+        .open               = opt_open,
+        .release            = opt_release,
+        .ioctl              = opt_ioctl,
+        .check_media_change = opt_media_change,
+};
+   </programlisting>
+   <para>
+    This makes it easy to grep for, and makes it clear which
+    structure fields are set.  You should do this because it looks
+    cool.
+   </para>
+  </sect1>
+
+  <sect1 id="conventions-gnu-extns">
+   <title>GNU Extensions</title>
+
+   <para>
+    GNU Extensions are explicitly allowed in the Linux kernel.
+    Note that some of the more complex ones are not very well
+    supported, due to lack of general use, but the following are
+    considered standard (see the GCC info page section "C
+    Extensions" for more details - Yes, really the info page, the
+    man page is only a short summary of the stuff in info):
+   </para>
+   <itemizedlist>
+    <listitem>
+     <para>
+      Inline functions
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Statement expressions (ie. the ({ and }) constructs).
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Declaring attributes of a function / variable / type
+      (__attribute__)
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      typeof
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Zero length arrays
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Macro varargs
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Arithmetic on void pointers
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Non-Constant initializers
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Assembler Instructions (not outside arch/ and include/asm/)
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Function names as strings (__FUNCTION__)
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      __builtin_constant_p()
+     </para>
+    </listitem>
+   </itemizedlist>
+
+   <para>
+    Be wary when using long long in the kernel, the code gcc generates for
+    it is horrible and worse: division and multiplication does not work
+    on i386 because the GCC runtime functions for it are missing from
+    the kernel environment.
+   </para>
+
+    <!-- FIXME: add a note about ANSI aliasing cleanness -->
+  </sect1>
+
+  <sect1 id="conventions-cplusplus">
+   <title>C++</title>
+   
+   <para>
+    Using C++ in the kernel is usually a bad idea, because the
+    kernel does not provide the necessary runtime environment
+    and the include files are not tested for it.  It is still
+    possible, but not recommended.  If you really want to do
+    this, forget about exceptions at least.
+   </para>
+  </sect1>
+
+  <sect1 id="conventions-ifdef">
+   <title>&num;if</title>
+   
+   <para>
+    It is generally considered cleaner to use macros in header files
+    (or at the top of .c files) to abstract away functions rather than
+    using `#if' pre-processor statements throughout the source code.
+   </para>
+  </sect1>
+ </chapter>
+
+ <chapter id="submitting">
+  <title>Putting Your Stuff in the Kernel</title>
+
+  <para>
+   In order to get your stuff into shape for official inclusion, or
+   even to make a neat patch, there's administrative work to be
+   done:
+  </para>
+  <itemizedlist>
+   <listitem>
+    <para>
+     Figure out whose pond you've been pissing in.  Look at the top of
+     the source files, inside the <filename>MAINTAINERS</filename>
+     file, and last of all in the <filename>CREDITS</filename> file.
+     You should coordinate with this person to make sure you're not
+     duplicating effort, or trying something that's already been
+     rejected.
+    </para>
+
+    <para>
+     Make sure you put your name and EMail address at the top of
+     any files you create or mangle significantly.  This is the
+     first place people will look when they find a bug, or when
+     <emphasis>they</emphasis> want to make a change.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Usually you want a configuration option for your kernel hack.
+     Edit <filename>Config.in</filename> in the appropriate directory
+     (but under <filename>arch/</filename> it's called
+     <filename>config.in</filename>).  The Config Language used is not
+     bash, even though it looks like bash; the safe way is to use only
+     the constructs that you already see in
+     <filename>Config.in</filename> files (see
+     <filename>Documentation/kbuild/kconfig-language.txt</filename>).
+     It's good to run "make xconfig" at least once to test (because
+     it's the only one with a static parser).
+    </para>
+
+    <para>
+     Variables which can be Y or N use <type>bool</type> followed by a
+     tagline and the config define name (which must start with
+     CONFIG_).  The <type>tristate</type> function is the same, but
+     allows the answer M (which defines
+     <symbol>CONFIG_foo_MODULE</symbol> in your source, instead of
+     <symbol>CONFIG_FOO</symbol>) if <symbol>CONFIG_MODULES</symbol>
+     is enabled.
+    </para>
+
+    <para>
+     You may well want to make your CONFIG option only visible if
+     <symbol>CONFIG_EXPERIMENTAL</symbol> is enabled: this serves as a
+     warning to users.  There many other fancy things you can do: see
+     the various <filename>Config.in</filename> files for ideas.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Edit the <filename>Makefile</filename>: the CONFIG variables are
+     exported here so you can conditionalize compilation with `ifeq'.
+     If your file exports symbols then add the names to
+     <varname>export-objs</varname> so that genksyms will find them.
+     <caution>
+      <para>
+       There is a restriction on the kernel build system that objects
+       which export symbols must have globally unique names.
+       If your object does not have a globally unique name then the
+       standard fix is to move the
+       <function>EXPORT_SYMBOL()</function> statements to their own
+       object with a unique name.
+       This is why several systems have separate exporting objects,
+       usually suffixed with ksyms.
+      </para>
+     </caution>
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Document your option in Documentation/Configure.help.  Mention
+     incompatibilities and issues here.  <emphasis> Definitely
+     </emphasis> end your description with <quote> if in doubt, say N
+     </quote> (or, occasionally, `Y'); this is for people who have no
+     idea what you are talking about.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Put yourself in <filename>CREDITS</filename> if you've done
+     something noteworthy, usually beyond a single file (your name
+     should be at the top of the source files anyway).
+     <filename>MAINTAINERS</filename> means you want to be consulted
+     when changes are made to a subsystem, and hear about bugs; it
+     implies a more-than-passing commitment to some part of the code.
+    </para>
+   </listitem>
+   
+   <listitem>
+    <para>
+     Finally, don't forget to read <filename>Documentation/SubmittingPatches</filename>
+     and possibly <filename>Documentation/SubmittingDrivers</filename>.
+    </para>
+   </listitem>
+  </itemizedlist>
+ </chapter>
+
+ <chapter id="cantrips">
+  <title>Kernel Cantrips</title>
+
+  <para>
+   Some favorites from browsing the source.  Feel free to add to this
+   list.
+  </para>
+
+  <para>
+   <filename>include/linux/brlock.h:</filename>
+  </para>
+  <programlisting>
+extern inline void br_read_lock (enum brlock_indices idx)
+{
+        /*
+         * This causes a link-time bug message if an
+         * invalid index is used:
+         */
+        if (idx >= __BR_END)
+                __br_lock_usage_bug();
+
+        read_lock(&amp;__brlock_array[smp_processor_id()][idx]);
+}
+  </programlisting>
+
+  <para>
+   <filename>include/linux/fs.h</filename>:
+  </para>
+  <programlisting>
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+ #define ERR_PTR(err)    ((void *)((long)(err)))
+ #define PTR_ERR(ptr)    ((long)(ptr))
+ #define IS_ERR(ptr)     ((unsigned long)(ptr) > (unsigned long)(-1000))
+</programlisting>
+
+  <para>
+   <filename>include/asm-i386/uaccess.h:</filename>
+  </para>
+
+  <programlisting>
+#define copy_to_user(to,from,n)                         \
+        (__builtin_constant_p(n) ?                      \
+         __constant_copy_to_user((to),(from),(n)) :     \
+         __generic_copy_to_user((to),(from),(n)))
+  </programlisting>
+
+  <para>
+   <filename>arch/sparc/kernel/head.S:</filename>
+  </para>
+
+  <programlisting>
+/*
+ * Sun people can't spell worth damn. "compatability" indeed.
+ * At least we *know* we can't spell, and use a spell-checker.
+ */
+
+/* Uh, actually Linus it is I who cannot spell. Too much murky
+ * Sparc assembly will do this to ya.
+ */
+C_LABEL(cputypvar):
+        .asciz "compatability"
+
+/* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */
+        .align 4
+C_LABEL(cputypvar_sun4m):
+        .asciz "compatible"
+  </programlisting>
+
+  <para>
+   <filename>arch/sparc/lib/checksum.S:</filename>
+  </para>
+
+  <programlisting>
+        /* Sun, you just can't beat me, you just can't.  Stop trying,
+         * give up.  I'm serious, I am going to kick the living shit
+         * out of you, game over, lights out.
+         */
+  </programlisting>
+ </chapter>
+
+ <chapter id="credits">
+  <title>Thanks</title>
+
+  <para>
+   Thanks to Andi Kleen for the idea, answering my questions, fixing
+   my mistakes, filling content, etc.  Philipp Rumpf for more spelling
+   and clarity fixes, and some excellent non-obvious points.  Werner
+   Almesberger for giving me a great summary of
+   <function>disable_irq()</function>, and Jes Sorensen and Andrea
+   Arcangeli added caveats. Michael Elizabeth Chastain for checking
+   and adding to the Configure section. <!-- Rusty insisted on this
+   bit; I didn't do it! --> Telsa Gwynne for teaching me DocBook. 
+  </para>
+ </chapter>
+</book>
+

+ 2088 - 0
Documentation/DocBook/kernel-locking.tmpl

@@ -0,0 +1,2088 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="LKLockingGuide">
+ <bookinfo>
+  <title>Unreliable Guide To Locking</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Rusty</firstname>
+    <surname>Russell</surname>
+    <affiliation>
+     <address>
+      <email>rusty@rustcorp.com.au</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2003</year>
+   <holder>Rusty Russell</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+ <toc></toc>
+  <chapter id="intro">
+   <title>Introduction</title>
+   <para>
+     Welcome, to Rusty's Remarkably Unreliable Guide to Kernel
+     Locking issues.  This document describes the locking systems in
+     the Linux Kernel in 2.6.
+   </para>
+   <para>
+     With the wide availability of HyperThreading, and <firstterm
+     linkend="gloss-preemption">preemption </firstterm> in the Linux
+     Kernel, everyone hacking on the kernel needs to know the
+     fundamentals of concurrency and locking for
+     <firstterm linkend="gloss-smp"><acronym>SMP</acronym></firstterm>.
+   </para>
+  </chapter>
+
+   <chapter id="races">
+    <title>The Problem With Concurrency</title>
+    <para>
+      (Skip this if you know what a Race Condition is).
+    </para>
+    <para>
+      In a normal program, you can increment a counter like so:
+    </para>
+    <programlisting>
+      very_important_count++;
+    </programlisting>
+
+    <para>
+      This is what they would expect to happen:
+    </para>
+
+    <table>
+     <title>Expected Results</title>
+
+     <tgroup cols="2" align="left">
+
+      <thead>
+       <row>
+        <entry>Instance 1</entry>
+        <entry>Instance 2</entry>
+       </row>
+      </thead>
+
+      <tbody>
+       <row>
+        <entry>read very_important_count (5)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry>add 1 (6)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry>write very_important_count (6)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>read very_important_count (6)</entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>add 1 (7)</entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>write very_important_count (7)</entry>
+       </row>
+      </tbody>
+
+     </tgroup>
+    </table>
+
+    <para>
+     This is what might happen:
+    </para>
+
+    <table>
+     <title>Possible Results</title>
+
+     <tgroup cols="2" align="left">
+      <thead>
+       <row>
+        <entry>Instance 1</entry>
+        <entry>Instance 2</entry>
+       </row>
+      </thead>
+
+      <tbody>
+       <row>
+        <entry>read very_important_count (5)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>read very_important_count (5)</entry>
+       </row>
+       <row>
+        <entry>add 1 (6)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>add 1 (6)</entry>
+       </row>
+       <row>
+        <entry>write very_important_count (6)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>write very_important_count (6)</entry>
+       </row>
+      </tbody>
+     </tgroup>
+    </table>
+
+    <sect1 id="race-condition">
+    <title>Race Conditions and Critical Regions</title>
+    <para>
+      This overlap, where the result depends on the
+      relative timing of multiple tasks, is called a <firstterm>race condition</firstterm>.
+      The piece of code containing the concurrency issue is called a
+      <firstterm>critical region</firstterm>.  And especially since Linux starting running
+      on SMP machines, they became one of the major issues in kernel
+      design and implementation.
+    </para>
+    <para>
+      Preemption can have the same effect, even if there is only one
+      CPU: by preempting one task during the critical region, we have
+      exactly the same race condition.  In this case the thread which
+      preempts might run the critical region itself.
+    </para>
+    <para>
+      The solution is to recognize when these simultaneous accesses
+      occur, and use locks to make sure that only one instance can
+      enter the critical region at any time.  There are many
+      friendly primitives in the Linux kernel to help you do this.
+      And then there are the unfriendly primitives, but I'll pretend
+      they don't exist.
+    </para>
+    </sect1>
+  </chapter>
+
+  <chapter id="locks">
+   <title>Locking in the Linux Kernel</title>
+
+   <para>
+     If I could give you one piece of advice: never sleep with anyone
+     crazier than yourself.  But if I had to give you advice on
+     locking: <emphasis>keep it simple</emphasis>.
+   </para>
+
+   <para>
+     Be reluctant to introduce new locks.
+   </para>
+
+   <para>
+     Strangely enough, this last one is the exact reverse of my advice when
+     you <emphasis>have</emphasis> slept with someone crazier than yourself.
+     And you should think about getting a big dog.
+   </para>
+
+   <sect1 id="lock-intro">
+   <title>Two Main Types of Kernel Locks: Spinlocks and Semaphores</title>
+
+   <para>
+     There are two main types of kernel locks.  The fundamental type
+     is the spinlock 
+     (<filename class="headerfile">include/asm/spinlock.h</filename>),
+     which is a very simple single-holder lock: if you can't get the 
+     spinlock, you keep trying (spinning) until you can.  Spinlocks are 
+     very small and fast, and can be used anywhere.
+   </para>
+   <para>
+     The second type is a semaphore
+     (<filename class="headerfile">include/asm/semaphore.h</filename>): it
+     can have more than one holder at any time (the number decided at
+     initialization time), although it is most commonly used as a
+     single-holder lock (a mutex).  If you can't get a semaphore,
+     your task will put itself on the queue, and be woken up when the
+     semaphore is released.  This means the CPU will do something
+     else while you are waiting, but there are many cases when you
+     simply can't sleep (see <xref linkend="sleeping-things"/>), and so
+     have to use a spinlock instead.
+   </para>
+   <para>
+     Neither type of lock is recursive: see
+     <xref linkend="deadlock"/>.
+   </para>
+   </sect1>
+ 
+   <sect1 id="uniprocessor">
+    <title>Locks and Uniprocessor Kernels</title>
+
+    <para>
+      For kernels compiled without <symbol>CONFIG_SMP</symbol>, and
+      without <symbol>CONFIG_PREEMPT</symbol> spinlocks do not exist at
+      all.  This is an excellent design decision: when no-one else can
+      run at the same time, there is no reason to have a lock.
+    </para>
+
+    <para>
+      If the kernel is compiled without <symbol>CONFIG_SMP</symbol>,
+      but <symbol>CONFIG_PREEMPT</symbol> is set, then spinlocks
+      simply disable preemption, which is sufficient to prevent any
+      races.  For most purposes, we can think of preemption as
+      equivalent to SMP, and not worry about it separately.
+    </para>
+
+    <para>
+      You should always test your locking code with <symbol>CONFIG_SMP</symbol>
+      and <symbol>CONFIG_PREEMPT</symbol> enabled, even if you don't have an SMP test box, because it
+      will still catch some kinds of locking bugs.
+    </para>
+
+    <para>
+      Semaphores still exist, because they are required for
+      synchronization between <firstterm linkend="gloss-usercontext">user 
+      contexts</firstterm>, as we will see below.
+    </para>
+   </sect1>
+
+    <sect1 id="usercontextlocking">
+     <title>Locking Only In User Context</title>
+
+     <para>
+       If you have a data structure which is only ever accessed from
+       user context, then you can use a simple semaphore
+       (<filename>linux/asm/semaphore.h</filename>) to protect it.  This 
+       is the most trivial case: you initialize the semaphore to the number 
+       of resources available (usually 1), and call
+       <function>down_interruptible()</function> to grab the semaphore, and 
+       <function>up()</function> to release it.  There is also a 
+       <function>down()</function>, which should be avoided, because it 
+       will not return if a signal is received.
+     </para>
+
+     <para>
+       Example: <filename>linux/net/core/netfilter.c</filename> allows 
+       registration of new <function>setsockopt()</function> and 
+       <function>getsockopt()</function> calls, with
+       <function>nf_register_sockopt()</function>.  Registration and 
+       de-registration are only done on module load and unload (and boot 
+       time, where there is no concurrency), and the list of registrations 
+       is only consulted for an unknown <function>setsockopt()</function>
+       or <function>getsockopt()</function> system call.  The 
+       <varname>nf_sockopt_mutex</varname> is perfect to protect this,
+       especially since the setsockopt and getsockopt calls may well
+       sleep.
+     </para>
+   </sect1>
+
+   <sect1 id="lock-user-bh">
+    <title>Locking Between User Context and Softirqs</title>
+
+    <para>
+      If a <firstterm linkend="gloss-softirq">softirq</firstterm> shares
+      data with user context, you have two problems.  Firstly, the current 
+      user context can be interrupted by a softirq, and secondly, the
+      critical region could be entered from another CPU.  This is where
+      <function>spin_lock_bh()</function> 
+      (<filename class="headerfile">include/linux/spinlock.h</filename>) is
+      used.  It disables softirqs on that CPU, then grabs the lock.
+      <function>spin_unlock_bh()</function> does the reverse.  (The
+      '_bh' suffix is a historical reference to "Bottom Halves", the
+      old name for software interrupts.  It should really be
+      called spin_lock_softirq()' in a perfect world).
+    </para>
+
+    <para>
+      Note that you can also use <function>spin_lock_irq()</function>
+      or <function>spin_lock_irqsave()</function> here, which stop
+      hardware interrupts as well: see <xref linkend="hardirq-context"/>.
+    </para>
+
+    <para>
+      This works perfectly for <firstterm linkend="gloss-up"><acronym>UP
+      </acronym></firstterm> as well: the spin lock vanishes, and this macro 
+      simply becomes <function>local_bh_disable()</function>
+      (<filename class="headerfile">include/linux/interrupt.h</filename>), which
+      protects you from the softirq being run.
+    </para>
+   </sect1>
+
+   <sect1 id="lock-user-tasklet">
+    <title>Locking Between User Context and Tasklets</title>
+
+    <para>
+      This is exactly the same as above, because <firstterm
+      linkend="gloss-tasklet">tasklets</firstterm> are actually run
+      from a softirq.
+    </para>
+   </sect1>
+
+   <sect1 id="lock-user-timers">
+    <title>Locking Between User Context and Timers</title>
+
+    <para>
+      This, too, is exactly the same as above, because <firstterm
+      linkend="gloss-timers">timers</firstterm> are actually run from
+      a softirq.  From a locking point of view, tasklets and timers
+      are identical.
+    </para>
+   </sect1>
+
+   <sect1 id="lock-tasklets">
+    <title>Locking Between Tasklets/Timers</title>
+
+    <para>
+      Sometimes a tasklet or timer might want to share data with
+      another tasklet or timer.
+    </para>
+
+    <sect2 id="lock-tasklets-same">
+     <title>The Same Tasklet/Timer</title>
+     <para>
+       Since a tasklet is never run on two CPUs at once, you don't
+       need to worry about your tasklet being reentrant (running
+       twice at once), even on SMP.
+     </para>
+    </sect2>
+
+    <sect2 id="lock-tasklets-different">
+     <title>Different Tasklets/Timers</title>
+     <para>
+       If another tasklet/timer wants
+       to share data with your tasklet or timer , you will both need to use
+       <function>spin_lock()</function> and
+       <function>spin_unlock()</function> calls.  
+       <function>spin_lock_bh()</function> is
+       unnecessary here, as you are already in a tasklet, and
+       none will be run on the same CPU.
+     </para>
+    </sect2>
+   </sect1>
+
+   <sect1 id="lock-softirqs">
+    <title>Locking Between Softirqs</title>
+
+    <para>
+      Often a softirq might
+      want to share data with itself or a tasklet/timer.
+    </para>
+
+    <sect2 id="lock-softirqs-same">
+     <title>The Same Softirq</title>
+
+     <para>
+       The same softirq can run on the other CPUs: you can use a
+       per-CPU array (see <xref linkend="per-cpu"/>) for better
+       performance.  If you're going so far as to use a softirq,
+       you probably care about scalable performance enough
+       to justify the extra complexity.
+     </para>
+
+     <para>
+       You'll need to use <function>spin_lock()</function> and 
+       <function>spin_unlock()</function> for shared data.
+     </para>
+    </sect2>
+
+    <sect2 id="lock-softirqs-different">
+     <title>Different Softirqs</title>
+
+     <para>
+       You'll need to use <function>spin_lock()</function> and
+       <function>spin_unlock()</function> for shared data, whether it
+       be a timer, tasklet, different softirq or the same or another
+       softirq: any of them could be running on a different CPU.
+     </para>
+    </sect2>
+   </sect1>
+  </chapter>
+
+  <chapter id="hardirq-context">
+   <title>Hard IRQ Context</title>
+
+   <para>
+     Hardware interrupts usually communicate with a
+     tasklet or softirq.  Frequently this involves putting work in a
+     queue, which the softirq will take out.
+   </para>
+
+   <sect1 id="hardirq-softirq">
+    <title>Locking Between Hard IRQ and Softirqs/Tasklets</title>
+
+    <para>
+      If a hardware irq handler shares data with a softirq, you have
+      two concerns.  Firstly, the softirq processing can be
+      interrupted by a hardware interrupt, and secondly, the
+      critical region could be entered by a hardware interrupt on
+      another CPU.  This is where <function>spin_lock_irq()</function> is 
+      used.  It is defined to disable interrupts on that cpu, then grab 
+      the lock. <function>spin_unlock_irq()</function> does the reverse.
+    </para>
+
+    <para>
+      The irq handler does not to use
+      <function>spin_lock_irq()</function>, because the softirq cannot
+      run while the irq handler is running: it can use
+      <function>spin_lock()</function>, which is slightly faster.  The
+      only exception would be if a different hardware irq handler uses
+      the same lock: <function>spin_lock_irq()</function> will stop
+      that from interrupting us.
+    </para>
+
+    <para>
+      This works perfectly for UP as well: the spin lock vanishes,
+      and this macro simply becomes <function>local_irq_disable()</function>
+      (<filename class="headerfile">include/asm/smp.h</filename>), which
+      protects you from the softirq/tasklet/BH being run.
+    </para>
+
+    <para>
+      <function>spin_lock_irqsave()</function> 
+      (<filename>include/linux/spinlock.h</filename>) is a variant
+      which saves whether interrupts were on or off in a flags word,
+      which is passed to <function>spin_unlock_irqrestore()</function>.  This
+      means that the same code can be used inside an hard irq handler (where
+      interrupts are already off) and in softirqs (where the irq
+      disabling is required).
+    </para>
+
+    <para>
+      Note that softirqs (and hence tasklets and timers) are run on
+      return from hardware interrupts, so
+      <function>spin_lock_irq()</function> also stops these.  In that
+      sense, <function>spin_lock_irqsave()</function> is the most
+      general and powerful locking function.
+    </para>
+
+   </sect1>
+   <sect1 id="hardirq-hardirq">
+    <title>Locking Between Two Hard IRQ Handlers</title>
+    <para>
+      It is rare to have to share data between two IRQ handlers, but
+      if you do, <function>spin_lock_irqsave()</function> should be
+      used: it is architecture-specific whether all interrupts are
+      disabled inside irq handlers themselves.
+    </para>
+   </sect1>
+
+  </chapter>
+
+  <chapter id="cheatsheet">
+   <title>Cheat Sheet For Locking</title>
+   <para>
+     Pete Zaitcev gives the following summary:
+   </para>
+   <itemizedlist>
+      <listitem>
+	<para>
+          If you are in a process context (any syscall) and want to
+	lock other process out, use a semaphore.  You can take a semaphore
+	and sleep (<function>copy_from_user*(</function> or
+	<function>kmalloc(x,GFP_KERNEL)</function>).
+      </para>
+      </listitem>
+      <listitem>
+	<para>
+	Otherwise (== data can be touched in an interrupt), use
+	<function>spin_lock_irqsave()</function> and
+	<function>spin_unlock_irqrestore()</function>.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	Avoid holding spinlock for more than 5 lines of code and
+	across any function call (except accessors like
+	<function>readb</function>).
+	</para>
+      </listitem>
+    </itemizedlist>
+
+   <sect1 id="minimum-lock-reqirements">
+   <title>Table of Minimum Requirements</title>
+
+   <para> The following table lists the <emphasis>minimum</emphasis>
+	locking requirements between various contexts.  In some cases,
+	the same context can only be running on one CPU at a time, so
+	no locking is required for that context (eg. a particular
+	thread can only run on one CPU at a time, but if it needs
+	shares data with another thread, locking is required).
+   </para>
+   <para>
+	Remember the advice above: you can always use
+	<function>spin_lock_irqsave()</function>, which is a superset
+	of all other spinlock primitives.
+   </para>
+   <table>
+<title>Table of Locking Requirements</title>
+<tgroup cols="11">
+<tbody>
+<row>
+<entry></entry>
+<entry>IRQ Handler A</entry>
+<entry>IRQ Handler B</entry>
+<entry>Softirq A</entry>
+<entry>Softirq B</entry>
+<entry>Tasklet A</entry>
+<entry>Tasklet B</entry>
+<entry>Timer A</entry>
+<entry>Timer B</entry>
+<entry>User Context A</entry>
+<entry>User Context B</entry>
+</row>
+
+<row>
+<entry>IRQ Handler A</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>IRQ Handler B</entry>
+<entry>spin_lock_irqsave</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>Softirq A</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+</row>
+
+<row>
+<entry>Softirq B</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+</row>
+
+<row>
+<entry>Tasklet A</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>Tasklet B</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>Timer A</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>Timer B</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>User Context A</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>User Context B</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>down_interruptible</entry>
+<entry>None</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+</sect1>
+</chapter>
+
+  <chapter id="Examples">
+   <title>Common Examples</title>
+    <para>
+Let's step through a simple example: a cache of number to name
+mappings.  The cache keeps a count of how often each of the objects is
+used, and when it gets full, throws out the least used one.
+
+    </para>
+
+   <sect1 id="examples-usercontext">
+    <title>All In User Context</title>
+    <para>
+For our first example, we assume that all operations are in user
+context (ie. from system calls), so we can sleep.  This means we can
+use a semaphore to protect the cache and all the objects within
+it.  Here's the code:
+    </para>
+
+    <programlisting>
+#include &lt;linux/list.h&gt;
+#include &lt;linux/slab.h&gt;
+#include &lt;linux/string.h&gt;
+#include &lt;asm/semaphore.h&gt;
+#include &lt;asm/errno.h&gt;
+
+struct object
+{
+        struct list_head list;
+        int id;
+        char name[32];
+        int popularity;
+};
+
+/* Protects the cache, cache_num, and the objects within it */
+static DECLARE_MUTEX(cache_lock);
+static LIST_HEAD(cache);
+static unsigned int cache_num = 0;
+#define MAX_CACHE_SIZE 10
+
+/* Must be holding cache_lock */
+static struct object *__cache_find(int id)
+{
+        struct object *i;
+
+        list_for_each_entry(i, &amp;cache, list)
+                if (i-&gt;id == id) {
+                        i-&gt;popularity++;
+                        return i;
+                }
+        return NULL;
+}
+
+/* Must be holding cache_lock */
+static void __cache_delete(struct object *obj)
+{
+        BUG_ON(!obj);
+        list_del(&amp;obj-&gt;list);
+        kfree(obj);
+        cache_num--;
+}
+
+/* Must be holding cache_lock */
+static void __cache_add(struct object *obj)
+{
+        list_add(&amp;obj-&gt;list, &amp;cache);
+        if (++cache_num > MAX_CACHE_SIZE) {
+                struct object *i, *outcast = NULL;
+                list_for_each_entry(i, &amp;cache, list) {
+                        if (!outcast || i-&gt;popularity &lt; outcast-&gt;popularity)
+                                outcast = i;
+                }
+                __cache_delete(outcast);
+        }
+}
+
+int cache_add(int id, const char *name)
+{
+        struct object *obj;
+
+        if ((obj = kmalloc(sizeof(*obj), GFP_KERNEL)) == NULL)
+                return -ENOMEM;
+
+        strlcpy(obj-&gt;name, name, sizeof(obj-&gt;name));
+        obj-&gt;id = id;
+        obj-&gt;popularity = 0;
+
+        down(&amp;cache_lock);
+        __cache_add(obj);
+        up(&amp;cache_lock);
+        return 0;
+}
+
+void cache_delete(int id)
+{
+        down(&amp;cache_lock);
+        __cache_delete(__cache_find(id));
+        up(&amp;cache_lock);
+}
+
+int cache_find(int id, char *name)
+{
+        struct object *obj;
+        int ret = -ENOENT;
+
+        down(&amp;cache_lock);
+        obj = __cache_find(id);
+        if (obj) {
+                ret = 0;
+                strcpy(name, obj-&gt;name);
+        }
+        up(&amp;cache_lock);
+        return ret;
+}
+</programlisting>
+
+    <para>
+Note that we always make sure we have the cache_lock when we add,
+delete, or look up the cache: both the cache infrastructure itself and
+the contents of the objects are protected by the lock.  In this case
+it's easy, since we copy the data for the user, and never let them
+access the objects directly.
+    </para>
+    <para>
+There is a slight (and common) optimization here: in
+<function>cache_add</function> we set up the fields of the object
+before grabbing the lock.  This is safe, as no-one else can access it
+until we put it in cache.
+    </para>
+    </sect1>
+
+   <sect1 id="examples-interrupt">
+    <title>Accessing From Interrupt Context</title>
+    <para>
+Now consider the case where <function>cache_find</function> can be
+called from interrupt context: either a hardware interrupt or a
+softirq.  An example would be a timer which deletes object from the
+cache.
+    </para>
+    <para>
+The change is shown below, in standard patch format: the
+<symbol>-</symbol> are lines which are taken away, and the
+<symbol>+</symbol> are lines which are added.
+    </para>
+<programlisting>
+--- cache.c.usercontext	2003-12-09 13:58:54.000000000 +1100
++++ cache.c.interrupt	2003-12-09 14:07:49.000000000 +1100
+@@ -12,7 +12,7 @@
+         int popularity;
+ };
+
+-static DECLARE_MUTEX(cache_lock);
++static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED;
+ static LIST_HEAD(cache);
+ static unsigned int cache_num = 0;
+ #define MAX_CACHE_SIZE 10
+@@ -55,6 +55,7 @@
+ int cache_add(int id, const char *name)
+ {
+         struct object *obj;
++        unsigned long flags;
+
+         if ((obj = kmalloc(sizeof(*obj), GFP_KERNEL)) == NULL)
+                 return -ENOMEM;
+@@ -63,30 +64,33 @@
+         obj-&gt;id = id;
+         obj-&gt;popularity = 0;
+
+-        down(&amp;cache_lock);
++        spin_lock_irqsave(&amp;cache_lock, flags);
+         __cache_add(obj);
+-        up(&amp;cache_lock);
++        spin_unlock_irqrestore(&amp;cache_lock, flags);
+         return 0;
+ }
+
+ void cache_delete(int id)
+ {
+-        down(&amp;cache_lock);
++        unsigned long flags;
++
++        spin_lock_irqsave(&amp;cache_lock, flags);
+         __cache_delete(__cache_find(id));
+-        up(&amp;cache_lock);
++        spin_unlock_irqrestore(&amp;cache_lock, flags);
+ }
+
+ int cache_find(int id, char *name)
+ {
+         struct object *obj;
+         int ret = -ENOENT;
++        unsigned long flags;
+
+-        down(&amp;cache_lock);
++        spin_lock_irqsave(&amp;cache_lock, flags);
+         obj = __cache_find(id);
+         if (obj) {
+                 ret = 0;
+                 strcpy(name, obj-&gt;name);
+         }
+-        up(&amp;cache_lock);
++        spin_unlock_irqrestore(&amp;cache_lock, flags);
+         return ret;
+ }
+</programlisting>
+
+    <para>
+Note that the <function>spin_lock_irqsave</function> will turn off
+interrupts if they are on, otherwise does nothing (if we are already
+in an interrupt handler), hence these functions are safe to call from
+any context.
+    </para>
+    <para>
+Unfortunately, <function>cache_add</function> calls
+<function>kmalloc</function> with the <symbol>GFP_KERNEL</symbol>
+flag, which is only legal in user context.  I have assumed that
+<function>cache_add</function> is still only called in user context,
+otherwise this should become a parameter to
+<function>cache_add</function>.
+    </para>
+  </sect1>
+   <sect1 id="examples-refcnt">
+    <title>Exposing Objects Outside This File</title>
+    <para>
+If our objects contained more information, it might not be sufficient
+to copy the information in and out: other parts of the code might want
+to keep pointers to these objects, for example, rather than looking up
+the id every time.  This produces two problems.
+    </para>
+    <para>
+The first problem is that we use the <symbol>cache_lock</symbol> to
+protect objects: we'd need to make this non-static so the rest of the
+code can use it.  This makes locking trickier, as it is no longer all
+in one place.
+    </para>
+    <para>
+The second problem is the lifetime problem: if another structure keeps
+a pointer to an object, it presumably expects that pointer to remain
+valid.  Unfortunately, this is only guaranteed while you hold the
+lock, otherwise someone might call <function>cache_delete</function>
+and even worse, add another object, re-using the same address.
+    </para>
+    <para>
+As there is only one lock, you can't hold it forever: no-one else would
+get any work done.
+    </para>
+    <para>
+The solution to this problem is to use a reference count: everyone who
+has a pointer to the object increases it when they first get the
+object, and drops the reference count when they're finished with it.
+Whoever drops it to zero knows it is unused, and can actually delete it.
+    </para>
+    <para>
+Here is the code:
+    </para>
+
+<programlisting>
+--- cache.c.interrupt	2003-12-09 14:25:43.000000000 +1100
++++ cache.c.refcnt	2003-12-09 14:33:05.000000000 +1100
+@@ -7,6 +7,7 @@
+ struct object
+ {
+         struct list_head list;
++        unsigned int refcnt;
+         int id;
+         char name[32];
+         int popularity;
+@@ -17,6 +18,35 @@
+ static unsigned int cache_num = 0;
+ #define MAX_CACHE_SIZE 10
+
++static void __object_put(struct object *obj)
++{
++        if (--obj-&gt;refcnt == 0)
++                kfree(obj);
++}
++
++static void __object_get(struct object *obj)
++{
++        obj-&gt;refcnt++;
++}
++
++void object_put(struct object *obj)
++{
++        unsigned long flags;
++
++        spin_lock_irqsave(&amp;cache_lock, flags);
++        __object_put(obj);
++        spin_unlock_irqrestore(&amp;cache_lock, flags);
++}
++
++void object_get(struct object *obj)
++{
++        unsigned long flags;
++
++        spin_lock_irqsave(&amp;cache_lock, flags);
++        __object_get(obj);
++        spin_unlock_irqrestore(&amp;cache_lock, flags);
++}
++
+ /* Must be holding cache_lock */
+ static struct object *__cache_find(int id)
+ {
+@@ -35,6 +65,7 @@
+ {
+         BUG_ON(!obj);
+         list_del(&amp;obj-&gt;list);
++        __object_put(obj);
+         cache_num--;
+ }
+
+@@ -63,6 +94,7 @@
+         strlcpy(obj-&gt;name, name, sizeof(obj-&gt;name));
+         obj-&gt;id = id;
+         obj-&gt;popularity = 0;
++        obj-&gt;refcnt = 1; /* The cache holds a reference */
+
+         spin_lock_irqsave(&amp;cache_lock, flags);
+         __cache_add(obj);
+@@ -79,18 +111,15 @@
+         spin_unlock_irqrestore(&amp;cache_lock, flags);
+ }
+
+-int cache_find(int id, char *name)
++struct object *cache_find(int id)
+ {
+         struct object *obj;
+-        int ret = -ENOENT;
+         unsigned long flags;
+
+         spin_lock_irqsave(&amp;cache_lock, flags);
+         obj = __cache_find(id);
+-        if (obj) {
+-                ret = 0;
+-                strcpy(name, obj-&gt;name);
+-        }
++        if (obj)
++                __object_get(obj);
+         spin_unlock_irqrestore(&amp;cache_lock, flags);
+-        return ret;
++        return obj;
+ }
+</programlisting>
+
+<para>
+We encapsulate the reference counting in the standard 'get' and 'put'
+functions.  Now we can return the object itself from
+<function>cache_find</function> which has the advantage that the user
+can now sleep holding the object (eg. to
+<function>copy_to_user</function> to name to userspace).
+</para>
+<para>
+The other point to note is that I said a reference should be held for
+every pointer to the object: thus the reference count is 1 when first
+inserted into the cache.  In some versions the framework does not hold
+a reference count, but they are more complicated.
+</para>
+
+   <sect2 id="examples-refcnt-atomic">
+    <title>Using Atomic Operations For The Reference Count</title>
+<para>
+In practice, <type>atomic_t</type> would usually be used for
+<structfield>refcnt</structfield>.  There are a number of atomic
+operations defined in
+
+<filename class="headerfile">include/asm/atomic.h</filename>: these are
+guaranteed to be seen atomically from all CPUs in the system, so no
+lock is required.  In this case, it is simpler than using spinlocks,
+although for anything non-trivial using spinlocks is clearer.  The
+<function>atomic_inc</function> and
+<function>atomic_dec_and_test</function> are used instead of the
+standard increment and decrement operators, and the lock is no longer
+used to protect the reference count itself.
+</para>
+
+<programlisting>
+--- cache.c.refcnt	2003-12-09 15:00:35.000000000 +1100
++++ cache.c.refcnt-atomic	2003-12-11 15:49:42.000000000 +1100
+@@ -7,7 +7,7 @@
+ struct object
+ {
+         struct list_head list;
+-        unsigned int refcnt;
++        atomic_t refcnt;
+         int id;
+         char name[32];
+         int popularity;
+@@ -18,33 +18,15 @@
+ static unsigned int cache_num = 0;
+ #define MAX_CACHE_SIZE 10
+
+-static void __object_put(struct object *obj)
+-{
+-        if (--obj-&gt;refcnt == 0)
+-                kfree(obj);
+-}
+-
+-static void __object_get(struct object *obj)
+-{
+-        obj-&gt;refcnt++;
+-}
+-
+ void object_put(struct object *obj)
+ {
+-        unsigned long flags;
+-
+-        spin_lock_irqsave(&amp;cache_lock, flags);
+-        __object_put(obj);
+-        spin_unlock_irqrestore(&amp;cache_lock, flags);
++        if (atomic_dec_and_test(&amp;obj-&gt;refcnt))
++                kfree(obj);
+ }
+
+ void object_get(struct object *obj)
+ {
+-        unsigned long flags;
+-
+-        spin_lock_irqsave(&amp;cache_lock, flags);
+-        __object_get(obj);
+-        spin_unlock_irqrestore(&amp;cache_lock, flags);
++        atomic_inc(&amp;obj-&gt;refcnt);
+ }
+
+ /* Must be holding cache_lock */
+@@ -65,7 +47,7 @@
+ {
+         BUG_ON(!obj);
+         list_del(&amp;obj-&gt;list);
+-        __object_put(obj);
++        object_put(obj);
+         cache_num--;
+ }
+
+@@ -94,7 +76,7 @@
+         strlcpy(obj-&gt;name, name, sizeof(obj-&gt;name));
+         obj-&gt;id = id;
+         obj-&gt;popularity = 0;
+-        obj-&gt;refcnt = 1; /* The cache holds a reference */
++        atomic_set(&amp;obj-&gt;refcnt, 1); /* The cache holds a reference */
+
+         spin_lock_irqsave(&amp;cache_lock, flags);
+         __cache_add(obj);
+@@ -119,7 +101,7 @@
+         spin_lock_irqsave(&amp;cache_lock, flags);
+         obj = __cache_find(id);
+         if (obj)
+-                __object_get(obj);
++                object_get(obj);
+         spin_unlock_irqrestore(&amp;cache_lock, flags);
+         return obj;
+ }
+</programlisting>
+</sect2>
+</sect1>
+
+   <sect1 id="examples-lock-per-obj">
+    <title>Protecting The Objects Themselves</title>
+    <para>
+In these examples, we assumed that the objects (except the reference
+counts) never changed once they are created.  If we wanted to allow
+the name to change, there are three possibilities:
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para>
+You can make <symbol>cache_lock</symbol> non-static, and tell people
+to grab that lock before changing the name in any object.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+You can provide a <function>cache_obj_rename</function> which grabs
+this lock and changes the name for the caller, and tell everyone to
+use that function.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+You can make the <symbol>cache_lock</symbol> protect only the cache
+itself, and use another lock to protect the name.
+        </para>
+      </listitem>
+    </itemizedlist>
+
+      <para>
+Theoretically, you can make the locks as fine-grained as one lock for
+every field, for every object.  In practice, the most common variants
+are:
+</para>
+    <itemizedlist>
+      <listitem>
+	<para>
+One lock which protects the infrastructure (the <symbol>cache</symbol>
+list in this example) and all the objects.  This is what we have done
+so far.
+	</para>
+      </listitem>
+      <listitem>
+        <para>
+One lock which protects the infrastructure (including the list
+pointers inside the objects), and one lock inside the object which
+protects the rest of that object.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+Multiple locks to protect the infrastructure (eg. one lock per hash
+chain), possibly with a separate per-object lock.
+        </para>
+      </listitem>
+    </itemizedlist>
+
+<para>
+Here is the "lock-per-object" implementation:
+</para>
+<programlisting>
+--- cache.c.refcnt-atomic	2003-12-11 15:50:54.000000000 +1100
++++ cache.c.perobjectlock	2003-12-11 17:15:03.000000000 +1100
+@@ -6,11 +6,17 @@
+
+ struct object
+ {
++        /* These two protected by cache_lock. */
+         struct list_head list;
++        int popularity;
++
+         atomic_t refcnt;
++
++        /* Doesn't change once created. */
+         int id;
++
++        spinlock_t lock; /* Protects the name */
+         char name[32];
+-        int popularity;
+ };
+
+ static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED;
+@@ -77,6 +84,7 @@
+         obj-&gt;id = id;
+         obj-&gt;popularity = 0;
+         atomic_set(&amp;obj-&gt;refcnt, 1); /* The cache holds a reference */
++        spin_lock_init(&amp;obj-&gt;lock);
+
+         spin_lock_irqsave(&amp;cache_lock, flags);
+         __cache_add(obj);
+</programlisting>
+
+<para>
+Note that I decide that the <structfield>popularity</structfield>
+count should be protected by the <symbol>cache_lock</symbol> rather
+than the per-object lock: this is because it (like the
+<structname>struct list_head</structname> inside the object) is
+logically part of the infrastructure.  This way, I don't need to grab
+the lock of every object in <function>__cache_add</function> when
+seeking the least popular.
+</para>
+
+<para>
+I also decided that the <structfield>id</structfield> member is
+unchangeable, so I don't need to grab each object lock in
+<function>__cache_find()</function> to examine the
+<structfield>id</structfield>: the object lock is only used by a
+caller who wants to read or write the <structfield>name</structfield>
+field.
+</para>
+
+<para>
+Note also that I added a comment describing what data was protected by
+which locks.  This is extremely important, as it describes the runtime
+behavior of the code, and can be hard to gain from just reading.  And
+as Alan Cox says, <quote>Lock data, not code</quote>.
+</para>
+</sect1>
+</chapter>
+
+   <chapter id="common-problems">
+    <title>Common Problems</title>
+    <sect1 id="deadlock">
+    <title>Deadlock: Simple and Advanced</title>
+
+    <para>
+      There is a coding bug where a piece of code tries to grab a
+      spinlock twice: it will spin forever, waiting for the lock to
+      be released (spinlocks, rwlocks and semaphores are not
+      recursive in Linux).  This is trivial to diagnose: not a
+      stay-up-five-nights-talk-to-fluffy-code-bunnies kind of
+      problem.
+    </para>
+
+    <para>
+      For a slightly more complex case, imagine you have a region
+      shared by a softirq and user context.  If you use a
+      <function>spin_lock()</function> call to protect it, it is 
+      possible that the user context will be interrupted by the softirq
+      while it holds the lock, and the softirq will then spin
+      forever trying to get the same lock.
+    </para>
+
+    <para>
+      Both of these are called deadlock, and as shown above, it can
+      occur even with a single CPU (although not on UP compiles,
+      since spinlocks vanish on kernel compiles with 
+      <symbol>CONFIG_SMP</symbol>=n. You'll still get data corruption 
+      in the second example).
+    </para>
+
+    <para>
+      This complete lockup is easy to diagnose: on SMP boxes the
+      watchdog timer or compiling with <symbol>DEBUG_SPINLOCKS</symbol> set
+      (<filename>include/linux/spinlock.h</filename>) will show this up 
+      immediately when it happens.
+    </para>
+
+    <para>
+      A more complex problem is the so-called 'deadly embrace',
+      involving two or more locks.  Say you have a hash table: each
+      entry in the table is a spinlock, and a chain of hashed
+      objects.  Inside a softirq handler, you sometimes want to
+      alter an object from one place in the hash to another: you
+      grab the spinlock of the old hash chain and the spinlock of
+      the new hash chain, and delete the object from the old one,
+      and insert it in the new one.
+    </para>
+
+    <para>
+      There are two problems here.  First, if your code ever
+      tries to move the object to the same chain, it will deadlock
+      with itself as it tries to lock it twice.  Secondly, if the
+      same softirq on another CPU is trying to move another object
+      in the reverse direction, the following could happen:
+    </para>
+
+    <table>
+     <title>Consequences</title>
+
+     <tgroup cols="2" align="left">
+
+      <thead>
+       <row>
+        <entry>CPU 1</entry>
+        <entry>CPU 2</entry>
+       </row>
+      </thead>
+
+      <tbody>
+       <row>
+        <entry>Grab lock A -&gt; OK</entry>
+        <entry>Grab lock B -&gt; OK</entry>
+       </row>
+       <row>
+        <entry>Grab lock B -&gt; spin</entry>
+        <entry>Grab lock A -&gt; spin</entry>
+       </row>
+      </tbody>
+     </tgroup>
+    </table>
+
+    <para>
+      The two CPUs will spin forever, waiting for the other to give up
+      their lock.  It will look, smell, and feel like a crash.
+    </para>
+    </sect1>
+
+    <sect1 id="techs-deadlock-prevent">
+     <title>Preventing Deadlock</title>
+
+     <para>
+       Textbooks will tell you that if you always lock in the same
+       order, you will never get this kind of deadlock.  Practice
+       will tell you that this approach doesn't scale: when I
+       create a new lock, I don't understand enough of the kernel
+       to figure out where in the 5000 lock hierarchy it will fit.
+     </para>
+
+     <para>
+       The best locks are encapsulated: they never get exposed in
+       headers, and are never held around calls to non-trivial
+       functions outside the same file.  You can read through this
+       code and see that it will never deadlock, because it never
+       tries to grab another lock while it has that one.  People
+       using your code don't even need to know you are using a
+       lock.
+     </para>
+
+     <para>
+       A classic problem here is when you provide callbacks or
+       hooks: if you call these with the lock held, you risk simple
+       deadlock, or a deadly embrace (who knows what the callback
+       will do?).  Remember, the other programmers are out to get
+       you, so don't do this.
+     </para>
+
+    <sect2 id="techs-deadlock-overprevent">
+     <title>Overzealous Prevention Of Deadlocks</title>
+
+     <para>
+       Deadlocks are problematic, but not as bad as data
+       corruption.  Code which grabs a read lock, searches a list,
+       fails to find what it wants, drops the read lock, grabs a
+       write lock and inserts the object has a race condition.
+     </para>
+
+     <para>
+       If you don't see why, please stay the fuck away from my code.
+     </para>
+    </sect2>
+    </sect1>
+
+   <sect1 id="racing-timers">
+    <title>Racing Timers: A Kernel Pastime</title>
+
+    <para>
+      Timers can produce their own special problems with races.
+      Consider a collection of objects (list, hash, etc) where each
+      object has a timer which is due to destroy it.
+    </para>
+
+    <para>
+      If you want to destroy the entire collection (say on module
+      removal), you might do the following:
+    </para>
+
+    <programlisting>
+        /* THIS CODE BAD BAD BAD BAD: IF IT WAS ANY WORSE IT WOULD USE
+           HUNGARIAN NOTATION */
+        spin_lock_bh(&amp;list_lock);
+
+        while (list) {
+                struct foo *next = list-&gt;next;
+                del_timer(&amp;list-&gt;timer);
+                kfree(list);
+                list = next;
+        }
+
+        spin_unlock_bh(&amp;list_lock);
+    </programlisting>
+
+    <para>
+      Sooner or later, this will crash on SMP, because a timer can
+      have just gone off before the <function>spin_lock_bh()</function>,
+      and it will only get the lock after we
+      <function>spin_unlock_bh()</function>, and then try to free
+      the element (which has already been freed!).
+    </para>
+
+    <para>
+      This can be avoided by checking the result of
+      <function>del_timer()</function>: if it returns
+      <returnvalue>1</returnvalue>, the timer has been deleted.
+      If <returnvalue>0</returnvalue>, it means (in this
+      case) that it is currently running, so we can do:
+    </para>
+
+    <programlisting>
+        retry:
+                spin_lock_bh(&amp;list_lock);
+
+                while (list) {
+                        struct foo *next = list-&gt;next;
+                        if (!del_timer(&amp;list-&gt;timer)) {
+                                /* Give timer a chance to delete this */
+                                spin_unlock_bh(&amp;list_lock);
+                                goto retry;
+                        }
+                        kfree(list);
+                        list = next;
+                }
+
+                spin_unlock_bh(&amp;list_lock);
+    </programlisting>
+
+    <para>
+      Another common problem is deleting timers which restart
+      themselves (by calling <function>add_timer()</function> at the end
+      of their timer function).  Because this is a fairly common case
+      which is prone to races, you should use <function>del_timer_sync()</function>
+      (<filename class="headerfile">include/linux/timer.h</filename>)
+      to handle this case.  It returns the number of times the timer
+      had to be deleted before we finally stopped it from adding itself back
+      in.
+    </para>
+   </sect1>
+
+  </chapter>
+
+ <chapter id="Efficiency">
+    <title>Locking Speed</title>
+
+    <para>
+There are three main things to worry about when considering speed of
+some code which does locking.  First is concurrency: how many things
+are going to be waiting while someone else is holding a lock.  Second
+is the time taken to actually acquire and release an uncontended lock.
+Third is using fewer, or smarter locks.  I'm assuming that the lock is
+used fairly often: otherwise, you wouldn't be concerned about
+efficiency.
+</para>
+    <para>
+Concurrency depends on how long the lock is usually held: you should
+hold the lock for as long as needed, but no longer.  In the cache
+example, we always create the object without the lock held, and then
+grab the lock only when we are ready to insert it in the list.
+</para>
+    <para>
+Acquisition times depend on how much damage the lock operations do to
+the pipeline (pipeline stalls) and how likely it is that this CPU was
+the last one to grab the lock (ie. is the lock cache-hot for this
+CPU): on a machine with more CPUs, this likelihood drops fast.
+Consider a 700MHz Intel Pentium III: an instruction takes about 0.7ns,
+an atomic increment takes about 58ns, a lock which is cache-hot on
+this CPU takes 160ns, and a cacheline transfer from another CPU takes
+an additional 170 to 360ns.  (These figures from Paul McKenney's
+<ulink url="http://www.linuxjournal.com/article.php?sid=6993"> Linux
+Journal RCU article</ulink>).
+</para>
+    <para>
+These two aims conflict: holding a lock for a short time might be done
+by splitting locks into parts (such as in our final per-object-lock
+example), but this increases the number of lock acquisitions, and the
+results are often slower than having a single lock.  This is another
+reason to advocate locking simplicity.
+</para>
+    <para>
+The third concern is addressed below: there are some methods to reduce
+the amount of locking which needs to be done.
+</para>
+
+  <sect1 id="efficiency-rwlocks">
+   <title>Read/Write Lock Variants</title>
+
+   <para>
+      Both spinlocks and semaphores have read/write variants:
+      <type>rwlock_t</type> and <structname>struct rw_semaphore</structname>.
+      These divide users into two classes: the readers and the writers.  If
+      you are only reading the data, you can get a read lock, but to write to
+      the data you need the write lock.  Many people can hold a read lock,
+      but a writer must be sole holder.
+    </para>
+
+   <para>
+      If your code divides neatly along reader/writer lines (as our
+      cache code does), and the lock is held by readers for
+      significant lengths of time, using these locks can help.  They
+      are slightly slower than the normal locks though, so in practice
+      <type>rwlock_t</type> is not usually worthwhile.
+    </para>
+   </sect1>
+
+   <sect1 id="efficiency-read-copy-update">
+    <title>Avoiding Locks: Read Copy Update</title>
+
+    <para>
+      There is a special method of read/write locking called Read Copy
+      Update.  Using RCU, the readers can avoid taking a lock
+      altogether: as we expect our cache to be read more often than
+      updated (otherwise the cache is a waste of time), it is a
+      candidate for this optimization.
+    </para>
+
+    <para>
+      How do we get rid of read locks?  Getting rid of read locks
+      means that writers may be changing the list underneath the
+      readers.  That is actually quite simple: we can read a linked
+      list while an element is being added if the writer adds the
+      element very carefully.  For example, adding
+      <symbol>new</symbol> to a single linked list called
+      <symbol>list</symbol>:
+    </para>
+
+    <programlisting>
+        new-&gt;next = list-&gt;next;
+        wmb();
+        list-&gt;next = new;
+    </programlisting>
+
+    <para>
+      The <function>wmb()</function> is a write memory barrier.  It
+      ensures that the first operation (setting the new element's
+      <symbol>next</symbol> pointer) is complete and will be seen by
+      all CPUs, before the second operation is (putting the new
+      element into the list).  This is important, since modern
+      compilers and modern CPUs can both reorder instructions unless
+      told otherwise: we want a reader to either not see the new
+      element at all, or see the new element with the
+      <symbol>next</symbol> pointer correctly pointing at the rest of
+      the list.
+    </para>
+    <para>
+      Fortunately, there is a function to do this for standard
+      <structname>struct list_head</structname> lists:
+      <function>list_add_rcu()</function>
+      (<filename>include/linux/list.h</filename>).
+    </para>
+    <para>
+      Removing an element from the list is even simpler: we replace
+      the pointer to the old element with a pointer to its successor,
+      and readers will either see it, or skip over it.
+    </para>
+    <programlisting>
+        list-&gt;next = old-&gt;next;
+    </programlisting>
+    <para>
+      There is <function>list_del_rcu()</function>
+      (<filename>include/linux/list.h</filename>) which does this (the
+      normal version poisons the old object, which we don't want).
+    </para>
+    <para>
+      The reader must also be careful: some CPUs can look through the
+      <symbol>next</symbol> pointer to start reading the contents of
+      the next element early, but don't realize that the pre-fetched
+      contents is wrong when the <symbol>next</symbol> pointer changes
+      underneath them.  Once again, there is a
+      <function>list_for_each_entry_rcu()</function>
+      (<filename>include/linux/list.h</filename>) to help you.  Of
+      course, writers can just use
+      <function>list_for_each_entry()</function>, since there cannot
+      be two simultaneous writers.
+    </para>
+    <para>
+      Our final dilemma is this: when can we actually destroy the
+      removed element?  Remember, a reader might be stepping through
+      this element in the list right now: it we free this element and
+      the <symbol>next</symbol> pointer changes, the reader will jump
+      off into garbage and crash.  We need to wait until we know that
+      all the readers who were traversing the list when we deleted the
+      element are finished.  We use <function>call_rcu()</function> to
+      register a callback which will actually destroy the object once
+      the readers are finished.
+    </para>
+    <para>
+      But how does Read Copy Update know when the readers are
+      finished?  The method is this: firstly, the readers always
+      traverse the list inside
+      <function>rcu_read_lock()</function>/<function>rcu_read_unlock()</function>
+      pairs: these simply disable preemption so the reader won't go to
+      sleep while reading the list.
+    </para>
+    <para>
+      RCU then waits until every other CPU has slept at least once:
+      since readers cannot sleep, we know that any readers which were
+      traversing the list during the deletion are finished, and the
+      callback is triggered.  The real Read Copy Update code is a
+      little more optimized than this, but this is the fundamental
+      idea.
+    </para>
+
+<programlisting>
+--- cache.c.perobjectlock	2003-12-11 17:15:03.000000000 +1100
++++ cache.c.rcupdate	2003-12-11 17:55:14.000000000 +1100
+@@ -1,15 +1,18 @@
+ #include &lt;linux/list.h&gt;
+ #include &lt;linux/slab.h&gt;
+ #include &lt;linux/string.h&gt;
++#include &lt;linux/rcupdate.h&gt;
+ #include &lt;asm/semaphore.h&gt;
+ #include &lt;asm/errno.h&gt;
+
+ struct object
+ {
+-        /* These two protected by cache_lock. */
++        /* This is protected by RCU */
+         struct list_head list;
+         int popularity;
+
++        struct rcu_head rcu;
++
+         atomic_t refcnt;
+
+         /* Doesn't change once created. */
+@@ -40,7 +43,7 @@
+ {
+         struct object *i;
+
+-        list_for_each_entry(i, &amp;cache, list) {
++        list_for_each_entry_rcu(i, &amp;cache, list) {
+                 if (i-&gt;id == id) {
+                         i-&gt;popularity++;
+                         return i;
+@@ -49,19 +52,25 @@
+         return NULL;
+ }
+
++/* Final discard done once we know no readers are looking. */
++static void cache_delete_rcu(void *arg)
++{
++        object_put(arg);
++}
++
+ /* Must be holding cache_lock */
+ static void __cache_delete(struct object *obj)
+ {
+         BUG_ON(!obj);
+-        list_del(&amp;obj-&gt;list);
+-        object_put(obj);
++        list_del_rcu(&amp;obj-&gt;list);
+         cache_num--;
++        call_rcu(&amp;obj-&gt;rcu, cache_delete_rcu, obj);
+ }
+
+ /* Must be holding cache_lock */
+ static void __cache_add(struct object *obj)
+ {
+-        list_add(&amp;obj-&gt;list, &amp;cache);
++        list_add_rcu(&amp;obj-&gt;list, &amp;cache);
+         if (++cache_num > MAX_CACHE_SIZE) {
+                 struct object *i, *outcast = NULL;
+                 list_for_each_entry(i, &amp;cache, list) {
+@@ -85,6 +94,7 @@
+         obj-&gt;popularity = 0;
+         atomic_set(&amp;obj-&gt;refcnt, 1); /* The cache holds a reference */
+         spin_lock_init(&amp;obj-&gt;lock);
++        INIT_RCU_HEAD(&amp;obj-&gt;rcu);
+
+         spin_lock_irqsave(&amp;cache_lock, flags);
+         __cache_add(obj);
+@@ -104,12 +114,11 @@
+ struct object *cache_find(int id)
+ {
+         struct object *obj;
+-        unsigned long flags;
+
+-        spin_lock_irqsave(&amp;cache_lock, flags);
++        rcu_read_lock();
+         obj = __cache_find(id);
+         if (obj)
+                 object_get(obj);
+-        spin_unlock_irqrestore(&amp;cache_lock, flags);
++        rcu_read_unlock();
+         return obj;
+ }
+</programlisting>
+
+<para>
+Note that the reader will alter the
+<structfield>popularity</structfield> member in
+<function>__cache_find()</function>, and now it doesn't hold a lock.
+One solution would be to make it an <type>atomic_t</type>, but for
+this usage, we don't really care about races: an approximate result is
+good enough, so I didn't change it.
+</para>
+
+<para>
+The result is that <function>cache_find()</function> requires no
+synchronization with any other functions, so is almost as fast on SMP
+as it would be on UP.
+</para>
+
+<para>
+There is a furthur optimization possible here: remember our original
+cache code, where there were no reference counts and the caller simply
+held the lock whenever using the object?  This is still possible: if
+you hold the lock, noone can delete the object, so you don't need to
+get and put the reference count.
+</para>
+
+<para>
+Now, because the 'read lock' in RCU is simply disabling preemption, a
+caller which always has preemption disabled between calling
+<function>cache_find()</function> and
+<function>object_put()</function> does not need to actually get and
+put the reference count: we could expose
+<function>__cache_find()</function> by making it non-static, and
+such callers could simply call that.
+</para>
+<para>
+The benefit here is that the reference count is not written to: the
+object is not altered in any way, which is much faster on SMP
+machines due to caching.
+</para>
+  </sect1>
+
+   <sect1 id="per-cpu">
+    <title>Per-CPU Data</title>
+
+    <para>
+      Another technique for avoiding locking which is used fairly
+      widely is to duplicate information for each CPU.  For example,
+      if you wanted to keep a count of a common condition, you could
+      use a spin lock and a single counter.  Nice and simple.
+    </para>
+
+    <para>
+      If that was too slow (it's usually not, but if you've got a
+      really big machine to test on and can show that it is), you
+      could instead use a counter for each CPU, then none of them need
+      an exclusive lock.  See <function>DEFINE_PER_CPU()</function>,
+      <function>get_cpu_var()</function> and
+      <function>put_cpu_var()</function>
+      (<filename class="headerfile">include/linux/percpu.h</filename>).
+    </para>
+
+    <para>
+      Of particular use for simple per-cpu counters is the
+      <type>local_t</type> type, and the
+      <function>cpu_local_inc()</function> and related functions,
+      which are more efficient than simple code on some architectures
+      (<filename class="headerfile">include/asm/local.h</filename>).
+    </para>
+
+    <para>
+      Note that there is no simple, reliable way of getting an exact
+      value of such a counter, without introducing more locks.  This
+      is not a problem for some uses.
+    </para>
+   </sect1>
+
+   <sect1 id="mostly-hardirq">
+    <title>Data Which Mostly Used By An IRQ Handler</title>
+
+    <para>
+      If data is always accessed from within the same IRQ handler, you
+      don't need a lock at all: the kernel already guarantees that the
+      irq handler will not run simultaneously on multiple CPUs.
+    </para>
+    <para>
+      Manfred Spraul points out that you can still do this, even if
+      the data is very occasionally accessed in user context or
+      softirqs/tasklets.  The irq handler doesn't use a lock, and
+      all other accesses are done as so:
+    </para>
+
+<programlisting>
+	spin_lock(&amp;lock);
+	disable_irq(irq);
+	...
+	enable_irq(irq);
+	spin_unlock(&amp;lock);
+</programlisting>
+    <para>
+      The <function>disable_irq()</function> prevents the irq handler
+      from running (and waits for it to finish if it's currently
+      running on other CPUs).  The spinlock prevents any other
+      accesses happening at the same time.  Naturally, this is slower
+      than just a <function>spin_lock_irq()</function> call, so it
+      only makes sense if this type of access happens extremely
+      rarely.
+    </para>
+   </sect1>
+  </chapter>
+
+ <chapter id="sleeping-things">
+    <title>What Functions Are Safe To Call From Interrupts?</title>
+
+    <para>
+      Many functions in the kernel sleep (ie. call schedule())
+      directly or indirectly: you can never call them while holding a
+      spinlock, or with preemption disabled.  This also means you need
+      to be in user context: calling them from an interrupt is illegal.
+    </para>
+
+   <sect1 id="sleeping">
+    <title>Some Functions Which Sleep</title>
+
+    <para>
+      The most common ones are listed below, but you usually have to
+      read the code to find out if other calls are safe.  If everyone
+      else who calls it can sleep, you probably need to be able to
+      sleep, too.  In particular, registration and deregistration
+      functions usually expect to be called from user context, and can
+      sleep.
+    </para>
+
+    <itemizedlist>
+     <listitem>
+      <para>
+        Accesses to 
+        <firstterm linkend="gloss-userspace">userspace</firstterm>:
+      </para>
+      <itemizedlist>
+       <listitem>
+        <para>
+          <function>copy_from_user()</function>
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+          <function>copy_to_user()</function>
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+          <function>get_user()</function>
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+          <function> put_user()</function>
+        </para>
+       </listitem>
+      </itemizedlist>
+     </listitem>
+
+     <listitem>
+      <para>
+        <function>kmalloc(GFP_KERNEL)</function>
+      </para>
+     </listitem>
+
+     <listitem>
+      <para>
+      <function>down_interruptible()</function> and
+      <function>down()</function>
+      </para>
+      <para>
+       There is a <function>down_trylock()</function> which can be
+       used inside interrupt context, as it will not sleep.
+       <function>up()</function> will also never sleep.
+      </para>
+     </listitem>
+    </itemizedlist>
+   </sect1>
+
+   <sect1 id="dont-sleep">
+    <title>Some Functions Which Don't Sleep</title>
+
+    <para>
+     Some functions are safe to call from any context, or holding
+     almost any lock.
+    </para>
+
+    <itemizedlist>
+     <listitem>
+      <para>
+	<function>printk()</function>
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+        <function>kfree()</function>
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+	<function>add_timer()</function> and <function>del_timer()</function>
+      </para>
+     </listitem>
+    </itemizedlist>
+   </sect1>
+  </chapter>
+
+  <chapter id="references">
+   <title>Further reading</title>
+
+   <itemizedlist>
+    <listitem>
+     <para>
+       <filename>Documentation/spinlocks.txt</filename>: 
+       Linus Torvalds' spinlocking tutorial in the kernel sources.
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+       Unix Systems for Modern Architectures: Symmetric
+       Multiprocessing and Caching for Kernel Programmers:
+     </para>
+
+     <para>
+       Curt Schimmel's very good introduction to kernel level
+       locking (not written for Linux, but nearly everything
+       applies).  The book is expensive, but really worth every
+       penny to understand SMP locking. [ISBN: 0201633388]
+     </para>
+    </listitem>
+   </itemizedlist>
+  </chapter>
+
+  <chapter id="thanks">
+    <title>Thanks</title>
+
+    <para>
+      Thanks to Telsa Gwynne for DocBooking, neatening and adding
+      style.
+    </para>
+
+    <para>
+      Thanks to Martin Pool, Philipp Rumpf, Stephen Rothwell, Paul
+      Mackerras, Ruedi Aschwanden, Alan Cox, Manfred Spraul, Tim
+      Waugh, Pete Zaitcev, James Morris, Robert Love, Paul McKenney,
+      John Ashby for proofreading, correcting, flaming, commenting.
+    </para>
+
+    <para>
+      Thanks to the cabal for having no influence on this document.
+    </para>
+  </chapter>
+
+  <glossary id="glossary">
+   <title>Glossary</title>
+
+   <glossentry id="gloss-preemption">
+    <glossterm>preemption</glossterm>
+     <glossdef>
+      <para>
+        Prior to 2.5, or when <symbol>CONFIG_PREEMPT</symbol> is
+        unset, processes in user context inside the kernel would not
+        preempt each other (ie. you had that CPU until you have it up,
+        except for interrupts).  With the addition of
+        <symbol>CONFIG_PREEMPT</symbol> in 2.5.4, this changed: when
+        in user context, higher priority tasks can "cut in": spinlocks
+        were changed to disable preemption, even on UP.
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-bh">
+    <glossterm>bh</glossterm>
+     <glossdef>
+      <para>
+        Bottom Half: for historical reasons, functions with
+        '_bh' in them often now refer to any software interrupt, e.g.
+        <function>spin_lock_bh()</function> blocks any software interrupt 
+        on the current CPU.  Bottom halves are deprecated, and will 
+        eventually be replaced by tasklets.  Only one bottom half will be 
+        running at any time.
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-hwinterrupt">
+    <glossterm>Hardware Interrupt / Hardware IRQ</glossterm>
+    <glossdef>
+     <para>
+       Hardware interrupt request.  <function>in_irq()</function> returns 
+       <returnvalue>true</returnvalue> in a hardware interrupt handler.
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-interruptcontext">
+    <glossterm>Interrupt Context</glossterm>
+    <glossdef>
+     <para>
+       Not user context: processing a hardware irq or software irq.
+       Indicated by the <function>in_interrupt()</function> macro 
+       returning <returnvalue>true</returnvalue>.
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-smp">
+    <glossterm><acronym>SMP</acronym></glossterm>
+    <glossdef>
+     <para>
+       Symmetric Multi-Processor: kernels compiled for multiple-CPU
+       machines.  (CONFIG_SMP=y).
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-softirq">
+    <glossterm>Software Interrupt / softirq</glossterm>
+    <glossdef>
+     <para>
+       Software interrupt handler.  <function>in_irq()</function> returns
+       <returnvalue>false</returnvalue>; <function>in_softirq()</function>
+       returns <returnvalue>true</returnvalue>.  Tasklets and softirqs
+	both fall into the category of 'software interrupts'.
+     </para>
+     <para>
+       Strictly speaking a softirq is one of up to 32 enumerated software
+       interrupts which can run on multiple CPUs at once.
+       Sometimes used to refer to tasklets as
+       well (ie. all software interrupts).
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-tasklet">
+    <glossterm>tasklet</glossterm>
+    <glossdef>
+     <para>
+       A dynamically-registrable software interrupt,
+       which is guaranteed to only run on one CPU at a time.
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-timers">
+    <glossterm>timer</glossterm>
+    <glossdef>
+     <para>
+       A dynamically-registrable software interrupt, which is run at
+       (or close to) a given time.  When running, it is just like a
+       tasklet (in fact, they are called from the TIMER_SOFTIRQ).
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-up">
+    <glossterm><acronym>UP</acronym></glossterm>
+    <glossdef>
+     <para>
+       Uni-Processor: Non-SMP.  (CONFIG_SMP=n).
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-usercontext">
+    <glossterm>User Context</glossterm>
+    <glossdef>
+     <para>
+       The kernel executing on behalf of a particular process (ie. a
+       system call or trap) or kernel thread.  You can tell which
+       process with the <symbol>current</symbol> macro.)  Not to
+       be confused with userspace.  Can be interrupted by software or
+       hardware interrupts.
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-userspace">
+    <glossterm>Userspace</glossterm>
+    <glossdef>
+     <para>
+       A process executing its own code outside the kernel.
+     </para>
+    </glossdef>
+   </glossentry>      
+
+  </glossary>
+</book>
+

+ 282 - 0
Documentation/DocBook/libata.tmpl

@@ -0,0 +1,282 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="libataDevGuide">
+ <bookinfo>
+  <title>libATA Developer's Guide</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Jeff</firstname>
+    <surname>Garzik</surname>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2003</year>
+   <holder>Jeff Garzik</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+   The contents of this file are subject to the Open
+   Software License version 1.1 that can be found at
+   <ulink url="http://www.opensource.org/licenses/osl-1.1.txt">http://www.opensource.org/licenses/osl-1.1.txt</ulink> and is included herein
+   by reference.
+   </para>
+
+   <para>
+   Alternatively, the contents of this file may be used under the terms
+   of the GNU General Public License version 2 (the "GPL") as distributed
+   in the kernel source COPYING file, in which case the provisions of
+   the GPL are applicable instead of the above.  If you wish to allow
+   the use of your version of this file only under the terms of the
+   GPL and not to allow others to use your version of this file under
+   the OSL, indicate your decision by deleting the provisions above and
+   replace them with the notice and other provisions required by the GPL.
+   If you do not delete the provisions above, a recipient may use your
+   version of this file under either the OSL or the GPL.
+   </para>
+
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="libataThanks">
+     <title>Thanks</title>
+  <para>
+  The bulk of the ATA knowledge comes thanks to long conversations with
+  Andre Hedrick (www.linux-ide.org).
+  </para>
+  <para>
+  Thanks to Alan Cox for pointing out similarities 
+  between SATA and SCSI, and in general for motivation to hack on
+  libata.
+  </para>
+  <para>
+  libata's device detection
+  method, ata_pio_devchk, and in general all the early probing was
+  based on extensive study of Hale Landis's probe/reset code in his
+  ATADRVR driver (www.ata-atapi.com).
+  </para>
+  </chapter>
+
+  <chapter id="libataDriverApi">
+     <title>libata Driver API</title>
+     <sect1>
+        <title>struct ata_port_operations</title>
+
+	<programlisting>
+void (*port_disable) (struct ata_port *);
+	</programlisting>
+
+	<para>
+	Called from ata_bus_probe() and ata_bus_reset() error paths,
+	as well as when unregistering from the SCSI module (rmmod, hot
+	unplug).
+	</para>
+
+	<programlisting>
+void (*dev_config) (struct ata_port *, struct ata_device *);
+	</programlisting>
+
+	<para>
+	Called after IDENTIFY [PACKET] DEVICE is issued to each device
+	found.  Typically used to apply device-specific fixups prior to
+	issue of SET FEATURES - XFER MODE, and prior to operation.
+	</para>
+
+	<programlisting>
+void (*set_piomode) (struct ata_port *, struct ata_device *);
+void (*set_dmamode) (struct ata_port *, struct ata_device *);
+void (*post_set_mode) (struct ata_port *ap);
+	</programlisting>
+
+	<para>
+	Hooks called prior to the issue of SET FEATURES - XFER MODE
+	command.  dev->pio_mode is guaranteed to be valid when
+	->set_piomode() is called, and dev->dma_mode is guaranteed to be
+	valid when ->set_dmamode() is called.  ->post_set_mode() is
+	called unconditionally, after the SET FEATURES - XFER MODE
+	command completes successfully.
+	</para>
+
+	<para>
+	->set_piomode() is always called (if present), but
+	->set_dma_mode() is only called if DMA is possible.
+	</para>
+
+	<programlisting>
+void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
+void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
+	</programlisting>
+
+	<para>
+	->tf_load() is called to load the given taskfile into hardware
+	registers / DMA buffers.  ->tf_read() is called to read the
+	hardware registers / DMA buffers, to obtain the current set of
+	taskfile register values.
+	</para>
+
+	<programlisting>
+void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
+	</programlisting>
+
+	<para>
+	causes an ATA command, previously loaded with
+	->tf_load(), to be initiated in hardware.
+	</para>
+
+	<programlisting>
+u8   (*check_status)(struct ata_port *ap);
+void (*dev_select)(struct ata_port *ap, unsigned int device);
+	</programlisting>
+
+	<para>
+	Reads the Status ATA shadow register from hardware.  On some
+	hardware, this has the side effect of clearing the interrupt
+	condition.
+	</para>
+
+	<programlisting>
+void (*dev_select)(struct ata_port *ap, unsigned int device);
+	</programlisting>
+
+	<para>
+	Issues the low-level hardware command(s) that causes one of N
+	hardware devices to be considered 'selected' (active and
+	available for use) on the ATA bus.
+	</para>
+
+	<programlisting>
+void (*phy_reset) (struct ata_port *ap);
+	</programlisting>
+
+	<para>
+	The very first step in the probe phase.  Actions vary depending
+	on the bus type, typically.  After waking up the device and probing
+	for device presence (PATA and SATA), typically a soft reset
+	(SRST) will be performed.  Drivers typically use the helper
+	functions ata_bus_reset() or sata_phy_reset() for this hook.
+	</para>
+
+	<programlisting>
+void (*bmdma_setup) (struct ata_queued_cmd *qc);
+void (*bmdma_start) (struct ata_queued_cmd *qc);
+	</programlisting>
+
+	<para>
+	When setting up an IDE BMDMA transaction, these hooks arm
+	(->bmdma_setup) and fire (->bmdma_start) the hardware's DMA
+	engine.
+	</para>
+
+	<programlisting>
+void (*qc_prep) (struct ata_queued_cmd *qc);
+int (*qc_issue) (struct ata_queued_cmd *qc);
+	</programlisting>
+
+	<para>
+	Higher-level hooks, these two hooks can potentially supercede
+	several of the above taskfile/DMA engine hooks.  ->qc_prep is
+	called after the buffers have been DMA-mapped, and is typically
+	used to populate the hardware's DMA scatter-gather table.
+	Most drivers use the standard ata_qc_prep() helper function, but
+	more advanced drivers roll their own.
+	</para>
+	<para>
+	->qc_issue is used to make a command active, once the hardware
+	and S/G tables have been prepared.  IDE BMDMA drivers use the
+	helper function ata_qc_issue_prot() for taskfile protocol-based
+	dispatch.  More advanced drivers roll their own ->qc_issue
+	implementation, using this as the "issue new ATA command to
+	hardware" hook.
+	</para>
+
+	<programlisting>
+void (*eng_timeout) (struct ata_port *ap);
+	</programlisting>
+
+	<para>
+	This is a high level error handling function, called from the
+	error handling thread, when a command times out.
+	</para>
+
+	<programlisting>
+irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
+void (*irq_clear) (struct ata_port *);
+	</programlisting>
+
+	<para>
+	->irq_handler is the interrupt handling routine registered with
+	the system, by libata.  ->irq_clear is called during probe just
+	before the interrupt handler is registered, to be sure hardware
+	is quiet.
+	</para>
+
+	<programlisting>
+u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
+void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
+                   u32 val);
+	</programlisting>
+
+	<para>
+	Read and write standard SATA phy registers.  Currently only used
+	if ->phy_reset hook called the sata_phy_reset() helper function.
+	</para>
+
+	<programlisting>
+int (*port_start) (struct ata_port *ap);
+void (*port_stop) (struct ata_port *ap);
+void (*host_stop) (struct ata_host_set *host_set);
+	</programlisting>
+
+	<para>
+	->port_start() is called just after the data structures for each
+	port are initialized.  Typically this is used to alloc per-port
+	DMA buffers / tables / rings, enable DMA engines, and similar
+	tasks.  
+	</para>
+	<para>
+	->host_stop() is called when the rmmod or hot unplug process
+	begins.  The hook must stop all hardware interrupts, DMA
+	engines, etc.
+	</para>
+	<para>
+	->port_stop() is called after ->host_stop().  It's sole function
+	is to release DMA/memory resources, now that they are no longer
+	actively being used.
+	</para>
+
+     </sect1>
+  </chapter>
+
+  <chapter id="libataExt">
+     <title>libata Library</title>
+!Edrivers/scsi/libata-core.c
+  </chapter>
+
+  <chapter id="libataInt">
+     <title>libata Core Internals</title>
+!Idrivers/scsi/libata-core.c
+  </chapter>
+
+  <chapter id="libataScsiInt">
+     <title>libata SCSI translation/emulation</title>
+!Edrivers/scsi/libata-scsi.c
+!Idrivers/scsi/libata-scsi.c
+  </chapter>
+
+  <chapter id="PiixInt">
+     <title>ata_piix Internals</title>
+!Idrivers/scsi/ata_piix.c
+  </chapter>
+
+  <chapter id="SILInt">
+     <title>sata_sil Internals</title>
+!Idrivers/scsi/sata_sil.c
+  </chapter>
+
+</book>

+ 289 - 0
Documentation/DocBook/librs.tmpl

@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="Reed-Solomon-Library-Guide">
+ <bookinfo>
+  <title>Reed-Solomon Library Programming Interface</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Thomas</firstname>
+    <surname>Gleixner</surname>
+    <affiliation>
+     <address>
+      <email>tglx@linutronix.de</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2004</year>
+   <holder>Thomas Gleixner</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License version 2 as published by the Free Software Foundation.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+  	The generic Reed-Solomon Library provides encoding, decoding
+	and error correction functions.
+  </para>
+  <para>
+  	Reed-Solomon codes are used in communication and storage
+	applications to ensure data integrity. 
+  </para>
+  <para>
+  	This documentation is provided for developers who want to utilize
+	the functions provided by the library.
+  </para>
+  </chapter>
+  
+  <chapter id="bugs">
+     <title>Known Bugs And Assumptions</title>
+  <para>
+	None.	
+  </para>
+  </chapter>
+
+  <chapter id="usage">
+     	<title>Usage</title>
+	<para>
+		This chapter provides examples how to use the library.
+	</para>
+	<sect1>
+		<title>Initializing</title>
+		<para>
+			The init function init_rs returns a pointer to a
+			rs decoder structure, which holds the necessary
+			information for encoding, decoding and error correction
+			with the given polynomial. It either uses an existing
+			matching decoder or creates a new one. On creation all
+			the lookup tables for fast en/decoding are created.
+			The function may take a while, so make sure not to 
+			call it in critical code paths.
+		</para>
+		<programlisting>
+/* the Reed Solomon control structure */
+static struct rs_control *rs_decoder;
+
+/* Symbolsize is 10 (bits)
+ * Primitve polynomial is x^10+x^3+1
+ * first consecutive root is 0
+ * primitve element to generate roots = 1
+ * generator polinomial degree (number of roots) = 6
+ */
+rs_decoder = init_rs (10, 0x409, 0, 1, 6);
+		</programlisting>
+	</sect1>
+	<sect1>
+		<title>Encoding</title>
+		<para>
+			The encoder calculates the Reed-Solomon code over
+			the given data length and stores the result in 
+			the parity buffer. Note that the parity buffer must
+			be initialized before calling the encoder.
+		</para>
+		<para>
+			The expanded data can be inverted on the fly by
+			providing a non zero inversion mask. The expanded data is
+			XOR'ed with the mask. This is used e.g. for FLASH
+			ECC, where the all 0xFF is inverted to an all 0x00.
+			The Reed-Solomon code for all 0x00 is all 0x00. The
+			code is inverted before storing to FLASH so it is 0xFF
+			too. This prevent's that reading from an erased FLASH
+			results in ECC errors.
+		</para>
+		<para>
+			The databytes are expanded to the given symbol size
+			on the fly. There is no support for encoding continuous
+			bitstreams with a symbol size != 8 at the moment. If
+			it is necessary it should be not a big deal to implement
+			such functionality.
+		</para>
+		<programlisting>
+/* Parity buffer. Size = number of roots */
+uint16_t par[6];
+/* Initialize the parity buffer */
+memset(par, 0, sizeof(par));
+/* Encode 512 byte in data8. Store parity in buffer par */
+encode_rs8 (rs_decoder, data8, 512, par, 0);
+		</programlisting>
+	</sect1>
+	<sect1>
+		<title>Decoding</title>
+		<para>
+			The decoder calculates the syndrome over
+			the given data length and the received parity symbols
+			and corrects errors in the data.
+		</para>
+		<para>
+			If a syndrome is available from a hardware decoder
+			then the syndrome calculation is skipped.
+		</para>
+		<para>
+			The correction of the data buffer can be suppressed
+			by providing a correction pattern buffer and an error
+			location buffer to the decoder. The decoder stores the
+			calculated error location and the correction bitmask
+			in the given buffers. This is useful for hardware
+			decoders which use a weird bit ordering scheme.
+		</para>
+		<para>
+			The databytes are expanded to the given symbol size
+			on the fly. There is no support for decoding continuous
+			bitstreams with a symbolsize != 8 at the moment. If
+			it is necessary it should be not a big deal to implement
+			such functionality.
+		</para>
+		
+		<sect2>
+		<title>
+			Decoding with syndrome calculation, direct data correction
+		</title>
+		<programlisting>
+/* Parity buffer. Size = number of roots */
+uint16_t par[6];
+uint8_t  data[512];
+int numerr;
+/* Receive data */
+.....
+/* Receive parity */
+.....
+/* Decode 512 byte in data8.*/
+numerr = decode_rs8 (rs_decoder, data8, par, 512, NULL, 0, NULL, 0, NULL);
+		</programlisting>
+		</sect2>
+
+		<sect2>
+		<title>
+			Decoding with syndrome given by hardware decoder, direct data correction
+		</title>
+		<programlisting>
+/* Parity buffer. Size = number of roots */
+uint16_t par[6], syn[6];
+uint8_t  data[512];
+int numerr;
+/* Receive data */
+.....
+/* Receive parity */
+.....
+/* Get syndrome from hardware decoder */
+.....
+/* Decode 512 byte in data8.*/
+numerr = decode_rs8 (rs_decoder, data8, par, 512, syn, 0, NULL, 0, NULL);
+		</programlisting>
+		</sect2>
+
+		<sect2>
+		<title>
+			Decoding with syndrome given by hardware decoder, no direct data correction.
+		</title>
+		<para>
+			Note: It's not necessary to give data and received parity to the decoder.
+		</para>
+		<programlisting>
+/* Parity buffer. Size = number of roots */
+uint16_t par[6], syn[6], corr[8];
+uint8_t  data[512];
+int numerr, errpos[8];
+/* Receive data */
+.....
+/* Receive parity */
+.....
+/* Get syndrome from hardware decoder */
+.....
+/* Decode 512 byte in data8.*/
+numerr = decode_rs8 (rs_decoder, NULL, NULL, 512, syn, 0, errpos, 0, corr);
+for (i = 0; i &lt; numerr; i++) {
+	do_error_correction_in_your_buffer(errpos[i], corr[i]);
+}
+		</programlisting>
+		</sect2>
+	</sect1>
+	<sect1>
+		<title>Cleanup</title>
+		<para>
+			The function free_rs frees the allocated resources,
+			if the caller is the last user of the decoder.
+		</para>
+		<programlisting>
+/* Release resources */
+free_rs(rs_decoder);
+		</programlisting>
+	</sect1>
+
+  </chapter>
+	
+  <chapter id="structs">
+     <title>Structures</title>
+     <para>
+     This chapter contains the autogenerated documentation of the structures which are
+     used in the Reed-Solomon Library and are relevant for a developer.
+     </para>
+!Iinclude/linux/rslib.h
+  </chapter>
+
+  <chapter id="pubfunctions">
+     <title>Public Functions Provided</title>
+     <para>
+     This chapter contains the autogenerated documentation of the Reed-Solomon functions
+     which are exported.
+     </para>
+!Elib/reed_solomon/reed_solomon.c
+  </chapter>
+  
+  <chapter id="credits">
+     <title>Credits</title>
+	<para>
+		The library code for encoding and decoding was written by Phil Karn.
+	</para>
+	<programlisting>
+		Copyright 2002, Phil Karn, KA9Q
+ 		May be used under the terms of the GNU General Public License (GPL)
+	</programlisting>
+	<para>
+		The wrapper functions and interfaces are written by Thomas Gleixner
+	</para>
+	<para>
+		Many users have provided bugfixes, improvements and helping hands for testing.
+		Thanks a lot.
+	</para>
+	<para>
+		The following people have contributed to this document:
+	</para>
+	<para>
+		Thomas Gleixner<email>tglx@linutronix.de</email>
+	</para>
+  </chapter>
+</book>

+ 265 - 0
Documentation/DocBook/lsm.tmpl

@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<article class="whitepaper" id="LinuxSecurityModule" lang="en">
+ <articleinfo>
+ <title>Linux Security Modules:  General Security Hooks for Linux</title>
+ <authorgroup>
+ <author>
+ <firstname>Stephen</firstname> 
+ <surname>Smalley</surname>
+ <affiliation>
+ <orgname>NAI Labs</orgname>
+ <address><email>ssmalley@nai.com</email></address>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>Timothy</firstname> 
+ <surname>Fraser</surname>
+ <affiliation>
+ <orgname>NAI Labs</orgname>
+ <address><email>tfraser@nai.com</email></address>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>Chris</firstname> 
+ <surname>Vance</surname>
+ <affiliation>
+ <orgname>NAI Labs</orgname>
+ <address><email>cvance@nai.com</email></address>
+ </affiliation>
+ </author>
+ </authorgroup>
+ </articleinfo>
+
+<sect1><title>Introduction</title>
+
+<para>
+In March 2001, the National Security Agency (NSA) gave a presentation
+about Security-Enhanced Linux (SELinux) at the 2.5 Linux Kernel
+Summit.  SELinux is an implementation of flexible and fine-grained
+nondiscretionary access controls in the Linux kernel, originally
+implemented as its own particular kernel patch.  Several other
+security projects (e.g. RSBAC, Medusa) have also developed flexible
+access control architectures for the Linux kernel, and various
+projects have developed particular access control models for Linux
+(e.g. LIDS, DTE, SubDomain).  Each project has developed and
+maintained its own kernel patch to support its security needs.
+</para>
+
+<para>
+In response to the NSA presentation, Linus Torvalds made a set of
+remarks that described a security framework he would be willing to
+consider for inclusion in the mainstream Linux kernel.  He described a
+general framework that would provide a set of security hooks to
+control operations on kernel objects and a set of opaque security
+fields in kernel data structures for maintaining security attributes.
+This framework could then be used by loadable kernel modules to
+implement any desired model of security.  Linus also suggested the
+possibility of migrating the Linux capabilities code into such a
+module.
+</para>
+
+<para>
+The Linux Security Modules (LSM) project was started by WireX to
+develop such a framework.  LSM is a joint development effort by
+several security projects, including Immunix, SELinux, SGI and Janus,
+and several individuals, including Greg Kroah-Hartman and James
+Morris, to develop a Linux kernel patch that implements this
+framework.  The patch is currently tracking the 2.4 series and is
+targeted for integration into the 2.5 development series.  This
+technical report provides an overview of the framework and the example
+capabilities security module provided by the LSM kernel patch.
+</para>
+
+</sect1>
+
+<sect1 id="framework"><title>LSM Framework</title>
+
+<para>
+The LSM kernel patch provides a general kernel framework to support
+security modules.  In particular, the LSM framework is primarily
+focused on supporting access control modules, although future
+development is likely to address other security needs such as
+auditing.  By itself, the framework does not provide any additional
+security; it merely provides the infrastructure to support security
+modules.  The LSM kernel patch also moves most of the capabilities
+logic into an optional security module, with the system defaulting
+to the traditional superuser logic.  This capabilities module
+is discussed further in <xref linkend="cap"/>.
+</para>
+
+<para>
+The LSM kernel patch adds security fields to kernel data structures
+and inserts calls to hook functions at critical points in the kernel
+code to manage the security fields and to perform access control.  It
+also adds functions for registering and unregistering security
+modules, and adds a general <function>security</function> system call
+to support new system calls for security-aware applications.
+</para>
+
+<para>
+The LSM security fields are simply <type>void*</type> pointers.  For
+process and program execution security information, security fields
+were added to <structname>struct task_struct</structname> and 
+<structname>struct linux_binprm</structname>.  For filesystem security
+information, a security field was added to 
+<structname>struct super_block</structname>.  For pipe, file, and socket
+security information, security fields were added to 
+<structname>struct inode</structname> and 
+<structname>struct file</structname>.  For packet and network device security
+information, security fields were added to
+<structname>struct sk_buff</structname> and
+<structname>struct net_device</structname>.  For System V IPC security
+information, security fields were added to
+<structname>struct kern_ipc_perm</structname> and
+<structname>struct msg_msg</structname>; additionally, the definitions
+for <structname>struct msg_msg</structname>, <structname>struct 
+msg_queue</structname>, and <structname>struct 
+shmid_kernel</structname> were moved to header files
+(<filename>include/linux/msg.h</filename> and
+<filename>include/linux/shm.h</filename> as appropriate) to allow
+the security modules to use these definitions.
+</para>
+
+<para>
+Each LSM hook is a function pointer in a global table,
+security_ops. This table is a
+<structname>security_operations</structname> structure as defined by
+<filename>include/linux/security.h</filename>.  Detailed documentation
+for each hook is included in this header file.  At present, this
+structure consists of a collection of substructures that group related
+hooks based on the kernel object (e.g. task, inode, file, sk_buff,
+etc) as well as some top-level hook function pointers for system
+operations.  This structure is likely to be flattened in the future
+for performance.  The placement of the hook calls in the kernel code
+is described by the "called:" lines in the per-hook documentation in
+the header file.  The hook calls can also be easily found in the
+kernel code by looking for the string "security_ops->".
+
+</para>
+
+<para>
+Linus mentioned per-process security hooks in his original remarks as a
+possible alternative to global security hooks.  However, if LSM were
+to start from the perspective of per-process hooks, then the base
+framework would have to deal with how to handle operations that
+involve multiple processes (e.g. kill), since each process might have
+its own hook for controlling the operation.  This would require a
+general mechanism for composing hooks in the base framework.
+Additionally, LSM would still need global hooks for operations that
+have no process context (e.g. network input operations).
+Consequently, LSM provides global security hooks, but a security
+module is free to implement per-process hooks (where that makes sense)
+by storing a security_ops table in each process' security field and
+then invoking these per-process hooks from the global hooks.
+The problem of composition is thus deferred to the module.
+</para>
+
+<para>
+The global security_ops table is initialized to a set of hook
+functions provided by a dummy security module that provides
+traditional superuser logic.  A <function>register_security</function>
+function (in <filename>security/security.c</filename>) is provided to
+allow a security module to set security_ops to refer to its own hook
+functions, and an <function>unregister_security</function> function is
+provided to revert security_ops to the dummy module hooks.  This
+mechanism is used to set the primary security module, which is
+responsible for making the final decision for each hook.
+</para>
+
+<para>
+LSM also provides a simple mechanism for stacking additional security
+modules with the primary security module.  It defines
+<function>register_security</function> and
+<function>unregister_security</function> hooks in the
+<structname>security_operations</structname> structure and provides
+<function>mod_reg_security</function> and
+<function>mod_unreg_security</function> functions that invoke these
+hooks after performing some sanity checking.  A security module can
+call these functions in order to stack with other modules.  However,
+the actual details of how this stacking is handled are deferred to the
+module, which can implement these hooks in any way it wishes
+(including always returning an error if it does not wish to support
+stacking).  In this manner, LSM again defers the problem of
+composition to the module.
+</para>
+
+<para>
+Although the LSM hooks are organized into substructures based on
+kernel object, all of the hooks can be viewed as falling into two
+major categories: hooks that are used to manage the security fields
+and hooks that are used to perform access control.  Examples of the
+first category of hooks include the
+<function>alloc_security</function> and
+<function>free_security</function> hooks defined for each kernel data
+structure that has a security field.  These hooks are used to allocate
+and free security structures for kernel objects.  The first category
+of hooks also includes hooks that set information in the security
+field after allocation, such as the <function>post_lookup</function>
+hook in <structname>struct inode_security_ops</structname>.  This hook
+is used to set security information for inodes after successful lookup
+operations.  An example of the second category of hooks is the
+<function>permission</function> hook in 
+<structname>struct inode_security_ops</structname>.  This hook checks
+permission when accessing an inode.
+</para>
+
+</sect1>
+
+<sect1 id="cap"><title>LSM Capabilities Module</title>
+
+<para>
+The LSM kernel patch moves most of the existing POSIX.1e capabilities
+logic into an optional security module stored in the file
+<filename>security/capability.c</filename>.  This change allows
+users who do not want to use capabilities to omit this code entirely
+from their kernel, instead using the dummy module for traditional
+superuser logic or any other module that they desire.  This change
+also allows the developers of the capabilities logic to maintain and
+enhance their code more freely, without needing to integrate patches
+back into the base kernel.
+</para>
+
+<para>
+In addition to moving the capabilities logic, the LSM kernel patch
+could move the capability-related fields from the kernel data
+structures into the new security fields managed by the security
+modules.  However, at present, the LSM kernel patch leaves the
+capability fields in the kernel data structures.  In his original
+remarks, Linus suggested that this might be preferable so that other
+security modules can be easily stacked with the capabilities module
+without needing to chain multiple security structures on the security field.
+It also avoids imposing extra overhead on the capabilities module
+to manage the security fields.  However, the LSM framework could
+certainly support such a move if it is determined to be desirable,
+with only a few additional changes described below.
+</para>
+
+<para>
+At present, the capabilities logic for computing process capabilities
+on <function>execve</function> and <function>set*uid</function>,
+checking capabilities for a particular process, saving and checking
+capabilities for netlink messages, and handling the
+<function>capget</function> and <function>capset</function> system
+calls have been moved into the capabilities module.  There are still a
+few locations in the base kernel where capability-related fields are
+directly examined or modified, but the current version of the LSM
+patch does allow a security module to completely replace the
+assignment and testing of capabilities.  These few locations would
+need to be changed if the capability-related fields were moved into
+the security field.  The following is a list of known locations that
+still perform such direct examination or modification of
+capability-related fields:
+<itemizedlist>
+<listitem><para><filename>fs/open.c</filename>:<function>sys_access</function></para></listitem>
+<listitem><para><filename>fs/lockd/host.c</filename>:<function>nlm_bind_host</function></para></listitem>
+<listitem><para><filename>fs/nfsd/auth.c</filename>:<function>nfsd_setuser</function></para></listitem>
+<listitem><para><filename>fs/proc/array.c</filename>:<function>task_cap</function></para></listitem>
+</itemizedlist>
+</para>
+
+</sect1>
+
+</article>

+ 3 - 0
Documentation/DocBook/man/Makefile

@@ -0,0 +1,3 @@
+# Rules are put in Documentation/DocBook
+
+clean-files := *.9.gz *.sgml manpage.links manpage.refs

+ 107 - 0
Documentation/DocBook/mcabook.tmpl

@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="MCAGuide">
+ <bookinfo>
+  <title>MCA Driver Programming Interface</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Alan</firstname>
+    <surname>Cox</surname>
+    <affiliation>
+     <address>
+      <email>alan@redhat.com</email>
+     </address>
+    </affiliation>
+   </author>
+   <author>
+    <firstname>David</firstname>
+    <surname>Weinehall</surname>
+   </author>
+   <author>
+    <firstname>Chris</firstname>
+    <surname>Beauregard</surname>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2000</year>
+   <holder>Alan Cox</holder>
+   <holder>David Weinehall</holder>
+   <holder>Chris Beauregard</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+	The MCA bus functions provide a generalised interface to find MCA
+	bus cards, to claim them for a driver, and to read and manipulate POS 
+	registers without being aware of the motherboard internals or 
+	certain deep magic specific to onboard devices.
+  </para>
+  <para>
+	The basic interface to the MCA bus devices is the slot. Each slot
+	is numbered and virtual slot numbers are assigned to the internal
+	devices. Using a pci_dev as other busses do does not really make
+	sense in the MCA context as the MCA bus resources require card
+	specific interpretation.
+  </para>
+  <para>
+	Finally the MCA bus functions provide a parallel set of DMA
+	functions mimicing the ISA bus DMA functions as closely as possible,
+	although also supporting the additional DMA functionality on the
+	MCA bus controllers.
+  </para>
+  </chapter>
+  <chapter id="bugs">
+     <title>Known Bugs And Assumptions</title>
+  <para>
+	None.	
+  </para>
+  </chapter>
+
+  <chapter id="pubfunctions">
+     <title>Public Functions Provided</title>
+!Earch/i386/kernel/mca.c
+  </chapter>
+
+  <chapter id="dmafunctions">
+     <title>DMA Functions Provided</title>
+!Iinclude/asm-i386/mca_dma.h
+  </chapter>
+
+</book>

+ 1320 - 0
Documentation/DocBook/mtdnand.tmpl

@@ -0,0 +1,1320 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="MTD-NAND-Guide">
+ <bookinfo>
+  <title>MTD NAND Driver Programming Interface</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Thomas</firstname>
+    <surname>Gleixner</surname>
+    <affiliation>
+     <address>
+      <email>tglx@linutronix.de</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2004</year>
+   <holder>Thomas Gleixner</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License version 2 as published by the Free Software Foundation.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+  	The generic NAND driver supports almost all NAND and AG-AND based
+	chips and connects them to the Memory Technology Devices (MTD)
+	subsystem of the Linux Kernel.
+  </para>
+  <para>
+  	This documentation is provided for developers who want to implement
+	board drivers or filesystem drivers suitable for NAND devices.
+  </para>
+  </chapter>
+  
+  <chapter id="bugs">
+     <title>Known Bugs And Assumptions</title>
+  <para>
+	None.	
+  </para>
+  </chapter>
+
+  <chapter id="dochints">
+     <title>Documentation hints</title>
+     <para>
+     The function and structure docs are autogenerated. Each function and 
+     struct member has a short description which is marked with an [XXX] identifier.
+     The following chapters explain the meaning of those identifiers.
+     </para>
+     <sect1>   
+	<title>Function identifiers [XXX]</title>
+     	<para>
+	The functions are marked with [XXX] identifiers in the short
+	comment. The identifiers explain the usage and scope of the
+	functions. Following identifiers are used:
+     	</para>
+	<itemizedlist>
+		<listitem><para>
+	  	[MTD Interface]</para><para>
+		These functions provide the interface to the MTD kernel API. 
+		They are not replacable and provide functionality
+		which is complete hardware independent.
+		</para></listitem>
+		<listitem><para>
+	  	[NAND Interface]</para><para>
+		These functions are exported and provide the interface to the NAND kernel API. 
+		</para></listitem>
+		<listitem><para>
+	  	[GENERIC]</para><para>
+		Generic functions are not replacable and provide functionality
+		which is complete hardware independent.
+		</para></listitem>
+		<listitem><para>
+	  	[DEFAULT]</para><para>
+		Default functions provide hardware related functionality which is suitable
+		for most of the implementations. These functions can be replaced by the
+		board driver if neccecary. Those functions are called via pointers in the
+		NAND chip description structure. The board driver can set the functions which
+		should be replaced by board dependend functions before calling nand_scan().
+		If the function pointer is NULL on entry to nand_scan() then the pointer
+		is set to the default function which is suitable for the detected chip type.
+		</para></listitem>
+	</itemizedlist>
+     </sect1>
+     <sect1>   
+	<title>Struct member identifiers [XXX]</title>
+     	<para>
+	The struct members are marked with [XXX] identifiers in the 
+	comment. The identifiers explain the usage and scope of the
+	members. Following identifiers are used:
+     	</para>
+	<itemizedlist>
+		<listitem><para>
+	  	[INTERN]</para><para>
+		These members are for NAND driver internal use only and must not be
+		modified. Most of these values are calculated from the chip geometry
+		information which is evaluated during nand_scan().
+		</para></listitem>
+		<listitem><para>
+	  	[REPLACEABLE]</para><para>
+		Replaceable members hold hardware related functions which can be 
+		provided by the board driver. The board driver can set the functions which
+		should be replaced by board dependend functions before calling nand_scan().
+		If the function pointer is NULL on entry to nand_scan() then the pointer
+		is set to the default function which is suitable for the detected chip type.
+		</para></listitem>
+		<listitem><para>
+	  	[BOARDSPECIFIC]</para><para>
+		Board specific members hold hardware related information which must
+		be provided by the board driver. The board driver must set the function
+		pointers and datafields before calling nand_scan().
+		</para></listitem>
+		<listitem><para>
+	  	[OPTIONAL]</para><para>
+		Optional members can hold information relevant for the board driver. The
+		generic NAND driver code does not use this information.
+		</para></listitem>
+	</itemizedlist>
+     </sect1>
+  </chapter>   
+
+  <chapter id="basicboarddriver">
+     	<title>Basic board driver</title>
+	<para>
+		For most boards it will be sufficient to provide just the
+		basic functions and fill out some really board dependend
+		members in the nand chip description structure.
+		See drivers/mtd/nand/skeleton for reference.
+	</para>
+	<sect1>
+		<title>Basic defines</title>
+		<para>
+			At least you have to provide a mtd structure and
+			a storage for the ioremap'ed chip address.
+			You can allocate the mtd structure using kmalloc
+			or you can allocate it statically.
+			In case of static allocation you have to allocate
+			a nand_chip structure too.
+		</para>
+		<para>
+			Kmalloc based example
+		</para>
+		<programlisting>
+static struct mtd_info *board_mtd;
+static unsigned long baseaddr;
+		</programlisting>
+		<para>
+			Static example
+		</para>
+		<programlisting>
+static struct mtd_info board_mtd;
+static struct nand_chip board_chip;
+static unsigned long baseaddr;
+		</programlisting>
+	</sect1>
+	<sect1>
+		<title>Partition defines</title>
+		<para>
+			If you want to divide your device into parititions, then
+			enable the configuration switch CONFIG_MTD_PARITIONS and define
+			a paritioning scheme suitable to your board.
+		</para>
+		<programlisting>
+#define NUM_PARTITIONS 2
+static struct mtd_partition partition_info[] = {
+	{ .name = "Flash partition 1",
+	  .offset =  0,
+	  .size =    8 * 1024 * 1024 },
+	{ .name = "Flash partition 2",
+	  .offset =  MTDPART_OFS_NEXT,
+	  .size =    MTDPART_SIZ_FULL },
+};
+		</programlisting>
+	</sect1>
+	<sect1>
+		<title>Hardware control function</title>
+		<para>
+			The hardware control function provides access to the 
+			control pins of the NAND chip(s). 
+			The access can be done by GPIO pins or by address lines.
+			If you use address lines, make sure that the timing
+			requirements are met.
+		</para>
+		<para>
+			<emphasis>GPIO based example</emphasis>
+		</para>
+		<programlisting>
+static void board_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+	switch(cmd){
+		case NAND_CTL_SETCLE: /* Set CLE pin high */ break;
+		case NAND_CTL_CLRCLE: /* Set CLE pin low */ break;
+		case NAND_CTL_SETALE: /* Set ALE pin high */ break;
+		case NAND_CTL_CLRALE: /* Set ALE pin low */ break;
+		case NAND_CTL_SETNCE: /* Set nCE pin low */ break;
+		case NAND_CTL_CLRNCE: /* Set nCE pin high */ break;
+	}
+}
+		</programlisting>
+		<para>
+			<emphasis>Address lines based example.</emphasis> It's assumed that the
+			nCE pin is driven by a chip select decoder.
+		</para>
+		<programlisting>
+static void board_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+	struct nand_chip *this = (struct nand_chip *) mtd->priv;
+	switch(cmd){
+		case NAND_CTL_SETCLE: this->IO_ADDR_W |= CLE_ADRR_BIT;  break;
+		case NAND_CTL_CLRCLE: this->IO_ADDR_W &amp;= ~CLE_ADRR_BIT; break;
+		case NAND_CTL_SETALE: this->IO_ADDR_W |= ALE_ADRR_BIT;  break;
+		case NAND_CTL_CLRALE: this->IO_ADDR_W &amp;= ~ALE_ADRR_BIT; break;
+	}
+}
+		</programlisting>
+	</sect1>
+	<sect1>
+		<title>Device ready function</title>
+		<para>
+			If the hardware interface has the ready busy pin of the NAND chip connected to a
+			GPIO or other accesible I/O pin, this function is used to read back the state of the
+			pin. The function has no arguments and should return 0, if the device is busy (R/B pin 
+			is low) and 1, if the device is ready (R/B pin is high).
+			If the hardware interface does not give access to the ready busy pin, then
+			the function must not be defined and the function pointer this->dev_ready is set to NULL.		
+		</para>
+	</sect1>
+	<sect1>
+		<title>Init function</title>
+		<para>
+			The init function allocates memory and sets up all the board
+			specific parameters and function pointers. When everything
+			is set up nand_scan() is called. This function tries to
+			detect and identify then chip. If a chip is found all the
+			internal data fields are initialized accordingly.
+			The structure(s) have to be zeroed out first and then filled with the neccecary 
+			information about the device.
+		</para>
+		<programlisting>
+int __init board_init (void)
+{
+	struct nand_chip *this;
+	int err = 0;
+
+	/* Allocate memory for MTD device structure and private data */
+	board_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL);
+	if (!board_mtd) {
+		printk ("Unable to allocate NAND MTD device structure.\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	/* Initialize structures */
+	memset ((char *) board_mtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip));
+
+	/* map physical adress */
+	baseaddr = (unsigned long)ioremap(CHIP_PHYSICAL_ADDRESS, 1024);
+	if(!baseaddr){
+		printk("Ioremap to access NAND chip failed\n");
+		err = -EIO;
+		goto out_mtd;
+	}
+
+	/* Get pointer to private data */
+	this = (struct nand_chip *) ();
+	/* Link the private data with the MTD structure */
+	board_mtd->priv = this;
+
+	/* Set address of NAND IO lines */
+	this->IO_ADDR_R = baseaddr;
+	this->IO_ADDR_W = baseaddr;
+	/* Reference hardware control function */
+	this->hwcontrol = board_hwcontrol;
+	/* Set command delay time, see datasheet for correct value */
+	this->chip_delay = CHIP_DEPENDEND_COMMAND_DELAY;
+	/* Assign the device ready function, if available */
+	this->dev_ready = board_dev_ready;
+	this->eccmode = NAND_ECC_SOFT;
+
+	/* Scan to find existance of the device */
+	if (nand_scan (board_mtd, 1)) {
+		err = -ENXIO;
+		goto out_ior;
+	}
+	
+	add_mtd_partitions(board_mtd, partition_info, NUM_PARTITIONS);
+	goto out;
+
+out_ior:
+	iounmap((void *)baseaddr);
+out_mtd:
+	kfree (board_mtd);
+out:
+	return err;
+}
+module_init(board_init);
+		</programlisting>
+	</sect1>
+	<sect1>
+		<title>Exit function</title>
+		<para>
+			The exit function is only neccecary if the driver is
+			compiled as a module. It releases all resources which
+			are held by the chip driver and unregisters the partitions
+			in the MTD layer.
+		</para>
+		<programlisting>
+#ifdef MODULE
+static void __exit board_cleanup (void)
+{
+	/* Release resources, unregister device */
+	nand_release (board_mtd);
+
+	/* unmap physical adress */
+	iounmap((void *)baseaddr);
+	
+	/* Free the MTD device structure */
+	kfree (board_mtd);
+}
+module_exit(board_cleanup);
+#endif
+		</programlisting>
+	</sect1>
+  </chapter>
+
+  <chapter id="boarddriversadvanced">
+     	<title>Advanced board driver functions</title>
+	<para>
+		This chapter describes the advanced functionality of the NAND
+		driver. For a list of functions which can be overridden by the board
+		driver see the documentation of the nand_chip structure.
+	</para>
+	<sect1>
+		<title>Multiple chip control</title>
+		<para>
+			The nand driver can control chip arrays. Therefor the
+			board driver must provide an own select_chip function. This
+			function must (de)select the requested chip.
+			The function pointer in the nand_chip structure must
+			be set before calling nand_scan(). The maxchip parameter
+			of nand_scan() defines the maximum number of chips to
+			scan for. Make sure that the select_chip function can
+			handle the requested number of chips.
+		</para>
+		<para>
+			The nand driver concatenates the chips to one virtual
+			chip and provides this virtual chip to the MTD layer.
+		</para>
+		<para>
+			<emphasis>Note: The driver can only handle linear chip arrays
+			of equally sized chips. There is no support for
+			parallel arrays which extend the buswidth.</emphasis>
+		</para>
+		<para>
+			<emphasis>GPIO based example</emphasis>
+		</para>
+		<programlisting>
+static void board_select_chip (struct mtd_info *mtd, int chip)
+{
+	/* Deselect all chips, set all nCE pins high */
+	GPIO(BOARD_NAND_NCE) |= 0xff;	
+	if (chip >= 0)
+		GPIO(BOARD_NAND_NCE) &amp;= ~ (1 &lt;&lt; chip);
+}
+		</programlisting>
+		<para>
+			<emphasis>Address lines based example.</emphasis>
+			Its assumed that the nCE pins are connected to an
+			address decoder.
+		</para>
+		<programlisting>
+static void board_select_chip (struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *this = (struct nand_chip *) mtd->priv;
+	
+	/* Deselect all chips */
+	this->IO_ADDR_R &amp;= ~BOARD_NAND_ADDR_MASK;
+	this->IO_ADDR_W &amp;= ~BOARD_NAND_ADDR_MASK;
+	switch (chip) {
+	case 0:
+		this->IO_ADDR_R |= BOARD_NAND_ADDR_CHIP0;
+		this->IO_ADDR_W |= BOARD_NAND_ADDR_CHIP0;
+		break;
+	....	
+	case n:
+		this->IO_ADDR_R |= BOARD_NAND_ADDR_CHIPn;
+		this->IO_ADDR_W |= BOARD_NAND_ADDR_CHIPn;
+		break;
+	}	
+}
+		</programlisting>
+	</sect1>
+	<sect1>
+		<title>Hardware ECC support</title>
+		<sect2>
+			<title>Functions and constants</title>
+			<para>
+				The nand driver supports three different types of
+				hardware ECC.
+				<itemizedlist>
+				<listitem><para>NAND_ECC_HW3_256</para><para>
+				Hardware ECC generator providing 3 bytes ECC per
+				256 byte.
+				</para>	</listitem>
+				<listitem><para>NAND_ECC_HW3_512</para><para>
+				Hardware ECC generator providing 3 bytes ECC per
+				512 byte.
+				</para>	</listitem>
+				<listitem><para>NAND_ECC_HW6_512</para><para>
+				Hardware ECC generator providing 6 bytes ECC per
+				512 byte.
+				</para>	</listitem>
+				<listitem><para>NAND_ECC_HW8_512</para><para>
+				Hardware ECC generator providing 6 bytes ECC per
+				512 byte.
+				</para>	</listitem>
+				</itemizedlist>
+				If your hardware generator has a different functionality
+				add it at the appropriate place in nand_base.c
+			</para>
+			<para>
+				The board driver must provide following functions:
+				<itemizedlist>
+				<listitem><para>enable_hwecc</para><para>
+				This function is called before reading / writing to
+				the chip. Reset or initialize the hardware generator
+				in this function. The function is called with an
+				argument which let you distinguish between read 
+				and write operations.
+				</para>	</listitem>
+				<listitem><para>calculate_ecc</para><para>
+				This function is called after read / write from / to
+				the chip. Transfer the ECC from the hardware to
+				the buffer. If the option NAND_HWECC_SYNDROME is set
+				then the function is only called on write. See below.
+				</para>	</listitem>
+				<listitem><para>correct_data</para><para>
+				In case of an ECC error this function is called for
+				error detection and correction. Return 1 respectively 2
+				in case the error can be corrected. If the error is
+				not correctable return -1. If your hardware generator
+				matches the default algorithm of the nand_ecc software
+				generator then use the correction function provided
+				by nand_ecc instead of implementing duplicated code.
+				</para>	</listitem>
+				</itemizedlist>
+			</para>
+		</sect2>
+		<sect2>
+		<title>Hardware ECC with syndrome calculation</title>
+			<para>
+				Many hardware ECC implementations provide Reed-Solomon
+				codes and calculate an error syndrome on read. The syndrome
+				must be converted to a standard Reed-Solomon syndrome
+				before calling the error correction code in the generic
+				Reed-Solomon library.
+			</para>
+			<para>
+				The ECC bytes must be placed immidiately after the data
+				bytes in order to make the syndrome generator work. This
+				is contrary to the usual layout used by software ECC. The
+				seperation of data and out of band area is not longer
+				possible. The nand driver code handles this layout and
+				the remaining free bytes in the oob area are managed by 
+				the autoplacement code. Provide a matching oob-layout
+				in this case. See rts_from4.c and diskonchip.c for 
+				implementation reference. In those cases we must also
+				use bad block tables on FLASH, because the ECC layout is
+				interferring with the bad block marker positions.
+				See bad block table support for details.
+			</para>
+		</sect2>
+	</sect1>
+	<sect1>
+		<title>Bad block table support</title>
+		<para>
+			Most NAND chips mark the bad blocks at a defined
+			position in the spare area. Those blocks must 
+			not be erased under any circumstances as the bad 
+			block information would be lost.
+			It is possible to check the bad block mark each
+			time when the blocks are accessed by reading the
+			spare area of the first page in the block. This
+			is time consuming so a bad block table is used.
+		</para>
+		<para>
+			The nand driver supports various types of bad block
+			tables.
+			<itemizedlist>
+			<listitem><para>Per device</para><para>
+			The bad block table contains all bad block information
+			of the device which can consist of multiple chips.
+			</para>	</listitem>
+			<listitem><para>Per chip</para><para>
+			A bad block table is used per chip and contains the
+			bad block information for this particular chip.
+			</para>	</listitem>
+			<listitem><para>Fixed offset</para><para>
+			The bad block table is located at a fixed offset
+			in the chip (device). This applies to various
+			DiskOnChip devices.
+			</para>	</listitem>
+			<listitem><para>Automatic placed</para><para>
+			The bad block table is automatically placed and
+			detected either at the end or at the beginning
+			of a chip (device)
+			</para>	</listitem>
+			<listitem><para>Mirrored tables</para><para>
+			The bad block table is mirrored on the chip (device) to
+			allow updates of the bad block table without data loss.
+			</para>	</listitem>
+			</itemizedlist>
+		</para>
+		<para>	
+			nand_scan() calls the function nand_default_bbt(). 
+			nand_default_bbt() selects appropriate default
+			bad block table desriptors depending on the chip information
+			which was retrieved by nand_scan().
+		</para>
+		<para>
+			The standard policy is scanning the device for bad 
+			blocks and build a ram based bad block table which
+			allows faster access than always checking the
+			bad block information on the flash chip itself.
+		</para>
+		<sect2>
+			<title>Flash based tables</title>
+			<para>
+				It may be desired or neccecary to keep a bad block table in FLASH. 
+				For AG-AND chips this is mandatory, as they have no factory marked
+				bad blocks. They have factory marked good blocks. The marker pattern
+				is erased when the block is erased to be reused. So in case of
+				powerloss before writing the pattern back to the chip this block 
+				would be lost and added to the bad blocks. Therefor we scan the 
+				chip(s) when we detect them the first time for good blocks and 
+				store this information in a bad block table before erasing any 
+				of the blocks.
+			</para>
+			<para>
+				The blocks in which the tables are stored are procteted against
+				accidental access by marking them bad in the memory bad block
+				table. The bad block table managment functions are allowed
+				to circumvernt this protection.
+			</para>
+			<para>
+				The simplest way to activate the FLASH based bad block table support 
+				is to set the option NAND_USE_FLASH_BBT in the option field of
+				the nand chip structure before calling nand_scan(). For AG-AND
+				chips is this done by default.
+				This activates the default FLASH based bad block table functionality 
+				of the NAND driver. The default bad block table options are
+				<itemizedlist>
+				<listitem><para>Store bad block table per chip</para></listitem>
+				<listitem><para>Use 2 bits per block</para></listitem>
+				<listitem><para>Automatic placement at the end of the chip</para></listitem>
+				<listitem><para>Use mirrored tables with version numbers</para></listitem>
+				<listitem><para>Reserve 4 blocks at the end of the chip</para></listitem>
+				</itemizedlist>
+			</para>
+		</sect2>
+		<sect2>
+			<title>User defined tables</title>
+			<para>
+				User defined tables are created by filling out a 
+				nand_bbt_descr structure and storing the pointer in the
+				nand_chip structure member bbt_td before calling nand_scan(). 
+				If a mirror table is neccecary a second structure must be
+				created and a pointer to this structure must be stored
+				in bbt_md inside the nand_chip structure. If the bbt_md 
+				member is set to NULL then only the main table is used
+				and no scan for the mirrored table is performed.
+			</para>
+			<para>
+				The most important field in the nand_bbt_descr structure
+				is the options field. The options define most of the 
+				table properties. Use the predefined constants from
+				nand.h to define the options.
+				<itemizedlist>
+				<listitem><para>Number of bits per block</para>
+				<para>The supported number of bits is 1, 2, 4, 8.</para></listitem>
+				<listitem><para>Table per chip</para>
+				<para>Setting the constant NAND_BBT_PERCHIP selects that
+				a bad block table is managed for each chip in a chip array.
+				If this option is not set then a per device bad block table
+				is used.</para></listitem>
+				<listitem><para>Table location is absolute</para>
+				<para>Use the option constant NAND_BBT_ABSPAGE and
+				define the absolute page number where the bad block
+				table starts in the field pages. If you have selected bad block
+				tables per chip and you have a multi chip array then the start page
+				must be given for each chip in the chip array. Note: there is no scan
+				for a table ident pattern performed, so the fields 
+				pattern, veroffs, offs, len can be left uninitialized</para></listitem>
+				<listitem><para>Table location is automatically detected</para>
+				<para>The table can either be located in the first or the last good
+				blocks of the chip (device). Set NAND_BBT_LASTBLOCK to place
+				the bad block table at the end of the chip (device). The
+				bad block tables are marked and identified by a pattern which
+				is stored in the spare area of the first page in the block which
+				holds the bad block table. Store a pointer to the pattern  
+				in the pattern field. Further the length of the pattern has to be 
+				stored in len and the offset in the spare area must be given
+				in the offs member of the nand_bbt_descr stucture. For mirrored
+				bad block tables different patterns are mandatory.</para></listitem>
+				<listitem><para>Table creation</para>
+				<para>Set the option NAND_BBT_CREATE to enable the table creation
+				if no table can be found during the scan. Usually this is done only 
+				once if a new chip is found. </para></listitem>
+				<listitem><para>Table write support</para>
+				<para>Set the option NAND_BBT_WRITE to enable the table write support.
+				This allows the update of the bad block table(s) in case a block has
+				to be marked bad due to wear. The MTD interface function block_markbad
+				is calling the update function of the bad block table. If the write
+				support is enabled then the table is updated on FLASH.</para>
+				<para>
+				Note: Write support should only be enabled for mirrored tables with
+				version control.
+				</para></listitem>
+				<listitem><para>Table version control</para>
+				<para>Set the option NAND_BBT_VERSION to enable the table version control.
+				It's highly recommended to enable this for mirrored tables with write
+				support. It makes sure that the risk of loosing the bad block
+				table information is reduced to the loss of the information about the
+				one worn out block which should be marked bad. The version is stored in
+				4 consecutive bytes in the spare area of the device. The position of
+				the version number is defined by the member veroffs in the bad block table
+				descriptor.</para></listitem>
+				<listitem><para>Save block contents on write</para>
+				<para>
+				In case that the block which holds the bad block table does contain
+				other useful information, set the option NAND_BBT_SAVECONTENT. When
+				the bad block table is written then the whole block is read the bad
+				block table is updated and the block is erased and everything is 
+				written back. If this option is not set only the bad block table
+				is written and everything else in the block is ignored and erased.
+				</para></listitem>
+				<listitem><para>Number of reserved blocks</para>
+				<para>
+				For automatic placement some blocks must be reserved for
+				bad block table storage. The number of reserved blocks is defined 
+				in the maxblocks member of the babd block table description structure.
+				Reserving 4 blocks for mirrored tables should be a reasonable number. 
+				This also limits the number of blocks which are scanned for the bad
+				block table ident pattern.
+				</para></listitem>
+				</itemizedlist>
+			</para>
+		</sect2>
+	</sect1>
+	<sect1>
+		<title>Spare area (auto)placement</title>
+		<para>
+			The nand driver implements different possibilities for
+			placement of filesystem data in the spare area, 
+			<itemizedlist>
+			<listitem><para>Placement defined by fs driver</para></listitem>
+			<listitem><para>Automatic placement</para></listitem>
+			</itemizedlist>
+			The default placement function is automatic placement. The
+			nand driver has built in default placement schemes for the
+			various chiptypes. If due to hardware ECC functionality the
+			default placement does not fit then the board driver can
+			provide a own placement scheme.
+		</para>
+		<para>
+			File system drivers can provide a own placement scheme which
+			is used instead of the default placement scheme.
+		</para>
+		<para>
+			Placement schemes are defined by a nand_oobinfo structure
+	     		<programlisting>
+struct nand_oobinfo {
+	int	useecc;
+	int	eccbytes;
+	int	eccpos[24];
+	int	oobfree[8][2];
+};
+	     		</programlisting>
+			<itemizedlist>
+			<listitem><para>useecc</para><para>
+				The useecc member controls the ecc and placement function. The header
+				file include/mtd/mtd-abi.h contains constants to select ecc and
+				placement. MTD_NANDECC_OFF switches off the ecc complete. This is
+				not recommended and available for testing and diagnosis only.
+				MTD_NANDECC_PLACE selects caller defined placement, MTD_NANDECC_AUTOPLACE
+				selects automatic placement.
+			</para></listitem>
+			<listitem><para>eccbytes</para><para>
+				The eccbytes member defines the number of ecc bytes per page.
+			</para></listitem>
+			<listitem><para>eccpos</para><para>
+				The eccpos array holds the byte offsets in the spare area where
+				the ecc codes are placed.
+			</para></listitem>
+			<listitem><para>oobfree</para><para>
+				The oobfree array defines the areas in the spare area which can be
+				used for automatic placement. The information is given in the format
+				{offset, size}. offset defines the start of the usable area, size the
+				length in bytes. More than one area can be defined. The list is terminated
+				by an {0, 0} entry.
+			</para></listitem>
+			</itemizedlist>
+		</para>
+		<sect2>
+			<title>Placement defined by fs driver</title>
+			<para>
+				The calling function provides a pointer to a nand_oobinfo
+				structure which defines the ecc placement. For writes the
+				caller must provide a spare area buffer along with the
+				data buffer. The spare area buffer size is (number of pages) *
+				(size of spare area). For reads the buffer size is
+				(number of pages) * ((size of spare area) + (number of ecc
+				steps per page) * sizeof (int)). The driver stores the
+				result of the ecc check for each tuple in the spare buffer.
+				The storage sequence is 
+			</para>
+			<para>
+				&lt;spare data page 0&gt;&lt;ecc result 0&gt;...&lt;ecc result n&gt;
+			</para>
+			<para>
+				...
+			</para>
+			<para>
+				&lt;spare data page n&gt;&lt;ecc result 0&gt;...&lt;ecc result n&gt;
+			</para>
+			<para>
+				This is a legacy mode used by YAFFS1.
+			</para>
+			<para>
+				If the spare area buffer is NULL then only the ECC placement is
+				done according to the given scheme in the nand_oobinfo structure.
+			</para>
+		</sect2>
+		<sect2>
+			<title>Automatic placement</title>
+			<para>
+				Automatic placement uses the built in defaults to place the
+				ecc bytes in the spare area. If filesystem data have to be stored /
+				read into the spare area then the calling function must provide a
+				buffer. The buffer size per page is determined by the oobfree array in
+				the nand_oobinfo structure.
+			</para>
+			<para>
+				If the spare area buffer is NULL then only the ECC placement is
+				done according to the default builtin scheme.
+			</para>
+		</sect2>
+		<sect2>
+			<title>User space placement selection</title>
+		<para>
+			All non ecc functions like mtd->read and mtd->write use an internal 
+			structure, which can be set by an ioctl. This structure is preset 
+			to the autoplacement default.
+	     		<programlisting>
+	ioctl (fd, MEMSETOOBSEL, oobsel);
+	     		</programlisting>
+			oobsel is a pointer to a user supplied structure of type
+			nand_oobconfig. The contents of this structure must match the 
+			criteria of the filesystem, which will be used. See an example in utils/nandwrite.c.
+		</para>
+		</sect2>
+	</sect1>	
+	<sect1>
+		<title>Spare area autoplacement default schemes</title>
+		<sect2>
+			<title>256 byte pagesize</title>
+<informaltable><tgroup cols="3"><tbody>
+<row>
+<entry>Offset</entry>
+<entry>Content</entry>
+<entry>Comment</entry>
+</row>
+<row>
+<entry>0x00</entry>
+<entry>ECC byte 0</entry>
+<entry>Error correction code byte 0</entry>
+</row>
+<row>
+<entry>0x01</entry>
+<entry>ECC byte 1</entry>
+<entry>Error correction code byte 1</entry>
+</row>
+<row>
+<entry>0x02</entry>
+<entry>ECC byte 2</entry>
+<entry>Error correction code byte 2</entry>
+</row>
+<row>
+<entry>0x03</entry>
+<entry>Autoplace 0</entry>
+<entry></entry>
+</row>
+<row>
+<entry>0x04</entry>
+<entry>Autoplace 1</entry>
+<entry></entry>
+</row>
+<row>
+<entry>0x05</entry>
+<entry>Bad block marker</entry>
+<entry>If any bit in this byte is zero, then this block is bad.
+This applies only to the first page in a block. In the remaining
+pages this byte is reserved</entry>
+</row>
+<row>
+<entry>0x06</entry>
+<entry>Autoplace 2</entry>
+<entry></entry>
+</row>
+<row>
+<entry>0x07</entry>
+<entry>Autoplace 3</entry>
+<entry></entry>
+</row>
+</tbody></tgroup></informaltable>
+		</sect2>
+		<sect2>
+			<title>512 byte pagesize</title>
+<informaltable><tgroup cols="3"><tbody>
+<row>
+<entry>Offset</entry>
+<entry>Content</entry>
+<entry>Comment</entry>
+</row>
+<row>
+<entry>0x00</entry>
+<entry>ECC byte 0</entry>
+<entry>Error correction code byte 0 of the lower 256 Byte data in
+this page</entry>
+</row>
+<row>
+<entry>0x01</entry>
+<entry>ECC byte 1</entry>
+<entry>Error correction code byte 1 of the lower 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x02</entry>
+<entry>ECC byte 2</entry>
+<entry>Error correction code byte 2 of the lower 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x03</entry>
+<entry>ECC byte 3</entry>
+<entry>Error correction code byte 0 of the upper 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x04</entry>
+<entry>reserved</entry>
+<entry>reserved</entry>
+</row>
+<row>
+<entry>0x05</entry>
+<entry>Bad block marker</entry>
+<entry>If any bit in this byte is zero, then this block is bad.
+This applies only to the first page in a block. In the remaining
+pages this byte is reserved</entry>
+</row>
+<row>
+<entry>0x06</entry>
+<entry>ECC byte 4</entry>
+<entry>Error correction code byte 1 of the upper 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x07</entry>
+<entry>ECC byte 5</entry>
+<entry>Error correction code byte 2 of the upper 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x08 - 0x0F</entry>
+<entry>Autoplace 0 - 7</entry>
+<entry></entry>
+</row>
+</tbody></tgroup></informaltable>
+		</sect2>
+		<sect2>
+			<title>2048 byte pagesize</title>
+<informaltable><tgroup cols="3"><tbody>
+<row>
+<entry>Offset</entry>
+<entry>Content</entry>
+<entry>Comment</entry>
+</row>
+<row>
+<entry>0x00</entry>
+<entry>Bad block marker</entry>
+<entry>If any bit in this byte is zero, then this block is bad.
+This applies only to the first page in a block. In the remaining
+pages this byte is reserved</entry>
+</row>
+<row>
+<entry>0x01</entry>
+<entry>Reserved</entry>
+<entry>Reserved</entry>
+</row>
+<row>
+<entry>0x02-0x27</entry>
+<entry>Autoplace 0 - 37</entry>
+<entry></entry>
+</row>
+<row>
+<entry>0x28</entry>
+<entry>ECC byte 0</entry>
+<entry>Error correction code byte 0 of the first 256 Byte data in
+this page</entry>
+</row>
+<row>
+<entry>0x29</entry>
+<entry>ECC byte 1</entry>
+<entry>Error correction code byte 1 of the first 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x2A</entry>
+<entry>ECC byte 2</entry>
+<entry>Error correction code byte 2 of the first 256 Bytes data in
+this page</entry>
+</row>
+<row>
+<entry>0x2B</entry>
+<entry>ECC byte 3</entry>
+<entry>Error correction code byte 0 of the second 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x2C</entry>
+<entry>ECC byte 4</entry>
+<entry>Error correction code byte 1 of the second 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x2D</entry>
+<entry>ECC byte 5</entry>
+<entry>Error correction code byte 2 of the second 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x2E</entry>
+<entry>ECC byte 6</entry>
+<entry>Error correction code byte 0 of the third 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x2F</entry>
+<entry>ECC byte 7</entry>
+<entry>Error correction code byte 1 of the third 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x30</entry>
+<entry>ECC byte 8</entry>
+<entry>Error correction code byte 2 of the third 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x31</entry>
+<entry>ECC byte 9</entry>
+<entry>Error correction code byte 0 of the fourth 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x32</entry>
+<entry>ECC byte 10</entry>
+<entry>Error correction code byte 1 of the fourth 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x33</entry>
+<entry>ECC byte 11</entry>
+<entry>Error correction code byte 2 of the fourth 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x34</entry>
+<entry>ECC byte 12</entry>
+<entry>Error correction code byte 0 of the fifth 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x35</entry>
+<entry>ECC byte 13</entry>
+<entry>Error correction code byte 1 of the fifth 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x36</entry>
+<entry>ECC byte 14</entry>
+<entry>Error correction code byte 2 of the fifth 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x37</entry>
+<entry>ECC byte 15</entry>
+<entry>Error correction code byte 0 of the sixt 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x38</entry>
+<entry>ECC byte 16</entry>
+<entry>Error correction code byte 1 of the sixt 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x39</entry>
+<entry>ECC byte 17</entry>
+<entry>Error correction code byte 2 of the sixt 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x3A</entry>
+<entry>ECC byte 18</entry>
+<entry>Error correction code byte 0 of the seventh 256 Bytes of
+data in this page</entry>
+</row>
+<row>
+<entry>0x3B</entry>
+<entry>ECC byte 19</entry>
+<entry>Error correction code byte 1 of the seventh 256 Bytes of
+data in this page</entry>
+</row>
+<row>
+<entry>0x3C</entry>
+<entry>ECC byte 20</entry>
+<entry>Error correction code byte 2 of the seventh 256 Bytes of
+data in this page</entry>
+</row>
+<row>
+<entry>0x3D</entry>
+<entry>ECC byte 21</entry>
+<entry>Error correction code byte 0 of the eigth 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x3E</entry>
+<entry>ECC byte 22</entry>
+<entry>Error correction code byte 1 of the eigth 256 Bytes of data
+in this page</entry>
+</row>
+<row>
+<entry>0x3F</entry>
+<entry>ECC byte 23</entry>
+<entry>Error correction code byte 2 of the eigth 256 Bytes of data
+in this page</entry>
+</row>
+</tbody></tgroup></informaltable>
+		</sect2>
+     	</sect1>
+  </chapter>
+
+  <chapter id="filesystems">
+     	<title>Filesystem support</title>
+	<para>
+		The NAND driver provides all neccecary functions for a
+		filesystem via the MTD interface.
+	</para>
+	<para>
+		Filesystems must be aware of the NAND pecularities and
+		restrictions. One major restrictions of NAND Flash is, that you cannot 
+		write as often as you want to a page. The consecutive writes to a page, 
+		before erasing it again, are restricted to 1-3 writes, depending on the 
+		manufacturers specifications. This applies similar to the spare area. 
+	</para>
+	<para>
+		Therefor NAND aware filesystems must either write in page size chunks
+		or hold a writebuffer to collect smaller writes until they sum up to 
+		pagesize. Available NAND aware filesystems: JFFS2, YAFFS. 		
+	</para>
+	<para>
+		The spare area usage to store filesystem data is controlled by
+		the spare area placement functionality which is described in one
+		of the earlier chapters.
+	</para>
+  </chapter>	
+  <chapter id="tools">
+     	<title>Tools</title>
+	<para>
+		The MTD project provides a couple of helpful tools to handle NAND Flash.
+		<itemizedlist>
+		<listitem><para>flasherase, flasheraseall: Erase and format FLASH partitions</para></listitem>
+		<listitem><para>nandwrite: write filesystem images to NAND FLASH</para></listitem>
+		<listitem><para>nanddump: dump the contents of a NAND FLASH partitions</para></listitem>
+		</itemizedlist>
+	</para>
+	<para>
+		These tools are aware of the NAND restrictions. Please use those tools
+		instead of complaining about errors which are caused by non NAND aware
+		access methods.
+	</para>
+  </chapter>	
+
+  <chapter id="defines">
+     <title>Constants</title>
+     <para>
+     This chapter describes the constants which might be relevant for a driver developer.
+     </para>
+     <sect1>   
+	<title>Chip option constants</title>
+     	<sect2>   
+		<title>Constants for chip id table</title>
+     		<para>
+		These constants are defined in nand.h. They are ored together to describe
+		the chip functionality.
+     		<programlisting>
+/* Chip can not auto increment pages */
+#define NAND_NO_AUTOINCR	0x00000001
+/* Buswitdh is 16 bit */
+#define NAND_BUSWIDTH_16	0x00000002
+/* Device supports partial programming without padding */
+#define NAND_NO_PADDING		0x00000004
+/* Chip has cache program function */
+#define NAND_CACHEPRG		0x00000008
+/* Chip has copy back function */
+#define NAND_COPYBACK		0x00000010
+/* AND Chip which has 4 banks and a confusing page / block 
+ * assignment. See Renesas datasheet for further information */
+#define NAND_IS_AND		0x00000020
+/* Chip has a array of 4 pages which can be read without
+ * additional ready /busy waits */
+#define NAND_4PAGE_ARRAY	0x00000040 
+		</programlisting>
+     		</para>
+     	</sect2>
+     	<sect2>   
+		<title>Constants for runtime options</title>
+     		<para>
+		These constants are defined in nand.h. They are ored together to describe
+		the functionality.
+     		<programlisting>
+/* Use a flash based bad block table. This option is parsed by the
+ * default bad block table function (nand_default_bbt). */
+#define NAND_USE_FLASH_BBT	0x00010000
+/* The hw ecc generator provides a syndrome instead a ecc value on read 
+ * This can only work if we have the ecc bytes directly behind the 
+ * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
+#define NAND_HWECC_SYNDROME	0x00020000
+		</programlisting>
+     		</para>
+     	</sect2>
+     </sect1>	
+
+     <sect1>   
+	<title>ECC selection constants</title>
+	<para>
+	Use these constants to select the ECC algorithm.
+  	<programlisting>
+/* No ECC. Usage is not recommended ! */
+#define NAND_ECC_NONE		0
+/* Software ECC 3 byte ECC per 256 Byte data */
+#define NAND_ECC_SOFT		1
+/* Hardware ECC 3 byte ECC per 256 Byte data */
+#define NAND_ECC_HW3_256	2
+/* Hardware ECC 3 byte ECC per 512 Byte data */
+#define NAND_ECC_HW3_512	3
+/* Hardware ECC 6 byte ECC per 512 Byte data */
+#define NAND_ECC_HW6_512	4
+/* Hardware ECC 6 byte ECC per 512 Byte data */
+#define NAND_ECC_HW8_512	6
+	</programlisting>
+	</para>
+     </sect1>	
+
+     <sect1>   
+	<title>Hardware control related constants</title>
+	<para>
+	These constants describe the requested hardware access function when
+	the boardspecific hardware control function is called
+  	<programlisting>
+/* Select the chip by setting nCE to low */
+#define NAND_CTL_SETNCE 	1
+/* Deselect the chip by setting nCE to high */
+#define NAND_CTL_CLRNCE		2
+/* Select the command latch by setting CLE to high */
+#define NAND_CTL_SETCLE		3
+/* Deselect the command latch by setting CLE to low */
+#define NAND_CTL_CLRCLE		4
+/* Select the address latch by setting ALE to high */
+#define NAND_CTL_SETALE		5
+/* Deselect the address latch by setting ALE to low */
+#define NAND_CTL_CLRALE		6
+/* Set write protection by setting WP to high. Not used! */
+#define NAND_CTL_SETWP		7
+/* Clear write protection by setting WP to low. Not used! */
+#define NAND_CTL_CLRWP		8
+	</programlisting>
+	</para>
+     </sect1>	
+
+     <sect1>   
+	<title>Bad block table related constants</title>
+	<para>
+	These constants describe the options used for bad block
+	table descriptors.
+  	<programlisting>
+/* Options for the bad block table descriptors */
+
+/* The number of bits used per block in the bbt on the device */
+#define NAND_BBT_NRBITS_MSK	0x0000000F
+#define NAND_BBT_1BIT		0x00000001
+#define NAND_BBT_2BIT		0x00000002
+#define NAND_BBT_4BIT		0x00000004
+#define NAND_BBT_8BIT		0x00000008
+/* The bad block table is in the last good block of the device */
+#define	NAND_BBT_LASTBLOCK	0x00000010
+/* The bbt is at the given page, else we must scan for the bbt */
+#define NAND_BBT_ABSPAGE	0x00000020
+/* The bbt is at the given page, else we must scan for the bbt */
+#define NAND_BBT_SEARCH		0x00000040
+/* bbt is stored per chip on multichip devices */
+#define NAND_BBT_PERCHIP	0x00000080
+/* bbt has a version counter at offset veroffs */
+#define NAND_BBT_VERSION	0x00000100
+/* Create a bbt if none axists */
+#define NAND_BBT_CREATE		0x00000200
+/* Search good / bad pattern through all pages of a block */
+#define NAND_BBT_SCANALLPAGES	0x00000400
+/* Scan block empty during good / bad block scan */
+#define NAND_BBT_SCANEMPTY	0x00000800
+/* Write bbt if neccecary */
+#define NAND_BBT_WRITE		0x00001000
+/* Read and write back block contents when writing bbt */
+#define NAND_BBT_SAVECONTENT	0x00002000
+	</programlisting>
+	</para>
+     </sect1>	
+
+  </chapter>
+  	
+  <chapter id="structs">
+     <title>Structures</title>
+     <para>
+     This chapter contains the autogenerated documentation of the structures which are
+     used in the NAND driver and might be relevant for a driver developer. Each  
+     struct member has a short description which is marked with an [XXX] identifier.
+     See the chapter "Documentation hints" for an explanation.
+     </para>
+!Iinclude/linux/mtd/nand.h
+  </chapter>
+
+  <chapter id="pubfunctions">
+     <title>Public Functions Provided</title>
+     <para>
+     This chapter contains the autogenerated documentation of the NAND kernel API functions
+      which are exported. Each function has a short description which is marked with an [XXX] identifier.
+     See the chapter "Documentation hints" for an explanation.
+     </para>
+!Edrivers/mtd/nand/nand_base.c
+!Edrivers/mtd/nand/nand_bbt.c
+!Edrivers/mtd/nand/nand_ecc.c
+  </chapter>
+  
+  <chapter id="intfunctions">
+     <title>Internal Functions Provided</title>
+     <para>
+     This chapter contains the autogenerated documentation of the NAND driver internal functions.
+     Each function has a short description which is marked with an [XXX] identifier.
+     See the chapter "Documentation hints" for an explanation.
+     The functions marked with [DEFAULT] might be relevant for a board driver developer.
+     </para>
+!Idrivers/mtd/nand/nand_base.c
+!Idrivers/mtd/nand/nand_bbt.c
+!Idrivers/mtd/nand/nand_ecc.c
+  </chapter>
+
+  <chapter id="credits">
+     <title>Credits</title>
+	<para>
+		The following people have contributed to the NAND driver:
+		<orderedlist>
+			<listitem><para>Steven J. Hill<email>sjhill@realitydiluted.com</email></para></listitem>
+			<listitem><para>David Woodhouse<email>dwmw2@infradead.org</email></para></listitem>
+			<listitem><para>Thomas Gleixner<email>tglx@linutronix.de</email></para></listitem>
+		</orderedlist>
+		A lot of users have provided bugfixes, improvements and helping hands for testing.
+		Thanks a lot.
+	</para>
+	<para>
+		The following people have contributed to this document:
+		<orderedlist>
+			<listitem><para>Thomas Gleixner<email>tglx@linutronix.de</email></para></listitem>
+		</orderedlist>
+	</para>
+  </chapter>
+</book>

+ 591 - 0
Documentation/DocBook/procfs-guide.tmpl

@@ -0,0 +1,591 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!ENTITY procfsexample SYSTEM "procfs_example.xml">
+]>
+
+<book id="LKProcfsGuide">
+  <bookinfo>
+    <title>Linux Kernel Procfs Guide</title>
+
+    <authorgroup>
+      <author>
+	<firstname>Erik</firstname>
+	<othername>(J.A.K.)</othername>
+	<surname>Mouw</surname>
+	<affiliation>
+	  <orgname>Delft University of Technology</orgname>
+	  <orgdiv>Faculty of Information Technology and Systems</orgdiv>
+	  <address>
+            <email>J.A.K.Mouw@its.tudelft.nl</email>
+            <pob>PO BOX 5031</pob>
+            <postcode>2600 GA</postcode>
+            <city>Delft</city>
+            <country>The Netherlands</country>
+          </address>
+	</affiliation>
+      </author>
+    </authorgroup>
+
+    <revhistory>
+      <revision>
+	<revnumber>1.0&nbsp;</revnumber>
+	<date>May 30, 2001</date>
+	<revremark>Initial revision posted to linux-kernel</revremark>
+      </revision>
+      <revision>
+	<revnumber>1.1&nbsp;</revnumber>
+	<date>June 3, 2001</date>
+	<revremark>Revised after comments from linux-kernel</revremark>
+      </revision>
+    </revhistory>
+
+    <copyright>
+      <year>2001</year>
+      <holder>Erik Mouw</holder>
+    </copyright>
+
+
+    <legalnotice>
+      <para>
+        This documentation is free software; you can redistribute it
+        and/or modify it under the terms of the GNU General Public
+        License as published by the Free Software Foundation; either
+        version 2 of the License, or (at your option) any later
+        version.
+      </para>
+      
+      <para>
+        This documentation is distributed in the hope that it will be
+        useful, but WITHOUT ANY WARRANTY; without even the implied
+        warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+        PURPOSE.  See the GNU General Public License for more details.
+      </para>
+      
+      <para>
+        You should have received a copy of the GNU General Public
+        License along with this program; if not, write to the Free
+        Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+        MA 02111-1307 USA
+      </para>
+      
+      <para>
+        For more details see the file COPYING in the source
+        distribution of Linux.
+      </para>
+    </legalnotice>
+  </bookinfo>
+
+
+
+
+  <toc>
+  </toc>
+
+
+
+
+  <preface>
+    <title>Preface</title>
+
+    <para>
+      This guide describes the use of the procfs file system from
+      within the Linux kernel. The idea to write this guide came up on
+      the #kernelnewbies IRC channel (see <ulink
+      url="http://www.kernelnewbies.org/">http://www.kernelnewbies.org/</ulink>),
+      when Jeff Garzik explained the use of procfs and forwarded me a
+      message Alexander Viro wrote to the linux-kernel mailing list. I
+      agreed to write it up nicely, so here it is.
+    </para>
+
+    <para>
+      I'd like to thank Jeff Garzik
+      <email>jgarzik@pobox.com</email> and Alexander Viro
+      <email>viro@parcelfarce.linux.theplanet.co.uk</email> for their input,
+      Tim Waugh <email>twaugh@redhat.com</email> for his <ulink
+      url="http://people.redhat.com/twaugh/docbook/selfdocbook/">Selfdocbook</ulink>,
+      and Marc Joosen <email>marcj@historia.et.tudelft.nl</email> for
+      proofreading.
+    </para>
+
+    <para>
+      This documentation was written while working on the LART
+      computing board (<ulink
+      url="http://www.lart.tudelft.nl/">http://www.lart.tudelft.nl/</ulink>),
+      which is sponsored by the Mobile Multi-media Communications
+      (<ulink
+      url="http://www.mmc.tudelft.nl/">http://www.mmc.tudelft.nl/</ulink>)
+      and Ubiquitous Communications (<ulink
+      url="http://www.ubicom.tudelft.nl/">http://www.ubicom.tudelft.nl/</ulink>)
+      projects.
+    </para>
+
+    <para>
+      Erik
+    </para>
+  </preface>
+
+
+
+
+  <chapter id="intro">
+    <title>Introduction</title>
+
+    <para>
+      The <filename class="directory">/proc</filename> file system
+      (procfs) is a special file system in the linux kernel. It's a
+      virtual file system: it is not associated with a block device
+      but exists only in memory. The files in the procfs are there to
+      allow userland programs access to certain information from the
+      kernel (like process information in <filename
+      class="directory">/proc/[0-9]+/</filename>), but also for debug
+      purposes (like <filename>/proc/ksyms</filename>).
+    </para>
+
+    <para>
+      This guide describes the use of the procfs file system from
+      within the Linux kernel. It starts by introducing all relevant
+      functions to manage the files within the file system. After that
+      it shows how to communicate with userland, and some tips and
+      tricks will be pointed out. Finally a complete example will be
+      shown.
+    </para>
+
+    <para>
+      Note that the files in <filename
+      class="directory">/proc/sys</filename> are sysctl files: they
+      don't belong to procfs and are governed by a completely
+      different API described in the Kernel API book.
+    </para>
+  </chapter>
+
+
+
+
+  <chapter id="managing">
+    <title>Managing procfs entries</title>
+    
+    <para>
+      This chapter describes the functions that various kernel
+      components use to populate the procfs with files, symlinks,
+      device nodes, and directories.
+    </para>
+
+    <para>
+      A minor note before we start: if you want to use any of the
+      procfs functions, be sure to include the correct header file! 
+      This should be one of the first lines in your code:
+    </para>
+
+    <programlisting>
+#include &lt;linux/proc_fs.h&gt;
+    </programlisting>
+
+
+
+
+    <sect1 id="regularfile">
+      <title>Creating a regular file</title>
+      
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>create_proc_entry</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        This function creates a regular file with the name
+        <parameter>name</parameter>, file mode
+        <parameter>mode</parameter> in the directory
+        <parameter>parent</parameter>. To create a file in the root of
+        the procfs, use <constant>NULL</constant> as
+        <parameter>parent</parameter> parameter. When successful, the
+        function will return a pointer to the freshly created
+        <structname>struct proc_dir_entry</structname>; otherwise it
+        will return <constant>NULL</constant>. <xref
+        linkend="userland"/> describes how to do something useful with
+        regular files.
+      </para>
+
+      <para>
+        Note that it is specifically supported that you can pass a
+        path that spans multiple directories. For example
+        <function>create_proc_entry</function>(<parameter>"drivers/via0/info"</parameter>)
+        will create the <filename class="directory">via0</filename>
+        directory if necessary, with standard
+        <constant>0755</constant> permissions.
+      </para>
+
+    <para>
+      If you only want to be able to read the file, the function
+      <function>create_proc_read_entry</function> described in <xref
+      linkend="convenience"/> may be used to create and initialise
+      the procfs entry in one single call.
+    </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Creating a symlink</title>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry*
+	  <function>proc_symlink</function></funcdef> <paramdef>const
+	  char* <parameter>name</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry*
+	  <parameter>parent</parameter></paramdef> <paramdef>const
+	  char* <parameter>dest</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+      
+      <para>
+        This creates a symlink in the procfs directory
+        <parameter>parent</parameter> that points from
+        <parameter>name</parameter> to
+        <parameter>dest</parameter>. This translates in userland to
+        <literal>ln -s</literal> <parameter>dest</parameter>
+        <parameter>name</parameter>.
+      </para>
+    </sect1>
+
+    <sect1>
+      <title>Creating a directory</title>
+      
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>proc_mkdir</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        Create a directory <parameter>name</parameter> in the procfs
+        directory <parameter>parent</parameter>.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Removing an entry</title>
+      
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>void <function>remove_proc_entry</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        Removes the entry <parameter>name</parameter> in the directory
+        <parameter>parent</parameter> from the procfs. Entries are
+        removed by their <emphasis>name</emphasis>, not by the
+        <structname>struct proc_dir_entry</structname> returned by the
+        various create functions. Note that this function doesn't
+        recursively remove entries.
+      </para>
+
+      <para>
+        Be sure to free the <structfield>data</structfield> entry from
+        the <structname>struct proc_dir_entry</structname> before
+        <function>remove_proc_entry</function> is called (that is: if
+        there was some <structfield>data</structfield> allocated, of
+        course). See <xref linkend="usingdata"/> for more information
+        on using the <structfield>data</structfield> entry.
+      </para>
+    </sect1>
+  </chapter>
+
+
+
+
+  <chapter id="userland">
+    <title>Communicating with userland</title>
+    
+    <para>
+       Instead of reading (or writing) information directly from
+       kernel memory, procfs works with <emphasis>call back
+       functions</emphasis> for files: functions that are called when
+       a specific file is being read or written. Such functions have
+       to be initialised after the procfs file is created by setting
+       the <structfield>read_proc</structfield> and/or
+       <structfield>write_proc</structfield> fields in the
+       <structname>struct proc_dir_entry*</structname> that the
+       function <function>create_proc_entry</function> returned:
+    </para>
+
+    <programlisting>
+struct proc_dir_entry* entry;
+
+entry->read_proc = read_proc_foo;
+entry->write_proc = write_proc_foo;
+    </programlisting>
+
+    <para>
+      If you only want to use a the
+      <structfield>read_proc</structfield>, the function
+      <function>create_proc_read_entry</function> described in <xref
+      linkend="convenience"/> may be used to create and initialise the
+      procfs entry in one single call.
+    </para>
+
+
+
+    <sect1>
+      <title>Reading data</title>
+
+      <para>
+        The read function is a call back function that allows userland
+        processes to read data from the kernel. The read function
+        should have the following format:
+      </para>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>int <function>read_func</function></funcdef>
+	  <paramdef>char* <parameter>page</parameter></paramdef>
+	  <paramdef>char** <parameter>start</parameter></paramdef>
+	  <paramdef>off_t <parameter>off</parameter></paramdef>
+	  <paramdef>int <parameter>count</parameter></paramdef>
+	  <paramdef>int* <parameter>eof</parameter></paramdef>
+	  <paramdef>void* <parameter>data</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        The read function should write its information into the
+        <parameter>page</parameter>. For proper use, the function
+        should start writing at an offset of
+        <parameter>off</parameter> in <parameter>page</parameter> and
+        write at most <parameter>count</parameter> bytes, but because
+        most read functions are quite simple and only return a small
+        amount of information, these two parameters are usually
+        ignored (it breaks pagers like <literal>more</literal> and
+        <literal>less</literal>, but <literal>cat</literal> still
+        works).
+      </para>
+
+      <para>
+        If the <parameter>off</parameter> and
+        <parameter>count</parameter> parameters are properly used,
+        <parameter>eof</parameter> should be used to signal that the
+        end of the file has been reached by writing
+        <literal>1</literal> to the memory location
+        <parameter>eof</parameter> points to.
+      </para>
+
+      <para>
+        The parameter <parameter>start</parameter> doesn't seem to be
+        used anywhere in the kernel. The <parameter>data</parameter>
+        parameter can be used to create a single call back function for
+        several files, see <xref linkend="usingdata"/>.
+      </para>
+
+      <para>
+        The <function>read_func</function> function must return the
+        number of bytes written into the <parameter>page</parameter>.
+      </para>
+
+      <para>
+        <xref linkend="example"/> shows how to use a read call back
+        function.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Writing data</title>
+
+      <para>
+        The write call back function allows a userland process to write
+        data to the kernel, so it has some kind of control over the
+        kernel. The write function should have the following format:
+      </para>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>int <function>write_func</function></funcdef>
+	  <paramdef>struct file* <parameter>file</parameter></paramdef>
+	  <paramdef>const char* <parameter>buffer</parameter></paramdef>
+	  <paramdef>unsigned long <parameter>count</parameter></paramdef>
+	  <paramdef>void* <parameter>data</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        The write function should read <parameter>count</parameter>
+        bytes at maximum from the <parameter>buffer</parameter>. Note
+        that the <parameter>buffer</parameter> doesn't live in the
+        kernel's memory space, so it should first be copied to kernel
+        space with <function>copy_from_user</function>. The
+        <parameter>file</parameter> parameter is usually
+        ignored. <xref linkend="usingdata"/> shows how to use the
+        <parameter>data</parameter> parameter.
+      </para>
+
+      <para>
+        Again, <xref linkend="example"/> shows how to use this call back
+        function.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1 id="usingdata">
+      <title>A single call back for many files</title>
+
+      <para>
+         When a large number of almost identical files is used, it's
+         quite inconvenient to use a separate call back function for
+         each file. A better approach is to have a single call back
+         function that distinguishes between the files by using the
+         <structfield>data</structfield> field in <structname>struct
+         proc_dir_entry</structname>. First of all, the
+         <structfield>data</structfield> field has to be initialised:
+      </para>
+
+      <programlisting>
+struct proc_dir_entry* entry;
+struct my_file_data *file_data;
+
+file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL);
+entry->data = file_data;
+      </programlisting>
+     
+      <para>
+          The <structfield>data</structfield> field is a <type>void
+          *</type>, so it can be initialised with anything.
+      </para>
+
+      <para>
+        Now that the <structfield>data</structfield> field is set, the
+        <function>read_proc</function> and
+        <function>write_proc</function> can use it to distinguish
+        between files because they get it passed into their
+        <parameter>data</parameter> parameter:
+      </para>
+
+      <programlisting>
+int foo_read_func(char *page, char **start, off_t off,
+                  int count, int *eof, void *data)
+{
+        int len;
+
+        if(data == file_data) {
+                /* special case for this file */
+        } else {
+                /* normal processing */
+        }
+
+        return len;
+}
+      </programlisting>
+
+      <para>
+        Be sure to free the <structfield>data</structfield> data field
+        when removing the procfs entry.
+      </para>
+    </sect1>
+  </chapter>
+
+
+
+
+  <chapter id="tips">
+    <title>Tips and tricks</title>
+
+
+
+
+    <sect1 id="convenience">
+      <title>Convenience functions</title>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>create_proc_read_entry</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	  <paramdef>read_proc_t* <parameter>read_proc</parameter></paramdef>
+	  <paramdef>void* <parameter>data</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+      
+      <para>
+        This function creates a regular file in exactly the same way
+        as <function>create_proc_entry</function> from <xref
+        linkend="regularfile"/> does, but also allows to set the read
+        function <parameter>read_proc</parameter> in one call. This
+        function can set the <parameter>data</parameter> as well, like
+        explained in <xref linkend="usingdata"/>.
+      </para>
+    </sect1>
+
+
+
+    <sect1>
+      <title>Modules</title>
+
+      <para>
+        If procfs is being used from within a module, be sure to set
+        the <structfield>owner</structfield> field in the
+        <structname>struct proc_dir_entry</structname> to
+        <constant>THIS_MODULE</constant>.
+      </para>
+
+      <programlisting>
+struct proc_dir_entry* entry;
+
+entry->owner = THIS_MODULE;
+      </programlisting>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Mode and ownership</title>
+
+      <para>
+        Sometimes it is useful to change the mode and/or ownership of
+        a procfs entry. Here is an example that shows how to achieve
+        that:
+      </para>
+
+      <programlisting>
+struct proc_dir_entry* entry;
+
+entry->mode =  S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH;
+entry->uid = 0;
+entry->gid = 100;
+      </programlisting>
+
+    </sect1>
+  </chapter>
+
+
+
+
+  <chapter id="example">
+    <title>Example</title>
+
+    <!-- be careful with the example code: it shouldn't be wider than
+    approx. 60 columns, or otherwise it won't fit properly on a page
+    -->
+
+&procfsexample;
+
+  </chapter>
+</book>

+ 224 - 0
Documentation/DocBook/procfs_example.c

@@ -0,0 +1,224 @@
+/*
+ * procfs_example.c: an example proc interface
+ *
+ * Copyright (C) 2001, Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This file accompanies the procfs-guide in the Linux kernel
+ * source. Its main use is to demonstrate the concepts and
+ * functions described in the guide.
+ *
+ * This software has been developed while working on the LART
+ * computing board (http://www.lart.tudelft.nl/), which is
+ * sponsored by the Mobile Multi-media Communications
+ * (http://www.mmc.tudelft.nl/) and Ubiquitous Communications 
+ * (http://www.ubicom.tudelft.nl/) projects.
+ *
+ * The author can be reached at:
+ *
+ *  Erik Mouw
+ *  Information and Communication Theory Group
+ *  Faculty of Information Technology and Systems
+ *  Delft University of Technology
+ *  P.O. Box 5031
+ *  2600 GA Delft
+ *  The Netherlands
+ *
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/jiffies.h>
+#include <asm/uaccess.h>
+
+
+#define MODULE_VERS "1.0"
+#define MODULE_NAME "procfs_example"
+
+#define FOOBAR_LEN 8
+
+struct fb_data_t {
+	char name[FOOBAR_LEN + 1];
+	char value[FOOBAR_LEN + 1];
+};
+
+
+static struct proc_dir_entry *example_dir, *foo_file,
+	*bar_file, *jiffies_file, *symlink;
+
+
+struct fb_data_t foo_data, bar_data;
+
+
+static int proc_read_jiffies(char *page, char **start,
+			     off_t off, int count,
+			     int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "jiffies = %ld\n",
+                      jiffies);
+
+	return len;
+}
+
+
+static int proc_read_foobar(char *page, char **start,
+			    off_t off, int count, 
+			    int *eof, void *data)
+{
+	int len;
+	struct fb_data_t *fb_data = (struct fb_data_t *)data;
+
+	/* DON'T DO THAT - buffer overruns are bad */
+	len = sprintf(page, "%s = '%s'\n", 
+		      fb_data->name, fb_data->value);
+
+	return len;
+}
+
+
+static int proc_write_foobar(struct file *file,
+			     const char *buffer,
+			     unsigned long count, 
+			     void *data)
+{
+	int len;
+	struct fb_data_t *fb_data = (struct fb_data_t *)data;
+
+	if(count > FOOBAR_LEN)
+		len = FOOBAR_LEN;
+	else
+		len = count;
+
+	if(copy_from_user(fb_data->value, buffer, len))
+		return -EFAULT;
+
+	fb_data->value[len] = '\0';
+
+	return len;
+}
+
+
+static int __init init_procfs_example(void)
+{
+	int rv = 0;
+
+	/* create directory */
+	example_dir = proc_mkdir(MODULE_NAME, NULL);
+	if(example_dir == NULL) {
+		rv = -ENOMEM;
+		goto out;
+	}
+	
+	example_dir->owner = THIS_MODULE;
+	
+	/* create jiffies using convenience function */
+	jiffies_file = create_proc_read_entry("jiffies", 
+					      0444, example_dir, 
+					      proc_read_jiffies,
+					      NULL);
+	if(jiffies_file == NULL) {
+		rv  = -ENOMEM;
+		goto no_jiffies;
+	}
+
+	jiffies_file->owner = THIS_MODULE;
+
+	/* create foo and bar files using same callback
+	 * functions 
+	 */
+	foo_file = create_proc_entry("foo", 0644, example_dir);
+	if(foo_file == NULL) {
+		rv = -ENOMEM;
+		goto no_foo;
+	}
+
+	strcpy(foo_data.name, "foo");
+	strcpy(foo_data.value, "foo");
+	foo_file->data = &foo_data;
+	foo_file->read_proc = proc_read_foobar;
+	foo_file->write_proc = proc_write_foobar;
+	foo_file->owner = THIS_MODULE;
+		
+	bar_file = create_proc_entry("bar", 0644, example_dir);
+	if(bar_file == NULL) {
+		rv = -ENOMEM;
+		goto no_bar;
+	}
+
+	strcpy(bar_data.name, "bar");
+	strcpy(bar_data.value, "bar");
+	bar_file->data = &bar_data;
+	bar_file->read_proc = proc_read_foobar;
+	bar_file->write_proc = proc_write_foobar;
+	bar_file->owner = THIS_MODULE;
+		
+	/* create symlink */
+	symlink = proc_symlink("jiffies_too", example_dir, 
+			       "jiffies");
+	if(symlink == NULL) {
+		rv = -ENOMEM;
+		goto no_symlink;
+	}
+
+	symlink->owner = THIS_MODULE;
+
+	/* everything OK */
+	printk(KERN_INFO "%s %s initialised\n",
+	       MODULE_NAME, MODULE_VERS);
+	return 0;
+
+no_symlink:
+	remove_proc_entry("tty", example_dir);
+no_tty:
+	remove_proc_entry("bar", example_dir);
+no_bar:
+	remove_proc_entry("foo", example_dir);
+no_foo:
+	remove_proc_entry("jiffies", example_dir);
+no_jiffies:			      
+	remove_proc_entry(MODULE_NAME, NULL);
+out:
+	return rv;
+}
+
+
+static void __exit cleanup_procfs_example(void)
+{
+	remove_proc_entry("jiffies_too", example_dir);
+	remove_proc_entry("tty", example_dir);
+	remove_proc_entry("bar", example_dir);
+	remove_proc_entry("foo", example_dir);
+	remove_proc_entry("jiffies", example_dir);
+	remove_proc_entry(MODULE_NAME, NULL);
+
+	printk(KERN_INFO "%s %s removed\n",
+	       MODULE_NAME, MODULE_VERS);
+}
+
+
+module_init(init_procfs_example);
+module_exit(cleanup_procfs_example);
+
+MODULE_AUTHOR("Erik Mouw");
+MODULE_DESCRIPTION("procfs examples");

+ 193 - 0
Documentation/DocBook/scsidrivers.tmpl

@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="scsidrivers">
+ <bookinfo>
+  <title>SCSI Subsystem Interfaces</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Douglas</firstname>
+    <surname>Gilbert</surname>
+    <affiliation>
+     <address>
+      <email>dgilbert@interlog.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+  <pubdate>2003-08-11</pubdate>
+
+  <copyright>
+   <year>2002</year>
+   <year>2003</year>
+   <holder>Douglas Gilbert</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+This document outlines the interface between the Linux scsi mid level
+and lower level drivers. Lower level drivers are variously called HBA
+(host bus adapter) drivers, host drivers (HD) or pseudo adapter drivers.
+The latter alludes to the fact that a lower level driver may be a
+bridge to another IO subsystem (and the "ide-scsi" driver is an example
+of this). There can be many lower level drivers active in a running
+system, but only one per hardware type. For example, the aic7xxx driver
+controls adaptec controllers based on the 7xxx chip series. Most lower
+level drivers can control one or more scsi hosts (a.k.a. scsi initiators).
+  </para>
+<para>
+This document can been found in an ASCII text file in the linux kernel 
+source: <filename>Documentation/scsi/scsi_mid_low_api.txt</filename> .
+It currently hold a little more information than this document. The
+<filename>drivers/scsi/hosts.h</filename> and <filename>
+drivers/scsi/scsi.h</filename> headers contain descriptions of members
+of important structures for the scsi subsystem.
+</para>
+  </chapter>
+
+  <chapter id="driver-struct">
+      <title>Driver structure</title>
+  <para>
+Traditionally a lower level driver for the scsi subsystem has been
+at least two files in the drivers/scsi directory. For example, a
+driver called "xyz" has a header file "xyz.h" and a source file
+"xyz.c". [Actually there is no good reason why this couldn't all
+be in one file.] Some drivers that have been ported to several operating
+systems (e.g. aic7xxx which has separate  files for generic and
+OS-specific code) have more than two files. Such drivers tend to have
+their own directory under the drivers/scsi directory.
+  </para>
+  <para>
+scsi_module.c is normally included at the end of a lower
+level driver. For it to work a declaration like this is needed before
+it is included:
+<programlisting>
+    static Scsi_Host_Template driver_template = DRIVER_TEMPLATE;
+    /* DRIVER_TEMPLATE should contain pointers to supported interface
+       functions. Scsi_Host_Template is defined hosts.h */
+    #include "scsi_module.c"
+</programlisting>
+  </para>
+  <para>
+The scsi_module.c assumes the name "driver_template" is appropriately
+defined. It contains 2 functions:
+<orderedlist>
+<listitem><para>
+     init_this_scsi_driver() called during builtin and module driver
+     initialization: invokes mid level's scsi_register_host()
+</para></listitem>
+<listitem><para>
+     exit_this_scsi_driver() called during closedown: invokes
+     mid level's scsi_unregister_host()
+</para></listitem>
+</orderedlist>
+  </para>
+<para>
+When a new, lower level driver is being added to Linux, the following 
+files (all found in the drivers/scsi directory) will need some attention: 
+Makefile, Config.help and Config.in . It is probably best to look at what 
+an existing lower level driver does in this regard.
+</para>
+  </chapter>
+
+  <chapter id="intfunctions">
+     <title>Interface Functions</title>
+!EDocumentation/scsi/scsi_mid_low_api.txt
+  </chapter>
+
+  <chapter id="locks">
+     <title>Locks</title>
+<para>
+Each Scsi_Host instance has a spin_lock called Scsi_Host::default_lock
+which is initialized in scsi_register() [found in hosts.c]. Within the
+same function the Scsi_Host::host_lock pointer is initialized to point
+at default_lock with the scsi_assign_lock() function. Thereafter
+lock and unlock operations performed by the mid level use the
+Scsi_Host::host_lock pointer.
+</para>
+<para>
+Lower level drivers can override the use of Scsi_Host::default_lock by
+using scsi_assign_lock(). The earliest opportunity to do this would
+be in the detect() function after it has invoked scsi_register(). It
+could be replaced by a coarser grain lock (e.g. per driver) or a
+lock of equal granularity (i.e. per host). Using finer grain locks
+(e.g. per scsi device) may be possible by juggling locks in
+queuecommand().
+</para>
+  </chapter>
+
+  <chapter id="changes">
+     <title>Changes since lk 2.4 series</title>
+<para>
+io_request_lock has been replaced by several finer grained locks. The lock
+relevant to lower level drivers is Scsi_Host::host_lock and there is one
+per scsi host.
+</para>
+<para>
+The older error handling mechanism has been removed. This means the
+lower level interface functions abort() and reset() have been removed.
+</para>
+<para>
+In the 2.4 series the scsi subsystem configuration descriptions were
+aggregated with the configuration descriptions from all other Linux
+subsystems in the Documentation/Configure.help file. In the 2.5 series,
+the scsi subsystem now has its own (much smaller) drivers/scsi/Config.help
+file.
+</para>
+  </chapter>
+
+  <chapter id="credits">
+     <title>Credits</title>
+<para>
+The following people have contributed to this document:
+<orderedlist>
+<listitem><para>
+Mike Anderson <email>andmike@us.ibm.com</email>
+</para></listitem>
+<listitem><para>
+James Bottomley <email>James.Bottomley@steeleye.com</email>
+</para></listitem>
+<listitem><para>
+Patrick Mansfield <email>patmans@us.ibm.com</email>
+</para></listitem>
+</orderedlist>
+</para>
+  </chapter>
+
+</book>

+ 585 - 0
Documentation/DocBook/sis900.tmpl

@@ -0,0 +1,585 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="SiS900Guide">
+
+<bookinfo>
+
+<title>SiS 900/7016 Fast Ethernet Device Driver</title>
+
+<authorgroup>
+<author>
+<firstname>Ollie</firstname>
+<surname>Lho</surname>
+</author>
+
+<author>
+<firstname>Lei Chun</firstname>
+<surname>Chang</surname>
+</author>
+</authorgroup>
+
+<edition>Document Revision: 0.3 for SiS900 driver v1.06 &amp; v1.07</edition>
+<pubdate>November 16, 2000</pubdate>
+
+<copyright>
+ <year>1999</year>
+ <holder>Silicon Integrated System Corp.</holder>
+</copyright>
+
+<legalnotice>
+ <para>
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+ </para>
+
+ <para>
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+ </para>
+
+ <para>
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ </para>
+</legalnotice>
+
+<abstract>
+<para>
+This document gives some information on installation and usage of SiS 900/7016
+device driver under Linux.
+</para>
+</abstract>
+
+</bookinfo>
+
+<toc></toc>
+
+<chapter id="intro">
+ <title>Introduction</title>
+
+<para>
+This document describes the revision 1.06 and 1.07 of SiS 900/7016 Fast Ethernet 
+device driver under Linux. The driver is developed by Silicon Integrated
+System Corp. and distributed freely under the GNU General Public License (GPL).
+The driver can be compiled as a loadable module and used under Linux kernel 
+version 2.2.x. (rev. 1.06)
+With minimal changes, the driver can also be used under 2.3.x and 2.4.x kernel 
+(rev. 1.07), please see 
+<xref linkend="install"/>. If you are intended to
+use the driver for earlier kernels, you are on your own.
+</para>
+
+<para>
+The driver is tested with usual TCP/IP applications including
+FTP, Telnet, Netscape etc. and is used constantly by the developers.
+</para>
+
+<para>
+Please send all comments/fixes/questions to
+<ulink url="mailto:lcchang@sis.com.tw">Lei-Chun Chang</ulink>.
+</para>
+</chapter>
+
+<chapter id="changes">
+ <title>Changes</title>
+
+<para>
+Changes made in Revision 1.07
+
+<orderedlist>
+<listitem>
+<para>
+Separation of sis900.c and sis900.h in order to move most 
+constant definition to sis900.h (many of those constants were
+corrected)
+</para>
+</listitem>
+
+<listitem>
+<para>
+Clean up PCI detection, the pci-scan from Donald Becker were not used,
+just simple pci&lowbar;find&lowbar;*.
+</para>
+</listitem>
+
+<listitem>
+<para>
+MII detection is modified to support multiple mii transceiver.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugs in read&lowbar;eeprom, mdio&lowbar;* were removed.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Lot of sis900 irrelevant comments were removed/changed and
+more comments were added to reflect the real situation.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Clean up of physical/virtual address space mess in buffer 
+descriptors.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Better transmit/receive error handling.
+</para>
+</listitem>
+
+<listitem>
+<para>
+The driver now uses zero-copy single buffer management
+scheme to improve performance.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Names of variables were changed to be more consistent.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Clean up of auo-negotiation and timer code.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Automatic detection and change of PHY on the fly.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bug in mac probing fixed.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Fix 630E equalier problem by modifying the equalizer workaround rule.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Support for ICS1893 10/100 Interated PHYceiver.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Support for media select by ifconfig.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Added kernel-doc extratable documentation.
+</para>
+</listitem>
+
+</orderedlist>
+</para>
+</chapter>
+
+<chapter id="tested">
+ <title>Tested Environment</title>
+
+<para>
+This driver is developed on the following hardware
+
+<itemizedlist>
+<listitem>
+
+<para>
+Intel Celeron 500 with SiS 630 (rev 02) chipset
+</para>
+</listitem>
+<listitem>
+
+<para>
+SiS 900 (rev 01) and SiS 7016/7014 Fast Ethernet Card
+</para>
+</listitem>
+
+</itemizedlist>
+
+and tested with these software environments
+
+<itemizedlist>
+<listitem>
+
+<para>
+Red Hat Linux version 6.2
+</para>
+</listitem>
+<listitem>
+
+<para>
+Linux kernel version 2.4.0
+</para>
+</listitem>
+<listitem>
+
+<para>
+Netscape version 4.6
+</para>
+</listitem>
+<listitem>
+
+<para>
+NcFTP 3.0.0 beta 18
+</para>
+</listitem>
+<listitem>
+
+<para>
+Samba version 2.0.3
+</para>
+</listitem>
+
+</itemizedlist>
+
+</para>
+
+</chapter>
+
+<chapter id="files">
+<title>Files in This Package</title>
+
+<para>
+In the package you can find these files:
+</para>
+
+<para>
+<variablelist>
+
+<varlistentry>
+<term>sis900.c</term>
+<listitem>
+<para>
+Driver source file in C 
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>sis900.h</term>
+<listitem>
+<para>
+Header file for sis900.c
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>sis900.sgml</term>
+<listitem>
+<para>
+DocBook SGML source of the document
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>sis900.txt</term>
+<listitem>
+<para>
+Driver document in plain text
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+</chapter>
+
+<chapter id="install">
+ <title>Installation</title>
+
+<para>
+Silicon Integrated System Corp. is cooperating closely with core Linux Kernel
+developers. The revisions of SiS 900 driver are distributed by the usuall channels
+for kernel tar files and patches. Those kernel tar files for official kernel and
+patches for kernel pre-release can be download at 
+<ulink url="http://ftp.kernel.org/pub/linux/kernel/">official kernel ftp site</ulink>
+and its mirrors.
+The 1.06 revision can be found in kernel version later than 2.3.15 and pre-2.2.14, 
+and 1.07 revision can be found in kernel version 2.4.0.
+If you have no prior experience in networking under Linux, please read
+<ulink url="http://www.tldp.org/">Ethernet HOWTO</ulink> and
+<ulink url="http://www.tldp.org/">Networking HOWTO</ulink> available from
+Linux Documentation Project (LDP).
+</para>
+
+<para>
+The driver is bundled in release later than 2.2.11 and 2.3.15 so this 
+is the most easy case. 
+Be sure you have the appropriate packages for compiling kernel source.
+Those packages are listed in Document/Changes in kernel source 
+distribution. If you have to install the driver other than those bundled
+in kernel release, you should have your driver file 
+<filename>sis900.c</filename> and <filename>sis900.h</filename> 
+copied into <filename class="directory">/usr/src/linux/drivers/net/</filename> first.
+There are two alternative ways to install the driver
+</para>
+
+<sect1>
+<title>Building the driver as loadable module</title>
+
+<para>
+To build the driver as a loadable kernel module you have to reconfigure
+the kernel to activate network support by
+</para>
+
+<para><screen>
+make menuconfig
+</screen></para>
+
+<para>
+Choose <quote>Loadable module support  ---></quote>, 
+then select <quote>Enable loadable module support</quote>.
+</para>
+
+<para>
+Choose <quote>Network Device Support  ---></quote>, select 
+<quote>Ethernet (10 or 100Mbit)</quote>.
+Then select <quote>EISA, VLB, PCI and on board controllers</quote>, 
+and choose <quote>SiS 900/7016 PCI Fast Ethernet Adapter support</quote> 
+to <quote>M</quote>.
+</para>
+
+<para>
+After reconfiguring the kernel, you can make the driver module by
+</para>
+
+<para><screen>
+make modules
+</screen></para>
+
+<para>
+The driver should be compiled with no errors. After compiling the driver,
+the driver can be installed to proper place by
+</para>
+
+<para><screen>
+make modules_install
+</screen></para>
+
+<para>
+Load the driver into kernel by
+</para>
+
+<para><screen>
+insmod sis900
+</screen></para>
+
+<para>
+When loading the driver into memory, some information message can be view by
+</para>
+
+<para>
+<screen>
+dmesg
+</screen>
+
+or
+
+<screen>
+cat /var/log/message
+</screen>
+</para>
+
+<para>
+If the driver is loaded properly you will have messages similar to this:
+</para>
+
+<para><screen>
+sis900.c: v1.07.06  11/07/2000
+eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4.
+eth0: SiS 900 Internal MII PHY transceiver found at address 1.
+eth0: Using SiS 900 Internal MII PHY as default
+</screen></para>
+
+<para>
+showing the version of the driver and the results of probing routine.
+</para>
+
+<para>
+Once the driver is loaded, network can be brought up by
+</para>
+
+<para><screen>
+/sbin/ifconfig eth0 IPADDR broadcast BROADCAST netmask NETMASK media TYPE
+</screen></para>
+
+<para>
+where IPADDR, BROADCAST, NETMASK are your IP address, broadcast address and
+netmask respectively. TYPE is used to set medium type used by the device. 
+Typical values are "10baseT"(twisted-pair 10Mbps Ethernet) or "100baseT"
+(twisted-pair 100Mbps Ethernet). For more information on how to configure 
+network interface, please refer to  
+<ulink url="http://www.tldp.org/">Networking HOWTO</ulink>.
+</para>
+
+<para>
+The link status is also shown by kernel messages. For example, after the
+network interface is activated, you may have the message:
+</para>
+
+<para><screen>
+eth0: Media Link On 100mbps full-duplex
+</screen></para>
+
+<para>
+If you try to unplug the twist pair (TP) cable you will get
+</para>
+
+<para><screen>
+eth0: Media Link Off
+</screen></para>
+
+<para>
+indicating that the link is failed.
+</para>
+</sect1>
+
+<sect1>
+<title>Building the driver into kernel</title>
+
+<para>
+If you want to make the driver into kernel, choose <quote>Y</quote> 
+rather than <quote>M</quote> on 
+<quote>SiS 900/7016 PCI Fast Ethernet Adapter support</quote> 
+when configuring the kernel. Build the kernel image in the usual way
+</para>
+
+<para><screen>
+make clean
+
+make bzlilo
+</screen></para>
+
+<para>
+Next time the system reboot, you have the driver in memory.
+</para>
+
+</sect1>
+</chapter>
+
+<chapter id="problems">
+ <title>Known Problems and Bugs</title>
+
+<para>
+There are some known problems and bugs. If you find any other bugs please 
+mail to <ulink url="mailto:lcchang@sis.com.tw">lcchang@sis.com.tw</ulink>
+
+<orderedlist>
+
+<listitem>
+<para>
+AM79C901 HomePNA PHY is not thoroughly tested, there may be some 
+bugs in the <quote>on the fly</quote> change of transceiver. 
+</para>
+</listitem>
+
+<listitem>
+<para>
+A bug is hidden somewhere in the receive buffer management code, 
+the bug causes NULL pointer reference in the kernel. This fault is 
+caught before bad things happen and reported with the message:
+
+<computeroutput>
+eth0: NULL pointer encountered in Rx ring, skipping 
+</computeroutput>
+
+which can be viewed with <literal remap="tt">dmesg</literal> or
+<literal remap="tt">cat /var/log/message</literal>.
+</para>
+</listitem>
+
+<listitem>
+<para>
+The media type change from 10Mbps to 100Mbps twisted-pair ethernet 
+by ifconfig causes the media link down.
+</para>
+</listitem>
+
+</orderedlist>
+</para>
+</chapter>
+
+<chapter id="RHistory">
+ <title>Revision History</title>
+
+<para>
+<itemizedlist>
+
+<listitem>
+<para>
+November 13, 2000, Revision 1.07, seventh release, 630E problem fixed 
+and further clean up.
+</para>
+</listitem>
+
+<listitem>
+<para>
+November 4, 1999, Revision 1.06, Second release, lots of clean up
+and optimization.
+</para>
+</listitem>
+
+<listitem>
+<para>
+August 8, 1999, Revision 1.05, Initial Public Release
+</para>
+</listitem>
+
+</itemizedlist>
+</para>
+</chapter>
+
+<chapter id="acknowledgements">
+ <title>Acknowledgements</title>
+
+<para>
+This driver was originally derived form 
+<ulink url="mailto:becker@cesdis1.gsfc.nasa.gov">Donald Becker</ulink>'s
+<ulink url="ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/kern-2.3/pci-skeleton.c"
+>pci-skeleton</ulink> and
+<ulink url="ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/kern-2.3/rtl8139.c"
+>rtl8139</ulink> drivers. Donald also provided various suggestion
+regarded with improvements made in revision 1.06.
+</para>
+
+<para>
+The 1.05 revision was created by 
+<ulink url="mailto:cmhuang@sis.com.tw">Jim Huang</ulink>, AMD 79c901
+support was added by <ulink url="mailto:lcs@sis.com.tw">Chin-Shan Li</ulink>.
+</para>
+</chapter>
+
+<chapter id="functions">
+<title>List of Functions</title>
+!Idrivers/net/sis900.c
+</chapter>
+
+</book>

+ 327 - 0
Documentation/DocBook/tulip-user.tmpl

@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="TulipUserGuide">
+ <bookinfo>
+  <title>Tulip Driver User's Guide</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Jeff</firstname>
+    <surname>Garzik</surname>
+    <affiliation>
+     <address>
+      <email>jgarzik@pobox.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2001</year>
+   <holder>Jeff Garzik</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+ <toc></toc>
+
+  <chapter id="intro">
+    <title>Introduction</title>
+<para>
+The Tulip Ethernet Card Driver
+is maintained by Jeff Garzik (<email>jgarzik@pobox.com</email>).
+</para>
+
+<para>
+The Tulip driver was developed by Donald Becker and changed by
+Jeff Garzik, Takashi Manabe and a cast of thousands.
+</para>
+
+<para>
+For 2.4.x and later kernels, the Linux Tulip driver is available at
+<ulink url="http://sourceforge.net/projects/tulip/">http://sourceforge.net/projects/tulip/</ulink>
+</para>
+
+<para>
+	This driver is for the Digital "Tulip" Ethernet adapter interface.
+	It should work with most DEC 21*4*-based chips/ethercards, as well as
+	with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX.
+</para>
+
+<para>
+        The original author may be reached as becker@scyld.com, or C/O
+        Scyld Computing Corporation,
+        410 Severn Ave., Suite 210,
+        Annapolis MD 21403
+</para>
+
+<para>
+	Additional information on Donald Becker's tulip.c
+	is available at <ulink url="http://www.scyld.com/network/tulip.html">http://www.scyld.com/network/tulip.html</ulink>
+</para>
+
+  </chapter>
+
+  <chapter id="drvr-compat">
+    <title>Driver Compatibility</title>
+
+<para>
+This device driver is designed for the DECchip "Tulip", Digital's
+single-chip ethernet controllers for PCI (now owned by Intel).
+Supported members of the family
+are the 21040, 21041, 21140, 21140A, 21142, and 21143.  Similar work-alike
+chips from Lite-On, Macronics, ASIX, Compex and other listed below are also
+supported.
+</para>
+
+<para>
+These chips are used on at least 140 unique PCI board designs.  The great
+number of chips and board designs supported is the reason for the
+driver size and complexity.  Almost of the increasing complexity is in the
+board configuration and media selection code.  There is very little
+increasing in the operational critical path length.
+</para>
+  </chapter>
+
+  <chapter id="board-settings">
+    <title>Board-specific Settings</title>
+
+<para>
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS preferably should assign the
+PCI INTA signal to an otherwise unused system IRQ line.
+</para>
+
+<para>
+Some boards have EEPROMs tables with default media entry.  The factory default
+is usually "autoselect".  This should only be overridden when using
+transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)
+for forcing full-duplex when used with old link partners that do not do
+autonegotiation.
+</para>
+  </chapter>
+
+  <chapter id="driver-operation">
+    <title>Driver Operation</title>
+
+<sect1><title>Ring buffers</title>
+
+<para>
+The Tulip can use either ring buffers or lists of Tx and Rx descriptors.
+This driver uses statically allocated rings of Rx and Tx descriptors, set at
+compile time by RX/TX_RING_SIZE.  This version of the driver allocates skbuffs
+for the Rx ring buffers at open() time and passes the skb->data field to the
+Tulip as receive data buffers.  When an incoming frame is less than
+RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
+copied to the new skbuff.  When the incoming frame is larger, the skbuff is
+passed directly up the protocol stack and replaced by a newly allocated
+skbuff.
+</para>
+
+<para>
+The RX_COPYBREAK value is chosen to trade-off the memory wasted by
+using a full-sized skbuff for small frames vs. the copying costs of larger
+frames.  For small frames the copying cost is negligible (esp. considering
+that we are pre-loading the cache with immediately useful header
+information).  For large frames the copying cost is non-trivial, and the
+larger copy might flush the cache of useful data.  A subtle aspect of this
+choice is that the Tulip only receives into longword aligned buffers, thus
+the IP header at offset 14 isn't longword aligned for further processing.
+Copied frames are put into the new skbuff at an offset of "+2", thus copying
+has the beneficial effect of aligning the IP header and preloading the
+cache.
+</para>
+
+</sect1>
+
+<sect1><title>Synchronization</title>
+<para>
+The driver runs as two independent, single-threaded flows of control.  One
+is the send-packet routine, which enforces single-threaded use by the
+dev->tbusy flag.  The other thread is the interrupt handler, which is single
+threaded by the hardware and other software.
+</para>
+
+<para>
+The send packet thread has partial control over the Tx ring and 'dev->tbusy'
+flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
+queue slot is empty, it clears the tbusy flag when finished otherwise it sets
+the 'tp->tx_full' flag.
+</para>
+
+<para>
+The interrupt handler has exclusive control over the Rx ring and records stats
+from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
+we can't avoid the interrupt overhead by having the Tx routine reap the Tx
+stats.)	 After reaping the stats, it marks the queue entry as empty by setting
+the 'base' to zero.	 Iff the 'tp->tx_full' flag is set, it clears both the
+tx_full and tbusy flags.
+</para>
+
+</sect1>
+
+  </chapter>
+
+  <chapter id="errata">
+    <title>Errata</title>
+
+<para>
+The old DEC databooks were light on details.
+The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last
+register of the set CSR12-15 written.  Hmmm, now how is that possible?
+</para>
+
+<para>
+The DEC SROM format is very badly designed not precisely defined, leading to
+part of the media selection junkheap below.  Some boards do not have EEPROM
+media tables and need to be patched up.  Worse, other boards use the DEC
+design kit media table when it isn't correct for their board.
+</para>
+
+<para>
+We cannot use MII interrupts because there is no defined GPIO pin to attach
+them.  The MII transceiver status is polled using an kernel timer.
+</para>
+  </chapter>
+
+  <chapter id="changelog">
+    <title>Driver Change History</title>
+
+    <sect1><title>Version 0.9.14 (February 20, 2001)</title>
+    <itemizedlist>
+    <listitem><para>Fix PNIC problems (Manfred Spraul)</para></listitem>
+    <listitem><para>Add new PCI id for Accton comet</para></listitem>
+    <listitem><para>Support Davicom tulips</para></listitem>
+    <listitem><para>Fix oops in eeprom parsing</para></listitem>
+    <listitem><para>Enable workarounds for early PCI chipsets</para></listitem>
+    <listitem><para>IA64, hppa csr0 support</para></listitem>
+    <listitem><para>Support media types 5, 6</para></listitem>
+    <listitem><para>Interpret a bit more of the 21142 SROM extended media type 3</para></listitem>
+    <listitem><para>Add missing delay in eeprom reading</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.11 (November 3, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Eliminate extra bus accesses when sharing interrupts (prumpf)</para></listitem>
+    <listitem><para>Barrier following ownership descriptor bit flip (prumpf)</para></listitem>
+    <listitem><para>Endianness fixes for >14 addresses in setup frames (prumpf)</para></listitem>
+    <listitem><para>Report link beat to kernel/userspace via netif_carrier_*. (kuznet)</para></listitem>
+    <listitem><para>Better spinlocking in set_rx_mode.</para></listitem>
+    <listitem><para>Fix I/O resource request failure error messages (DaveM catch)</para></listitem>
+    <listitem><para>Handle DMA allocation failure.</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.10 (September 6, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Simple interrupt mitigation (via jamal)</para></listitem>
+    <listitem><para>More PCI ids</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.9 (August 11, 2000)</title>
+    <itemizedlist>
+    <listitem><para>More PCI ids</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.8 (July 13, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Correct signed/unsigned comparison for dummy frame index</para></listitem>
+    <listitem><para>Remove outdated references to struct enet_statistics</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.7 (June 17, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Timer cleanups (Andrew Morton)</para></listitem>
+    <listitem><para>Alpha compile fix (somebody?)</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.6 (May 31, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Revert 21143-related support flag patch</para></listitem>
+    <listitem><para>Add HPPA/media-table debugging printk</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.5 (May 30, 2000)</title>
+    <itemizedlist>
+    <listitem><para>HPPA support (willy@puffingroup)</para></listitem>
+    <listitem><para>CSR6 bits and tulip.h cleanup (Chris Smith)</para></listitem>
+    <listitem><para>Improve debugging messages a bit</para></listitem>
+    <listitem><para>Add delay after CSR13 write in t21142_start_nway</para></listitem>
+    <listitem><para>Remove unused ETHER_STATS code</para></listitem>
+    <listitem><para>Convert 'extern inline' to 'static inline' in tulip.h (Chris Smith)</para></listitem>
+    <listitem><para>Update DS21143 support flags in tulip_chip_info[]</para></listitem>
+    <listitem><para>Use spin_lock_irq, not _irqsave/restore, in tulip_start_xmit()</para></listitem>
+    <listitem><para>Add locking to set_rx_mode()</para></listitem>
+    <listitem><para>Fix race with chip setting DescOwned bit (Hal Murray)</para></listitem>
+    <listitem><para>Request 100% of PIO and MMIO resource space assigned to card</para></listitem>
+    <listitem><para>Remove error message from pci_enable_device failure</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.4.3 (April 14, 2000)</title>
+    <itemizedlist>
+    <listitem><para>mod_timer fix (Hal Murray)</para></listitem>
+    <listitem><para>PNIC2 resuscitation (Chris Smith)</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.4.2 (March 21, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Fix 21041 CSR7, CSR13/14/15 handling</para></listitem>
+    <listitem><para>Merge some PCI ids from tulip 0.91x</para></listitem>
+    <listitem><para>Merge some HAS_xxx flags and flag settings from tulip 0.91x</para></listitem>
+    <listitem><para>asm/io.h fix (submitted by many) and cleanup</para></listitem>
+    <listitem><para>s/HAS_NWAY143/HAS_NWAY/</para></listitem>
+    <listitem><para>Cleanup 21041 mode reporting</para></listitem>
+    <listitem><para>Small code cleanups</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.4.1 (March 18, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Finish PCI DMA conversion (davem)</para></listitem>
+    <listitem><para>Do not netif_start_queue() at end of tulip_tx_timeout() (kuznet)</para></listitem>
+    <listitem><para>PCI DMA fix (kuznet)</para></listitem>
+    <listitem><para>eeprom.c code cleanup</para></listitem>
+    <listitem><para>Remove Xircom Tulip crud</para></listitem>
+    </itemizedlist>
+    </sect1>
+  </chapter>
+
+</book>

+ 979 - 0
Documentation/DocBook/usb.tmpl

@@ -0,0 +1,979 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="Linux-USB-API">
+ <bookinfo>
+  <title>The Linux-USB Host Side API</title>
+  
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+<chapter id="intro">
+    <title>Introduction to USB on Linux</title>
+
+    <para>A Universal Serial Bus (USB) is used to connect a host,
+    such as a PC or workstation, to a number of peripheral
+    devices.  USB uses a tree structure, with the host at the
+    root (the system's master), hubs as interior nodes, and
+    peripheral devices as leaves (and slaves).
+    Modern PCs support several such trees of USB devices, usually
+    one USB 2.0 tree (480 Mbit/sec each) with
+    a few USB 1.1 trees (12 Mbit/sec each) that are used when you
+    connect a USB 1.1 device directly to the machine's "root hub".
+    </para>
+
+    <para>That master/slave asymmetry was designed in part for
+    ease of use.  It is not physically possible to assemble
+    (legal) USB cables incorrectly:  all upstream "to-the-host"
+    connectors are the rectangular type, matching the sockets on
+    root hubs, and the downstream type are the squarish type
+    (or they are built in to the peripheral).
+    Software doesn't need to deal with distributed autoconfiguration
+    since the pre-designated master node manages all that.
+    At the electrical level, bus protocol overhead is reduced by
+    eliminating arbitration and moving scheduling into host software.
+    </para>
+
+    <para>USB 1.0 was announced in January 1996, and was revised
+    as USB 1.1 (with improvements in hub specification and
+    support for interrupt-out transfers) in September 1998.
+    USB 2.0 was released in April 2000, including high speed
+    transfers and transaction translating hubs (used for USB 1.1
+    and 1.0 backward compatibility).
+    </para>
+
+    <para>USB support was added to Linux early in the 2.2 kernel series
+    shortly before the 2.3 development forked off.  Updates
+    from 2.3 were regularly folded back into 2.2 releases, bringing
+    new features such as <filename>/sbin/hotplug</filename> support,
+    more drivers, and more robustness.
+    The 2.5 kernel series continued such improvements, and also
+    worked on USB 2.0 support,
+    higher performance,
+    better consistency between host controller drivers,
+    API simplification (to make bugs less likely),
+    and providing internal "kerneldoc" documentation.
+    </para>
+
+    <para>Linux can run inside USB devices as well as on
+    the hosts that control the devices.
+    Because the Linux 2.x USB support evolved to support mass market
+    platforms such as Apple Macintosh or PC-compatible systems,
+    it didn't address design concerns for those types of USB systems.
+    So it can't be used inside mass-market PDAs, or other peripherals.
+    USB device drivers running inside those Linux peripherals
+    don't do the same things as the ones running inside hosts,
+    and so they've been given a different name:
+    they're called <emphasis>gadget drivers</emphasis>.
+    This document does not present gadget drivers.
+    </para>
+
+    </chapter>
+
+<chapter id="host">
+    <title>USB Host-Side API Model</title>
+
+    <para>Within the kernel,
+    host-side drivers for USB devices talk to the "usbcore" APIs.
+    There are two types of public "usbcore" APIs, targetted at two different
+    layers of USB driver.  Those are
+    <emphasis>general purpose</emphasis> drivers, exposed through
+    driver frameworks such as block, character, or network devices;
+    and drivers that are <emphasis>part of the core</emphasis>,
+    which are involved in managing a USB bus.
+    Such core drivers include the <emphasis>hub</emphasis> driver,
+    which manages trees of USB devices, and several different kinds
+    of <emphasis>host controller driver (HCD)</emphasis>,
+    which control individual busses.
+    </para>
+
+    <para>The device model seen by USB drivers is relatively complex.
+    </para>
+     
+    <itemizedlist>
+
+	<listitem><para>USB supports four kinds of data transfer
+	(control, bulk, interrupt, and isochronous).  Two transfer
+	types use bandwidth as it's available (control and bulk),
+	while the other two types of transfer (interrupt and isochronous)
+	are scheduled to provide guaranteed bandwidth.
+	</para></listitem>
+
+	<listitem><para>The device description model includes one or more
+	"configurations" per device, only one of which is active at a time.
+	Devices that are capable of high speed operation must also support
+	full speed configurations, along with a way to ask about the
+	"other speed" configurations that might be used.
+	</para></listitem>
+
+	<listitem><para>Configurations have one or more "interface", each
+	of which may have "alternate settings".  Interfaces may be
+	standardized by USB "Class" specifications, or may be specific to
+	a vendor or device.</para>
+
+	<para>USB device drivers actually bind to interfaces, not devices.
+	Think of them as "interface drivers", though you
+	may not see many devices where the distinction is important.
+	<emphasis>Most USB devices are simple, with only one configuration,
+	one interface, and one alternate setting.</emphasis>
+	</para></listitem>
+
+	<listitem><para>Interfaces have one or more "endpoints", each of
+	which supports one type and direction of data transfer such as
+	"bulk out" or "interrupt in".  The entire configuration may have
+	up to sixteen endpoints in each direction, allocated as needed
+	among all the interfaces.
+	</para></listitem>
+
+	<listitem><para>Data transfer on USB is packetized; each endpoint
+	has a maximum packet size.
+	Drivers must often be aware of conventions such as flagging the end
+	of bulk transfers using "short" (including zero length) packets.
+	</para></listitem>
+
+	<listitem><para>The Linux USB API supports synchronous calls for
+	control and bulk messaging.
+	It also supports asynchnous calls for all kinds of data transfer,
+	using request structures called "URBs" (USB Request Blocks).
+	</para></listitem>
+
+    </itemizedlist>
+
+    <para>Accordingly, the USB Core API exposed to device drivers
+    covers quite a lot of territory.  You'll probably need to consult
+    the USB 2.0 specification, available online from www.usb.org at
+    no cost, as well as class or device specifications.
+    </para>
+
+    <para>The only host-side drivers that actually touch hardware
+    (reading/writing registers, handling IRQs, and so on) are the HCDs.
+    In theory, all HCDs provide the same functionality through the same
+    API.  In practice, that's becoming more true on the 2.5 kernels,
+    but there are still differences that crop up especially with
+    fault handling.  Different controllers don't necessarily report
+    the same aspects of failures, and recovery from faults (including
+    software-induced ones like unlinking an URB) isn't yet fully
+    consistent.
+    Device driver authors should make a point of doing disconnect
+    testing (while the device is active) with each different host
+    controller driver, to make sure drivers don't have bugs of
+    their own as well as to make sure they aren't relying on some
+    HCD-specific behavior.
+    (You will need external USB 1.1 and/or
+    USB 2.0 hubs to perform all those tests.)
+    </para>
+
+    </chapter>
+
+<chapter><title>USB-Standard Types</title>
+
+    <para>In <filename>&lt;linux/usb_ch9.h&gt;</filename> you will find
+    the USB data types defined in chapter 9 of the USB specification.
+    These data types are used throughout USB, and in APIs including
+    this host side API, gadget APIs, and usbfs.
+    </para>
+
+!Iinclude/linux/usb_ch9.h
+
+    </chapter>
+
+<chapter><title>Host-Side Data Types and Macros</title>
+
+    <para>The host side API exposes several layers to drivers, some of
+    which are more necessary than others.
+    These support lifecycle models for host side drivers
+    and devices, and support passing buffers through usbcore to
+    some HCD that performs the I/O for the device driver.
+    </para>
+
+
+!Iinclude/linux/usb.h
+
+    </chapter>
+
+    <chapter><title>USB Core APIs</title>
+
+    <para>There are two basic I/O models in the USB API.
+    The most elemental one is asynchronous:  drivers submit requests
+    in the form of an URB, and the URB's completion callback
+    handle the next step.
+    All USB transfer types support that model, although there
+    are special cases for control URBs (which always have setup
+    and status stages, but may not have a data stage) and
+    isochronous URBs (which allow large packets and include
+    per-packet fault reports).
+    Built on top of that is synchronous API support, where a
+    driver calls a routine that allocates one or more URBs,
+    submits them, and waits until they complete.
+    There are synchronous wrappers for single-buffer control
+    and bulk transfers (which are awkward to use in some
+    driver disconnect scenarios), and for scatterlist based
+    streaming i/o (bulk or interrupt).
+    </para>
+
+    <para>USB drivers need to provide buffers that can be
+    used for DMA, although they don't necessarily need to
+    provide the DMA mapping themselves.
+    There are APIs to use used when allocating DMA buffers,
+    which can prevent use of bounce buffers on some systems.
+    In some cases, drivers may be able to rely on 64bit DMA
+    to eliminate another kind of bounce buffer.
+    </para>
+
+!Edrivers/usb/core/urb.c
+!Edrivers/usb/core/message.c
+!Edrivers/usb/core/file.c
+!Edrivers/usb/core/usb.c
+!Edrivers/usb/core/hub.c
+    </chapter>
+
+    <chapter><title>Host Controller APIs</title>
+
+    <para>These APIs are only for use by host controller drivers,
+    most of which implement standard register interfaces such as
+    EHCI, OHCI, or UHCI.
+    UHCI was one of the first interfaces, designed by Intel and
+    also used by VIA; it doesn't do much in hardware.
+    OHCI was designed later, to have the hardware do more work
+    (bigger transfers, tracking protocol state, and so on).
+    EHCI was designed with USB 2.0; its design has features that
+    resemble OHCI (hardware does much more work) as well as
+    UHCI (some parts of ISO support, TD list processing).
+    </para>
+
+    <para>There are host controllers other than the "big three",
+    although most PCI based controllers (and a few non-PCI based
+    ones) use one of those interfaces.
+    Not all host controllers use DMA; some use PIO, and there
+    is also a simulator.
+    </para>
+
+    <para>The same basic APIs are available to drivers for all
+    those controllers.  
+    For historical reasons they are in two layers:
+    <structname>struct usb_bus</structname> is a rather thin
+    layer that became available in the 2.2 kernels, while
+    <structname>struct usb_hcd</structname> is a more featureful
+    layer (available in later 2.4 kernels and in 2.5) that
+    lets HCDs share common code, to shrink driver size
+    and significantly reduce hcd-specific behaviors.
+    </para>
+
+!Edrivers/usb/core/hcd.c
+!Edrivers/usb/core/hcd-pci.c
+!Edrivers/usb/core/buffer.c
+    </chapter>
+
+    <chapter>
+	<title>The USB Filesystem (usbfs)</title>
+
+	<para>This chapter presents the Linux <emphasis>usbfs</emphasis>.
+	You may prefer to avoid writing new kernel code for your
+	USB driver; that's the problem that usbfs set out to solve.
+	User mode device drivers are usually packaged as applications
+	or libraries, and may use usbfs through some programming library
+	that wraps it.  Such libraries include
+	<ulink url="http://libusb.sourceforge.net">libusb</ulink>
+	for C/C++, and
+	<ulink url="http://jUSB.sourceforge.net">jUSB</ulink> for Java.
+	</para>
+
+	<note><title>Unfinished</title>
+	    <para>This particular documentation is incomplete,
+	    especially with respect to the asynchronous mode.
+	    As of kernel 2.5.66 the code and this (new) documentation
+	    need to be cross-reviewed.
+	    </para>
+	    </note>
+
+	<para>Configure usbfs into Linux kernels by enabling the
+	<emphasis>USB filesystem</emphasis> option (CONFIG_USB_DEVICEFS),
+	and you get basic support for user mode USB device drivers.
+	Until relatively recently it was often (confusingly) called
+	<emphasis>usbdevfs</emphasis> although it wasn't solving what
+	<emphasis>devfs</emphasis> was.
+	Every USB device will appear in usbfs, regardless of whether or
+	not it has a kernel driver; but only devices with kernel drivers
+	show up in devfs.
+	</para>
+
+	<sect1>
+	    <title>What files are in "usbfs"?</title>
+
+	    <para>Conventionally mounted at
+	    <filename>/proc/bus/usb</filename>, usbfs 
+	    features include:
+	    <itemizedlist>
+		<listitem><para><filename>/proc/bus/usb/devices</filename>
+		    ... a text file
+		    showing each of the USB devices on known to the kernel,
+		    and their configuration descriptors.
+		    You can also poll() this to learn about new devices.
+		    </para></listitem>
+		<listitem><para><filename>/proc/bus/usb/BBB/DDD</filename>
+		    ... magic files
+		    exposing the each device's configuration descriptors, and
+		    supporting a series of ioctls for making device requests,
+		    including I/O to devices.  (Purely for access by programs.)
+		    </para></listitem>
+	    </itemizedlist>
+	    </para>
+
+	    <para> Each bus is given a number (BBB) based on when it was
+	    enumerated; within each bus, each device is given a similar
+	    number (DDD).
+	    Those BBB/DDD paths are not "stable" identifiers;
+	    expect them to change even if you always leave the devices
+	    plugged in to the same hub port.
+	    <emphasis>Don't even think of saving these in application
+	    configuration files.</emphasis>
+	    Stable identifiers are available, for user mode applications
+	    that want to use them.  HID and networking devices expose
+	    these stable IDs, so that for example you can be sure that
+	    you told the right UPS to power down its second server.
+	    "usbfs" doesn't (yet) expose those IDs.
+	    </para>
+
+	</sect1>
+
+	<sect1>
+	    <title>Mounting and Access Control</title>
+
+	    <para>There are a number of mount options for usbfs, which will
+	    be of most interest to you if you need to override the default
+	    access control policy.
+	    That policy is that only root may read or write device files
+	    (<filename>/proc/bus/BBB/DDD</filename>) although anyone may read
+	    the <filename>devices</filename>
+	    or <filename>drivers</filename> files.
+	    I/O requests to the device also need the CAP_SYS_RAWIO capability,
+	    </para>
+
+	    <para>The significance of that is that by default, all user mode
+	    device drivers need super-user privileges.
+	    You can change modes or ownership in a driver setup
+	    when the device hotplugs, or maye just start the
+	    driver right then, as a privileged server (or some activity
+	    within one).
+	    That's the most secure approach for multi-user systems,
+	    but for single user systems ("trusted" by that user)
+	    it's more convenient just to grant everyone all access
+	    (using the <emphasis>devmode=0666</emphasis> option)
+	    so the driver can start whenever it's needed.
+	    </para>
+
+	    <para>The mount options for usbfs, usable in /etc/fstab or
+	    in command line invocations of <emphasis>mount</emphasis>, are:
+
+	    <variablelist>
+		<varlistentry>
+		    <term><emphasis>busgid</emphasis>=NNNNN</term>
+		    <listitem><para>Controls the GID used for the
+		    /proc/bus/usb/BBB
+		    directories.  (Default: 0)</para></listitem></varlistentry>
+		<varlistentry><term><emphasis>busmode</emphasis>=MMM</term>
+		    <listitem><para>Controls the file mode used for the
+		    /proc/bus/usb/BBB
+		    directories.  (Default: 0555)
+		    </para></listitem></varlistentry>
+		<varlistentry><term><emphasis>busuid</emphasis>=NNNNN</term>
+		    <listitem><para>Controls the UID used for the
+		    /proc/bus/usb/BBB
+		    directories.  (Default: 0)</para></listitem></varlistentry>
+
+		<varlistentry><term><emphasis>devgid</emphasis>=NNNNN</term>
+		    <listitem><para>Controls the GID used for the
+		    /proc/bus/usb/BBB/DDD
+		    files.  (Default: 0)</para></listitem></varlistentry>
+		<varlistentry><term><emphasis>devmode</emphasis>=MMM</term>
+		    <listitem><para>Controls the file mode used for the
+		    /proc/bus/usb/BBB/DDD
+		    files.  (Default: 0644)</para></listitem></varlistentry>
+		<varlistentry><term><emphasis>devuid</emphasis>=NNNNN</term>
+		    <listitem><para>Controls the UID used for the
+		    /proc/bus/usb/BBB/DDD
+		    files.  (Default: 0)</para></listitem></varlistentry>
+
+		<varlistentry><term><emphasis>listgid</emphasis>=NNNNN</term>
+		    <listitem><para>Controls the GID used for the
+		    /proc/bus/usb/devices and drivers files.
+		    (Default: 0)</para></listitem></varlistentry>
+		<varlistentry><term><emphasis>listmode</emphasis>=MMM</term>
+		    <listitem><para>Controls the file mode used for the
+		    /proc/bus/usb/devices and drivers files.
+		    (Default: 0444)</para></listitem></varlistentry>
+		<varlistentry><term><emphasis>listuid</emphasis>=NNNNN</term>
+		    <listitem><para>Controls the UID used for the
+		    /proc/bus/usb/devices and drivers files.
+		    (Default: 0)</para></listitem></varlistentry>
+	    </variablelist>
+
+	    </para>
+
+	    <para>Note that many Linux distributions hard-wire the mount options
+	    for usbfs in their init scripts, such as
+	    <filename>/etc/rc.d/rc.sysinit</filename>,
+	    rather than making it easy to set this per-system
+	    policy in <filename>/etc/fstab</filename>.
+	    </para>
+
+	</sect1>
+
+	<sect1>
+	    <title>/proc/bus/usb/devices</title>
+
+	    <para>This file is handy for status viewing tools in user
+	    mode, which can scan the text format and ignore most of it.
+	    More detailed device status (including class and vendor
+	    status) is available from device-specific files.
+	    For information about the current format of this file,
+	    see the
+	    <filename>Documentation/usb/proc_usb_info.txt</filename>
+	    file in your Linux kernel sources.
+	    </para>
+
+	    <para>Otherwise the main use for this file from programs
+	    is to poll() it to get notifications of usb devices
+	    as they're plugged or unplugged.
+	    To see what changed, you'd need to read the file and
+	    compare "before" and "after" contents, scan the filesystem,
+	    or see its hotplug event.
+	    </para>
+
+	</sect1>
+
+	<sect1>
+	    <title>/proc/bus/usb/BBB/DDD</title>
+
+	    <para>Use these files in one of these basic ways:
+	    </para>
+
+	    <para><emphasis>They can be read,</emphasis>
+	    producing first the device descriptor
+	    (18 bytes) and then the descriptors for the current configuration.
+	    See the USB 2.0 spec for details about those binary data formats.
+	    You'll need to convert most multibyte values from little endian
+	    format to your native host byte order, although a few of the
+	    fields in the device descriptor (both of the BCD-encoded fields,
+	    and the vendor and product IDs) will be byteswapped for you.
+	    Note that configuration descriptors include descriptors for
+	    interfaces, altsettings, endpoints, and maybe additional
+	    class descriptors.
+	    </para>
+
+	    <para><emphasis>Perform USB operations</emphasis> using 
+	    <emphasis>ioctl()</emphasis> requests to make endpoint I/O
+	    requests (synchronously or asynchronously) or manage
+	    the device.
+	    These requests need the CAP_SYS_RAWIO capability,
+	    as well as filesystem access permissions.
+	    Only one ioctl request can be made on one of these
+	    device files at a time.
+	    This means that if you are synchronously reading an endpoint
+	    from one thread, you won't be able to write to a different
+	    endpoint from another thread until the read completes.
+	    This works for <emphasis>half duplex</emphasis> protocols,
+	    but otherwise you'd use asynchronous i/o requests. 
+	    </para>
+
+	    </sect1>
+
+
+	<sect1>
+	    <title>Life Cycle of User Mode Drivers</title>
+
+	    <para>Such a driver first needs to find a device file
+	    for a device it knows how to handle.
+	    Maybe it was told about it because a
+	    <filename>/sbin/hotplug</filename> event handling agent
+	    chose that driver to handle the new device.
+	    Or maybe it's an application that scans all the
+	    /proc/bus/usb device files, and ignores most devices.
+	    In either case, it should <function>read()</function> all
+	    the descriptors from the device file,
+	    and check them against what it knows how to handle.
+	    It might just reject everything except a particular
+	    vendor and product ID, or need a more complex policy.
+	    </para>
+
+	    <para>Never assume there will only be one such device
+	    on the system at a time!
+	    If your code can't handle more than one device at
+	    a time, at least detect when there's more than one, and
+	    have your users choose which device to use.
+	    </para>
+
+	    <para>Once your user mode driver knows what device to use,
+	    it interacts with it in either of two styles.
+	    The simple style is to make only control requests; some
+	    devices don't need more complex interactions than those.
+	    (An example might be software using vendor-specific control
+	    requests for some initialization or configuration tasks,
+	    with a kernel driver for the rest.)
+	    </para>
+
+	    <para>More likely, you need a more complex style driver:
+	    one using non-control endpoints, reading or writing data
+	    and claiming exclusive use of an interface.
+	    <emphasis>Bulk</emphasis> transfers are easiest to use,
+	    but only their sibling <emphasis>interrupt</emphasis> transfers 
+	    work with low speed devices.
+	    Both interrupt and <emphasis>isochronous</emphasis> transfers
+	    offer service guarantees because their bandwidth is reserved.
+	    Such "periodic" transfers are awkward to use through usbfs,
+	    unless you're using the asynchronous calls.  However, interrupt
+	    transfers can also be used in a synchronous "one shot" style.
+	    </para>
+
+	    <para>Your user-mode driver should never need to worry
+	    about cleaning up request state when the device is
+	    disconnected, although it should close its open file
+	    descriptors as soon as it starts seeing the ENODEV
+	    errors.
+	    </para>
+
+	    </sect1>
+
+	<sect1><title>The ioctl() Requests</title>
+
+	    <para>To use these ioctls, you need to include the following
+	    headers in your userspace program:
+<programlisting>#include &lt;linux/usb.h&gt;
+#include &lt;linux/usbdevice_fs.h&gt;
+#include &lt;asm/byteorder.h&gt;</programlisting>
+	    The standard USB device model requests, from "Chapter 9" of
+	    the USB 2.0 specification, are automatically included from
+	    the <filename>&lt;linux/usb_ch9.h&gt;</filename> header.
+	    </para>
+
+	    <para>Unless noted otherwise, the ioctl requests
+	    described here will
+	    update the modification time on the usbfs file to which
+	    they are applied (unless they fail).
+	    A return of zero indicates success; otherwise, a
+	    standard USB error code is returned.  (These are
+	    documented in
+	    <filename>Documentation/usb/error-codes.txt</filename>
+	    in your kernel sources.)
+	    </para>
+
+	    <para>Each of these files multiplexes access to several
+	    I/O streams, one per endpoint.
+	    Each device has one control endpoint (endpoint zero)
+	    which supports a limited RPC style RPC access.
+	    Devices are configured
+	    by khubd (in the kernel) setting a device-wide
+	    <emphasis>configuration</emphasis> that affects things
+	    like power consumption and basic functionality.
+	    The endpoints are part of USB <emphasis>interfaces</emphasis>,
+	    which may have <emphasis>altsettings</emphasis>
+	    affecting things like which endpoints are available.
+	    Many devices only have a single configuration and interface,
+	    so drivers for them will ignore configurations and altsettings.
+	    </para>
+
+
+	    <sect2>
+		<title>Management/Status Requests</title>
+
+		<para>A number of usbfs requests don't deal very directly
+		with device I/O.
+		They mostly relate to device management and status.
+		These are all synchronous requests.
+		</para>
+
+		<variablelist>
+
+		<varlistentry><term>USBDEVFS_CLAIMINTERFACE</term>
+		    <listitem><para>This is used to force usbfs to
+		    claim a specific interface,
+		    which has not previously been claimed by usbfs or any other
+		    kernel driver.
+		    The ioctl parameter is an integer holding the number of
+		    the interface (bInterfaceNumber from descriptor).
+		    </para><para>
+		    Note that if your driver doesn't claim an interface
+		    before trying to use one of its endpoints, and no
+		    other driver has bound to it, then the interface is
+		    automatically claimed by usbfs.
+		    </para><para>
+		    This claim will be released by a RELEASEINTERFACE ioctl,
+		    or by closing the file descriptor.
+		    File modification time is not updated by this request.
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_CONNECTINFO</term>
+		    <listitem><para>Says whether the device is lowspeed.
+		    The ioctl parameter points to a structure like this:
+<programlisting>struct usbdevfs_connectinfo {
+        unsigned int   devnum;
+        unsigned char  slow;
+}; </programlisting>
+		    File modification time is not updated by this request.
+		    </para><para>
+		    <emphasis>You can't tell whether a "not slow"
+		    device is connected at high speed (480 MBit/sec)
+		    or just full speed (12 MBit/sec).</emphasis>
+		    You should know the devnum value already,
+		    it's the DDD value of the device file name.
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_GETDRIVER</term>
+		    <listitem><para>Returns the name of the kernel driver
+		    bound to a given interface (a string).  Parameter
+		    is a pointer to this structure, which is modified:
+<programlisting>struct usbdevfs_getdriver {
+        unsigned int  interface;
+        char          driver[USBDEVFS_MAXDRIVERNAME + 1];
+};</programlisting>
+		    File modification time is not updated by this request.
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_IOCTL</term>
+		    <listitem><para>Passes a request from userspace through
+		    to a kernel driver that has an ioctl entry in the
+		    <emphasis>struct usb_driver</emphasis> it registered.
+<programlisting>struct usbdevfs_ioctl {
+        int     ifno;
+        int     ioctl_code;
+        void    *data;
+};
+
+/* user mode call looks like this.
+ * 'request' becomes the driver->ioctl() 'code' parameter.
+ * the size of 'param' is encoded in 'request', and that data
+ * is copied to or from the driver->ioctl() 'buf' parameter.
+ */
+static int
+usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
+{
+        struct usbdevfs_ioctl	wrapper;
+
+        wrapper.ifno = ifno;
+        wrapper.ioctl_code = request;
+        wrapper.data = param;
+
+        return ioctl (fd, USBDEVFS_IOCTL, &amp;wrapper);
+} </programlisting>
+		    File modification time is not updated by this request.
+		    </para><para>
+		    This request lets kernel drivers talk to user mode code
+		    through filesystem operations even when they don't create
+		    a charactor or block special device.
+		    It's also been used to do things like ask devices what
+		    device special file should be used.
+		    Two pre-defined ioctls are used
+		    to disconnect and reconnect kernel drivers, so
+		    that user mode code can completely manage binding
+		    and configuration of devices.
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_RELEASEINTERFACE</term>
+		    <listitem><para>This is used to release the claim usbfs
+		    made on interface, either implicitly or because of a
+		    USBDEVFS_CLAIMINTERFACE call, before the file
+		    descriptor is closed.
+		    The ioctl parameter is an integer holding the number of
+		    the interface (bInterfaceNumber from descriptor);
+		    File modification time is not updated by this request.
+		    </para><warning><para>
+		    <emphasis>No security check is made to ensure
+		    that the task which made the claim is the one
+		    which is releasing it.
+		    This means that user mode driver may interfere
+		    other ones.  </emphasis>
+		    </para></warning></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_RESETEP</term>
+		    <listitem><para>Resets the data toggle value for an endpoint
+		    (bulk or interrupt) to DATA0.
+		    The ioctl parameter is an integer endpoint number
+		    (1 to 15, as identified in the endpoint descriptor),
+		    with USB_DIR_IN added if the device's endpoint sends
+		    data to the host.
+		    </para><warning><para>
+		    <emphasis>Avoid using this request.
+		    It should probably be removed.</emphasis>
+		    Using it typically means the device and driver will lose
+		    toggle synchronization.  If you really lost synchronization,
+		    you likely need to completely handshake with the device,
+		    using a request like CLEAR_HALT
+		    or SET_INTERFACE.
+		    </para></warning></listitem></varlistentry>
+
+		</variablelist>
+
+		</sect2>
+
+	    <sect2>
+		<title>Synchronous I/O Support</title>
+
+		<para>Synchronous requests involve the kernel blocking
+		until until the user mode request completes, either by
+		finishing successfully or by reporting an error.
+		In most cases this is the simplest way to use usbfs,
+		although as noted above it does prevent performing I/O
+		to more than one endpoint at a time.
+		</para>
+
+		<variablelist>
+
+		<varlistentry><term>USBDEVFS_BULK</term>
+		    <listitem><para>Issues a bulk read or write request to the
+		    device.
+		    The ioctl parameter is a pointer to this structure:
+<programlisting>struct usbdevfs_bulktransfer {
+        unsigned int  ep;
+        unsigned int  len;
+        unsigned int  timeout; /* in milliseconds */
+        void          *data;
+};</programlisting>
+		    </para><para>The "ep" value identifies a
+		    bulk endpoint number (1 to 15, as identified in an endpoint
+		    descriptor),
+		    masked with USB_DIR_IN when referring to an endpoint which
+		    sends data to the host from the device.
+		    The length of the data buffer is identified by "len";
+		    Recent kernels support requests up to about 128KBytes.
+		    <emphasis>FIXME say how read length is returned,
+		    and how short reads are handled.</emphasis>.
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_CLEAR_HALT</term>
+		    <listitem><para>Clears endpoint halt (stall) and
+		    resets the endpoint toggle.  This is only
+		    meaningful for bulk or interrupt endpoints.
+		    The ioctl parameter is an integer endpoint number
+		    (1 to 15, as identified in an endpoint descriptor),
+		    masked with USB_DIR_IN when referring to an endpoint which
+		    sends data to the host from the device.
+		    </para><para>
+		    Use this on bulk or interrupt endpoints which have
+		    stalled, returning <emphasis>-EPIPE</emphasis> status
+		    to a data transfer request.
+		    Do not issue the control request directly, since
+		    that could invalidate the host's record of the
+		    data toggle.
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_CONTROL</term>
+		    <listitem><para>Issues a control request to the device.
+		    The ioctl parameter points to a structure like this:
+<programlisting>struct usbdevfs_ctrltransfer {
+        __u8   bRequestType;
+        __u8   bRequest;
+        __u16  wValue;
+        __u16  wIndex;
+        __u16  wLength;
+        __u32  timeout;  /* in milliseconds */
+        void   *data;
+};</programlisting>
+		    </para><para>
+		    The first eight bytes of this structure are the contents
+		    of the SETUP packet to be sent to the device; see the
+		    USB 2.0 specification for details.
+		    The bRequestType value is composed by combining a
+		    USB_TYPE_* value, a USB_DIR_* value, and a
+		    USB_RECIP_* value (from
+		    <emphasis>&lt;linux/usb.h&gt;</emphasis>).
+		    If wLength is nonzero, it describes the length of the data
+		    buffer, which is either written to the device
+		    (USB_DIR_OUT) or read from the device (USB_DIR_IN).
+		    </para><para>
+		    At this writing, you can't transfer more than 4 KBytes
+		    of data to or from a device; usbfs has a limit, and
+		    some host controller drivers have a limit.
+		    (That's not usually a problem.)
+		    <emphasis>Also</emphasis> there's no way to say it's
+		    not OK to get a short read back from the device.
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_RESET</term>
+		    <listitem><para>Does a USB level device reset.
+		    The ioctl parameter is ignored.
+		    After the reset, this rebinds all device interfaces.
+		    File modification time is not updated by this request.
+		    </para><warning><para>
+		    <emphasis>Avoid using this call</emphasis>
+		    until some usbcore bugs get fixed,
+		    since it does not fully synchronize device, interface,
+		    and driver (not just usbfs) state.
+		    </para></warning></listitem></varlistentry>
+	    
+		<varlistentry><term>USBDEVFS_SETINTERFACE</term>
+		    <listitem><para>Sets the alternate setting for an
+		    interface.  The ioctl parameter is a pointer to a
+		    structure like this:
+<programlisting>struct usbdevfs_setinterface {
+        unsigned int  interface;
+        unsigned int  altsetting;
+}; </programlisting>
+		    File modification time is not updated by this request.
+		    </para><para>
+		    Those struct members are from some interface descriptor
+		    applying to the the current configuration.
+		    The interface number is the bInterfaceNumber value, and
+		    the altsetting number is the bAlternateSetting value.
+		    (This resets each endpoint in the interface.)
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_SETCONFIGURATION</term>
+		    <listitem><para>Issues the
+		    <function>usb_set_configuration</function> call
+		    for the device.
+		    The parameter is an integer holding the number of
+		    a configuration (bConfigurationValue from descriptor).
+		    File modification time is not updated by this request.
+		    </para><warning><para>
+		    <emphasis>Avoid using this call</emphasis>
+		    until some usbcore bugs get fixed,
+		    since it does not fully synchronize device, interface,
+		    and driver (not just usbfs) state.
+		    </para></warning></listitem></varlistentry>
+
+		</variablelist>
+	    </sect2>
+
+	    <sect2>
+		<title>Asynchronous I/O Support</title>
+
+		<para>As mentioned above, there are situations where it may be
+		important to initiate concurrent operations from user mode code.
+		This is particularly important for periodic transfers
+		(interrupt and isochronous), but it can be used for other
+		kinds of USB requests too.
+		In such cases, the asynchronous requests described here
+		are essential.  Rather than submitting one request and having
+		the kernel block until it completes, the blocking is separate.
+		</para>
+
+		<para>These requests are packaged into a structure that
+		resembles the URB used by kernel device drivers.
+		(No POSIX Async I/O support here, sorry.)
+		It identifies the endpoint type (USBDEVFS_URB_TYPE_*),
+		endpoint (number, masked with USB_DIR_IN as appropriate),
+		buffer and length, and a user "context" value serving to
+		uniquely identify each request.
+		(It's usually a pointer to per-request data.)
+		Flags can modify requests (not as many as supported for
+		kernel drivers).
+		</para>
+
+		<para>Each request can specify a realtime signal number
+		(between SIGRTMIN and SIGRTMAX, inclusive) to request a
+		signal be sent when the request completes.
+		</para>
+
+		<para>When usbfs returns these urbs, the status value
+		is updated, and the buffer may have been modified.
+		Except for isochronous transfers, the actual_length is
+		updated to say how many bytes were transferred; if the
+		USBDEVFS_URB_DISABLE_SPD flag is set
+		("short packets are not OK"), if fewer bytes were read
+		than were requested then you get an error report.
+		</para>
+
+<programlisting>struct usbdevfs_iso_packet_desc {
+        unsigned int                     length;
+        unsigned int                     actual_length;
+        unsigned int                     status;
+};
+
+struct usbdevfs_urb {
+        unsigned char                    type;
+        unsigned char                    endpoint;
+        int                              status;
+        unsigned int                     flags;
+        void                             *buffer;
+        int                              buffer_length;
+        int                              actual_length;
+        int                              start_frame;
+        int                              number_of_packets;
+        int                              error_count;
+        unsigned int                     signr;
+        void                             *usercontext;
+        struct usbdevfs_iso_packet_desc  iso_frame_desc[];
+};</programlisting>
+
+		<para> For these asynchronous requests, the file modification
+		time reflects when the request was initiated.
+		This contrasts with their use with the synchronous requests,
+		where it reflects when requests complete.
+		</para>
+
+		<variablelist>
+
+		<varlistentry><term>USBDEVFS_DISCARDURB</term>
+		    <listitem><para>
+		    <emphasis>TBS</emphasis>
+		    File modification time is not updated by this request.
+		    </para><para>
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_DISCSIGNAL</term>
+		    <listitem><para>
+		    <emphasis>TBS</emphasis>
+		    File modification time is not updated by this request.
+		    </para><para>
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_REAPURB</term>
+		    <listitem><para>
+		    <emphasis>TBS</emphasis>
+		    File modification time is not updated by this request.
+		    </para><para>
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_REAPURBNDELAY</term>
+		    <listitem><para>
+		    <emphasis>TBS</emphasis>
+		    File modification time is not updated by this request.
+		    </para><para>
+		    </para></listitem></varlistentry>
+
+		<varlistentry><term>USBDEVFS_SUBMITURB</term>
+		    <listitem><para>
+		    <emphasis>TBS</emphasis>
+		    </para><para>
+		    </para></listitem></varlistentry>
+
+		</variablelist>
+	    </sect2>
+
+	</sect1>
+
+    </chapter>
+
+</book>
+<!-- vim:syntax=sgml:sw=4
+-->

+ 597 - 0
Documentation/DocBook/via-audio.tmpl

@@ -0,0 +1,597 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="ViaAudioGuide">
+ <bookinfo>
+  <title>Via 686 Audio Driver for Linux</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Jeff</firstname>
+    <surname>Garzik</surname>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>1999-2001</year>
+   <holder>Jeff Garzik</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+  	The Via VT82C686A "super southbridge" chips contain
+	AC97-compatible audio logic which features dual 16-bit stereo
+	PCM sound channels (full duplex), plus a third PCM channel intended for use
+	in hardware-assisted FM synthesis.
+  </para>
+  <para>
+  	The current Linux kernel audio driver for this family of chips
+	supports audio playback and recording, but hardware-assisted
+	FM features, and hardware buffer direct-access (mmap)
+	support are not yet available.
+  </para>
+  <para>
+  	This driver supports any Linux kernel version after 2.4.10.
+  </para>
+  <para>
+	Please send bug reports to the mailing list <email>linux-via@gtf.org</email>.
+	To subscribe, e-mail <email>majordomo@gtf.org</email> with
+  </para>
+  <programlisting>
+	subscribe linux-via
+  </programlisting>
+  <para>
+	in the body of the message.
+  </para>
+  </chapter>
+  
+  <chapter id="install">
+      <title>Driver Installation</title>
+  <para>
+  	To use this audio driver, select the
+	CONFIG_SOUND_VIA82CXXX option in the section Sound during kernel configuration.
+	Follow the usual kernel procedures for rebuilding the kernel,
+	or building and installing driver modules.
+  </para>
+  <para>
+  	To make this driver the default audio driver, you can add the
+	following to your /etc/conf.modules file:
+  </para>
+  <programlisting>
+	alias sound via82cxxx_audio
+  </programlisting>
+  <para>
+  	Note that soundcore and ac97_codec support modules
+	are also required for working audio, in addition to
+	the via82cxxx_audio module itself.
+  </para>
+  </chapter>
+  
+  <chapter id="reportbug">
+      <title>Submitting a bug report</title>
+  <sect1 id="bugrepdesc"><title>Description of problem</title>
+  <para>
+	Describe the application you were using to play/record sound, and how
+	to reproduce the problem.
+  </para>
+  </sect1>
+  <sect1 id="bugrepdiag"><title>Diagnostic output</title>
+  <para>
+	Obtain the via-audio-diag diagnostics program from
+	http://sf.net/projects/gkernel/ and provide a dump of the
+	audio chip's registers while the problem is occurring.  Sample command line:
+  </para>
+  <programlisting>
+	./via-audio-diag -aps > diag-output.txt
+  </programlisting>
+  </sect1>
+  <sect1 id="bugrepdebug"><title>Driver debug output</title>
+  <para>
+	Define <constant>VIA_DEBUG</constant> at the beginning of the driver, then capture and email
+	the kernel log output.  This can be viewed in the system kernel log (if
+	enabled), or via the dmesg program.  Sample command line:
+  </para>
+  <programlisting>
+	dmesg > /tmp/dmesg-output.txt
+  </programlisting>
+  </sect1>
+  <sect1 id="bugrepprintk"><title>Bigger kernel message buffer</title>
+  <para>
+	If you wish to increase the size of the buffer displayed by dmesg, then
+	change the <constant>LOG_BUF_LEN</constant> macro at the top of linux/kernel/printk.c, recompile
+	your kernel, and pass the <constant>LOG_BUF_LEN</constant> value to dmesg.  Sample command line with
+	<constant>LOG_BUF_LEN</constant> == 32768:
+  </para>
+  <programlisting>
+	dmesg -s 32768 > /tmp/dmesg-output.txt
+  </programlisting>
+  </sect1>
+  </chapter>
+  
+  <chapter id="bugs">
+     <title>Known Bugs And Assumptions</title>
+  <para>
+  <variablelist>
+    <varlistentry><term>Low volume</term>
+    <listitem>
+    <para>
+	Volume too low on many systems.  Workaround:  use mixer program
+	such as xmixer to increase volume.
+    </para>
+    </listitem></varlistentry>
+
+  </variablelist>
+	
+  </para>
+  </chapter>
+
+  <chapter id="thanks">
+      <title>Thanks</title>
+  <para>
+	Via for providing e-mail support, specs, and NDA'd source code.
+  </para>
+  <para>
+	MandrakeSoft for providing hacking time.
+  </para>
+  <para>
+	AC97 mixer interface fixes and debugging by Ron Cemer <email>roncemer@gte.net</email>.
+  </para>
+  <para>
+	Rui Sousa <email>rui.sousa@conexant.com</email>, for bugfixing
+	MMAP support, and several other notable fixes that resulted from
+	his hard work and testing.
+  </para>
+  <para>
+	Adrian Cox <email>adrian@humboldt.co.uk</email>, for bugfixing
+	MMAP support, and several other notable fixes that resulted from
+	his hard work and testing.
+  </para>
+  <para>
+  	Thomas Sailer for further bugfixes.
+  </para>
+  </chapter>
+  
+  <chapter id="notes">
+     <title>Random Notes</title>
+  <para>
+	Two /proc pseudo-files provide diagnostic information.  This is generally
+	not useful to most users.  Power users can disable CONFIG_SOUND_VIA82CXXX_PROCFS,
+	and remove the /proc support code.  Once
+	version 2.0.0 is released, the /proc support code will be disabled by
+	default.  Available /proc pseudo-files:
+  </para>
+  <programlisting>
+	/proc/driver/via/0/info
+	/proc/driver/via/0/ac97
+  </programlisting>
+  <para>
+	This driver by default supports all PCI audio devices which report
+	a vendor id of 0x1106, and a device id of 0x3058.  Subsystem vendor
+	and device ids are not examined.
+  </para>
+  <para>
+	GNU indent formatting options:
+  <programlisting>
+-kr -i8 -ts8 -br -ce -bap -sob -l80 -pcs -cs -ss -bs -di1 -nbc -lp -psl
+  </programlisting>
+  </para>
+  <para>
+	Via has graciously donated e-mail support and source code to help further
+	the development of this driver.  Their assistance has been invaluable
+	in the design and coding of the next major version of this driver.
+  </para>
+  <para>
+	The Via audio chip apparently provides a second PCM scatter-gather
+	DMA channel just for FM data, but does not have a full hardware MIDI
+	processor.  I haven't put much thought towards a solution here, but it
+	might involve using SoftOSS midi wave table, or simply disabling MIDI
+	support altogether and using the FM PCM channel as a second (input? output?)
+  </para>
+  </chapter>
+
+  <chapter id="changelog">
+      <title>Driver ChangeLog</title>
+
+<sect1 id="version191"><title>
+Version 1.9.1
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+    DSP read/write bugfixes from Thomas Sailer.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Add new PCI id for single-channel use of Via 8233.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Other bug fixes, tweaks, new ioctls.
+    </para>
+   </listitem>
+
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version1115"><title>
+Version 1.1.15
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+    Support for variable fragment size and variable fragment number (Rui
+    Sousa)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Fixes for the SPEED, STEREO, CHANNELS, FMT ioctls when in read &amp;
+    write mode (Rui Sousa)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Mmaped sound is now fully functional. (Rui Sousa)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Make sure to enable PCI device before reading any of its PCI
+    config information. (fixes potential hotplug problems)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Clean up code a bit and add more internal function documentation.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    AC97 codec access fixes (Adrian Cox)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Big endian fixes (Adrian Cox)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    MIDI support (Adrian Cox)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Detect and report locked-rate AC97 codecs.  If your hardware only
+    supports 48Khz (locked rate), then your recording/playback software
+    must upsample or downsample accordingly.  The hardware cannot do it.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Use new pci_request_regions and pci_disable_device functions in
+    kernel 2.4.6.
+    </para>
+   </listitem>
+
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version1114"><title>
+Version 1.1.14
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+    Use VM_RESERVE when available, to eliminate unnecessary page faults.
+    </para>
+   </listitem>
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version1112"><title>
+Version 1.1.12
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+    mmap bug fixes from Linus.
+    </para>
+   </listitem>
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version1111"><title>
+Version 1.1.11
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+    Many more bug fixes.  mmap enabled by default, but may still be buggy.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Uses new and spiffy method of mmap'ing the DMA buffer, based
+    on a suggestion from Linus.
+    </para>
+   </listitem>
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version1110"><title>
+Version 1.1.10
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+    Many bug fixes.  mmap enabled by default, but may still be buggy.
+    </para>
+   </listitem>
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version119"><title>
+Version 1.1.9
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+    Redesign and rewrite audio playback implementation.  (faster and smaller, hopefully)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Implement recording and full duplex (DSP_CAP_DUPLEX) support.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Make procfs support optional.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Quick interrupt status check, to lessen overhead in interrupt
+    sharing situations.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Add mmap(2) support.  Disabled for now, it is still buggy and experimental.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Surround all syscalls with a semaphore for cheap and easy SMP protection.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Fix bug in channel shutdown (hardware channel reset) code.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Remove unnecessary spinlocks (better performance).
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Eliminate "unknown AFMT" message by using a different method
+    of selecting the best AFMT_xxx sound sample format for use.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Support for realtime hardware pointer position reporting
+    (DSP_CAP_REALTIME, SNDCTL_DSP_GETxPTR ioctls)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Support for capture/playback triggering
+    (DSP_CAP_TRIGGER, SNDCTL_DSP_SETTRIGGER ioctls)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    SNDCTL_DSP_SETDUPLEX and SNDCTL_DSP_POST ioctls now handled.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Rewrite open(2) and close(2) logic to allow only one user at
+    a time.  All other open(2) attempts will sleep until they succeed.
+    FIXME: open(O_RDONLY) and open(O_WRONLY) should be allowed to succeed.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Reviewed code to ensure that SMP and multiple audio devices
+    are fully supported.
+    </para>
+   </listitem>
+
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version118"><title>
+Version 1.1.8
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+    	Clean up interrupt handler output.  Fixes the following kernel error message:
+    </para>
+  	<programlisting>
+	unhandled interrupt ...
+  	</programlisting>
+   </listitem>
+
+   <listitem>
+    <para>
+    	Convert documentation to DocBook, so that PDF, HTML and PostScript (.ps) output is readily
+	available.
+    </para>
+   </listitem>
+
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version117"><title>
+Version 1.1.7
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+ Fix module unload bug where mixer device left registered
+  after driver exit
+    </para>
+   </listitem>
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version116"><title>
+Version 1.1.6
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+ Rewrite via_set_rate to mimic ALSA basic AC97 rate setting
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+ Remove much dead code
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+ Complete spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+ Fix build problem in via_dsp_ioctl
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+ Optimize included headers to eliminate headers found in linux/sound
+	</para>
+   </listitem>
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version115"><title>
+Version 1.1.5
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+ Disable some overly-verbose debugging code
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+ Remove unnecessary sound locks
+   </para>
+   </listitem>
+   <listitem>
+    <para>
+ Fix some ioctls for better time resolution
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+ Begin spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl
+    </para>
+   </listitem>
+  </itemizedlist>
+</sect1>
+
+<sect1 id="version114"><title>
+Version 1.1.4
+</title>
+  <itemizedlist spacing="compact">
+   <listitem>
+    <para>
+ Completed rewrite of driver.  Eliminated SoundBlaster compatibility
+  completely, and now uses the much-faster scatter-gather DMA engine.
+    </para>
+   </listitem>
+  </itemizedlist>
+</sect1>
+
+  </chapter>
+  
+  <chapter id="intfunctions">
+     <title>Internal Functions</title>
+!Isound/oss/via82cxxx_audio.c
+  </chapter>
+
+</book>
+
+

+ 1663 - 0
Documentation/DocBook/videobook.tmpl

@@ -0,0 +1,1663 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="V4LGuide">
+ <bookinfo>
+  <title>Video4Linux Programming</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Alan</firstname>
+    <surname>Cox</surname>
+    <affiliation>
+     <address>
+      <email>alan@redhat.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2000</year>
+   <holder>Alan Cox</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+        Parts of this document first appeared in Linux Magazine under a
+        ninety day exclusivity.
+  </para>
+  <para>
+        Video4Linux is intended to provide a common programming interface
+        for the many TV and capture cards now on the market, as well as
+        parallel port and USB video cameras. Radio, teletext decoders and
+        vertical blanking data interfaces are also provided.
+  </para>
+  </chapter>
+  <chapter id="radio">
+        <title>Radio Devices</title>
+  <para>
+        There are a wide variety of radio interfaces available for PC's, and these
+        are generally very simple to program. The biggest problem with supporting
+        such devices is normally extracting documentation from the vendor.
+  </para>
+  <para>
+        The radio interface supports a simple set of control ioctls standardised
+        across all radio and tv interfaces. It does not support read or write, which
+        are used for video streams. The reason radio cards do not allow you to read
+        the audio stream into an application is that without exception they provide
+        a connection on to a soundcard. Soundcards can be used to read the radio
+        data just fine. 
+  </para>
+  <sect1 id="registerradio">
+  <title>Registering Radio Devices</title>
+  <para>
+        The Video4linux core provides an interface for registering devices. The
+        first step in writing our radio card driver is to register it.
+  </para>
+  <programlisting>
+
+
+static struct video_device my_radio
+{
+        "My radio",
+        VID_TYPE_TUNER,
+        VID_HARDWARE_MYRADIO,
+        radio_open.
+        radio_close,
+        NULL,                /* no read */
+        NULL,                 /* no write */
+        NULL,                /* no poll */
+        radio_ioctl,
+        NULL,                /* no special init function */
+        NULL                /* no private data */
+};
+
+
+  </programlisting>
+  <para>
+        This declares our video4linux device driver interface. The VID_TYPE_ value
+        defines what kind of an interface we are, and defines basic capabilities.
+  </para>
+  <para>
+        The only defined value relevant for a radio card is VID_TYPE_TUNER which
+        indicates that the device can be tuned. Clearly our radio is going to have some
+        way to change channel so it is tuneable.
+  </para>
+  <para>
+        The VID_HARDWARE_ types are unique to each device. Numbers are assigned by
+        <email>alan@redhat.com</email> when device drivers are going to be released. Until then you
+        can pull a suitably large number out of your hat and use it. 10000 should be
+        safe for a very long time even allowing for the huge number of vendors
+        making new and different radio cards at the moment.
+  </para>
+  <para>
+        We declare an open and close routine, but we do not need read or write,
+        which are used to read and write video data to or from the card itself. As
+        we have no read or write there is no poll function.
+  </para>
+  <para>
+        The private initialise function is run when the device is registered. In
+        this driver we've already done all the work needed. The final pointer is a
+        private data pointer that can be used by the device driver to attach and
+        retrieve private data structures. We set this field "priv" to NULL for
+        the moment.
+  </para>
+  <para>
+        Having the structure defined is all very well but we now need to register it
+        with the kernel. 
+  </para>
+  <programlisting>
+
+
+static int io = 0x320;
+
+int __init myradio_init(struct video_init *v)
+{
+        if(!request_region(io, MY_IO_SIZE, "myradio"))
+        {
+                printk(KERN_ERR 
+                    "myradio: port 0x%03X is in use.\n", io);
+                return -EBUSY;
+        }
+
+        if(video_device_register(&amp;my_radio, VFL_TYPE_RADIO)==-1) {
+                release_region(io, MY_IO_SIZE);
+                return -EINVAL;
+        }		
+        return 0;
+}
+
+  </programlisting>
+  <para>
+        The first stage of the initialisation, as is normally the case, is to check 
+        that the I/O space we are about to fiddle with doesn't belong to some other 
+        driver. If it is we leave well alone. If the user gives the address of the 
+        wrong device then we will spot this. These policies will generally avoid 
+        crashing the machine.
+  </para>
+  <para>
+        Now we ask the Video4Linux layer to register the device for us. We hand it
+        our carefully designed video_device structure and also tell it which group
+        of devices we want it registered with. In this case VFL_TYPE_RADIO.
+  </para>
+  <para>
+        The types available are
+  </para>
+   <table frame="all"><title>Device Types</title>
+   <tgroup cols="3" align="left">
+   <tbody>
+   <row>
+        <entry>VFL_TYPE_RADIO</entry><entry>/dev/radio{n}</entry><entry>
+
+        Radio devices are assigned in this block. As with all of these
+        selections the actual number assignment is done by the video layer
+        accordijng to what is free.</entry>
+	</row><row>
+        <entry>VFL_TYPE_GRABBER</entry><entry>/dev/video{n}</entry><entry>
+        Video capture devices and also -- counter-intuitively for the name --
+        hardware video playback devices such as MPEG2 cards.</entry>
+	</row><row>
+        <entry>VFL_TYPE_VBI</entry><entry>/dev/vbi{n}</entry><entry>
+        The VBI devices capture the hidden lines on a television picture
+        that carry further information like closed caption data, teletext
+        (primarily in Europe) and now Intercast and the ATVEC internet
+        television encodings.</entry>
+	</row><row>
+        <entry>VFL_TYPE_VTX</entry><entry>/dev/vtx[n}</entry><entry>
+        VTX is 'Videotext' also known as 'Teletext'. This is a system for
+        sending numbered, 40x25, mostly textual page images over the hidden
+        lines. Unlike the /dev/vbi interfaces, this is for 'smart' decoder 
+        chips. (The use of the word smart here has to be taken in context,
+        the smartest teletext chips are fairly dumb pieces of technology).
+	</entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+  <para>
+        We are most definitely a radio.
+  </para>
+  <para>
+        Finally we allocate our I/O space so that nobody treads on us and return 0
+        to signify general happiness with the state of the universe.
+  </para>
+  </sect1>
+  <sect1 id="openradio">
+  <title>Opening And Closing The Radio</title>
+
+  <para>
+        The functions we declared in our video_device are mostly very simple.
+        Firstly we can drop in what is basically standard code for open and close. 
+  </para>
+  <programlisting>
+
+
+static int users = 0;
+
+static int radio_open(stuct video_device *dev, int flags)
+{
+        if(users)
+                return -EBUSY;
+        users++;
+        return 0;
+}
+
+  </programlisting>
+  <para>
+        At open time we need to do nothing but check if someone else is also using
+        the radio card. If nobody is using it we make a note that we are using it,
+        then we ensure that nobody unloads our driver on us.
+  </para>
+  <programlisting>
+
+
+static int radio_close(struct video_device *dev)
+{
+        users--;
+}
+
+  </programlisting>
+  <para>
+        At close time we simply need to reduce the user count and allow the module
+        to become unloadable.
+  </para>
+  <para>
+        If you are sharp you will have noticed neither the open nor the close
+        routines attempt to reset or change the radio settings. This is intentional.
+        It allows an application to set up the radio and exit. It avoids a user
+        having to leave an application running all the time just to listen to the
+        radio. 
+  </para>
+  </sect1>
+  <sect1 id="ioctlradio">
+  <title>The Ioctl Interface</title>
+  <para>
+        This leaves the ioctl routine, without which the driver will not be
+        terribly useful to anyone.
+  </para>
+  <programlisting>
+
+
+static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+        switch(cmd)
+        {
+                case VIDIOCGCAP:
+                {
+                        struct video_capability v;
+                        v.type = VID_TYPE_TUNER;
+                        v.channels = 1;
+                        v.audios = 1;
+                        v.maxwidth = 0;
+                        v.minwidth = 0;
+                        v.maxheight = 0;
+                        v.minheight = 0;
+                        strcpy(v.name, "My Radio");
+                        if(copy_to_user(arg, &amp;v, sizeof(v)))
+                                return -EFAULT;
+                        return 0;
+                }
+
+  </programlisting>
+  <para>
+        VIDIOCGCAP is the first ioctl all video4linux devices must support. It
+        allows the applications to find out what sort of a card they have found and
+        to figure out what they want to do about it. The fields in the structure are
+  </para>
+   <table frame="all"><title>struct video_capability fields</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+        <entry>name</entry><entry>The device text name. This is intended for the user.</entry>
+	</row><row>
+        <entry>channels</entry><entry>The number of different channels you can tune on
+                        this card. It could even by zero for a card that has
+                        no tuning capability. For our simple FM radio it is 1. 
+                        An AM/FM radio would report 2.</entry>
+	</row><row>
+        <entry>audios</entry><entry>The number of audio inputs on this device. For our
+                        radio there is only one audio input.</entry>
+	</row><row>
+        <entry>minwidth,minheight</entry><entry>The smallest size the card is capable of capturing
+		        images in. We set these to zero. Radios do not
+                        capture pictures</entry>
+	</row><row>
+        <entry>maxwidth,maxheight</entry><entry>The largest image size the card is capable of
+                                      capturing. For our radio we report 0.
+				</entry>
+	</row><row>
+        <entry>type</entry><entry>This reports the capabilities of the device, and
+                        matches the field we filled in in the struct
+                        video_device when registering.</entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+  <para>
+        Having filled in the fields, we use copy_to_user to copy the structure into
+        the users buffer. If the copy fails we return an EFAULT to the application
+        so that it knows it tried to feed us garbage.
+  </para>
+  <para>
+        The next pair of ioctl operations select which tuner is to be used and let
+        the application find the tuner properties. We have only a single FM band
+        tuner in our example device.
+  </para>
+  <programlisting>
+
+
+                case VIDIOCGTUNER:
+                {
+                        struct video_tuner v;
+                        if(copy_from_user(&amp;v, arg, sizeof(v))!=0)
+                                return -EFAULT;
+                        if(v.tuner)
+                                return -EINVAL;
+                        v.rangelow=(87*16000);
+                        v.rangehigh=(108*16000);
+                        v.flags = VIDEO_TUNER_LOW;
+                        v.mode = VIDEO_MODE_AUTO;
+                        v.signal = 0xFFFF;
+                        strcpy(v.name, "FM");
+                        if(copy_to_user(&amp;v, arg, sizeof(v))!=0)
+                                return -EFAULT;
+                        return 0;
+                }
+
+  </programlisting>
+  <para>
+        The VIDIOCGTUNER ioctl allows applications to query a tuner. The application
+        sets the tuner field to the tuner number it wishes to query. The query does
+        not change the tuner that is being used, it merely enquires about the tuner
+        in question.
+  </para>
+  <para>
+        We have exactly one tuner so after copying the user buffer to our temporary
+        structure we complain if they asked for a tuner other than tuner 0. 
+  </para>
+  <para>
+        The video_tuner structure has the following fields
+  </para>
+   <table frame="all"><title>struct video_tuner fields</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+        <entry>int tuner</entry><entry>The number of the tuner in question</entry>
+   </row><row>
+        <entry>char name[32]</entry><entry>A text description of this tuner. "FM" will do fine.
+                        This is intended for the application.</entry>
+   </row><row>
+        <entry>u32 flags</entry>
+        <entry>Tuner capability flags</entry>
+   </row>
+   <row>
+        <entry>u16 mode</entry><entry>The current reception mode</entry>
+
+   </row><row>
+        <entry>u16 signal</entry><entry>The signal strength scaled between 0 and 65535. If
+                        a device cannot tell the signal strength it should
+                        report 65535. Many simple cards contain only a 
+                        signal/no signal bit. Such cards will report either
+                        0 or 65535.</entry>
+
+   </row><row>
+        <entry>u32 rangelow, rangehigh</entry><entry>
+                        The range of frequencies supported by the radio
+                        or TV. It is scaled according to the VIDEO_TUNER_LOW
+                        flag.</entry>
+
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+
+   <table frame="all"><title>struct video_tuner flags</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+	<entry>VIDEO_TUNER_PAL</entry><entry>A PAL TV tuner</entry>
+	</row><row>
+        <entry>VIDEO_TUNER_NTSC</entry><entry>An NTSC (US) TV tuner</entry>
+	</row><row>
+        <entry>VIDEO_TUNER_SECAM</entry><entry>A SECAM (French) TV tuner</entry>
+	</row><row>
+        <entry>VIDEO_TUNER_LOW</entry><entry>
+             The tuner frequency is scaled in 1/16th of a KHz
+             steps. If not it is in 1/16th of a MHz steps
+	</entry>
+	</row><row>
+        <entry>VIDEO_TUNER_NORM</entry><entry>The tuner can set its format</entry>
+	</row><row>
+        <entry>VIDEO_TUNER_STEREO_ON</entry><entry>The tuner is currently receiving a stereo signal</entry>
+        </row>
+    </tbody>
+    </tgroup>
+    </table>
+
+   <table frame="all"><title>struct video_tuner modes</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+                <entry>VIDEO_MODE_PAL</entry><entry>PAL Format</entry>
+   </row><row>
+                <entry>VIDEO_MODE_NTSC</entry><entry>NTSC Format (USA)</entry>
+   </row><row>
+                <entry>VIDEO_MODE_SECAM</entry><entry>French Format</entry>
+   </row><row>
+                <entry>VIDEO_MODE_AUTO</entry><entry>A device that does not need to do
+                                        TV format switching</entry>
+   </row>
+    </tbody>
+    </tgroup>
+    </table>
+  <para>
+        The settings for the radio card are thus fairly simple. We report that we
+        are a tuner called "FM" for FM radio. In order to get the best tuning
+        resolution we report VIDEO_TUNER_LOW and select tuning to 1/16th of KHz. Its
+        unlikely our card can do that resolution but it is a fair bet the card can
+        do better than 1/16th of a MHz. VIDEO_TUNER_LOW is appropriate to almost all
+        radio usage.
+  </para>
+  <para>
+        We report that the tuner automatically handles deciding what format it is
+        receiving - true enough as it only handles FM radio. Our example card is
+        also incapable of detecting stereo or signal strengths so it reports a
+        strength of 0xFFFF (maximum) and no stereo detected.
+  </para>
+  <para>
+        To finish off we set the range that can be tuned to be 87-108Mhz, the normal
+        FM broadcast radio range. It is important to find out what the card is
+        actually capable of tuning. It is easy enough to simply use the FM broadcast
+        range. Unfortunately if you do this you will discover the FM broadcast
+        ranges in the USA, Europe and Japan are all subtly different and some users
+        cannot receive all the stations they wish.
+  </para>
+  <para>
+        The application also needs to be able to set the tuner it wishes to use. In
+        our case, with a single tuner this is rather simple to arrange.
+  </para>
+  <programlisting>
+
+                case VIDIOCSTUNER:
+                {
+                        struct video_tuner v;
+                        if(copy_from_user(&amp;v, arg, sizeof(v)))
+                                return -EFAULT;
+                        if(v.tuner != 0)
+                                return -EINVAL;
+                        return 0;
+                }
+
+  </programlisting>
+  <para>
+        We copy the user supplied structure into kernel memory so we can examine it. 
+        If the user has selected a tuner other than zero we reject the request. If 
+        they wanted tuner 0 then, surprisingly enough, that is the current tuner already.
+  </para>
+  <para>
+        The next two ioctls we need to provide are to get and set the frequency of
+        the radio. These both use an unsigned long argument which is the frequency.
+        The scale of the frequency depends on the VIDEO_TUNER_LOW flag as I
+        mentioned earlier on. Since we have VIDEO_TUNER_LOW set this will be in
+        1/16ths of a KHz.
+  </para>
+  <programlisting>
+
+static unsigned long current_freq;
+
+
+
+                case VIDIOCGFREQ:
+                        if(copy_to_user(arg, &amp;current_freq, 
+                                sizeof(unsigned long))
+                                return -EFAULT;
+                        return 0;
+
+  </programlisting>
+  <para>
+        Querying the frequency in our case is relatively simple. Our radio card is
+        too dumb to let us query the signal strength so we remember our setting if 
+        we know it. All we have to do is copy it to the user.
+  </para>
+  <programlisting>
+
+
+                case VIDIOCSFREQ:
+                {
+                        u32 freq;
+                        if(copy_from_user(arg, &amp;freq, 
+                                sizeof(unsigned long))!=0)
+                                return -EFAULT;
+                        if(hardware_set_freq(freq)&lt;0)
+                                return -EINVAL;
+                        current_freq = freq;
+                        return 0;
+                }
+
+  </programlisting>
+  <para>
+        Setting the frequency is a little more complex. We begin by copying the
+        desired frequency into kernel space. Next we call a hardware specific routine
+        to set the radio up. This might be as simple as some scaling and a few
+        writes to an I/O port. For most radio cards it turns out a good deal more
+        complicated and may involve programming things like a phase locked loop on
+        the card. This is what documentation is for. 
+  </para>
+  <para>
+        The final set of operations we need to provide for our radio are the 
+        volume controls. Not all radio cards can even do volume control. After all
+        there is a perfectly good volume control on the sound card. We will assume
+        our radio card has a simple 4 step volume control.
+  </para>
+  <para>
+        There are two ioctls with audio we need to support
+  </para>
+  <programlisting>
+
+static int current_volume=0;
+
+                case VIDIOCGAUDIO:
+                {
+                        struct video_audio v;
+                        if(copy_from_user(&amp;v, arg, sizeof(v)))
+                                return -EFAULT;
+                        if(v.audio != 0)
+                                return -EINVAL;
+                        v.volume = 16384*current_volume;
+                        v.step = 16384;
+                        strcpy(v.name, "Radio");
+                        v.mode = VIDEO_SOUND_MONO;
+                        v.balance = 0;
+                        v.base = 0;
+                        v.treble = 0;
+                        
+                        if(copy_to_user(arg. &amp;v, sizeof(v)))
+                                return -EFAULT;
+                        return 0;
+                }
+
+  </programlisting>
+  <para>
+        Much like the tuner we start by copying the user structure into kernel
+        space. Again we check if the user has asked for a valid audio input. We have
+        only input 0 and we punt if they ask for another input.
+  </para>
+  <para>
+        Then we fill in the video_audio structure. This has the following format
+  </para>
+   <table frame="all"><title>struct video_audio fields</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+   <entry>audio</entry><entry>The input the user wishes to query</entry>
+   </row><row>
+   <entry>volume</entry><entry>The volume setting on a scale of 0-65535</entry>
+   </row><row>
+   <entry>base</entry><entry>The base level on a scale of 0-65535</entry>
+   </row><row>
+   <entry>treble</entry><entry>The treble level on a scale of 0-65535</entry>
+   </row><row>
+   <entry>flags</entry><entry>The features this audio device supports
+   </entry>
+   </row><row>
+   <entry>name</entry><entry>A text name to display to the user. We picked
+                        "Radio" as it explains things quite nicely.</entry>
+   </row><row>
+   <entry>mode</entry><entry>The current reception mode for the audio
+
+                We report MONO because our card is too stupid to know if it is in
+                mono or stereo. 
+   </entry>
+   </row><row>
+   <entry>balance</entry><entry>The stereo balance on a scale of 0-65535, 32768 is
+                        middle.</entry>
+   </row><row>
+   <entry>step</entry><entry>The step by which the volume control jumps. This is
+                        used to help make it easy for applications to set 
+                        slider behaviour.</entry>
+   </row>
+   </tbody>
+   </tgroup>
+   </table>
+
+   <table frame="all"><title>struct video_audio flags</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+                <entry>VIDEO_AUDIO_MUTE</entry><entry>The audio is currently muted. We
+                                        could fake this in our driver but we
+                                        choose not to bother.</entry>
+   </row><row>
+                <entry>VIDEO_AUDIO_MUTABLE</entry><entry>The input has a mute option</entry>
+   </row><row>
+                <entry>VIDEO_AUDIO_TREBLE</entry><entry>The  input has a treble control</entry>
+   </row><row>
+                <entry>VIDEO_AUDIO_BASS</entry><entry>The input has a base control</entry>
+   </row>
+   </tbody>
+   </tgroup>
+   </table>
+
+   <table frame="all"><title>struct video_audio modes</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+                <entry>VIDEO_SOUND_MONO</entry><entry>Mono sound</entry>
+   </row><row>
+                <entry>VIDEO_SOUND_STEREO</entry><entry>Stereo sound</entry>
+   </row><row>
+                <entry>VIDEO_SOUND_LANG1</entry><entry>Alternative language 1 (TV specific)</entry>
+   </row><row>
+                <entry>VIDEO_SOUND_LANG2</entry><entry>Alternative language 2 (TV specific)</entry>
+   </row>
+   </tbody>
+   </tgroup>
+   </table>
+  <para>
+        Having filled in the structure we copy it back to user space.
+  </para>
+  <para>
+        The VIDIOCSAUDIO ioctl allows the user to set the audio parameters in the
+        video_audio structure. The driver does its best to honour the request.
+  </para>
+  <programlisting>
+
+                case VIDIOCSAUDIO:
+                {
+                        struct video_audio v;
+                        if(copy_from_user(&amp;v, arg, sizeof(v)))
+                                return -EFAULT;
+                        if(v.audio)
+                                return -EINVAL;
+                        current_volume = v/16384;
+                        hardware_set_volume(current_volume);
+                        return 0;
+                }
+
+  </programlisting>
+  <para>
+        In our case there is very little that the user can set. The volume is
+        basically the limit. Note that we could pretend to have a mute feature
+        by rewriting this to 
+  </para>
+  <programlisting>
+
+                case VIDIOCSAUDIO:
+                {
+                        struct video_audio v;
+                        if(copy_from_user(&amp;v, arg, sizeof(v)))
+                                return -EFAULT;
+                        if(v.audio)
+                                return -EINVAL;
+                        current_volume = v/16384;
+                        if(v.flags&amp;VIDEO_AUDIO_MUTE)
+                                hardware_set_volume(0);
+                        else
+                                hardware_set_volume(current_volume);
+                        current_muted = v.flags &amp; 
+                                              VIDEO_AUDIO_MUTE;
+                        return 0;
+                }
+
+  </programlisting>
+  <para>
+        This with the corresponding changes to the VIDIOCGAUDIO code to report the
+        state of the mute flag we save and to report the card has a mute function,
+        will allow applications to use a mute facility with this card. It is
+        questionable whether this is a good idea however. User applications can already
+        fake this themselves and kernel space is precious.
+  </para>
+  <para>
+        We now have a working radio ioctl handler. So we just wrap up the function
+  </para>
+  <programlisting>
+
+
+        }
+        return -ENOIOCTLCMD;
+}
+
+  </programlisting>
+  <para>
+        and pass the Video4Linux layer back an error so that it knows we did not
+        understand the request we got passed.
+  </para>
+  </sect1>
+  <sect1 id="modradio">
+  <title>Module Wrapper</title>
+  <para>
+        Finally we add in the usual module wrapping and the driver is done.
+  </para>
+  <programlisting>
+
+#ifndef MODULE
+
+static int io = 0x300;
+
+#else
+
+static int io = -1;
+
+#endif
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("A driver for an imaginary radio card.");
+module_param(io, int, 0444);
+MODULE_PARM_DESC(io, "I/O address of the card.");
+
+static int __init init(void)
+{
+        if(io==-1)
+        {
+                printk(KERN_ERR 
+         "You must set an I/O address with io=0x???\n");
+                return -EINVAL;
+        }
+        return myradio_init(NULL);
+}
+
+static void __exit cleanup(void)
+{
+        video_unregister_device(&amp;my_radio);
+        release_region(io, MY_IO_SIZE);
+}
+
+module_init(init);
+module_exit(cleanup);
+
+  </programlisting>
+  <para>
+        In this example we set the IO base by default if the driver is compiled into
+        the kernel: you can still set it using "my_radio.irq" if this file is called <filename>my_radio.c</filename>. For the module we require the
+        user sets the parameter. We set io to a nonsense port (-1) so that we can
+        tell if the user supplied an io parameter or not.
+  </para>
+  <para>
+        We use MODULE_ defines to give an author for the card driver and a
+        description. We also use them to declare that io is an integer and it is the
+        address of the card, and can be read by anyone from sysfs.
+  </para>
+  <para>
+        The clean-up routine unregisters the video_device we registered, and frees
+        up the I/O space. Note that the unregister takes the actual video_device
+        structure as its argument. Unlike the file operations structure which can be
+        shared by all instances of a device a video_device structure as an actual
+        instance of the device. If you are registering multiple radio devices you
+        need to fill in one structure per device (most likely by setting up a
+        template and copying it to each of the actual device structures).
+  </para>
+  </sect1>
+  </chapter>
+  <chapter>
+        <title>Video Capture Devices</title>
+  <sect1 id="introvid">
+  <title>Video Capture Device Types</title>
+  <para>
+        The video capture devices share the same interfaces as radio devices. In
+        order to explain the video capture interface I will use the example of a
+        camera that has no tuners or audio input. This keeps the example relatively
+        clean. To get both combine the two driver examples.
+  </para>
+  <para>
+        Video capture devices divide into four categories. A little technology
+        backgrounder. Full motion video even at television resolution (which is
+        actually fairly low) is pretty resource-intensive. You are continually
+        passing megabytes of data every second from the capture card to the display. 
+        several alternative approaches have emerged because copying this through the 
+        processor and the user program is a particularly bad idea .
+  </para>
+  <para>
+        The first is to add the television image onto the video output directly.
+        This is also how some 3D cards work. These basic cards can generally drop the
+        video into any chosen rectangle of the display. Cards like this, which
+        include most mpeg1 cards that used the feature connector,  aren't very
+        friendly in a windowing environment. They don't understand windows or
+        clipping. The video window is always on the top of the display.
+  </para>
+  <para>
+        Chroma keying is a technique used by cards to get around this. It is an old
+        television mixing trick where you mark all the areas you wish to replace
+        with a single clear colour that isn't used in the image - TV people use an
+        incredibly bright blue while computing people often use a particularly
+        virulent purple. Bright blue occurs on the desktop. Anyone with virulent
+        purple windows has another problem besides their TV overlay.
+  </para>
+  <para>
+        The third approach is to copy the data from the capture card to the video
+        card, but to do it directly across the PCI bus. This relieves the processor
+        from doing the work but does require some smartness on the part of the video
+        capture chip, as well as a suitable video card. Programming this kind of
+        card and more so debugging it can be extremely tricky. There are some quite
+        complicated interactions with the display and you may also have to cope with
+        various chipset bugs that show up when PCI cards start talking to each
+        other. 
+  </para>
+  <para>
+        To keep our example fairly simple we will assume a card that supports
+        overlaying a flat rectangular image onto the frame buffer output, and which
+        can also capture stuff into processor memory.
+  </para>
+  </sect1>
+  <sect1 id="regvid">
+  <title>Registering Video Capture Devices</title>
+  <para>
+        This time we need to add more functions for our camera device.
+  </para>
+  <programlisting>
+static struct video_device my_camera
+{
+        "My Camera",
+        VID_TYPE_OVERLAY|VID_TYPE_SCALES|\
+        VID_TYPE_CAPTURE|VID_TYPE_CHROMAKEY,
+        VID_HARDWARE_MYCAMERA,
+        camera_open.
+        camera_close,
+        camera_read,      /* no read */
+        NULL,             /* no write */
+        camera_poll,      /* no poll */
+        camera_ioctl,
+        NULL,             /* no special init function */
+        NULL              /* no private data */
+};
+  </programlisting>
+  <para>
+        We need a read() function which is used for capturing data from
+        the card, and we need a poll function so that a driver can wait for the next
+        frame to be captured.
+  </para>
+  <para>
+        We use the extra video capability flags that did not apply to the
+        radio interface. The video related flags are
+  </para>
+   <table frame="all"><title>Capture Capabilities</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+<entry>VID_TYPE_CAPTURE</entry><entry>We support image capture</entry>
+</row><row>
+<entry>VID_TYPE_TELETEXT</entry><entry>A teletext capture device (vbi{n])</entry>
+</row><row>
+<entry>VID_TYPE_OVERLAY</entry><entry>The image can be directly overlaid onto the
+                                frame buffer</entry>
+</row><row>
+<entry>VID_TYPE_CHROMAKEY</entry><entry>Chromakey can be used to select which parts
+                                of the image to display</entry>
+</row><row>
+<entry>VID_TYPE_CLIPPING</entry><entry>It is possible to give the board a list of
+                                rectangles to draw around. </entry>
+</row><row>
+<entry>VID_TYPE_FRAMERAM</entry><entry>The video capture goes into the video memory
+                                and actually changes it. Applications need
+                                to know this so they can clean up after the
+                                card</entry>
+</row><row>
+<entry>VID_TYPE_SCALES</entry><entry>The image can be scaled to various sizes,
+                                rather than being a single fixed size.</entry>
+</row><row>
+<entry>VID_TYPE_MONOCHROME</entry><entry>The capture will be monochrome. This isn't a
+                                complete answer to the question since a mono
+                                camera on a colour capture card will still
+                                produce mono output.</entry>
+</row><row>
+<entry>VID_TYPE_SUBCAPTURE</entry><entry>The card allows only part of its field of
+                                view to be captured. This enables
+                                applications to avoid copying all of a large
+                                image into memory when only some section is
+                                relevant.</entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+  <para>
+        We set VID_TYPE_CAPTURE so that we are seen as a capture card,
+        VID_TYPE_CHROMAKEY so the application knows it is time to draw in virulent
+        purple, and VID_TYPE_SCALES because we can be resized.
+  </para>
+  <para>
+        Our setup is fairly similar. This time we also want an interrupt line
+        for the 'frame captured' signal. Not all cards have this so some of them
+        cannot handle poll().
+  </para>
+  <programlisting>
+
+
+static int io = 0x320;
+static int irq = 11;
+
+int __init mycamera_init(struct video_init *v)
+{
+        if(!request_region(io, MY_IO_SIZE, "mycamera"))
+        {
+                printk(KERN_ERR 
+                      "mycamera: port 0x%03X is in use.\n", io);
+                return -EBUSY;
+        }
+
+        if(video_device_register(&amp;my_camera, 
+            VFL_TYPE_GRABBER)==-1) {
+                release_region(io, MY_IO_SIZE);
+                return -EINVAL;
+        }
+        return 0;
+}
+
+  </programlisting>
+  <para>
+        This is little changed from the needs of the radio card. We specify
+        VFL_TYPE_GRABBER this time as we want to be allocated a /dev/video name.
+  </para>
+  </sect1>
+  <sect1 id="opvid">
+  <title>Opening And Closing The Capture Device</title>
+  <programlisting>
+
+
+static int users = 0;
+
+static int camera_open(stuct video_device *dev, int flags)
+{
+        if(users)
+                return -EBUSY;
+        if(request_irq(irq, camera_irq, 0, "camera", dev)&lt;0)
+                return -EBUSY;
+        users++;
+        return 0;
+}
+
+
+static int camera_close(struct video_device *dev)
+{
+        users--;
+        free_irq(irq, dev);
+}
+  </programlisting>
+  <para>
+        The open and close routines are also quite similar. The only real change is
+        that we now request an interrupt for the camera device interrupt line. If we
+        cannot get the interrupt we report EBUSY to the application and give up.
+  </para>
+  </sect1>
+  <sect1 id="irqvid">
+  <title>Interrupt Handling</title>
+  <para>
+        Our example handler is for an ISA bus device. If it was PCI you would be
+        able to share the interrupt and would have set SA_SHIRQ to indicate a 
+        shared IRQ. We pass the device pointer as the interrupt routine argument. We
+        don't need to since we only support one card but doing this will make it
+        easier to upgrade the driver for multiple devices in the future.
+  </para>
+  <para>
+        Our interrupt routine needs to do little if we assume the card can simply
+        queue one frame to be read after it captures it. 
+  </para>
+  <programlisting>
+
+
+static struct wait_queue *capture_wait;
+static int capture_ready = 0;
+
+static void camera_irq(int irq, void *dev_id, 
+                          struct pt_regs *regs)
+{
+        capture_ready=1;
+        wake_up_interruptible(&amp;capture_wait);
+}
+  </programlisting>
+  <para>
+        The interrupt handler is nice and simple for this card as we are assuming
+        the card is buffering the frame for us. This means we have little to do but
+        wake up        anybody interested. We also set a capture_ready flag, as we may
+        capture a frame before an application needs it. In this case we need to know
+        that a frame is ready. If we had to collect the frame on the interrupt life
+        would be more complex.
+  </para>
+  <para>
+        The two new routines we need to supply are camera_read which returns a
+        frame, and camera_poll which waits for a frame to become ready.
+  </para>
+  <programlisting>
+
+
+static int camera_poll(struct video_device *dev, 
+	struct file *file, struct poll_table *wait)
+{
+        poll_wait(file, &amp;capture_wait, wait);
+        if(capture_read)
+                return POLLIN|POLLRDNORM;
+        return 0;
+}
+
+  </programlisting>
+  <para>
+        Our wait queue for polling is the capture_wait queue. This will cause the
+        task to be woken up by our camera_irq routine. We check capture_read to see
+        if there is an image present and if so report that it is readable.
+  </para>
+  </sect1>
+  <sect1 id="rdvid">
+  <title>Reading The Video Image</title>
+  <programlisting>
+
+
+static long camera_read(struct video_device *dev, char *buf,
+                                unsigned long count)
+{
+        struct wait_queue wait = { current, NULL };
+        u8 *ptr;
+        int len;
+        int i;
+
+        add_wait_queue(&amp;capture_wait, &amp;wait);
+
+        while(!capture_ready)
+        {
+                if(file->flags&amp;O_NDELAY)
+                {
+                        remove_wait_queue(&amp;capture_wait, &amp;wait);
+                        current->state = TASK_RUNNING;
+                        return -EWOULDBLOCK;
+                }
+                if(signal_pending(current))
+                {
+                        remove_wait_queue(&amp;capture_wait, &amp;wait);
+                        current->state = TASK_RUNNING;
+                        return -ERESTARTSYS;
+                }
+                schedule();
+                current->state = TASK_INTERRUPTIBLE;
+        }
+        remove_wait_queue(&amp;capture_wait, &amp;wait);
+        current->state = TASK_RUNNING;
+
+  </programlisting>
+  <para>
+        The first thing we have to do is to ensure that the application waits until
+        the next frame is ready. The code here is almost identical to the mouse code
+        we used earlier in this chapter. It is one of the common building blocks of
+        Linux device driver code and probably one which you will find occurs in any
+        drivers you write.
+  </para>
+  <para>
+        We wait for a frame to be ready, or for a signal to interrupt our waiting. If a
+        signal occurs we need to return from the system call so that the signal can
+        be sent to the application itself. We also check to see if the user actually
+        wanted to avoid waiting - ie  if they are using non-blocking I/O and have other things 
+        to get on with.
+  </para>
+  <para>
+        Next we copy the data from the card to the user application. This is rarely
+        as easy as our example makes out. We will add capture_w, and capture_h here
+        to hold the width and height of the captured image. We assume the card only
+        supports 24bit RGB for now.
+  </para>
+  <programlisting>
+
+
+
+        capture_ready = 0;
+
+        ptr=(u8 *)buf;
+        len = capture_w * 3 * capture_h; /* 24bit RGB */
+
+        if(len>count)
+                len=count;  /* Doesn't all fit */
+
+        for(i=0; i&lt;len; i++)
+        {
+                put_user(inb(io+IMAGE_DATA), ptr);
+                ptr++;
+        }
+
+        hardware_restart_capture();
+                
+        return i;
+}
+
+  </programlisting>
+  <para>
+        For a real hardware device you would try to avoid the loop with put_user().
+        Each call to put_user() has a time overhead checking whether the accesses to user
+        space are allowed. It would be better to read a line into a temporary buffer
+        then copy this to user space in one go.
+  </para>
+  <para>
+        Having captured the image and put it into user space we can kick the card to
+        get the next frame acquired.
+  </para>
+  </sect1>
+  <sect1 id="iocvid">
+  <title>Video Ioctl Handling</title>
+  <para>
+        As with the radio driver the major control interface is via the ioctl()
+        function. Video capture devices support the same tuner calls as a radio
+        device and also support additional calls to control how the video functions
+        are handled. In this simple example the card has no tuners to avoid making
+        the code complex. 
+  </para>
+  <programlisting>
+
+
+
+static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+        switch(cmd)
+        {
+                case VIDIOCGCAP:
+                {
+                        struct video_capability v;
+                        v.type = VID_TYPE_CAPTURE|\
+                                 VID_TYPE_CHROMAKEY|\
+                                 VID_TYPE_SCALES|\
+                                 VID_TYPE_OVERLAY;
+                        v.channels = 1;
+                        v.audios = 0;
+                        v.maxwidth = 640;
+                        v.minwidth = 16;
+                        v.maxheight = 480;
+                        v.minheight = 16;
+                        strcpy(v.name, "My Camera");
+                        if(copy_to_user(arg, &amp;v, sizeof(v)))
+                                return -EFAULT;
+                        return 0;
+                }
+
+
+  </programlisting>
+  <para>
+        The first ioctl we must support and which all video capture and radio
+        devices are required to support is VIDIOCGCAP. This behaves exactly the same
+        as with a radio device. This time, however, we report the extra capabilities
+        we outlined earlier on when defining our video_dev structure.
+  </para>
+  <para>
+        We now set the video flags saying that we support overlay, capture,
+        scaling and chromakey. We also report size limits - our smallest image is
+        16x16 pixels, our largest is 640x480. 
+  </para>
+  <para>
+        To keep things simple we report no audio and no tuning capabilities at all.
+  </para>
+  <programlisting>        
+
+                case VIDIOCGCHAN:
+                {
+                        struct video_channel v;
+                        if(copy_from_user(&amp;v, arg, sizeof(v)))
+                                return -EFAULT;
+                        if(v.channel != 0)
+                                return -EINVAL;
+                        v.flags = 0;
+                        v.tuners = 0;
+                        v.type = VIDEO_TYPE_CAMERA;
+                        v.norm = VIDEO_MODE_AUTO;
+                        strcpy(v.name, "Camera Input");break;
+                        if(copy_to_user(&amp;v, arg, sizeof(v)))
+                                return -EFAULT;
+                        return 0;
+                }
+
+
+  </programlisting>
+  <para>
+        This follows what is very much the standard way an ioctl handler looks
+        in Linux. We copy the data into a kernel space variable and we check that the
+        request is valid (in this case that the input is 0). Finally we copy the
+        camera info back to the user.
+  </para>
+  <para>
+        The VIDIOCGCHAN ioctl allows a user to ask about video channels (that is
+        inputs to the video card). Our example card has a single camera input. The
+        fields in the structure are
+  </para>
+   <table frame="all"><title>struct video_channel fields</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+
+   <entry>channel</entry><entry>The channel number we are selecting</entry>
+   </row><row>
+   <entry>name</entry><entry>The name for this channel. This is intended
+                   to describe the port to the user.
+                   Appropriate names are therefore things like
+                   "Camera" "SCART input"</entry>
+   </row><row>
+   <entry>flags</entry><entry>Channel properties</entry>
+   </row><row>
+   <entry>type</entry><entry>Input type</entry>
+   </row><row>
+   <entry>norm</entry><entry>The current television encoding being used
+                   if relevant for this channel.
+    </entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+    <table frame="all"><title>struct video_channel flags</title>
+    <tgroup cols="2" align="left">
+    <tbody>
+    <row>
+        <entry>VIDEO_VC_TUNER</entry><entry>Channel has a tuner.</entry>
+   </row><row>
+        <entry>VIDEO_VC_AUDIO</entry><entry>Channel has audio.</entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+    <table frame="all"><title>struct video_channel types</title>
+    <tgroup cols="2" align="left">
+    <tbody>
+    <row>
+        <entry>VIDEO_TYPE_TV</entry><entry>Television input.</entry>
+   </row><row>
+        <entry>VIDEO_TYPE_CAMERA</entry><entry>Fixed camera input.</entry>
+   </row><row>
+	<entry>0</entry><entry>Type is unknown.</entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+    <table frame="all"><title>struct video_channel norms</title>
+    <tgroup cols="2" align="left">
+    <tbody>
+    <row>
+        <entry>VIDEO_MODE_PAL</entry><entry>PAL encoded Television</entry>
+   </row><row>
+        <entry>VIDEO_MODE_NTSC</entry><entry>NTSC (US) encoded Television</entry>
+   </row><row>
+        <entry>VIDEO_MODE_SECAM</entry><entry>SECAM (French) Television </entry>
+   </row><row>
+        <entry>VIDEO_MODE_AUTO</entry><entry>Automatic switching, or format does not
+                                matter</entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+    <para>
+        The corresponding VIDIOCSCHAN ioctl allows a user to change channel and to
+        request the norm is changed - for example to switch between a PAL or an NTSC
+        format camera.
+  </para>
+  <programlisting>
+
+
+                case VIDIOCSCHAN:
+                {
+                        struct video_channel v;
+                        if(copy_from_user(&amp;v, arg, sizeof(v)))
+                                return -EFAULT;
+                        if(v.channel != 0)
+                                return -EINVAL;
+                        if(v.norm != VIDEO_MODE_AUTO)
+                                return -EINVAL;
+                        return 0;
+                }
+
+
+  </programlisting>
+  <para>
+        The implementation of this call in our driver is remarkably easy. Because we
+        are assuming fixed format hardware we need only check that the user has not
+        tried to change anything. 
+  </para>
+  <para>
+        The user also needs to be able to configure and adjust the picture they are
+        seeing. This is much like adjusting a television set. A user application
+        also needs to know the palette being used so that it knows how to display
+        the image that has been captured. The VIDIOCGPICT and VIDIOCSPICT ioctl
+        calls provide this information.
+  </para>
+  <programlisting>
+
+
+                case VIDIOCGPICT
+                {
+                        struct video_picture v;
+                        v.brightness = hardware_brightness();
+                        v.hue = hardware_hue();
+                        v.colour = hardware_saturation();
+                        v.contrast = hardware_brightness();
+                        /* Not settable */
+                        v.whiteness = 32768;
+                        v.depth = 24;           /* 24bit */
+                        v.palette = VIDEO_PALETTE_RGB24;
+                        if(copy_to_user(&amp;v, arg, 
+                             sizeof(v)))
+                                return -EFAULT;
+                        return 0;
+                }
+
+
+  </programlisting>
+  <para>
+        The brightness, hue, color, and contrast provide the picture controls that
+        are akin to a conventional television. Whiteness provides additional
+        control for greyscale images. All of these values are scaled between 0-65535
+        and have 32768 as the mid point setting. The scaling means that applications
+        do not have to worry about the capability range of the hardware but can let
+        it make a best effort attempt.
+  </para>
+  <para>
+        Our depth is 24, as this is in bits. We will be returning RGB24 format. This
+        has one byte of red, then one of green, then one of blue. This then repeats
+        for every other pixel in the image. The other common formats the interface 
+        defines are
+  </para>
+   <table frame="all"><title>Framebuffer Encodings</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+   <entry>GREY</entry><entry>Linear greyscale. This is for simple cameras and the
+                        like</entry>
+   </row><row>
+   <entry>RGB565</entry><entry>The top 5 bits hold 32 red levels, the next six bits
+                        hold green and the low 5 bits hold blue. </entry>
+   </row><row>
+   <entry>RGB555</entry><entry>The top bit is clear. The red green and blue levels
+                        each occupy five bits.</entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+  <para>
+        Additional modes are support for YUV capture formats. These are common for
+        TV and video conferencing applications.
+  </para>
+  <para>
+        The VIDIOCSPICT ioctl allows a user to set some of the picture parameters.
+        Exactly which ones are supported depends heavily on the card itself. It is
+        possible to support many modes and effects in software. In general doing
+        this in the kernel is a bad idea. Video capture is a performance-sensitive
+        application and the programs can often do better if they aren't being
+        'helped' by an overkeen driver writer. Thus for our device we will report
+        RGB24 only and refuse to allow a change.
+  </para>
+  <programlisting>
+
+
+                case VIDIOCSPICT:
+                {
+                        struct video_picture v;
+                        if(copy_from_user(&amp;v, arg, sizeof(v)))
+                                return -EFAULT;
+                        if(v.depth!=24 || 
+                           v.palette != VIDEO_PALETTE_RGB24)
+                                return -EINVAL;
+                        set_hardware_brightness(v.brightness);
+                        set_hardware_hue(v.hue);
+                        set_hardware_saturation(v.colour);
+                        set_hardware_brightness(v.contrast);
+                        return 0;
+                }
+
+
+  </programlisting>
+  <para>
+        We check the user has not tried to change the palette or the depth. We do
+        not want to carry out some of the changes and then return an error. This may
+        confuse the application which will be assuming no change occurred.
+  </para>
+  <para>
+        In much the same way as you need to be able to set the picture controls to
+        get the right capture images, many cards need to know what they are
+        displaying onto when generating overlay output. In some cases getting this
+        wrong even makes a nasty mess or may crash the computer. For that reason
+        the VIDIOCSBUF ioctl used to set up the frame buffer information may well
+        only be usable by root.
+  </para>
+  <para>
+        We will assume our card is one of the old ISA devices with feature connector
+        and only supports a couple of standard video modes. Very common for older
+        cards although the PCI devices are way smarter than this.
+  </para>
+  <programlisting>
+
+
+static struct video_buffer capture_fb;
+
+                case VIDIOCGFBUF:
+                {
+                        if(copy_to_user(arg, &amp;capture_fb, 
+                             sizeof(capture_fb)))
+                                return -EFAULT;
+                        return 0;
+                        
+                }
+
+
+  </programlisting>
+  <para>
+        We keep the frame buffer information in the format the ioctl uses. This
+        makes it nice and easy to work with in the ioctl calls.
+  </para>
+  <programlisting>
+
+                case VIDIOCSFBUF:
+                {
+                        struct video_buffer v;
+
+                        if(!capable(CAP_SYS_ADMIN))
+                                return -EPERM;
+
+                        if(copy_from_user(&amp;v, arg, sizeof(v)))
+                                return -EFAULT;
+                        if(v.width!=320 &amp;&amp; v.width!=640)
+                                return -EINVAL;
+                        if(v.height!=200 &amp;&amp; v.height!=240 
+                                &amp;&amp; v.height!=400
+                                &amp;&amp; v.height !=480)
+                                return -EINVAL;
+                        memcpy(&amp;capture_fb, &amp;v, sizeof(v));
+                        hardware_set_fb(&amp;v);
+                        return 0;
+                }
+
+
+
+  </programlisting>
+  <para>
+        The capable() function checks a user has the required capability. The Linux
+        operating system has a set of about 30 capabilities indicating privileged
+        access to services. The default set up gives the superuser (uid 0) all of
+        them and nobody else has any.
+  </para>
+  <para>
+        We check that the user has the SYS_ADMIN capability, that is they are
+        allowed to operate as the machine administrator. We don't want anyone but
+        the administrator making a mess of the display.
+  </para>
+  <para>
+        Next we check for standard PC video modes (320 or 640 wide with either
+        EGA or VGA depths). If the mode is not a standard video mode we reject it as
+        not supported by our card. If the mode is acceptable we save it so that
+        VIDIOCFBUF will give the right answer next time it is called.  The
+        hardware_set_fb() function is some undescribed card specific function to
+        program the card for the desired mode.
+  </para>
+  <para>
+        Before the driver can display an overlay window it needs to know where the
+        window should be placed, and also how large it should be. If the card
+        supports clipping it needs to know which rectangles to omit from the
+        display. The video_window structure is used to describe the way the image 
+        should be displayed. 
+   </para>
+   <table frame="all"><title>struct video_window fields</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+        <entry>width</entry><entry>The width in pixels of the desired image. The card
+                        may use a smaller size if this size is not available</entry>
+	</row><row>
+        <entry>height</entry><entry>The height of the image. The card may use a smaller
+                        size if this size is not available.</entry>
+	</row><row>
+        <entry>x</entry><entry>   The X position of the top left of the window. This
+                        is in pixels relative to the left hand edge of the
+                        picture. Not all cards can display images aligned on
+                        any pixel boundary. If the position is unsuitable
+                        the card adjusts the image right and reduces the
+                        width.</entry>
+	</row><row>
+        <entry>y</entry><entry>   The Y position of the top left of the window. This
+                        is counted in pixels relative to the top edge of the
+                        picture. As with the width if the card cannot
+                        display  starting on this line it will adjust the
+                        values.</entry>
+	</row><row>
+        <entry>chromakey</entry><entry>The colour (expressed in RGB32 format) for the
+                        chromakey colour if chroma keying is being used. </entry>
+	</row><row>
+        <entry>clips</entry><entry>An array of rectangles that must not be drawn
+			over.</entry>
+	</row><row>
+        <entry>clipcount</entry><entry>The number of clips in this array.</entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+    <para>
+        Each clip is a struct video_clip which has the following fields
+   </para>
+   <table frame="all"><title>video_clip fields</title>
+   <tgroup cols="2" align="left">
+   <tbody>
+   <row>
+        <entry>x, y</entry><entry>Co-ordinates relative to the display</entry>
+	</row><row>
+        <entry>width, height</entry><entry>Width and height in pixels</entry>
+	</row><row>
+        <entry>next</entry><entry>A spare field for the application to use</entry>
+    </row>
+    </tbody>
+    </tgroup>
+    </table>
+    <para>
+        The driver is required to ensure it always draws in the area requested or a        smaller area, and that it never draws in any of the areas that are clipped.
+        This may well mean it has to leave alone. small areas the application wished to be
+        drawn.
+  </para>
+  <para>
+        Our example card uses chromakey so does not have to address most of the
+        clipping.  We will add a video_window structure to our global variables to
+        remember our parameters, as we did with the frame buffer.
+  </para>
+  <programlisting>
+
+
+                case VIDIOCGWIN:
+                {
+                        if(copy_to_user(arg, &amp;capture_win, 
+                            sizeof(capture_win)))
+                                return -EFAULT;
+                        return 0;
+                }
+
+
+                case VIDIOCSWIN:
+                {
+                        struct video_window v;
+                        if(copy_from_user(&amp;v, arg, sizeof(v)))
+                                return -EFAULT;
+                        if(v.width &gt; 640 || v.height &gt; 480)
+                                return -EINVAL;
+                        if(v.width &lt; 16 || v.height &lt; 16)
+                                return -EINVAL;
+                        hardware_set_key(v.chromakey);
+                        hardware_set_window(v);
+                        memcpy(&amp;capture_win, &amp;v, sizeof(v));
+                        capture_w = v.width;
+                        capture_h = v.height;
+                        return 0;
+                }
+
+
+  </programlisting>
+  <para>
+        Because we are using Chromakey our setup is fairly simple. Mostly we have to
+        check the values are sane and load them into the capture card.
+  </para>
+  <para>
+        With all the setup done we can now turn on the actual capture/overlay. This
+        is done with the VIDIOCCAPTURE ioctl. This takes a single integer argument
+        where 0 is on and 1 is off.
+  </para>
+  <programlisting>
+
+
+                case VIDIOCCAPTURE:
+                {
+                        int v;
+                        if(get_user(v, (int *)arg))
+                                return -EFAULT;
+                        if(v==0)
+                                hardware_capture_off();
+                        else
+                        {
+                                if(capture_fb.width == 0 
+                                    || capture_w == 0)
+                                        return -EINVAL;
+                                hardware_capture_on();
+                        }
+                        return 0;
+                }
+
+
+  </programlisting>
+  <para>
+        We grab the flag from user space and either enable or disable according to
+        its value. There is one small corner case we have to consider here. Suppose
+        that the capture was requested before the video window or the frame buffer
+        had been set up. In those cases there will be unconfigured fields in our
+        card data, as well as unconfigured hardware settings. We check for this case and
+        return an error if the frame buffer or the capture window width is zero.
+  </para>
+  <programlisting>
+
+
+                default:
+                        return -ENOIOCTLCMD;
+        }
+}
+  </programlisting>
+  <para>
+
+        We don't need to support any other ioctls, so if we get this far, it is time
+        to tell the video layer that we don't now what the user is talking about.
+  </para>
+  </sect1>
+  <sect1 id="endvid">
+  <title>Other Functionality</title>
+  <para>
+        The Video4Linux layer supports additional features, including a high
+        performance mmap() based capture mode and capturing part of the image. 
+        These features are out of the scope of the book.  You should however have enough 
+        example code to implement most simple video4linux devices for radio and TV
+        cards.
+  </para>
+  </sect1>
+  </chapter>
+  <chapter id="bugs">
+     <title>Known Bugs And Assumptions</title>
+  <para>
+  <variablelist>
+    <varlistentry><term>Multiple Opens</term>
+    <listitem>
+    <para>
+        The driver assumes multiple opens should not be allowed. A driver
+        can work around this but not cleanly.
+    </para>
+    </listitem></varlistentry>
+
+    <varlistentry><term>API Deficiencies</term>
+    <listitem>
+    <para>
+        The existing API poorly reflects compression capable devices. There
+        are plans afoot to merge V4L, V4L2 and some other ideas into a
+        better interface.
+    </para>
+    </listitem></varlistentry>
+  </variablelist>
+
+  </para>
+  </chapter>
+
+  <chapter id="pubfunctions">
+     <title>Public Functions Provided</title>
+!Edrivers/media/video/videodev.c
+  </chapter>
+
+</book>

+ 99 - 0
Documentation/DocBook/wanbook.tmpl

@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="WANGuide">
+ <bookinfo>
+  <title>Synchronous PPP and Cisco HDLC Programming Guide</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Alan</firstname>
+    <surname>Cox</surname>
+    <affiliation>
+     <address>
+      <email>alan@redhat.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2000</year>
+   <holder>Alan Cox</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+	The syncppp drivers in Linux provide a fairly complete 
+	implementation of Cisco HDLC and a minimal implementation of
+	PPP. The longer term goal is to switch the PPP layer to the
+	generic PPP interface that is new in Linux 2.3.x. The API should
+	remain unchanged when this is done, but support will then be
+	available for IPX, compression and other PPP features
+  </para>
+  </chapter>
+  <chapter id="bugs">
+     <title>Known Bugs And Assumptions</title>
+  <para>
+  <variablelist>
+    <varlistentry><term>PPP is minimal</term>
+    <listitem>
+    <para>
+	The current PPP implementation is very basic, although sufficient
+	for most wan usages.
+    </para>
+    </listitem></varlistentry>
+
+    <varlistentry><term>Cisco HDLC Quirks</term>
+    <listitem>
+    <para>
+	Currently we do not end all packets with the correct Cisco multicast
+	or unicast flags. Nothing appears to mind too much but this should
+	be corrected.
+    </para>
+    </listitem></varlistentry>
+  </variablelist>
+	
+  </para>
+  </chapter>
+
+  <chapter id="pubfunctions">
+     <title>Public Functions Provided</title>
+!Edrivers/net/wan/syncppp.c
+  </chapter>
+
+</book>

+ 419 - 0
Documentation/DocBook/writing_usb_driver.tmpl

@@ -0,0 +1,419 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="USBDeviceDriver">
+ <bookinfo>
+  <title>Writing USB Device Drivers</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Greg</firstname>
+    <surname>Kroah-Hartman</surname>
+    <affiliation>
+     <address>
+      <email>greg@kroah.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2001-2002</year>
+   <holder>Greg Kroah-Hartman</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+
+   <para>
+     This documentation is based on an article published in 
+     Linux Journal Magazine, October 2001, Issue 90.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+      The Linux USB subsystem has grown from supporting only two different
+      types of devices in the 2.2.7 kernel (mice and keyboards), to over 20
+      different types of devices in the 2.4 kernel. Linux currently supports
+      almost all USB class devices (standard types of devices like keyboards,
+      mice, modems, printers and speakers) and an ever-growing number of
+      vendor-specific devices (such as USB to serial converters, digital
+      cameras, Ethernet devices and MP3 players). For a full list of the
+      different USB devices currently supported, see Resources.
+  </para>
+  <para>
+      The remaining kinds of USB devices that do not have support on Linux are
+      almost all vendor-specific devices. Each vendor decides to implement a
+      custom protocol to talk to their device, so a custom driver usually needs
+      to be created. Some vendors are open with their USB protocols and help
+      with the creation of Linux drivers, while others do not publish them, and
+      developers are forced to reverse-engineer. See Resources for some links
+      to handy reverse-engineering tools.
+  </para>
+  <para>
+      Because each different protocol causes a new driver to be created, I have
+      written a generic USB driver skeleton, modeled after the pci-skeleton.c
+      file in the kernel source tree upon which many PCI network drivers have
+      been based. This USB skeleton can be found at drivers/usb/usb-skeleton.c
+      in the kernel source tree. In this article I will walk through the basics
+      of the skeleton driver, explaining the different pieces and what needs to
+      be done to customize it to your specific device.
+  </para>
+  </chapter>
+
+  <chapter id="basics">
+      <title>Linux USB Basics</title>
+  <para>
+      If you are going to write a Linux USB driver, please become familiar with
+      the USB protocol specification. It can be found, along with many other
+      useful documents, at the USB home page (see Resources). An excellent
+      introduction to the Linux USB subsystem can be found at the USB Working
+      Devices List (see Resources). It explains how the Linux USB subsystem is
+      structured and introduces the reader to the concept of USB urbs, which
+      are essential to USB drivers.
+  </para>
+  <para>
+      The first thing a Linux USB driver needs to do is register itself with
+      the Linux USB subsystem, giving it some information about which devices
+      the driver supports and which functions to call when a device supported
+      by the driver is inserted or removed from the system. All of this
+      information is passed to the USB subsystem in the usb_driver structure.
+      The skeleton driver declares a usb_driver as:
+  </para>
+  <programlisting>
+static struct usb_driver skel_driver = {
+        .name        = "skeleton",
+        .probe       = skel_probe,
+        .disconnect  = skel_disconnect,
+        .fops        = &amp;skel_fops,
+        .minor       = USB_SKEL_MINOR_BASE,
+        .id_table    = skel_table,
+};
+  </programlisting>
+  <para>
+      The variable name is a string that describes the driver. It is used in
+      informational messages printed to the system log. The probe and
+      disconnect function pointers are called when a device that matches the
+      information provided in the id_table variable is either seen or removed.
+  </para>
+  <para>
+      The fops and minor variables are optional. Most USB drivers hook into
+      another kernel subsystem, such as the SCSI, network or TTY subsystem.
+      These types of drivers register themselves with the other kernel
+      subsystem, and any user-space interactions are provided through that
+      interface. But for drivers that do not have a matching kernel subsystem,
+      such as MP3 players or scanners, a method of interacting with user space
+      is needed. The USB subsystem provides a way to register a minor device
+      number and a set of file_operations function pointers that enable this
+      user-space interaction. The skeleton driver needs this kind of interface,
+      so it provides a minor starting number and a pointer to its
+      file_operations functions.
+  </para>
+  <para>
+      The USB driver is then registered with a call to usb_register, usually in
+      the driver's init function, as shown here:
+  </para>
+  <programlisting>
+static int __init usb_skel_init(void)
+{
+        int result;
+
+        /* register this driver with the USB subsystem */
+        result = usb_register(&amp;skel_driver);
+        if (result &lt; 0) {
+                err(&quot;usb_register failed for the &quot;__FILE__ &quot;driver.&quot;
+                    &quot;Error number %d&quot;, result);
+                return -1;
+        }
+
+        return 0;
+}
+module_init(usb_skel_init);
+  </programlisting>
+  <para>
+      When the driver is unloaded from the system, it needs to unregister
+      itself with the USB subsystem. This is done with the usb_unregister
+      function:
+  </para>
+  <programlisting>
+static void __exit usb_skel_exit(void)
+{
+        /* deregister this driver with the USB subsystem */
+        usb_deregister(&amp;skel_driver);
+}
+module_exit(usb_skel_exit);
+  </programlisting>
+  <para>
+     To enable the linux-hotplug system to load the driver automatically when
+     the device is plugged in, you need to create a MODULE_DEVICE_TABLE. The
+     following code tells the hotplug scripts that this module supports a
+     single device with a specific vendor and product ID:
+  </para>
+  <programlisting>
+/* table of devices that work with this driver */
+static struct usb_device_id skel_table [] = {
+        { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
+        { }                      /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, skel_table);
+  </programlisting>
+  <para>
+     There are other macros that can be used in describing a usb_device_id for
+     drivers that support a whole class of USB drivers. See usb.h for more
+     information on this.
+  </para>
+  </chapter>
+
+  <chapter id="device">
+      <title>Device operation</title>
+  <para>
+     When a device is plugged into the USB bus that matches the device ID
+     pattern that your driver registered with the USB core, the probe function
+     is called. The usb_device structure, interface number and the interface ID
+     are passed to the function:
+  </para>
+  <programlisting>
+static int skel_probe(struct usb_interface *interface,
+    const struct usb_device_id *id)
+  </programlisting>
+  <para>
+     The driver now needs to verify that this device is actually one that it
+     can accept. If so, it returns 0.
+     If not, or if any error occurs during initialization, an errorcode
+     (such as <literal>-ENOMEM</literal> or <literal>-ENODEV</literal>)
+     is returned from the probe function.
+  </para>
+  <para>
+     In the skeleton driver, we determine what end points are marked as bulk-in
+     and bulk-out. We create buffers to hold the data that will be sent and
+     received from the device, and a USB urb to write data to the device is
+     initialized.
+  </para>
+  <para>
+     Conversely, when the device is removed from the USB bus, the disconnect
+     function is called with the device pointer. The driver needs to clean any
+     private data that has been allocated at this time and to shut down any
+     pending urbs that are in the USB system. The driver also unregisters
+     itself from the devfs subsystem with the call:
+  </para>
+  <programlisting>
+/* remove our devfs node */
+devfs_unregister(skel->devfs);
+  </programlisting>
+  <para>
+     Now that the device is plugged into the system and the driver is bound to
+     the device, any of the functions in the file_operations structure that
+     were passed to the USB subsystem will be called from a user program trying
+     to talk to the device. The first function called will be open, as the
+     program tries to open the device for I/O. We increment our private usage
+     count and save off a pointer to our internal structure in the file
+     structure. This is done so that future calls to file operations will
+     enable the driver to determine which device the user is addressing.  All
+     of this is done with the following code:
+  </para>
+  <programlisting>
+/* increment our usage count for the module */
+++skel->open_count;
+
+/* save our object in the file's private structure */
+file->private_data = dev;
+  </programlisting>
+  <para>
+     After the open function is called, the read and write functions are called
+     to receive and send data to the device. In the skel_write function, we
+     receive a pointer to some data that the user wants to send to the device
+     and the size of the data. The function determines how much data it can
+     send to the device based on the size of the write urb it has created (this
+     size depends on the size of the bulk out end point that the device has).
+     Then it copies the data from user space to kernel space, points the urb to
+     the data and submits the urb to the USB subsystem.  This can be shown in
+     he following code:
+  </para>
+  <programlisting>
+/* we can only write as much as 1 urb will hold */
+bytes_written = (count > skel->bulk_out_size) ? skel->bulk_out_size : count;
+
+/* copy the data from user space into our urb */
+copy_from_user(skel->write_urb->transfer_buffer, buffer, bytes_written);
+
+/* set up our urb */
+usb_fill_bulk_urb(skel->write_urb,
+                  skel->dev,
+                  usb_sndbulkpipe(skel->dev, skel->bulk_out_endpointAddr),
+                  skel->write_urb->transfer_buffer,
+                  bytes_written,
+                  skel_write_bulk_callback,
+                  skel);
+
+/* send the data out the bulk port */
+result = usb_submit_urb(skel->write_urb);
+if (result) {
+        err(&quot;Failed submitting write urb, error %d&quot;, result);
+}
+  </programlisting>
+  <para>
+     When the write urb is filled up with the proper information using the
+     usb_fill_bulk_urb function, we point the urb's completion callback to call our
+     own skel_write_bulk_callback function. This function is called when the
+     urb is finished by the USB subsystem. The callback function is called in
+     interrupt context, so caution must be taken not to do very much processing
+     at that time. Our implementation of skel_write_bulk_callback merely
+     reports if the urb was completed successfully or not and then returns.
+  </para>
+  <para>
+     The read function works a bit differently from the write function in that
+     we do not use an urb to transfer data from the device to the driver.
+     Instead we call the usb_bulk_msg function, which can be used to send or
+     receive data from a device without having to create urbs and handle
+     urb completion callback functions. We call the usb_bulk_msg function,
+     giving it a buffer into which to place any data received from the device
+     and a timeout value. If the timeout period expires without receiving any
+     data from the device, the function will fail and return an error message.
+     This can be shown with the following code:
+  </para>
+  <programlisting>
+/* do an immediate bulk read to get data from the device */
+retval = usb_bulk_msg (skel->dev,
+                       usb_rcvbulkpipe (skel->dev,
+                       skel->bulk_in_endpointAddr),
+                       skel->bulk_in_buffer,
+                       skel->bulk_in_size,
+                       &amp;count, HZ*10);
+/* if the read was successful, copy the data to user space */
+if (!retval) {
+        if (copy_to_user (buffer, skel->bulk_in_buffer, count))
+                retval = -EFAULT;
+        else
+                retval = count;
+}
+  </programlisting>
+  <para>
+     The usb_bulk_msg function can be very useful for doing single reads or
+     writes to a device; however, if you need to read or write constantly to a
+     device, it is recommended to set up your own urbs and submit them to the
+     USB subsystem.
+  </para>
+  <para>
+     When the user program releases the file handle that it has been using to
+     talk to the device, the release function in the driver is called. In this
+     function we decrement our private usage count and wait for possible
+     pending writes:
+  </para>
+  <programlisting>
+/* decrement our usage count for the device */
+--skel->open_count;
+  </programlisting>
+  <para>
+     One of the more difficult problems that USB drivers must be able to handle
+     smoothly is the fact that the USB device may be removed from the system at
+     any point in time, even if a program is currently talking to it. It needs
+     to be able to shut down any current reads and writes and notify the
+     user-space programs that the device is no longer there. The following
+     code (function <function>skel_delete</function>)
+     is an example of how to do this: </para>
+  <programlisting>
+static inline void skel_delete (struct usb_skel *dev)
+{
+    if (dev->bulk_in_buffer != NULL)
+        kfree (dev->bulk_in_buffer);
+    if (dev->bulk_out_buffer != NULL)
+        usb_buffer_free (dev->udev, dev->bulk_out_size,
+            dev->bulk_out_buffer,
+            dev->write_urb->transfer_dma);
+    if (dev->write_urb != NULL)
+        usb_free_urb (dev->write_urb);
+    kfree (dev);
+}
+  </programlisting>
+  <para>
+     If a program currently has an open handle to the device, we reset the flag
+     <literal>device_present</literal>. For
+     every read, write, release and other functions that expect a device to be
+     present, the driver first checks this flag to see if the device is
+     still present. If not, it releases that the device has disappeared, and a
+     -ENODEV error is returned to the user-space program. When the release
+     function is eventually called, it determines if there is no device
+     and if not, it does the cleanup that the skel_disconnect
+     function normally does if there are no open files on the device (see
+     Listing 5).
+  </para>
+  </chapter>
+
+  <chapter id="iso">
+      <title>Isochronous Data</title>
+  <para>
+     This usb-skeleton driver does not have any examples of interrupt or
+     isochronous data being sent to or from the device. Interrupt data is sent
+     almost exactly as bulk data is, with a few minor exceptions.  Isochronous
+     data works differently with continuous streams of data being sent to or
+     from the device. The audio and video camera drivers are very good examples
+     of drivers that handle isochronous data and will be useful if you also
+     need to do this.
+  </para>
+  </chapter>
+  
+  <chapter id="Conclusion">
+      <title>Conclusion</title>
+  <para>
+     Writing Linux USB device drivers is not a difficult task as the
+     usb-skeleton driver shows. This driver, combined with the other current
+     USB drivers, should provide enough examples to help a beginning author
+     create a working driver in a minimal amount of time. The linux-usb-devel
+     mailing list archives also contain a lot of helpful information.
+  </para>
+  </chapter>
+
+  <chapter id="resources">
+      <title>Resources</title>
+  <para>
+     The Linux USB Project: <ulink url="http://www.linux-usb.org">http://www.linux-usb.org/</ulink>
+  </para>
+  <para>
+     Linux Hotplug Project: <ulink url="http://linux-hotplug.sourceforge.net">http://linux-hotplug.sourceforge.net/</ulink>
+  </para>
+  <para>
+     Linux USB Working Devices List: <ulink url="http://www.qbik.ch/usb/devices">http://www.qbik.ch/usb/devices/</ulink>
+  </para>
+  <para>
+     linux-usb-devel Mailing List Archives: <ulink url="http://marc.theaimsgroup.com/?l=linux-usb-devel">http://marc.theaimsgroup.com/?l=linux-usb-devel</ulink>
+  </para>
+  <para>
+     Programming Guide for Linux USB Device Drivers: <ulink url="http://usb.cs.tum.edu/usbdoc">http://usb.cs.tum.edu/usbdoc</ulink>
+  </para>
+  <para>
+     USB Home Page: <ulink url="http://www.usb.org">http://www.usb.org</ulink>
+  </para>
+  </chapter>
+
+</book>

+ 385 - 0
Documentation/DocBook/z8530book.tmpl

@@ -0,0 +1,385 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="Z85230Guide">
+ <bookinfo>
+  <title>Z8530 Programming Guide</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Alan</firstname>
+    <surname>Cox</surname>
+    <affiliation>
+     <address>
+      <email>alan@redhat.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2000</year>
+   <holder>Alan Cox</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+	The Z85x30 family synchronous/asynchronous controller chips are
+	used on a large number of cheap network interface cards. The
+	kernel provides a core interface layer that is designed to make
+	it easy to provide WAN services using this chip.
+  </para>
+  <para>
+	The current driver only support synchronous operation. Merging the
+	asynchronous driver support into this code to allow any Z85x30
+	device to be used as both a tty interface and as a synchronous 
+	controller is a project for Linux post the 2.4 release
+  </para>
+  <para>
+	The support code handles most common card configurations and
+	supports running both Cisco HDLC and Synchronous PPP. With extra
+	glue the frame relay and X.25 protocols can also be used with this
+	driver.
+  </para>
+  </chapter>
+  
+  <chapter>
+ 	<title>Driver Modes</title>
+  <para>
+	The Z85230 driver layer can drive Z8530, Z85C30 and Z85230 devices
+	in three different modes. Each mode can be applied to an individual
+	channel on the chip (each chip has two channels).
+  </para>
+  <para>
+	The PIO synchronous mode supports the most common Z8530 wiring. Here
+	the chip is interface to the I/O and interrupt facilities of the
+	host machine but not to the DMA subsystem. When running PIO the
+	Z8530 has extremely tight timing requirements. Doing high speeds,
+	even with a Z85230 will be tricky. Typically you should expect to
+	achieve at best 9600 baud with a Z8C530 and 64Kbits with a Z85230.
+  </para>
+  <para>
+	The DMA mode supports the chip when it is configured to use dual DMA
+	channels on an ISA bus. The better cards tend to support this mode
+	of operation for a single channel. With DMA running the Z85230 tops
+	out when it starts to hit ISA DMA constraints at about 512Kbits. It
+	is worth noting here that many PC machines hang or crash when the
+	chip is driven fast enough to hold the ISA bus solid.
+  </para>
+  <para>
+	Transmit DMA mode uses a single DMA channel. The DMA channel is used
+	for transmission as the transmit FIFO is smaller than the receive
+	FIFO. it gives better performance than pure PIO mode but is nowhere
+	near as ideal as pure DMA mode. 
+  </para>
+  </chapter>
+
+  <chapter>
+ 	<title>Using the Z85230 driver</title>
+  <para>
+	The Z85230 driver provides the back end interface to your board. To
+	configure a Z8530 interface you need to detect the board and to 
+	identify its ports and interrupt resources. It is also your problem
+	to verify the resources are available.
+  </para>
+  <para>
+	Having identified the chip you need to fill in a struct z8530_dev,
+	which describes each chip. This object must exist until you finally
+	shutdown the board. Firstly zero the active field. This ensures 
+	nothing goes off without you intending it. The irq field should
+	be set to the interrupt number of the chip. (Each chip has a single
+	interrupt source rather than each channel). You are responsible
+	for allocating the interrupt line. The interrupt handler should be
+	set to <function>z8530_interrupt</function>. The device id should
+	be set to the z8530_dev structure pointer. Whether the interrupt can
+	be shared or not is board dependent, and up to you to initialise.
+  </para>
+  <para>
+	The structure holds two channel structures. 
+	Initialise chanA.ctrlio and chanA.dataio with the address of the
+	control and data ports. You can or this with Z8530_PORT_SLEEP to
+	indicate your interface needs the 5uS delay for chip settling done
+	in software. The PORT_SLEEP option is architecture specific. Other
+	flags may become available on future platforms, eg for MMIO.
+	Initialise the chanA.irqs to &amp;z8530_nop to start the chip up
+	as disabled and discarding interrupt events. This ensures that
+	stray interrupts will be mopped up and not hang the bus. Set
+	chanA.dev to point to the device structure itself. The
+	private and name field you may use as you wish. The private field
+	is unused by the Z85230 layer. The name is used for error reporting
+	and it may thus make sense to make it match the network name.
+  </para>
+  <para>
+	Repeat the same operation with the B channel if your chip has
+	both channels wired to something useful. This isn't always the
+	case. If it is not wired then the I/O values do not matter, but
+	you must initialise chanB.dev.
+  </para>
+  <para>
+	If your board has DMA facilities then initialise the txdma and
+	rxdma fields for the relevant channels. You must also allocate the
+	ISA DMA channels and do any necessary board level initialisation
+	to configure them. The low level driver will do the Z8530 and
+	DMA controller programming but not board specific magic.
+  </para>
+  <para>
+	Having initialised the device you can then call
+	<function>z8530_init</function>. This will probe the chip and 
+	reset it into a known state. An identification sequence is then
+	run to identify the chip type. If the checks fail to pass the
+	function returns a non zero error code. Typically this indicates
+	that the port given is not valid. After this call the
+	type field of the z8530_dev structure is initialised to either
+	Z8530, Z85C30 or Z85230 according to the chip found.
+  </para>
+  <para>
+	Once you have called z8530_init you can also make use of the utility
+	function <function>z8530_describe</function>. This provides a 
+	consistent reporting format for the Z8530 devices, and allows all
+	the drivers to provide consistent reporting.
+  </para>
+  </chapter>
+
+  <chapter>
+ 	<title>Attaching Network Interfaces</title>
+  <para>
+	If you wish to use the network interface facilities of the driver,
+	then you need to attach a network device to each channel that is
+	present and in use. In addition to use the SyncPPP and Cisco HDLC
+	you need to follow some additional plumbing rules. They may seem 
+	complex but a look at the example hostess_sv11 driver should
+	reassure you.
+  </para>
+  <para>
+	The network device used for each channel should be pointed to by
+	the netdevice field of each channel. The dev-&gt; priv field of the
+	network device points to your private data - you will need to be
+	able to find your ppp device from this. In addition to use the
+	sync ppp layer the private data must start with a void * pointer
+	to the syncppp structures.
+  </para>
+  <para>
+	The way most drivers approach this particular problem is to
+	create a structure holding the Z8530 device definition and
+	put that and the syncppp pointer into the private field of
+	the network device. The network device fields of the channels
+	then point back to the network devices. The ppp_device can also
+	be put in the private structure conveniently.
+  </para>
+  <para>
+	If you wish to use the synchronous ppp then you need to attach
+	the syncppp layer to the network device. You should do this before
+	you register the network device. The
+	<function>sppp_attach</function> requires that the first void *
+	pointer in your private data is pointing to an empty struct
+	ppp_device. The function fills in the initial data for the
+	ppp/hdlc layer.
+  </para>
+  <para>
+	Before you register your network device you will also need to
+	provide suitable handlers for most of the network device callbacks. 
+	See the network device documentation for more details on this.
+  </para>
+  </chapter>
+
+  <chapter>
+ 	<title>Configuring And Activating The Port</title>
+  <para>
+	The Z85230 driver provides helper functions and tables to load the
+	port registers on the Z8530 chips. When programming the register
+	settings for a channel be aware that the documentation recommends
+	initialisation orders. Strange things happen when these are not
+	followed. 
+  </para>
+  <para>
+	<function>z8530_channel_load</function> takes an array of
+	pairs of initialisation values in an array of u8 type. The first
+	value is the Z8530 register number. Add 16 to indicate the alternate
+	register bank on the later chips. The array is terminated by a 255.
+  </para>
+  <para>
+	The driver provides a pair of public tables. The
+	z8530_hdlc_kilostream table is for the UK 'Kilostream' service and
+	also happens to cover most other end host configurations. The
+	z8530_hdlc_kilostream_85230 table is the same configuration using
+	the enhancements of the 85230 chip. The configuration loaded is
+	standard NRZ encoded synchronous data with HDLC bitstuffing. All
+	of the timing is taken from the other end of the link.
+  </para>
+  <para>
+	When writing your own tables be aware that the driver internally
+	tracks register values. It may need to reload values. You should
+	therefore be sure to set registers 1-7, 9-11, 14 and 15 in all
+	configurations. Where the register settings depend on DMA selection
+	the driver will update the bits itself when you open or close.
+	Loading a new table with the interface open is not recommended.
+  </para>
+  <para>
+	There are three standard configurations supported by the core
+	code. In PIO mode the interface is programmed up to use
+	interrupt driven PIO. This places high demands on the host processor
+	to avoid latency. The driver is written to take account of latency
+	issues but it cannot avoid latencies caused by other drivers,
+	notably IDE in PIO mode. Because the drivers allocate buffers you
+	must also prevent MTU changes while the port is open.
+  </para>
+  <para>
+	Once the port is open it will call the rx_function of each channel
+	whenever a completed packet arrived. This is invoked from
+	interrupt context and passes you the channel and a network	
+	buffer (struct sk_buff) holding the data. The data includes
+	the CRC bytes so most users will want to trim the last two
+	bytes before processing the data. This function is very timing
+	critical. When you wish to simply discard data the support
+	code provides the function <function>z8530_null_rx</function>
+	to discard the data.
+  </para>
+  <para>
+	To active PIO mode sending and receiving the <function>
+	z8530_sync_open</function> is called. This expects to be passed
+	the network device and the channel. Typically this is called from
+	your network device open callback. On a failure a non zero error
+	status is returned. The <function>z8530_sync_close</function> 
+	function shuts down a PIO channel. This must be done before the 
+	channel is opened again	and before the driver shuts down 
+	and unloads.
+  </para>
+  <para>
+	The ideal mode of operation is dual channel DMA mode. Here the
+	kernel driver will configure the board for DMA in both directions.
+	The driver also handles ISA DMA issues such as controller
+	programming and the memory range limit for you. This mode is
+	activated by calling the <function>z8530_sync_dma_open</function>
+	function. On failure a non zero error value is returned.
+	Once this mode is activated it can be shut down by calling the
+	<function>z8530_sync_dma_close</function>. You must call the close
+	function matching the open mode you used.
+  </para>
+  <para>
+	The final supported mode uses a single DMA channel to drive the
+	transmit side. As the Z85C30 has a larger FIFO on the receive
+	channel	this tends to increase the maximum speed a little. 
+	This is activated by calling the <function>z8530_sync_txdma_open
+	</function>. This returns a non zero error code on failure. The
+	<function>z8530_sync_txdma_close</function> function closes down
+	the Z8530 interface from this mode.
+  </para>
+  </chapter>
+
+  <chapter>
+ 	<title>Network Layer Functions</title>
+  <para>
+	The Z8530 layer provides functions to queue packets for
+	transmission. The driver internally buffers the frame currently
+	being transmitted and one further frame (in order to keep back
+	to back transmission running). Any further buffering is up to
+	the caller.
+  </para>
+  <para>
+	The function <function>z8530_queue_xmit</function> takes a network
+	buffer in sk_buff format and queues it for transmission. The
+	caller must provide the entire packet with the exception of the
+	bitstuffing and CRC. This is normally done by the caller via
+	the syncppp interface layer. It returns 0 if the buffer has been 
+        queued and non zero values  for queue full. If the function accepts 
+	the buffer it becomes property of the Z8530 layer and the caller 
+	should not free it. 
+  </para>
+  <para>
+	The function <function>z8530_get_stats</function> returns a pointer
+	to an internally maintained per interface statistics block. This
+	provides most of the interface code needed to implement the network
+	layer get_stats callback.
+  </para>
+  </chapter>
+
+  <chapter>
+     <title>Porting The Z8530 Driver</title>
+  <para>
+	The Z8530 driver is written to be portable. In DMA mode it makes
+	assumptions about the use of ISA DMA. These are probably warranted
+	in most cases as the Z85230 in particular was designed to glue to PC
+	type machines. The PIO mode makes no real assumptions.
+  </para>
+  <para>
+	Should you need to retarget the Z8530 driver to another architecture
+	the only code that should need changing are the port I/O functions.
+	At the moment these assume PC I/O port accesses. This may not be
+	appropriate for all platforms. Replacing 
+	<function>z8530_read_port</function> and <function>z8530_write_port
+	</function> is intended to be all that is required to port this
+	driver layer.
+  </para>
+  </chapter>
+
+  <chapter id="bugs">
+     <title>Known Bugs And Assumptions</title>
+  <para>
+  <variablelist>
+    <varlistentry><term>Interrupt Locking</term>
+    <listitem>
+    <para>
+	The locking in the driver is done via the global cli/sti lock. This
+	makes for relatively poor SMP performance. Switching this to use a
+	per device spin lock would probably materially improve performance.
+    </para>
+    </listitem></varlistentry>
+
+    <varlistentry><term>Occasional Failures</term>
+    <listitem>
+    <para>
+	We have reports of occasional failures when run for very long
+	periods of time and the driver starts to receive junk frames. At
+	the moment the cause of this is not clear.
+    </para>
+    </listitem></varlistentry>
+  </variablelist>
+	
+  </para>
+  </chapter>
+
+  <chapter id="pubfunctions">
+     <title>Public Functions Provided</title>
+!Edrivers/net/wan/z85230.c
+  </chapter>
+
+  <chapter id="intfunctions">
+     <title>Internal Functions</title>
+!Idrivers/net/wan/z85230.c
+  </chapter>
+
+</book>

+ 208 - 0
Documentation/IO-mapping.txt

@@ -0,0 +1,208 @@
+[ NOTE: The virt_to_bus() and bus_to_virt() functions have been
+	superseded by the functionality provided by the PCI DMA
+	interface (see Documentation/DMA-mapping.txt).  They continue
+	to be documented below for historical purposes, but new code
+	must not use them. --davidm 00/12/12 ]
+
+[ This is a mail message in response to a query on IO mapping, thus the
+  strange format for a "document" ]
+
+The AHA-1542 is a bus-master device, and your patch makes the driver give the
+controller the physical address of the buffers, which is correct on x86
+(because all bus master devices see the physical memory mappings directly). 
+
+However, on many setups, there are actually _three_ different ways of looking
+at memory addresses, and in this case we actually want the third, the
+so-called "bus address". 
+
+Essentially, the three ways of addressing memory are (this is "real memory",
+that is, normal RAM--see later about other details): 
+
+ - CPU untranslated.  This is the "physical" address.  Physical address 
+   0 is what the CPU sees when it drives zeroes on the memory bus.
+
+ - CPU translated address. This is the "virtual" address, and is 
+   completely internal to the CPU itself with the CPU doing the appropriate
+   translations into "CPU untranslated". 
+
+ - bus address. This is the address of memory as seen by OTHER devices, 
+   not the CPU. Now, in theory there could be many different bus 
+   addresses, with each device seeing memory in some device-specific way, but
+   happily most hardware designers aren't actually actively trying to make
+   things any more complex than necessary, so you can assume that all 
+   external hardware sees the memory the same way. 
+
+Now, on normal PCs the bus address is exactly the same as the physical
+address, and things are very simple indeed. However, they are that simple
+because the memory and the devices share the same address space, and that is
+not generally necessarily true on other PCI/ISA setups. 
+
+Now, just as an example, on the PReP (PowerPC Reference Platform), the 
+CPU sees a memory map something like this (this is from memory):
+
+	0-2 GB		"real memory"
+	2 GB-3 GB	"system IO" (inb/out and similar accesses on x86)
+	3 GB-4 GB 	"IO memory" (shared memory over the IO bus)
+
+Now, that looks simple enough. However, when you look at the same thing from
+the viewpoint of the devices, you have the reverse, and the physical memory
+address 0 actually shows up as address 2 GB for any IO master.
+
+So when the CPU wants any bus master to write to physical memory 0, it 
+has to give the master address 0x80000000 as the memory address.
+
+So, for example, depending on how the kernel is actually mapped on the 
+PPC, you can end up with a setup like this:
+
+ physical address:	0
+ virtual address:	0xC0000000
+ bus address:		0x80000000
+
+where all the addresses actually point to the same thing.  It's just seen 
+through different translations..
+
+Similarly, on the Alpha, the normal translation is
+
+ physical address:	0
+ virtual address:	0xfffffc0000000000
+ bus address:		0x40000000
+
+(but there are also Alphas where the physical address and the bus address
+are the same). 
+
+Anyway, the way to look up all these translations, you do
+
+	#include <asm/io.h>
+
+	phys_addr = virt_to_phys(virt_addr);
+	virt_addr = phys_to_virt(phys_addr);
+	 bus_addr = virt_to_bus(virt_addr);
+	virt_addr = bus_to_virt(bus_addr);
+
+Now, when do you need these?
+
+You want the _virtual_ address when you are actually going to access that 
+pointer from the kernel. So you can have something like this:
+
+	/*
+	 * this is the hardware "mailbox" we use to communicate with
+	 * the controller. The controller sees this directly.
+	 */
+	struct mailbox {
+		__u32 status;
+		__u32 bufstart;
+		__u32 buflen;
+		..
+	} mbox;
+
+		unsigned char * retbuffer;
+
+		/* get the address from the controller */
+		retbuffer = bus_to_virt(mbox.bufstart);
+		switch (retbuffer[0]) {
+			case STATUS_OK:
+				...
+
+on the other hand, you want the bus address when you have a buffer that 
+you want to give to the controller:
+
+	/* ask the controller to read the sense status into "sense_buffer" */
+	mbox.bufstart = virt_to_bus(&sense_buffer);
+	mbox.buflen = sizeof(sense_buffer);
+	mbox.status = 0;
+	notify_controller(&mbox);
+
+And you generally _never_ want to use the physical address, because you can't
+use that from the CPU (the CPU only uses translated virtual addresses), and
+you can't use it from the bus master. 
+
+So why do we care about the physical address at all? We do need the physical
+address in some cases, it's just not very often in normal code.  The physical
+address is needed if you use memory mappings, for example, because the
+"remap_pfn_range()" mm function wants the physical address of the memory to
+be remapped as measured in units of pages, a.k.a. the pfn (the memory
+management layer doesn't know about devices outside the CPU, so it
+shouldn't need to know about "bus addresses" etc).
+
+NOTE NOTE NOTE! The above is only one part of the whole equation. The above
+only talks about "real memory", that is, CPU memory (RAM). 
+
+There is a completely different type of memory too, and that's the "shared
+memory" on the PCI or ISA bus. That's generally not RAM (although in the case
+of a video graphics card it can be normal DRAM that is just used for a frame
+buffer), but can be things like a packet buffer in a network card etc. 
+
+This memory is called "PCI memory" or "shared memory" or "IO memory" or
+whatever, and there is only one way to access it: the readb/writeb and
+related functions. You should never take the address of such memory, because
+there is really nothing you can do with such an address: it's not
+conceptually in the same memory space as "real memory" at all, so you cannot
+just dereference a pointer. (Sadly, on x86 it _is_ in the same memory space,
+so on x86 it actually works to just deference a pointer, but it's not
+portable). 
+
+For such memory, you can do things like
+
+ - reading:
+	/*
+	 * read first 32 bits from ISA memory at 0xC0000, aka
+	 * C000:0000 in DOS terms
+	 */
+	unsigned int signature = isa_readl(0xC0000);
+
+ - remapping and writing:
+	/*
+	 * remap framebuffer PCI memory area at 0xFC000000,
+	 * size 1MB, so that we can access it: We can directly
+	 * access only the 640k-1MB area, so anything else
+	 * has to be remapped.
+	 */
+	char * baseptr = ioremap(0xFC000000, 1024*1024);
+
+	/* write a 'A' to the offset 10 of the area */
+	writeb('A',baseptr+10);
+
+	/* unmap when we unload the driver */
+	iounmap(baseptr);
+
+ - copying and clearing:
+	/* get the 6-byte Ethernet address at ISA address E000:0040 */
+	memcpy_fromio(kernel_buffer, 0xE0040, 6);
+	/* write a packet to the driver */
+	memcpy_toio(0xE1000, skb->data, skb->len);
+	/* clear the frame buffer */
+	memset_io(0xA0000, 0, 0x10000);
+
+OK, that just about covers the basics of accessing IO portably.  Questions?
+Comments? You may think that all the above is overly complex, but one day you
+might find yourself with a 500 MHz Alpha in front of you, and then you'll be
+happy that your driver works ;)
+
+Note that kernel versions 2.0.x (and earlier) mistakenly called the
+ioremap() function "vremap()".  ioremap() is the proper name, but I
+didn't think straight when I wrote it originally.  People who have to
+support both can do something like:
+ 
+	/* support old naming silliness */
+	#if LINUX_VERSION_CODE < 0x020100                                     
+	#define ioremap vremap
+	#define iounmap vfree                                                     
+	#endif
+ 
+at the top of their source files, and then they can use the right names
+even on 2.0.x systems. 
+
+And the above sounds worse than it really is.  Most real drivers really
+don't do all that complex things (or rather: the complexity is not so
+much in the actual IO accesses as in error handling and timeouts etc). 
+It's generally not hard to fix drivers, and in many cases the code
+actually looks better afterwards:
+
+	unsigned long signature = *(unsigned int *) 0xC0000;
+		vs
+	unsigned long signature = readl(0xC0000);
+
+I think the second version actually is more readable, no?
+
+		Linus
+

+ 534 - 0
Documentation/IPMI.txt

@@ -0,0 +1,534 @@
+
+                          The Linux IPMI Driver
+			  ---------------------
+			      Corey Minyard
+			  <minyard@mvista.com>
+			    <minyard@acm.org>
+
+The Intelligent Platform Management Interface, or IPMI, is a
+standard for controlling intelligent devices that monitor a system.
+It provides for dynamic discovery of sensors in the system and the
+ability to monitor the sensors and be informed when the sensor's
+values change or go outside certain boundaries.  It also has a
+standardized database for field-replacable units (FRUs) and a watchdog
+timer.
+
+To use this, you need an interface to an IPMI controller in your
+system (called a Baseboard Management Controller, or BMC) and
+management software that can use the IPMI system.
+
+This document describes how to use the IPMI driver for Linux.  If you
+are not familiar with IPMI itself, see the web site at
+http://www.intel.com/design/servers/ipmi/index.htm.  IPMI is a big
+subject and I can't cover it all here!
+
+Configuration
+-------------
+
+The LinuxIPMI driver is modular, which means you have to pick several
+things to have it work right depending on your hardware.  Most of
+these are available in the 'Character Devices' menu.
+
+No matter what, you must pick 'IPMI top-level message handler' to use
+IPMI.  What you do beyond that depends on your needs and hardware.
+
+The message handler does not provide any user-level interfaces.
+Kernel code (like the watchdog) can still use it.  If you need access
+from userland, you need to select 'Device interface for IPMI' if you
+want access through a device driver.  Another interface is also
+available, you may select 'IPMI sockets' in the 'Networking Support'
+main menu.  This provides a socket interface to IPMI.  You may select
+both of these at the same time, they will both work together.
+
+The driver interface depends on your hardware.  If you have a board
+with a standard interface (These will generally be either "KCS",
+"SMIC", or "BT", consult your hardware manual), choose the 'IPMI SI
+handler' option.  A driver also exists for direct I2C access to the
+IPMI management controller.  Some boards support this, but it is
+unknown if it will work on every board.  For this, choose 'IPMI SMBus
+handler', but be ready to try to do some figuring to see if it will
+work.
+
+There is also a KCS-only driver interface supplied, but it is
+depracated in favor of the SI interface.
+
+You should generally enable ACPI on your system, as systems with IPMI
+should have ACPI tables describing them.
+
+If you have a standard interface and the board manufacturer has done
+their job correctly, the IPMI controller should be automatically
+detect (via ACPI or SMBIOS tables) and should just work.  Sadly, many
+boards do not have this information.  The driver attempts standard
+defaults, but they may not work.  If you fall into this situation, you
+need to read the section below named 'The SI Driver' on how to
+hand-configure your system.
+
+IPMI defines a standard watchdog timer.  You can enable this with the
+'IPMI Watchdog Timer' config option.  If you compile the driver into
+the kernel, then via a kernel command-line option you can have the
+watchdog timer start as soon as it intitializes.  It also have a lot
+of other options, see the 'Watchdog' section below for more details.
+Note that you can also have the watchdog continue to run if it is
+closed (by default it is disabled on close).  Go into the 'Watchdog
+Cards' menu, enable 'Watchdog Timer Support', and enable the option
+'Disable watchdog shutdown on close'.
+
+
+Basic Design
+------------
+
+The Linux IPMI driver is designed to be very modular and flexible, you
+only need to take the pieces you need and you can use it in many
+different ways.  Because of that, it's broken into many chunks of
+code.  These chunks are:
+
+ipmi_msghandler - This is the central piece of software for the IPMI
+system.  It handles all messages, message timing, and responses.  The
+IPMI users tie into this, and the IPMI physical interfaces (called
+System Management Interfaces, or SMIs) also tie in here.  This
+provides the kernelland interface for IPMI, but does not provide an
+interface for use by application processes.
+
+ipmi_devintf - This provides a userland IOCTL interface for the IPMI
+driver, each open file for this device ties in to the message handler
+as an IPMI user.
+
+ipmi_si - A driver for various system interfaces.  This supports
+KCS, SMIC, and may support BT in the future.  Unless you have your own
+custom interface, you probably need to use this.
+
+ipmi_smb - A driver for accessing BMCs on the SMBus. It uses the
+I2C kernel driver's SMBus interfaces to send and receive IPMI messages
+over the SMBus.
+
+af_ipmi - A network socket interface to IPMI.  This doesn't take up
+a character device in your system.
+
+Note that the KCS-only interface ahs been removed.
+
+Much documentation for the interface is in the include files.  The
+IPMI include files are:
+
+net/af_ipmi.h - Contains the socket interface.
+
+linux/ipmi.h - Contains the user interface and IOCTL interface for IPMI.
+
+linux/ipmi_smi.h - Contains the interface for system management interfaces
+(things that interface to IPMI controllers) to use.
+
+linux/ipmi_msgdefs.h - General definitions for base IPMI messaging.
+
+
+Addressing
+----------
+
+The IPMI addressing works much like IP addresses, you have an overlay
+to handle the different address types.  The overlay is:
+
+  struct ipmi_addr
+  {
+	int   addr_type;
+	short channel;
+	char  data[IPMI_MAX_ADDR_SIZE];
+  };
+
+The addr_type determines what the address really is.  The driver
+currently understands two different types of addresses.
+
+"System Interface" addresses are defined as:
+
+  struct ipmi_system_interface_addr
+  {
+	int   addr_type;
+	short channel;
+  };
+
+and the type is IPMI_SYSTEM_INTERFACE_ADDR_TYPE.  This is used for talking
+straight to the BMC on the current card.  The channel must be
+IPMI_BMC_CHANNEL.
+
+Messages that are destined to go out on the IPMB bus use the
+IPMI_IPMB_ADDR_TYPE address type.  The format is
+
+  struct ipmi_ipmb_addr
+  {
+	int           addr_type;
+	short         channel;
+	unsigned char slave_addr;
+	unsigned char lun;
+  };
+
+The "channel" here is generally zero, but some devices support more
+than one channel, it corresponds to the channel as defined in the IPMI
+spec.
+
+
+Messages
+--------
+
+Messages are defined as:
+
+struct ipmi_msg
+{
+	unsigned char netfn;
+	unsigned char lun;
+	unsigned char cmd;
+	unsigned char *data;
+	int           data_len;
+};
+
+The driver takes care of adding/stripping the header information.  The
+data portion is just the data to be send (do NOT put addressing info
+here) or the response.  Note that the completion code of a response is
+the first item in "data", it is not stripped out because that is how
+all the messages are defined in the spec (and thus makes counting the
+offsets a little easier :-).
+
+When using the IOCTL interface from userland, you must provide a block
+of data for "data", fill it, and set data_len to the length of the
+block of data, even when receiving messages.  Otherwise the driver
+will have no place to put the message.
+
+Messages coming up from the message handler in kernelland will come in
+as:
+
+  struct ipmi_recv_msg
+  {
+	struct list_head link;
+
+	/* The type of message as defined in the "Receive Types"
+           defines above. */
+	int         recv_type;
+
+	ipmi_user_t      *user;
+	struct ipmi_addr addr;
+	long             msgid;
+	struct ipmi_msg  msg;
+
+	/* Call this when done with the message.  It will presumably free
+	   the message and do any other necessary cleanup. */
+	void (*done)(struct ipmi_recv_msg *msg);
+
+	/* Place-holder for the data, don't make any assumptions about
+	   the size or existence of this, since it may change. */
+	unsigned char   msg_data[IPMI_MAX_MSG_LENGTH];
+  };
+
+You should look at the receive type and handle the message
+appropriately.
+
+
+The Upper Layer Interface (Message Handler)
+-------------------------------------------
+
+The upper layer of the interface provides the users with a consistent
+view of the IPMI interfaces.  It allows multiple SMI interfaces to be
+addressed (because some boards actually have multiple BMCs on them)
+and the user should not have to care what type of SMI is below them.
+
+
+Creating the User
+
+To user the message handler, you must first create a user using
+ipmi_create_user.  The interface number specifies which SMI you want
+to connect to, and you must supply callback functions to be called
+when data comes in.  The callback function can run at interrupt level,
+so be careful using the callbacks.  This also allows to you pass in a
+piece of data, the handler_data, that will be passed back to you on
+all calls.
+
+Once you are done, call ipmi_destroy_user() to get rid of the user.
+
+From userland, opening the device automatically creates a user, and
+closing the device automatically destroys the user.
+
+
+Messaging
+
+To send a message from kernel-land, the ipmi_request() call does
+pretty much all message handling.  Most of the parameter are
+self-explanatory.  However, it takes a "msgid" parameter.  This is NOT
+the sequence number of messages.  It is simply a long value that is
+passed back when the response for the message is returned.  You may
+use it for anything you like.
+
+Responses come back in the function pointed to by the ipmi_recv_hndl
+field of the "handler" that you passed in to ipmi_create_user().
+Remember again, these may be running at interrupt level.  Remember to
+look at the receive type, too.
+
+From userland, you fill out an ipmi_req_t structure and use the
+IPMICTL_SEND_COMMAND ioctl.  For incoming stuff, you can use select()
+or poll() to wait for messages to come in.  However, you cannot use
+read() to get them, you must call the IPMICTL_RECEIVE_MSG with the
+ipmi_recv_t structure to actually get the message.  Remember that you
+must supply a pointer to a block of data in the msg.data field, and
+you must fill in the msg.data_len field with the size of the data.
+This gives the receiver a place to actually put the message.
+
+If the message cannot fit into the data you provide, you will get an
+EMSGSIZE error and the driver will leave the data in the receive
+queue.  If you want to get it and have it truncate the message, us
+the IPMICTL_RECEIVE_MSG_TRUNC ioctl.
+
+When you send a command (which is defined by the lowest-order bit of
+the netfn per the IPMI spec) on the IPMB bus, the driver will
+automatically assign the sequence number to the command and save the
+command.  If the response is not receive in the IPMI-specified 5
+seconds, it will generate a response automatically saying the command
+timed out.  If an unsolicited response comes in (if it was after 5
+seconds, for instance), that response will be ignored.
+
+In kernelland, after you receive a message and are done with it, you
+MUST call ipmi_free_recv_msg() on it, or you will leak messages.  Note
+that you should NEVER mess with the "done" field of a message, that is
+required to properly clean up the message.
+
+Note that when sending, there is an ipmi_request_supply_msgs() call
+that lets you supply the smi and receive message.  This is useful for
+pieces of code that need to work even if the system is out of buffers
+(the watchdog timer uses this, for instance).  You supply your own
+buffer and own free routines.  This is not recommended for normal use,
+though, since it is tricky to manage your own buffers.
+
+
+Events and Incoming Commands
+
+The driver takes care of polling for IPMI events and receiving
+commands (commands are messages that are not responses, they are
+commands that other things on the IPMB bus have sent you).  To receive
+these, you must register for them, they will not automatically be sent
+to you.
+
+To receive events, you must call ipmi_set_gets_events() and set the
+"val" to non-zero.  Any events that have been received by the driver
+since startup will immediately be delivered to the first user that
+registers for events.  After that, if multiple users are registered
+for events, they will all receive all events that come in.
+
+For receiving commands, you have to individually register commands you
+want to receive.  Call ipmi_register_for_cmd() and supply the netfn
+and command name for each command you want to receive.  Only one user
+may be registered for each netfn/cmd, but different users may register
+for different commands.
+
+From userland, equivalent IOCTLs are provided to do these functions.
+
+
+The Lower Layer (SMI) Interface
+-------------------------------
+
+As mentioned before, multiple SMI interfaces may be registered to the
+message handler, each of these is assigned an interface number when
+they register with the message handler.  They are generally assigned
+in the order they register, although if an SMI unregisters and then
+another one registers, all bets are off.
+
+The ipmi_smi.h defines the interface for management interfaces, see
+that for more details.
+
+
+The SI Driver
+-------------
+
+The SI driver allows up to 4 KCS or SMIC interfaces to be configured
+in the system.  By default, scan the ACPI tables for interfaces, and
+if it doesn't find any the driver will attempt to register one KCS
+interface at the spec-specified I/O port 0xca2 without interrupts.
+You can change this at module load time (for a module) with:
+
+  modprobe ipmi_si.o type=<type1>,<type2>....
+       ports=<port1>,<port2>... addrs=<addr1>,<addr2>...
+       irqs=<irq1>,<irq2>... trydefaults=[0|1]
+       regspacings=<sp1>,<sp2>,... regsizes=<size1>,<size2>,...
+       regshifts=<shift1>,<shift2>,...
+       slave_addrs=<addr1>,<addr2>,...
+
+Each of these except si_trydefaults is a list, the first item for the
+first interface, second item for the second interface, etc.
+
+The si_type may be either "kcs", "smic", or "bt".  If you leave it blank, it
+defaults to "kcs".
+
+If you specify si_addrs as non-zero for an interface, the driver will
+use the memory address given as the address of the device.  This
+overrides si_ports.
+
+If you specify si_ports as non-zero for an interface, the driver will
+use the I/O port given as the device address.
+
+If you specify si_irqs as non-zero for an interface, the driver will
+attempt to use the given interrupt for the device.
+
+si_trydefaults sets whether the standard IPMI interface at 0xca2 and
+any interfaces specified by ACPE are tried.  By default, the driver
+tries it, set this value to zero to turn this off.
+
+The next three parameters have to do with register layout.  The
+registers used by the interfaces may not appear at successive
+locations and they may not be in 8-bit registers.  These parameters
+allow the layout of the data in the registers to be more precisely
+specified.
+
+The regspacings parameter give the number of bytes between successive
+register start addresses.  For instance, if the regspacing is set to 4
+and the start address is 0xca2, then the address for the second
+register would be 0xca6.  This defaults to 1.
+
+The regsizes parameter gives the size of a register, in bytes.  The
+data used by IPMI is 8-bits wide, but it may be inside a larger
+register.  This parameter allows the read and write type to specified.
+It may be 1, 2, 4, or 8.  The default is 1.
+
+Since the register size may be larger than 32 bits, the IPMI data may not
+be in the lower 8 bits.  The regshifts parameter give the amount to shift
+the data to get to the actual IPMI data.
+
+The slave_addrs specifies the IPMI address of the local BMC.  This is
+usually 0x20 and the driver defaults to that, but in case it's not, it
+can be specified when the driver starts up.
+
+When compiled into the kernel, the addresses can be specified on the
+kernel command line as:
+
+  ipmi_si.type=<type1>,<type2>...
+       ipmi_si.ports=<port1>,<port2>... ipmi_si.addrs=<addr1>,<addr2>...
+       ipmi_si.irqs=<irq1>,<irq2>... ipmi_si.trydefaults=[0|1]
+       ipmi_si.regspacings=<sp1>,<sp2>,...
+       ipmi_si.regsizes=<size1>,<size2>,...
+       ipmi_si.regshifts=<shift1>,<shift2>,...
+       ipmi_si.slave_addrs=<addr1>,<addr2>,...
+
+It works the same as the module parameters of the same names.
+
+By default, the driver will attempt to detect any device specified by
+ACPI, and if none of those then a KCS device at the spec-specified
+0xca2.  If you want to turn this off, set the "trydefaults" option to
+false.
+
+If you have high-res timers compiled into the kernel, the driver will
+use them to provide much better performance.  Note that if you do not
+have high-res timers enabled in the kernel and you don't have
+interrupts enabled, the driver will run VERY slowly.  Don't blame me,
+these interfaces suck.
+
+
+The SMBus Driver
+----------------
+
+The SMBus driver allows up to 4 SMBus devices to be configured in the
+system.  By default, the driver will register any SMBus interfaces it finds
+in the I2C address range of 0x20 to 0x4f on any adapter.  You can change this
+at module load time (for a module) with:
+
+  modprobe ipmi_smb.o
+	addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]]
+	dbg=<flags1>,<flags2>...
+	[defaultprobe=0] [dbg_probe=1]
+
+The addresses are specified in pairs, the first is the adapter ID and the
+second is the I2C address on that adapter.
+
+The debug flags are bit flags for each BMC found, they are:
+IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8
+
+Setting smb_defaultprobe to zero disabled the default probing of SMBus
+interfaces at address range 0x20 to 0x4f.  This means that only the
+BMCs specified on the smb_addr line will be detected.
+
+Setting smb_dbg_probe to 1 will enable debugging of the probing and
+detection process for BMCs on the SMBusses.
+
+Discovering the IPMI compilant BMC on the SMBus can cause devices
+on the I2C bus to fail. The SMBus driver writes a "Get Device ID" IPMI
+message as a block write to the I2C bus and waits for a response.
+This action can be detrimental to some I2C devices. It is highly recommended
+that the known I2c address be given to the SMBus driver in the smb_addr
+parameter. The default adrress range will not be used when a smb_addr
+parameter is provided.
+
+When compiled into the kernel, the addresses can be specified on the
+kernel command line as:
+
+  ipmb_smb.addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]]
+	ipmi_smb.dbg=<flags1>,<flags2>...
+	ipmi_smb.defaultprobe=0 ipmi_smb.dbg_probe=1
+
+These are the same options as on the module command line.
+
+Note that you might need some I2C changes if CONFIG_IPMI_PANIC_EVENT
+is enabled along with this, so the I2C driver knows to run to
+completion during sending a panic event.
+
+
+Other Pieces
+------------
+
+Watchdog
+--------
+
+A watchdog timer is provided that implements the Linux-standard
+watchdog timer interface.  It has three module parameters that can be
+used to control it:
+
+  modprobe ipmi_watchdog timeout=<t> pretimeout=<t> action=<action type>
+      preaction=<preaction type> preop=<preop type> start_now=x
+      nowayout=x
+
+The timeout is the number of seconds to the action, and the pretimeout
+is the amount of seconds before the reset that the pre-timeout panic will
+occur (if pretimeout is zero, then pretimeout will not be enabled).  Note
+that the pretimeout is the time before the final timeout.  So if the
+timeout is 50 seconds and the pretimeout is 10 seconds, then the pretimeout
+will occur in 40 second (10 seconds before the timeout).
+
+The action may be "reset", "power_cycle", or "power_off", and
+specifies what to do when the timer times out, and defaults to
+"reset".
+
+The preaction may be "pre_smi" for an indication through the SMI
+interface, "pre_int" for an indication through the SMI with an
+interrupts, and "pre_nmi" for a NMI on a preaction.  This is how
+the driver is informed of the pretimeout.
+
+The preop may be set to "preop_none" for no operation on a pretimeout,
+"preop_panic" to set the preoperation to panic, or "preop_give_data"
+to provide data to read from the watchdog device when the pretimeout
+occurs.  A "pre_nmi" setting CANNOT be used with "preop_give_data"
+because you can't do data operations from an NMI.
+
+When preop is set to "preop_give_data", one byte comes ready to read
+on the device when the pretimeout occurs.  Select and fasync work on
+the device, as well.
+
+If start_now is set to 1, the watchdog timer will start running as
+soon as the driver is loaded.
+
+If nowayout is set to 1, the watchdog timer will not stop when the
+watchdog device is closed.  The default value of nowayout is true
+if the CONFIG_WATCHDOG_NOWAYOUT option is enabled, or false if not.
+
+When compiled into the kernel, the kernel command line is available
+for configuring the watchdog:
+
+  ipmi_watchdog.timeout=<t> ipmi_watchdog.pretimeout=<t>
+	ipmi_watchdog.action=<action type>
+	ipmi_watchdog.preaction=<preaction type>
+	ipmi_watchdog.preop=<preop type>
+	ipmi_watchdog.start_now=x
+	ipmi_watchdog.nowayout=x
+
+The options are the same as the module parameter options.
+
+The watchdog will panic and start a 120 second reset timeout if it
+gets a pre-action.  During a panic or a reboot, the watchdog will
+start a 120 timer if it is running to make sure the reboot occurs.
+
+Note that if you use the NMI preaction for the watchdog, you MUST
+NOT use nmi watchdog mode 1.  If you use the NMI watchdog, you
+must use mode 2.
+
+Once you open the watchdog timer, you must write a 'V' character to the
+device to close it, or the timer will not stop.  This is a new semantic
+for the driver, but makes it consistent with the rest of the watchdog
+drivers in Linux.

+ 37 - 0
Documentation/IRQ-affinity.txt

@@ -0,0 +1,37 @@
+
+SMP IRQ affinity, started by Ingo Molnar <mingo@redhat.com>
+
+
+/proc/irq/IRQ#/smp_affinity specifies which target CPUs are permitted
+for a given IRQ source. It's a bitmask of allowed CPUs. It's not allowed
+to turn off all CPUs, and if an IRQ controller does not support IRQ
+affinity then the value will not change from the default 0xffffffff.
+
+Here is an example of restricting IRQ44 (eth1) to CPU0-3 then restricting
+the IRQ to CPU4-7 (this is an 8-CPU SMP box):
+
+[root@moon 44]# cat smp_affinity
+ffffffff
+[root@moon 44]# echo 0f > smp_affinity
+[root@moon 44]# cat smp_affinity
+0000000f
+[root@moon 44]# ping -f h
+PING hell (195.4.7.3): 56 data bytes
+...
+--- hell ping statistics ---
+6029 packets transmitted, 6027 packets received, 0% packet loss
+round-trip min/avg/max = 0.1/0.1/0.4 ms
+[root@moon 44]# cat /proc/interrupts | grep 44:
+ 44:          0       1785       1785       1783       1783          1
+1          0   IO-APIC-level  eth1
+[root@moon 44]# echo f0 > smp_affinity
+[root@moon 44]# ping -f h
+PING hell (195.4.7.3): 56 data bytes
+..
+--- hell ping statistics ---
+2779 packets transmitted, 2777 packets received, 0% packet loss
+round-trip min/avg/max = 0.1/0.5/585.4 ms
+[root@moon 44]# cat /proc/interrupts | grep 44:
+ 44:       1068       1785       1785       1784       1784       1069       1070       1069   IO-APIC-level  eth1
+[root@moon 44]#
+

+ 503 - 0
Documentation/MSI-HOWTO.txt

@@ -0,0 +1,503 @@
+		The MSI Driver Guide HOWTO
+	Tom L Nguyen tom.l.nguyen@intel.com
+			10/03/2003
+	Revised Feb 12, 2004 by Martine Silbermann
+		email: Martine.Silbermann@hp.com
+	Revised Jun 25, 2004 by Tom L Nguyen
+
+1. About this guide
+
+This guide describes the basics of Message Signaled Interrupts (MSI),
+the advantages of using MSI over traditional interrupt mechanisms,
+and how to enable your driver to use MSI or MSI-X. Also included is
+a Frequently Asked Questions.
+
+2. Copyright 2003 Intel Corporation
+
+3. What is MSI/MSI-X?
+
+Message Signaled Interrupt (MSI), as described in the PCI Local Bus
+Specification Revision 2.3 or latest, is an optional feature, and a
+required feature for PCI Express devices. MSI enables a device function
+to request service by sending an Inbound Memory Write on its PCI bus to
+the FSB as a Message Signal Interrupt transaction. Because MSI is
+generated in the form of a Memory Write, all transaction conditions,
+such as a Retry, Master-Abort, Target-Abort or normal completion, are
+supported.
+
+A PCI device that supports MSI must also support pin IRQ assertion
+interrupt mechanism to provide backward compatibility for systems that
+do not support MSI. In Systems, which support MSI, the bus driver is
+responsible for initializing the message address and message data of
+the device function's MSI/MSI-X capability structure during device
+initial configuration.
+
+An MSI capable device function indicates MSI support by implementing
+the MSI/MSI-X capability structure in its PCI capability list. The
+device function may implement both the MSI capability structure and
+the MSI-X capability structure; however, the bus driver should not
+enable both.
+
+The MSI capability structure contains Message Control register,
+Message Address register and Message Data register. These registers
+provide the bus driver control over MSI. The Message Control register
+indicates the MSI capability supported by the device. The Message
+Address register specifies the target address and the Message Data
+register specifies the characteristics of the message. To request
+service, the device function writes the content of the Message Data
+register to the target address. The device and its software driver
+are prohibited from writing to these registers.
+
+The MSI-X capability structure is an optional extension to MSI. It
+uses an independent and separate capability structure. There are
+some key advantages to implementing the MSI-X capability structure
+over the MSI capability structure as described below.
+
+	- Support a larger maximum number of vectors per function.
+
+	- Provide the ability for system software to configure
+	each vector with an independent message address and message
+	data, specified by a table that resides in Memory Space.
+
+        - MSI and MSI-X both support per-vector masking. Per-vector
+	masking is an optional extension of MSI but a required
+	feature for MSI-X. Per-vector masking provides the kernel
+	the ability to mask/unmask MSI when servicing its software
+	interrupt service routing handler. If per-vector masking is
+	not supported, then the device driver should provide the
+	hardware/software synchronization to ensure that the device
+	generates MSI when the driver wants it to do so.
+
+4. Why use MSI?
+
+As a benefit the simplification of board design, MSI allows board
+designers to remove out of band interrupt routing. MSI is another
+step towards a legacy-free environment.
+
+Due to increasing pressure on chipset and processor packages to
+reduce pin count, the need for interrupt pins is expected to
+diminish over time. Devices, due to pin constraints, may implement
+messages to increase performance.
+
+PCI Express endpoints uses INTx emulation (in-band messages) instead
+of IRQ pin assertion. Using INTx emulation requires interrupt
+sharing among devices connected to the same node (PCI bridge) while
+MSI is unique (non-shared) and does not require BIOS configuration
+support. As a result, the PCI Express technology requires MSI
+support for better interrupt performance.
+
+Using MSI enables the device functions to support two or more
+vectors, which can be configured to target different CPU's to
+increase scalability.
+
+5. Configuring a driver to use MSI/MSI-X
+
+By default, the kernel will not enable MSI/MSI-X on all devices that
+support this capability. The CONFIG_PCI_MSI kernel option
+must be selected to enable MSI/MSI-X support.
+
+5.1 Including MSI/MSI-X support into the kernel
+
+To allow MSI/MSI-X capable device drivers to selectively enable
+MSI/MSI-X (using pci_enable_msi()/pci_enable_msix() as described
+below), the VECTOR based scheme needs to be enabled by setting
+CONFIG_PCI_MSI during kernel config.
+
+Since the target of the inbound message is the local APIC, providing
+CONFIG_X86_LOCAL_APIC must be enabled as well as CONFIG_PCI_MSI.
+
+5.2 Configuring for MSI support
+
+Due to the non-contiguous fashion in vector assignment of the
+existing Linux kernel, this version does not support multiple
+messages regardless of a device function is capable of supporting
+more than one vector. To enable MSI on a device function's MSI
+capability structure requires a device driver to call the function
+pci_enable_msi() explicitly.
+
+5.2.1 API pci_enable_msi
+
+int pci_enable_msi(struct pci_dev *dev)
+
+With this new API, any existing device driver, which like to have
+MSI enabled on its device function, must call this API to enable MSI
+A successful call will initialize the MSI capability structure
+with ONE vector, regardless of whether a device function is
+capable of supporting multiple messages. This vector replaces the
+pre-assigned dev->irq with a new MSI vector. To avoid the conflict
+of new assigned vector with existing pre-assigned vector requires
+a device driver to call this API before calling request_irq().
+
+5.2.2 API pci_disable_msi
+
+void pci_disable_msi(struct pci_dev *dev)
+
+This API should always be used to undo the effect of pci_enable_msi()
+when a device driver is unloading. This API restores dev->irq with
+the pre-assigned IOAPIC vector and switches a device's interrupt
+mode to PCI pin-irq assertion/INTx emulation mode.
+
+Note that a device driver should always call free_irq() on MSI vector
+it has done request_irq() on before calling this API. Failure to do
+so results a BUG_ON() and a device will be left with MSI enabled and
+leaks its vector.
+
+5.2.3 MSI mode vs. legacy mode diagram
+
+The below diagram shows the events, which switches the interrupt
+mode on the MSI-capable device function between MSI mode and
+PIN-IRQ assertion mode.
+
+	 ------------   pci_enable_msi 	 ------------------------
+	|	     | <===============	| 			 |
+	| MSI MODE   |	  	     	| PIN-IRQ ASSERTION MODE |
+	| 	     | ===============>	|			 |
+ 	 ------------	pci_disable_msi  ------------------------
+
+
+Figure 1.0 MSI Mode vs. Legacy Mode
+
+In Figure 1.0, a device operates by default in legacy mode. Legacy
+in this context means PCI pin-irq assertion or PCI-Express INTx
+emulation. A successful MSI request (using pci_enable_msi()) switches
+a device's interrupt mode to MSI mode. A pre-assigned IOAPIC vector
+stored in dev->irq will be saved by the PCI subsystem and a new
+assigned MSI vector will replace dev->irq.
+
+To return back to its default mode, a device driver should always call
+pci_disable_msi() to undo the effect of pci_enable_msi(). Note that a
+device driver should always call free_irq() on MSI vector it has done
+request_irq() on before calling pci_disable_msi(). Failure to do so
+results a BUG_ON() and a device will be left with MSI enabled and
+leaks its vector. Otherwise, the PCI subsystem restores a device's
+dev->irq with a pre-assigned IOAPIC vector and marks released
+MSI vector as unused.
+
+Once being marked as unused, there is no guarantee that the PCI
+subsystem will reserve this MSI vector for a device. Depending on
+the availability of current PCI vector resources and the number of
+MSI/MSI-X requests from other drivers, this MSI may be re-assigned.
+
+For the case where the PCI subsystem re-assigned this MSI vector
+another driver, a request to switching back to MSI mode may result
+in being assigned a different MSI vector or a failure if no more
+vectors are available.
+
+5.3 Configuring for MSI-X support
+
+Due to the ability of the system software to configure each vector of
+the MSI-X capability structure with an independent message address
+and message data, the non-contiguous fashion in vector assignment of
+the existing Linux kernel has no impact on supporting multiple
+messages on an MSI-X capable device functions. To enable MSI-X on
+a device function's MSI-X capability structure requires its device
+driver to call the function pci_enable_msix() explicitly.
+
+The function pci_enable_msix(), once invoked, enables either
+all or nothing, depending on the current availability of PCI vector
+resources. If the PCI vector resources are available for the number
+of vectors requested by a device driver, this function will configure
+the MSI-X table of the MSI-X capability structure of a device with
+requested messages. To emphasize this reason, for example, a device
+may be capable for supporting the maximum of 32 vectors while its
+software driver usually may request 4 vectors. It is recommended
+that the device driver should call this function once during the
+initialization phase of the device driver.
+
+Unlike the function pci_enable_msi(), the function pci_enable_msix()
+does not replace the pre-assigned IOAPIC dev->irq with a new MSI
+vector because the PCI subsystem writes the 1:1 vector-to-entry mapping
+into the field vector of each element contained in a second argument.
+Note that the pre-assigned IO-APIC dev->irq is valid only if the device
+operates in PIN-IRQ assertion mode. In MSI-X mode, any attempt of
+using dev->irq by the device driver to request for interrupt service
+may result unpredictabe behavior.
+
+For each MSI-X vector granted, a device driver is responsible to call
+other functions like request_irq(), enable_irq(), etc. to enable
+this vector with its corresponding interrupt service handler. It is
+a device driver's choice to assign all vectors with the same
+interrupt service handler or each vector with a unique interrupt
+service handler.
+
+5.3.1 Handling MMIO address space of MSI-X Table
+
+The PCI 3.0 specification has implementation notes that MMIO address
+space for a device's MSI-X structure should be isolated so that the
+software system can set different page for controlling accesses to
+the MSI-X structure. The implementation of MSI patch requires the PCI
+subsystem, not a device driver, to maintain full control of the MSI-X
+table/MSI-X PBA and MMIO address space of the MSI-X table/MSI-X PBA.
+A device driver is prohibited from requesting the MMIO address space
+of the MSI-X table/MSI-X PBA. Otherwise, the PCI subsystem will fail
+enabling MSI-X on its hardware device when it calls the function
+pci_enable_msix().
+
+5.3.2 Handling MSI-X allocation
+
+Determining the number of MSI-X vectors allocated to a function is
+dependent on the number of MSI capable devices and MSI-X capable
+devices populated in the system. The policy of allocating MSI-X
+vectors to a function is defined as the following:
+
+#of MSI-X vectors allocated to a function = (x - y)/z where
+
+x = 	The number of available PCI vector resources by the time
+	the device driver calls pci_enable_msix(). The PCI vector
+	resources is the sum of the number of unassigned vectors
+	(new) and the number of released vectors when any MSI/MSI-X
+	device driver switches its hardware device back to a legacy
+	mode or is hot-removed.	The number of unassigned vectors
+	may exclude some vectors reserved, as defined in parameter
+	NR_HP_RESERVED_VECTORS, for the case where the system is
+	capable of supporting hot-add/hot-remove operations. Users
+	may change the value defined in NR_HR_RESERVED_VECTORS to
+	meet their specific needs.
+
+y =	The number of MSI capable devices populated in the system.
+	This policy ensures that each MSI capable device has its
+	vector reserved to avoid the case where some MSI-X capable
+	drivers may attempt to claim all available vector resources.
+
+z =	The number of MSI-X capable devices pupulated in the system.
+	This policy ensures that maximum (x - y) is distributed
+	evenly among MSI-X capable devices.
+
+Note that the PCI subsystem scans y and z during a bus enumeration.
+When the PCI subsystem completes configuring MSI/MSI-X capability
+structure of a device as requested by its device driver, y/z is
+decremented accordingly.
+
+5.3.3 Handling MSI-X shortages
+
+For the case where fewer MSI-X vectors are allocated to a function
+than requested, the function pci_enable_msix() will return the
+maximum number of MSI-X vectors available to the caller. A device
+driver may re-send its request with fewer or equal vectors indicated
+in a return. For example, if a device driver requests 5 vectors, but
+the number of available vectors is 3 vectors, a value of 3 will be a
+return as a result of pci_enable_msix() call. A function could be
+designed for its driver to use only 3 MSI-X table entries as
+different combinations as ABC--, A-B-C, A--CB, etc. Note that this
+patch does not support multiple entries with the same vector. Such
+attempt by a device driver to use 5 MSI-X table entries with 3 vectors
+as ABBCC, AABCC, BCCBA, etc will result as a failure by the function
+pci_enable_msix(). Below are the reasons why supporting multiple
+entries with the same vector is an undesirable solution.
+
+	- The PCI subsystem can not determine which entry, which
+	  generated the message, to mask/unmask MSI while handling
+	  software driver ISR. Attempting to walk through all MSI-X
+	  table entries (2048 max) to mask/unmask any match vector
+	  is an undesirable solution.
+
+	- Walk through all MSI-X table entries (2048 max) to handle
+	  SMP affinity of any match vector is an undesirable solution.
+
+5.3.4 API pci_enable_msix
+
+int pci_enable_msix(struct pci_dev *dev, u32 *entries, int nvec)
+
+This API enables a device driver to request the PCI subsystem
+for enabling MSI-X messages on its hardware device. Depending on
+the availability of PCI vectors resources, the PCI subsystem enables
+either all or nothing.
+
+Argument dev points to the device (pci_dev) structure.
+
+Argument entries is a pointer of unsigned integer type. The number of
+elements is indicated in argument nvec. The content of each element
+will be mapped to the following struct defined in /driver/pci/msi.h.
+
+struct msix_entry {
+	u16 	vector; /* kernel uses to write alloc vector */
+	u16	entry; /* driver uses to specify entry */
+};
+
+A device driver is responsible for initializing the field entry of
+each element with unique entry supported by MSI-X table. Otherwise,
+-EINVAL will be returned as a result. A successful return of zero
+indicates the PCI subsystem completes initializing each of requested
+entries of the MSI-X table with message address and message data.
+Last but not least, the PCI subsystem will write the 1:1
+vector-to-entry mapping into the field vector of each element. A
+device driver is responsible of keeping track of allocated MSI-X
+vectors in its internal data structure.
+
+Argument nvec is an integer indicating the number of messages
+requested.
+
+A return of zero indicates that the number of MSI-X vectors is
+successfully allocated. A return of greater than zero indicates
+MSI-X vector shortage. Or a return of less than zero indicates
+a failure. This failure may be a result of duplicate entries
+specified in second argument, or a result of no available vector,
+or a result of failing to initialize MSI-X table entries.
+
+5.3.5 API pci_disable_msix
+
+void pci_disable_msix(struct pci_dev *dev)
+
+This API should always be used to undo the effect of pci_enable_msix()
+when a device driver is unloading. Note that a device driver should
+always call free_irq() on all MSI-X vectors it has done request_irq()
+on before calling this API. Failure to do so results a BUG_ON() and
+a device will be left with MSI-X enabled and leaks its vectors.
+
+5.3.6 MSI-X mode vs. legacy mode diagram
+
+The below diagram shows the events, which switches the interrupt
+mode on the MSI-X capable device function between MSI-X mode and
+PIN-IRQ assertion mode (legacy).
+
+	 ------------   pci_enable_msix(,,n) ------------------------
+	|	     | <===============	    | 			     |
+	| MSI-X MODE |	  	     	    | PIN-IRQ ASSERTION MODE |
+	| 	     | ===============>	    |			     |
+ 	 ------------	pci_disable_msix     ------------------------
+
+Figure 2.0 MSI-X Mode vs. Legacy Mode
+
+In Figure 2.0, a device operates by default in legacy mode. A
+successful MSI-X request (using pci_enable_msix()) switches a
+device's interrupt mode to MSI-X mode. A pre-assigned IOAPIC vector
+stored in dev->irq will be saved by the PCI subsystem; however,
+unlike MSI mode, the PCI subsystem will not replace dev->irq with
+assigned MSI-X vector because the PCI subsystem already writes the 1:1
+vector-to-entry mapping into the field vector of each element
+specified in second argument.
+
+To return back to its default mode, a device driver should always call
+pci_disable_msix() to undo the effect of pci_enable_msix(). Note that
+a device driver should always call free_irq() on all MSI-X vectors it
+has done request_irq() on before calling pci_disable_msix(). Failure
+to do so results a BUG_ON() and a device will be left with MSI-X
+enabled and leaks its vectors. Otherwise, the PCI subsystem switches a
+device function's interrupt mode from MSI-X mode to legacy mode and
+marks all allocated MSI-X vectors as unused.
+
+Once being marked as unused, there is no guarantee that the PCI
+subsystem will reserve these MSI-X vectors for a device. Depending on
+the availability of current PCI vector resources and the number of
+MSI/MSI-X requests from other drivers, these MSI-X vectors may be
+re-assigned.
+
+For the case where the PCI subsystem re-assigned these MSI-X vectors
+to other driver, a request to switching back to MSI-X mode may result
+being assigned with another set of MSI-X vectors or a failure if no
+more vectors are available.
+
+5.4 Handling function implementng both MSI and MSI-X capabilities
+
+For the case where a function implements both MSI and MSI-X
+capabilities, the PCI subsystem enables a device to run either in MSI
+mode or MSI-X mode but not both. A device driver determines whether it
+wants MSI or MSI-X enabled on its hardware device. Once a device
+driver requests for MSI, for example, it is prohibited to request for
+MSI-X; in other words, a device driver is not permitted to ping-pong
+between MSI mod MSI-X mode during a run-time.
+
+5.5 Hardware requirements for MSI/MSI-X support
+MSI/MSI-X support requires support from both system hardware and
+individual hardware device functions.
+
+5.5.1 System hardware support
+Since the target of MSI address is the local APIC CPU, enabling
+MSI/MSI-X support in Linux kernel is dependent on whether existing
+system hardware supports local APIC. Users should verify their
+system whether it runs when CONFIG_X86_LOCAL_APIC=y.
+
+In SMP environment, CONFIG_X86_LOCAL_APIC is automatically set;
+however, in UP environment, users must manually set
+CONFIG_X86_LOCAL_APIC. Once CONFIG_X86_LOCAL_APIC=y, setting
+CONFIG_PCI_MSI enables the VECTOR based scheme and
+the option for MSI-capable device drivers to selectively enable
+MSI/MSI-X.
+
+Note that CONFIG_X86_IO_APIC setting is irrelevant because MSI/MSI-X
+vector is allocated new during runtime and MSI/MSI-X support does not
+depend on BIOS support. This key independency enables MSI/MSI-X
+support on future IOxAPIC free platform.
+
+5.5.2 Device hardware support
+The hardware device function supports MSI by indicating the
+MSI/MSI-X capability structure on its PCI capability list. By
+default, this capability structure will not be initialized by
+the kernel to enable MSI during the system boot. In other words,
+the device function is running on its default pin assertion mode.
+Note that in many cases the hardware supporting MSI have bugs,
+which may result in system hang. The software driver of specific
+MSI-capable hardware is responsible for whether calling
+pci_enable_msi or not. A return of zero indicates the kernel
+successfully initializes the MSI/MSI-X capability structure of the
+device funtion. The device function is now running on MSI/MSI-X mode.
+
+5.6 How to tell whether MSI/MSI-X is enabled on device function
+
+At the driver level, a return of zero from the function call of
+pci_enable_msi()/pci_enable_msix() indicates to a device driver that
+its device function is initialized successfully and ready to run in
+MSI/MSI-X mode.
+
+At the user level, users can use command 'cat /proc/interrupts'
+to display the vector allocated for a device and its interrupt
+MSI/MSI-X mode ("PCI MSI"/"PCI MSIX"). Below shows below MSI mode is
+enabled on a SCSI Adaptec 39320D Ultra320.
+
+           CPU0       CPU1
+  0:     324639          0    IO-APIC-edge  timer
+  1:       1186          0    IO-APIC-edge  i8042
+  2:          0          0          XT-PIC  cascade
+ 12:       2797          0    IO-APIC-edge  i8042
+ 14:       6543          0    IO-APIC-edge  ide0
+ 15:          1          0    IO-APIC-edge  ide1
+169:          0          0   IO-APIC-level  uhci-hcd
+185:          0          0   IO-APIC-level  uhci-hcd
+193:        138         10         PCI MSI  aic79xx
+201:         30          0         PCI MSI  aic79xx
+225:         30          0   IO-APIC-level  aic7xxx
+233:         30          0   IO-APIC-level  aic7xxx
+NMI:          0          0
+LOC:     324553     325068
+ERR:          0
+MIS:          0
+
+6. FAQ
+
+Q1. Are there any limitations on using the MSI?
+
+A1. If the PCI device supports MSI and conforms to the
+specification and the platform supports the APIC local bus,
+then using MSI should work.
+
+Q2. Will it work on all the Pentium processors (P3, P4, Xeon,
+AMD processors)? In P3 IPI's are transmitted on the APIC local
+bus and in P4 and Xeon they are transmitted on the system
+bus. Are there any implications with this?
+
+A2. MSI support enables a PCI device sending an inbound
+memory write (0xfeexxxxx as target address) on its PCI bus
+directly to the FSB. Since the message address has a
+redirection hint bit cleared, it should work.
+
+Q3. The target address 0xfeexxxxx will be translated by the
+Host Bridge into an interrupt message. Are there any
+limitations on the chipsets such as Intel 8xx, Intel e7xxx,
+or VIA?
+
+A3. If these chipsets support an inbound memory write with
+target address set as 0xfeexxxxx, as conformed to PCI
+specification 2.3 or latest, then it should work.
+
+Q4. From the driver point of view, if the MSI is lost because
+of the errors occur during inbound memory write, then it may
+wait for ever. Is there a mechanism for it to recover?
+
+A4. Since the target of the transaction is an inbound memory
+write, all transaction termination conditions (Retry,
+Master-Abort, Target-Abort, or normal completion) are
+supported. A device sending an MSI must abide by all the PCI
+rules and conditions regarding that inbound memory write. So,
+if a retry is signaled it must retry, etc... We believe that
+the recommendation for Abort is also a retry (refer to PCI
+specification 2.3 or latest).

+ 276 - 0
Documentation/ManagementStyle

@@ -0,0 +1,276 @@
+
+                Linux kernel management style
+
+This is a short document describing the preferred (or made up, depending
+on who you ask) management style for the linux kernel.  It's meant to
+mirror the CodingStyle document to some degree, and mainly written to
+avoid answering (*) the same (or similar) questions over and over again. 
+
+Management style is very personal and much harder to quantify than
+simple coding style rules, so this document may or may not have anything
+to do with reality.  It started as a lark, but that doesn't mean that it
+might not actually be true. You'll have to decide for yourself.
+
+Btw, when talking about "kernel manager", it's all about the technical
+lead persons, not the people who do traditional management inside
+companies.  If you sign purchase orders or you have any clue about the
+budget of your group, you're almost certainly not a kernel manager. 
+These suggestions may or may not apply to you. 
+
+First off, I'd suggest buying "Seven Habits of Highly Successful
+People", and NOT read it.  Burn it, it's a great symbolic gesture. 
+
+(*) This document does so not so much by answering the question, but by
+making it painfully obvious to the questioner that we don't have a clue
+to what the answer is. 
+
+Anyway, here goes:
+
+
+		Chapter 1: Decisions
+
+Everybody thinks managers make decisions, and that decision-making is
+important.  The bigger and more painful the decision, the bigger the
+manager must be to make it.  That's very deep and obvious, but it's not
+actually true. 
+
+The name of the game is to _avoid_ having to make a decision.  In
+particular, if somebody tells you "choose (a) or (b), we really need you
+to decide on this", you're in trouble as a manager.  The people you
+manage had better know the details better than you, so if they come to
+you for a technical decision, you're screwed.  You're clearly not
+competent to make that decision for them. 
+
+(Corollary:if the people you manage don't know the details better than
+you, you're also screwed, although for a totally different reason. 
+Namely that you are in the wrong job, and that _they_ should be managing
+your brilliance instead). 
+
+So the name of the game is to _avoid_ decisions, at least the big and
+painful ones.  Making small and non-consequential decisions is fine, and
+makes you look like you know what you're doing, so what a kernel manager
+needs to do is to turn the big and painful ones into small things where
+nobody really cares. 
+
+It helps to realize that the key difference between a big decision and a
+small one is whether you can fix your decision afterwards.  Any decision
+can be made small by just always making sure that if you were wrong (and
+you _will_ be wrong), you can always undo the damage later by
+backtracking.  Suddenly, you get to be doubly managerial for making
+_two_ inconsequential decisions - the wrong one _and_ the right one. 
+
+And people will even see that as true leadership (*cough* bullshit
+*cough*).
+
+Thus the key to avoiding big decisions becomes to just avoiding to do
+things that can't be undone.  Don't get ushered into a corner from which
+you cannot escape.  A cornered rat may be dangerous - a cornered manager
+is just pitiful. 
+
+It turns out that since nobody would be stupid enough to ever really let
+a kernel manager have huge fiscal responsibility _anyway_, it's usually
+fairly easy to backtrack.  Since you're not going to be able to waste
+huge amounts of money that you might not be able to repay, the only
+thing you can backtrack on is a technical decision, and there
+back-tracking is very easy: just tell everybody that you were an
+incompetent nincompoop, say you're sorry, and undo all the worthless
+work you had people work on for the last year.  Suddenly the decision
+you made a year ago wasn't a big decision after all, since it could be
+easily undone. 
+
+It turns out that some people have trouble with this approach, for two
+reasons:
+ - admitting you were an idiot is harder than it looks.  We all like to
+   maintain appearances, and coming out in public to say that you were
+   wrong is sometimes very hard indeed. 
+ - having somebody tell you that what you worked on for the last year
+   wasn't worthwhile after all can be hard on the poor lowly engineers
+   too, and while the actual _work_ was easy enough to undo by just
+   deleting it, you may have irrevocably lost the trust of that
+   engineer.  And remember: "irrevocable" was what we tried to avoid in
+   the first place, and your decision ended up being a big one after
+   all. 
+
+Happily, both of these reasons can be mitigated effectively by just
+admitting up-front that you don't have a friggin' clue, and telling
+people ahead of the fact that your decision is purely preliminary, and
+might be the wrong thing.  You should always reserve the right to change
+your mind, and make people very _aware_ of that.  And it's much easier
+to admit that you are stupid when you haven't _yet_ done the really
+stupid thing.
+
+Then, when it really does turn out to be stupid, people just roll their
+eyes and say "Oops, he did it again".  
+
+This preemptive admission of incompetence might also make the people who
+actually do the work also think twice about whether it's worth doing or
+not.  After all, if _they_ aren't certain whether it's a good idea, you
+sure as hell shouldn't encourage them by promising them that what they
+work on will be included.  Make them at least think twice before they
+embark on a big endeavor. 
+
+Remember: they'd better know more about the details than you do, and
+they usually already think they have the answer to everything.  The best
+thing you can do as a manager is not to instill confidence, but rather a
+healthy dose of critical thinking on what they do. 
+
+Btw, another way to avoid a decision is to plaintively just whine "can't
+we just do both?" and look pitiful.  Trust me, it works.  If it's not
+clear which approach is better, they'll eventually figure it out.  The
+answer may end up being that both teams get so frustrated by the
+situation that they just give up. 
+
+That may sound like a failure, but it's usually a sign that there was
+something wrong with both projects, and the reason the people involved
+couldn't decide was that they were both wrong.  You end up coming up
+smelling like roses, and you avoided yet another decision that you could
+have screwed up on. 
+
+
+		Chapter 2: People
+
+Most people are idiots, and being a manager means you'll have to deal
+with it, and perhaps more importantly, that _they_ have to deal with
+_you_. 
+
+It turns out that while it's easy to undo technical mistakes, it's not
+as easy to undo personality disorders.  You just have to live with
+theirs - and yours. 
+
+However, in order to prepare yourself as a kernel manager, it's best to
+remember not to burn any bridges, bomb any innocent villagers, or
+alienate too many kernel developers. It turns out that alienating people
+is fairly easy, and un-alienating them is hard. Thus "alienating"
+immediately falls under the heading of "not reversible", and becomes a
+no-no according to Chapter 1.
+
+There's just a few simple rules here:
+ (1) don't call people d*ckheads (at least not in public)
+ (2) learn how to apologize when you forgot rule (1)
+
+The problem with #1 is that it's very easy to do, since you can say
+"you're a d*ckhead" in millions of different ways (*), sometimes without
+even realizing it, and almost always with a white-hot conviction that
+you are right. 
+
+And the more convinced you are that you are right (and let's face it,
+you can call just about _anybody_ a d*ckhead, and you often _will_ be
+right), the harder it ends up being to apologize afterwards. 
+
+To solve this problem, you really only have two options:
+ - get really good at apologies
+ - spread the "love" out so evenly that nobody really ends up feeling
+   like they get unfairly targeted.  Make it inventive enough, and they
+   might even be amused. 
+
+The option of being unfailingly polite really doesn't exist. Nobody will
+trust somebody who is so clearly hiding his true character.
+
+(*) Paul Simon sang "Fifty Ways to Lose Your Lover", because quite
+frankly, "A Million Ways to Tell a Developer He Is a D*ckhead" doesn't
+scan nearly as well.  But I'm sure he thought about it. 
+
+
+		Chapter 3: People II - the Good Kind
+
+While it turns out that most people are idiots, the corollary to that is
+sadly that you are one too, and that while we can all bask in the secure
+knowledge that we're better than the average person (let's face it,
+nobody ever believes that they're average or below-average), we should
+also admit that we're not the sharpest knife around, and there will be
+other people that are less of an idiot that you are. 
+
+Some people react badly to smart people.  Others take advantage of them. 
+
+Make sure that you, as a kernel maintainer, are in the second group. 
+Suck up to them, because they are the people who will make your job
+easier. In particular, they'll be able to make your decisions for you,
+which is what the game is all about.
+
+So when you find somebody smarter than you are, just coast along.  Your
+management responsibilities largely become ones of saying "Sounds like a
+good idea - go wild", or "That sounds good, but what about xxx?".  The
+second version in particular is a great way to either learn something
+new about "xxx" or seem _extra_ managerial by pointing out something the
+smarter person hadn't thought about.  In either case, you win.
+
+One thing to look out for is to realize that greatness in one area does
+not necessarily translate to other areas.  So you might prod people in
+specific directions, but let's face it, they might be good at what they
+do, and suck at everything else.  The good news is that people tend to
+naturally gravitate back to what they are good at, so it's not like you
+are doing something irreversible when you _do_ prod them in some
+direction, just don't push too hard.
+
+
+		Chapter 4: Placing blame
+
+Things will go wrong, and people want somebody to blame. Tag, you're it.
+
+It's not actually that hard to accept the blame, especially if people
+kind of realize that it wasn't _all_ your fault.  Which brings us to the
+best way of taking the blame: do it for another guy. You'll feel good
+for taking the fall, he'll feel good about not getting blamed, and the
+guy who lost his whole 36GB porn-collection because of your incompetence
+will grudgingly admit that you at least didn't try to weasel out of it.
+
+Then make the developer who really screwed up (if you can find him) know
+_in_private_ that he screwed up.  Not just so he can avoid it in the
+future, but so that he knows he owes you one.  And, perhaps even more
+importantly, he's also likely the person who can fix it.  Because, let's
+face it, it sure ain't you. 
+
+Taking the blame is also why you get to be manager in the first place. 
+It's part of what makes people trust you, and allow you the potential
+glory, because you're the one who gets to say "I screwed up".  And if
+you've followed the previous rules, you'll be pretty good at saying that
+by now. 
+
+
+		Chapter 5: Things to avoid
+
+There's one thing people hate even more than being called "d*ckhead",
+and that is being called a "d*ckhead" in a sanctimonious voice.  The
+first you can apologize for, the second one you won't really get the
+chance.  They likely will no longer be listening even if you otherwise
+do a good job. 
+
+We all think we're better than anybody else, which means that when
+somebody else puts on airs, it _really_ rubs us the wrong way.  You may
+be morally and intellectually superior to everybody around you, but
+don't try to make it too obvious unless you really _intend_ to irritate
+somebody (*). 
+
+Similarly, don't be too polite or subtle about things. Politeness easily
+ends up going overboard and hiding the problem, and as they say, "On the
+internet, nobody can hear you being subtle". Use a big blunt object to
+hammer the point in, because you can't really depend on people getting
+your point otherwise.
+
+Some humor can help pad both the bluntness and the moralizing.  Going
+overboard to the point of being ridiculous can drive a point home
+without making it painful to the recipient, who just thinks you're being
+silly.  It can thus help get through the personal mental block we all
+have about criticism. 
+
+(*) Hint: internet newsgroups that are not directly related to your work
+are great ways to take out your frustrations at other people. Write
+insulting posts with a sneer just to get into a good flame every once in
+a while, and you'll feel cleansed. Just don't crap too close to home.
+
+
+		Chapter 6: Why me?
+
+Since your main responsibility seems to be to take the blame for other
+peoples mistakes, and make it painfully obvious to everybody else that
+you're incompetent, the obvious question becomes one of why do it in the
+first place?
+
+First off, while you may or may not get screaming teenage girls (or
+boys, let's not be judgmental or sexist here) knocking on your dressing
+room door, you _will_ get an immense feeling of personal accomplishment
+for being "in charge".  Never mind the fact that you're really leading
+by trying to keep up with everybody else and running after them as fast
+as you can.  Everybody will still think you're the person in charge. 
+
+It's a great job if you can hack it.

+ 217 - 0
Documentation/PCIEBUS-HOWTO.txt

@@ -0,0 +1,217 @@
+		The PCI Express Port Bus Driver Guide HOWTO
+	Tom L Nguyen tom.l.nguyen@intel.com
+			11/03/2004
+
+1. About this guide
+
+This guide describes the basics of the PCI Express Port Bus driver
+and provides information on how to enable the service drivers to
+register/unregister with the PCI Express Port Bus Driver.
+
+2. Copyright 2004 Intel Corporation
+
+3. What is the PCI Express Port Bus Driver
+
+A PCI Express Port is a logical PCI-PCI Bridge structure. There
+are two types of PCI Express Port: the Root Port and the Switch
+Port. The Root Port originates a PCI Express link from a PCI Express
+Root Complex and the Switch Port connects PCI Express links to
+internal logical PCI buses. The Switch Port, which has its secondary
+bus representing the switch's internal routing logic, is called the
+switch's Upstream Port. The switch's Downstream Port is bridging from
+switch's internal routing bus to a bus representing the downstream
+PCI Express link from the PCI Express Switch.
+
+A PCI Express Port can provide up to four distinct functions,
+referred to in this document as services, depending on its port type.
+PCI Express Port's services include native hotplug support (HP),
+power management event support (PME), advanced error reporting
+support (AER), and virtual channel support (VC). These services may
+be handled by a single complex driver or be individually distributed
+and handled by corresponding service drivers.
+
+4. Why use the PCI Express Port Bus Driver?
+
+In existing Linux kernels, the Linux Device Driver Model allows a
+physical device to be handled by only a single driver. The PCI
+Express Port is a PCI-PCI Bridge device with multiple distinct
+services. To maintain a clean and simple solution each service
+may have its own software service driver. In this case several
+service drivers will compete for a single PCI-PCI Bridge device.
+For example, if the PCI Express Root Port native hotplug service
+driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
+kernel therefore does not load other service drivers for that Root
+Port. In other words, it is impossible to have multiple service
+drivers load and run on a PCI-PCI Bridge device simultaneously
+using the current driver model.
+
+To enable multiple service drivers running simultaneously requires
+having a PCI Express Port Bus driver, which manages all populated
+PCI Express Ports and distributes all provided service requests
+to the corresponding service drivers as required. Some key
+advantages of using the PCI Express Port Bus driver are listed below:
+
+	- Allow multiple service drivers to run simultaneously on
+	  a PCI-PCI Bridge Port device.
+
+	- Allow service drivers implemented in an independent
+	  staged approach.
+	
+	- Allow one service driver to run on multiple PCI-PCI Bridge
+	  Port devices. 
+
+	- Manage and distribute resources of a PCI-PCI Bridge Port
+	  device to requested service drivers.
+
+5. Configuring the PCI Express Port Bus Driver vs. Service Drivers
+
+5.1 Including the PCI Express Port Bus Driver Support into the Kernel
+
+Including the PCI Express Port Bus driver depends on whether the PCI
+Express support is included in the kernel config. The kernel will
+automatically include the PCI Express Port Bus driver as a kernel
+driver when the PCI Express support is enabled in the kernel.
+
+5.2 Enabling Service Driver Support
+
+PCI device drivers are implemented based on Linux Device Driver Model.
+All service drivers are PCI device drivers. As discussed above, it is
+impossible to load any service driver once the kernel has loaded the
+PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
+Model requires some minimal changes on existing service drivers that
+imposes no impact on the functionality of existing service drivers.
+
+A service driver is required to use the two APIs shown below to
+register its service with the PCI Express Port Bus driver (see 
+section 5.2.1 & 5.2.2). It is important that a service driver
+initializes the pcie_port_service_driver data structure, included in
+header file /include/linux/pcieport_if.h, before calling these APIs.
+Failure to do so will result an identity mismatch, which prevents
+the PCI Express Port Bus driver from loading a service driver.
+
+5.2.1 pcie_port_service_register
+
+int pcie_port_service_register(struct pcie_port_service_driver *new)
+
+This API replaces the Linux Driver Model's pci_module_init API. A
+service driver should always calls pcie_port_service_register at
+module init. Note that after service driver being loaded, calls
+such as pci_enable_device(dev) and pci_set_master(dev) are no longer
+necessary since these calls are executed by the PCI Port Bus driver.
+
+5.2.2 pcie_port_service_unregister
+
+void pcie_port_service_unregister(struct pcie_port_service_driver *new)
+
+pcie_port_service_unregister replaces the Linux Driver Model's
+pci_unregister_driver. It's always called by service driver when a
+module exits.
+
+5.2.3 Sample Code
+
+Below is sample service driver code to initialize the port service
+driver data structure.
+
+static struct pcie_port_service_id service_id[] = { {
+	.vendor = PCI_ANY_ID,
+	.device = PCI_ANY_ID,
+	.port_type = PCIE_RC_PORT,
+	.service_type = PCIE_PORT_SERVICE_AER,
+	}, { /* end: all zeroes */ }
+};
+
+static struct pcie_port_service_driver root_aerdrv = {
+	.name		= (char *)device_name,
+	.id_table	= &service_id[0],
+
+	.probe		= aerdrv_load,
+	.remove		= aerdrv_unload,
+
+	.suspend	= aerdrv_suspend,
+	.resume		= aerdrv_resume,
+};
+
+Below is a sample code for registering/unregistering a service
+driver.
+
+static int __init aerdrv_service_init(void)
+{
+	int retval = 0;
+	
+	retval = pcie_port_service_register(&root_aerdrv);
+	if (!retval) {
+		/*
+		 * FIX ME
+		 */
+	}
+	return retval;
+}
+
+static void __exit aerdrv_service_exit(void) 
+{
+	pcie_port_service_unregister(&root_aerdrv);
+}
+
+module_init(aerdrv_service_init);
+module_exit(aerdrv_service_exit);
+
+6. Possible Resource Conflicts
+
+Since all service drivers of a PCI-PCI Bridge Port device are
+allowed to run simultaneously, below lists a few of possible resource
+conflicts with proposed solutions.
+
+6.1 MSI Vector Resource
+
+The MSI capability structure enables a device software driver to call
+pci_enable_msi to request MSI based interrupts. Once MSI interrupts
+are enabled on a device, it stays in this mode until a device driver
+calls pci_disable_msi to disable MSI interrupts and revert back to
+INTx emulation mode. Since service drivers of the same PCI-PCI Bridge
+port share the same physical device, if an individual service driver
+calls pci_enable_msi/pci_disable_msi it may result unpredictable
+behavior. For example, two service drivers run simultaneously on the
+same physical Root Port. Both service drivers call pci_enable_msi to
+request MSI based interrupts. A service driver may not know whether
+any other service drivers have run on this Root Port. If either one
+of them calls pci_disable_msi, it puts the other service driver
+in a wrong interrupt mode. 
+
+To avoid this situation all service drivers are not permitted to
+switch interrupt mode on its device. The PCI Express Port Bus driver
+is responsible for determining the interrupt mode and this should be
+transparent to service drivers. Service drivers need to know only
+the vector IRQ assigned to the field irq of struct pcie_device, which
+is passed in when the PCI Express Port Bus driver probes each service
+driver. Service drivers should use (struct pcie_device*)dev->irq to
+call request_irq/free_irq. In addition, the interrupt mode is stored
+in the field interrupt_mode of struct pcie_device.
+
+6.2 MSI-X Vector Resources
+
+Similar to the MSI a device driver for an MSI-X capable device can
+call pci_enable_msix to request MSI-X interrupts. All service drivers
+are not permitted to switch interrupt mode on its device. The PCI
+Express Port Bus driver is responsible for determining the interrupt
+mode and this should be transparent to service drivers. Any attempt
+by service driver to call pci_enable_msix/pci_disable_msix may
+result unpredictable behavior. Service drivers should use
+(struct pcie_device*)dev->irq and call request_irq/free_irq.
+
+6.3 PCI Memory/IO Mapped Regions
+
+Service drivers for PCI Express Power Management (PME), Advanced
+Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
+PCI configuration space on the PCI Express port. In all cases the
+registers accessed are independent of each other. This patch assumes
+that all service drivers will be well behaved and not overwrite
+other service driver's configuration settings.
+
+6.4 PCI Config Registers
+
+Each service driver runs its PCI config operations on its own
+capability structure except the PCI Express capability structure, in
+which Root Control register and Device Control register are shared
+between PME and AER. This patch assumes that all service drivers
+will be well behaved and not overwrite other service driver's
+configuration settings.

+ 387 - 0
Documentation/RCU/RTFP.txt

@@ -0,0 +1,387 @@
+Read the F-ing Papers!
+
+
+This document describes RCU-related publications, and is followed by
+the corresponding bibtex entries.
+
+The first thing resembling RCU was published in 1980, when Kung and Lehman
+[Kung80] recommended use of a garbage collector to defer destruction
+of nodes in a parallel binary search tree in order to simplify its
+implementation.  This works well in environments that have garbage
+collectors, but current production garbage collectors incur significant
+read-side overhead.
+
+In 1982, Manber and Ladner [Manber82,Manber84] recommended deferring
+destruction until all threads running at that time have terminated, again
+for a parallel binary search tree.  This approach works well in systems
+with short-lived threads, such as the K42 research operating system.
+However, Linux has long-lived tasks, so more is needed.
+
+In 1986, Hennessy, Osisek, and Seigh [Hennessy89] introduced passive
+serialization, which is an RCU-like mechanism that relies on the presence
+of "quiescent states" in the VM/XA hypervisor that are guaranteed not
+to be referencing the data structure.  However, this mechanism was not
+optimized for modern computer systems, which is not surprising given
+that these overheads were not so expensive in the mid-80s.  Nonetheless,
+passive serialization appears to be the first deferred-destruction
+mechanism to be used in production.  Furthermore, the relevant patent has
+lapsed, so this approach may be used in non-GPL software, if desired.
+(In contrast, use of RCU is permitted only in software licensed under
+GPL.  Sorry!!!)
+
+In 1990, Pugh [Pugh90] noted that explicitly tracking which threads
+were reading a given data structure permitted deferred free to operate
+in the presence of non-terminating threads.  However, this explicit
+tracking imposes significant read-side overhead, which is undesirable
+in read-mostly situations.  This algorithm does take pains to avoid
+write-side contention and parallelize the other write-side overheads by
+providing a fine-grained locking design, however, it would be interesting
+to see how much of the performance advantage reported in 1990 remains
+in 2004.
+
+At about this same time, Adams [Adams91] described ``chaotic relaxation'',
+where the normal barriers between successive iterations of convergent
+numerical algorithms are relaxed, so that iteration $n$ might use
+data from iteration $n-1$ or even $n-2$.  This introduces error,
+which typically slows convergence and thus increases the number of
+iterations required.  However, this increase is sometimes more than made
+up for by a reduction in the number of expensive barrier operations,
+which are otherwise required to synchronize the threads at the end
+of each iteration.  Unfortunately, chaotic relaxation requires highly
+structured data, such as the matrices used in scientific programs, and
+is thus inapplicable to most data structures in operating-system kernels.
+
+In 1993, Jacobson [Jacobson93] verbally described what is perhaps the
+simplest deferred-free technique: simply waiting a fixed amount of time
+before freeing blocks awaiting deferred free.  Jacobson did not describe
+any write-side changes he might have made in this work using SGI's Irix
+kernel.  Aju John published a similar technique in 1995 [AjuJohn95].
+This works well if there is a well-defined upper bound on the length of
+time that reading threads can hold references, as there might well be in
+hard real-time systems.  However, if this time is exceeded, perhaps due
+to preemption, excessive interrupts, or larger-than-anticipated load,
+memory corruption can ensue, with no reasonable means of diagnosis.
+Jacobson's technique is therefore inappropriate for use in production
+operating-system kernels, except when such kernels can provide hard
+real-time response guarantees for all operations.
+
+Also in 1995, Pu et al. [Pu95a] applied a technique similar to that of Pugh's
+read-side-tracking to permit replugging of algorithms within a commercial
+Unix operating system.  However, this replugging permitted only a single
+reader at a time.  The following year, this same group of researchers
+extended their technique to allow for multiple readers [Cowan96a].
+Their approach requires memory barriers (and thus pipeline stalls),
+but reduces memory latency, contention, and locking overheads.
+
+1995 also saw the first publication of DYNIX/ptx's RCU mechanism
+[Slingwine95], which was optimized for modern CPU architectures,
+and was successfully applied to a number of situations within the
+DYNIX/ptx kernel.  The corresponding conference paper appeared in 1998
+[McKenney98].
+
+In 1999, the Tornado and K42 groups described their "generations"
+mechanism, which quite similar to RCU [Gamsa99].  These operating systems
+made pervasive use of RCU in place of "existence locks", which greatly
+simplifies locking hierarchies.
+
+2001 saw the first RCU presentation involving Linux [McKenney01a]
+at OLS.  The resulting abundance of RCU patches was presented the
+following year [McKenney02a], and use of RCU in dcache was first
+described that same year [Linder02a].
+
+Also in 2002, Michael [Michael02b,Michael02a] presented techniques
+that defer the destruction of data structures to simplify non-blocking
+synchronization (wait-free synchronization, lock-free synchronization,
+and obstruction-free synchronization are all examples of non-blocking
+synchronization).  In particular, this technique eliminates locking,
+reduces contention, reduces memory latency for readers, and parallelizes
+pipeline stalls and memory latency for writers.  However, these
+techniques still impose significant read-side overhead in the form of
+memory barriers.  Researchers at Sun worked along similar lines in the
+same timeframe [HerlihyLM02,HerlihyLMS03].
+
+In 2003, the K42 group described how RCU could be used to create
+hot-pluggable implementations of operating-system functions.  Later that
+year saw a paper describing an RCU implementation of System V IPC
+[Arcangeli03], and an introduction to RCU in Linux Journal [McKenney03a].
+
+2004 has seen a Linux-Journal article on use of RCU in dcache
+[McKenney04a], a performance comparison of locking to RCU on several
+different CPUs [McKenney04b], a dissertation describing use of RCU in a
+number of operating-system kernels [PaulEdwardMcKenneyPhD], and a paper
+describing how to make RCU safe for soft-realtime applications [Sarma04c].
+
+
+Bibtex Entries
+
+@article{Kung80
+,author="H. T. Kung and Q. Lehman"
+,title="Concurrent Maintenance of Binary Search Trees"
+,Year="1980"
+,Month="September"
+,journal="ACM Transactions on Database Systems"
+,volume="5"
+,number="3"
+,pages="354-382"
+}
+
+@techreport{Manber82
+,author="Udi Manber and Richard E. Ladner"
+,title="Concurrency Control in a Dynamic Search Structure"
+,institution="Department of Computer Science, University of Washington"
+,address="Seattle, Washington"
+,year="1982"
+,number="82-01-01"
+,month="January"
+,pages="28"
+}
+
+@article{Manber84
+,author="Udi Manber and Richard E. Ladner"
+,title="Concurrency Control in a Dynamic Search Structure"
+,Year="1984"
+,Month="September"
+,journal="ACM Transactions on Database Systems"
+,volume="9"
+,number="3"
+,pages="439-455"
+}
+
+@techreport{Hennessy89
+,author="James P. Hennessy and Damian L. Osisek and Joseph W. {Seigh II}"
+,title="Passive Serialization in a Multitasking Environment"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1989"
+,number="US Patent 4,809,168 (lapsed)"
+,month="February"
+,pages="11"
+}
+
+@techreport{Pugh90
+,author="William Pugh"
+,title="Concurrent Maintenance of Skip Lists"
+,institution="Institute of Advanced Computer Science Studies, Department of Computer Science, University of Maryland"
+,address="College Park, Maryland"
+,year="1990"
+,number="CS-TR-2222.1"
+,month="June"
+}
+
+@Book{Adams91
+,Author="Gregory R. Adams"
+,title="Concurrent Programming, Principles, and Practices"
+,Publisher="Benjamin Cummins"
+,Year="1991"
+}
+
+@unpublished{Jacobson93
+,author="Van Jacobson"
+,title="Avoid Read-Side Locking Via Delayed Free"
+,year="1993"
+,month="September"
+,note="Verbal discussion"
+}
+
+@Conference{AjuJohn95
+,Author="Aju John"
+,Title="Dynamic vnodes -- Design and Implementation"
+,Booktitle="{USENIX Winter 1995}"
+,Publisher="USENIX Association"
+,Month="January"
+,Year="1995"
+,pages="11-23"
+,Address="New Orleans, LA"
+}
+
+@techreport{Slingwine95
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Apparatus and Method for Achieving Reduced Overhead Mutual
+Exclusion and Maintaining Coherency in a Multiprocessor System
+Utilizing Execution History and Thread Monitoring"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1995"
+,number="US Patent 5,442,758 (contributed under GPL)"
+,month="August"
+}
+
+@techreport{Slingwine97
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Method for maintaining data coherency using thread
+activity summaries in a multicomputer system"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1997"
+,number="US Patent 5,608,893 (contributed under GPL)"
+,month="March"
+}
+
+@techreport{Slingwine98
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Apparatus and method for achieving reduced overhead
+mutual exclusion and maintaining coherency in a multiprocessor
+system utilizing execution history and thread monitoring"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1998"
+,number="US Patent 5,727,209 (contributed under GPL)"
+,month="March"
+}
+
+@Conference{McKenney98
+,Author="Paul E. McKenney and John D. Slingwine"
+,Title="Read-Copy Update: Using Execution History to Solve Concurrency
+Problems"
+,Booktitle="{Parallel and Distributed Computing and Systems}"
+,Month="October"
+,Year="1998"
+,pages="509-518"
+,Address="Las Vegas, NV"
+}
+
+@Conference{Gamsa99
+,Author="Ben Gamsa and Orran Krieger and Jonathan Appavoo and Michael Stumm"
+,Title="Tornado: Maximizing Locality and Concurrency in a Shared Memory
+Multiprocessor Operating System"
+,Booktitle="{Proceedings of the 3\textsuperscript{rd} Symposium on
+Operating System Design and Implementation}"
+,Month="February"
+,Year="1999"
+,pages="87-100"
+,Address="New Orleans, LA"
+}
+
+@techreport{Slingwine01
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Apparatus and method for achieving reduced overhead
+mutual exclusion and maintaining coherency in a multiprocessor
+system utilizing execution history and thread monitoring"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="2001"
+,number="US Patent 5,219,690 (contributed under GPL)"
+,month="April"
+}
+
+@Conference{McKenney01a
+,Author="Paul E. McKenney and Jonathan Appavoo and Andi Kleen and
+Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
+,Title="Read-Copy Update"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="July"
+,Year="2001"
+,note="Available:
+\url{http://www.linuxsymposium.org/2001/abstracts/readcopy.php}
+\url{http://www.rdrop.com/users/paulmck/rclock/rclock_OLS.2001.05.01c.pdf}
+[Viewed June 23, 2004]"
+annotation="
+Described RCU, and presented some patches implementing and using it in
+the Linux kernel.
+"
+}
+
+@Conference{Linder02a
+,Author="Hanna Linder and Dipankar Sarma and Maneesh Soni"
+,Title="Scalability of the Directory Entry Cache"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="June"
+,Year="2002"
+,pages="289-300"
+}
+
+@Conference{McKenney02a
+,Author="Paul E. McKenney and Dipankar Sarma and
+Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
+,Title="Read-Copy Update"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="June"
+,Year="2002"
+,pages="338-367"
+,note="Available:
+\url{http://www.linux.org.uk/~ajh/ols2002_proceedings.pdf.gz}
+[Viewed June 23, 2004]"
+}
+
+@article{Appavoo03a
+,author="J. Appavoo and K. Hui and C. A. N. Soules and R. W. Wisniewski and
+D. M. {Da Silva} and O. Krieger and M. A. Auslander and D. J. Edelsohn and
+B. Gamsa and G. R. Ganger and P. McKenney and M. Ostrowski and
+B. Rosenburg and M. Stumm and J. Xenidis"
+,title="Enabling Autonomic Behavior in Systems Software With Hot Swapping"
+,Year="2003"
+,Month="January"
+,journal="IBM Systems Journal"
+,volume="42"
+,number="1"
+,pages="60-76"
+}
+
+@Conference{Arcangeli03
+,Author="Andrea Arcangeli and Mingming Cao and Paul E. McKenney and
+Dipankar Sarma"
+,Title="Using Read-Copy Update Techniques for {System V IPC} in the
+{Linux} 2.5 Kernel"
+,Booktitle="Proceedings of the 2003 USENIX Annual Technical Conference
+(FREENIX Track)"
+,Publisher="USENIX Association"
+,year="2003"
+,month="June"
+,pages="297-310"
+}
+
+@article{McKenney03a
+,author="Paul E. McKenney"
+,title="Using {RCU} in the {Linux} 2.5 Kernel"
+,Year="2003"
+,Month="October"
+,journal="Linux Journal"
+,volume="1"
+,number="114"
+,pages="18-26"
+}
+
+@article{McKenney04a
+,author="Paul E. McKenney and Dipankar Sarma and Maneesh Soni"
+,title="Scaling dcache with {RCU}"
+,Year="2004"
+,Month="January"
+,journal="Linux Journal"
+,volume="1"
+,number="118"
+,pages="38-46"
+}
+
+@Conference{McKenney04b
+,Author="Paul E. McKenney"
+,Title="{RCU} vs. Locking Performance on Different {CPUs}"
+,Booktitle="{linux.conf.au}"
+,Month="January"
+,Year="2004"
+,Address="Adelaide, Australia"
+,note="Available:
+\url{http://www.linux.org.au/conf/2004/abstracts.html#90}
+\url{http://www.rdrop.com/users/paulmck/rclock/lockperf.2004.01.17a.pdf}
+[Viewed June 23, 2004]"
+}
+
+@phdthesis{PaulEdwardMcKenneyPhD
+,author="Paul E. McKenney"
+,title="Exploiting Deferred Destruction:
+An Analysis of Read-Copy-Update Techniques
+in Operating System Kernels"
+,school="OGI School of Science and Engineering at
+Oregon Health and Sciences University"
+,year="2004"
+}
+
+@Conference{Sarma04c
+,Author="Dipankar Sarma and Paul E. McKenney"
+,Title="Making RCU Safe for Deep Sub-Millisecond Response Realtime Applications"
+,Booktitle="Proceedings of the 2004 USENIX Annual Technical Conference
+(FREENIX Track)"
+,Publisher="USENIX Association"
+,year="2004"
+,month="June"
+,pages="182-191"
+}

+ 64 - 0
Documentation/RCU/UP.txt

@@ -0,0 +1,64 @@
+RCU on Uniprocessor Systems
+
+
+A common misconception is that, on UP systems, the call_rcu() primitive
+may immediately invoke its function, and that the synchronize_kernel
+primitive may return immediately.  The basis of this misconception
+is that since there is only one CPU, it should not be necessary to
+wait for anything else to get done, since there are no other CPUs for
+anything else to be happening on.  Although this approach will sort of
+work a surprising amount of the time, it is a very bad idea in general.
+This document presents two examples that demonstrate exactly how bad an
+idea this is.
+
+
+Example 1: softirq Suicide
+
+Suppose that an RCU-based algorithm scans a linked list containing
+elements A, B, and C in process context, and can delete elements from
+this same list in softirq context.  Suppose that the process-context scan
+is referencing element B when it is interrupted by softirq processing,
+which deletes element B, and then invokes call_rcu() to free element B
+after a grace period.
+
+Now, if call_rcu() were to directly invoke its arguments, then upon return
+from softirq, the list scan would find itself referencing a newly freed
+element B.  This situation can greatly decrease the life expectancy of
+your kernel.
+
+
+Example 2: Function-Call Fatality
+
+Of course, one could avert the suicide described in the preceding example
+by having call_rcu() directly invoke its arguments only if it was called
+from process context.  However, this can fail in a similar manner.
+
+Suppose that an RCU-based algorithm again scans a linked list containing
+elements A, B, and C in process contexts, but that it invokes a function
+on each element as it is scanned.  Suppose further that this function
+deletes element B from the list, then passes it to call_rcu() for deferred
+freeing.  This may be a bit unconventional, but it is perfectly legal
+RCU usage, since call_rcu() must wait for a grace period to elapse.
+Therefore, in this case, allowing call_rcu() to immediately invoke
+its arguments would cause it to fail to make the fundamental guarantee
+underlying RCU, namely that call_rcu() defers invoking its arguments until
+all RCU read-side critical sections currently executing have completed.
+
+Quick Quiz: why is it -not- legal to invoke synchronize_kernel() in
+this case?
+
+
+Summary
+
+Permitting call_rcu() to immediately invoke its arguments or permitting
+synchronize_kernel() to immediately return breaks RCU, even on a UP system.
+So do not do it!  Even on a UP system, the RCU infrastructure -must-
+respect grace periods.
+
+
+Answer to Quick Quiz
+
+The calling function is scanning an RCU-protected linked list, and
+is therefore within an RCU read-side critical section.  Therefore,
+the called function has been invoked within an RCU read-side critical
+section, and is not permitted to block.

+ 141 - 0
Documentation/RCU/arrayRCU.txt

@@ -0,0 +1,141 @@
+Using RCU to Protect Read-Mostly Arrays
+
+
+Although RCU is more commonly used to protect linked lists, it can
+also be used to protect arrays.  Three situations are as follows:
+
+1.  Hash Tables
+
+2.  Static Arrays
+
+3.  Resizeable Arrays
+
+Each of these situations are discussed below.
+
+
+Situation 1: Hash Tables
+
+Hash tables are often implemented as an array, where each array entry
+has a linked-list hash chain.  Each hash chain can be protected by RCU
+as described in the listRCU.txt document.  This approach also applies
+to other array-of-list situations, such as radix trees.
+
+
+Situation 2: Static Arrays
+
+Static arrays, where the data (rather than a pointer to the data) is
+located in each array element, and where the array is never resized,
+have not been used with RCU.  Rik van Riel recommends using seqlock in
+this situation, which would also have minimal read-side overhead as long
+as updates are rare.
+
+Quick Quiz:  Why is it so important that updates be rare when
+	     using seqlock?
+
+
+Situation 3: Resizeable Arrays
+
+Use of RCU for resizeable arrays is demonstrated by the grow_ary()
+function used by the System V IPC code.  The array is used to map from
+semaphore, message-queue, and shared-memory IDs to the data structure
+that represents the corresponding IPC construct.  The grow_ary()
+function does not acquire any locks; instead its caller must hold the
+ids->sem semaphore.
+
+The grow_ary() function, shown below, does some limit checks, allocates a
+new ipc_id_ary, copies the old to the new portion of the new, initializes
+the remainder of the new, updates the ids->entries pointer to point to
+the new array, and invokes ipc_rcu_putref() to free up the old array.
+Note that rcu_assign_pointer() is used to update the ids->entries pointer,
+which includes any memory barriers required on whatever architecture
+you are running on.
+
+	static int grow_ary(struct ipc_ids* ids, int newsize)
+	{
+		struct ipc_id_ary* new;
+		struct ipc_id_ary* old;
+		int i;
+		int size = ids->entries->size;
+
+		if(newsize > IPCMNI)
+			newsize = IPCMNI;
+		if(newsize <= size)
+			return newsize;
+
+		new = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*newsize +
+				    sizeof(struct ipc_id_ary));
+		if(new == NULL)
+			return size;
+		new->size = newsize;
+		memcpy(new->p, ids->entries->p,
+		       sizeof(struct kern_ipc_perm *)*size +
+		       sizeof(struct ipc_id_ary));
+		for(i=size;i<newsize;i++) {
+			new->p[i] = NULL;
+		}
+		old = ids->entries;
+
+		/*
+		 * Use rcu_assign_pointer() to make sure the memcpyed
+		 * contents of the new array are visible before the new
+		 * array becomes visible.
+		 */
+		rcu_assign_pointer(ids->entries, new);
+
+		ipc_rcu_putref(old);
+		return newsize;
+	}
+
+The ipc_rcu_putref() function decrements the array's reference count
+and then, if the reference count has dropped to zero, uses call_rcu()
+to free the array after a grace period has elapsed.
+
+The array is traversed by the ipc_lock() function.  This function
+indexes into the array under the protection of rcu_read_lock(),
+using rcu_dereference() to pick up the pointer to the array so
+that it may later safely be dereferenced -- memory barriers are
+required on the Alpha CPU.  Since the size of the array is stored
+with the array itself, there can be no array-size mismatches, so
+a simple check suffices.  The pointer to the structure corresponding
+to the desired IPC object is placed in "out", with NULL indicating
+a non-existent entry.  After acquiring "out->lock", the "out->deleted"
+flag indicates whether the IPC object is in the process of being
+deleted, and, if not, the pointer is returned.
+
+	struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
+	{
+		struct kern_ipc_perm* out;
+		int lid = id % SEQ_MULTIPLIER;
+		struct ipc_id_ary* entries;
+
+		rcu_read_lock();
+		entries = rcu_dereference(ids->entries);
+		if(lid >= entries->size) {
+			rcu_read_unlock();
+			return NULL;
+		}
+		out = entries->p[lid];
+		if(out == NULL) {
+			rcu_read_unlock();
+			return NULL;
+		}
+		spin_lock(&out->lock);
+
+		/* ipc_rmid() may have already freed the ID while ipc_lock
+		 * was spinning: here verify that the structure is still valid
+		 */
+		if (out->deleted) {
+			spin_unlock(&out->lock);
+			rcu_read_unlock();
+			return NULL;
+		}
+		return out;
+	}
+
+
+Answer to Quick Quiz:
+
+	The reason that it is important that updates be rare when
+	using seqlock is that frequent updates can livelock readers.
+	One way to avoid this problem is to assign a seqlock for
+	each array entry rather than to the entire array.

+ 157 - 0
Documentation/RCU/checklist.txt

@@ -0,0 +1,157 @@
+Review Checklist for RCU Patches
+
+
+This document contains a checklist for producing and reviewing patches
+that make use of RCU.  Violating any of the rules listed below will
+result in the same sorts of problems that leaving out a locking primitive
+would cause.  This list is based on experiences reviewing such patches
+over a rather long period of time, but improvements are always welcome!
+
+0.	Is RCU being applied to a read-mostly situation?  If the data
+	structure is updated more than about 10% of the time, then
+	you should strongly consider some other approach, unless
+	detailed performance measurements show that RCU is nonetheless
+	the right tool for the job.
+
+	The other exception would be where performance is not an issue,
+	and RCU provides a simpler implementation.  An example of this
+	situation is the dynamic NMI code in the Linux 2.6 kernel,
+	at least on architectures where NMIs are rare.
+
+1.	Does the update code have proper mutual exclusion?
+
+	RCU does allow -readers- to run (almost) naked, but -writers- must
+	still use some sort of mutual exclusion, such as:
+
+	a.	locking,
+	b.	atomic operations, or
+	c.	restricting updates to a single task.
+
+	If you choose #b, be prepared to describe how you have handled
+	memory barriers on weakly ordered machines (pretty much all of
+	them -- even x86 allows reads to be reordered), and be prepared
+	to explain why this added complexity is worthwhile.  If you
+	choose #c, be prepared to explain how this single task does not
+	become a major bottleneck on big multiprocessor machines.
+
+2.	Do the RCU read-side critical sections make proper use of
+	rcu_read_lock() and friends?  These primitives are needed
+	to suppress preemption (or bottom halves, in the case of
+	rcu_read_lock_bh()) in the read-side critical sections,
+	and are also an excellent aid to readability.
+
+3.	Does the update code tolerate concurrent accesses?
+
+	The whole point of RCU is to permit readers to run without
+	any locks or atomic operations.  This means that readers will
+	be running while updates are in progress.  There are a number
+	of ways to handle this concurrency, depending on the situation:
+
+	a.	Make updates appear atomic to readers.  For example,
+		pointer updates to properly aligned fields will appear
+		atomic, as will individual atomic primitives.  Operations
+		performed under a lock and sequences of multiple atomic
+		primitives will -not- appear to be atomic.
+
+		This is almost always the best approach.
+
+	b.	Carefully order the updates and the reads so that
+		readers see valid data at all phases of the update.
+		This is often more difficult than it sounds, especially
+		given modern CPUs' tendency to reorder memory references.
+		One must usually liberally sprinkle memory barriers
+		(smp_wmb(), smp_rmb(), smp_mb()) through the code,
+		making it difficult to understand and to test.
+
+		It is usually better to group the changing data into
+		a separate structure, so that the change may be made
+		to appear atomic by updating a pointer to reference
+		a new structure containing updated values.
+
+4.	Weakly ordered CPUs pose special challenges.  Almost all CPUs
+	are weakly ordered -- even i386 CPUs allow reads to be reordered.
+	RCU code must take all of the following measures to prevent
+	memory-corruption problems:
+
+	a.	Readers must maintain proper ordering of their memory
+		accesses.  The rcu_dereference() primitive ensures that
+		the CPU picks up the pointer before it picks up the data
+		that the pointer points to.  This really is necessary
+		on Alpha CPUs.	If you don't believe me, see:
+
+			http://www.openvms.compaq.com/wizard/wiz_2637.html
+
+		The rcu_dereference() primitive is also an excellent
+		documentation aid, letting the person reading the code
+		know exactly which pointers are protected by RCU.
+
+		The rcu_dereference() primitive is used by the various
+		"_rcu()" list-traversal primitives, such as the
+		list_for_each_entry_rcu().
+
+	b.	If the list macros are being used, the list_del_rcu(),
+		list_add_tail_rcu(), and list_del_rcu() primitives must
+		be used in order to prevent weakly ordered machines from
+		misordering structure initialization and pointer planting.
+		Similarly, if the hlist macros are being used, the
+		hlist_del_rcu() and hlist_add_head_rcu() primitives
+		are required.
+
+	c.	Updates must ensure that initialization of a given
+		structure happens before pointers to that structure are
+		publicized.  Use the rcu_assign_pointer() primitive
+		when publicizing a pointer to a structure that can
+		be traversed by an RCU read-side critical section.
+
+		[The rcu_assign_pointer() primitive is in process.]
+
+5.	If call_rcu(), or a related primitive such as call_rcu_bh(),
+	is used, the callback function must be written to be called
+	from softirq context.  In particular, it cannot block.
+
+6.	Since synchronize_kernel() blocks, it cannot be called from
+	any sort of irq context.
+
+7.	If the updater uses call_rcu(), then the corresponding readers
+	must use rcu_read_lock() and rcu_read_unlock().  If the updater
+	uses call_rcu_bh(), then the corresponding readers must use
+	rcu_read_lock_bh() and rcu_read_unlock_bh().  Mixing things up
+	will result in confusion and broken kernels.
+
+	One exception to this rule: rcu_read_lock() and rcu_read_unlock()
+	may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
+	in cases where local bottom halves are already known to be
+	disabled, for example, in irq or softirq context.  Commenting
+	such cases is a must, of course!  And the jury is still out on
+	whether the increased speed is worth it.
+
+8.	Although synchronize_kernel() is a bit slower than is call_rcu(),
+	it usually results in simpler code.  So, unless update performance
+	is important or the updaters cannot block, synchronize_kernel()
+	should be used in preference to call_rcu().
+
+9.	All RCU list-traversal primitives, which include
+	list_for_each_rcu(), list_for_each_entry_rcu(),
+	list_for_each_continue_rcu(), and list_for_each_safe_rcu(),
+	must be within an RCU read-side critical section.  RCU
+	read-side critical sections are delimited by rcu_read_lock()
+	and rcu_read_unlock(), or by similar primitives such as
+	rcu_read_lock_bh() and rcu_read_unlock_bh().
+
+	Use of the _rcu() list-traversal primitives outside of an
+	RCU read-side critical section causes no harm other than
+	a slight performance degradation on Alpha CPUs and some
+	confusion on the part of people trying to read the code.
+
+	Another way of thinking of this is "If you are holding the
+	lock that prevents the data structure from changing, why do
+	you also need RCU-based protection?"  That said, there may
+	well be situations where use of the _rcu() list-traversal
+	primitives while the update-side lock is held results in
+	simpler and more maintainable code.  The jury is still out
+	on this question.
+
+10.	Conversely, if you are in an RCU read-side critical section,
+	you -must- use the "_rcu()" variants of the list macros.
+	Failing to do so will break Alpha and confuse people reading
+	your code.

+ 307 - 0
Documentation/RCU/listRCU.txt

@@ -0,0 +1,307 @@
+Using RCU to Protect Read-Mostly Linked Lists
+
+
+One of the best applications of RCU is to protect read-mostly linked lists
+("struct list_head" in list.h).  One big advantage of this approach
+is that all of the required memory barriers are included for you in
+the list macros.  This document describes several applications of RCU,
+with the best fits first.
+
+
+Example 1: Read-Side Action Taken Outside of Lock, No In-Place Updates
+
+The best applications are cases where, if reader-writer locking were
+used, the read-side lock would be dropped before taking any action
+based on the results of the search.  The most celebrated example is
+the routing table.  Because the routing table is tracking the state of
+equipment outside of the computer, it will at times contain stale data.
+Therefore, once the route has been computed, there is no need to hold
+the routing table static during transmission of the packet.  After all,
+you can hold the routing table static all you want, but that won't keep
+the external Internet from changing, and it is the state of the external
+Internet that really matters.  In addition, routing entries are typically
+added or deleted, rather than being modified in place.
+
+A straightforward example of this use of RCU may be found in the
+system-call auditing support.  For example, a reader-writer locked
+implementation of audit_filter_task() might be as follows:
+
+	static enum audit_state audit_filter_task(struct task_struct *tsk)
+	{
+		struct audit_entry *e;
+		enum audit_state   state;
+
+		read_lock(&auditsc_lock);
+		list_for_each_entry(e, &audit_tsklist, list) {
+			if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+				read_unlock(&auditsc_lock);
+				return state;
+			}
+		}
+		read_unlock(&auditsc_lock);
+		return AUDIT_BUILD_CONTEXT;
+	}
+
+Here the list is searched under the lock, but the lock is dropped before
+the corresponding value is returned.  By the time that this value is acted
+on, the list may well have been modified.  This makes sense, since if
+you are turning auditing off, it is OK to audit a few extra system calls.
+
+This means that RCU can be easily applied to the read side, as follows:
+
+	static enum audit_state audit_filter_task(struct task_struct *tsk)
+	{
+		struct audit_entry *e;
+		enum audit_state   state;
+
+		rcu_read_lock();
+		list_for_each_entry_rcu(e, &audit_tsklist, list) {
+			if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+				rcu_read_unlock();
+				return state;
+			}
+		}
+		rcu_read_unlock();
+		return AUDIT_BUILD_CONTEXT;
+	}
+
+The read_lock() and read_unlock() calls have become rcu_read_lock()
+and rcu_read_unlock(), respectively, and the list_for_each_entry() has
+become list_for_each_entry_rcu().  The _rcu() list-traversal primitives
+insert the read-side memory barriers that are required on DEC Alpha CPUs.
+
+The changes to the update side are also straightforward.  A reader-writer
+lock might be used as follows for deletion and insertion:
+
+	static inline int audit_del_rule(struct audit_rule *rule,
+					 struct list_head *list)
+	{
+		struct audit_entry  *e;
+
+		write_lock(&auditsc_lock);
+		list_for_each_entry(e, list, list) {
+			if (!audit_compare_rule(rule, &e->rule)) {
+				list_del(&e->list);
+				write_unlock(&auditsc_lock);
+				return 0;
+			}
+		}
+		write_unlock(&auditsc_lock);
+		return -EFAULT;		/* No matching rule */
+	}
+
+	static inline int audit_add_rule(struct audit_entry *entry,
+					 struct list_head *list)
+	{
+		write_lock(&auditsc_lock);
+		if (entry->rule.flags & AUDIT_PREPEND) {
+			entry->rule.flags &= ~AUDIT_PREPEND;
+			list_add(&entry->list, list);
+		} else {
+			list_add_tail(&entry->list, list);
+		}
+		write_unlock(&auditsc_lock);
+		return 0;
+	}
+
+Following are the RCU equivalents for these two functions:
+
+	static inline int audit_del_rule(struct audit_rule *rule,
+					 struct list_head *list)
+	{
+		struct audit_entry  *e;
+
+		/* Do not use the _rcu iterator here, since this is the only
+		 * deletion routine. */
+		list_for_each_entry(e, list, list) {
+			if (!audit_compare_rule(rule, &e->rule)) {
+				list_del_rcu(&e->list);
+				call_rcu(&e->rcu, audit_free_rule, e);
+				return 0;
+			}
+		}
+		return -EFAULT;		/* No matching rule */
+	}
+
+	static inline int audit_add_rule(struct audit_entry *entry,
+					 struct list_head *list)
+	{
+		if (entry->rule.flags & AUDIT_PREPEND) {
+			entry->rule.flags &= ~AUDIT_PREPEND;
+			list_add_rcu(&entry->list, list);
+		} else {
+			list_add_tail_rcu(&entry->list, list);
+		}
+		return 0;
+	}
+
+Normally, the write_lock() and write_unlock() would be replaced by
+a spin_lock() and a spin_unlock(), but in this case, all callers hold
+audit_netlink_sem, so no additional locking is required.  The auditsc_lock
+can therefore be eliminated, since use of RCU eliminates the need for
+writers to exclude readers.
+
+The list_del(), list_add(), and list_add_tail() primitives have been
+replaced by list_del_rcu(), list_add_rcu(), and list_add_tail_rcu().
+The _rcu() list-manipulation primitives add memory barriers that are
+needed on weakly ordered CPUs (most of them!).
+
+So, when readers can tolerate stale data and when entries are either added
+or deleted, without in-place modification, it is very easy to use RCU!
+
+
+Example 2: Handling In-Place Updates
+
+The system-call auditing code does not update auditing rules in place.
+However, if it did, reader-writer-locked code to do so might look as
+follows (presumably, the field_count is only permitted to decrease,
+otherwise, the added fields would need to be filled in):
+
+	static inline int audit_upd_rule(struct audit_rule *rule,
+					 struct list_head *list,
+					 __u32 newaction,
+					 __u32 newfield_count)
+	{
+		struct audit_entry  *e;
+		struct audit_newentry *ne;
+
+		write_lock(&auditsc_lock);
+		list_for_each_entry(e, list, list) {
+			if (!audit_compare_rule(rule, &e->rule)) {
+				e->rule.action = newaction;
+				e->rule.file_count = newfield_count;
+				write_unlock(&auditsc_lock);
+				return 0;
+			}
+		}
+		write_unlock(&auditsc_lock);
+		return -EFAULT;		/* No matching rule */
+	}
+
+The RCU version creates a copy, updates the copy, then replaces the old
+entry with the newly updated entry.  This sequence of actions, allowing
+concurrent reads while doing a copy to perform an update, is what gives
+RCU ("read-copy update") its name.  The RCU code is as follows:
+
+	static inline int audit_upd_rule(struct audit_rule *rule,
+					 struct list_head *list,
+					 __u32 newaction,
+					 __u32 newfield_count)
+	{
+		struct audit_entry  *e;
+		struct audit_newentry *ne;
+
+		list_for_each_entry(e, list, list) {
+			if (!audit_compare_rule(rule, &e->rule)) {
+				ne = kmalloc(sizeof(*entry), GFP_ATOMIC);
+				if (ne == NULL)
+					return -ENOMEM;
+				audit_copy_rule(&ne->rule, &e->rule);
+				ne->rule.action = newaction;
+				ne->rule.file_count = newfield_count;
+				list_add_rcu(ne, e);
+				list_del(e);
+				call_rcu(&e->rcu, audit_free_rule, e);
+				return 0;
+			}
+		}
+		return -EFAULT;		/* No matching rule */
+	}
+
+Again, this assumes that the caller holds audit_netlink_sem.  Normally,
+the reader-writer lock would become a spinlock in this sort of code.
+
+
+Example 3: Eliminating Stale Data
+
+The auditing examples above tolerate stale data, as do most algorithms
+that are tracking external state.  Because there is a delay from the
+time the external state changes before Linux becomes aware of the change,
+additional RCU-induced staleness is normally not a problem.
+
+However, there are many examples where stale data cannot be tolerated.
+One example in the Linux kernel is the System V IPC (see the ipc_lock()
+function in ipc/util.c).  This code checks a "deleted" flag under a
+per-entry spinlock, and, if the "deleted" flag is set, pretends that the
+entry does not exist.  For this to be helpful, the search function must
+return holding the per-entry spinlock, as ipc_lock() does in fact do.
+
+Quick Quiz:  Why does the search function need to return holding the
+per-entry lock for this deleted-flag technique to be helpful?
+
+If the system-call audit module were to ever need to reject stale data,
+one way to accomplish this would be to add a "deleted" flag and a "lock"
+spinlock to the audit_entry structure, and modify audit_filter_task()
+as follows:
+
+	static enum audit_state audit_filter_task(struct task_struct *tsk)
+	{
+		struct audit_entry *e;
+		enum audit_state   state;
+
+		rcu_read_lock();
+		list_for_each_entry_rcu(e, &audit_tsklist, list) {
+			if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+				spin_lock(&e->lock);
+				if (e->deleted) {
+					spin_unlock(&e->lock);
+					rcu_read_unlock();
+					return AUDIT_BUILD_CONTEXT;
+				}
+				rcu_read_unlock();
+				return state;
+			}
+		}
+		rcu_read_unlock();
+		return AUDIT_BUILD_CONTEXT;
+	}
+
+Note that this example assumes that entries are only added and deleted.
+Additional mechanism is required to deal correctly with the
+update-in-place performed by audit_upd_rule().  For one thing,
+audit_upd_rule() would need additional memory barriers to ensure
+that the list_add_rcu() was really executed before the list_del_rcu().
+
+The audit_del_rule() function would need to set the "deleted"
+flag under the spinlock as follows:
+
+	static inline int audit_del_rule(struct audit_rule *rule,
+					 struct list_head *list)
+	{
+		struct audit_entry  *e;
+
+		/* Do not use the _rcu iterator here, since this is the only
+		 * deletion routine. */
+		list_for_each_entry(e, list, list) {
+			if (!audit_compare_rule(rule, &e->rule)) {
+				spin_lock(&e->lock);
+				list_del_rcu(&e->list);
+				e->deleted = 1;
+				spin_unlock(&e->lock);
+				call_rcu(&e->rcu, audit_free_rule, e);
+				return 0;
+			}
+		}
+		return -EFAULT;		/* No matching rule */
+	}
+
+
+Summary
+
+Read-mostly list-based data structures that can tolerate stale data are
+the most amenable to use of RCU.  The simplest case is where entries are
+either added or deleted from the data structure (or atomically modified
+in place), but non-atomic in-place modifications can be handled by making
+a copy, updating the copy, then replacing the original with the copy.
+If stale data cannot be tolerated, then a "deleted" flag may be used
+in conjunction with a per-entry spinlock in order to allow the search
+function to reject newly deleted data.
+
+
+Answer to Quick Quiz
+
+If the search function drops the per-entry lock before returning, then
+the caller will be processing stale data in any case.  If it is really
+OK to be processing stale data, then you don't need a "deleted" flag.
+If processing stale data really is a problem, then you need to hold the
+per-entry lock across all of the code that uses the value looked up.

+ 67 - 0
Documentation/RCU/rcu.txt

@@ -0,0 +1,67 @@
+RCU Concepts
+
+
+The basic idea behind RCU (read-copy update) is to split destructive
+operations into two parts, one that prevents anyone from seeing the data
+item being destroyed, and one that actually carries out the destruction.
+A "grace period" must elapse between the two parts, and this grace period
+must be long enough that any readers accessing the item being deleted have
+since dropped their references.  For example, an RCU-protected deletion
+from a linked list would first remove the item from the list, wait for
+a grace period to elapse, then free the element.  See the listRCU.txt
+file for more information on using RCU with linked lists.
+
+
+Frequently Asked Questions
+
+o	Why would anyone want to use RCU?
+
+	The advantage of RCU's two-part approach is that RCU readers need
+	not acquire any locks, perform any atomic instructions, write to
+	shared memory, or (on CPUs other than Alpha) execute any memory
+	barriers.  The fact that these operations are quite expensive
+	on modern CPUs is what gives RCU its performance advantages
+	in read-mostly situations.  The fact that RCU readers need not
+	acquire locks can also greatly simplify deadlock-avoidance code.
+
+o	How can the updater tell when a grace period has completed
+	if the RCU readers give no indication when they are done?
+
+	Just as with spinlocks, RCU readers are not permitted to
+	block, switch to user-mode execution, or enter the idle loop.
+	Therefore, as soon as a CPU is seen passing through any of these
+	three states, we know that that CPU has exited any previous RCU
+	read-side critical sections.  So, if we remove an item from a
+	linked list, and then wait until all CPUs have switched context,
+	executed in user mode, or executed in the idle loop, we can
+	safely free up that item.
+
+o	If I am running on a uniprocessor kernel, which can only do one
+	thing at a time, why should I wait for a grace period?
+
+	See the UP.txt file in this directory.
+
+o	How can I see where RCU is currently used in the Linux kernel?
+
+	Search for "rcu_read_lock", "call_rcu", and "synchronize_kernel".
+
+o	What guidelines should I follow when writing code that uses RCU?
+
+	See the checklist.txt file in this directory.
+
+o	Why the name "RCU"?
+
+	"RCU" stands for "read-copy update".  The file listRCU.txt has
+	more information on where this name came from, search for
+	"read-copy update" to find it.
+
+o	I hear that RCU is patented?  What is with that?
+
+	Yes, it is.  There are several known patents related to RCU,
+	search for the string "Patent" in RTFP.txt to find them.
+	Of these, one was allowed to lapse by the assignee, and the
+	others have been contributed to the Linux kernel under GPL.
+
+o	Where can I find more information on RCU?
+
+	See the RTFP.txt file in this directory.

+ 756 - 0
Documentation/README.DAC960

@@ -0,0 +1,756 @@
+   Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
+
+			Version 2.2.11 for Linux 2.2.19
+			Version 2.4.11 for Linux 2.4.12
+
+			      PRODUCTION RELEASE
+
+				11 October 2001
+
+			       Leonard N. Zubkoff
+			       Dandelion Digital
+			       lnz@dandelion.com
+
+	 Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+
+				 INTRODUCTION
+
+Mylex, Inc. designs and manufactures a variety of high performance PCI RAID
+controllers.  Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont,
+California 94555, USA and can be reached at 510.796.6100 or on the World Wide
+Web at http://www.mylex.com.  Mylex Technical Support can be reached by
+electronic mail at mylexsup@us.ibm.com, by voice at 510.608.2400, or by FAX at
+510.745.7715.  Contact information for offices in Europe and Japan is available
+on their Web site.
+
+The latest information on Linux support for DAC960 PCI RAID Controllers, as
+well as the most recent release of this driver, will always be available from
+my Linux Home Page at URL "http://www.dandelion.com/Linux/".  The Linux DAC960
+driver supports all current Mylex PCI RAID controllers including the new
+eXtremeRAID 2000/3000 and AcceleRAID 352/170/160 models which have an entirely
+new firmware interface from the older eXtremeRAID 1100, AcceleRAID 150/200/250,
+and DAC960PJ/PG/PU/PD/PL.  See below for a complete controller list as well as
+minimum firmware version requirements.  For simplicity, in most places this
+documentation refers to DAC960 generically rather than explicitly listing all
+the supported models.
+
+Driver bug reports should be sent via electronic mail to "lnz@dandelion.com".
+Please include with the bug report the complete configuration messages reported
+by the driver at startup, along with any subsequent system messages relevant to
+the controller's operation, and a detailed description of your system's
+hardware configuration.  Driver bugs are actually quite rare; if you encounter
+problems with disks being marked offline, for example, please contact Mylex
+Technical Support as the problem is related to the hardware configuration
+rather than the Linux driver.
+
+Please consult the RAID controller documentation for detailed information
+regarding installation and configuration of the controllers.  This document
+primarily provides information specific to the Linux support.
+
+
+				DRIVER FEATURES
+
+The DAC960 RAID controllers are supported solely as high performance RAID
+controllers, not as interfaces to arbitrary SCSI devices.  The Linux DAC960
+driver operates at the block device level, the same level as the SCSI and IDE
+drivers.  Unlike other RAID controllers currently supported on Linux, the
+DAC960 driver is not dependent on the SCSI subsystem, and hence avoids all the
+complexity and unnecessary code that would be associated with an implementation
+as a SCSI driver.  The DAC960 driver is designed for as high a performance as
+possible with no compromises or extra code for compatibility with lower
+performance devices.  The DAC960 driver includes extensive error logging and
+online configuration management capabilities.  Except for initial configuration
+of the controller and adding new disk drives, most everything can be handled
+from Linux while the system is operational.
+
+The DAC960 driver is architected to support up to 8 controllers per system.
+Each DAC960 parallel SCSI controller can support up to 15 disk drives per
+channel, for a maximum of 60 drives on a four channel controller; the fibre
+channel eXtremeRAID 3000 controller supports up to 125 disk drives per loop for
+a total of 250 drives.  The drives installed on a controller are divided into
+one or more "Drive Groups", and then each Drive Group is subdivided further
+into 1 to 32 "Logical Drives".  Each Logical Drive has a specific RAID Level
+and caching policy associated with it, and it appears to Linux as a single
+block device.  Logical Drives are further subdivided into up to 7 partitions
+through the normal Linux and PC disk partitioning schemes.  Logical Drives are
+also known as "System Drives", and Drive Groups are also called "Packs".  Both
+terms are in use in the Mylex documentation; I have chosen to standardize on
+the more generic "Logical Drive" and "Drive Group".
+
+DAC960 RAID disk devices are named in the style of the Device File System
+(DEVFS).  The device corresponding to Logical Drive D on Controller C is
+referred to as /dev/rd/cCdD, and the partitions are called /dev/rd/cCdDp1
+through /dev/rd/cCdDp7.  For example, partition 3 of Logical Drive 5 on
+Controller 2 is referred to as /dev/rd/c2d5p3.  Note that unlike with SCSI
+disks the device names will not change in the event of a disk drive failure.
+The DAC960 driver is assigned major numbers 48 - 55 with one major number per
+controller.  The 8 bits of minor number are divided into 5 bits for the Logical
+Drive and 3 bits for the partition.
+
+
+	  SUPPORTED DAC960/AcceleRAID/eXtremeRAID PCI RAID CONTROLLERS
+
+The following list comprises the supported DAC960, AcceleRAID, and eXtremeRAID
+PCI RAID Controllers as of the date of this document.  It is recommended that
+anyone purchasing a Mylex PCI RAID Controller not in the following table
+contact the author beforehand to verify that it is or will be supported.
+
+eXtremeRAID 3000
+	    1 Wide Ultra-2/LVD SCSI channel
+	    2 External Fibre FC-AL channels
+	    233MHz StrongARM SA 110 Processor
+	    64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
+	    32MB/64MB ECC SDRAM Memory
+
+eXtremeRAID 2000
+	    4 Wide Ultra-160 LVD SCSI channels
+	    233MHz StrongARM SA 110 Processor
+	    64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
+	    32MB/64MB ECC SDRAM Memory
+
+AcceleRAID 352
+	    2 Wide Ultra-160 LVD SCSI channels
+	    100MHz Intel i960RN RISC Processor
+	    64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
+	    32MB/64MB ECC SDRAM Memory
+
+AcceleRAID 170
+	    1 Wide Ultra-160 LVD SCSI channel
+	    100MHz Intel i960RM RISC Processor
+	    16MB/32MB/64MB ECC SDRAM Memory
+
+AcceleRAID 160 (AcceleRAID 170LP)
+	    1 Wide Ultra-160 LVD SCSI channel
+	    100MHz Intel i960RS RISC Processor
+	    Built in 16M ECC SDRAM Memory
+	    PCI Low Profile Form Factor - fit for 2U height
+
+eXtremeRAID 1100 (DAC1164P)
+	    3 Wide Ultra-2/LVD SCSI channels
+	    233MHz StrongARM SA 110 Processor
+	    64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
+	    16MB/32MB/64MB Parity SDRAM Memory with Battery Backup
+
+AcceleRAID 250 (DAC960PTL1)
+	    Uses onboard Symbios SCSI chips on certain motherboards
+	    Also includes one onboard Wide Ultra-2/LVD SCSI Channel
+	    66MHz Intel i960RD RISC Processor
+	    4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
+
+AcceleRAID 200 (DAC960PTL0)
+	    Uses onboard Symbios SCSI chips on certain motherboards
+	    Includes no onboard SCSI Channels
+	    66MHz Intel i960RD RISC Processor
+	    4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
+
+AcceleRAID 150 (DAC960PRL)
+	    Uses onboard Symbios SCSI chips on certain motherboards
+	    Also includes one onboard Wide Ultra-2/LVD SCSI Channel
+	    33MHz Intel i960RP RISC Processor
+	    4MB Parity EDO Memory
+
+DAC960PJ    1/2/3 Wide Ultra SCSI-3 Channels
+	    66MHz Intel i960RD RISC Processor
+	    4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
+
+DAC960PG    1/2/3 Wide Ultra SCSI-3 Channels
+	    33MHz Intel i960RP RISC Processor
+	    4MB/8MB ECC EDO Memory
+
+DAC960PU    1/2/3 Wide Ultra SCSI-3 Channels
+	    Intel i960CF RISC Processor
+	    4MB/8MB EDRAM or 2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+DAC960PD    1/2/3 Wide Fast SCSI-2 Channels
+	    Intel i960CF RISC Processor
+	    4MB/8MB EDRAM or 2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+DAC960PL    1/2/3 Wide Fast SCSI-2 Channels
+	    Intel i960 RISC Processor
+	    2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+DAC960P	    1/2/3 Wide Fast SCSI-2 Channels
+	    Intel i960 RISC Processor
+	    2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+For the eXtremeRAID 2000/3000 and AcceleRAID 352/170/160, firmware version
+6.00-01 or above is required.
+
+For the eXtremeRAID 1100, firmware version 5.06-0-52 or above is required.
+
+For the AcceleRAID 250, 200, and 150, firmware version 4.06-0-57 or above is
+required.
+
+For the DAC960PJ and DAC960PG, firmware version 4.06-0-00 or above is required.
+
+For the DAC960PU, DAC960PD, DAC960PL, and DAC960P, either firmware version
+3.51-0-04 or above is required (for dual Flash ROM controllers), or firmware
+version 2.73-0-00 or above is required (for single Flash ROM controllers)
+
+Please note that not all SCSI disk drives are suitable for use with DAC960
+controllers, and only particular firmware versions of any given model may
+actually function correctly.  Similarly, not all motherboards have a BIOS that
+properly initializes the AcceleRAID 250, AcceleRAID 200, AcceleRAID 150,
+DAC960PJ, and DAC960PG because the Intel i960RD/RP is a multi-function device.
+If in doubt, contact Mylex RAID Technical Support (mylexsup@us.ibm.com) to
+verify compatibility.  Mylex makes available a hard disk compatibility list at
+http://www.mylex.com/support/hdcomp/hd-lists.html.
+
+
+			      DRIVER INSTALLATION
+
+This distribution was prepared for Linux kernel version 2.2.19 or 2.4.12.
+
+To install the DAC960 RAID driver, you may use the following commands,
+replacing "/usr/src" with wherever you keep your Linux kernel source tree:
+
+  cd /usr/src
+  tar -xvzf DAC960-2.2.11.tar.gz (or DAC960-2.4.11.tar.gz)
+  mv README.DAC960 linux/Documentation
+  mv DAC960.[ch] linux/drivers/block
+  patch -p0 < DAC960.patch (if DAC960.patch is included)
+  cd linux
+  make config
+  make bzImage (or zImage)
+
+Then install "arch/i386/boot/bzImage" or "arch/i386/boot/zImage" as your
+standard kernel, run lilo if appropriate, and reboot.
+
+To create the necessary devices in /dev, the "make_rd" script included in
+"DAC960-Utilities.tar.gz" from http://www.dandelion.com/Linux/ may be used.
+LILO 21 and FDISK v2.9 include DAC960 support; also included in this archive
+are patches to LILO 20 and FDISK v2.8 that add DAC960 support, along with
+statically linked executables of LILO and FDISK.  This modified version of LILO
+will allow booting from a DAC960 controller and/or mounting the root file
+system from a DAC960.
+
+Red Hat Linux 6.0 and SuSE Linux 6.1 include support for Mylex PCI RAID
+controllers.  Installing directly onto a DAC960 may be problematic from other
+Linux distributions until their installation utilities are updated.
+
+
+			      INSTALLATION NOTES
+
+Before installing Linux or adding DAC960 logical drives to an existing Linux
+system, the controller must first be configured to provide one or more logical
+drives using the BIOS Configuration Utility or DACCF.  Please note that since
+there are only at most 6 usable partitions on each logical drive, systems
+requiring more partitions should subdivide a drive group into multiple logical
+drives, each of which can have up to 6 usable partitions.  Also, note that with
+large disk arrays it is advisable to enable the 8GB BIOS Geometry (255/63)
+rather than accepting the default 2GB BIOS Geometry (128/32); failing to so do
+will cause the logical drive geometry to have more than 65535 cylinders which
+will make it impossible for FDISK to be used properly.  The 8GB BIOS Geometry
+can be enabled by configuring the DAC960 BIOS, which is accessible via Alt-M
+during the BIOS initialization sequence.
+
+For maximum performance and the most efficient E2FSCK performance, it is
+recommended that EXT2 file systems be built with a 4KB block size and 16 block
+stride to match the DAC960 controller's 64KB default stripe size.  The command
+"mke2fs -b 4096 -R stride=16 <device>" is appropriate.  Unless there will be a
+large number of small files on the file systems, it is also beneficial to add
+the "-i 16384" option to increase the bytes per inode parameter thereby
+reducing the file system metadata.  Finally, on systems that will only be run
+with Linux 2.2 or later kernels it is beneficial to enable sparse superblocks
+with the "-s 1" option.
+
+
+		      DAC960 ANNOUNCEMENTS MAILING LIST
+
+The DAC960 Announcements Mailing List provides a forum for informing Linux
+users of new driver releases and other announcements regarding Linux support
+for DAC960 PCI RAID Controllers.  To join the mailing list, send a message to
+"dac960-announce-request@dandelion.com" with the line "subscribe" in the
+message body.
+
+
+		CONTROLLER CONFIGURATION AND STATUS MONITORING
+
+The DAC960 RAID controllers running firmware 4.06 or above include a Background
+Initialization facility so that system downtime is minimized both for initial
+installation and subsequent configuration of additional storage.  The BIOS
+Configuration Utility (accessible via Alt-R during the BIOS initialization
+sequence) is used to quickly configure the controller, and then the logical
+drives that have been created are available for immediate use even while they
+are still being initialized by the controller.  The primary need for online
+configuration and status monitoring is then to avoid system downtime when disk
+drives fail and must be replaced.  Mylex's online monitoring and configuration
+utilities are being ported to Linux and will become available at some point in
+the future.  Note that with a SAF-TE (SCSI Accessed Fault-Tolerant Enclosure)
+enclosure, the controller is able to rebuild failed drives automatically as
+soon as a drive replacement is made available.
+
+The primary interfaces for controller configuration and status monitoring are
+special files created in the /proc/rd/... hierarchy along with the normal
+system console logging mechanism.  Whenever the system is operating, the DAC960
+driver queries each controller for status information every 10 seconds, and
+checks for additional conditions every 60 seconds.  The initial status of each
+controller is always available for controller N in /proc/rd/cN/initial_status,
+and the current status as of the last status monitoring query is available in
+/proc/rd/cN/current_status.  In addition, status changes are also logged by the
+driver to the system console and will appear in the log files maintained by
+syslog.  The progress of asynchronous rebuild or consistency check operations
+is also available in /proc/rd/cN/current_status, and progress messages are
+logged to the system console at most every 60 seconds.
+
+Starting with the 2.2.3/2.0.3 versions of the driver, the status information
+available in /proc/rd/cN/initial_status and /proc/rd/cN/current_status has been
+augmented to include the vendor, model, revision, and serial number (if
+available) for each physical device found connected to the controller:
+
+***** DAC960 RAID Driver Version 2.2.3 of 19 August 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PRL PCI RAID Controller
+  Firmware Version: 4.07-0-07, Channels: 1, Memory Size: 16MB
+  PCI Bus: 1, Device: 4, Function: 1, I/O Address: Unassigned
+  PCI Address: 0xFE300000 mapped at 0xA0800000, IRQ Channel: 21
+  Controller Queue Depth: 128, Maximum Blocks per Command: 128
+  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+  SAF-TE Enclosure Management Enabled
+  Physical Devices:
+    0:0  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       68016775HA
+         Disk Status: Online, 17928192 blocks
+    0:1  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       68004E53HA
+         Disk Status: Online, 17928192 blocks
+    0:2  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       13013935HA
+         Disk Status: Online, 17928192 blocks
+    0:3  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       13016897HA
+         Disk Status: Online, 17928192 blocks
+    0:4  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       68019905HA
+         Disk Status: Online, 17928192 blocks
+    0:5  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       68012753HA
+         Disk Status: Online, 17928192 blocks
+    0:6  Vendor: ESG-SHV   Model: SCA HSBP M6       Revision: 0.61
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 89640960 blocks, Write Thru
+  No Rebuild or Consistency Check in Progress
+
+To simplify the monitoring process for custom software, the special file
+/proc/rd/status returns "OK" when all DAC960 controllers in the system are
+operating normally and no failures have occurred, or "ALERT" if any logical
+drives are offline or critical or any non-standby physical drives are dead.
+
+Configuration commands for controller N are available via the special file
+/proc/rd/cN/user_command.  A human readable command can be written to this
+special file to initiate a configuration operation, and the results of the
+operation can then be read back from the special file in addition to being
+logged to the system console.  The shell command sequence
+
+  echo "<configuration-command>" > /proc/rd/c0/user_command
+  cat /proc/rd/c0/user_command
+
+is typically used to execute configuration commands.  The configuration
+commands are:
+
+  flush-cache
+
+    The "flush-cache" command flushes the controller's cache.  The system
+    automatically flushes the cache at shutdown or if the driver module is
+    unloaded, so this command is only needed to be certain a write back cache
+    is flushed to disk before the system is powered off by a command to a UPS.
+    Note that the flush-cache command also stops an asynchronous rebuild or
+    consistency check, so it should not be used except when the system is being
+    halted.
+
+  kill <channel>:<target-id>
+
+    The "kill" command marks the physical drive <channel>:<target-id> as DEAD.
+    This command is provided primarily for testing, and should not be used
+    during normal system operation.
+
+  make-online <channel>:<target-id>
+
+    The "make-online" command changes the physical drive <channel>:<target-id>
+    from status DEAD to status ONLINE.  In cases where multiple physical drives
+    have been killed simultaneously, this command may be used to bring all but
+    one of them back online, after which a rebuild to the final drive is
+    necessary.
+
+    Warning: make-online should only be used on a dead physical drive that is
+    an active part of a drive group, never on a standby drive.  The command
+    should never be used on a dead drive that is part of a critical logical
+    drive; rebuild should be used if only a single drive is dead.
+
+  make-standby <channel>:<target-id>
+
+    The "make-standby" command changes physical drive <channel>:<target-id>
+    from status DEAD to status STANDBY.  It should only be used in cases where
+    a dead drive was replaced after an automatic rebuild was performed onto a
+    standby drive.  It cannot be used to add a standby drive to the controller
+    configuration if one was not created initially; the BIOS Configuration
+    Utility must be used for that currently.
+
+  rebuild <channel>:<target-id>
+
+    The "rebuild" command initiates an asynchronous rebuild onto physical drive
+    <channel>:<target-id>.  It should only be used when a dead drive has been
+    replaced.
+
+  check-consistency <logical-drive-number>
+
+    The "check-consistency" command initiates an asynchronous consistency check
+    of <logical-drive-number> with automatic restoration.  It can be used
+    whenever it is desired to verify the consistency of the redundancy
+    information.
+
+  cancel-rebuild
+  cancel-consistency-check
+
+    The "cancel-rebuild" and "cancel-consistency-check" commands cancel any
+    rebuild or consistency check operations previously initiated.
+
+
+	       EXAMPLE I - DRIVE FAILURE WITHOUT A STANDBY DRIVE
+
+The following annotated logs demonstrate the controller configuration and and
+online status monitoring capabilities of the Linux DAC960 Driver.  The test
+configuration comprises 6 1GB Quantum Atlas I disk drives on two channels of a
+DAC960PJ controller.  The physical drives are configured into a single drive
+group without a standby drive, and the drive group has been configured into two
+logical drives, one RAID-5 and one RAID-6.  Note that these logs are from an
+earlier version of the driver and the messages have changed somewhat with newer
+releases, but the functionality remains similar.  First, here is the current
+status of the RAID configuration:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PJ PCI RAID Controller
+  Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
+  PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
+  PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
+  Controller Queue Depth: 128, Maximum Blocks per Command: 128
+  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 5498880 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Online, 3305472 blocks, Write Thru
+  No Rebuild or Consistency Check in Progress
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+The above messages indicate that everything is healthy, and /proc/rd/status
+returns "OK" indicating that there are no problems with any DAC960 controller
+in the system.  For demonstration purposes, while I/O is active Physical Drive
+1:1 is now disconnected, simulating a drive failure.  The failure is noted by
+the driver within 10 seconds of the controller's having detected it, and the
+driver logs the following console status messages indicating that Logical
+Drives 0 and 1 are now CRITICAL as a result of Physical Drive 1:1 being DEAD:
+
+DAC960#0: Physical Drive 1:2 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:3 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:1 killed because of timeout on SCSI command
+DAC960#0: Physical Drive 1:1 is now DEAD
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now CRITICAL
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now CRITICAL
+
+The Sense Keys logged here are just Check Condition / Unit Attention conditions
+arising from a SCSI bus reset that is forced by the controller during its error
+recovery procedures.  Concurrently with the above, the driver status available
+from /proc/rd also reflects the drive failure.  The status message in
+/proc/rd/status has changed from "OK" to "ALERT":
+
+gwynedd:/u/lnz# cat /proc/rd/status
+ALERT
+
+and /proc/rd/c0/current_status has been updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Dead, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
+  No Rebuild or Consistency Check in Progress
+
+Since there are no standby drives configured, the system can continue to access
+the logical drives in a performance degraded mode until the failed drive is
+replaced and a rebuild operation completed to restore the redundancy of the
+logical drives.  Once Physical Drive 1:1 is replaced with a properly
+functioning drive, or if the physical drive was killed without having failed
+(e.g., due to electrical problems on the SCSI bus), the user can instruct the
+controller to initiate a rebuild operation onto the newly replaced drive:
+
+gwynedd:/u/lnz# echo "rebuild 1:1" > /proc/rd/c0/user_command
+gwynedd:/u/lnz# cat /proc/rd/c0/user_command
+Rebuild of Physical Drive 1:1 Initiated
+
+The echo command instructs the controller to initiate an asynchronous rebuild
+operation onto Physical Drive 1:1, and the status message that results from the
+operation is then available for reading from /proc/rd/c0/user_command, as well
+as being logged to the console by the driver.
+
+Within 10 seconds of this command the driver logs the initiation of the
+asynchronous rebuild operation:
+
+DAC960#0: Rebuild of Physical Drive 1:1 Initiated
+DAC960#0: Physical Drive 1:1 Error Log: Sense Key = 6, ASC = 29, ASCQ = 01
+DAC960#0: Physical Drive 1:1 is now WRITE-ONLY
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 1% completed
+
+and /proc/rd/c0/current_status is updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Write-Only, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
+  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 6% completed
+
+As the rebuild progresses, the current status in /proc/rd/c0/current_status is
+updated every 10 seconds:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Write-Only, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
+  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 15% completed
+
+and every minute a progress message is logged to the console by the driver:
+
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 32% completed
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 63% completed
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 94% completed
+DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 94% completed
+
+Finally, the rebuild completes successfully.  The driver logs the status of the 
+logical and physical drives and the rebuild completion:
+
+DAC960#0: Rebuild Completed Successfully
+DAC960#0: Physical Drive 1:1 is now ONLINE
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now ONLINE
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now ONLINE
+
+/proc/rd/c0/current_status is updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 5498880 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Online, 3305472 blocks, Write Thru
+  Rebuild Completed Successfully
+
+and /proc/rd/status indicates that everything is healthy once again:
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+
+		EXAMPLE II - DRIVE FAILURE WITH A STANDBY DRIVE
+
+The following annotated logs demonstrate the controller configuration and and
+online status monitoring capabilities of the Linux DAC960 Driver.  The test
+configuration comprises 6 1GB Quantum Atlas I disk drives on two channels of a
+DAC960PJ controller.  The physical drives are configured into a single drive
+group with a standby drive, and the drive group has been configured into two
+logical drives, one RAID-5 and one RAID-6.  Note that these logs are from an
+earlier version of the driver and the messages have changed somewhat with newer
+releases, but the functionality remains similar.  First, here is the current
+status of the RAID configuration:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PJ PCI RAID Controller
+  Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
+  PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
+  PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
+  Controller Queue Depth: 128, Maximum Blocks per Command: 128
+  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Standby, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
+  No Rebuild or Consistency Check in Progress
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+The above messages indicate that everything is healthy, and /proc/rd/status
+returns "OK" indicating that there are no problems with any DAC960 controller
+in the system.  For demonstration purposes, while I/O is active Physical Drive
+1:2 is now disconnected, simulating a drive failure.  The failure is noted by
+the driver within 10 seconds of the controller's having detected it, and the
+driver logs the following console status messages:
+
+DAC960#0: Physical Drive 1:1 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:3 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:2 killed because of timeout on SCSI command
+DAC960#0: Physical Drive 1:2 is now DEAD
+DAC960#0: Physical Drive 1:2 killed because it was removed
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now CRITICAL
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now CRITICAL
+
+Since a standby drive is configured, the controller automatically begins
+rebuilding onto the standby drive:
+
+DAC960#0: Physical Drive 1:3 is now WRITE-ONLY
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 4% completed
+
+Concurrently with the above, the driver status available from /proc/rd also
+reflects the drive failure and automatic rebuild.  The status message in
+/proc/rd/status has changed from "OK" to "ALERT":
+
+gwynedd:/u/lnz# cat /proc/rd/status
+ALERT
+
+and /proc/rd/c0/current_status has been updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Dead, 2201600 blocks
+    1:3 - Disk: Write-Only, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Critical, 4399104 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Critical, 2754560 blocks, Write Thru
+  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 4% completed
+
+As the rebuild progresses, the current status in /proc/rd/c0/current_status is
+updated every 10 seconds:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Dead, 2201600 blocks
+    1:3 - Disk: Write-Only, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Critical, 4399104 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Critical, 2754560 blocks, Write Thru
+  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 40% completed
+
+and every minute a progress message is logged on the console by the driver:
+
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 40% completed
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 76% completed
+DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 66% completed
+DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 84% completed
+
+Finally, the rebuild completes successfully.  The driver logs the status of the 
+logical and physical drives and the rebuild completion:
+
+DAC960#0: Rebuild Completed Successfully
+DAC960#0: Physical Drive 1:3 is now ONLINE
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now ONLINE
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now ONLINE
+
+/proc/rd/c0/current_status is updated:
+
+***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PJ PCI RAID Controller
+  Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
+  PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
+  PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
+  Controller Queue Depth: 128, Maximum Blocks per Command: 128
+  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Dead, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
+  Rebuild Completed Successfully
+
+and /proc/rd/status indicates that everything is healthy once again:
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+Note that the absence of a viable standby drive does not create an "ALERT"
+status.  Once dead Physical Drive 1:2 has been replaced, the controller must be
+told that this has occurred and that the newly replaced drive should become the
+new standby drive:
+
+gwynedd:/u/lnz# echo "make-standby 1:2" > /proc/rd/c0/user_command
+gwynedd:/u/lnz# cat /proc/rd/c0/user_command
+Make Standby of Physical Drive 1:2 Succeeded
+
+The echo command instructs the controller to make Physical Drive 1:2 into a
+standby drive, and the status message that results from the operation is then
+available for reading from /proc/rd/c0/user_command, as well as being logged to
+the console by the driver.  Within 60 seconds of this command the driver logs:
+
+DAC960#0: Physical Drive 1:2 Error Log: Sense Key = 6, ASC = 29, ASCQ = 01
+DAC960#0: Physical Drive 1:2 is now STANDBY
+DAC960#0: Make Standby of Physical Drive 1:2 Succeeded
+
+and /proc/rd/c0/current_status is updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Standby, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
+  Rebuild Completed Successfully

+ 8 - 0
Documentation/README.cycladesZ

@@ -0,0 +1,8 @@
+
+The Cyclades-Z must have firmware loaded onto the card before it will
+operate.  This operation should be performed during system startup,
+
+The firmware, loader program and the latest device driver code are
+available from Cyclades at
+    ftp://ftp.cyclades.com/pub/cyclades/cyclades-z/linux/
+

+ 88 - 0
Documentation/SAK.txt

@@ -0,0 +1,88 @@
+Linux 2.4.2 Secure Attention Key (SAK) handling
+18 March 2001, Andrew Morton <akpm@osdl.org>
+
+An operating system's Secure Attention Key is a security tool which is
+provided as protection against trojan password capturing programs.  It
+is an undefeatable way of killing all programs which could be
+masquerading as login applications.  Users need to be taught to enter
+this key sequence before they log in to the system.
+
+From the PC keyboard, Linux has two similar but different ways of
+providing SAK.  One is the ALT-SYSRQ-K sequence.  You shouldn't use
+this sequence.  It is only available if the kernel was compiled with
+sysrq support.
+
+The proper way of generating a SAK is to define the key sequence using
+`loadkeys'.  This will work whether or not sysrq support is compiled
+into the kernel.
+
+SAK works correctly when the keyboard is in raw mode.  This means that
+once defined, SAK will kill a running X server.  If the system is in
+run level 5, the X server will restart.  This is what you want to
+happen.
+
+What key sequence should you use? Well, CTRL-ALT-DEL is used to reboot
+the machine.  CTRL-ALT-BACKSPACE is magical to the X server.  We'll
+choose CTRL-ALT-PAUSE.
+
+In your rc.sysinit (or rc.local) file, add the command
+
+	echo "control alt keycode 101 = SAK" | /bin/loadkeys
+
+And that's it!  Only the superuser may reprogram the SAK key.
+
+
+NOTES
+=====
+
+1: Linux SAK is said to be not a "true SAK" as is required by
+   systems which implement C2 level security.  This author does not
+   know why.
+
+
+2: On the PC keyboard, SAK kills all applications which have
+   /dev/console opened.
+
+   Unfortunately this includes a number of things which you don't
+   actually want killed.  This is because these applications are
+   incorrectly holding /dev/console open.  Be sure to complain to your
+   Linux distributor about this!
+
+   You can identify processes which will be killed by SAK with the
+   command
+
+	# ls -l /proc/[0-9]*/fd/* | grep console
+	l-wx------    1 root     root           64 Mar 18 00:46 /proc/579/fd/0 -> /dev/console
+
+   Then:
+
+	# ps aux|grep 579
+	root       579  0.0  0.1  1088  436 ?        S    00:43   0:00 gpm -t ps/2
+
+   So `gpm' will be killed by SAK.  This is a bug in gpm.  It should
+   be closing standard input.  You can work around this by finding the
+   initscript which launches gpm and changing it thusly:
+
+   Old:
+
+	daemon gpm
+
+   New:
+
+	daemon gpm < /dev/null
+
+   Vixie cron also seems to have this problem, and needs the same treatment.
+
+   Also, one prominent Linux distribution has the following three
+   lines in its rc.sysinit and rc scripts:
+
+	exec 3<&0
+	exec 4>&1
+	exec 5>&2
+
+   These commands cause *all* daemons which are launched by the
+   initscripts to have file descriptors 3, 4 and 5 attached to
+   /dev/console.  So SAK kills them all.  A workaround is to simply
+   delete these lines, but this may cause system management
+   applications to malfunction - test everything well.
+

+ 38 - 0
Documentation/SecurityBugs

@@ -0,0 +1,38 @@
+Linux kernel developers take security very seriously.  As such, we'd
+like to know when a security bug is found so that it can be fixed and
+disclosed as quickly as possible.  Please report security bugs to the
+Linux kernel security team.
+
+1) Contact
+
+The Linux kernel security team can be contacted by email at
+<security@kernel.org>.  This is a private list of security officers
+who will help verify the bug report and develop and release a fix.
+It is possible that the security team will bring in extra help from
+area maintainers to understand and fix the security vulnerability.
+
+As it is with any bug, the more information provided the easier it
+will be to diagnose and fix.  Please review the procedure outlined in
+REPORTING-BUGS if you are unclear about what information is helpful.
+Any exploit code is very helpful and will not be released without
+consent from the reporter unless it has already been made public.
+
+2) Disclosure
+
+The goal of the Linux kernel security team is to work with the
+bug submitter to bug resolution as well as disclosure.  We prefer
+to fully disclose the bug as soon as possible.  It is reasonable to
+delay disclosure when the bug or the fix is not yet fully understood,
+the solution is not well-tested or for vendor coordination.  However, we
+expect these delays to be short, measurable in days, not weeks or months.
+A disclosure date is negotiated by the security team working with the
+bug submitter as well as vendors.  However, the kernel security team
+holds the final say when setting a disclosure date.  The timeframe for
+disclosure is from immediate (esp. if it's already publically known)
+to a few weeks.  As a basic default policy, we expect report date to
+disclosure date to be on the order of 7 days.
+
+3) Non-disclosure agreements
+
+The Linux kernel security team is not a formal body and therefore unable
+to enter any non-disclosure agreements.

+ 145 - 0
Documentation/SubmittingDrivers

@@ -0,0 +1,145 @@
+Submitting Drivers For The Linux Kernel
+---------------------------------------
+
+This document is intended to explain how to submit device drivers to the
+various kernel trees. Note that if you are interested in video card drivers
+you should probably talk to XFree86 (http://www.xfree86.org/) and/or X.Org
+(http://x.org/) instead.
+
+Also read the Documentation/SubmittingPatches document.
+
+
+Allocating Device Numbers
+-------------------------
+
+Major and minor numbers for block and character devices are allocated
+by the Linux assigned name and number authority (currently better
+known as H Peter Anvin). The site is http://www.lanana.org/. This
+also deals with allocating numbers for devices that are not going to
+be submitted to the mainstream kernel.
+
+If you don't use assigned numbers then when you device is submitted it will
+get given an assigned number even if that is different from values you may
+have shipped to customers before.
+
+Who To Submit Drivers To
+------------------------
+
+Linux 2.0:
+	No new drivers are accepted for this kernel tree
+
+Linux 2.2:
+	If the code area has a general maintainer then please submit it to
+	the maintainer listed in MAINTAINERS in the kernel file. If the
+	maintainer does not respond or you cannot find the appropriate
+	maintainer then please contact Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+Linux 2.4:
+	The same rules apply as 2.2. The final contact point for Linux 2.4
+	submissions is Marcelo Tosatti <marcelo.tosatti@cyclades.com>.
+
+Linux 2.6:
+	The same rules apply as 2.4 except that you should follow linux-kernel
+	to track changes in API's. The final contact point for Linux 2.6
+	submissions is Andrew Morton <akpm@osdl.org>.
+
+What Criteria Determine Acceptance
+----------------------------------
+
+Licensing:	The code must be released to us under the
+		GNU General Public License. We don't insist on any kind
+		of exclusively GPL licensing, and if you wish the driver
+		to be useful to other communities such as BSD you may well
+		wish to release under multiple licenses.
+
+Copyright:	The copyright owner must agree to use of GPL.
+		It's best if the submitter and copyright owner
+		are the same person/entity. If not, the name of
+		the person/entity authorizing use of GPL should be
+		listed in case it's necessary to verify the will of
+		the copright owner.
+
+Interfaces:	If your driver uses existing interfaces and behaves like
+		other drivers in the same class it will be much more likely
+		to be accepted than if it invents gratuitous new ones. 
+		If you need to implement a common API over Linux and NT
+		drivers do it in userspace.
+
+Code:		Please use the Linux style of code formatting as documented
+		in Documentation/CodingStyle. If you have sections of code
+		that need to be in other formats, for example because they
+		are shared with a windows driver kit and you want to
+		maintain them just once separate them out nicely and note
+		this fact.
+
+Portability:	Pointers are not always 32bits, not all computers are little
+		endian, people do not all have floating point and you
+		shouldn't use inline x86 assembler in your driver without
+		careful thought. Pure x86 drivers generally are not popular.
+		If you only have x86 hardware it is hard to test portability
+		but it is easy to make sure the code can easily be made
+		portable.
+
+Clarity:	It helps if anyone can see how to fix the driver. It helps
+		you because you get patches not bug reports. If you submit a
+		driver that intentionally obfuscates how the hardware works
+		it will go in the bitbucket.
+
+Control:	In general if there is active maintainance of a driver by
+		the author then patches will be redirected to them unless 
+		they are totally obvious and without need of checking.
+		If you want to be the contact and update point for the
+		driver it is a good idea to state this in the comments,
+		and include an entry in MAINTAINERS for your driver.
+
+What Criteria Do Not Determine Acceptance
+-----------------------------------------
+
+Vendor:		Being the hardware vendor and maintaining the driver is
+		often a good thing. If there is a stable working driver from
+		other people already in the tree don't expect 'we are the
+		vendor' to get your driver chosen. Ideally work with the 
+		existing driver author to build a single perfect driver.
+
+Author:		It doesn't matter if a large Linux company wrote the driver,
+		or you did. Nobody has any special access to the kernel
+		tree. Anyone who tells you otherwise isn't telling the
+		whole story.
+
+
+Resources
+---------
+
+Linux kernel master tree:
+	ftp.??.kernel.org:/pub/linux/kernel/...
+	?? == your country code, such as "us", "uk", "fr", etc.
+
+Linux kernel mailing list:		
+	linux-kernel@vger.kernel.org
+	[mail majordomo@vger.kernel.org to subscribe]
+
+Linux Device Drivers, Third Edition (covers 2.6.10):
+	http://lwn.net/Kernel/LDD3/  (free version)
+
+Kernel traffic:
+	Weekly summary of kernel list activity (much easier to read)
+	http://www.kerneltraffic.org/kernel-traffic/
+
+LWN.net:
+	Weekly summary of kernel development activity - http://lwn.net/
+	2.6 API changes:
+		http://lwn.net/Articles/2.6-kernel-api/
+	Porting drivers from prior kernels to 2.6:
+		http://lwn.net/Articles/driver-porting/
+
+KernelTrap:
+	Occasional Linux kernel articles and developer interviews
+	http://kerneltrap.org/
+
+KernelNewbies:
+	Documentation and assistance for new kernel programmers
+	http://kernelnewbies.org/
+
+Linux USB project:
+	http://sourceforge.net/projects/linux-usb/
+

+ 374 - 0
Documentation/SubmittingPatches

@@ -0,0 +1,374 @@
+
+	How to Get Your Change Into the Linux Kernel
+		or
+	Care And Operation Of Your Linus Torvalds
+
+
+
+For a person or company who wishes to submit a change to the Linux
+kernel, the process can sometimes be daunting if you're not familiar
+with "the system."  This text is a collection of suggestions which
+can greatly increase the chances of your change being accepted.
+
+If you are submitting a driver, also read Documentation/SubmittingDrivers.
+
+
+
+--------------------------------------------
+SECTION 1 - CREATING AND SENDING YOUR CHANGE
+--------------------------------------------
+
+
+
+1) "diff -up"
+------------
+
+Use "diff -up" or "diff -uprN" to create patches.
+
+All changes to the Linux kernel occur in the form of patches, as
+generated by diff(1).  When creating your patch, make sure to create it
+in "unified diff" format, as supplied by the '-u' argument to diff(1).
+Also, please use the '-p' argument which shows which C function each
+change is in - that makes the resultant diff a lot easier to read.
+Patches should be based in the root kernel source directory,
+not in any lower subdirectory.
+
+To create a patch for a single file, it is often sufficient to do:
+
+	SRCTREE= linux-2.4
+	MYFILE=  drivers/net/mydriver.c
+
+	cd $SRCTREE
+	cp $MYFILE $MYFILE.orig
+	vi $MYFILE	# make your change
+	cd ..
+	diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+To create a patch for multiple files, you should unpack a "vanilla",
+or unmodified kernel source tree, and generate a diff against your
+own source tree.  For example:
+
+	MYSRC= /devel/linux-2.4
+
+	tar xvfz linux-2.4.0-test11.tar.gz
+	mv linux linux-vanilla
+	wget http://www.moses.uklinux.net/patches/dontdiff
+	diff -uprN -X dontdiff linux-vanilla $MYSRC > /tmp/patch
+	rm -f dontdiff
+
+"dontdiff" is a list of files which are generated by the kernel during
+the build process, and should be ignored in any diff(1)-generated
+patch.  dontdiff is maintained by Tigran Aivazian <tigran@veritas.com>
+
+Make sure your patch does not include any extra files which do not
+belong in a patch submission.  Make sure to review your patch -after-
+generated it with diff(1), to ensure accuracy.
+
+If your changes produce a lot of deltas, you may want to look into
+splitting them into individual patches which modify things in
+logical stages, this will facilitate easier reviewing by other
+kernel developers, very important if you want your patch accepted.
+There are a number of scripts which can aid in this;
+
+Quilt:
+http://savannah.nongnu.org/projects/quilt
+
+Randy Dunlap's patch scripts:
+http://developer.osdl.org/rddunlap/scripts/patching-scripts.tgz
+
+Andrew Morton's patch scripts:
+http://www.zip.com.au/~akpm/linux/patches/patch-scripts-0.16
+
+2) Describe your changes.
+
+Describe the technical detail of the change(s) your patch includes.
+
+Be as specific as possible.  The WORST descriptions possible include
+things like "update driver X", "bug fix for driver X", or "this patch
+includes updates for subsystem X.  Please apply."
+
+If your description starts to get long, that's a sign that you probably
+need to split up your patch.  See #3, next.
+
+
+
+3) Separate your changes.
+
+Separate each logical change into its own patch.
+
+For example, if your changes include both bug fixes and performance
+enhancements for a single driver, separate those changes into two
+or more patches.  If your changes include an API update, and a new
+driver which uses that new API, separate those into two patches.
+
+On the other hand, if you make a single change to numerous files,
+group those changes into a single patch.  Thus a single logical change
+is contained within a single patch.
+
+If one patch depends on another patch in order for a change to be
+complete, that is OK.  Simply note "this patch depends on patch X"
+in your patch description.
+
+
+4) Select e-mail destination.
+
+Look through the MAINTAINERS file and the source code, and determine
+if your change applies to a specific subsystem of the kernel, with
+an assigned maintainer.  If so, e-mail that person.
+
+If no maintainer is listed, or the maintainer does not respond, send
+your patch to the primary Linux kernel developer's mailing list,
+linux-kernel@vger.kernel.org.  Most kernel developers monitor this
+e-mail list, and can comment on your changes.
+
+Linus Torvalds is the final arbiter of all changes accepted into the
+Linux kernel.  His e-mail address is <torvalds@osdl.org>.  He gets
+a lot of e-mail, so typically you should do your best to -avoid- sending
+him e-mail.
+
+Patches which are bug fixes, are "obvious" changes, or similarly
+require little discussion should be sent or CC'd to Linus.  Patches
+which require discussion or do not have a clear advantage should
+usually be sent first to linux-kernel.  Only after the patch is
+discussed should the patch then be submitted to Linus.
+
+For small patches you may want to CC the Trivial Patch Monkey
+trivial@rustcorp.com.au set up by Rusty Russell; which collects "trivial"
+patches. Trivial patches must qualify for one of the following rules:
+ Spelling fixes in documentation
+ Spelling fixes which could break grep(1).
+ Warning fixes (cluttering with useless warnings is bad)
+ Compilation fixes (only if they are actually correct)
+ Runtime fixes (only if they actually fix things)
+ Removing use of deprecated functions/macros (eg. check_region).
+ Contact detail and documentation fixes
+ Non-portable code replaced by portable code (even in arch-specific,
+ since people copy, as long as it's trivial)
+ Any fix by the author/maintainer of the file. (ie. patch monkey
+ in re-transmission mode)
+
+
+
+5) Select your CC (e-mail carbon copy) list.
+
+Unless you have a reason NOT to do so, CC linux-kernel@vger.kernel.org.
+
+Other kernel developers besides Linus need to be aware of your change,
+so that they may comment on it and offer code review and suggestions.
+linux-kernel is the primary Linux kernel developer mailing list.
+Other mailing lists are available for specific subsystems, such as
+USB, framebuffer devices, the VFS, the SCSI subsystem, etc.  See the
+MAINTAINERS file for a mailing list that relates specifically to
+your change.
+
+Even if the maintainer did not respond in step #4, make sure to ALWAYS
+copy the maintainer when you change their code.
+
+For small patches you may want to CC the Trivial Patch Monkey
+trivial@rustcorp.com.au set up by Rusty Russell; which collects "trivial"
+patches. Trivial patches must qualify for one of the following rules:
+ Spelling fixes in documentation
+ Spelling fixes which could break grep(1).
+ Warning fixes (cluttering with useless warnings is bad)
+ Compilation fixes (only if they are actually correct)
+ Runtime fixes (only if they actually fix things)
+ Removing use of deprecated functions/macros (eg. check_region).
+ Contact detail and documentation fixes
+ Non-portable code replaced by portable code (even in arch-specific,
+ since people copy, as long as it's trivial)
+ Any fix by the author/maintainer of the file. (ie. patch monkey
+ in re-transmission mode)
+
+
+
+6) No MIME, no links, no compression, no attachments.  Just plain text.
+
+Linus and other kernel developers need to be able to read and comment
+on the changes you are submitting.  It is important for a kernel
+developer to be able to "quote" your changes, using standard e-mail
+tools, so that they may comment on specific portions of your code.
+
+For this reason, all patches should be submitting e-mail "inline".
+WARNING:  Be wary of your editor's word-wrap corrupting your patch,
+if you choose to cut-n-paste your patch.
+
+Do not attach the patch as a MIME attachment, compressed or not.
+Many popular e-mail applications will not always transmit a MIME
+attachment as plain text, making it impossible to comment on your
+code.  A MIME attachment also takes Linus a bit more time to process,
+decreasing the likelihood of your MIME-attached change being accepted.
+
+Exception:  If your mailer is mangling patches then someone may ask
+you to re-send them using MIME.
+
+
+
+7) E-mail size.
+
+When sending patches to Linus, always follow step #6.
+
+Large changes are not appropriate for mailing lists, and some
+maintainers.  If your patch, uncompressed, exceeds 40 kB in size,
+it is preferred that you store your patch on an Internet-accessible
+server, and provide instead a URL (link) pointing to your patch.
+
+
+
+8) Name your kernel version.
+
+It is important to note, either in the subject line or in the patch
+description, the kernel version to which this patch applies.
+
+If the patch does not apply cleanly to the latest kernel version,
+Linus will not apply it.
+
+
+
+9) Don't get discouraged.  Re-submit.
+
+After you have submitted your change, be patient and wait.  If Linus
+likes your change and applies it, it will appear in the next version
+of the kernel that he releases.
+
+However, if your change doesn't appear in the next version of the
+kernel, there could be any number of reasons.  It's YOUR job to
+narrow down those reasons, correct what was wrong, and submit your
+updated change.
+
+It is quite common for Linus to "drop" your patch without comment.
+That's the nature of the system.  If he drops your patch, it could be
+due to
+* Your patch did not apply cleanly to the latest kernel version
+* Your patch was not sufficiently discussed on linux-kernel.
+* A style issue (see section 2),
+* An e-mail formatting issue (re-read this section)
+* A technical problem with your change
+* He gets tons of e-mail, and yours got lost in the shuffle
+* You are being annoying (See Figure 1)
+
+When in doubt, solicit comments on linux-kernel mailing list.
+
+
+
+10) Include PATCH in the subject
+
+Due to high e-mail traffic to Linus, and to linux-kernel, it is common
+convention to prefix your subject line with [PATCH].  This lets Linus
+and other kernel developers more easily distinguish patches from other
+e-mail discussions.
+
+
+
+11) Sign your work
+
+To improve tracking of who did what, especially with patches that can
+percolate to their final resting place in the kernel through several
+layers of maintainers, we've introduced a "sign-off" procedure on
+patches that are being emailed around.
+
+The sign-off is a simple line at the end of the explanation for the
+patch, which certifies that you wrote it or otherwise have the right to
+pass it on as a open-source patch.  The rules are pretty simple: if you
+can certify the below:
+
+        Developer's Certificate of Origin 1.0
+
+        By making a contribution to this project, I certify that:
+
+        (a) The contribution was created in whole or in part by me and I
+            have the right to submit it under the open source license
+            indicated in the file; or
+
+        (b) The contribution is based upon previous work that, to the best
+            of my knowledge, is covered under an appropriate open source
+            license and I have the right under that license to submit that
+            work with modifications, whether created in whole or in part
+            by me, under the same open source license (unless I am
+            permitted to submit under a different license), as indicated
+            in the file; or
+
+        (c) The contribution was provided directly to me by some other
+            person who certified (a), (b) or (c) and I have not modified
+            it.
+
+then you just add a line saying
+
+	Signed-off-by: Random J Developer <random@developer.org>
+
+Some people also put extra tags at the end.  They'll just be ignored for
+now, but you can do this to mark internal company procedures or just
+point out some special detail about the sign-off. 
+
+
+-----------------------------------
+SECTION 2 - HINTS, TIPS, AND TRICKS
+-----------------------------------
+
+This section lists many of the common "rules" associated with code
+submitted to the kernel.  There are always exceptions... but you must
+have a really good reason for doing so.  You could probably call this
+section Linus Computer Science 101.
+
+
+
+1) Read Documentation/CodingStyle
+
+Nuff said.  If your code deviates too much from this, it is likely
+to be rejected without further review, and without comment.
+
+
+
+2) #ifdefs are ugly
+
+Code cluttered with ifdefs is difficult to read and maintain.  Don't do
+it.  Instead, put your ifdefs in a header, and conditionally define
+'static inline' functions, or macros, which are used in the code.
+Let the compiler optimize away the "no-op" case.
+
+Simple example, of poor code:
+
+	dev = alloc_etherdev (sizeof(struct funky_private));
+	if (!dev)
+		return -ENODEV;
+	#ifdef CONFIG_NET_FUNKINESS
+	init_funky_net(dev);
+	#endif
+
+Cleaned-up example:
+
+(in header)
+	#ifndef CONFIG_NET_FUNKINESS
+	static inline void init_funky_net (struct net_device *d) {}
+	#endif
+
+(in the code itself)
+	dev = alloc_etherdev (sizeof(struct funky_private));
+	if (!dev)
+		return -ENODEV;
+	init_funky_net(dev);
+
+
+
+3) 'static inline' is better than a macro
+
+Static inline functions are greatly preferred over macros.
+They provide type safety, have no length limitations, no formatting
+limitations, and under gcc they are as cheap as macros.
+
+Macros should only be used for cases where a static inline is clearly
+suboptimal [there a few, isolated cases of this in fast paths],
+or where it is impossible to use a static inline function [such as
+string-izing].
+
+'static inline' is preferred over 'static __inline__', 'extern inline',
+and 'extern __inline__'.
+
+
+
+4) Don't over-design.
+
+Don't try to anticipate nebulous future cases which may or may not
+be useful:  "Make it as simple as you can, and no simpler"
+
+
+

+ 39 - 0
Documentation/VGA-softcursor.txt

@@ -0,0 +1,39 @@
+Software cursor for VGA    by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
+=======================    and Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+
+   Linux now has some ability to manipulate cursor appearance. Normally, you
+can set the size of hardware cursor (and also work around some ugly bugs in
+those miserable Trident cards--see #define TRIDENT_GLITCH in drivers/video/
+vgacon.c). You can now play a few new tricks:  you can make your cursor look
+like a non-blinking red block, make it inverse background of the character it's
+over or to highlight that character and still choose whether the original
+hardware cursor should remain visible or not.  There may be other things I have
+never thought of.
+
+   The cursor appearance is controlled by a "<ESC>[?1;2;3c" escape sequence
+where 1, 2 and 3 are parameters described below. If you omit any of them,
+they will default to zeroes.
+
+   Parameter 1 specifies cursor size (0=default, 1=invisible, 2=underline, ...,
+8=full block) + 16 if you want the software cursor to be applied + 32 if you
+want to always change the background color + 64 if you dislike having the
+background the same as the foreground.  Highlights are ignored for the last two
+flags.
+
+   The second parameter selects character attribute bits you want to change
+(by simply XORing them with the value of this parameter). On standard VGA,
+the high four bits specify background and the low four the foreground. In both
+groups, low three bits set color (as in normal color codes used by the console)
+and the most significant one turns on highlight (or sometimes blinking--it
+depends on the configuration of your VGA).
+
+   The third parameter consists of character attribute bits you want to set.
+Bit setting takes place before bit toggling, so you can simply clear a bit by 
+including it in both the set mask and the toggle mask.
+
+Examples:
+=========
+
+To get normal blinking underline, use: echo -e '\033[?2c'
+To get blinking block, use:            echo -e '\033[?6c'
+To get red non-blinking block, use:    echo -e '\033[?17;0;64c'

+ 91 - 0
Documentation/aoe/aoe.txt

@@ -0,0 +1,91 @@
+The EtherDrive (R) HOWTO for users of 2.6 kernels is found at ...
+
+  http://www.coraid.com/support/linux/EtherDrive-2.6-HOWTO.html
+
+  It has many tips and hints!
+
+CREATING DEVICE NODES
+
+  Users of udev should find the block device nodes created
+  automatically, but to create all the necessary device nodes, use the
+  udev configuration rules provided in udev.txt (in this directory).
+
+  There is a udev-install.sh script that shows how to install these
+  rules on your system.
+
+  If you are not using udev, two scripts are provided in
+  Documentation/aoe as examples of static device node creation for
+  using the aoe driver.
+
+    rm -rf /dev/etherd
+    sh Documentation/aoe/mkdevs.sh /dev/etherd
+
+  ... or to make just one shelf's worth of block device nodes ...
+
+    sh Documentation/aoe/mkshelf.sh /dev/etherd 0
+
+  There is also an autoload script that shows how to edit
+  /etc/modprobe.conf to ensure that the aoe module is loaded when
+  necessary.
+
+USING DEVICE NODES
+
+  "cat /dev/etherd/err" blocks, waiting for error diagnostic output,
+  like any retransmitted packets.
+
+  "echo eth2 eth4 > /dev/etherd/interfaces" tells the aoe driver to
+  limit ATA over Ethernet traffic to eth2 and eth4.  AoE traffic from
+  untrusted networks should be ignored as a matter of security.
+
+  "echo > /dev/etherd/discover" tells the driver to find out what AoE
+  devices are available.
+
+  These character devices may disappear and be replaced by sysfs
+  counterparts, so distribution maintainers are encouraged to create
+  scripts that use these devices.
+
+  The block devices are named like this:
+
+	e{shelf}.{slot}
+	e{shelf}.{slot}p{part}
+
+  ... so that "e0.2" is the third blade from the left (slot 2) in the
+  first shelf (shelf address zero).  That's the whole disk.  The first
+  partition on that disk would be "e0.2p1".
+
+USING SYSFS
+
+  Each aoe block device in /sys/block has the extra attributes of
+  state, mac, and netif.  The state attribute is "up" when the device
+  is ready for I/O and "down" if detected but unusable.  The
+  "down,closewait" state shows that the device is still open and
+  cannot come up again until it has been closed.
+
+  The mac attribute is the ethernet address of the remote AoE device.
+  The netif attribute is the network interface on the localhost
+  through which we are communicating with the remote AoE device.
+
+  There is a script in this directory that formats this information
+  in a convenient way.
+
+  root@makki root# sh Documentation/aoe/status.sh 
+     e10.0            eth3              up
+     e10.1            eth3              up
+     e10.2            eth3              up
+     e10.3            eth3              up
+     e10.4            eth3              up
+     e10.5            eth3              up
+     e10.6            eth3              up
+     e10.7            eth3              up
+     e10.8            eth3              up
+     e10.9            eth3              up
+      e4.0            eth1              up
+      e4.1            eth1              up
+      e4.2            eth1              up
+      e4.3            eth1              up
+      e4.4            eth1              up
+      e4.5            eth1              up
+      e4.6            eth1              up
+      e4.7            eth1              up
+      e4.8            eth1              up
+      e4.9            eth1              up

+ 17 - 0
Documentation/aoe/autoload.sh

@@ -0,0 +1,17 @@
+#!/bin/sh
+# set aoe to autoload by installing the
+# aliases in /etc/modprobe.conf
+
+f=/etc/modprobe.conf
+
+if test ! -r $f || test ! -w $f; then
+	echo "cannot configure $f for module autoloading" 1>&2
+	exit 1
+fi
+
+grep major-152 $f >/dev/null
+if [ $? = 1 ]; then
+	echo alias block-major-152 aoe >> $f
+	echo alias char-major-152 aoe >> $f
+fi
+

+ 36 - 0
Documentation/aoe/mkdevs.sh

@@ -0,0 +1,36 @@
+#!/bin/sh
+
+n_shelves=${n_shelves:-10}
+n_partitions=${n_partitions:-16}
+
+if test "$#" != "1"; then
+	echo "Usage: sh `basename $0` {dir}" 1>&2
+	exit 1
+fi
+dir=$1
+
+MAJOR=152
+
+echo "Creating AoE devnode files in $dir ..."
+
+set -e
+
+mkdir -p $dir
+
+# (Status info is in sysfs.  See status.sh.)
+# rm -f $dir/stat
+# mknod -m 0400 $dir/stat c $MAJOR 1
+rm -f $dir/err
+mknod -m 0400 $dir/err c $MAJOR 2
+rm -f $dir/discover
+mknod -m 0200 $dir/discover c $MAJOR 3
+rm -f $dir/interfaces
+mknod -m 0200 $dir/interfaces c $MAJOR 4
+
+export n_partitions
+mkshelf=`echo $0 | sed 's!mkdevs!mkshelf!'`
+i=0
+while test $i -lt $n_shelves; do
+	sh -xc "sh $mkshelf $dir $i"
+	i=`expr $i + 1`
+done

+ 25 - 0
Documentation/aoe/mkshelf.sh

@@ -0,0 +1,25 @@
+#! /bin/sh
+
+if test "$#" != "2"; then
+	echo "Usage: sh `basename $0` {dir} {shelfaddress}" 1>&2
+	exit 1
+fi
+n_partitions=${n_partitions:-16}
+dir=$1
+shelf=$2
+MAJOR=152
+
+set -e
+
+minor=`echo 10 \* $shelf \* $n_partitions | bc`
+endp=`echo $n_partitions - 1 | bc`
+for slot in `seq 0 9`; do
+	for part in `seq 0 $endp`; do
+		name=e$shelf.$slot
+		test "$part" != "0" && name=${name}p$part
+		rm -f $dir/$name
+		mknod -m 0660 $dir/$name b $MAJOR $minor
+
+		minor=`expr $minor + 1`
+	done
+done

+ 31 - 0
Documentation/aoe/status.sh

@@ -0,0 +1,31 @@
+#! /bin/sh
+# collate and present sysfs information about AoE storage
+
+set -e
+format="%8s\t%8s\t%8s\n"
+me=`basename $0`
+sysd=${sysfs_dir:-/sys}
+
+# printf "$format" device mac netif state
+
+# Suse 9.1 Pro doesn't put /sys in /etc/mtab
+#test -z "`mount | grep sysfs`" && {
+test ! -d "$sysd/block" && {
+	echo "$me Error: sysfs is not mounted" 1>&2
+	exit 1
+}
+test -z "`lsmod | grep '^aoe'`" && {
+	echo  "$me Error: aoe module is not loaded" 1>&2
+	exit 1
+}
+
+for d in `ls -d $sysd/block/etherd* 2>/dev/null | grep -v p` end; do
+	# maybe ls comes up empty, so we use "end"
+	test $d = end && continue
+
+	dev=`echo "$d" | sed 's/.*!//'`
+	printf "$format" \
+		"$dev" \
+		"`cat \"$d/netif\"`" \
+		"`cat \"$d/state\"`"
+done | sort

+ 26 - 0
Documentation/aoe/udev-install.sh

@@ -0,0 +1,26 @@
+# install the aoe-specific udev rules from udev.txt into 
+# the system's udev configuration
+# 
+
+me="`basename $0`"
+
+# find udev.conf, often /etc/udev/udev.conf
+# (or environment can specify where to find udev.conf)
+#
+if test -z "$conf"; then
+	if test -r /etc/udev/udev.conf; then
+		conf=/etc/udev/udev.conf
+	else
+		conf="`find /etc -type f -name udev.conf 2> /dev/null`"
+		if test -z "$conf" || test ! -r "$conf"; then
+			echo "$me Error: no udev.conf found" 1>&2
+			exit 1
+		fi
+	fi
+fi
+
+# find the directory where udev rules are stored, often
+# /etc/udev/rules.d
+#
+rules_d="`sed -n '/^udev_rules=/{ s!udev_rules=!!; s!\"!!g; p; }' $conf`"
+test "$rules_d" && sh -xc "cp `dirname $0`/udev.txt $rules_d/60-aoe.rules"

+ 23 - 0
Documentation/aoe/udev.txt

@@ -0,0 +1,23 @@
+# These rules tell udev what device nodes to create for aoe support.
+# They may be installed along the following lines (adjusted to what
+# you see on your system).
+# 
+#   ecashin@makki ~$ su
+#   Password:
+#   bash# find /etc -type f -name udev.conf
+#   /etc/udev/udev.conf
+#   bash# grep udev_rules= /etc/udev/udev.conf
+#   udev_rules="/etc/udev/rules.d/"
+#   bash# ls /etc/udev/rules.d/
+#   10-wacom.rules  50-udev.rules
+#   bash# cp /path/to/linux-2.6.xx/Documentation/aoe/udev.txt \
+#           /etc/udev/rules.d/60-aoe.rules
+#  
+
+# aoe char devices
+SUBSYSTEM="aoe", KERNEL="discover",	NAME="etherd/%k", GROUP="disk", MODE="0220"
+SUBSYSTEM="aoe", KERNEL="err",		NAME="etherd/%k", GROUP="disk", MODE="0440"
+SUBSYSTEM="aoe", KERNEL="interfaces",	NAME="etherd/%k", GROUP="disk", MODE="0220"
+
+# aoe block devices     
+KERNEL="etherd*",       NAME="%k", GROUP="disk"

+ 20 - 0
Documentation/arm/00-INDEX

@@ -0,0 +1,20 @@
+00-INDEX
+	- this file
+Booting
+	- requirements for booting
+Interrupts
+	- ARM Interrupt subsystem documentation
+Netwinder
+	- Netwinder specific documentation
+README
+	- General ARM documentation
+SA1100
+	- SA1100 documentation
+XScale
+	- XScale documentation
+empeg
+	- Empeg documentation
+mem_alignment
+	- alignment abort handler documentation
+nwfpe
+	- NWFPE floating point emulator documentation

+ 141 - 0
Documentation/arm/Booting

@@ -0,0 +1,141 @@
+			Booting ARM Linux
+			=================
+
+Author:	Russell King
+Date  : 18 May 2002
+
+The following documentation is relevant to 2.4.18-rmk6 and beyond.
+
+In order to boot ARM Linux, you require a boot loader, which is a small
+program that runs before the main kernel.  The boot loader is expected
+to initialise various devices, and eventually call the Linux kernel,
+passing information to the kernel.
+
+Essentially, the boot loader should provide (as a minimum) the
+following:
+
+1. Setup and initialise the RAM.
+2. Initialise one serial port.
+3. Detect the machine type.
+4. Setup the kernel tagged list.
+5. Call the kernel image.
+
+
+1. Setup and initialise RAM
+---------------------------
+
+Existing boot loaders:		MANDATORY
+New boot loaders:		MANDATORY
+
+The boot loader is expected to find and initialise all RAM that the
+kernel will use for volatile data storage in the system.  It performs
+this in a machine dependent manner.  (It may use internal algorithms
+to automatically locate and size all RAM, or it may use knowledge of
+the RAM in the machine, or any other method the boot loader designer
+sees fit.)
+
+
+2. Initialise one serial port
+-----------------------------
+
+Existing boot loaders:		OPTIONAL, RECOMMENDED
+New boot loaders:		OPTIONAL, RECOMMENDED
+
+The boot loader should initialise and enable one serial port on the
+target.  This allows the kernel serial driver to automatically detect
+which serial port it should use for the kernel console (generally
+used for debugging purposes, or communication with the target.)
+
+As an alternative, the boot loader can pass the relevant 'console='
+option to the kernel via the tagged lists specifying the port, and
+serial format options as described in
+
+       Documentation/kernel-parameters.txt.
+
+
+3. Detect the machine type
+--------------------------
+
+Existing boot loaders:		OPTIONAL
+New boot loaders:		MANDATORY
+
+The boot loader should detect the machine type its running on by some
+method.  Whether this is a hard coded value or some algorithm that
+looks at the connected hardware is beyond the scope of this document.
+The boot loader must ultimately be able to provide a MACH_TYPE_xxx
+value to the kernel. (see linux/arch/arm/tools/mach-types).
+
+
+4. Setup the kernel tagged list
+-------------------------------
+
+Existing boot loaders:		OPTIONAL, HIGHLY RECOMMENDED
+New boot loaders:		MANDATORY
+
+The boot loader must create and initialise the kernel tagged list.
+A valid tagged list starts with ATAG_CORE and ends with ATAG_NONE.
+The ATAG_CORE tag may or may not be empty.  An empty ATAG_CORE tag
+has the size field set to '2' (0x00000002).  The ATAG_NONE must set
+the size field to zero.
+
+Any number of tags can be placed in the list.  It is undefined
+whether a repeated tag appends to the information carried by the
+previous tag, or whether it replaces the information in its
+entirety; some tags behave as the former, others the latter.
+
+The boot loader must pass at a minimum the size and location of
+the system memory, and root filesystem location.  Therefore, the
+minimum tagged list should look:
+
+	+-----------+
+base ->	| ATAG_CORE |  |
+	+-----------+  |
+	| ATAG_MEM  |  | increasing address
+	+-----------+  |
+	| ATAG_NONE |  |
+	+-----------+  v
+
+The tagged list should be stored in system RAM.
+
+The tagged list must be placed in a region of memory where neither
+the kernel decompressor nor initrd 'bootp' program will overwrite
+it.  The recommended placement is in the first 16KiB of RAM.
+
+5. Calling the kernel image
+---------------------------
+
+Existing boot loaders:		MANDATORY
+New boot loaders:		MANDATORY
+
+There are two options for calling the kernel zImage.  If the zImage
+is stored in flash, and is linked correctly to be run from flash,
+then it is legal for the boot loader to call the zImage in flash
+directly.
+
+The zImage may also be placed in system RAM (at any location) and
+called there.  Note that the kernel uses 16K of RAM below the image
+to store page tables.  The recommended placement is 32KiB into RAM.
+
+In either case, the following conditions must be met:
+
+- Quiesce all DMA capable devicess so that memory does not get
+  corrupted by bogus network packets or disk data. This will save
+  you many hours of debug.
+
+- CPU register settings
+  r0 = 0,
+  r1 = machine type number discovered in (3) above.
+  r2 = physical address of tagged list in system RAM.
+
+- CPU mode
+  All forms of interrupts must be disabled (IRQs and FIQs)
+  The CPU must be in SVC mode.  (A special exception exists for Angel)
+
+- Caches, MMUs
+  The MMU must be off.
+  Instruction cache may be on or off.
+  Data cache must be off.
+
+- The boot loader is expected to call the kernel image by jumping
+  directly to the first instruction of the kernel image.
+

+ 69 - 0
Documentation/arm/IXP2000

@@ -0,0 +1,69 @@
+
+-------------------------------------------------------------------------
+Release Notes for Linux on Intel's IXP2000 Network Processor
+
+Maintained by Deepak Saxena <dsaxena@plexity.net>
+-------------------------------------------------------------------------
+
+1. Overview
+
+Intel's IXP2000 family of NPUs (IXP2400, IXP2800, IXP2850) is designed
+for high-performance network applications such high-availability
+telecom systems. In addition to an XScale core, it contains up to 8
+"MicroEngines" that run special code, several high-end networking 
+interfaces (UTOPIA, SPI, etc), a PCI host bridge, one serial port,
+flash interface, and some other odds and ends. For more information, see:
+
+http://developer.intel.com/design/network/products/npfamily/ixp2xxx.htm
+
+2. Linux Support
+
+Linux currently supports the following features on the IXP2000 NPUs:
+
+- On-chip serial
+- PCI
+- Flash (MTD/JFFS2)
+- I2C through GPIO
+- Timers (watchdog, OS)
+
+That is about all we can support under Linux ATM b/c the core networking
+components of the chip are accessed via Intel's closed source SDK. 
+Please contact Intel directly on issues with using those. There is
+also a mailing list run by some folks at Princeton University that might
+be of help:  https://lists.cs.princeton.edu/mailman/listinfo/ixp2xxx
+
+WHATEVER YOU DO, DO NOT POST EMAIL TO THE LINUX-ARM OR LINUX-ARM-KERNEL
+MAILING LISTS REGARDING THE INTEL SDK.
+
+3. Supported Platforms
+
+- Intel IXDP2400 Reference Platform
+- Intel IXDP2800 Reference Platform
+- Intel IXDP2401 Reference Platform
+- Intel IXDP2801 Reference Platform
+- RadiSys ENP-2611
+
+4. Usage Notes
+
+- The IXP2000 platforms usually have rather complex PCI bus topologies
+  with large memory space requirements. In addition, b/c of the way the
+  Intel SDK is designed, devices are enumerated in a very specific
+  way. B/c of this this, we use "pci=firmware" option in the kernel
+  command line so that we do not re-enumerate the bus.
+
+- IXDP2x01 systems have variable clock tick rates that we cannot determine 
+  via HW registers. The "ixdp2x01_clk=XXX" cmd line options allow you
+  to pass the clock rate to the board port.
+
+5. Thanks
+
+The IXP2000 work has been funded by Intel Corp. and MontaVista Software, Inc.
+
+The following people have contributed patches/comments/etc:
+
+Naeem F. Afzal
+Lennert Buytenhek
+Jeffrey Daly
+
+-------------------------------------------------------------------------
+Last Update: 8/09/2004

+ 174 - 0
Documentation/arm/IXP4xx

@@ -0,0 +1,174 @@
+
+-------------------------------------------------------------------------
+Release Notes for Linux on Intel's IXP4xx Network Processor
+
+Maintained by Deepak Saxena <dsaxena@plexity.net>
+-------------------------------------------------------------------------
+
+1. Overview
+
+Intel's IXP4xx network processor is a highly integrated SOC that
+is targeted for network applications, though it has become popular 
+in industrial control and other areas due to low cost and power
+consumption. The IXP4xx family currently consists of several processors
+that support different network offload functions such as encryption,
+routing, firewalling, etc. The IXP46x family is an updated version which
+supports faster speeds, new memory and flash configurations, and more
+integration such as an on-chip I2C controller.
+
+For more information on the various versions of the CPU, see:
+
+   http://developer.intel.com/design/network/products/npfamily/ixp4xx.htm
+
+Intel also made the IXCP1100 CPU for sometime which is an IXP4xx 
+stripped of much of the network intelligence.
+
+2. Linux Support
+
+Linux currently supports the following features on the IXP4xx chips:
+
+- Dual serial ports
+- PCI interface
+- Flash access (MTD/JFFS)
+- I2C through GPIO on IXP42x
+- GPIO for input/output/interrupts 
+  See include/asm-arm/arch-ixp4xx/platform.h for access functions.
+- Timers (watchdog, OS)
+
+The following components of the chips are not supported by Linux and
+require the use of Intel's propietary CSR softare:
+
+- USB device interface
+- Network interfaces (HSS, Utopia, NPEs, etc)
+- Network offload functionality
+
+If you need to use any of the above, you need to download Intel's
+software from:
+
+   http://developer.intel.com/design/network/products/npfamily/ixp425swr1.htm
+
+DO NOT POST QUESTIONS TO THE LINUX MAILING LISTS REGARDING THE PROPIETARY
+SOFTWARE.
+
+There are several websites that provide directions/pointers on using
+Intel's software:
+
+http://ixp4xx-osdg.sourceforge.net/ 
+   Open Source Developer's Guide for using uClinux and the Intel libraries 
+
+http://gatewaymaker.sourceforge.net/ 
+   Simple one page summary of building a gateway using an IXP425 and Linux
+
+http://ixp425.sourceforge.net/
+   ATM device driver for IXP425 that relies on Intel's libraries
+
+3. Known Issues/Limitations
+
+3a. Limited inbound PCI window
+
+The IXP4xx family allows for up to 256MB of memory but the PCI interface
+can only expose 64MB of that memory to the PCI bus. This means that if
+you are running with > 64MB, all PCI buffers outside of the accessible
+range will be bounced using the routines in arch/arm/common/dmabounce.c.
+   
+3b. Limited outbound PCI window
+
+IXP4xx provides two methods of accessing PCI memory space:
+
+1) A direct mapped window from 0x48000000 to 0x4bffffff (64MB).
+   To access PCI via this space, we simply ioremap() the BAR
+   into the kernel and we can use the standard read[bwl]/write[bwl]
+   macros. This is the preffered method due to speed but it
+   limits the system to just 64MB of PCI memory. This can be 
+   problamatic if using video cards and other memory-heavy devices.
+          
+2) If > 64MB of memory space is required, the IXP4xx can be 
+   configured to use indirect registers to access PCI This allows 
+   for up to 128MB (0x48000000 to 0x4fffffff) of memory on the bus. 
+   The disadvantadge of this is that every PCI access requires 
+   three local register accesses plus a spinlock, but in some 
+   cases the performance hit is acceptable. In addition, you cannot 
+   mmap() PCI devices in this case due to the indirect nature
+   of the PCI window.
+
+By default, the direct method is used for performance reasons. If
+you need more PCI memory, enable the IXP4XX_INDIRECT_PCI config option.
+
+3c. GPIO as Interrupts
+
+Currently the code only handles level-sensitive GPIO interrupts 
+
+4. Supported platforms
+
+ADI Engineering Coyote Gateway Reference Platform
+http://www.adiengineering.com/productsCoyote.html
+
+   The ADI Coyote platform is reference design for those building 
+   small residential/office gateways. One NPE is connected to a 10/100
+   interface, one to 4-port 10/100 switch, and the third to and ADSL
+   interface. In addition, it also supports to POTs interfaces connected
+   via SLICs. Note that those are not supported by Linux ATM. Finally,
+   the platform has two mini-PCI slots used for 802.11[bga] cards.
+   Finally, there is an IDE port hanging off the expansion bus.
+
+Gateworks Avila Network Platform
+http://www.gateworks.com/avila_sbc.htm
+
+   The Avila platform is basically and IXDP425 with the 4 PCI slots
+   replaced with mini-PCI slots and a CF IDE interface hanging off
+   the expansion bus.
+
+Intel IXDP425 Development Platform
+http://developer.intel.com/design/network/products/npfamily/ixdp425.htm
+
+   This is Intel's standard reference platform for the IXDP425 and is 
+   also known as the Richfield board. It contains 4 PCI slots, 16MB
+   of flash, two 10/100 ports and one ADSL port.
+
+Intel IXDP465 Development Platform
+http://developer.intel.com/design/network/products/npfamily/ixdp465.htm
+
+   This is basically an IXDP425 with an IXP465 and 32M of flash instead
+   of just 16.
+
+Intel IXDPG425 Development Platform
+
+   This is basically and ADI Coyote board with a NEC EHCI controller
+   added. One issue with this board is that the mini-PCI slots only
+   have the 3.3v line connected, so you can't use a PCI to mini-PCI
+   adapter with an E100 card. So to NFS root you need to use either
+   the CSR or a WiFi card and a ramdisk that BOOTPs and then does
+   a pivot_root to NFS.
+
+Motorola PrPMC1100 Processor Mezanine Card
+http://www.fountainsys.com/datasheet/PrPMC1100.pdf
+
+   The PrPMC1100 is based on the IXCP1100 and is meant to plug into
+   and IXP2400/2800 system to act as the system controller. It simply
+   contains a CPU and 16MB of flash on the board and needs to be
+   plugged into a carrier board to function. Currently Linux only
+   supports the Motorola PrPMC carrier board for this platform.
+   See https://mcg.motorola.com/us/ds/pdf/ds0144.pdf for info
+   on the carrier board.
+
+5. TODO LIST
+
+- Add support for Coyote IDE
+- Add support for edge-based GPIO interrupts
+- Add support for CF IDE on expansion bus
+
+6. Thanks
+
+The IXP4xx work has been funded by Intel Corp. and MontaVista Software, Inc.
+
+The following people have contributed patches/comments/etc:
+
+Lennerty Buytenhek
+Lutz Jaenicke
+Justin Mayfield
+Robert E. Ranslam
+[I know I've forgotten others, please email me to be added] 
+
+-------------------------------------------------------------------------
+
+Last Update: 01/04/2005

+ 173 - 0
Documentation/arm/Interrupts

@@ -0,0 +1,173 @@
+2.5.2-rmk5
+----------
+
+This is the first kernel that contains a major shake up of some of the
+major architecture-specific subsystems.
+
+Firstly, it contains some pretty major changes to the way we handle the
+MMU TLB.  Each MMU TLB variant is now handled completely separately -
+we have TLB v3, TLB v4 (without write buffer), TLB v4 (with write buffer),
+and finally TLB v4 (with write buffer, with I TLB invalidate entry).
+There is more assembly code inside each of these functions, mainly to
+allow more flexible TLB handling for the future.
+
+Secondly, the IRQ subsystem.
+
+The 2.5 kernels will be having major changes to the way IRQs are handled.
+Unfortunately, this means that machine types that touch the irq_desc[]
+array (basically all machine types) will break, and this means every
+machine type that we currently have.
+
+Lets take an example.  On the Assabet with Neponset, we have:
+
+                  GPIO25                 IRR:2
+        SA1100 ------------> Neponset -----------> SA1111
+                                         IIR:1
+                                      -----------> USAR
+                                         IIR:0
+                                      -----------> SMC9196
+
+The way stuff currently works, all SA1111 interrupts are mutually
+exclusive of each other - if you're processing one interrupt from the
+SA1111 and another comes in, you have to wait for that interrupt to
+finish processing before you can service the new interrupt.  Eg, an
+IDE PIO-based interrupt on the SA1111 excludes all other SA1111 and
+SMC9196 interrupts until it has finished transferring its multi-sector
+data, which can be a long time.  Note also that since we loop in the
+SA1111 IRQ handler, SA1111 IRQs can hold off SMC9196 IRQs indefinitely.
+
+
+The new approach brings several new ideas...
+
+We introduce the concept of a "parent" and a "child".  For example,
+to the Neponset handler, the "parent" is GPIO25, and the "children"d
+are SA1111, SMC9196 and USAR.
+
+We also bring the idea of an IRQ "chip" (mainly to reduce the size of
+the irqdesc array).  This doesn't have to be a real "IC"; indeed the
+SA11x0 IRQs are handled by two separate "chip" structures, one for
+GPIO0-10, and another for all the rest.  It is just a container for
+the various operations (maybe this'll change to a better name).
+This structure has the following operations:
+
+struct irqchip {
+        /*
+         * Acknowledge the IRQ.
+         * If this is a level-based IRQ, then it is expected to mask the IRQ
+         * as well.
+         */
+        void (*ack)(unsigned int irq);
+        /*
+         * Mask the IRQ in hardware.
+         */
+        void (*mask)(unsigned int irq);
+        /*
+         * Unmask the IRQ in hardware.
+         */
+        void (*unmask)(unsigned int irq);
+        /*
+         * Re-run the IRQ
+         */
+        void (*rerun)(unsigned int irq);
+        /*
+         * Set the type of the IRQ.
+         */
+        int (*type)(unsigned int irq, unsigned int, type);
+};
+
+ack    - required.  May be the same function as mask for IRQs
+         handled by do_level_IRQ.
+mask   - required.
+unmask - required.
+rerun  - optional.  Not required if you're using do_level_IRQ for all
+         IRQs that use this 'irqchip'.  Generally expected to re-trigger
+         the hardware IRQ if possible.  If not, may call the handler
+	 directly.
+type   - optional.  If you don't support changing the type of an IRQ,
+         it should be null so people can detect if they are unable to
+         set the IRQ type.
+
+For each IRQ, we keep the following information:
+
+        - "disable" depth (number of disable_irq()s without enable_irq()s)
+        - flags indicating what we can do with this IRQ (valid, probe,
+          noautounmask) as before
+        - status of the IRQ (probing, enable, etc)
+        - chip
+        - per-IRQ handler
+        - irqaction structure list
+
+The handler can be one of the 3 standard handlers - "level", "edge" and
+"simple", or your own specific handler if you need to do something special.
+
+The "level" handler is what we currently have - its pretty simple.
+"edge" knows about the brokenness of such IRQ implementations - that you
+need to leave the hardware IRQ enabled while processing it, and queueing
+further IRQ events should the IRQ happen again while processing.  The
+"simple" handler is very basic, and does not perform any hardware
+manipulation, nor state tracking.  This is useful for things like the
+SMC9196 and USAR above.
+
+So, what's changed?
+
+1. Machine implementations must not write to the irqdesc array.
+
+2. New functions to manipulate the irqdesc array.  The first 4 are expected
+   to be useful only to machine specific code.  The last is recommended to
+   only be used by machine specific code, but may be used in drivers if
+   absolutely necessary.
+
+        set_irq_chip(irq,chip)
+
+                Set the mask/unmask methods for handling this IRQ
+
+        set_irq_handler(irq,handler)
+
+                Set the handler for this IRQ (level, edge, simple)
+
+        set_irq_chained_handler(irq,handler)
+
+                Set a "chained" handler for this IRQ - automatically
+                enables this IRQ (eg, Neponset and SA1111 handlers).
+
+        set_irq_flags(irq,flags)
+
+                Set the valid/probe/noautoenable flags.
+
+        set_irq_type(irq,type)
+
+                Set active the IRQ edge(s)/level.  This replaces the
+                SA1111 INTPOL manipulation, and the set_GPIO_IRQ_edge()
+                function.  Type should be one of the following:
+
+                #define IRQT_NOEDGE     (0)
+                #define IRQT_RISING     (__IRQT_RISEDGE)
+                #define IRQT_FALLING    (__IRQT_FALEDGE)
+                #define IRQT_BOTHEDGE   (__IRQT_RISEDGE|__IRQT_FALEDGE)
+                #define IRQT_LOW        (__IRQT_LOWLVL)
+                #define IRQT_HIGH       (__IRQT_HIGHLVL)
+
+3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type.
+
+4. Direct access to SA1111 INTPOL is depreciated.  Use set_irq_type instead.
+
+5. A handler is expected to perform any necessary acknowledgement of the
+   parent IRQ via the correct chip specific function.  For instance, if
+   the SA1111 is directly connected to a SA1110 GPIO, then you should
+   acknowledge the SA1110 IRQ each time you re-read the SA1111 IRQ status.
+
+6. For any child which doesn't have its own IRQ enable/disable controls
+   (eg, SMC9196), the handler must mask or acknowledge the parent IRQ
+   while the child handler is called, and the child handler should be the
+   "simple" handler (not "edge" nor "level").  After the handler completes,
+   the parent IRQ should be unmasked, and the status of all children must
+   be re-checked for pending events.  (see the Neponset IRQ handler for
+   details).
+
+7. fixup_irq() is gone, as is include/asm-arm/arch-*/irq.h
+
+Please note that this will not solve all problems - some of them are
+hardware based.  Mixing level-based and edge-based IRQs on the same
+parent signal (eg neponset) is one such area where a software based
+solution can't provide the full answer to low IRQ latency.
+

+ 78 - 0
Documentation/arm/Netwinder

@@ -0,0 +1,78 @@
+NetWinder specific documentation
+================================
+
+The NetWinder is a small low-power computer, primarily designed
+to run Linux.  It is based around the StrongARM RISC processor,
+DC21285 PCI bridge, with PC-type hardware glued around it.
+
+Port usage
+==========
+
+Min    - Max	Description
+---------------------------
+0x0000 - 0x000f	DMA1
+0x0020 - 0x0021	PIC1
+0x0060 - 0x006f	Keyboard
+0x0070 - 0x007f	RTC
+0x0080 - 0x0087	DMA1
+0x0088 - 0x008f	DMA2
+0x00a0 - 0x00a3	PIC2
+0x00c0 - 0x00df	DMA2
+0x0180 - 0x0187	IRDA
+0x01f0 - 0x01f6	ide0
+0x0201		Game port
+0x0203		RWA010 configuration read
+0x0220 - ?	SoundBlaster
+0x0250 - ?	WaveArtist
+0x0279		RWA010 configuration index
+0x02f8 - 0x02ff	Serial ttyS1
+0x0300 - 0x031f	Ether10
+0x0338		GPIO1
+0x033a		GPIO2
+0x0370 - 0x0371	W83977F configuration registers
+0x0388 - ?	AdLib
+0x03c0 - 0x03df	VGA
+0x03f6		ide0
+0x03f8 - 0x03ff	Serial ttyS0
+0x0400 - 0x0408	DC21143
+0x0480 - 0x0487	DMA1
+0x0488 - 0x048f	DMA2
+0x0a79		RWA010 configuration write
+0xe800 - 0xe80f	ide0/ide1 BM DMA
+
+
+Interrupt usage
+===============
+
+IRQ	type	Description
+---------------------------
+ 0	ISA	100Hz timer
+ 1	ISA	Keyboard
+ 2	ISA	cascade
+ 3	ISA	Serial ttyS1
+ 4	ISA	Serial ttyS0
+ 5	ISA	PS/2 mouse
+ 6	ISA	IRDA
+ 7	ISA	Printer
+ 8	ISA	RTC alarm
+ 9	ISA
+10	ISA	GP10 (Orange reset button)
+11	ISA
+12	ISA	WaveArtist
+13	ISA
+14	ISA	hda1
+15	ISA
+
+DMA usage
+=========
+
+DMA	type	Description
+---------------------------
+ 0	ISA	IRDA
+ 1	ISA
+ 2	ISA	cascade
+ 3	ISA	WaveArtist
+ 4	ISA
+ 5	ISA
+ 6	ISA
+ 7	ISA	WaveArtist

+ 135 - 0
Documentation/arm/Porting

@@ -0,0 +1,135 @@
+Taken from list archive at http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2001-July/004064.html
+
+Initial definitions
+-------------------
+
+The following symbol definitions rely on you knowing the translation that
+__virt_to_phys() does for your machine.  This macro converts the passed
+virtual address to a physical address.  Normally, it is simply:
+
+		phys = virt - PAGE_OFFSET + PHYS_OFFSET
+
+
+Decompressor Symbols
+--------------------
+
+ZTEXTADDR
+	Start address of decompressor.  There's no point in talking about
+	virtual or physical addresses here, since the MMU will be off at
+	the time when you call the decompressor code.  You normally call
+	the kernel at this address to start it booting.  This doesn't have
+	to be located in RAM, it can be in flash or other read-only or
+	read-write addressable medium.
+
+ZBSSADDR
+	Start address of zero-initialised work area for the decompressor.
+	This must be pointing at RAM.  The decompressor will zero initialise
+	this for you.  Again, the MMU will be off.
+
+ZRELADDR
+	This is the address where the decompressed kernel will be written,
+	and eventually executed.  The following constraint must be valid:
+
+		__virt_to_phys(TEXTADDR) == ZRELADDR
+
+	The initial part of the kernel is carefully coded to be position
+	independent.
+
+INITRD_PHYS
+	Physical address to place the initial RAM disk.  Only relevant if
+	you are using the bootpImage stuff (which only works on the old
+	struct param_struct).
+
+INITRD_VIRT
+	Virtual address of the initial RAM disk.  The following  constraint
+	must be valid:
+
+		__virt_to_phys(INITRD_VIRT) == INITRD_PHYS
+
+PARAMS_PHYS
+	Physical address of the struct param_struct or tag list, giving the
+	kernel various parameters about its execution environment.
+
+
+Kernel Symbols
+--------------
+
+PHYS_OFFSET
+	Physical start address of the first bank of RAM.
+
+PAGE_OFFSET
+	Virtual start address of the first bank of RAM.  During the kernel
+	boot phase, virtual address PAGE_OFFSET will be mapped to physical
+	address PHYS_OFFSET, along with any other mappings you supply.
+	This should be the same value as TASK_SIZE.
+
+TASK_SIZE
+	The maximum size of a user process in bytes.  Since user space
+	always starts at zero, this is the maximum address that a user
+	process can access+1.  The user space stack grows down from this
+	address.
+
+	Any virtual address below TASK_SIZE is deemed to be user process
+	area, and therefore managed dynamically on a process by process
+	basis by the kernel.  I'll call this the user segment.
+
+	Anything above TASK_SIZE is common to all processes.  I'll call
+	this the kernel segment.
+
+	(In other words, you can't put IO mappings below TASK_SIZE, and
+	hence PAGE_OFFSET).
+
+TEXTADDR
+	Virtual start address of kernel, normally PAGE_OFFSET + 0x8000.
+	This is where the kernel image ends up.  With the latest kernels,
+	it must be located at 32768 bytes into a 128MB region.  Previous
+	kernels placed a restriction of 256MB here.
+
+DATAADDR
+	Virtual address for the kernel data segment.  Must not be defined
+	when using the decompressor.
+
+VMALLOC_START
+VMALLOC_END
+	Virtual addresses bounding the vmalloc() area.  There must not be
+	any static mappings in this area; vmalloc will overwrite them.
+	The addresses must also be in the kernel segment (see above).
+	Normally, the vmalloc() area starts VMALLOC_OFFSET bytes above the
+	last virtual RAM address (found using variable high_memory).
+
+VMALLOC_OFFSET
+	Offset normally incorporated into VMALLOC_START to provide a hole
+	between virtual RAM and the vmalloc area.  We do this to allow
+	out of bounds memory accesses (eg, something writing off the end
+	of the mapped memory map) to be caught.  Normally set to 8MB.
+
+Architecture Specific Macros
+----------------------------
+
+BOOT_MEM(pram,pio,vio)
+	`pram' specifies the physical start address of RAM.  Must always
+	be present, and should be the same as PHYS_OFFSET.
+
+	`pio' is the physical address of an 8MB region containing IO for
+	use with the debugging macros in arch/arm/kernel/debug-armv.S.
+
+	`vio' is the virtual address of the 8MB debugging region.
+
+	It is expected that the debugging region will be re-initialised
+	by the architecture specific code later in the code (via the
+	MAPIO function).
+
+BOOT_PARAMS
+	Same as, and see PARAMS_PHYS.
+
+FIXUP(func)
+	Machine specific fixups, run before memory subsystems have been
+	initialised.
+
+MAPIO(func)
+	Machine specific function to map IO areas (including the debug
+	region above).
+
+INITIRQ(func)
+	Machine specific function to initialise interrupts.
+

+ 198 - 0
Documentation/arm/README

@@ -0,0 +1,198 @@
+			   ARM Linux 2.6
+			   =============
+
+    Please check <ftp://ftp.arm.linux.org.uk/pub/armlinux> for
+    updates.
+
+Compilation of kernel
+---------------------
+
+  In order to compile ARM Linux, you will need a compiler capable of
+  generating ARM ELF code with GNU extensions.  GCC 2.95.1, EGCS
+  1.1.2, and GCC 3.3 are known to be good compilers.  Fortunately, you
+  needn't guess.  The kernel will report an error if your compiler is
+  a recognized offender.
+
+  To build ARM Linux natively, you shouldn't have to alter the ARCH = line
+  in the top level Makefile.  However, if you don't have the ARM Linux ELF
+  tools installed as default, then you should change the CROSS_COMPILE
+  line as detailed below.
+
+  If you wish to cross-compile, then alter the following lines in the top
+  level make file:
+
+    ARCH = <whatever>
+	with
+    ARCH = arm
+
+	and
+
+    CROSS_COMPILE=
+	to
+    CROSS_COMPILE=<your-path-to-your-compiler-without-gcc>
+	eg.
+    CROSS_COMPILE=arm-linux-
+
+  Do a 'make config', followed by 'make Image' to build the kernel 
+  (arch/arm/boot/Image).  A compressed image can be built by doing a 
+  'make zImage' instead of 'make Image'.
+
+
+Bug reports etc
+---------------
+
+  Please send patches to the patch system.  For more information, see
+  http://www.arm.linux.org.uk/patches/info.html  Always include some
+  explanation as to what the patch does and why it is needed.
+
+  Bug reports should be sent to linux-arm-kernel@lists.arm.linux.org.uk,
+  or submitted through the web form at
+  http://www.arm.linux.org.uk/forms/solution.shtml
+
+  When sending bug reports, please ensure that they contain all relevant
+  information, eg. the kernel messages that were printed before/during
+  the problem, what you were doing, etc.
+
+
+Include files
+-------------
+
+  Several new include directories have been created under include/asm-arm,
+  which are there to reduce the clutter in the top-level directory.  These
+  directories, and their purpose is listed below:
+
+   arch-*	machine/platform specific header files
+   hardware	driver-internal ARM specific data structures/definitions
+   mach		descriptions of generic ARM to specific machine interfaces
+   proc-*	processor dependent header files (currently only two
+		categories)
+
+
+Machine/Platform support
+------------------------
+
+  The ARM tree contains support for a lot of different machine types.  To
+  continue supporting these differences, it has become necessary to split
+  machine-specific parts by directory.  For this, the machine category is
+  used to select which directories and files get included (we will use
+  $(MACHINE) to refer to the category)
+
+  To this end, we now have arch/arm/mach-$(MACHINE) directories which are
+  designed to house the non-driver files for a particular machine (eg, PCI,
+  memory management, architecture definitions etc).  For all future
+  machines, there should be a corresponding include/asm-arm/arch-$(MACHINE)
+  directory.
+
+
+Modules
+-------
+
+  Although modularisation is supported (and required for the FP emulator),
+  each module on an ARM2/ARM250/ARM3 machine when is loaded will take
+  memory up to the next 32k boundary due to the size of the pages.
+  Therefore, modularisation on these machines really worth it?
+
+  However, ARM6 and up machines allow modules to take multiples of 4k, and
+  as such Acorn RiscPCs and other architectures using these processors can
+  make good use of modularisation.
+
+
+ADFS Image files
+----------------
+
+  You can access image files on your ADFS partitions by mounting the ADFS
+  partition, and then using the loopback device driver.  You must have
+  losetup installed.
+
+  Please note that the PCEmulator DOS partitions have a partition table at
+  the start, and as such, you will have to give '-o offset' to losetup.
+
+
+Request to developers
+---------------------
+
+  When writing device drivers which include a separate assembler file, please
+  include it in with the C file, and not the arch/arm/lib directory.  This
+  allows the driver to be compiled as a loadable module without requiring
+  half the code to be compiled into the kernel image.
+
+  In general, try to avoid using assembler unless it is really necessary.  It
+  makes drivers far less easy to port to other hardware.
+
+
+ST506 hard drives
+-----------------
+
+  The ST506 hard drive controllers seem to be working fine (if a little
+  slowly).  At the moment they will only work off the controllers on an
+  A4x0's motherboard, but for it to work off a Podule just requires
+  someone with a podule to add the addresses for the IRQ mask and the
+  HDC base to the source.
+
+  As of 31/3/96 it works with two drives (you should get the ADFS
+  *configure harddrive set to 2). I've got an internal 20MB and a great
+  big external 5.25" FH 64MB drive (who could ever want more :-) ).
+
+  I've just got 240K/s off it (a dd with bs=128k); thats about half of what
+  RiscOS gets; but it's a heck of a lot better than the 50K/s I was getting
+  last week :-)
+
+  Known bug: Drive data errors can cause a hang; including cases where
+  the controller has fixed the error using ECC. (Possibly ONLY
+  in that case...hmm).
+
+
+1772 Floppy
+-----------
+  This also seems to work OK, but hasn't been stressed much lately.  It
+  hasn't got any code for disc change detection in there at the moment which
+  could be a bit of a problem!  Suggestions on the correct way to do this
+  are welcome.
+
+
+CONFIG_MACH_ and CONFIG_ARCH_
+-----------------------------
+  A change was made in 2003 to the macro names for new machines.
+  Historically, CONFIG_ARCH_ was used for the bonafide architecture,
+  e.g. SA1100, as well as implementations of the architecture,
+  e.g. Assabet.  It was decided to change the implementation macros
+  to read CONFIG_MACH_ for clarity.  Moreover, a retroactive fixup has
+  not been made because it would complicate patching.
+
+  Previous registrations may be found online.
+
+    <http://www.arm.linux.org.uk/developer/machines/>
+
+Kernel entry (head.S)
+--------------------------
+  The initial entry into the kernel is via head.S, which uses machine
+  independent code.  The machine is selected by the value of 'r1' on
+  entry, which must be kept unique.
+
+  Due to the large number of machines which the ARM port of Linux provides
+  for, we have a method to manage this which ensures that we don't end up
+  duplicating large amounts of code.
+
+  We group machine (or platform) support code into machine classes.  A
+  class typically based around one or more system on a chip devices, and
+  acts as a natural container around the actual implementations.  These
+  classes are given directories - arch/arm/mach-<class> and
+  include/asm-arm/arch-<class> - which contain the source files to
+  support the machine class.  This directories also contain any machine
+  specific supporting code.
+
+  For example, the SA1100 class is based upon the SA1100 and SA1110 SoC
+  devices, and contains the code to support the way the on-board and off-
+  board devices are used, or the device is setup, and provides that
+  machine specific "personality."
+
+  This fine-grained machine specific selection is controlled by the machine
+  type ID, which acts both as a run-time and a compile-time code selection
+  method.
+
+  You can register a new machine via the web site at:
+
+    <http://www.arm.linux.org.uk/developer/machines/>
+
+---
+Russell King (15/03/2004)

+ 43 - 0
Documentation/arm/SA1100/ADSBitsy

@@ -0,0 +1,43 @@
+ADS Bitsy Single Board Computer
+(It is different from Bitsy(iPAQ) of Compaq)
+
+For more details, contact Applied Data Systems or see
+http://www.applieddata.net/products.html
+
+The Linux support for this product has been provided by
+Woojung Huh <whuh@applieddata.net>
+
+Use 'make adsbitsy_config' before any 'make config'.
+This will set up defaults for ADS Bitsy support.
+
+The kernel zImage is linked to be loaded and executed at 0xc0400000.
+
+Linux can  be used with the ADS BootLoader that ships with the
+newer rev boards. See their documentation on how to load Linux.
+
+Supported peripherals:
+- SA1100 LCD frame buffer (8/16bpp...sort of)
+- SA1111 USB Master
+- SA1100 serial port
+- pcmcia, compact flash
+- touchscreen(ucb1200)
+- console on LCD screen
+- serial ports (ttyS[0-2])
+  - ttyS0 is default for serial console
+
+To do:
+- everything else!  :-)
+
+Notes:
+
+- The flash on board is divided into 3 partitions.
+  You should be careful to use flash on board.
+  It's partition is different from GraphicsClient Plus and GraphicsMaster
+
+- 16bpp mode requires a different cable than what ships with the board.
+  Contact ADS or look through the manual to wire your own. Currently,
+  if you compile with 16bit mode support and switch into a lower bpp
+  mode, the timing is off so the image is corrupted.  This will be
+  fixed soon.
+
+Any contribution can be sent to nico@cam.org and will be greatly welcome!

+ 301 - 0
Documentation/arm/SA1100/Assabet

@@ -0,0 +1,301 @@
+The Intel Assabet (SA-1110 evaluation) board
+============================================
+
+Please see:
+http://developer.intel.com/design/strong/quicklist/eval-plat/sa-1110.htm
+http://developer.intel.com/design/strong/guides/278278.htm
+
+Also some notes from John G Dorsey <jd5q@andrew.cmu.edu>:
+http://www.cs.cmu.edu/~wearable/software/assabet.html
+
+
+Building the kernel
+-------------------
+
+To build the kernel with current defaults:
+
+	make assabet_config
+	make oldconfig
+	make zImage
+
+The resulting kernel image should be available in linux/arch/arm/boot/zImage.
+
+
+Installing a bootloader
+-----------------------
+
+A couple of bootloaders able to boot Linux on Assabet are available:
+
+BLOB (http://www.lart.tudelft.nl/lartware/blob/)
+
+   BLOB is a bootloader used within the LART project.  Some contributed
+   patches were merged into BLOB to add support for Assabet.
+
+Compaq's Bootldr + John Dorsey's patch for Assabet support
+(http://www.handhelds.org/Compaq/bootldr.html)
+(http://www.wearablegroup.org/software/bootldr/)
+
+   Bootldr is the bootloader developed by Compaq for the iPAQ Pocket PC.
+   John Dorsey has produced add-on patches to add support for Assabet and
+   the JFFS filesystem.
+
+RedBoot (http://sources.redhat.com/redboot/)
+
+   RedBoot is a bootloader developed by Red Hat based on the eCos RTOS
+   hardware abstraction layer.  It supports Assabet amongst many other
+   hardware platforms.
+
+RedBoot is currently the recommended choice since it's the only one to have
+networking support, and is the most actively maintained.
+
+Brief examples on how to boot Linux with RedBoot are shown below.  But first
+you need to have RedBoot installed in your flash memory.  A known to work
+precompiled RedBoot binary is available from the following location:
+
+ftp://ftp.netwinder.org/users/n/nico/
+ftp://ftp.arm.linux.org.uk/pub/linux/arm/people/nico/
+ftp://ftp.handhelds.org/pub/linux/arm/sa-1100-patches/
+
+Look for redboot-assabet*.tgz.  Some installation infos are provided in
+redboot-assabet*.txt.
+
+
+Initial RedBoot configuration
+-----------------------------
+
+The commands used here are explained in The RedBoot User's Guide available
+on-line at http://sources.redhat.com/ecos/docs-latest/redboot/redboot.html.
+Please refer to it for explanations.
+
+If you have a CF network card (my Assabet kit contained a CF+ LP-E from
+Socket Communications Inc.), you should strongly consider using it for TFTP
+file transfers.  You must insert it before RedBoot runs since it can't detect
+it dynamically.
+
+To initialize the flash directory:
+
+	fis init -f
+
+To initialize the non-volatile settings, like whether you want to use BOOTP or
+a static IP address, etc, use this command:
+
+	fconfig -i
+
+
+Writing a kernel image into flash
+---------------------------------
+
+First, the kernel image must be loaded into RAM.  If you have the zImage file
+available on a TFTP server:
+
+	load zImage -r -b 0x100000
+
+If you rather want to use Y-Modem upload over the serial port:
+
+	load -m ymodem -r -b 0x100000
+
+To write it to flash:
+
+	fis create "Linux kernel" -b 0x100000 -l 0xc0000
+
+
+Booting the kernel
+------------------
+
+The kernel still requires a filesystem to boot.  A ramdisk image can be loaded
+as follows:
+
+	load ramdisk_image.gz -r -b 0x800000
+
+Again, Y-Modem upload can be used instead of TFTP by replacing the file name
+by '-y ymodem'.
+
+Now the kernel can be retrieved from flash like this:
+
+	fis load "Linux kernel"
+
+or loaded as described previously.  To boot the kernel:
+
+	exec -b 0x100000 -l 0xc0000
+
+The ramdisk image could be stored into flash as well, but there are better
+solutions for on-flash filesystems as mentioned below.
+
+
+Using JFFS2
+-----------
+
+Using JFFS2 (the Second Journalling Flash File System) is probably the most
+convenient way to store a writable filesystem into flash.  JFFS2 is used in
+conjunction with the MTD layer which is responsible for low-level flash
+management.  More information on the Linux MTD can be found on-line at:
+http://www.linux-mtd.infradead.org/.  A JFFS howto with some infos about
+creating JFFS/JFFS2 images is available from the same site.
+
+For instance, a sample JFFS2 image can be retrieved from the same FTP sites
+mentioned below for the precompiled RedBoot image.
+
+To load this file:
+
+	load sample_img.jffs2 -r -b 0x100000
+
+The result should look like:
+
+RedBoot> load sample_img.jffs2 -r -b 0x100000
+Raw file loaded 0x00100000-0x00377424
+
+Now we must know the size of the unallocated flash:
+
+	fis free
+
+Result:
+
+RedBoot> fis free
+  0x500E0000 .. 0x503C0000
+
+The values above may be different depending on the size of the filesystem and
+the type of flash.  See their usage below as an example and take care of
+substituting yours appropriately.
+
+We must determine some values:
+
+size of unallocated flash:	0x503c0000 - 0x500e0000 = 0x2e0000
+size of the filesystem image:	0x00377424 - 0x00100000 = 0x277424
+
+We want to fit the filesystem image of course, but we also want to give it all
+the remaining flash space as well.  To write it:
+
+	fis unlock -f 0x500E0000 -l 0x2e0000
+	fis erase -f 0x500E0000 -l 0x2e0000
+	fis write -b 0x100000 -l 0x277424 -f 0x500E0000
+	fis create "JFFS2" -n -f 0x500E0000 -l 0x2e0000
+
+Now the filesystem is associated to a MTD "partition" once Linux has discovered
+what they are in the boot process.  From Redboot, the 'fis list' command
+displays them:
+
+RedBoot> fis list
+Name              FLASH addr  Mem addr    Length      Entry point
+RedBoot           0x50000000  0x50000000  0x00020000  0x00000000
+RedBoot config    0x503C0000  0x503C0000  0x00020000  0x00000000
+FIS directory     0x503E0000  0x503E0000  0x00020000  0x00000000
+Linux kernel      0x50020000  0x00100000  0x000C0000  0x00000000
+JFFS2             0x500E0000  0x500E0000  0x002E0000  0x00000000
+
+However Linux should display something like:
+
+SA1100 flash: probing 32-bit flash bus
+SA1100 flash: Found 2 x16 devices at 0x0 in 32-bit mode
+Using RedBoot partition definition
+Creating 5 MTD partitions on "SA1100 flash":
+0x00000000-0x00020000 : "RedBoot"
+0x00020000-0x000e0000 : "Linux kernel"
+0x000e0000-0x003c0000 : "JFFS2"
+0x003c0000-0x003e0000 : "RedBoot config"
+0x003e0000-0x00400000 : "FIS directory"
+
+What's important here is the position of the partition we are interested in,
+which is the third one.  Within Linux, this correspond to /dev/mtdblock2.
+Therefore to boot Linux with the kernel and its root filesystem in flash, we
+need this RedBoot command:
+
+	fis load "Linux kernel"
+	exec -b 0x100000 -l 0xc0000 -c "root=/dev/mtdblock2"
+
+Of course other filesystems than JFFS might be used, like cramfs for example.
+You might want to boot with a root filesystem over NFS, etc.  It is also
+possible, and sometimes more convenient, to flash a filesystem directly from
+within Linux while booted from a ramdisk or NFS.  The Linux MTD repository has
+many tools to deal with flash memory as well, to erase it for example.  JFFS2
+can then be mounted directly on a freshly erased partition and files can be
+copied over directly.  Etc...
+
+
+RedBoot scripting
+-----------------
+
+All the commands above aren't so useful if they have to be typed in every
+time the Assabet is rebooted.  Therefore it's possible to automatize the boot
+process using RedBoot's scripting capability.
+
+For example, I use this to boot Linux with both the kernel and the ramdisk
+images retrieved from a TFTP server on the network:
+
+RedBoot> fconfig
+Run script at boot: false true
+Boot script:
+Enter script, terminate with empty line
+>> load zImage -r -b 0x100000
+>> load ramdisk_ks.gz -r -b 0x800000
+>> exec -b 0x100000 -l 0xc0000
+>>
+Boot script timeout (1000ms resolution): 3
+Use BOOTP for network configuration: true
+GDB connection port: 9000
+Network debug at boot time: false
+Update RedBoot non-volatile configuration - are you sure (y/n)? y
+
+Then, rebooting the Assabet is just a matter of waiting for the login prompt.
+
+
+
+Nicolas Pitre
+nico@cam.org
+June 12, 2001
+
+
+Status of peripherals in -rmk tree (updated 14/10/2001)
+-------------------------------------------------------
+
+Assabet:
+ Serial ports:
+  Radio:		TX, RX, CTS, DSR, DCD, RI
+   PM:			Not tested.
+  COM:			TX, RX, CTS, DSR, DCD, RTS, DTR, PM
+   PM:			Not tested.
+  I2C:			Implemented, not fully tested.
+  L3:			Fully tested, pass.
+   PM:			Not tested.
+
+ Video:
+  LCD:			Fully tested.  PM
+			(LCD doesn't like being blanked with
+			 neponset connected)
+  Video out:		Not fully
+
+ Audio:
+  UDA1341:
+   Playback:		Fully tested, pass.
+   Record:		Implemented, not tested.
+   PM:			Not tested.
+
+  UCB1200:
+   Audio play:		Implemented, not heavily tested.
+   Audio rec:		Implemented, not heavily tested.
+   Telco audio play:	Implemented, not heavily tested.
+   Telco audio rec:	Implemented, not heavily tested.
+   POTS control:	No
+   Touchscreen:		Yes
+   PM:			Not tested.
+
+ Other:
+  PCMCIA:
+   LPE:			Fully tested, pass.
+  USB:			No
+  IRDA:
+   SIR:			Fully tested, pass.
+   FIR:			Fully tested, pass.
+   PM:			Not tested.
+
+Neponset:
+ Serial ports:
+  COM1,2:	TX, RX, CTS, DSR, DCD, RTS, DTR
+   PM:			Not tested.
+  USB:			Implemented, not heavily tested.
+  PCMCIA:		Implemented, not heavily tested.
+   PM:			Not tested.
+  CF:			Implemented, not heavily tested.
+   PM:			Not tested.
+
+More stuff can be found in the -np (Nicolas Pitre's) tree.
+

+ 66 - 0
Documentation/arm/SA1100/Brutus

@@ -0,0 +1,66 @@
+Brutus is an evaluation platform for the SA1100 manufactured by Intel.  
+For more details, see:
+
+http://developer.intel.com/design/strong/applnots/sa1100lx/getstart.htm
+
+To compile for Brutus, you must issue the following commands:
+
+	make brutus_config
+	make config
+	[accept all the defaults]
+	make zImage
+
+The resulting kernel will end up in linux/arch/arm/boot/zImage.  This file
+must be loaded at 0xc0008000 in Brutus's memory and execution started at
+0xc0008000 as well with the value of registers r0 = 0 and r1 = 16 upon
+entry.
+
+But prior to execute the kernel, a ramdisk image must also be loaded in
+memory.  Use memory address 0xd8000000 for this.  Note that the file 
+containing the (compressed) ramdisk image must not exceed 4 MB.
+
+Typically, you'll need angelboot to load the kernel.
+The following angelboot.opt file should be used:
+
+----- begin angelboot.opt -----
+base 0xc0008000
+entry 0xc0008000
+r0 0x00000000
+r1 0x00000010
+device /dev/ttyS0
+options "9600 8N1"
+baud 115200
+otherfile ramdisk_img.gz
+otherbase 0xd8000000
+----- end angelboot.opt -----
+
+Then load the kernel and ramdisk with:
+
+	angelboot -f angelboot.opt zImage
+
+The first Brutus serial port (assumed to be linked to /dev/ttyS0 on your
+host PC) is used by angel to load the kernel and ramdisk image. The serial
+console is provided through the second Brutus serial port. To access it,
+you may use minicom configured with /dev/ttyS1, 9600 baud, 8N1, no flow
+control.
+
+Currently supported:
+	- RS232 serial ports
+	- audio output
+	- LCD screen
+	- keyboard
+	
+The actual Brutus support may not be complete without extra patches. 
+If such patches exist, they should be found from 
+ftp.netwinder.org/users/n/nico.
+
+A full PCMCIA support is still missing, although it's possible to hack
+some drivers in order to drive already inserted cards at boot time with
+little modifications.
+
+Any contribution is welcome.
+
+Please send patches to nico@cam.org
+
+Have Fun !
+

+ 29 - 0
Documentation/arm/SA1100/CERF

@@ -0,0 +1,29 @@
+*** The StrongARM version of the CerfBoard/Cube has been discontinued ***
+
+The Intrinsyc CerfBoard is a StrongARM 1110-based computer on a board
+that measures approximately 2" square. It includes an Ethernet
+controller, an RS232-compatible serial port, a USB function port, and
+one CompactFlash+ slot on the back. Pictures can be found at the
+Intrinsyc website, http://www.intrinsyc.com.
+
+This document describes the support in the Linux kernel for the
+Intrinsyc CerfBoard.
+
+Supported in this version:
+   - CompactFlash+ slot (select PCMCIA in General Setup and any options
+     that may be required)
+   - Onboard Crystal CS8900 Ethernet controller (Cerf CS8900A support in
+     Network Devices)
+   - Serial ports with a serial console (hardcoded to 38400 8N1)
+
+In order to get this kernel onto your Cerf, you need a server that runs
+both BOOTP and TFTP. Detailed instructions should have come with your
+evaluation kit on how to use the bootloader. This series of commands
+will suffice:
+
+   make ARCH=arm CROSS_COMPILE=arm-linux- cerfcube_defconfig
+   make ARCH=arm CROSS_COMPILE=arm-linux- zImage
+   make ARCH=arm CROSS_COMPILE=arm-linux- modules
+   cp arch/arm/boot/zImage <TFTP directory>
+
+support@intrinsyc.com

+ 21 - 0
Documentation/arm/SA1100/FreeBird

@@ -0,0 +1,21 @@
+Freebird-1.1 is produced by Legned(C) ,Inc.
+(http://www.legend.com.cn)
+and software/linux mainatined by Coventive(C),Inc.
+(http://www.coventive.com)
+
+Based on the Nicolas's strongarm kernel tree.
+
+===============================================================
+Maintainer:
+
+Chester Kuo <chester@coventive.com>
+	    <chester@linux.org.tw>
+
+Author :
+Tim wu <timwu@coventive.com>
+CIH <cih@coventive.com>
+Eric Peng <ericpeng@coventive.com>
+Jeff Lee <jeff_lee@coventive.com>
+Allen Cheng
+Tony Liu <tonyliu@coventive.com>
+

+ 98 - 0
Documentation/arm/SA1100/GraphicsClient

@@ -0,0 +1,98 @@
+ADS GraphicsClient Plus Single Board Computer
+
+For more details, contact Applied Data Systems or see
+http://www.applieddata.net/products.html
+
+The original Linux support for this product has been provided by 
+Nicolas Pitre <nico@cam.org>. Continued development work by
+Woojung Huh <whuh@applieddata.net>
+
+It's currently possible to mount a root filesystem via NFS providing a
+complete Linux environment.  Otherwise a ramdisk image may be used.  The
+board supports MTD/JFFS, so you could also mount something on there.
+
+Use 'make graphicsclient_config' before any 'make config'.  This will set up
+defaults for GraphicsClient Plus support.
+
+The kernel zImage is linked to be loaded and executed at 0xc0200000.  
+Also the following registers should have the specified values upon entry:
+
+	r0 = 0
+	r1 = 29	(this is the GraphicsClient architecture number)
+
+Linux can  be used with the ADS BootLoader that ships with the
+newer rev boards. See their documentation on how to load Linux.
+Angel is not available for the GraphicsClient Plus AFAIK.
+
+There is a  board known as just the GraphicsClient that ADS used to
+produce but has end of lifed. This code will not work on the older
+board with the ADS bootloader, but should still work with Angel,
+as outlined below.  In any case, if you're planning on deploying
+something en masse, you should probably get the newer board.
+
+If using Angel on the older boards, here is a typical angel.opt option file
+if the kernel is loaded through the Angel Debug Monitor:
+
+----- begin angelboot.opt -----
+base 0xc0200000
+entry 0xc0200000
+r0 0x00000000
+r1 0x0000001d
+device /dev/ttyS1
+options "38400 8N1"
+baud 115200
+#otherfile ramdisk.gz
+#otherbase 0xc0800000
+exec minicom
+----- end angelboot.opt -----
+
+Then the kernel (and ramdisk if otherfile/otherbase lines above are
+uncommented) would be loaded with:
+
+	angelboot -f angelboot.opt zImage
+
+Here it is assumed that the board is connected to ttyS1 on your PC
+and that minicom is preconfigured with /dev/ttyS1, 38400 baud, 8N1, no flow
+control by default.
+
+If any other bootloader is used, ensure it accomplish the same, especially
+for r0/r1 register values before jumping into the kernel.
+
+
+Supported peripherals:
+- SA1100 LCD frame buffer (8/16bpp...sort of)
+- on-board SMC 92C96 ethernet NIC
+- SA1100 serial port
+- flash memory access (MTD/JFFS)
+- pcmcia
+- touchscreen(ucb1200)
+- ps/2 keyboard
+- console on LCD screen
+- serial ports (ttyS[0-2])
+  - ttyS0 is default for serial console
+- Smart I/O (ADC, keypad, digital inputs, etc)
+  See http://www.applieddata.com/developers/linux for IOCTL documentation
+  and example user space code. ps/2 keybd is multiplexed through this driver
+
+To do:
+- UCB1200 audio with new ucb_generic layer
+- everything else!  :-)
+
+Notes:
+
+- The flash on board is divided into 3 partitions.  mtd0 is where
+  the ADS boot ROM and zImage is stored.  It's been marked as
+  read-only to keep you from blasting over the bootloader. :)  mtd1 is
+  for the ramdisk.gz image.  mtd2 is user flash space and can be
+  utilized for either JFFS or if you're feeling crazy, running ext2
+  on top of it. If you're not using the ADS bootloader, you're
+  welcome to blast over the mtd1 partition also.
+
+- 16bpp mode requires a different cable than what ships with the board.
+  Contact ADS or look through the manual to wire your own. Currently,
+  if you compile with 16bit mode support and switch into a lower bpp
+  mode, the timing is off so the image is corrupted.  This will be
+  fixed soon.
+
+Any contribution can be sent to nico@cam.org and will be greatly welcome!
+

+ 53 - 0
Documentation/arm/SA1100/GraphicsMaster

@@ -0,0 +1,53 @@
+ADS GraphicsMaster Single Board Computer
+
+For more details, contact Applied Data Systems or see
+http://www.applieddata.net/products.html
+
+The original Linux support for this product has been provided by
+Nicolas Pitre <nico@cam.org>. Continued development work by
+Woojung Huh <whuh@applieddata.net>
+
+Use 'make graphicsmaster_config' before any 'make config'.
+This will set up defaults for GraphicsMaster support.
+
+The kernel zImage is linked to be loaded and executed at 0xc0400000.
+
+Linux can  be used with the ADS BootLoader that ships with the
+newer rev boards. See their documentation on how to load Linux.
+
+Supported peripherals:
+- SA1100 LCD frame buffer (8/16bpp...sort of)
+- SA1111 USB Master
+- on-board SMC 92C96 ethernet NIC
+- SA1100 serial port
+- flash memory access (MTD/JFFS)
+- pcmcia, compact flash
+- touchscreen(ucb1200)
+- ps/2 keyboard
+- console on LCD screen
+- serial ports (ttyS[0-2])
+  - ttyS0 is default for serial console
+- Smart I/O (ADC, keypad, digital inputs, etc)
+  See http://www.applieddata.com/developers/linux for IOCTL documentation
+  and example user space code. ps/2 keybd is multiplexed through this driver
+
+To do:
+- everything else!  :-)
+
+Notes:
+
+- The flash on board is divided into 3 partitions.  mtd0 is where
+  the zImage is stored.  It's been marked as read-only to keep you
+  from blasting over the bootloader. :)  mtd1 is
+  for the ramdisk.gz image.  mtd2 is user flash space and can be
+  utilized for either JFFS or if you're feeling crazy, running ext2
+  on top of it. If you're not using the ADS bootloader, you're
+  welcome to blast over the mtd1 partition also.
+
+- 16bpp mode requires a different cable than what ships with the board.
+  Contact ADS or look through the manual to wire your own. Currently,
+  if you compile with 16bit mode support and switch into a lower bpp
+  mode, the timing is off so the image is corrupted.  This will be
+  fixed soon.
+
+Any contribution can be sent to nico@cam.org and will be greatly welcome!

+ 17 - 0
Documentation/arm/SA1100/HUW_WEBPANEL

@@ -0,0 +1,17 @@
+The HUW_WEBPANEL is a product of the german company Hoeft & Wessel AG
+
+If you want more information, please visit
+http://www.hoeft-wessel.de
+
+To build the kernel:
+	make huw_webpanel_config
+	make oldconfig
+	[accept all defaults]
+	make zImage
+
+Mostly of the work is done by:
+Roman Jordan         jor@hoeft-wessel.de
+Christoph Schulz    schu@hoeft-wessel.de
+
+2000/12/18/
+

+ 39 - 0
Documentation/arm/SA1100/Itsy

@@ -0,0 +1,39 @@
+Itsy is a research project done by the Western Research Lab, and Systems
+Research Center in Palo Alto, CA. The Itsy project is one of several
+research projects at Compaq that are related to pocket computing.
+
+For more information, see:
+
+	http://www.research.digital.com/wrl/itsy/index.html
+
+Notes on initial 2.4 Itsy support (8/27/2000) :
+The port was done on an Itsy version 1.5 machine with a daughtercard with
+64 Meg of DRAM and 32 Meg of Flash. The initial work includes support for
+serial console (to see what you're doing).  No other devices have been
+enabled.
+
+To build, do a "make menuconfig" (or xmenuconfig) and select Itsy support.
+Disable Flash and LCD support. and then do a make zImage.
+Finally, you will need to cd to arch/arm/boot/tools and execute a make there
+to build the params-itsy program used to boot the kernel.
+
+In order to install the port of 2.4 to the itsy, You will need to set the
+configuration parameters in the monitor as follows:
+Arg 1:0x08340000, Arg2: 0xC0000000, Arg3:18 (0x12), Arg4:0
+Make sure the start-routine address is set to 0x00060000.
+
+Next, flash the params-itsy program to 0x00060000 ("p 1 0x00060000" in the
+flash menu)  Flash the kernel in arch/arm/boot/zImage into 0x08340000
+("p 1 0x00340000").  Finally flash an initial ramdisk into 0xC8000000
+("p 2 0x0")  We used ramdisk-2-30.gz from the 0.11 version directory on
+handhelds.org.
+
+The serial connection we established was at:
+ 8-bit data, no parity, 1 stop bit(s), 115200.00 b/s. in the monitor, in the
+params-itsy program, and in the kernel itself.  This can be changed, but
+not easily. The monitor parameters are easily changed, the params program
+setup is assembly outl's, and the kernel is a configuration item specific to
+the itsy. (i.e. grep for CONFIG_SA1100_ITSY and you'll find where it is.)
+
+
+This should get you a properly booting 2.4 kernel on the itsy.

+ 14 - 0
Documentation/arm/SA1100/LART

@@ -0,0 +1,14 @@
+Linux Advanced Radio Terminal (LART)
+------------------------------------
+
+The LART is a small (7.5 x 10cm) SA-1100 board, designed for embedded
+applications. It has 32 MB DRAM, 4MB Flash ROM, double RS232 and all
+other StrongARM-gadgets. Almost all SA signals are directly accessible
+through a number of connectors. The powersupply accepts voltages
+between 3.5V and 16V and is overdimensioned to support a range of
+daughterboards. A quad Ethernet / IDE / PS2 / sound daughterboard
+is under development, with plenty of others in different stages of
+planning.
+
+The hardware designs for this board have been released under an open license;
+see the LART page at http://www.lart.tudelft.nl/ for more information.

+ 11 - 0
Documentation/arm/SA1100/PLEB

@@ -0,0 +1,11 @@
+The PLEB project was started as a student initiative at the School of
+Computer Science and Engineering, University of New South Wales to make a
+pocket computer capable of running the Linux Kernel.
+
+PLEB support has yet to be fully integrated.
+
+For more information, see:
+
+	http://www.cse.unsw.edu.au/~pleb/
+
+

+ 23 - 0
Documentation/arm/SA1100/Pangolin

@@ -0,0 +1,23 @@
+Pangolin is a StrongARM 1110-based evaluation platform produced
+by Dialogue Technology (http://www.dialogue.com.tw/).
+It has EISA slots for ease of configuration with SDRAM/Flash
+memory card, USB/Serial/Audio card, Compact Flash card,
+PCMCIA/IDE card and TFT-LCD card.
+
+To compile for Pangolin, you must issue the following commands:
+
+	make pangolin_config
+	make oldconfig
+	make zImage
+
+Supported peripherals:
+- SA1110 serial port (UART1/UART2/UART3)
+- flash memory access
+- compact flash driver
+- UDA1341 sound driver
+- SA1100 LCD controller for 800x600 16bpp TFT-LCD
+- MQ-200 driver for 800x600 16bpp TFT-LCD
+- Penmount(touch panel) driver
+- PCMCIA driver
+- SMC91C94 LAN driver
+- IDE driver (experimental)

+ 7 - 0
Documentation/arm/SA1100/Tifon

@@ -0,0 +1,7 @@
+Tifon
+-----
+
+More info has to come...
+
+Contact: Peter Danielsson <peter.danielsson@era-t.ericsson.se>
+

+ 16 - 0
Documentation/arm/SA1100/Victor

@@ -0,0 +1,16 @@
+Victor is known as a "digital talking book player" manufactured by
+VisuAide, Inc. to be used by blind people.
+
+For more information related to Victor, see:
+
+	http://www.visuaide.com/victor
+
+Of course Victor is using Linux as its main operating system.
+The Victor implementation for Linux is maintained by Nicolas Pitre:
+
+	nico@visuaide.com
+	nico@cam.org
+
+For any comments, please feel free to contact me through the above
+addresses.
+

+ 2 - 0
Documentation/arm/SA1100/Yopy

@@ -0,0 +1,2 @@
+See http://www.yopydeveloper.org for more.
+

+ 2 - 0
Documentation/arm/SA1100/empeg

@@ -0,0 +1,2 @@
+See ../empeg/README
+

+ 11 - 0
Documentation/arm/SA1100/nanoEngine

@@ -0,0 +1,11 @@
+nanoEngine
+----------
+
+"nanoEngine" is a SA1110 based single board computer from 
+Bright Star Engineering Inc.  See www.brightstareng.com/arm
+for more info.
+(Ref: Stuart Adams <sja@brightstareng.com>)
+
+Also visit Larry Doolittle's "Linux for the nanoEngine" site:
+http://recycle.lbl.gov/~ldoolitt/bse/
+

+ 47 - 0
Documentation/arm/SA1100/serial_UART

@@ -0,0 +1,47 @@
+The SA1100 serial port had its major/minor numbers officially assigned:
+
+> Date: Sun, 24 Sep 2000 21:40:27 -0700
+> From: H. Peter Anvin <hpa@transmeta.com>
+> To: Nicolas Pitre <nico@CAM.ORG>
+> Cc: Device List Maintainer <device@lanana.org>
+> Subject: Re: device
+> 
+> Okay.  Note that device numbers 204 and 205 are used for "low density
+> serial devices", so you will have a range of minors on those majors (the
+> tty device layer handles this just fine, so you don't have to worry about
+> doing anything special.)
+> 
+> So your assignments are:
+> 
+> 204 char        Low-density serial ports
+>                   5 = /dev/ttySA0               SA1100 builtin serial port 0
+>                   6 = /dev/ttySA1               SA1100 builtin serial port 1
+>                   7 = /dev/ttySA2               SA1100 builtin serial port 2
+> 
+> 205 char        Low-density serial ports (alternate device)
+>                   5 = /dev/cusa0                Callout device for ttySA0
+>                   6 = /dev/cusa1                Callout device for ttySA1
+>                   7 = /dev/cusa2                Callout device for ttySA2
+>
+
+If you're not using devfs, you must create those inodes in /dev
+on the root filesystem used by your SA1100-based device:
+
+	mknod ttySA0 c 204 5
+	mknod ttySA1 c 204 6
+	mknod ttySA2 c 204 7
+	mknod cusa0 c 205 5
+	mknod cusa1 c 205 6
+	mknod cusa2 c 205 7
+
+In addition to the creation of the appropriate device nodes above, you
+must ensure your user space applications make use of the correct device
+name. The classic example is the content of the /etc/inittab file where
+you might have a getty process started on ttyS0.  In this case:
+
+- replace occurrences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc.
+
+- don't forget to add 'ttySA0', 'console', or the appropriate tty name
+  in /etc/securetty for root to be allowed to login as well.
+
+

+ 58 - 0
Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt

@@ -0,0 +1,58 @@
+		Simtec Electronics EB2410ITX (BAST)
+		===================================
+
+	http://www.simtec.co.uk/products/EB2410ITX/
+
+Introduction
+------------
+
+  The EB2410ITX is a S3C2410 based development board with a variety of
+  peripherals and expansion connectors. This board is also known by
+  the shortened name of Bast.
+
+
+Configuration
+-------------
+
+  To set the default configuration, use `make bast_defconfig` which
+  supports the commonly used features of this board.
+
+
+Support
+-------
+
+  Official support information can be found on the Simtec Electronics
+  website, at the product page http://www.simtec.co.uk/products/EB2410ITX/
+
+  Useful links:
+
+    - Resources Page http://www.simtec.co.uk/products/EB2410ITX/resources.html
+
+    - Board FAQ at http://www.simtec.co.uk/products/EB2410ITX/faq.html
+
+    - Bootloader info http://www.simtec.co.uk/products/SWABLE/resources.html
+      and FAQ http://www.simtec.co.uk/products/SWABLE/faq.html
+
+
+MTD
+---
+
+  The NAND and NOR support has been merged from the linux-mtd project.
+  Any prolbems, see http://www.linux-mtd.infradead.org/ for more
+  information or up-to-date versions of linux-mtd.
+
+
+IDE
+---
+
+  Both onboard IDE ports are supported, however there is no support for
+  changing speed of devices, PIO Mode 4 capable drives should be used.
+
+
+Maintainers
+-----------
+
+  This board is maintained by Simtec Electronics.
+
+
+(c) 2004 Ben Dooks, Simtec Electronics

+ 122 - 0
Documentation/arm/Samsung-S3C24XX/GPIO.txt

@@ -0,0 +1,122 @@
+			S3C2410 GPIO Control
+			====================
+
+Introduction
+------------
+
+  The s3c2410 kernel provides an interface to configure and
+  manipulate the state of the GPIO pins, and find out other
+  information about them.
+
+  There are a number of conditions attached to the configuration
+  of the s3c2410 GPIO system, please read the Samsung provided
+  data-sheet/users manual to find out the complete list.
+
+
+Headers
+-------
+
+  See include/asm-arm/arch-s3c2410/regs-gpio.h for the list
+  of GPIO pins, and the configuration values for them. This
+  is included by using #include <asm/arch/regs-gpio.h>
+
+  The GPIO management functions are defined in the hardware
+  header include/asm-arm/arch-s3c2410/hardware.h which can be
+  included by #include <asm/arch/hardware.h>
+
+  A useful ammount of documentation can be found in the hardware
+  header on how the GPIO functions (and others) work.
+
+  Whilst a number of these functions do make some checks on what
+  is passed to them, for speed of use, they may not always ensure
+  that the user supplied data to them is correct.
+
+
+PIN Numbers
+-----------
+
+  Each pin has an unique number associated with it in regs-gpio.h,
+  eg S3C2410_GPA0 or S3C2410_GPF1. These defines are used to tell
+  the GPIO functions which pin is to be used.
+
+
+Configuring a pin
+-----------------
+
+  The following function allows the configuration of a given pin to
+  be changed.
+
+    void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
+
+  Eg:
+
+     s3c2410_gpio_cfgpin(S3C2410_GPA0, S3C2410_GPA0_ADDR0);
+     s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
+
+   which would turn GPA0 into the lowest Address line A0, and set
+   GPE8 to be connected to the SDIO/MMC controller's SDDAT1 line.
+
+
+Reading the current configuration
+---------------------------------
+
+  The current configuration of a pin can be read by using:
+
+  s3c2410_gpio_getcfg(unsigned int pin);
+
+  The return value will be from the same set of values which can be
+  passed to s3c2410_gpio_cfgpin().
+
+
+Configuring a pull-up resistor
+------------------------------
+
+  A large proportion of the GPIO pins on the S3C2410 can have weak
+  pull-up resistors enabled. This can be configured by the following
+  function:
+
+    void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
+
+  Where the to value is zero to set the pull-up off, and 1 to enable
+  the specified pull-up. Any other values are currently undefined.
+
+
+Getting the state of a PIN
+--------------------------
+
+  The state of a pin can be read by using the function:
+
+    unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+  This will return either zero or non-zero. Do not count on this
+  function returning 1 if the pin is set.
+
+
+Setting the state of a PIN
+--------------------------
+
+  The value an pin is outputing can be modified by using the following:
+
+    void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+
+  Which sets the given pin to the value. Use 0 to write 0, and 1 to
+  set the output to 1.
+
+
+Getting the IRQ number associated with a PIN
+--------------------------------------------
+
+  The following function can map the given pin number to an IRQ
+  number to pass to the IRQ system.
+
+   int s3c2410_gpio_getirq(unsigned int pin);
+
+  Note, not all pins have an IRQ.
+
+
+Authour
+-------
+
+
+Ben Dooks, 03 October 2004
+(c) 2004 Ben Dooks, Simtec Electronics

+ 40 - 0
Documentation/arm/Samsung-S3C24XX/H1940.txt

@@ -0,0 +1,40 @@
+		HP IPAQ H1940
+		=============
+
+http://www.handhelds.org/projects/h1940.html
+
+Introduction
+------------
+
+  The HP H1940 is a S3C2410 based handheld device, with
+  bluetooth connectivity.
+
+
+Support
+-------
+
+  A variety of information is available
+
+  handhelds.org project page:
+
+    http://www.handhelds.org/projects/h1940.html
+
+  handhelds.org wiki page:
+
+    http://handhelds.org/moin/moin.cgi/HpIpaqH1940
+
+  Herbert Pötzl pages:
+
+    http://vserver.13thfloor.at/H1940/
+
+
+Maintainers
+-----------
+
+  This project is being maintained and developed by a variety
+  of people, including Ben Dooks, Arnaud Patard, and Herbert Pötzl.
+
+  Thanks to the many others who have also provided support.
+
+
+(c) 2005 Ben Dooks

+ 156 - 0
Documentation/arm/Samsung-S3C24XX/Overview.txt

@@ -0,0 +1,156 @@
+			S3C24XX ARM Linux Overview
+			==========================
+
+
+
+Introduction
+------------
+
+  The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
+  by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 and
+  the S3C2440 are supported CPUs.
+
+
+Configuration
+-------------
+
+  A generic S3C2410 configuration is provided, and can be used as the
+  default by `make s3c2410_defconfig`. This configuration has support
+  for all the machines, and the commonly used features on them.
+
+  Certain machines may have their own default configurations as well,
+  please check the machine specific documentation.
+
+
+Machines
+--------
+
+  The currently supported machines are as follows:
+
+  Simtec Electronics EB2410ITX (BAST)
+
+    A general purpose development board, see EB2410ITX.txt for further
+    details
+
+  Samsung SMDK2410
+
+    Samsung's own development board, geared for PDA work.
+
+  Samsung/Meritech SMDK2440
+
+    The S3C2440 compatible version of the SMDK2440
+
+  Thorcom VR1000
+
+    Custom embedded board
+
+  HP IPAQ 1940
+
+    Handheld (IPAQ), available in several varieties
+
+  HP iPAQ rx3715
+
+    S3C2440 based IPAQ, with a number of variations depending on
+    features shipped.
+
+  Acer N30
+
+    A S3C2410 based PDA from Acer.  There is a Wiki page at
+    http://handhelds.org/moin/moin.cgi/AcerN30Documentation .
+
+
+Adding New Machines
+-------------------
+
+  The archicture has been designed to support as many machines as can
+  be configured for it in one kernel build, and any future additions
+  should keep this in mind before altering items outside of their own
+  machine files.
+
+  Machine definitions should be kept in linux/arch/arm/mach-s3c2410,
+  and there are a number of examples that can be looked at.
+
+  Read the kernel patch submission policies as well as the
+  Documentation/arm directory before submitting patches. The
+  ARM kernel series is managed by Russell King, and has a patch system
+  located at http://www.arm.linux.org.uk/developer/patches/
+  as well as mailing lists that can be found from the same site.
+
+  As a courtesy, please notify <ben-linux@fluff.org> of any new
+  machines or other modifications.
+
+  Any large scale modifications, or new drivers should be discussed
+  on the ARM kernel mailing list (linux-arm-kernel) before being
+  attempted.
+
+
+NAND
+----
+
+  The current kernels now have support for the s3c2410 NAND
+  controller. If there are any problems the latest linux-mtd
+  CVS can be found from http://www.linux-mtd.infradead.org/
+
+
+Serial
+------
+
+  The s3c2410 serial driver provides support for the internal
+  serial ports. These devices appear as /dev/ttySAC0 through 3.
+
+  To create device nodes for these, use the following commands
+
+    mknod ttySAC0 c 204 64
+    mknod ttySAC1 c 204 65
+    mknod ttySAC2 c 204 66
+
+
+GPIO
+----
+
+  The core contains support for manipulating the GPIO, see the
+  documentation in GPIO.txt in the same directory as this file.
+
+
+Clock Management
+----------------
+
+  The core provides the interface defined in the header file
+  include/asm-arm/hardware/clock.h, to allow control over the
+  various clock units
+
+
+Port Contributors
+-----------------
+
+  Ben Dooks (BJD)
+  Vincent Sanders
+  Herbert Potzl
+  Arnaud Patard (RTP)
+  Roc Wu
+  Klaus Fetscher
+  Dimitry Andric
+  Shannon Holland
+  Guillaume Gourat (NexVision)
+  Christer Weinigel (wingel) (Acer N30)
+  Lucas Correia Villa Real (S3C2400 port)
+
+
+Document Changes
+----------------
+
+  05 Sep 2004 - BJD - Added Document Changes section
+  05 Sep 2004 - BJD - Added Klaus Fetscher to list of contributors
+  25 Oct 2004 - BJD - Added Dimitry Andric to list of contributors
+  25 Oct 2004 - BJD - Updated the MTD from the 2.6.9 merge
+  21 Jan 2005 - BJD - Added rx3715, added Shannon to contributors
+  10 Feb 2005 - BJD - Added Guillaume Gourat to contributors
+  02 Mar 2005 - BJD - Added SMDK2440 to list of machines
+  06 Mar 2005 - BJD - Added Christer Weinigel
+  08 Mar 2005 - BJD - Added LCVR to list of people, updated introduction
+  08 Mar 2005 - BJD - Added section on adding machines
+
+Document Author
+---------------
+
+Ben Dooks, (c) 2004-2005 Simtec Electronics

+ 56 - 0
Documentation/arm/Samsung-S3C24XX/SMDK2440.txt

@@ -0,0 +1,56 @@
+		Samsung/Meritech SMDK2440
+		=========================
+
+Introduction
+------------
+
+  The SMDK2440 is a two part evaluation board for the Samsung S3C2440
+  processor. It includes support for LCD, SmartMedia, Audio, SD and
+  10MBit Ethernet, and expansion headers for various signals, including
+  the camera and unused GPIO.
+
+
+Configuration
+-------------
+
+  To set the default configuration, use `make smdk2440_defconfig` which
+  will configure the common features of this board, or use
+  `make s3c2410_config` to include support for all s3c2410/s3c2440 machines
+
+
+Support
+-------
+
+  Ben Dooks' SMDK2440 site at http://www.fluff.org/ben/smdk2440/ which
+  includes linux based USB download tools.
+
+  Some of the h1940 patches that can be found from the H1940 project
+  site at http://www.handhelds.org/projects/h1940.html can also be
+  applied to this board.
+
+
+Peripherals
+-----------
+
+  There is no current support for any of the extra peripherals on the
+  base-board itself.
+
+
+MTD
+---
+
+  The NAND flash should be supported by the in kernel MTD NAND support,
+  NOR flash will be added later.
+
+
+Maintainers
+-----------
+
+  This board is being maintained by Ben Dooks, for more info, see
+  http://www.fluff.org/ben/smdk2440/
+
+  Many thanks to Dimitry Andric of TomTom for the loan of the SMDK2440,
+  and to Simtec Electronics for allowing me time to work on this.
+
+
+(c) 2004 Ben Dooks

+ 106 - 0
Documentation/arm/Samsung-S3C24XX/Suspend.txt

@@ -0,0 +1,106 @@
+			S3C24XX Suspend Support
+			=======================
+
+
+Introduction
+------------
+
+  The S3C2410 supports a low-power suspend mode, where the SDRAM is kept
+  in Self-Refresh mode, and all but the essential peripheral blocks are
+  powered down. For more information on how this works, please look
+  at the S3C2410 datasheets from Samsung.
+
+
+Requirements
+------------
+
+  1) A bootloader that can support the necessary resume operation
+
+  2) Support for at least 1 source for resume
+
+  3) CONFIG_PM enabled in the kernel
+
+  4) Any peripherals that are going to be powered down at the same
+     time require suspend/resume support.
+
+
+Resuming
+--------
+
+  The S3C2410 user manual defines the process of sending the CPU to
+  sleep and how it resumes. The default behaviour of the Linux code
+  is to set the GSTATUS3 register to the physical address of the
+  code to resume Linux operation.
+
+  GSTATUS4 is currently left alone by the sleep code, and is free to
+  use for any other purposes (for example, the EB2410ITX uses this to
+  save memory configuration in).
+
+
+Machine Support
+---------------
+
+  The machine specific functions must call the s3c2410_pm_init() function
+  to say that its bootloader is capable of resuming. This can be as
+  simple as adding the following to the machine's definition:
+
+  INITMACHINE(s3c2410_pm_init)
+
+  A board can do its own setup before calling s3c2410_pm_init, if it
+  needs to setup anything else for power management support.
+
+  There is currently no support for over-riding the default method of
+  saving the resume address, if your board requires it, then contact
+  the maintainer and discuss what is required.
+
+  Note, the original method of adding an late_initcall() is wrong,
+  and will end up initialising all compiled machines' pm init!
+
+
+Debugging
+---------
+
+  There are several important things to remember when using PM suspend:
+
+  1) The uart drivers will disable the clocks to the UART blocks when
+     suspending, which means that use of printascii() or similar direct
+     access to the UARTs will cause the debug to stop.
+
+  2) Whilst the pm code itself will attempt to re-enable the UART clocks,
+     care should be taken that any external clock sources that the UARTs
+     rely on are still enabled at that point.
+
+
+Configuration
+-------------
+
+  The S3C2410 specific configuration in `System Type` defines various
+  aspects of how the S3C2410 suspend and resume support is configured
+
+  `S3C2410 PM Suspend debug`
+
+    This option prints messages to the serial console before and after
+    the actual suspend, giving detailed information on what is
+    happening
+
+
+  `S3C2410 PM Suspend Memory CRC`
+
+    Allows the entire memory to be checksummed before and after the
+    suspend to see if there has been any corruption of the contents.
+
+    This support requires the CRC32 function to be enabled.
+
+
+  `S3C2410 PM Suspend CRC Chunksize (KiB)`
+
+    Defines the size of memory each CRC chunk covers. A smaller value
+    will mean that the CRC data block will take more memory, but will
+    identify any faults with better precision
+
+
+Document Author
+---------------
+
+Ben Dooks, (c) 2004 Simtec Electronics
+

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác