diff -u --recursive --new-file v2.4.9/linux/CREDITS linux/CREDITS
--- v2.4.9/linux/CREDITS	Mon Aug 27 12:41:37 2001
+++ linux/CREDITS	Sun Sep  9 10:43:02 2001
@@ -400,13 +400,12 @@
 S: USA
 
 N: Peter Braam
-E: braam@cs.cmu.edu
-W: http://coda.cs.cmu.edu/~braam
-D: Coda Filesystem
-S: Dept of Computer Science
-S: 5000 Forbes Avenue
-S: Pittsburgh, Pennsylvania 15213
-S: USA
+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
@@ -535,6 +534,12 @@
 S: Stanford, California 94305
 S: USA
 
+N: Randolph Chung
+E: tausq@debian.org
+D: Linux/PA-RISC hacker
+S: Fremont, CA 94538
+S: USA
+
 N: Juan Jose Ciarlante
 W: http://juanjox.kernelnotes.org/
 E: jjciarla@raiz.uncu.edu.ar
@@ -633,10 +638,11 @@
 S: USA
 
 N: Frank Davis
+E: fdavis@si.rr.com
 E: fdavis112@juno.com
 D: Various kernel patches
 S: 8 Lakeview Terr.
-S: Kerhonskon, NY 12446
+S: Kerhonkson, NY 12446
 S: USA
 
 N: Wayne Davison
@@ -714,7 +720,7 @@
 N: Oleg Drokin
 E: green@ccssu.crimea.ua
 W: http://www.ccssu.crimea.ua/~green
-D: Cleaning up sound drivers.
+D: Cleaning up sound drivers, SA1100 Watchdog.
 S: Skvoznoy per., 14a
 S: Evpatoria
 S: Crimea
diff -u --recursive --new-file v2.4.9/linux/Documentation/00-INDEX linux/Documentation/00-INDEX
--- v2.4.9/linux/Documentation/00-INDEX	Thu Feb  8 16:32:44 2001
+++ linux/Documentation/00-INDEX	Mon Aug 27 07:44:15 2001
@@ -5,6 +5,11 @@
 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.
 BUG-HUNTING
diff -u --recursive --new-file v2.4.9/linux/Documentation/Changes linux/Documentation/Changes
--- v2.4.9/linux/Documentation/Changes	Tue Jul  3 17:08:18 2001
+++ linux/Documentation/Changes	Mon Sep 17 23:10:44 2001
@@ -48,7 +48,7 @@
 Card) hardware, for example, you probably needn't concern yourself
 with pcmcia-cs.
 
-o  Gnu C                  2.91.66                 # gcc --version
+o  Gnu C                  2.95.3                  # gcc --version
 o  Gnu make               3.77                    # make --version
 o  binutils               2.9.1.0.25              # ld -v
 o  util-linux             2.10o                   # fdformat --version
@@ -70,17 +70,23 @@
 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 egcs 1.1.2 (gcc 2.91.66), and it
-should be used when you need absolute stability. You may use gcc 2.95.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
+The recommended compiler for the kernel is gcc 2.95.3 or .4, 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 egcs or plain gcc is just asking for trouble.
 
 Note that gcc 2.7.2.3 is no longer a supported kernel compiler. The kernel
 no longer works around bugs in gcc 2.7.2.3 and, in fact, will refuse to
-be compiled with it.
+be compiled with it. egcs-1.1.2 has register allocation problems in very
+obscure cases. We have ensured the kernel does not trip these in any known
+situation. The 2.5 tree is likely to drop egcs-1.1.2 workarounds.
+
+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
diff -u --recursive --new-file v2.4.9/linux/Documentation/CodingStyle linux/Documentation/CodingStyle
--- v2.4.9/linux/Documentation/CodingStyle	Wed Sep 29 13:59:12 1999
+++ linux/Documentation/CodingStyle	Sun Sep  9 16:40:43 2001
@@ -233,3 +233,34 @@
 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 8: 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-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.
diff -u --recursive --new-file v2.4.9/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.4.9/linux/Documentation/Configure.help	Mon Aug 27 12:41:37 2001
+++ linux/Documentation/Configure.help	Thu Sep 20 20:56:31 2001
@@ -1746,6 +1746,36 @@
   similar) CPU, R4xx0 might be a safe bet.
   If the resulting Kernel does not work try to recompile with R3000.
 
+CPU type
+CONFIG_CPU_VR41XX
+  The options selects support for the NEC VR41xx series of processors.
+  Only choose this option if you have one of these processors as a
+  kernel built with this option will not run on any other type of
+  processor or vice versa.
+
+CPU feature configuration
+CONFIG_CPU_ADVANCED
+  Saying yes here allows you to select support for various features your
+  CPU may or may not have.  Most people should say N here.
+
+ll and sc instructions
+CONFIG_CPU_HAS_LLSC
+  Say Y here if your CPU has the ll and sc instructions.  Say Y here for
+  better performance, N if you don't know.  You must say Y here for
+  multiprocessor machines.
+
+lld and scd instructions
+CONFIG_CPU_HAS_LLDSCD
+  Say Y here if your CPU has the lld and scd instructions, the 64-bit
+  equivalents of ll and sc.  Say Y here for better performance, N if
+  you don't know.  You must say Y here for multiprocessor machines.
+
+Support for writebuffer flushing
+CONFIG_CPU_HAS_WB
+  Say N here for slightly better performance.  You must say Y here for
+  machines which require flushing of write buffers in software.  Saying
+  Y is the safe option; N may result in kernel malfunction and crashes.
+
 Support for large 64-bit configurations
 CONFIG_MIPS_INSANE_LARGE
   MIPS R10000 does support a 44 bit / 16TB address space as opposed to
@@ -2551,7 +2581,7 @@
 AMD Irongate support
 CONFIG_AGP_AMD
   This option gives you AGP support for the GLX component of the
-  XFree86 4.x on AMD Irongate chipset.
+  XFree86 4.x on AMD Irongate and 761 chipsets.
 
   For the moment, you should probably say N, unless you want to test
   the GLX component for XFree86 3.3.6, which can be downloaded from
@@ -8779,13 +8809,13 @@
   say M here and read Documentation/modules.txt. This is recommended.
   The module will be called sis900.o.
 
-Packet Engines Yellowfin Gigabit-NIC support
+Packet Engines Yellowfin Gigabit-NIC / Symbios 53c885 support
 CONFIG_YELLOWFIN
   Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet
-  adapter. This adapter is used by the Beowulf Linux cluster project.
-  See http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html for
-  more information about this driver in particular and Beowulf in
-  general.
+  adapter or the SYM53C885 Ethernet controller. The Gigabit adapter is
+  used by the Beowulf Linux cluster project.  See
+  http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html for more
+  information about this driver in particular and Beowulf in general.
 
   If you want to compile this driver as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -11220,6 +11250,17 @@
   The module will be called keyspan_pda.o. If you want to compile it 
   as a module, say M here and read Documentation/modules.txt.
 
+USB Xircom / Entregra Single Port Serial Driver
+CONFIG_USB_SERIAL_XIRCOM
+  Say Y here if you want to use a Xircom or Entregra single port USB to
+  serial converter device.  This driver makes use of firmware
+  developed from scratch by Brian Warner.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called keyspan_pda.o. If you want to compile it
+  as a module, say M here and read <file:Documentation/modules.txt>.
+
 USB Keyspan USA-xxx Serial Driver
 CONFIG_USB_SERIAL_KEYSPAN
   Say Y here if you want to use Keyspan USB to serial converter
@@ -11478,6 +11519,45 @@
   The module will be called pegasus.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
+CONFIG_USB_KAWETH
+  Say Y here if you want to use one of the following 10Mbps only
+  USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
+       3Com 3C19250
+       ADS USB-10BT
+       ATEN USB Ethernet
+       ASANTE USB To Ethernet Adapter
+       AOX Endpoints USB Ethernet
+       Correga K.K.
+       D-Link DSB-650C and DU-E10
+       Entrega / Portgear E45
+       I-O DATA USB-ET/T
+       Jaton USB Ethernet Device Adapter
+       Kingston Technology USB Ethernet Adapter
+       Linksys USB10T
+       Mobility USB-Ethernet Adapter
+        NetGear EA-101
+       Peracom Enet and Enet2
+       Portsmith Express Ethernet Adapter
+       Shark Pocket Adapter
+       SMC 2202USB
+       Sony Vaio port extender
+
+  This driver is likely to work with most 10Mbps only USB Ethernet
+  adapters, including some "no brand" devices. It does NOT work on
+  SmartBridges smartNIC or on Belkin F5U111 devices - you should use
+  the CATC NetMate driver for those. If you are not sure which one
+  you need, select both, and the correct one should be selected for
+  you.
+
+  This driver makes the adapter appear as a normal Ethernet interface,
+  typically on eth0, if it is the only ethernet device, or perhaps on
+  eth1, if you have a PCI or ISA ethernet card installed.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called kaweth.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
 USB CATC NetMate-based Ethernet device support
 CONFIG_USB_CATC
   Say Y if you want to use one of the following 10Mbps USB Ethernet
@@ -11532,6 +11612,20 @@
   Say Y here in order to have the USB Mass Storage code generate
   verbose debugging messages.
 
+ISD-200 USB/ATA driver
+CONFIG_USB_STORAGE_ISD200
+  Say Y here if you want to use USB Mass Store devices based
+  on the In-Systems Design ISD-200 USB/ATA bridge.
+
+  Some of the products that use this chip are:
+
+    - Archos Jukebox 6000
+    - ISD SmartCable for Storage
+    - Taiwan Skymaster CD530U/DEL-0241 IDE bridge
+    - Sony CRX10U CD-R/RW drive
+    - CyQ've CQ8060A CDRW drive
+    - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U)
+
 USS720 parport driver
 CONFIG_USB_USS720
   This driver is for USB parallel port adapters that use the Lucent
@@ -11604,18 +11698,22 @@
   The module will be called dabusb.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-PLUSB driver
-CONFIG_USB_PLUSB
-  A driver for the Prolific PL-2302 USB-to-USB network device. This
-  'USB cable' connects two hosts via a point-to-point network with
-  bandwidth of 5 Mbit/s. Configure this driver after connecting the
-  USB cable via ifconfig plusb0 10.0.0.1 pointopoint 10.0.0.2 (and
-  vice versa on the other host).
+Host-to-Host USB networking
+CONFIG_USB_USBNET
+  This driver supports network links over USB with USB "Network"
+  or "data transfer" cables, often used to network laptops to PCs.
+  Such cables have chips from suppliers such as NetChip and Prolific.
+  Intelligent USB devices could also use this approach to provide
+  Internet access, using standard USB cabling.
+
+  These links will have names like "usb0", "usb1", etc.  They act
+  like two-node Ethernets, so you can use 802.1d Ethernet Bridging
+  (CONFIG_BRIDGE) to simplify your network routing.
 
-  This code is also available as a module ( = code which can be
+  This code is also available as a kernel module (code which can be
   inserted in and removed from the running kernel whenever you want).
-  The module will be called plusb.o. If you want to compile it as a
-  module, say M here and read Documentation/modules.txt.
+  The module will be called usbnet.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
 
 USB Diamond Rio500 support
 CONFIG_USB_RIO500
@@ -15754,6 +15852,14 @@
   better 32 MB RAM to avoid excessive linking time. This is only
   useful for kernel hackers. If unsure, say N.
 
+Run uncached
+CONFIG_MIPS_UNCACHED
+  If you say Y here there kernel will disable all CPU caches.  This will
+  reduce the system's performance dramatically but can help finding
+  otherwise hard to track bugs.  It can also useful if you're doing
+  hardware debugging with a logic analyzer and need to see all traffic
+  on the bus.
+
 Magic System Request Key support
 CONFIG_MAGIC_SYSRQ
   If you say Y here, you will have some control over the system even
@@ -16960,12 +17066,12 @@
 
 Motorola MPC8260 CPM support
 CONFIG_8260
-   The MPC8260 CPM (Communications Processor Module) is a typically
-   embedded CPU made by Motorola.  Selecting this option means that
-   you wish to build a kernel for a machine with specifically an 8260
-   for a CPU.
+  The MPC8260 CPM (Communications Processor Module) is a typical
+  embedded CPU made by Motorola. Selecting this option means that you
+  wish to build a kernel for a machine with specifically an 8260 for
+  a CPU.
 
-   If in doubt, say N.
+  If in doubt, say N.
 
 Workarounds for PPC601 bugs
 CONFIG_PPC601_SYNC_FIX
@@ -16983,11 +17089,190 @@
 CONFIG_ALL_PPC
   Linux currently supports several different kinds of PowerPC-based
   machines: Apple Power Macintoshes and clones (such as the Motorola
-  Starmax series), PReP (PowerPC Reference Platform) machines such as
-  the Motorola PowerStack, CHRP (Common Hardware Reference Platform), 
-  the embedded MBX boards from Motorola and many others. Currently, 
-  the default option is to build a kernel which works on the first 
-  three.  Support for other machines is currently incomplete.
+  Starmax series), PReP (PowerPC Reference Platform) machines (such
+  as the Motorola PowerStacks, Motorola cPCI/VME embedded systems,
+  and some IBM RS/6000 systems), CHRP (Common Hardware Reference
+  Platform), and several embedded PowerPC systems containing 4xx, 6xx,
+  7xx, 8xx, 74xx, and 82xx processors.  Currently, the default option
+  is to build a kernel which works on the first three. 
+
+Embedded 8xx Board Type
+CONFIG_RPXLITE
+  RPX-Lite:
+    Embedded Planet RPX Lite
+
+  RPX-Classic:
+    Embedded Planet RPX Classic Low-fat.
+
+  BSE-IP: 
+    Bright Star Engineering ip-Engine.
+
+  TQM823L:
+  TQM850L:
+  TQM855L:
+  TQM860L:
+    MPC8xx based family of mini modules, half credit card size,
+    up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports,
+    2 x CAN bus interface, ...
+      Manufacturer: TQ Components, www.tq-group.de
+      Date of Release: October (?) 1999
+      End of Life: not yet :-)
+      URL:
+      - module: http://www.denx.de/PDF/TQM8xxLHWM201.pdf
+      - starter kit: http://www.denx.de/PDF/STK8xxLHWM201.pdf
+      - images: http://www.denx.de/embedded-ppc-en.html
+
+  FPS850L:
+    FingerPrint Sensor System (based on TQM850L)
+      Manufacturer: IKENDI AG, http://www.ikendi.com/
+      Date of Release: November 1999
+      End of life: end 2000 ?
+      URL: see TQM850L
+
+  SPD823TS:
+    MPC823 based board used in the "Tele Server" product
+    Manufacturer: Speech Design, http://www.speech-design.de/
+    Date of Release: Mid 2000 (?)
+    End of life: -
+    URL: http://www.speech-design.de/
+         select "English", then "Teleteam Solutions", then "TeleServer"
+
+  IVMS8:
+    MPC860 based board used in the "Integrated Voice Mail System",
+    Small Version (8 voice channels)
+    Manufacturer: Speech Design, http://www.speech-design.de/
+    Date of Release: December 2000 (?)
+    End of life: -
+    URL: http://www.speech-design.de/
+
+  IVML24:
+    MPC860 based board used in the "Integrated Voice Mail System", 
+    Large Version (24 voice channels)
+    Manufacturer: Speech Design, http://www.speech-design.de/
+    Date of Release: March 2001  (?)
+    End of life: -
+    URL: http://www.speech-design.de/
+
+  SM850:
+    Service Module (based on TQM850L)
+    Manufacturer: Dependable Computer Systems, http://www.decomsys.com/
+    Date of Release: end 2000 (?)
+    End of life: mid 2001 (?)
+    URL: http://www.tz-mikroelektronik.de/ServiceModule/index.html
+
+  HERMES:
+    Hermes-Pro ISDN/LAN router with integrated 8 x hub
+    Manufacturer: Multidata Gesellschaft für Datentechnik und Informatik
+      http://www.multidata.de/
+    Date of Release: 2000 (?)
+    End of life: -
+    URL: http://www.multidata.de/english/products/hpro.htm
+
+  IP860:	
+    VMEBus IP (Industry Pack) carrier board with MPC860
+    Manufacturer: MicroSys GmbH, http://www.microsys.de/
+    Date of Release: ?
+    End of life: -
+    URL: http://www.microsys.de/html/ip860.html
+
+  PCU_E:
+    PCU = Peripheral Controller Unit, Extended
+    Manufacturer: Siemens AG, ICN (Information and Communication Networks)
+    	http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html
+    Date of Release: April 2001
+    End of life: August 2001
+    URL: n. a.
+
+Embedded 82xx Board Type
+CONFIG_EST8260
+  EST8260: Wind River System, Inc. EST SBC8260
+
+  TQM8260:
+    MPC8260 based module, little larger than credit card,
+    up to 128 MB global + 64 MB local RAM, 32 MB Flash,
+    32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet,
+    2 x serial ports, ...
+      Manufacturer: TQ Components, www.tq-group.de
+      Date of Release: June 2001
+      End of Life: not yet :-)
+      URL: http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf
+
+  PM826:
+    Modular system with MPC8260 CPU
+    Manufacturer: MicroSys GmbH, http://www.microsys.de/
+    Date of Release: mid 2001
+    End of life: -
+    URL: http://www.microsys.de/html/pm826.html
+
+  CU824:
+    VMEBus Board with PCI extension with MPC8240 CPU
+    Manufacturer: MicroSys GmbH, http://www.microsys.de/
+    Date of Release: early 2001 (?)
+    End of life: -
+    URL: http://www.microsys.de/html/cu824.html
+
+AltiVec Kernel Support
+CONFIG_ALTIVEC
+  This option enables kernel support for the Altivec extensions to the
+  PowerPC processor. The kernel currently supports saving and restoring
+  altivec registers, and turning on the 'altivec enable' bit so user
+  processes can execute altivec instructions.
+
+  This option is only usefully if you have a processor that supports 
+  altivec (G4, otherwise known as 74xx series), but does not have
+  any affect on a non-altivec cpu (it does, however add code to the
+  kernel).
+
+  If in doubt, say Y here.
+
+Thermal Management Support
+CONFIG_TAU
+  G3 and G4 processors have an on-chip temperature sensor called the
+  'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
+  temperature within 2-4 degrees celcius. This option shows the current
+  on-die temperature in /proc/cpuinfo if the cpu supports it.
+
+  Unfortunately, on some chip revisions, this sensor is very inaccurate
+  and in some cases, does not work at all, so don't assume the cpu
+  temp is actually what /proc/cpuinfo says it is.
+
+Interrupt driven TAU driver
+CONFIG_TAU_INT
+  The TAU supports an interrupt driven mode which causes an interrupt
+  whenever the temperature goes out of range. This is the fastest way
+  to get notified the temp has exceeded a range. With this option off,
+  a timer is used to re-check the temperature periodically.
+
+  However, on some cpus it appears that the TAU interrupt hardware
+  is buggy and can cause a situation which would lead unexplained hard
+  lockups.
+
+  Unless you are extending the TAU driver, or enjoy kernel/hardware
+  debugging, leave this option off.
+
+Average high and low temp
+CONFIG_TAU_AVERAGE
+  The TAU hardware can compare the temperature to an upper and lower bound.
+  The default behavior is to show both the upper and lower bound in 
+  /proc/cpuinfo. If the range is large, the temperature is either changing
+  a lot, or the TAU hardware is broken (likely on some G4's). If the range
+  is small (around 4 degrees), the temperature is relatively stable.
+
+Support for CUDA based PowerMacs
+CONFIG_ADB_CUDA
+  This provides support for CUDA based Power Macintosh systems.  This
+  includes most OldWorld PowerMacs, the first generation iMacs, the
+  Blue&White G3 and the Yikes G4 (PCI Graphics).  All later models
+  should use CONFIG_ADB_PMU instead.
+
+  If unsure say Y.
+
+Support for PMU based PowerMacs
+CONFIG_ADB_PMU
+  This provides support for PMU based Power Macintosh systems.  This
+  includes all PowerBooks and all AGP-based machines.
+  
+  If unsure say Y.
 
 Power management support for PowerBooks
 CONFIG_PMAC_PBOOK
@@ -17005,13 +17290,6 @@
   have it autoloaded. The act of removing the module shuts down the
   sound hardware for more power savings.
 
-Mac-on-Linux support
-CONFIG_MOL
-  This option enables low-level support for Mac-on-Linux.
-  MOL lets you run MacOS and Linux simultaneously. Please
-  visit <http://www.maconlinux.org> for more information.
-  If unsure, say Y.
-
 ADB raw keycode support
 CONFIG_MAC_ADBKEYCODES
   This provides support for sending raw ADB keycodes to console
@@ -17148,16 +17426,6 @@
   and iBook computers. 
 
   This driver is also available as a module called gmac.o ( = code
-  which can be inserted in and removed from the running kernel
-  whenever you want). If you want to compile it as a module, say M
-  here and read Documentation/modules.txt.
-
-Symbios 53c885 (Synergy ethernet) support
-CONFIG_NCR885E
-  This is and Ethernet driver for the dual-function NCR 53C885
-  SCSI/Ethernet controller.
-
-  This driver is also available as a module called ncr885e.o ( = code
   which can be inserted in and removed from the running kernel
   whenever you want). If you want to compile it as a module, say M
   here and read Documentation/modules.txt.
diff -u --recursive --new-file v2.4.9/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- v2.4.9/linux/Documentation/DocBook/Makefile	Wed Jul 25 17:10:16 2001
+++ linux/Documentation/DocBook/Makefile	Sun Sep 16 21:23:15 2001
@@ -24,10 +24,10 @@
 html:	$(HTML)
 
 %.eps: %.fig
-	-fig2dev -Leps $< $@
+	fig2dev -Leps $< $@
 
 %.jpeg: %.fig
-	-fig2dev -Ljpeg $< $@
+	fig2dev -Ljpeg $< $@
 
 %.sgml: %.c
 	echo "<programlisting>" > $@
@@ -88,6 +88,7 @@
 		$(TOPDIR)/arch/i386/kernel/mca.c \
 		$(TOPDIR)/arch/i386/kernel/mtrr.c \
 		$(TOPDIR)/drivers/char/misc.c \
+		$(TOPDIR)/kernel/printk.c \
 		$(TOPDIR)/drivers/net/net_init.c \
 		$(TOPDIR)/drivers/net/8390.c \
 		$(TOPDIR)/drivers/char/serial.c \
@@ -129,7 +130,7 @@
 		$(PERL) $(TOPDIR)/scripts/split-man $(TOPDIR)/Documentation/man
 
 parportbook: $(JPG-parportbook)
-parportbook.ps: $(EPS-parportbook)
+parportbook.ps parportbook.pdf: $(EPS-parportbook)
 parportbook.sgml: parportbook.tmpl $(TOPDIR)/drivers/parport/init.c
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/parport/init.c <$< >$@
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/DocBook/kernel-api.tmpl linux/Documentation/DocBook/kernel-api.tmpl
--- v2.4.9/linux/Documentation/DocBook/kernel-api.tmpl	Thu May 24 15:14:08 2001
+++ linux/Documentation/DocBook/kernel-api.tmpl	Sun Sep  9 12:00:55 2001
@@ -187,6 +187,11 @@
 !Edrivers/block/ll_rw_blk.c
   </chapter>
 
+  <chapter id="part">
+     <title>Partition Handling</title>
+!Edrivers/block/genhd.c
+  </chapter>
+
   <chapter id="miscdev">
      <title>Miscellaneous Devices</title>
 !Edrivers/char/misc.c
diff -u --recursive --new-file v2.4.9/linux/Documentation/DocBook/parportbook.tmpl linux/Documentation/DocBook/parportbook.tmpl
--- v2.4.9/linux/Documentation/DocBook/parportbook.tmpl	Sun Aug 12 13:27:58 2001
+++ linux/Documentation/DocBook/parportbook.tmpl	Fri Sep  7 18:15:17 2001
@@ -1654,6 +1654,16 @@
 
       </listitem></varlistentry>
 
+     <varlistentry><term><constant>PPGETMODE</constant></term>
+      <listitem>
+
+       <para>
+	Retrieves the current IEEE 1284 mode to use for
+	<function>read</function> and <function>write</function>.
+       </para>
+
+      </listitem></varlistentry>
+
      <varlistentry><term><constant>PPGETTIME</constant></term>
       <listitem>
 
@@ -1681,6 +1691,36 @@
 	should be a pointer to a <structname>struct
 	timeval</structname>.
        </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPGETMODES</constant></term>
+      <listitem>
+
+       <para>
+	Retrieves the capabilities of the hardware (i.e. the
+	<structfield>modes</structfield> field of the
+	<structname>parport</structname> structure).
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPSETFLAGS</constant></term>
+      <listitem>
+
+       <para>
+	Sets flags on the <literal>ppdev</literal> device which can
+	affect future I/O operations.  Available flags are:
+       </para>
+
+       <itemizedlist spacing=compact>
+	<listitem><para>
+	  <constant>PP_FASTWRITE</constant></para></listitem>
+	<listitem><para>
+	  <constant>PP_FASTREAD</constant></para></listitem>
+	<listitem><para>
+	  <constant>PP_W91284PIC</constant></para></listitem>
+       </itemizedlist>
 
       </listitem></varlistentry>
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/DocBook/procfs-guide.tmpl linux/Documentation/DocBook/procfs-guide.tmpl
--- v2.4.9/linux/Documentation/DocBook/procfs-guide.tmpl	Tue Jul  3 17:08:18 2001
+++ linux/Documentation/DocBook/procfs-guide.tmpl	Sat Sep  8 12:20:25 2001
@@ -207,7 +207,7 @@
         will return <constant>NULL</constant>. <xref
         linkend="userland"> describes how to do something useful with
         regular files.
-      <para>
+      </para>
 
       <para>
         Note that it is specifically supported that you can pass a
@@ -577,7 +577,7 @@
         the <structfield>owner</structfield> field in the
         <structname>struct proc_dir_entry</structname> to
         <constant>THIS_MODULE</constant>.
-      <para>
+      </para>
 
       <programlisting>
 struct proc_dir_entry* entry;
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/Assabet linux/Documentation/arm/SA1100/Assabet
--- v2.4.9/linux/Documentation/arm/SA1100/Assabet	Fri May 12 11:21:20 2000
+++ linux/Documentation/arm/SA1100/Assabet	Fri Sep  7 09:28:38 2001
@@ -9,38 +9,268 @@
 http://www.cs.cmu.edu/~wearable/software/assabet.html
 
 
-To build the kernel:
+Building the kernel
+-------------------
+
+To build the kernel with current defaults:
 
 	make assabet_config
-	make config
-	[accept all defaults]
+	make oldconfig
 	make dep
 	make zImage
 
-Typically, you'll need angelboot to load the kernel.
-The following angelboot.opt file should be used:
+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 Journaling 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
+----------------------------------
+
+Assabet:
+ Serial ports:
+  Radio:	TX, RX, CTS, DSR, DCD, RI
+  COM:		TX, RX, CTS, DSR, DCD, RTS, DTR, PM
+  I2C:		TX, RX
+  L3:		No
+
+ Video:
+  LCD:		PM
+  Video out:	Not fully
+  Touchscreen:	No
+
+ Audio:
+  Codec:	No
+  POTS:		No
+
+ Other:
+  PCMCIA:	Yes
+  USB:		No
 
------ begin angelboot.opt -----
-base 0xc0008000
-entry 0xc0008000
-r0 0x00000000
-r1 0x00000019
-device /dev/ttyS1
-options "9600 8N1"
-baud 115200
-otherfile ramdisk_img.gz
-otherbase 0xc0800000
-exec minicom
------ end angelboot.opt -----
-
-Then load the kernel and ramdisk with:
-
-	angelboot -f angelboot.opt zImage
-
-Here it is assumed that your Assabet is connected to ttyS1 and that
-minicom is preconfigured with /dev/ttyS1, 9600 baud, 8N1, no flow control
-by default.
+Neponset:
+ Serial ports:
+  COM1,2:	TX, RX, CTS, DSR, DCD, RTS, DTR
 
-This is work in progress...
+More stuff can be found in the -np (Nicolas Pitre's) tree.
 
-Please send any patches to nico@cam.org.
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/DMA linux/Documentation/arm/SA1100/DMA
--- v2.4.9/linux/Documentation/arm/SA1100/DMA	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/arm/SA1100/DMA	Fri Sep  7 09:28:38 2001
@@ -0,0 +1,248 @@
+Support functions for the SA11x0 internal DMA channels
+======================================================
+
+Nicolas Pitre <nico@cam.org>
+Last updated: 2001/07/15
+
+
+The DMA controller consists of six independent DMA channels. Each channel
+can be configured to service any of the serial controllers. Two channels
+are required to service a full-duplex serial controller. The DMA
+controller is intended to relieve the processor of the interrupt overhead
+in servicing these ports with programmed I/ O.
+
+If desired, any or all peripherals (except the UDC) may be serviced with
+programmed I/ O instead of DMA. Each peripheral is capable of requesting
+processor service through its own interrupt lines or through a DMA
+request.
+
+A set of functions is provided to support drivers working with DMA buffers
+through a generic interface for (wishfully) all DMA usages.  Those
+functions will take care of buffer queueing and splitting, DMA register
+management, interrupt handling, etc.
+
+
+SA11x0 DMA API
+--------------
+
+Here is the description for the DMA API.
+
+
+int sa1100_request_dma( dmach_t *channel, const char *device_id,
+			dma_device_t device );
+
+This function will search for a free DMA channel and returns the channel
+number in '*channel'.  'device_id' should point to a string identifying
+the DMA usage or device (mainly for /proc).  'device' is the SA11x0
+peripheral's ports.  Note that reading from a port and writing to the
+same port are actually considered as two different streams requiring
+two DMA channels with their own device type.  All possible dma_device_t
+are defined in include/asm-arm/arch-sa1100/dma.h.  If no channel is
+available, or if the desired device is already in use by another DMA
+channel, then an error code is returned.  This function must be called
+before any other DMA calls.
+
+
+int sa1100_dma_queue_buffer( dmach_t channel, void *buf_id,
+                             dma_addr_t data, int size );
+
+This function enqueue the specified buffer for DMA processing.  The buffer
+will be transmitted or filled with incoming data depending on the channel
+configuration made through sa1100_dma_set_device().  If the queue is
+empty, DMA starts immediately on the given buffer.
+
+Arguments are:
+
+dmach_t channel:	the channel number.
+void *buf_id:		a buffer identification known by the caller.
+dma_addr_t data:	the buffer's physical address.
+int size:		the buffer size in bytes.
+
+Note here the dma_addr_t which is not the same as the virtual address as
+returned by kmalloc() and friends.  The DMA controller must be given a
+physical address to a buffer which is not cached bye the CPU data cache.
+To get such address, the DMA mapping functions (see
+Documentation/DMA-mapping.txt) are recommended.  The only relevant
+functions are pci_alloc_consistent(), pci_map_single() and their unmap
+counterparts.  The PCI dev argument is NULL of course.
+
+There is no restriction on the buffer size.  The DMA code will split it up
+internally to acommodate the DMA controller as needed.  If the buffer
+can't be enqueued the appropriate error code is returned.
+
+
+int sa1100_dma_set_callback( dmach_t channel, dma_callback_t cb );
+
+As soon as the DMa completes with a buffer, a callback function is used to
+notify the driver which would have registered one.  The callback function
+is prototyped as:
+
+void dma_callback( void *buf_id, int size );
+
+The 'buf_id' argument is the buffer identifier as passed to
+sa1100_dma_queue_buffer().  The 'size' argument is the number of bytes the
+DMA processed (should be the same as the buffer size).
+
+Note that this callback function is called while in interrupt context.
+So it has to be small and efficient while posponing more complex
+processing to a bottom-half function or similar.  All
+restrictions for interrupt handlers still apply.
+
+
+int sa1100_dma_get_current( dmach_t channel, void **buf_id,
+                            dma_addr_t *addr );
+
+This returns the buffer ID and the DMA address pointer within the buffer
+currently being processed.  If no such buffer is currently processed, an
+error code is returned.  This is useful for mmap()'ed buffers like in
+audio drivers.
+
+
+int sa1100_dma_stop( dmach_t channel );
+
+This call stops any DMA transfer on the given channel.
+
+
+int sa1100_dma_resume( dmach_t channel );
+
+This call resumes a DMA transfer which would have been stopped through
+sa1100_dma_stop().
+
+
+int sa1100_dma_flush_all( dmach_t channel );
+
+This completely flushes all queued buffers and on-going DMA transfers on a
+given channel.  The next enqueued buffer following this call will be
+processed right away.
+
+
+int sa1100_dma_set_spin( dmach_t channel, dma_addr_t addr, int size );
+
+Because there is at least one device out there that uses its receive
+signal for its transmit clock reference, we need a mecanism to make the
+DMA "spin" on a certain buffer for when there is no more actual buffer to
+process.  The 'addr' argument is the physical memory address to use, and
+the 'size' argument determines the spin DMA chunk.  This size can't be
+larger than 8191 (if so, it is clamped to 4096).  When the size is 0,
+the spin function is turned off.
+
+When activated, DMA will "spin" until there is any buffer in the queue.
+The current DMA chunk will terminate before a newly queued buffer is
+processed.  The spin buffer will only be reused when there is no more
+acctual buffer to process.
+
+It is important not to choose a too small 'size' value since it will
+greatly increase the interrupt load required to restart the spin.  Since
+this feature will typically be used on transmit DMAs, and because a buffer
+full of zeros is probably the best thing to spin out, the 'addr' argument
+may well be used with FLUSH_BASE_PHYS for which no allocation nor memory
+bus request are needed.
+
+The spinning DMA is affected by sa1100_dma_stop() and sa1100_dma_resume()
+but not bu sa1100_dma_flush_all().
+
+
+void sa1100_free_dma( dmach_t channel );
+
+This clears all activities on a given DMA channel and releases it for
+future requests.
+
+
+Buffer allocation
+-----------------
+
+Like mentionned above, it is the driver's responsibility to allocate, free
+and keep track of buffer space with dma_addr_t type addresses. However the
+driver must not change the state of any buffer after it has been sent to
+sa1100-dma_queue_buffer().  When that function has been called, the buffer
+becomes the DMA's ownership until one of these events occur:
+
+- The callback function is called by the DMA code with a buffer ID to
+  indicate that DMA processing terminated on that buffer.  Then the
+  driver owns the buffer again.
+- The sa1100-dma_flush_all() function is called by the driver at which
+  point *all* queued buffers are owned by the driver again.
+- The sa1100-free_dma() does the same as sa1100-dma_flush_all().
+
+This doesn't mean that you can't change the content of a queued buffer in
+conjonction with the usage of pci_map_consistent() and
+sa1100_dma_get_current()... but then you must be sure you know what you're
+doing (this doesn't work with pci_map_single()).
+
+
+Examples
+--------
+
+A real example of audio ring buffers is implemented in the
+drivers/sound/sa1100-audio.c driver.  The SA1110 USB client and the
+SA11x0 FIR drivers are also using this interface to implement packetized
+DMA.
+
+A transmit DMA for network packets could look like this (largely simplified):
+
+struct sk_buff *tx_ring_skb[RING_SIZE];
+dma_addr_t      tx_ring_dma[RING_SIZE];
+int cur_tx;
+...
+
+transmit function:
+
+	tx_ring_skb[cur_tx] = skb;
+	tx_ring_dma[cur_tx] = pci_map_single(NULL, skb->data, skb->len,
+	                                     PCI_DMA_TODEVICE);
+	sa1100_dma_queue_buffer(channel, (void*)cur_tx,
+	                        tx_ring_dma[cur_tx], skb->len);
+	cur_tx++; cur_tx %= RING_SIZE;
+	...
+
+and the callback function:
+
+void tx_done_callback( void *buf_id, int size ) {
+	int done_tx = (int) buf_id;
+	struct sk_buff *skb = tx_ring_skb[done_tx];
+	pci_unmap_single(NULL, tx_ring_dma[done_tx], skb->len,
+	                 PCI_DMA_TODEVICE);
+	stats.tx_packets++;
+	stats.tx_bytes += size;
+	dev_kfree_skb_irq(skb);
+	tx_ring_skb[done_tx] = NULL;
+}
+
+
+For drivers expecting variable length packets i.e. USB client, it is
+necessary to register the appropriate IRQ to be notified when the receiver
+is idle, the packet is complete, etc.  We could use one buffer at a time
+with its ID being the virtual address of the buffer.
+
+Then the sequence:
+
+	/* be sure DMA won't continue under our feet */
+	sa1100_dma_stop(channel);
+	/* get the actual DMA length */
+	sa1100_get_current(channel, &data, &dma_ptr);
+	/* acquire ownership for the buffer */
+	sa1100_dma_flush_all(channel);
+	/* unmap the DMA buffer (actually doing cache coherency on ARM) */
+	pci_unmap_single (NULL, dma_addr, MAX_PKT_SIZE, PCI_DMA_FROMDEVICE);
+	/* get remaining bytes from the fifo */
+	ptr = data + dma_ptr - dma_addr;
+	while (fifo_not_empty)
+		*ptr++ = get_byte_from_fifo;
+	/* feed another free buffer for the next packet */
+	dma_addr2 = pci_map_single(NULL, data2, MAX_PKT_SIZE,
+					PCI_DMA_FROMDEVICE);
+	sa1100_dma_queue_buffer(channel, data2, dma_addr2, MAX_PKT_SIZE);
+	/* process the current packet */
+	...
+
+might do the trick.  This looks a bit ugly but that's a starting point for
+improvements.
+
+
+TODO
+----
+
+- Create kernel-doc comments in the source to document the API and
+  let the documentation be generated automatically.
+
+
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/FreeBird linux/Documentation/arm/SA1100/FreeBird
--- v2.4.9/linux/Documentation/arm/SA1100/FreeBird	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/arm/SA1100/FreeBird	Fri Sep  7 09:28:38 2001
@@ -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>
+
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/GraphicsClient linux/Documentation/arm/SA1100/GraphicsClient
--- v2.4.9/linux/Documentation/arm/SA1100/GraphicsClient	Mon Nov 27 17:07:59 2000
+++ linux/Documentation/arm/SA1100/GraphicsClient	Fri Sep  7 09:28:38 2001
@@ -1,15 +1,18 @@
-ADS GraphicsClient/ThinClient Single Board Computer
+ADS GraphicsClient Plus Single Board Computer
 
 For more details, contact Applied Data Systems or see
-http://www.flatpanels.com/products.html
+http://www.applieddata.net/products.html
 
 The original Linux support for this product has been provided by 
-Nicolas Pitre <nico@cam.org>.
+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.  Use
-'make graphicsclient_config' before any 'make config'.  This will set up
-defaults for GraphicsClient/ThinClient support.
+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:
@@ -17,8 +20,18 @@
 	r0 = 0
 	r1 = 29	(this is the GraphicsClient architecture number)
 
-Here is a tipical angel.opt option file if the kernel is loaded through
-the Angel Debug Monitor:
+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
@@ -26,7 +39,7 @@
 r0 0x00000000
 r1 0x0000001d
 device /dev/ttyS1
-options "9600 8N1"
+options "38400 8N1"
 baud 115200
 #otherfile ramdisk.gz
 #otherbase 0xc0800000
@@ -39,7 +52,7 @@
 	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, 9600 baud, 8N1, no flow
+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
@@ -47,19 +60,39 @@
 
 
 Supported peripherals:
-- SA1100 LCD frame buffer (only 8bpp yet)
-- on-board SMC 92C94 ethernet NIC
+- SA1100 LCD frame buffer (8/16bpp...sort of)
+- on-board SMC 92C96 ethernet NIC
 - SA1100 serial port
-- flash memory access
+- flash memory access (MTD/JFFS)
 - pcmcia
-- possibly UCB1200 audio (not tested yet)
+- 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:
-- touchscreen driver
-- 16bpp frame buffer support
-- extra (external) serial port driver
-- some console keyboard support (maybe IR?)
+- 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!
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/HUW_WEBPANEL linux/Documentation/arm/SA1100/HUW_WEBPANEL
--- v2.4.9/linux/Documentation/arm/SA1100/HUW_WEBPANEL	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/arm/SA1100/HUW_WEBPANEL	Fri Sep  7 09:28:38 2001
@@ -0,0 +1,18 @@
+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 dep
+	make zImage
+
+Mostly of the work is done by:
+Roman Jordan         jor@hoeft-wessel.de
+Christoph Schulz    schu@hoeft-wessel.de
+
+2000/12/18/
+
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/Itsy linux/Documentation/arm/SA1100/Itsy
--- v2.4.9/linux/Documentation/arm/SA1100/Itsy	Wed Oct 20 16:29:07 1999
+++ linux/Documentation/arm/SA1100/Itsy	Fri Sep  7 09:28:38 2001
@@ -2,11 +2,38 @@
 Research Center in Palo Alto, CA. The Itsy project is one of several
 research projects at Compaq that are related to pocket computing.
 
-Itsy support has yet to be fully integrated in this kernel.  Linux 2.0.x
-support is available though.
-
 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 dep and 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.
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/PCMCIA linux/Documentation/arm/SA1100/PCMCIA
--- v2.4.9/linux/Documentation/arm/SA1100/PCMCIA	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/arm/SA1100/PCMCIA	Fri Sep  7 09:28:38 2001
@@ -0,0 +1,374 @@
+Kernel Low-Level PCMCIA Interface Documentation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+John G Dorsey <john+@cs.cmu.edu>
+Updated: 30 June, 2000
+
+
+Note: this interface has not been finalized!
+See also: http://www.cs.cmu.edu/~wearable/software/pcmcia-arm.html
+
+
+Introduction
+
+Early versions of PCMCIA Card Services for StrongARM were designed to
+permit a single socket driver to run on a variety of SA-1100 boards by
+using a userland configuration process. During the conversion to the 2.3
+kernel series, all of the configuration has moved into sub-drivers in the
+kernel proper (see linux/drivers/pcmcia/sa1100*). This document describes
+the low-level interface between those sub-drivers and the sa1100 socket
+driver module.
+
+Presently, there are six operations which must be provided by the
+board-specific code. Only functions whose implementation is likely to
+differ across board designs are required at this level. Some examples
+include:
+
+  - configuring card detect lines to generate interrupts
+  - sensing the legal voltage levels for inserted cards
+  - asserting the reset signal for a card
+
+Functions which are assumed to be the same across all designs are
+performed within the generic socket driver itself. Some examples of these
+kinds of operations include:
+
+  - configuring memory access times based on the core clock frequency
+  - reads/writes on memory, byte swizzling, ...
+
+The current implementation allows the specific per-board set of low-level
+operations to be determined at run time. For each specific board, the
+following structure should be filled in:
+
+  struct pcmcia_low_level {
+    int (*init)(struct pcmcia_init *);
+    int (*shutdown)(void);
+    int (*socket_state)(struct pcmcia_state_array *);
+    int (*get_irq_info)(struct pcmcia_irq_info *);
+    int (*configure_socket)(const struct pcmcia_configure *);
+  };
+
+The component functions are described in detail below. Using the
+machine_is_*() tests, the pointer `pcmcia_low_level' should be assigned to
+the location of the table for your board.
+
+
+0. init(struct pcmcia_init *init)
+
+This operation has three responsibilities:
+
+  - perform any board-specific initialization tasks
+  - associate the given handler with any interrupt-generating signals
+    such as card detection, or battery voltage detection
+  - set up any necessary edge detection for card ready signals
+
+Argument passing for this operation is implemented by the following
+structure:
+
+  struct pcmcia_init {
+    void (*handler)(int irq, void *dev, struct pt_regs *regs);
+    struct pcmcia_maps *maps;
+  };
+
+Here, `handler' is provided by the socket driver, and `maps' must be
+modified if the default mapping isn't appropriate. This operation should
+return one of two values:
+
+  - the highest-numbered socket available, plus one
+  - a negative number, indicating an error in configuration
+
+Note that the former case is _not_ the same as "the number of sockets
+available." In particular, if your design uses SA-1100 slot "one" but
+not slot "zero," you MUST report "2" to the socket driver.
+
+
+1. shutdown(void)
+
+This operation takes no arguments, and will be called during cleanup for
+the socket driver module. Any state associated with the socket controller,
+including allocated data structures, reserved IRQs, etc. should be
+released in this routine.
+
+The return value for this operation is not examined.
+
+
+2. socket_state(struct pcmcia_state_array *state_array)
+
+This operation will be invoked from the interrupt handler which was set up
+in the earlier call to init(). Note, however, that it should not include
+any side effects which would be inappropriate if the operation were to
+occur when no interrupt is pending. (An extra invocation of this operation
+currently takes place to initialize state in the socket driver.)
+
+Argument passing for this operation is handled by a structure which
+contains an array of the following type:
+
+  struct pcmcia_state {
+    unsigned detect: 1,
+              ready: 1,
+               bvd1: 1,
+               bvd2: 1,
+             wrprot: 1,
+              vs_3v: 1,
+              vs_Xv: 1;
+  };
+
+Upon return from the operation, a struct pcmcia_state should be filled in
+for each socket available in the hardware. For every array element (up to
+`size' in the struct pcmcia_state_saarray) which does not correspond to an
+available socket, zero the element bits. (This includes element [0] if
+socket zero is not used.)
+
+Regardless of how the various signals are routed to the SA-1100, the bits
+in struct pcmcia_state always have the following semantics:
+
+  detect - 1 if a card is fully inserted, 0 otherwise
+  ready  - 1 if the card ready signal is asserted, 0 otherwise
+  bvd1   - the value of the Battery Voltage Detect 1 signal
+  bvd2   - the value of the Battery Voltage Detect 2 signal
+  wrprot - 1 if the card is write-protected, 0 otherwise
+  vs_3v  - 1 if the card must be operated at 3.3V, 0 otherwise
+  vs_Xv  - 1 if the card must be operated at X.XV, 0 otherwise
+
+A note about the BVD signals: if your board does not make both lines
+directly observable to the processor, just return reasonable values. The
+standard interpretation of the BVD signals is:
+
+  BVD1  BVD2
+
+   0     x    battery is dead
+   1     0    battery warning
+   1     1    battery ok
+
+Regarding the voltage sense flags (vs_3v, vs_Xv), these bits should be set
+based on a sampling of the Voltage Sense pins, if available. The standard
+interpretation of the VS signals (for a "low-voltage" socket) is:
+
+  VS1   VS2
+
+   0     0    X.XV, else 3.3V, else none
+   0     1    3.3V, else none
+   1     0    X.XV, else none
+   1     1    5V, else none
+
+More information about the BVD and VS conventions is available in chapter
+5 of "PCMCIA System Architecture," 2nd ed., by Don Anderson.
+
+This operation should return 1 if an IRQ is actually pending for the
+socket controller, 0 if no IRQ is pending (but no error condition exists,
+such as an undersized state array), or -1 on any error.
+
+
+3. get_irq_info(struct pcmcia_irq_info *info)
+
+This operation obtains the IRQ assignment which is legal for the given
+socket. An argument of the following type is passed:
+
+  struct pcmcia_irq_info {
+    unsigned int sock;
+    unsigned int irq ;
+  };
+
+The `sock' field contains the socket index being queried. The `irq' field
+should contain the IRQ number corresponding to the card ready signal from
+the device.
+
+This operation should return 0 on success, or -1 on any error.
+
+
+4. configure_socket(const struct pcmcia_configure *configure)
+
+This operation allows the caller to apply power to the socket, issue a
+reset, or enable various outputs. The argument is of the following type:
+
+  struct pcmcia_configure {
+    unsigned sock: 8,
+              vcc: 8,
+              vpp: 8,
+           output: 1,
+          speaker: 1,
+            reset: 1;
+  };
+
+The `sock' field contains the index of the socket to be configured. The
+`vcc' and `vpp' fields contain the voltages to be applied for Vcc and Vpp,
+respectively, in units of 0.1V. (Note that vpp==120 indicates that
+programming voltage should be applied.)
+
+The two output enables, `output' and `speaker', refer to the card data
+signal enable and the card speaker enable, respectively. The `reset' bit,
+when set, indicates that the card reset should be asserted.
+
+This operation should return 0 on success, or -1 on any error.
+
+
+Board-Specific Notes
+
+The following information is known about various SA-11x0 board designs
+which may be used as reference while adding support to the kernel.
+
+
+Carnegie Mellon Itsy/Cue (http://www.cs.cmu.edu/~wearable/itsy/)
+
+  Itsy Chip Select 3 (CS3) Interface
+  ("ITSY MEMORY/PCMCIA ADD-ON BOARD with BATTERY and CHARGER CIRCUITRY,"
+   memo dated 5-20-99, from Tim Manns to Richard Martin, et. al)
+
+  Read:
+    ABVD2    (SS)D0          A slot, Battery Voltage Detect
+    ABVD1    (SS)D1
+    AVSS2    (SS)D2          A slot, Voltage Sense
+    AVSS1    (SS)D3
+    GND      (SS)D4
+    GND      (SS)D5
+    GND      (SS)D6
+    GND      (SS)D7
+  
+    BBVD2    (SS)D8          B slot, Battery Voltage Detect
+    BBVD1    (SS)D9
+    BVSS2    (SS)D10         B slot, Voltage Sense
+    BVSS1    (SS)D11
+    GND      (SS)D12
+    GND      (SS)D13
+    GND      (SS)D14
+    GND      (SS)D15
+  
+  Write:
+    (SS)D0   A_VPP_VCC       LTC1472 VPPEN1
+    (SS)D1   A_VPP_PGM       LTC1472 VPPEN0
+    (SS)D2   A_VCC_3         LTC1472 VCCEN0
+    (SS)D3   A_VCC_5         LTC1472 VCCEN1
+    (SS)D4   RESET (A SLOT)
+    (SS)D5   GND
+    (SS)D6   GND
+    (SS)D7   GND
+ 
+    (SS)D8   B_VPP_VCC       LTC1472 VPPEN1
+    (SS)D9   B_VPP_PGM       LTC1472 VPPEN0
+    (SS)D10  B_VCC_3         LTC1472 VCCEN0
+    (SS)D11  B_VCC_5         LTC1472 VCCEN1
+    (SS)D12  RESET (B SLOT)
+    (SS)D13  GND
+    (SS)D14  GND
+    (SS)D15  GND
+ 
+  GPIO pin assignments are as follows: (from schematics)
+ 
+    GPIO 10                  Slot 0 Card Detect
+    GPIO 11                  Slot 1 Card Detect
+    GPIO 12                  Slot 0 Ready/Interrupt
+    GPIO 13                  Slot 1 Ready/Interrupt
+
+
+
+Intel SA-1100 Multimedia Board (http://developer.intel.com/design/strong/)
+
+  CPLD Registers
+  SA-1100 Multimedia Development Board with Companion SA-1101 Development
+    Board User's Guide, p.4-42
+
+  This SA-1100/1101 development package uses only one GPIO pin (24) to
+  signal changes in card status, and requires software to inspect a
+  PCMCIA status register to determine the source.
+
+  Read: (PCMCIA Power Sense Register - 0x19400000)
+    S0VS1           0        Slot 0 voltage sense
+    S0VS2           1
+    S0BVD1          2        Slot 0 battery voltage sense
+    S0BVD2          3
+    S1VS1           4        Slot 1 voltage sense
+    S1VS2           5
+    S1BVD1          6        Slot 1 battery voltage sense
+    S1BVD2          7
+
+  Read/Write: (PCMCIA Power Control Register - 0x19400002)
+    S0VPP0          0        Slot 0 Vpp
+    S0VPP1          1
+    S0VCC0          2        Slot 0 Vcc
+    S0VCC1          3
+    S1VPP0          4        Slot 1 Vpp
+    S1VPP1          5
+    S1VCC0          6        Slot 1 Vcc
+    S1VCC1          7
+
+  Read: (PCMCIA Status Register - 0x19400004)
+    S0CD1           0        Slot 0 Card Detect 1
+    S0RDY           1        Slot 0 Ready/Interrupt
+    S0STSCHG        2        Slot 0 Status Change
+    S0Reset         3        Slot 0 Reset (RW)
+    S1CD1           4        Slot 1 Card Detect 1
+    S1RDY           5        Slot 1 Ready/Interrupt
+    S1STSCHG        6        Slot 1 Status Change
+    S1Reset         7        Slot 1 Reset (RW)
+
+
+
+Intel SA-1100 Evaluation Platform (http://developer.intel.com/design/strong/)
+
+  Brutus I/O Pins and Chipselect Register
+  pcmcia-brutus.c, by Ivo Clarysse
+  (What's the official reference for this info?)
+
+  This SA-1100 development board uses more GPIO pins than say, the Itsy
+  or the SA-1100/1101 multimedia package. The pin assignments are as
+  follows:
+
+    GPIO 2                   Slot 0 Battery Voltage Detect 1
+    GPIO 3                   Slot 0 Ready/Interrupt
+    GPIO 4                   Slot 0 Card Detect
+    GPIO 5                   Slot 1 Battery Voltage Detect 1
+    GPIO 6                   Slot 1 Ready/Interrupt
+    GPIO 7                   Slot 1 Card Detect
+
+  Like the Itsy, Brutus uses a chipselect register in static memory
+  bank 3 for the other signals, such as voltage sense or reset:
+
+  Read:
+    P0_VS1          8        Slot 0 Voltage Sense
+    P0_VS2          9
+    P0_STSCHG      10        Slot 0 Status Change
+    P1_VS1         12        Slot 1 Voltage Sense
+    P1_VS2         13
+    P1_STSCHG      14        Slot 1 Status Change
+
+  Read/Write:
+    P0_            16        Slot 0 MAX1600EAI control line
+    P0_            17        Slot 0 MAX1600EAI control line
+    P0_            18        Slot 0 MAX1600EAI control line
+    P0_            19        Slot 0 MAX1600EAI control line
+    P0_            20        Slot 0 12V
+    P0_            21        Slot 0 Vpp to Vcc (CONFIRM?)
+    P0_            22        Slot 0 enable fan-out drivers & xcvrs
+    P0_SW_RST      23        Slot 0 Reset
+    P1_            24        Slot 1 MAX1600EAI control line
+    P1_            25        Slot 1 MAX1600EAI control line
+    P1_            26        Slot 1 MAX1600EAI control line
+    P1_            27        Slot 1 MAX1600EAI control line
+    P1_            28        Slot 1 12V
+    P1_            29        Slot 1 Vpp to Vcc (CONFIRM?)
+    P1_            30        Slot 1 enable fan-out drivers & xcvrs
+    P1_SW_RST      31        Slot 1 Reset
+
+  For each slot, the bits labelled "MAX1600EAI" should (apparently)
+  be written with the value 0101 for Vcc 3.3V, and 1001 for Vcc 5V.
+
+
+
+Intel SA-1110 Development Platform (http://developer.intel.com/design/strong/)
+
+  GPIO Pin Descriptions and Board Control Register
+  SA-1110 Microprocessor Development Board User's Guide, p.4-7, 4-10
+
+  The Assabet board contains only a single Compact Flash slot,
+  attached to slot 1 on the SA-1110. Card detect, ready, and BVD
+  signals are routed through GPIO, with power and reset placed in a
+  control register. Note that the CF bus must be enabled before use.
+
+    GPIO 21                  Slot 1 Compact Flash interrupt
+    GPIO 22                  Slot 1 card detect (CD1 NOR CD2)
+    GPIO 24                  Slot 1 Battery Voltage Detect 2
+    GPIO 25                  Slot 1 Battery Voltage Detect 1
+
+  Write-only: (Board Control Register - 0x12000000)
+    CF_PWR          0        CF bus power (3.3V)
+    CF_RST          1        CF reset
+    CF_Bus_On       7        CF bus enable
+
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/Pangolin linux/Documentation/arm/SA1100/Pangolin
--- v2.4.9/linux/Documentation/arm/SA1100/Pangolin	Mon Nov 27 17:07:59 2000
+++ linux/Documentation/arm/SA1100/Pangolin	Fri Sep  7 09:28:38 2001
@@ -1,25 +1,20 @@
-Pangolin is a StrongARM 1110-based evaluation  platform produced
-by Dialogue Technoloy (http://www.dialogue.com.tw/).
+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,
 and TFT-LCD card.
-This platform is currently under development.
 
 To compile for Pangolin, you must issue the following commands:
 
 	make pangolin_config
-	make config
-	[accept all defaults]
+	make oldconfig
 	make dep
 	make zImage
 
 Supported peripherals:
-- SA1110 serial port
+- SA1110 serial port (UART1/UART2/UART3)
 - flash memory access
-
-Testing:
-- pcmcia driver
-- sound driver
-
-To do:
-- MQ-200 driver
+- compact flash driver
+- UDA1341 sound driver
+- SA1100 LCD controller for 800x600 16bpp TFT-LCD
+- MQ-200 driver for 800x600 16bpp TFT-LCD
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/Yopy linux/Documentation/arm/SA1100/Yopy
--- v2.4.9/linux/Documentation/arm/SA1100/Yopy	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/arm/SA1100/Yopy	Fri Sep  7 09:28:38 2001
@@ -0,0 +1,2 @@
+See http://www.yopydeveloper.org for more.
+
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/nanoEngine linux/Documentation/arm/SA1100/nanoEngine
--- v2.4.9/linux/Documentation/arm/SA1100/nanoEngine	Sun Aug 13 09:58:24 2000
+++ linux/Documentation/arm/SA1100/nanoEngine	Fri Sep  7 09:28:38 2001
@@ -4,6 +4,8 @@
 "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>)
 
-Ref: Stuart Adams <sja@brightstareng.com>
+Also visit Larry Doolittle's "Linux for the nanoEngine" site:
+http://recycle.lbl.gov/~ldoolitt/bse/
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/serial_UART linux/Documentation/arm/SA1100/serial_UART
--- v2.4.9/linux/Documentation/arm/SA1100/serial_UART	Mon Nov 27 17:07:59 2000
+++ linux/Documentation/arm/SA1100/serial_UART	Fri Sep  7 09:28:38 2001
@@ -1,5 +1,4 @@
-The SA1100 serial port finally had its major/minor numbers officially 
-assigned:
+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>
@@ -25,7 +24,7 @@
 >                   7 = /dev/cusa2                Callout device for ttySA2
 >
 
-So, if you're not using devfs, you must create those inodes in /dev
+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
@@ -35,31 +34,14 @@
 	mknod cusa1 c 205 6
 	mknod cusa2 c 205 7
 
-Note that the old incorrect use of /dev/ttyS0 in order to use the serial port 
-won't work anymore.  This device node is reserved to the conventionnal 16x50
-UART which may appear on devices like PCMCIA modem, etc.
-
-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 where you might have 
-a getty process started on ttyS0.  In this case you have two choices:
-
-1- replace occurences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc.
-
-2- in the occurence of 'ttyS0', you may consider replacing it with 'console'.
-   as in "T0:12345:respawn:/sbin/getty -L console 9600 vt100"
-
-(don't forget to add 'ttySA0', 'console', or the appropriate tty name 
- in /etc/securetty for root to be allowed to login as well.)
-
-The use of /dev/console has the advantage of being independent of the real
-serial device used.  The kernel automatically forward all operations on
-/dev/console to the apropriate serial device.  The nature of the console may
-also be modified with a kernel command line parameter (see
-Documentation/serial-console.txt for the details).  Of course, 
-/dev/console must have been created as a char device with major 5 minor 1.
-
-Using /dev/console is also compatible with older kernels that used /dev/ttyS0.
-Therefore it is handy for ramdisk images which are targetted for different
-StrongARM platforms and older kernels.
+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 occurences 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.
+
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/fb/README-sstfb.txt linux/Documentation/fb/README-sstfb.txt
--- v2.4.9/linux/Documentation/fb/README-sstfb.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/fb/README-sstfb.txt	Fri Sep  7 09:28:38 2001
@@ -0,0 +1,167 @@
+
+Introduction
+
+	  This is a frame buffer device driver for 3dfx' Voodoo Graphics 
+	(aka voodoo 1, aka sst1) and Voodoo² (aka Voodoo 2, aka CVG) based 
+	video boards. It's highly experimental code, but is guaranteed to work
+	on my computer, with my "Maxi Gamer 3D" and "Maxi Gamer 3d²" boards,
+	and with me "between chair and keyboard". Some people tested other
+	combinations and it seems that it works.
+	  The main page is located at <http://sstfb.sourceforge.net>, and if
+	you want the latest version, check out the CVS, as the driver is a work
+	in progress, i feel incomfortable with releasing tarballs of something
+	not completely working...Don't worry, it's still more than useable
+	(I eat my own dog food)
+
+	  Please read the Bug section, and report any success or failure to me
+	(Ghozlane Toumi <gtoumi@messel.emse.fr>).
+	  BTW, If you have only one monitor , and you don't feel like playing
+	with the vga passthrou cable, I can only suggest borrowing a screen
+	somewhere... 
+
+
+Installation 
+
+	  This driver (should) work on ix86, with any 2.2.x kernel (tested
+	with x = 19) and "recent" 2.4.x kernel, as a module or compiled in.
+	  You can apply the patches found in sstfb/kernel/*-2.{2|4}.x.patch,
+	and copy sstfb.c to linux/drivers/video/, or apply a single patch, 
+	sstfb/patch-2.{2|4}.x-sstfb-yymmdd to your linux source tree.
+
+	  Then configure your kernel as usual: choose "m" or "y" to 3Dfx Voodoo
+	Graphics in section "console". Compile, install, have fun... and please
+	drop me a report :)
+
+
+Module Usage
+	
+	Warnings.
+	# You should read completely this section before issuing any command.
+	# If you have only one monitor to play with, once you insmod the
+	  module, the 3dfx takes control of the output, so you'll have to
+	  plug the monitor to the "normal" video board in order to issue
+	  the commands, or you can blindly use sst_dbg_vgapass
+          in the tools directory (See Tools). The latest option is pass the
+	  parameter vgapass=1 when insmodding the driver. (See Kernel/Modules
+	  Options)
+
+	Module insertion:
+	# insmod sstfb.o
+	  you should see some strange output frome the board: 
+	  a big blue square, a green and a red small squares and a vertical
+	  white rectangle. why ? the function's name is self explanatory :
+	  "sstfb_test()"...
+	  (if you don't have a second monitor, you'll have to plug your monitor
+	  directely to the 2D videocard to see what you're typing)
+	# con2fb /dev/fbx /dev/ttyx
+	  bind a tty to the new frame buffer. if you already have a frame
+	  buffer driver, the voodoo fb will likely be /dev/fb1. if not, 
+	  the device will be /dev/fb0. You can check this by doing a 
+	  cat /proc/fb. You can find a copy of con2fb in tools/ directory.
+	  if you don't have another fb device, this step is superfluous,
+	  as the console subsystem automagicaly binds ttys to the fb.
+	# switch to the virtual console you just mapped. "tadaaa" ...
+
+	Module removal:
+	# con2fb /dev/fbx /dev/ttyx
+	  bind the tty to the old frame buffer so the module can be removed.
+	  (how does it work with vgacon ? short answer : it doesn't work)
+	# rmmod sstfb
+
+
+Kernel/Modules Options
+
+	You can pass some otions to sstfb module, and via the kernel command
+	line when the driver is compiled in :
+	for module : insmod sstfb.o option1=value1 option2=value2 ...
+	in kernel :  video=sstfb:option1,option2:value2,option3 ...
+	
+	sstfb supports the folowing options :
+	module		kernel		description
+
+	vgapass=1	vgapass		enable or disable VGA passthrou cable
+	vgapass=0	vganopass	when enabled, the monitor will
+					get the signal from the VGA board
+					and not from the voodoo. default nopass
+
+	mem=x		mem:x		force frame buffer memory in MiB
+					allowed values: 1, 2, 4. default detect
+
+	inverse=1	inverse		suposed to enable inverse console.
+					doesn't work ...
+
+	clipping=1	clipping	enable or disable clipping . with
+	clipping=0	noclipping	clipping enabled, all offscreen reads
+					and writes are disgarded. default:
+					enable clipping.
+
+	gfxclk=x	gfxclk:x	force graphic clock frequency (in MHz)
+					becarefull with this option .
+					default is 50Mhz for voodoo1, 75MHz
+					for voodoo2. Be carefull, this one is
+					dangerous. default=auto
+
+	slowpci=0	slowpci		enable or disable fast PCI read/writes
+	slowpci=1	fastpci		default : fastpci
+
+	dev=x		dev:x		attach the driver to device number x
+					0 is the first compatible board (in 
+					lspci order)
+
+Tools
+
+	These tools are mostly for debugging purposes, but you can 
+	find some of these interesting :
+	 - con2fb , maps a tty to a fbramebuffer .
+		con2fb /dev/fb1 /dev/tty5
+	 - sst_dbg_vgapass , changes vga passthrou. You have to recompile the
+	driver with SST_DEBUG and SST_DEBUG_IOCTL set to 1
+		sst_dbg_vgapass /dev/fb1 1 (enables vga cable)
+		sst_dbg_vgapass /dev/fb1 0 (disables vga cable)
+	 - glide_reset , resets the voodoo using glide
+		use this after rmmoding sstfb, if the module refuses to
+		reinsert .
+
+Bugs
+
+	- DO NOT use glide while the sstfb module is in, you'll most likely
+	hang your computer.
+	- if you see some artefacts (pixels not cleaning and stuff like that), 
+	try turning off clipping (clipping=0)
+	- the driver don't detect the 4Mb frame buffer voodoos, it seems that
+	the 2 last Mbs wrap around. looking into that .
+	- The driver is 16 bpp only, 24/32 won't work.
+	- The driver is not your_favorite_toy-safe. this includes SMP...
+          [Actually from inspection it seems to be safe - Alan]
+	- when using XFree86 FBdev (X over fbdev) you may see strange color
+	patterns at the border of your windows (the pixels loose the lowest
+	byte -> basicaly the blue component nd some of the green) . I'm unable
+	to reproduce this with XFree86-3.3, but one of the testers has this
+	problem with XFree86-4. I don't know yet if this is the drivers fault
+	or X's (most likely the driver, of course).
+	- I didn't really test changing the palette, so you may find some weird
+	things when playing with that.
+	- Sometimes the driver will not recognise the DAC , and the
+        initialisation will fail. this is specificaly true for
+	voodoo 2 boards , but it should be solved in recent versions. please
+	contact me .
+	- the 24/32 is not likely to work anytime soon , knowing that the
+	hardware does ... unusual thigs in 24/32 bpp
+
+Todo
+
+	- Get rid of the previous paragraph.
+	- Buy more coffee.
+	- test/port to other arch.
+	- try to add panning using tweeks with front and back buffer .
+	- try to implement accel en voodoo2 , this board can actualy do a 
+	  lot in 2D even if it was sold as a 3D only board ...
+
+ghoz.
+
+-- 
+Ghozlane Toumi <gtoumi@messel.emse.fr>
+
+
+$Date: 2001/08/29 00:21:11 $
+http://sstfb.sourceforge.net/README
diff -u --recursive --new-file v2.4.9/linux/Documentation/filesystems/ntfs.txt linux/Documentation/filesystems/ntfs.txt
--- v2.4.9/linux/Documentation/filesystems/ntfs.txt	Mon Aug 27 12:41:37 2001
+++ linux/Documentation/filesystems/ntfs.txt	Tue Sep 11 17:02:46 2001
@@ -64,6 +64,25 @@
 			Be careful not to write anything to them or you could
 			crash the kernel and/or corrupt your file system!
 
+mft_zone_multiplier=	Set the MFT zone multiplier for the volume (this
+			setting is not persistent across mounts and can be
+			changed from mount to mount but cannot be changed on
+			remount). Values of 1 to 4 are allowed, 1 being the
+			default. The MFT zone multiplier determines how much
+			space is reserved for the MFT on the volume. If all
+			other space is used up, then the MFT zone will be
+			shrunk dynamically, so this has no impact on the
+			amount of free space. However, it can have an impact
+			on performance by affecting fragmentation of the MFT.
+			In general use the default. If you have a lot of small
+			files then use a higher value. The values have the
+			following meaning:
+			      Value	     MFT zone size (% of volume size)
+				1		12.5%
+				2		25%
+				3		37.5%
+				4		50%
+
 Known bugs and (mis-)features
 =============================
 
@@ -71,10 +90,6 @@
   use it, get the Linux-NTFS tools and use the ntfsfix utility after
   dismounting a partition you wrote to.
 
-- Use the show_sys_files mount option which should make things work generally
-  better. (It results in both the short and long file names being shown as well
-  as the sytem files.)
-
 - Writing of extension records is not supported properly.
 
 Please send bug reports/comments/feed back/abuse to the Linux-NTFS development
@@ -82,6 +97,96 @@
 
 ChangeLog
 =========
+
+NTFS 1.1.19:
+	- Fixed ntfs_getdir_unsorted(), ntfs_readdir() and ntfs_printcb() to
+	  cope with arbitrary cluster sizes. Very important for Win2k+. Also,
+	  make them detect directories which are too large and truncate the
+	  enumeration pretending end of directory was reached. Detect more
+	  error conditions and overflows. All this fixes the problem where the
+	  driver could end up in an infinite loop under certain circumstances.
+	- Fixed potential memory leaks in Unicode conversion functions and
+	  setup correct NULL return values.
+
+NTFS 1.1.18:
+
+	- Enhanced & bug fixed cluster deallocation (race fixes, etc.)
+	- Complete rewrite of cluster allocation, now race free.
+	- Fixed several bugs in the attribute modification codepaths.
+	- Hopefully fixed bug where the first sectors of some people's
+	  partitions would be overwritten by the mft. And in general fixed up
+	  mft extension code a bit (still incomplete though).
+	- Introduce splice_runlist() to allow generic splicing of two run
+	  lists into one.
+	- MFT zone is now implemented. [Stage 2 of 3; only lack dynamic
+	  growing of mft zone but that is AFAIK not even done by Windows, and
+	  the overhead would be so large that it is probably not worth doing
+	  at all, so Stage 3 might never happen...]
+	- Complete rewrite of $MFT extension and ntfs inode allocation code.
+	- Made the NTFS driver initialization string show the compile options
+	  used (i.e. whether read-only or read-write, whether a module, and
+	  whether with debug support).
+	- Modify ntfs_fill_mft_header() to set all fields and to accept more
+	  arguments.
+	- Get rid of superfluous add_mft_header().
+	- Get rid of some unused code.
+	- Fixed several bugs in and generally cleaned up ntfs_readdir,
+	  ntfs_getdir_unsorted(), and ntfs_printcb. Now they spew out huge
+	  amounts of debug output if debugging is enabled. This will be
+	  removed once I know that this works for everyone.
+	- ntfs_readdir now shows hidden files. The only files that are now
+	  hidden are the first 16 inodes (i.e. the hard coded system files),
+	  which is consistent with Windows NT4. Using the show_sys_files mount
+	  option, these files are then shown, too.
+	- Fixed the displaying of the "." and ".." directories. We still cannot
+	  cope with more than 65536 files in a directory index block which is
+	  not a problem and we now cannot cope with more than 32766 directory
+	  index blocks which should not be a problem unless you have a
+	  directory with an insanely large number of files in it. The exact
+	  number depends on the length of the file names of the directory
+	  entries and on the size of the dircetory index blocks.
+	- Fixed all problems with the last file in a directory (e.g. the last
+	  file should no longer disappear and tab completion should work). If
+	  there are still disappearing files or any other problems with the
+	  last file in a directory, please report them! Thanks.
+	- Rewrote ntfs_extend_attr() to use the new cluster allocator and the
+	  freshly introduced splice_runlists() function. This simplified
+	  ntfs_extend_attr() a lot which in turn seems to have removed one or
+	  more bugs from it.
+	- Probably other things I have forgotten... (-;
+	- Removed dollar signs from the names in the system file enumeration.
+	  Apparently gcc doesn't support dollar signs on PPC architecture.
+	  (Andrzej Krzysztofowicz)
+
+NTFS 1.1.17:
+
+	- Fixed system file handling. No longer need to use show_sys_files
+	  option for driver to work fine. System files are now always treated
+	  the same, but without the option, they are made invisible to
+	  directory listings. As a result system files can once again be opened
+	  even without the show_sys_files option. This is important for the
+	  statfs system call to work properly, for example.
+	- Implemented MFT zone including mount parameter to tune it (just like
+	  in Windows via the registry, only we make it per mount rather than
+	  global for the whole driver, so we are better but we have no way of
+	  storing the value as we don't have a registry so either specify on
+	  each mount or put it in /etc/fstab). [Stage 1 of 3, mount parameter
+	  handling.]
+	- Fixed fixup functions to handle corruption cases and to return error
+	  codes to the caller.
+	- Made fixup functions apply hotfixes where sensible. [Stage 1 of 2+,
+	  in memory only.]
+	- Fixed ommission of "NTFS: " string in ntfs_error() output.
+	- Fixed stupid if statement bug in unistr.c. Thanks to Yann E. Morin
+	  for spotting it. 
+	- Get rid of all uses of max and min macros. This actually allowed for
+	  optimizing the code in several places so it was a Good Thing(TM).
+	- Make ntfs use generic_file_open to enforce the O_LARGEFILE flag.
+	- Detect encrypted files and refuse to access them (return EACCES
+	  error code to user space).
+	- Fix handling of encrypted & compressed files so that an encrypted
+	  file no longer is considered to be compressed (this was causing
+	  kernel segmentation faults).
 
 NTFS 1.1.16:
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/ide.txt linux/Documentation/ide.txt
--- v2.4.9/linux/Documentation/ide.txt	Sat Feb 26 20:32:12 2000
+++ linux/Documentation/ide.txt	Fri Sep  7 09:28:38 2001
@@ -314,7 +314,7 @@
  "ide0=ht6560b"		: probe/support HT6560B interface
  "ide0=cmd640_vlb"	: *REQUIRED* for VLB cards with the CMD640 chip
 			  (not for PCI -- automatically detected)
- "ide0=qd6580"		: probe/support qd6580 interface
+ "ide0=qd65xx"		: probe/support qd65xx interface
  "ide0=ali14xx"		: probe/support ali14xx chipsets (ALI M1439/M1445)
  "ide0=umc8672"		: probe/support umc8672 chipsets
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/input/cs461x.txt linux/Documentation/input/cs461x.txt
--- v2.4.9/linux/Documentation/input/cs461x.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/input/cs461x.txt	Wed Sep 12 15:34:06 2001
@@ -0,0 +1,45 @@
+Preface.
+
+This is a new low-level driver to support analog joystick attached to
+Crystal SoundFusion CS4610/CS4612/CS4615. This code is based upon 
+Vortex/Solo drivers as an example of decoration style, and ALSA
+0.5.8a kernel drivers as an chipset documentation and samples.
+
+This version does not have cooked mode support; the basic code 
+is present here, but have not tested completely. The button analysis 
+is completed in this mode, but the axis movement is not. 
+
+Raw mode works fine with analog joystick front-end driver and cs461x
+driver as a backend. I've tested this driver with CS4610, 4-axis and 
+4-button joystick; I mean the jstest utility. Also I've tried to
+play in xracer game using joystick, and the result is better than
+keyboard only mode.
+
+The sensitivity and calibrate quality have not been tested; the two
+reasons are performed: the same hardware cannot work under Win95 (blue 
+screen in VJOYD); I have no documentation on my chip; and the existing 
+behavior in my case was not raised the requirement of joystick calibration. 
+So the driver have no code to perform hardware related calibration.
+
+The patch contains minor changes of Config.in and Makefile files. All
+needed code have been moved to one separate file cs461x.c like ns558.c
+This driver have the basic support for PCI devices only; there is no
+ISA or PnP ISA cards supported. AFAIK the ns558 have support for Crystal 
+ISA and PnP ISA series.
+
+The driver works witn ALSA drivers simultaneously. For exmple, the xracer
+uses joystick as input device and PCM device as sound output in one time.
+There are no sound or input collisions detected. The source code have
+comments about them; but I've found the joystick can be initialized 
+separately of ALSA modules. So, you canm use only one joystick driver
+without ALSA drivers. The ALSA drivers are not needed to compile or
+run this driver.
+
+There are no debug information print have been placed in source, and no
+specific options required to work this driver. The found chipset parameters
+are printed via printk(KERN_INFO "..."), see the /var/log/messages to
+inspect cs461x: prefixed messages to determine possible card detection 
+errors.
+
+Regards,
+Viktor
diff -u --recursive --new-file v2.4.9/linux/Documentation/input/ff.txt linux/Documentation/input/ff.txt
--- v2.4.9/linux/Documentation/input/ff.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/input/ff.txt	Wed Sep 12 15:34:06 2001
@@ -0,0 +1,194 @@
+Force feedback for Linux.
+By Johann Deneux <deneux@ifrance.com> on 2001/04/22.
+
+----------------------------------------------------------------------------
+
+0. Introduction
+~~~~~~~~~~~~~~~
+This document describes how to use force feedback devices under Linux. The
+goal is not to support these devices as if they were simple input-only devices
+(as it is already the case), but to really enable the rendering of force
+effects.
+At the moment, only I-Force devices are supported, and not officially. That
+means I had to find out how the protocol works on my own. Of course, the
+information I managed to grasp is far from being complete, and I can not
+guarranty that this driver will work for you.
+This document only describes the force feedback part of the driver for I-Force
+devices. Please read joystick.txt before reading further this document.
+
+2. Instructions to the user
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Here are instructions on how to compile and use the driver. In fact, this
+driver is the normal iforce.o, input.o and evdev.o drivers written by Vojtech
+Pavlik, plus additions to support force feedback.
+
+Before you start, let me WARN you that some devices shake violently during the
+initialisation phase. This happens for example with my "AVB Top Shot Pegasus".
+To stop this annoying behaviour, move you joystick to its limits. Anyway, you
+should keep a hand on your device, in order to avoid it to brake down if
+something goes wrong.
+
+At the kernel's compilation:
+	- Enable IForce/Serial
+	- Enable Event interface
+
+Compile the modules, install them.
+
+You also need inputattach.
+
+You then need to insert the modules into the following order:
+% modprobe joydev
+% modprobe serport
+% modprobe iforce
+% modprobe evdev
+% ./inputattach -ifor $2 &	# Only for serial
+For convenience, you may use the shell script named "ff" available from
+the cvs tree of the Linux Console Project at sourceforge. You can also
+retrieve it from http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/.
+If you are using USB, you don't need the inputattach step.
+
+Please check that you have all the /dev/input entries needed:
+cd /dev
+rm js*
+mkdir input
+mknod input/js0 c 13 0
+mknod input/js1 c 13 1
+mknod input/js2 c 13 2
+mknod input/js3 c 13 3
+ln -s input/js0 js0
+ln -s input/js1 js1
+ln -s input/js2 js2
+ln -s input/js3 js3
+
+mknod input/event0 c 13 64
+mknod input/event1 c 13 65
+mknod input/event2 c 13 66
+mknod input/event3 c 13 67
+
+2.1 Does it work ?
+~~~~~~~~~~~~~~~~~~
+There is an utility called fftest that will allow you to test the driver.
+% fftest /dev/eventXX
+
+3. Instructions to the developper
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  All interactions are done using the event API. That is, you can use ioctl()
+and write() on /dev/input/eventXX.
+  This information is subject to change.
+
+3.1 Querying device capabilities
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#include <linux/input.h>
+#include <sys/ioctl.h>
+
+int ioctl(int file_descriptor, int request, unsigned long *features);
+
+"request" must be EVIOCGBIT(EV_FF, sizeof(unsigned long))
+
+Returns the features supported by the device. features is a bitfield with the
+following bits:
+- FF_X		has an X axis (should allways be the case)
+- FF_Y		has an Y axis (usually not the case for wheels)
+- FF_CONSTANT	can render constant force effects
+- FF_PERIODIC	can render periodic effects (sine, ramp, square...)
+- FF_SPRING	can simulate the presence of a spring
+- FF_FRICTION	can simulate friction (aka drag, damper effect...)
+- FF_RUMBLE	rumble effects (normally the only effect supported by rumble
+		pads)
+- 8 bits from FF_N_EFFECTS_0 containing the number of effects that can be
+		simultaneously played.
+
+3.2 Uploading effects to the device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#include <linux/input.h>
+#include <sys/ioctl.h>
+ 
+int ioctl(int file_descriptor, int request, struct ff_effect *effect);
+
+"request" must be EVIOCSFF.
+
+"effect" points to a structure describing the effect to upload. The effect is
+uploaded, but not played.
+The content of effect may be modified. In particular, its field "id" is set
+to the unique id assigned by the driver. This data is required for performing
+some operations (removing an effect, controlling the playback).
+See <linux/input.h> for a description of the ff_effect stuct.
+
+3.3 Removing an effect from the device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+int ioctl(int fd, EVIOCRMFF, effect.id);
+
+This makes room for new effects in the device's memory. Please note this won't
+stop the effect if it was playing.
+
+3.4 Controlling the playback of effects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Control of playing is done with write(). Below is an example:
+
+#include <linux/input.h>
+#include <unistd.h>
+
+	struct input_event play;
+	struct input_event stop;
+	struct ff_effect effect;
+	int fd;
+...
+	fd = open("/dev/input/eventXX", O_RDWR);
+...
+	/* Play three times */
+	play.type = EV_FF;
+	play.code = effect.id;
+	play.value = 3;
+	
+	write(fd, (const void*) &play, sizeof(play));
+...
+	/* Stop an effect */
+	stop.type = EV_FF;
+	stop.code = effect.id;
+	stop.value = 0;
+	
+	write(fd, (const void*) &play, sizeof(stop));
+
+3.5 Setting the gain
+~~~~~~~~~~~~~~~~~~~~
+Not all devices have the same strength. Therefore, users should set a gain
+factor depending on how strong they want effects to be. This setting is
+persistent accross access to the driver, so you should not care about it if
+you are writing games, as another utility probably already set this for you.
+
+/* Set the gain of the device
+int gain;		/* between 0 and 100 */
+struct input_event ie;	/* structure used to communicate with the driver */
+
+ie.type = EV_FF;
+ie.code = FF_GAIN;
+ie.value = 0xFFFFUL * gain / 100;
+
+if (write(fd, &ie, sizeof(ie)) == -1)
+	perror("set gain");
+
+3.6 Enabling/Disabling autocenter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The autocenter feature quite disturbs the rendering of effects in my opinion,
+and I think it should be an effect, which computation depends on the game
+type. But you can enable it if you want.
+
+int autocenter;		/* between 0 and 100 */
+struct input_event ie;
+
+ie.type = EV_FF;
+ie.code = FF_AUTOCENTER;
+ie.value = 0xFFFFUL * autocenter / 100;
+
+if (write(fd, &ie, sizeof(ie)) == -1)
+	perror("set auto-center");
+
+A value of 0 means "no auto-center".
+
+3.7 Dynamic update of an effect
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This consists in changing some parameters of an effect while it's playing. The
+driver currently does not support that. You still have the brute-force method,
+which consists in erasing the effect and uploading the updated version. It
+actually works pretty well. You don't need to stop-and-start the effect.
+
diff -u --recursive --new-file v2.4.9/linux/Documentation/input/gameport-programming.txt linux/Documentation/input/gameport-programming.txt
--- v2.4.9/linux/Documentation/input/gameport-programming.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/input/gameport-programming.txt	Wed Sep 12 15:34:06 2001
@@ -0,0 +1,189 @@
+$Id: gameport-programming.txt,v 1.3 2001/04/24 13:51:37 vojtech Exp $
+
+Programming gameport drivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. A basic classic gameport
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the gameport doesn't provide more than the inb()/outb() functionality,
+the code needed to register it with the joystick drivers is simple:
+
+	struct gameport gameport;
+
+	gameport.io = MY_IO_ADDRESS;
+	gameport_register_port(&gameport);
+
+Make sure struct gameport is initialized to 0 in all other fields. The
+gameport generic code will take care of the rest.
+
+If your hardware supports more than one io address, and your driver can
+choose which one program the hardware to, starting from the more exotic
+addresses is preferred, because the likelyhood of clashing with the standard
+0x201 address is smaller.
+
+Eg. if your driver supports addresses 0x200, 0x208, 0x210 and 0x218, then
+0x218 would be the address of first choice.
+
+If your hardware supports a gameport address that is not mapped to ISA io
+space (is above 0x1000), use that one, and don't map the ISA mirror.
+
+Also, always request_region() on the whole io space occupied by the
+gameport. Although only one ioport is really used, the gameport usually
+occupies from one to sixteen addresses in the io space.
+
+Please also consider enabling the gameport on the card in the ->open()
+callback if the io is mapped to ISA space - this way it'll occupy the io
+space only when something really is using it. Disable it again in the
+->close() callback. You also can select the io address in the ->open()
+callback, so that it doesn't fail if some of the possible addresses are
+already occupied by other gameports.
+
+2. Memory mapped gameport
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When a gameport can be accessed through MMIO, this way is preferred, because
+it is faster, allowing more reads per second. Registering such a gameport
+isn't as easy as a basic IO one, but not so much complex:
+
+	struct gameport gameport;
+
+	void my_trigger(struct gameport *gameport)
+	{
+		my_mmio = 0xff;
+	}
+
+	unsigned char my_read(struct gameport *gameport)
+	{
+		return my_mmio;	
+	}
+
+	gameport.read = my_read;
+	gameport.trigger = my_trigger;
+	gameport_register_port(&gameport);
+
+3. Cooked mode gameport
+~~~~~~~~~~~~~~~~~~~~~~~
+
+There are gameports that can report the axis values as numbers, that means
+the driver doesn't have to measure them the old way - an ADC is built into
+the gameport. To register a cooked gameport:
+
+	struct gameport gameport;
+
+	int my_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+	{
+		int i;
+
+		for (i = 0; i < 4; i++)
+			axes[i] = my_mmio[i];
+		buttons[i] = my_mmio[4];
+	}
+
+	int my_open(struct gameport *gameport, int mode)
+	{
+		return -(mode != GAMEPORT_MODE_COOKED);
+	}
+
+	gameport.cooked_read = my_cooked_read;
+	gameport.open = my_open;
+	gameport.fuzz = 8;
+	gameport_register_port(&gameport);
+
+The only confusing thing here is the fuzz value. Best determined by
+experimentation, it is the amount of noise in the ADC data. Perfect
+gameports can set this to zero, most common have fuzz between 8 and 32.
+See analog.c and input.c for handling of fuzz - the fuzz value determines
+the size of a gaussian filter window that is used to eliminate the noise
+in the data.
+
+4. More complex gameports
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Gameports can support both raw and cooked modes. In that case combine either
+examples 1+2 or 1+3. Gameports can support internal calibration - see below,
+and also lightning.c and analog.c on how that works. If your driver supports
+more than one gameport instance simultaneously, use the ->private member of
+the gameport struct to point to your data.
+
+5. Unregistering a gameport
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Simple:
+
+gameport_unregister_port(&gameport);
+
+6. The gameport structure
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+struct gameport {
+
+	void *private;
+
+A private pointer for free use in the gameport driver. (Not the joystick
+driver!)
+
+	int number;
+
+Number assigned to the gameport when registered. Informational purpose only.
+
+	int io;
+
+I/O address for use with raw mode. You have to either set this, or ->read()
+to some value if your gameport supports raw mode.
+
+	int speed;
+
+Raw mode speed of the gameport reads in thousands of reads per second.
+
+	int fuzz;
+
+If the gameport supports cooked mode, this should be set to a value that
+represents the amount of noise in the data. See section 3.
+
+	void (*trigger)(struct gameport *);
+
+Trigger. This function should trigger the ns558 oneshots. If set to NULL,
+outb(0xff, io) will be used.
+
+	unsigned char (*read)(struct gameport *);
+
+Read the buttons and ns558 oneshot bits. If set to NULL, inb(io) will be
+used instead.
+
+	int (*cooked_read)(struct gameport *, int *axes, int *buttons);	
+
+If the gameport supports cooked mode, it should point this to its cooked
+read function. It should fill axes[0..3] with four values of the joystick axes
+and buttons[0] with four bits representing the buttons.
+
+	int (*calibrate)(struct gameport *, int *axes, int *max); 
+
+Function for calibrating the ADC hardware. When called, axes[0..3] should be
+pre-filled by cooked data by the caller, max[0..3] should be pre-filled with
+expected maximums for each axis. The calibrate() function should set the
+sensitivity of the ADC hardware so that the maximums fit in its range and
+recompute the axes[] values to match the new sensitivity or re-read them from
+the hardware so that they give valid values. 
+
+	int (*open)(struct gameport *, int mode);
+
+Open() serves two purposes. First a driver either opens the port in raw or
+in cooked mode, the open() callback can decide which modes are supported.
+Second, resource allocation can happen here. The port can also be enabled
+here. Prior to this call, other fields of the gameport struct (namely the io
+member) need not to be valid.
+
+	void (*close)(struct gameport *);
+
+Close() should free the resources allocated by open, possibly disabling the
+gameport.
+
+	struct gameport_dev *dev;
+	struct gameport *next;
+
+For internal use by the gameport layer.
+
+};
+
+Enjoy!
diff -u --recursive --new-file v2.4.9/linux/Documentation/input/input-programming.txt linux/Documentation/input/input-programming.txt
--- v2.4.9/linux/Documentation/input/input-programming.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/input/input-programming.txt	Wed Sep 12 15:34:06 2001
@@ -0,0 +1,271 @@
+$Id: input-programming.txt,v 1.4 2001/05/04 09:47:14 vojtech Exp $
+
+Programming input drivers
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Creating an input device driver
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1.0 The simplest example
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here comes a very simple example of an input device driver. The device has
+just one button and the button is accessible at i/o port BUTTON_PORT. When
+pressed or released a BUTTON_IRQ happens. The driver could look like:
+
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+
+static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
+{
+	input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT) & 1);
+}
+
+static int __init button_init(void)
+{
+	if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
+                printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
+                return -EBUSY;
+        }
+	
+	button_dev.evbit[0] = BIT(EV_KEY);
+	button_dev.keybit[LONG(BTN_0)] = BIT(BTN_0);
+	
+	input_register_device(&button_dev);
+}
+
+static void __exit button_exit(void)
+{
+        input_unregister_device(&button_dev);
+	free_irq(BUTTON_IRQ, button_interrupt);
+}
+
+module_init(button_init);
+module_exit(button_exit);
+
+1.1 What the example does
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+First it has to include the <linux/input.h> file, which interfaces to the
+input subsystem. This provides all the definitions needed.
+
+In the _init function, which is called either upon module load or when
+booting the kernel, it grabs the required resources (it should also check
+for the presence of the device).
+
+Then it sets the input bitfields. This way the device driver tells the other
+parts of the input systems what it is - what events can be generated or
+accepted by this input device. Our example device can only generate EV_KEY type
+events, and from those only BTN_0 event code. Thus we only set these two
+bits. We could have used
+
+	set_bit(EV_KEY, button_dev.evbit);
+	set_bit(BTN_0, button_dev.keybit);
+
+as well, but with more than single bits the first approach tends to be
+shorter. 
+
+Then the example driver registers the input device structure by calling
+
+	input_register_device(&button_dev);
+
+This adds the button_dev structure to linked lists of the input driver and
+calls device handler modules _connect functions to tell them a new input
+device has appeared. Because the _connect functions may call kmalloc(,
+GFP_KERNEL), which can sleep, input_register_device() must not be called
+from an interrupt or with a spinlock held.
+
+While in use, the only used function of the driver is
+
+	button_interrupt()
+
+which upon every interrupt from the button checks its state and reports it
+via the 
+
+	input_report_btn()
+
+call to the input system. There is no need to check whether the interrupt
+routine isn't reporting two same value events (press, press for example) to
+the input system, because the input_report_* functions check that
+themselves.
+
+1.2 dev->open() and dev->close()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In case the driver has to repeatedly poll the device, because it doesn't
+have an interrupt coming from it and the polling is too expensive to be done
+all the time, or if the device uses a valuable resource (eg. interrupt), it
+can use the open and close callback to know when it can stop polling or
+release the interrupt and when it must resume polling or grab the interrupt
+again. To do that, we would add this to our example driver:
+
+int button_used = 0;
+
+static int button_open(struct input_dev *dev)
+{
+        if (button_used++)
+                return 0;
+
+	if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
+                printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
+                button_used--;
+                return -EBUSY;
+        }
+
+        return 0;
+}
+
+static void button_close(struct input_dev *dev)
+{
+        if (!--button_used)
+                free_irq(IRQ_AMIGA_VERTB, button_interrupt);
+}
+
+static int __init button_init(void)
+{
+	...
+	button_dev.open = button_open;
+	button_dev.close = button_close;
+	...
+}
+
+Note the button_used variable - we have to track how many times the open
+function was called to know when exactly our device stops being used.
+
+The open() callback should return a 0 in case of succes or any nonzero value
+in case of failure. The close() callback (which is void) must always succeed.
+
+1.3 Basic event types
+~~~~~~~~~~~~~~~~~~~~~
+
+The most simple event type is EV_KEY, which is used for keys and buttons.
+It's reported to the input system via:
+
+	input_report_key(struct input_dev *dev, int code, int value)
+
+See linux/input.h for the allowable values of code (from 0 to KEY_MAX).
+Value is interpreted as a truth value, ie any nonzero value means key
+pressed, zero value means key released. The input code generates events only
+in case the value is different from before.
+
+In addition to EV_KEY, there are two more basic event types: EV_REL and
+EV_ABS. They are used for relative and absolute values supplied by the
+device. A relative value may be for example a mouse movement in the X axis.
+The mouse reports it as a relative difference from the last position,
+because it doesn't have any absolute coordinate system to work in. Absolute
+events are namely for joysticks and digitizers - devices that do work in an
+absolute coordinate systems.
+
+Having the device report EV_REL buttons is as simple as with EV_KEY, simply
+set the corresponding bits and call the
+
+	input_report_rel(struct input_dev *dev, int code, int value)
+
+function. Events are generated only for nonzero value. 
+
+However EV_ABS requires a little special care. Before calling
+input_register_devices, you have to fill additional fields in the input_dev
+struct for each absolute axis your device has. If our button device had also
+the ABS_X axis:
+
+	button_dev.absmin[ABS_X] = 0;
+	button_dev.absmax[ABS_X] = 255;
+	button_dev.absfuzz[ABS_X] = 4;
+	button_dev.absflat[ABS_X] = 8;
+
+This setting would be appropriate for a joystick X axis, with the minimum of
+0, maximum of 255 (which the joystick *must* be able to reach, no problem if
+it sometimes reports more, but it must be able to always reach the min and
+max values), with noise in the data up to +- 4, and with a center flat
+position of size 8.
+
+If you don't need absfuzz and absflat, you can set them to zero, which mean
+that the thing is precise and always returns to exactly the center position
+(if it has any).
+
+1.4 The void *private field
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This field in the input structure can be used to point to any private data
+structures in the input device driver, in case the driver handles more than
+one device. You'll need it in the open and close callbacks.
+
+1.5 NBITS(), LONG(), BIT()
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These three macros frin input.h help some bitfield computations:
+
+	NBITS(x) - returns the length of a bitfield array in longs for x bits
+	LONG(x)  - returns the index in the array in longs for bit x
+	BIT(x)   - returns the indes in a long for bit x
+
+1.6 The number, id* and name fields
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The dev->number is assigned by the input system to the input device when it
+is registered. It has no use except for identifying the device to the user
+in system messages.
+
+The dev->name should be set before registering the input device by the input
+device driver. It's a string like 'Generic button device' containing an
+user friendly name of the device.
+
+The id* fields contain the bus ID (PCI, USB, ...), vendor ID and device ID
+of the device. The bus IDs are defined in input.h. The vendor and device ids
+are defined in pci_ids.h, usb_ids.h and similar include files. These fields
+should be set by the input device driver before registering it.
+
+The idtype field can be used for specific information for the input device
+driver.
+
+The id and name fields can be passed to userland via the evdev interface.
+
+1.7 The keycode, keycodemax, keycodesize fields
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These two fields will be used for any inpur devices that report their data
+as scancodes. If not all scancodes can be known by autodetection, they may
+need to be set by userland utilities. The keycode array then is an array
+used to map from scancodes to input system keycodes. The keycode max will
+contain the size of the array and keycodesize the size of each entry in it
+(in bytes).
+
+1.8 Key autorepeat
+~~~~~~~~~~~~~~~~~~
+
+... is simple. It is handled by the input.c module. Hardware autorepeat is
+not used, because it's not present in many devices and even where it is
+present, it is broken sometimes (at keyboards: Toshiba notebooks). To enable
+autorepeat for your device, just set EV_REP in dev->evbit. All will be
+handled by the input system.
+
+1.9 Other event types, handling output events
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The other event types up to now are:
+
+EV_LED - used for the keyboad LEDs.
+EV_SND - used for keyboard beeps.
+
+They are very similar to for example key events, but they go in the other
+direction - from the system to the input device driver. If your input device
+driver can handle these events, it has to set the respective bits in evbit,
+*and* also the callback routine:
+
+	button_dev.event = button_event;
+
+int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+{
+	if (type == EV_SND && code == EV_BELL) {
+		outb(value, BUTTON_BELL);
+		return 0;
+	}
+	return -1;
+}
+
+This callback routine can be called from an interrupt or a BH (although that
+isn't a rule), and thus must not sleep, and must not take too long to finish.
diff -u --recursive --new-file v2.4.9/linux/Documentation/input/input.txt linux/Documentation/input/input.txt
--- v2.4.9/linux/Documentation/input/input.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/input/input.txt	Wed Sep 12 15:34:06 2001
@@ -0,0 +1,297 @@
+			  Linux Input drivers v1.0
+	       (c) 1999-2001 Vojtech Pavlik <vojtech@suse.cz>
+			     Sponsored by SuSE
+	    $Id: input.txt,v 1.5 2001/06/06 11:05:33 vojtech Exp $
+----------------------------------------------------------------------------
+
+0. Disclaimer
+~~~~~~~~~~~~~
+  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
+
+  Should you need to contact me, the author, you can do so either by e-mail
+- mail your message to <vojtech@suse.cz>, or by paper mail: Vojtech Pavlik,
+Simunkova 1594, Prague 8, 182 00 Czech Republic
+
+  For your convenience, the GNU General Public License version 2 is included
+in the package: See the file COPYING.
+
+1. Introduction
+~~~~~~~~~~~~~~~
+  This is a collection of drivers that is designed to support all input
+devices under Linux. However, in the current kernels, although it's
+possibilities are much bigger, it's limited to USB devices only. This is
+also why it resides in the drivers/usb subdirectory.
+
+  The center of the input drivers is the input.o module, which must be
+loaded before any other of the input modules - it serves as a way of
+communication between two groups of modules:
+
+1.1 Device drivers
+~~~~~~~~~~~~~~~~~~
+  These modules talk to the hardware (for example via USB), and provide
+events (keystrokes, mouse movements) to the input.o module.
+
+1.2 Event handlers
+~~~~~~~~~~~~~~~~~~
+  These modules get events from input.o and pass them where needed via
+various interfaces - keystrokes to the kernel, mouse movements via a
+simulated PS/2 interface to GPM and X and so on.
+
+2. Simple Usage
+~~~~~~~~~~~~~~~
+  For the most usual configuration, with one USB mouse and one USB keyboard,
+you'll have to load the following modules (or have them built in to the
+kernel):
+
+	input.o
+	mousedev.o
+	keybdev.o
+	usbcore.o
+	usb-[uo]hci.o
+	hid.o
+
+  After this, the USB keyboard will work straight away, and the USB mouse
+will be available as a character device on major 13, minor 63:
+
+	crw-r--r--   1 root     root      13,  63 Mar 28 22:45 mice
+
+  This device, has to be created, unless you use devfs, in which case it's
+created automatically. The commands to do that are:
+
+	cd /dev
+	mkdir input
+	mknod input/mice c 13 63
+
+  After that you have to point GPM (the textmode mouse cut&paste tool) and
+XFree to this device to use it - GPM should be called like:
+
+	gpm -t ps2 -m /dev/input/mice
+
+  And in X:
+
+	Section "Pointer"
+	    Protocol    "ImPS/2"
+	    Device      "/dev/input/mice"
+	    ZAxisMapping 4 5
+	EndSection
+
+  When you do all of the above, you can use your USB mouse and keyboard.
+
+3. Detailed Description
+~~~~~~~~~~~~~~~~~~~~~~~
+3.1 Device drivers
+~~~~~~~~~~~~~~~~~~
+  Device drivers are the modules that generate events. The events are
+however not useful without being handled, so you also will need to use some
+of the modules from section 3.2.
+
+3.1.1 hid.c
+~~~~~~~~~~~
+  Hid.c is the largest and most complex driver of the whole suite. It
+handles all HID devices, and because there is a very wide variety of them,
+and because the USB HID specification isn't simple, it needs to be this big.
+
+  Currently, it handles USB mice, joysticks, gamepads, steering wheels
+keyboards, trackballs and digitizers.
+
+ However, USB uses HID also for monitor controls, speaker controls, UPSs,
+LCDs and many other purposes.
+
+ The monitor and speaker controls should be easy to add to the hid/input
+interface, but for the UPSs and LCDs it doesn't make much sense. For this,
+the hiddev interface was designed. See Documentation/usb/hiddev.txt
+for more information about it.
+
+  The usage of the hid.o module is very simple, it takes no parameters,
+detects everything automatically and when a HID device is inserted, it
+detects it appropriately.
+
+  However, because the devices vary wildly, you might happen to have a
+device that doesn't work well. In that case #define DEBUG at the beginning
+of hid.c and send me the syslog traces.
+
+3.1.2 usbmouse.c
+~~~~~~~~~~~~~~~~
+  For embedded systems, for mice with broken HID descriptors and just any
+other use when the big hid.c wouldn't be a good choice, there is the
+usbmouse.c driver. It handles USB mice only. It uses a simpler HIDBP
+protocol. This also means the mice must support this simpler protocol. Not
+all do. If you don't have any strong reason to use this module, use hid.c
+instead.
+
+3.1.3 usbkbd.c
+~~~~~~~~~~~~~~
+  Much like usbmouse.c, this module talks to keyboards with a simpplified
+HIDBP protocol. It's smaller, but doesn't support any extra special keys.
+Use hid.c instead if there isn't any special reason to use this.
+
+3.1.4 wacom.c
+~~~~~~~~~~~~~
+  This is a driver for Wacom Graphire and Intuos tablets. Not for Wacom
+PenPartner, that one is handled by the HID driver. Although the Intuos and
+Graphire tablets claim that they are HID tablets as well, they are not and
+thus need this specific driver.
+
+3.1.5 iforce.c
+~~~~~~~~~~~~~~~
+  A driver for I-Force joysticks and wheels, both over USB and RS232. 
+It includes ForceFeedback support now, even though Immersion Corp. considers
+the protocol a trade secret and won't disclose a word about it.
+
+3.2 Event handlers
+~~~~~~~~~~~~~~~~~~
+  Event handlers distrubite the events from the devices to userland and
+kernel, as needed.
+
+3.2.1 keybdev.c
+~~~~~~~~~~~~~~~
+  Keybdev is currently a rather ugly hack that translates the input events
+into architecture-specific keyboard raw mode (Xlated AT Set2 on x86), and
+passes them into the handle_scancode function of the keyboard.c module. This
+works well enough on all architectures that keybdev can generate rawmode on,
+other architectures can be added to it.
+
+  The right way would be to pass the events to keyboard.c directly, best if
+keyboard.c would itself be an event handler. This is done in the input
+patch, available on the webpage mentioned below.
+
+3.2.2 mousedev.c
+~~~~~~~~~~~~~~~~
+  Mousedev is also a hack to make programs that use mouse input work. It
+takes events from either mice or digitizers/tablets and makes a PS/2-style
+(a la /dev/psaux) mouse device available to the userland. Ideally, the
+programs could use a more reasonable interface, for example evdev.c
+
+  Mousedev devices in /dev/input (as shown above) are:
+
+	crw-r--r--   1 root     root      13,  32 Mar 28 22:45 mouse0
+	crw-r--r--   1 root     root      13,  33 Mar 29 00:41 mouse1
+	crw-r--r--   1 root     root      13,  34 Mar 29 00:41 mouse2
+	crw-r--r--   1 root     root      13,  35 Apr  1 10:50 mouse3
+	...
+	...
+	crw-r--r--   1 root     root      13,  62 Apr  1 10:50 mouse30
+	crw-r--r--   1 root     root      13,  63 Apr  1 10:50 mice
+
+Each 'mouse' device is assigned to a single mouse or digitizer, except the last
+one - 'mice'. This single character device is shared by all mice and
+digitizers, and even if none are connected, the device is present.  This is
+useful for hotplugging USB mice, so that programs can open the device even when
+no mice are present.
+
+  CONFIG_INPUT_MOUSEDEV_SCREEN_[XY] in the kernel configuration are the size
+of your screen (in pixels) in XFree86. This is needed if you want to use
+your digitizer in X, because it's movement is sent to X via a virtual PS/2
+mouse and thus needs to be scaled accordingly. These values won't be used if
+you use a mouse only.
+
+  Mousedev will generate either PS/2, ImPS/2 (Microsoft IntelliMouse) or
+ExplorerPS/2 (IntelliMouse Explorer) protocols, depending on what the program
+reading the data wishes. You can set GPM and X to any of these. You'll need
+ImPS/2 if you want to make use of a wheel on a USB mouse and ExplorerPS/2 if you
+want to use extra (up to 5) buttons. 
+
+3.2.3 joydev.c
+~~~~~~~~~~~~~~
+  Joydev implements v0.x and v1.x Linux joystick api, much like
+drivers/char/joystick/joystick.c used to in earlier versions. See
+joystick-api.txt in the Documentation subdirectory for details.  As soon as
+any joystick is connected, it can be accessed in /dev/input on:
+
+	crw-r--r--   1 root     root      13,   0 Apr  1 10:50 js0
+	crw-r--r--   1 root     root      13,   1 Apr  1 10:50 js1
+	crw-r--r--   1 root     root      13,   2 Apr  1 10:50 js2
+	crw-r--r--   1 root     root      13,   3 Apr  1 10:50 js3
+	...
+
+And so on up to js31.
+
+3.2.4 evdev.c
+~~~~~~~~~~~~~
+  Evdev is the generic input event interface. It passes the events generated
+in the kernel straight to the program, with timestamps. The API is still
+evolving, but should be useable now. It's described in section 5.
+
+  This should be the way for GPM and X to get keyboard and mouse mouse
+events. It allows for multihead in X without any specific multihead kernel
+support. The event codes are the same on all architectures and are hardware
+independent.
+
+  The devices are in /dev/input:
+
+	crw-r--r--   1 root     root      13,  64 Apr  1 10:49 event0
+	crw-r--r--   1 root     root      13,  65 Apr  1 10:50 event1
+	crw-r--r--   1 root     root      13,  66 Apr  1 10:50 event2
+	crw-r--r--   1 root     root      13,  67 Apr  1 10:50 event3
+	...
+
+3. Contacts
+~~~~~~~~~~~
+  This effort has it's home page at:
+
+	http://www.suse.cz/development/input/
+
+You'll find both the latest HID driver and the complete Input driver there
+as well as information how to access the CVS repository for latest revisions
+of the drivers.
+
+  There is also a mailing list for this:
+
+	majordomo@atrey.karlin.mff.cuni.cz
+
+Send "subscribe linux-input" to subscribe to it.
+
+4. Verifying if it works
+~~~~~~~~~~~~~~~~~~~~~~~~
+  Typing a couple keys on the keyboard should be enough to check that a USB
+keyboard works and is correctly connected to the kernel keyboard driver.
+
+  Doing a cat /dev/input/mouse0 (c, 13, 32) will verify that a mouse is also
+emulated, characters should appear if you move it.
+
+  You can test the joystick emulation with the 'jstest' utility, available
+in the joystick package (see Documentation/joystick.txt).
+
+  You can test the event devics with the 'evtest' utitily available on the
+input driver homepage (see the URL above).
+
+5. Event interface
+~~~~~~~~~~~~~~~~~~
+  Should you want to add event device support into any application (X, gpm,
+svgalib ...) I <vojtech@suse.cz> will be happy to provide you any help I
+can. Here goes a description of the current state of things, which is going
+to be extended, but not changed incompatibly as time goes:
+
+  You can use blocking and nonblocking reads, also select() on the
+/dev/input/eventX devices, and you'll always get a whole number of input
+events on a read. Their layout is:
+
+struct input_event {
+	struct timeval time;
+	unsigned short type;
+	unsigned short code;
+	unsigned int value;
+};
+
+  'time' is the timestamp, it returns the time at which the event happened.
+Type is for example EV_REL for relative momement, REL_KEY for a keypress or
+release. More types are defined in include/linux/input.h.
+
+  'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
+list is in include/linux/input.h.
+
+  'value' is the value the event carries. Either a relative change for
+EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for
+release, 1 for keypress and 2 for autorepeat.
diff -u --recursive --new-file v2.4.9/linux/Documentation/input/joystick-api.txt linux/Documentation/input/joystick-api.txt
--- v2.4.9/linux/Documentation/input/joystick-api.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/input/joystick-api.txt	Wed Sep 12 15:34:06 2001
@@ -0,0 +1,316 @@
+		      Joystick API Documentation                -*-Text-*-
+
+		        Ragnar Hojland Espinosa
+			  <ragnar@macula.net>
+
+			      7 Aug 1998
+
+	$Id: joystick-api.txt,v 1.2 2001/05/08 21:21:23 vojtech Exp $
+
+1. Initialization
+~~~~~~~~~~~~~~~~~
+
+Open the joystick device following the usual semantics (that is, with open).
+Since the driver now reports events instead of polling for changes,
+immediately after the open it will issue a series of synthetic events
+(JS_EVENT_INIT) that you can read to check the initial state of the
+joystick.
+
+By default, the device is opened in blocking mode.
+
+	int fd = open ("/dev/js0", O_RDONLY);
+
+
+2. Event Reading
+~~~~~~~~~~~~~~~~
+
+	struct js_event e;
+	read (fd, &e, sizeof(struct js_event));
+
+where js_event is defined as
+
+	struct js_event {
+		__u32 time;     /* event timestamp in milliseconds */
+		__s16 value;    /* value */
+		__u8 type;      /* event type */
+		__u8 number;    /* axis/button number */
+	};
+
+If the read is successful, it will return sizeof(struct js_event), unless
+you wanted to read more than one event per read as described in section 3.1.
+
+
+2.1 js_event.type
+~~~~~~~~~~~~~~~~~
+
+The possible values of ``type'' are
+
+	#define JS_EVENT_BUTTON         0x01    /* button pressed/released */
+	#define JS_EVENT_AXIS           0x02    /* joystick moved */
+	#define JS_EVENT_INIT           0x80    /* initial state of device */
+
+As mentioned above, the driver will issue synthetic JS_EVENT_INIT ORed
+events on open. That is, if it's issuing a INIT BUTTON event, the
+current type value will be
+
+	int type = JS_EVENT_BUTTON | JS_EVENT_INIT;	/* 0x81 */
+
+If you choose not to differentiate between synthetic or real events
+you can turn off the JS_EVENT_INIT bits
+
+	type &= ~JS_EVENT_INIT;				/* 0x01 */
+
+
+2.2 js_event.number
+~~~~~~~~~~~~~~~~~~~
+
+The values of ``number'' correspond to the axis or button that
+generated the event. Note that they carry separate numeration (that
+is, you have both an axis 0 and a button 0). Generally,
+
+			number
+	1st Axis X	0
+	1st Axis Y	1
+	2nd Axis X	2
+	2nd Axis Y	3
+	...and so on
+
+Hats vary from one joystick type to another. Some can be moved in 8
+directions, some only in 4, The driver, however, always reports a hat as two
+independent axis, even if the hardware doesn't allow independent movement.
+
+
+2.3 js_event.value
+~~~~~~~~~~~~~~~~~~
+
+For an axis, ``value'' is a signed integer between -32767 and +32767
+representing the position of the joystick along that axis. If you
+don't read a 0 when the joystick is `dead', or if it doesn't span the
+full range, you should recalibrate it (with, for example, jscal).
+
+For a button, ``value'' for a press button event is 1 and for a release
+button event is 0.
+
+Though this
+
+	if (js_event.type == JS_EVENT_BUTTON) {
+		buttons_state ^= (1 << js_event.number);
+	}
+
+may work well if you handle JS_EVENT_INIT events separately,
+
+	if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) {
+		if (js_event.value)
+	        	buttons_state |= (1 << js_event.number);
+	   	else
+	      		buttons_state &= ~(1 << js_event.number);
+	}
+
+is much safer since it can't lose sync with the driver. As you would
+have to write a separate handler for JS_EVENT_INIT events in the first
+snippet, this ends up being shorter.
+
+
+2.4 js_event.time
+~~~~~~~~~~~~~~~~~
+
+The time an event was generated is stored in ``js_event.time''. It's a time
+in milliseconds since ... well, since sometime in the past.  This eases the
+task of detecting double clicks, figuring out if movement of axis and button
+presses happened at the same time, and similar.
+
+
+3. Reading
+~~~~~~~~~~
+
+If you open the device in blocking mode, a read will block (that is,
+wait) forever until an event is generated and effectively read. There
+are two alternatives if you can't afford to wait forever (which is,
+admittedly, a long time;)
+
+	a) use select to wait until there's data to be read on fd, or
+	   until it timeouts. There's a good example on the select(2)
+	   man page.
+
+	b) open the device in non-blocking mode (O_NONBLOCK)
+
+
+3.1 O_NONBLOCK
+~~~~~~~~~~~~~~
+
+If read returns -1 when reading in O_NONBLOCK mode, this isn't
+necessarily a "real" error (check errno(3)); it can just mean there
+are no events pending to be read on the driver queue. You should read
+all events on the queue (that is, until you get a -1).
+
+For example,
+
+	while (1) {
+		while (read (fd, &e, sizeof(struct js_event)) > 0) {
+	        	process_event (e);
+	   	}
+	   	/* EAGAIN is returned when the queue is empty */
+	   	if (errno != EAGAIN) {
+	      		/* error */
+	   	}
+	   	/* do something interesting with processed events */
+	}
+
+One reason for emptying the queue is that if it gets full you'll start
+missing events since the queue is finite, and older events will get
+overwritten.
+
+The other reason is that you want to know all what happened, and not
+delay the processing till later.
+
+Why can get the queue full? Because you don't empty the queue as
+mentioned, or because too much time elapses from one read to another
+and too many events to store in the queue get generated. Note that
+high system load may contribute to space those reads even more.
+
+If time between reads is enough to fill the queue and loose an event,
+the driver will switch to startup mode and next time you read it,
+synthetic events (JS_EVENT_INIT) will be generated to inform you of
+the actual state of the joystick.
+
+[As for version 1.2.8, the queue is circular and able to hold 64
+ events. You can increment this size bumping up JS_BUFF_SIZE in
+ joystick.h and recompiling the driver.]
+
+
+In the above code, you might as well want to read more than one event
+at a time using the typical read(2) functionality. For that, you would
+replace the read above with something like
+
+	struct js_event mybuffer[0xff];
+	int i = read (fd, mybuffer, sizeof(struct mybuffer));
+
+In this case, read would return -1 if the queue was empty, or some
+other value in which the number of events read would be i /
+sizeof(js_event)  Again, if the buffer was full, it's a good idea to
+process the events and keep reading it until you empty the driver queue.
+
+
+4. IOCTLs
+~~~~~~~~~
+
+The joystick driver defines the following ioctl(2) operations.
+
+				/* function			3rd arg  */
+	#define JSIOCGAXES	/* get number of axes		char	 */
+	#define JSIOCGBUTTONS	/* get number of buttons	char	 */
+	#define JSIOCGVERSION	/* get driver version		int	 */
+	#define JSIOCGNAME(len) /* get identifier string	char	 */
+	#define JSIOCSCORR	/* set correction values	&js_corr */
+	#define JSIOCGCORR	/* get correction values	&js_corr */
+
+For example, to read the number of axes
+
+	char number_of_axes;
+	ioctl (fd, JSIOCGAXES, &number_of_axes);
+
+
+4.1 JSIOGCVERSION
+~~~~~~~~~~~~~~~~~
+
+JSIOGCVERSION is a good way to check in run-time whether the running
+driver is 1.0+ and supports the event interface. If it is not, the
+IOCTL will fail. For a compile-time decision, you can test the
+JS_VERSION symbol
+
+	#ifdef JS_VERSION
+	#if JS_VERSION > 0xsomething
+
+
+4.2 JSIOCGNAME
+~~~~~~~~~~~~~~
+
+JSIOCGNAME(len) allows you to get the name string of the joystick - the same
+as is being printed at boot time. The 'len' argument is the length of the
+buffer provided by the application asking for the name. It is used to avoid
+possible overrun should the name be too long.
+
+	char name[128];
+	if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
+		strncpy(name, "Unknown", sizeof(name));
+	printf("Name: %s\n", name);
+
+
+4.3 JSIOC[SG]CORR
+~~~~~~~~~~~~~~~~~
+
+For usage on JSIOC[SG]CORR I suggest you to look into jscal.c  They are
+not needed in a normal program, only in joystick calibration software
+such as jscal or kcmjoy. These IOCTLs and data types aren't considered
+to be in the stable part of the API, and therefore may change without
+warning in following releases of the driver.
+
+Both JSIOCSCORR and JSIOCGCORR expect &js_corr to be able to hold
+information for all axis. That is, struct js_corr corr[MAX_AXIS];
+
+struct js_corr is defined as
+
+	struct js_corr {
+		__s32 coef[8];
+		__u16 prec;
+		__u16 type;
+	};
+
+and ``type''
+
+	#define JS_CORR_NONE            0x00    /* returns raw values */
+	#define JS_CORR_BROKEN          0x01    /* broken line */
+
+
+5. Backward compatibility
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The 0.x joystick driver API is quite limited and its usage is deprecated.
+The driver offers backward compatibility, though. Here's a quick summary:
+
+	struct JS_DATA_TYPE js;
+	while (1) {
+		if (read (fd, &js, JS_RETURN) != JS_RETURN) {
+	      		/* error */
+	   	}
+	   	usleep (1000);
+	}
+
+As you can figure out from the example, the read returns immediately,
+with the actual state of the joystick.
+
+	struct JS_DATA_TYPE {
+		int buttons;    /* immediate button state */
+		int x;          /* immediate x axis value */
+		int y;          /* immediate y axis value */
+	};
+
+and JS_RETURN is defined as
+
+	#define JS_RETURN       sizeof(struct JS_DATA_TYPE)
+
+To test the state of the buttons,
+
+	first_button_state  = js.buttons & 1;
+	second_button_state = js.buttons & 2;
+
+The axis values do not have a defined range in the original 0.x driver,
+except for that the values are non-negative. The 1.2.8+ drivers use a
+fixed range for reporting the values, 1 being the minimum, 128 the
+center, and 255 maximum value.
+
+The v0.8.0.2 driver also had an interface for 'digital joysticks', (now
+called Multisystem joysticks in this driver), under /dev/djsX. This driver
+doesn't try to be compatible with that interface.
+
+
+6. Final Notes
+~~~~~~~~~~~~~~
+
+____/|	Comments, additions, and specially corrections are welcome.
+\ o.O|	Documentation valid for at least version 1.2.8 of the joystick
+ =(_)=	driver and as usual, the ultimate source for documentation is
+   U	to "Use The Source Luke" or, at your convenience, Vojtech ;)
+
+					- Ragnar
+EOF
diff -u --recursive --new-file v2.4.9/linux/Documentation/input/joystick-parport.txt linux/Documentation/input/joystick-parport.txt
--- v2.4.9/linux/Documentation/input/joystick-parport.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/input/joystick-parport.txt	Wed Sep 12 15:34:06 2001
@@ -0,0 +1,533 @@
+		    Linux Joystick parport drivers v2.0
+	       (c) 1998-2000 Vojtech Pavlik <vojtech@suse.cz>
+	       (c) 1998 Andree Borrmann <a.borrmann@tu-bs.de>
+			     Sponsored by SuSE
+	$Id: joystick-parport.txt,v 1.5 2001/05/15 06:41:00 vojtech Exp $
+----------------------------------------------------------------------------
+
+0. Disclaimer
+~~~~~~~~~~~~~
+  Any information in this file is provided as-is, without any guarantee that
+it will be true. So, use it at your own risk. The possible damages that can
+happen include burning your parallel port, and/or the sticks and joystick
+and maybe even more. Like when a lightning kills you it is not our problem.
+
+1. Intro
+~~~~~~~~
+  The joystick parport drivers are used for joysticks and gamepads not
+originally designed for PCs and other computers Linux runs on. Because of
+that, PCs usually lack the right ports to connect these devices to. Parallel
+port, because of its ability to change single bits at will, and providing
+both output and input bits is the most suitable port on the PC for
+connecting such devices.
+
+2. Devices supported
+~~~~~~~~~~~~~~~~~~~~
+  Many console and 8-bit computer gamepads and joysticks are supported. The
+following subsections discuss usage of each.
+
+2.1 NES and SNES
+~~~~~~~~~~~~~~~~
+  The Nintendo Entertainment System and Super Nintendo Entertainment System
+gamepads are widely available, and easy to get. Also, they are quite easy to
+connect to a PC, and don't need much processing speed (108 us for NES and
+165 us for SNES, compared to about 1000 us for PC gamepads) to communicate
+with them.
+
+  All NES and SNES use the same synchronous serial protocol, clocked from
+the computer's side (and thus timing insensitive). To allow up to 5 NES
+and/or SNES gamepads connected to the parallel port at once, the output
+lines of the parallel port are shared, while one of 5 available input lines
+is assigned to each gamepad.
+
+  This protocol is handled by the gamecon.c driver, so that's the one
+you'll use for NES and SNES gamepads.
+
+  The main problem with PC parallel ports is that they don't have +5V power
+source on any of their pins. So, if you want a reliable source of power
+for your pads, use either keyboard or joystick port, and make a pass-through
+cable. You can also pull the power directly from the power supply (the red
+wire is +5V).
+
+  If you want to use the parallel port only, you can take the power is from
+some data pin. For most gamepad and parport implementations only one pin is
+needed, and I'd recommend pin 9 for that, the highest data bit. On the other
+hand, if you are not planning to use anything else than NES / SNES on the
+port, anything between and including pin 4 and pin 9 will work.
+
+(pin 9) -----> Power
+
+  Unfortunately, there are pads that need a lot more of power, and parallel
+ports that can't give much current through the data pins. If this is your
+case, you'll need to use diodes (as a prevention of destroying your parallel
+port), and combine the currents of two or more data bits together.
+
+	   Diodes
+(pin 9) ----|>|-------+------> Power
+		      |
+(pin 8) ----|>|-------+
+		      |
+(pin 7) ----|>|-------+
+		      |
+ <and so on>          :
+		      |
+(pin 4) ----|>|-------+
+
+  Ground is quite easy. On PC's parallel port the ground is on any of the
+pins from pin 18 to pin 25. So use any pin of these you like for the ground.
+
+(pin 18) -----> Ground
+
+  NES and SNES pads have two input bits, Clock and Latch, which drive the
+serial transfer. These are connected to pins 2 and 3 of the parallel port,
+respectively.
+
+(pin 2) -----> Clock
+(pin 3) -----> Latch
+
+  And the last thing is the NES / SNES data wire. Only that isn't shared and
+each pad needs its own data pin. The parallel port pins are:
+
+(pin 10) -----> Pad 1 data
+(pin 11) -----> Pad 2 data
+(pin 12) -----> Pad 3 data
+(pin 13) -----> Pad 4 data
+(pin 15) -----> Pad 5 data
+
+  Note that pin 14 is not used, since it is not an input pin on the parallel
+port.
+
+  This is everything you need on the PC's side of the connection, now on to
+the gamepads side. The NES and SNES have different connectors. Also, there
+are quite a lot of NES clones, and because Nintendo used proprietary
+connectors for their machines, the cloners couldn't and used standard D-Cannon
+connectors. Anyway, if you've got a gamepad, and it has buttons A, B, Turbo
+A, Turbo B, Select and Start, and is connected through 5 wires, then it is
+either a NES or NES clone and will work with this connection. SNES gamepads
+also use 5 wires, but have more buttons. They will work as well, of course.
+
+Pinout for NES gamepads                 Pinout for SNES gamepads
+
+	   +----> Power                   +-----------------------\
+	   |                            7 | o  o  o  o |  x  x  o  | 1
+ 5 +---------+  7                         +-----------------------/
+   | x  x  o   \                            |  |  |  |          |
+   | o  o  o  o |                           |  |  |  |          +-> Ground
+ 4 +------------+ 1                         |  |  |  +------------> Data
+     |  |  |  |                             |  |  +---------------> Latch
+     |  |  |  +-> Ground                    |  +------------------> Clock
+     |  |  +----> Clock                     +---------------------> Power
+     |  +-------> Latch
+     +----------> Data
+
+Pinout for NES clone (db9) gamepads     Pinout for NES clone (db15) gamepads
+
+	+---------> Clock                    +-----------------> Data
+	| +-------> Latch                    |             +---> Ground
+	| | +-----> Data                     |             |
+	| | |                              ___________________
+    _____________                        8 \ o x x x x x x o / 1
+  5 \ x o o o x / 1                         \ o x x o x x o /
+     \ x o x o /                          15 `~~~~~~~~~~~~~' 9
+    9 `~~~~~~~' 6                             |     |     |
+	 |   |                                |     |     +----> Clock
+	 |   +----> Power                     |     +----------> Latch
+	 +--------> Ground                    +----------------> Power
+
+2.2 Multisystem joysticks
+~~~~~~~~~~~~~~~~~~~~~~~~~
+  In the era of 8-bit machines, there was something like de-facto standard
+for joystick ports. They were all digital, and all used D-Cannon 9 pin
+connectors (db9). Because of that, a single joystick could be used without
+hassle on Atari (130, 800XE, 800XL, 2600, 7200), Amiga, Commodore C64,
+Amstrad CPC, Sinclair ZX Spectrum and many other machines. That's why these
+joysticks are called "Multisystem".
+
+  Now their pinout:
+
+      +---------> Right
+      | +-------> Left
+      | | +-----> Down
+      | | | +---> Up
+      | | | |
+  _____________
+5 \ x o o o o / 1
+   \ x o x o /
+  9 `~~~~~~~' 6
+       |   |
+       |   +----> Button
+       +--------> Ground
+
+  However, as time passed, extensions to this standard developed, and these
+were not compatible with each other:
+
+
+	Atari 130, 800/XL/XE		   MSX
+
+					 +-----------> Power
+      +---------> Right                  | +---------> Right
+      | +-------> Left                   | | +-------> Left
+      | | +-----> Down                   | | | +-----> Down
+      | | | +---> Up                     | | | | +---> Up
+      | | | |                            | | | | |
+  _____________                        _____________
+5 \ x o o o o / 1                    5 \ o o o o o / 1
+   \ x o o o /                          \ o o o o /
+  9 `~~~~~~~' 6                        9 `~~~~~~~' 6
+       | | |                              | | | |
+       | | +----> Button                  | | | +----> Button 1
+       | +------> Power                   | | +------> Button 2
+       +--------> Ground                  | +--------> Output 3
+					  +----------> Ground
+
+	Amstrad CPC			   Commodore C64
+
+					 +-----------> Analog Y
+      +---------> Right                  | +---------> Right
+      | +-------> Left                   | | +-------> Left
+      | | +-----> Down                   | | | +-----> Down
+      | | | +---> Up                     | | | | +---> Up
+      | | | |                            | | | | |
+  _____________                        _____________
+5 \ x o o o o / 1                    5 \ o o o o o / 1
+   \ x o o o /                          \ o o o o /
+  9 `~~~~~~~' 6                        9 `~~~~~~~' 6
+       | | |                              | | | |
+       | | +----> Button 1                | | | +----> Button
+       | +------> Button 2                | | +------> Power
+       +--------> Ground                  | +--------> Ground
+					  +----------> Analog X
+
+	Sinclair Spectrum +2A/+3           Amiga 1200
+                                     
+    +-----------> Up                     +-----------> Button 3
+    | +---------> Fire                   | +---------> Right
+    | |                                  | | +-------> Left
+    | |   +-----> Ground                 | | | +-----> Down
+    | |   |                              | | | | +---> Up
+    | |   |                              | | | | |
+  _____________                        _____________
+5 \ o o x o x / 1                    5 \ o o o o o / 1
+   \ o o o o /                          \ o o o o /
+  9 `~~~~~~~' 6                        9 `~~~~~~~' 6
+     | | | |                              | | | |
+     | | | +----> Right                   | | | +----> Button 1
+     | | +------> Left                    | | +------> Power
+     | +--------> Ground                  | +--------> Ground
+     +----------> Down                    +----------> Button 2
+
+  And there were many others.
+
+2.2.1 Multisystem joysticks using db9.c
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  For the Multisystem joysticks, and their derivatives, the db9.c driver
+was written. It allows only one joystick / gamepad per parallel port, but
+the interface is easy to build and works with almost anything.
+
+  For the basic 1-button Multisystem joystick you connect its wires to the
+parallel port like this:
+
+(pin  1) -----> Power
+(pin 18) -----> Ground
+
+(pin  2) -----> Up
+(pin  3) -----> Down
+(pin  4) -----> Left
+(pin  5) -----> Right
+(pin  6) -----> Button 1
+
+  However, if the joystick is switch based (eg. clicks when you move it),
+you might or might not, depending on your parallel port, need 10 kOhm pullup
+resistors on each of the direction and button signals, like this:
+
+(pin 2) ------------+------> Up
+	  Resistor  |
+(pin 1) --[10kOhm]--+
+
+  Try without, and if it doesn't work, add them. For TTL based joysticks /
+gamepads the pullups are not needed.
+
+  For joysticks with two buttons you connect the second button to pin 7 on
+the parallel port.
+
+(pin 7) -----> Button 2
+
+  And that's it.
+
+  On a side note, if you have already built a different adapter for use with
+the digital joystick driver 0.8.0.2, this is also supported by the db9.c
+driver, as device type 8. (See section 3.2)
+
+2.2.2 Multisystem joysticks using gamecon.c
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  For some people just one joystick per parallel port is not enough, and/or
+want to use them on one parallel port together with NES/SNES/PSX pads. This is
+possible using the gamecon.c. It supports up to 5 devices of the above types,
+including 1 and 2 buttons Multisystem joysticks.
+
+  However, there is nothing for free. To allow more sticks to be used at
+once, you need the sticks to be purely switch based (that is non-TTL), and
+not to need power. Just a plain simple six switches inside. If your
+joystick can do more (eg. turbofire) you'll need to disable it totally first
+if you want to use gamecon.c.
+
+  Also, the connection is a bit more complex. You'll need a bunch of diodes,
+and one pullup resistor. First, you connect the Directions and the button
+the same as for db9, however with the diodes inbetween.
+
+	    Diodes
+(pin 2) -----|<|----> Up
+(pin 3) -----|<|----> Down
+(pin 4) -----|<|----> Left
+(pin 5) -----|<|----> Right
+(pin 6) -----|<|----> Button 1
+
+  For two button sticks you also connect the other button.
+
+(pin 7) -----|<|----> Button 2
+
+  And finally, you connect the Ground wire of the joystick, like done in
+this little schematic to Power and Data on the parallel port, as described
+for the NES / SNES pads in section 2.1 of this file - that is, one data pin
+for each joystick. The power source is shared.
+
+Data    ------------+-----> Ground
+	  Resistor  |
+Power   --[10kOhm]--+
+
+  And that's all, here we go!
+
+2.2.3 Multisystem joysticks using turbografx.c
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  The TurboGraFX interface, designed by
+
+	Steffen Schwenke <schwenke@burg-halle.de>
+
+  allows up to 7 Multisystem joysticks connected to the parallel port. In
+Steffen's version, there is support for up to 5 buttons per joystick.  However,
+since this doesn't work reliably on all parallel ports, the turbografx.c driver
+supports only one button per joystick. For more information on how to build the
+interface, see
+
+	http://www2.burg-halle.de/~schwenke/parport.html
+
+2.3 Sony Playstation
+~~~~~~~~~~~~~~~~~~~~
+
+  The PSX controller is supported by the gamecon.c. Pinout of the PSX
+controller (compatible with DirectPadPro):
+
+  +---------+---------+---------+
+9 | o  o  o | o  o  o | o  o  o | 1               parallel
+   \________|_________|________/                  port pins
+    |  |      |  |  |   |
+    |  |      |  |  |   +-------->  Clock    ---  (4)
+    |  |      |  |  +------------>  Select   ---  (3)
+    |  |      |  +--------------->  Power    ---  (5-9)
+    |  |      +------------------>  Ground   ---  (18-25)
+    |  +------------------------->  Command  ---  (2)
+    +---------------------------->  Data     ---  (one of 10,11,12,13,15)
+
+  The driver supports these controllers:
+
+ * Standard PSX Pad
+ * NegCon PSX Pad
+ * Analog PSX Pad (red mode)
+ * Analog PSX Pad (green mode)
+ * PSX Rumble Pad
+
+2.4 Sega
+~~~~~~~~
+  All the Sega controllers are more or less based on the standard 2-button
+Multisystem joystick. However, since they don't use switches and use TTL
+logic, the only driver usable with them is the db9.c driver.
+
+2.4.1 Sega Master System
+~~~~~~~~~~~~~~~~~~~~~~~~
+  The SMS gamepads are almost exactly the same as normal 2-button
+Multisystem joysticks. Set the driver to Multi2 mode, use the corresponding
+parallel port pins, and the following schematic:
+
+    +-----------> Power
+    | +---------> Right
+    | | +-------> Left
+    | | | +-----> Down
+    | | | | +---> Up
+    | | | | |
+  _____________
+5 \ o o o o o / 1
+   \ o o x o /
+  9 `~~~~~~~' 6
+     | |   |
+     | |   +----> Button 1
+     | +--------> Ground
+     +----------> Button 2
+
+2.4.2 Sega Genesis aka MegaDrive
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  The Sega Genesis (in Europe sold as Sega MegaDrive) pads are an extension
+to the Sega Master System pads. They use more buttons (3+1, 5+1, 6+1).  Use
+the following schematic:
+
+    +-----------> Power
+    | +---------> Right
+    | | +-------> Left
+    | | | +-----> Down
+    | | | | +---> Up
+    | | | | |
+  _____________
+5 \ o o o o o / 1
+   \ o o o o /
+  9 `~~~~~~~' 6
+     | | | |
+     | | | +----> Button 1
+     | | +------> Select
+     | +--------> Ground
+     +----------> Button 2
+
+  The Select pin goes to pin 14 on the parallel port.
+
+(pin 14) -----> Select
+
+  The rest is the same as for Multi2 joysticks using db9.c
+
+2.4.3 Sega Saturn
+~~~~~~~~~~~~~~~~~
+  Sega Saturn has eight buttons, and to transfer that, without hacks like
+Genesis 6 pads use, it needs one more select pin. Anyway, it is still
+handled by the db9.c driver. Its pinout is very different from anything
+else.  Use this schematic:
+
+    +-----------> Select 1
+    | +---------> Power
+    | | +-------> Up
+    | | | +-----> Down
+    | | | | +---> Ground
+    | | | | |
+  _____________
+5 \ o o o o o / 1
+   \ o o o o /
+  9 `~~~~~~~' 6
+     | | | |
+     | | | +----> Select 2
+     | | +------> Right
+     | +--------> Left
+     +----------> Power
+
+  Select 1 is pin 14 on the parallel port, Select 2 is pin 16 on the
+parallel port.
+
+(pin 14) -----> Select 1
+(pin 16) -----> Select 2
+
+  The other pins (Up, Down, Right, Left, Power, Ground) are the same as for
+Multi joysticks using db9.c
+
+3. The drivers
+~~~~~~~~~~~~~~
+  There are three drivers for the parallel port interfaces. Each, as
+described above, allows to connect a different group of joysticks and pads.
+Here are described their command lines:
+
+3.1 gamecon.c
+~~~~~~~~~~~~~
+  Using gamecon.c you can connect up to five devices to one parallel port. It
+uses the following kernel/module command line:
+
+	gc=port,pad1,pad2,pad3,pad4,pad5
+
+  Where 'port' the number of the parport interface (eg. 0 for parport0).
+
+  And 'pad1' to 'pad5' are pad types connected to different data input pins
+(10,11,12,13,15), as described in section 2.1 of this file.
+
+  The types are:
+
+	Type | Joystick/Pad
+	--------------------
+	  0  | None
+	  1  | SNES pad
+	  2  | NES pad
+	  4  | Multisystem 1-button joystick
+	  5  | Multisystem 2-button joystick
+	  6  | N64 pad
+	  7  | Sony PSX controller
+
+  The exact type of the PSX controller type is autoprobed, so you must have
+your controller plugged in before initializing.
+
+  Should you want to use more than one of parallel ports at once, you can use
+gc_2 and gc_3 as additional command line parameters for two more parallel
+ports.
+
+3.2 db9.c
+~~~~~~~~~
+  Apart from making an interface, there is nothing difficult on using the
+db9.c driver. It uses the following kernel/module command line:
+
+	db9=port,type
+
+  Where 'port' is the number of the parport interface (eg. 0 for parport0).
+
+  Caveat here: This driver only works on bidirectional parallel ports. If
+your parallel port is recent enough, you should have no trouble with this.
+Old parallel ports may not have this feature.
+
+  'Type' is the type of joystick or pad attached:
+
+	Type | Joystick/Pad
+	--------------------
+	  0  | None
+	  1  | Multisystem 1-button joystick
+	  2  | Multisystem 2-button joystick
+	  3  | Genesis pad (3+1 buttons)
+	  5  | Genesis pad (5+1 buttons)
+	  6  | Genesis pad (6+2 buttons)
+	  7  | Saturn pad (8 buttons)
+	  8  | Multisystem 1-button joystick (v0.8.0.2 pin-out)
+	  9  | Two Multisystem 1-button joysticks (v0.8.0.2 pin-out) 
+	 10  | Amiga CD32 pad
+
+  Should you want to use more than one of these joysticks/pads at once, you
+can use db9_2 and db9_3 as additional command line parameters for two
+more joysticks/pads.
+
+3.3 turbografx.c
+~~~~~~~~~~~~~~~~
+  The turbografx.c driver uses a very simple kernel/module command line:
+
+	tgfx=port,js1,js2,js3,js4,js5,js6,js7
+
+  Where 'port' is the number of the parport interface (eg. 0 for parport0).
+
+  'jsX' is the number of buttons the Multisystem joysticks connected to the
+interface ports 1-7 have. For a standard multisystem joystick, this is 1.
+
+  Should you want to use more than one of these interfaces at once, you can
+use tgfx_2 and tgfx_3 as additional command line parameters for two more
+interfaces.
+
+3.4 PC parallel port pinout
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+		  .----------------------------------------.
+   At the PC:     \ 13 12 11 10  9  8  7  6  5  4  3  2  1 /
+                   \  25 24 23 22 21 20 19 18 17 16 15 14 /
+                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	  Pin | Name    | Description
+	~~~~~~|~~~~~~~~~|~~~~~~~~~~
+	    1 | /STROBE | Strobe
+	  2-9 | D0-D7   | Data Bit 0-7
+	   10 | /ACK    | Acknowledge
+	   11 | BUSY    | Busy
+	   12 | PE      | Paper End
+	   13 | SELIN   | Select In
+	   14 | /AUTOFD | Autofeed
+	   15 | /ERROR  | Error
+	   16 | /INIT   | Initialize
+	   17 | /SEL    | Select
+	18-25 | GND     | Signal Ground
+
+3.5 End
+~~~~~~~
+  That's all, folks! Have fun!
diff -u --recursive --new-file v2.4.9/linux/Documentation/input/joystick.txt linux/Documentation/input/joystick.txt
--- v2.4.9/linux/Documentation/input/joystick.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/input/joystick.txt	Wed Sep 12 15:34:06 2001
@@ -0,0 +1,583 @@
+		       Linux Joystick driver v2.0.0
+	       (c) 1996-2000 Vojtech Pavlik <vojtech@suse.cz>
+			     Sponsored by SuSE
+	   $Id: joystick.txt,v 1.6 2001/06/05 09:57:01 vojtech Exp $
+----------------------------------------------------------------------------
+
+0. Disclaimer
+~~~~~~~~~~~~~
+  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
+
+  Should you need to contact me, the author, you can do so either by e-mail
+- mail your message to <vojtech@suse.cz>, or by paper mail: Vojtech Pavlik,
+Ucitelska 1576, Prague 8, 182 00 Czech Republic
+
+  For your convenience, the GNU General Public License version 2 is included
+in the package: See the file COPYING.
+
+1. Intro
+~~~~~~~~
+  The joystick driver for Linux provides support for a variety of joysticks
+and similar devices. It is based on a larger project aiming to support all
+input devices in Linux.
+
+  Should you encounter any problems while using the driver, or joysticks
+this driver can't make complete use of, I'm very interested in hearing about
+them. Bug reports and success stories are also welcome.
+
+  The input project website is at:
+
+	http://www.suse.cz/development/input/
+	http://atrey.karlin.mff.cuni.cz/~vojtech/input/
+
+  There is also a mailing list for the driver at:
+
+	listproc@atrey.karlin.mff.cuni.cz
+
+send "subscribe linux-joystick Your Name" to subscribe to it.
+
+2. Usage
+~~~~~~~~
+  For basic usage you just choose the right options in kernel config and
+you should be set.
+
+2.1 inpututils
+~~~~~~~~~~~~~~
+For testing and other purposes (for example serial devices), a set of
+utilities is available at the abovementioned website. I suggest you download
+and install it before going on.
+
+2.2 Device nodes
+~~~~~~~~~~~~~~~~
+For applications to be able to use the joysticks, in you don't use devfs,
+you'll have to manually create these nodes in /dev:
+
+cd /dev
+rm js*
+mkdir input
+mknod input/js0 c 13 0
+mknod input/js1 c 13 1
+mknod input/js2 c 13 2
+mknod input/js3 c 13 3
+ln -s input/js0 js0
+ln -s input/js1 js1
+ln -s input/js2 js2
+ln -s input/js3 js3
+
+For testing with inpututils it's also convenient to create these:
+
+mknod input/event0 c 13 64
+mknod input/event1 c 13 65
+mknod input/event2 c 13 66
+mknod input/event3 c 13 67
+
+2.4 Modules needed 
+~~~~~~~~~~~~~~~~~~
+  For all joystick drivers to function, you'll need the userland interface
+module in kernel, either loaded or compiled in:
+
+	modprobe joydev
+
+  For gameport joysticks, you'll have to load the gameport driver as well;
+
+	modprobe ns558
+
+  And for serial port joysticks, you'll need the serial input line
+discipline module loaded and the inputattach utility started:
+
+	modprobe serport
+	inputattach -xxx /dev/tts/X &
+
+  In addition to that, you'll need the joystick driver module itself, most
+usually you'll have an analog joystick:
+
+	modprobe analog
+	
+  For automatic module loading, something like this might work - tailor to
+your needs:
+
+	alias tty-ldisc-2 serport
+	alias char-major-13 input
+	above input joydev ns558 analog
+	options analog js=gameport
+
+2.5 Verifying that it works
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  For testing the joystick driver functionality, there is the jstest
+program in the utilities package. You run it by typing:
+
+	jstest /dev/js0
+
+  And it should show a line with the joystick values, which update as you
+move the stick, and press its buttons. The axes should all be zero when the
+joystick is in the center position. They should not jitter by themselves to
+other close values, and they also should be steady in any other position of
+the stick. They should have the full range from -32767 to 32767. If all this
+is met, then it's all fine, and you can play the games. :)
+
+  If it's not, then there might be a problem. Try to calibrate the joystick,
+and if it still doesn't work, read the drivers section of this file, the
+troubleshooting section, and the FAQ.
+
+2.6. Calibration
+~~~~~~~~~~~~~~~~
+  For most joysticks you won't need any manual calibration, since the
+joystick should be autocalibrated by the driver automagically. However, with
+some analog joysticks, that either do not use linear resistors, or if you
+want better precision, you can use the jscal program
+
+	jscal -c /dev/js0
+
+ included in the joystick package to set better correction coefficients than
+what the driver would choose itself.
+
+  After calibrating the joystick you can verify if you like the new
+calibration using the jstest command, and if you do, you then can save the
+correction coefficients into a file
+
+	jscal -p /dev/js0 > /etc/joystick.cal
+
+  And add a line to your rc script executing that file
+
+	source /etc/joystick.cal
+
+  This way, after the next reboot your joystick will remain calibrated. You
+can also add the jscal -p line to your shutdown script.
+
+
+3. HW specific driver information
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In this section each of the separate hardware specific drivers is described.
+
+3.1 Analog joysticks
+~~~~~~~~~~~~~~~~~~~~
+  The analog.c uses the standard analog inputs of the gameport, and thus
+supports all standard joysticks and gamepads. It uses a very advanced
+routine for this, allowing for data precision that can't be found on any
+other system.
+
+  It also supports extensions like additional hats and buttons compatible
+with CH Flightstick Pro, ThrustMaster FCS or 6 and 8 button gamepads. Saitek
+Cyborg 'digital' joysticks are also supported by this driver, because
+they're basically souped up CHF sticks.
+
+  However the only types that can be autodetected are:
+
+* 2-axis, 4-button joystick
+* 3-axis, 4-button joystick
+* 4-axis, 4-button joystick
+* Saitek Cyborg 'digital' joysticks
+
+  For other joystick types (more/less axes, hats, and buttons) support
+you'll need to specify the types either on the kernel command line or on the
+module command line, when inserting analog.o into the kernel. The
+parameters are:
+
+	js=type,type,type,....
+
+  'type' is type of the joystick from the table below, defining joysticks
+present on gameports in the system, starting with gameport0, second 'type'
+entry defining joystick on gameport1 and so on.
+
+	Type     | Meaning
+	-----------------------------------
+	none     | No analog joystick on that port
+	auto     | Autodetect joystick
+	2btn     | 2-button n-axis joystick
+	y-joy    | Two 2-button 2-axis joysticks on an Y-cable
+	y-pad    | Two 2-button 2-axis gamepads on an Y-cable
+	fcs      | Thrustmaster FCS compatible joystick
+	chf      | Joystick with a CH Flightstick compatible hat
+	fullchf  | CH Flightstick compatible with two hats and 6 buttons
+	gamepad  | 4/6-button n-axis gamepad
+	gamepad8 | 8-button 2-axis gamepad
+
+  In case your joystick doesn't fit in any of the above categories, you can
+specify the type as a number by combining the bits in the table below. This
+is not recommended unless you really know what are you doing. It's not
+dangerous, but not simple either.
+
+	Bit | Meaning
+	--------------------------
+	 0  | Axis X1
+	 1  | Axis Y1
+	 2  | Axis X2
+	 3  | Axis Y2
+	 4  | Button A
+	 5  | Button B
+	 6  | Button C
+	 7  | Button D
+	 8  | CHF Buttons X and Y
+	 9  | CHF Hat 1
+	10  | CHF Hat 2
+	11  | FCS Hat
+	12  | Pad Button X
+	13  | Pad Button Y
+	14  | Pad Button U
+	15  | Pad Button V
+	16  | Saitek F1-F4 Buttons
+	17  | Saitek Digital Mode
+	19  | GamePad
+	20  | Joy2 Axis X1
+	21  | Joy2 Axis Y1
+	22  | Joy2 Axis X2
+	23  | Joy2 Axis Y2
+	24  | Joy2 Button A
+	25  | Joy2 Button B
+	26  | Joy2 Button C
+	27  | Joy2 Button D
+	31  | Joy2 GamePad
+
+3.2 Microsoft SideWinder joysticks
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  Microsoft 'Digital Overdrive' protocol is supported by the sidewinder.c
+module. All currently supported joysticks:
+
+* Microsoft SideWinder 3D Pro
+* Microsoft SideWinder Force Feedback Pro
+* Microsoft SideWinder Force Feedback Wheel
+* Microsoft SideWinder FreeStyle Pro 
+* Microsoft SideWinder GamePad (up to four, chained)
+* Microsoft SideWinder Precision Pro 
+* Microsoft SideWinder Precision Pro USB 
+
+  are autodetected, and thus no module parameters are needed.
+
+  There is one caveat with the 3D Pro. There are 9 buttons reported,
+although the joystick has only 8. The 9th button is the mode switch on the
+rear side of the joystick. However, moving it, you'll reset the joystick,
+and make it unresponsive for about a one third of a second. Furthermore, the
+joystick will also re-center itself, taking the position it was in during
+this time as a new center position. Use it if you want, but think first.
+
+  The SideWinder Standard is not a digital joystick, and thus is supported
+by the analog driver described above. 
+
+3.3 Logitech ADI devices
+~~~~~~~~~~~~~~~~~~~~~~~~
+  Logitech ADI protocol is supported by the adi.c module. It should support
+any Logitech device using this protocol. This includes, but is not limited
+to:
+
+* Logitech CyberMan 2
+* Logitech ThunderPad Digital
+* Logitech WingMan Extreme Digital
+* Logitech WingMan Formula
+* Logitech WingMan Interceptor
+* Logitech WingMan GamePad
+* Logitech WingMan GamePad USB
+* Logitech WingMan GamePad Extreme
+* Logitech WingMan Extreme Digital 3D
+
+  ADI devices are autodetected, and the driver supports up to two (any
+combination of) devices on a single gameport, using an Y-cable or chained
+together.
+
+  Logitech WingMan Joystick, Logitech WingMan Attack, Logitech WingMan
+Extreme and Logitech WingMan ThunderPad are not digital joysticks and are
+handled by the analog driver described above. Logitech WingMan Warrior and
+Logitech Magellan are supported by serial drivers described below.  Logitech
+WingMan Force and Logitech WingMan Formula Force are supported by the
+I-Force driver described below. Logitech CyberMan is not supported yet.
+
+3.4 Gravis GrIP
+~~~~~~~~~~~~~~~
+  Gravis GrIP protocol is supported by the grip.c module. It currently
+supports:
+
+* Gravis GamePad Pro
+* Gravis BlackHawk Digital
+* Gravis Xterminator
+* Gravis Xterminator DualControl
+
+  All these devices are autodetected, and you can even use any combination
+of up to two of these pads either chained together or using an Y-cable on a
+single gameport.
+
+GrIP MultiPort isn't supported yet. Gravis Stinger is a serial device and is
+supported by the stinger driver. Other Gravis joysticks are supported by the
+analog driver.
+
+3.5 FPGaming A3D and MadCatz A3D
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  The Assassin 3D protocol created by FPGaming, is used both by FPGaming
+themselves and is licensed to MadCatz. A3D devices are supported by the
+a3d.c module. It currently supports:
+
+* FPGaming Assassin 3D
+* MadCatz Panther
+* MadCatz Panther XL
+
+  All these devices are autodetected. Because the Assassin 3D and the Panther
+allow connecting analog joysticks to them, you'll need to load the analog
+driver as well to handle the attached joysticks.
+
+  The trackball should work with USB mousedev module as a normal mouse. See
+the USB documentation for how to setup an USB mouse.
+
+3.6 ThrustMaster DirectConnect (BSP)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  The TM DirectConnect (BSP) protocol is supported by the tmdc.c
+module. This includes, but is not limited to:
+
+* ThrustMaster Millenium 3D Inceptor
+* ThrustMaster 3D Rage Pad
+* ThrustMaster Fusion Digital Game Pad
+
+  Devices not directly supported, but hopefully working are:
+
+* ThrustMaster FragMaster
+* ThrustMaster Attack Throttle
+
+  If you have one of these, contact me.
+
+  TMDC devices are autodetected, and thus no parameters to the module
+are needed. Up to two TMDC devices can be connected to one gameport, using
+an Y-cable.
+
+3.7 Creative Labs Blaster
+~~~~~~~~~~~~~~~~~~~~~~~~~
+  The Blaster protocol is supported by the cobra.c module. It supports only
+the:
+
+* Creative Blaster GamePad Cobra
+
+  Up to two of these can be used on a single gameport, using an Y-cable.
+
+3.8 Genius Digital joysticks 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  The Genius digitally communicating joysticks are supported by the gf2k.c
+module. This includes:
+
+* Genius Flight2000 F-23 joystick 
+* Genius Flight2000 F-31 joystick 
+* Genius G-09D gamepad
+
+  Other Genius digital joysticks are not supported yet, but support can be
+added fairly easily.
+
+3.9 InterAct Digital joysticks
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  The InterAct digitally communicating joysticks are supported by the
+interact.c module. This includes:
+
+* InterAct HammerHead/FX gamepad
+* InterAct ProPad8 gamepad 
+
+  Other InterAct digital joysticks are not supported yet, but support can be 
+added fairly easily.
+
+3.10 PDPI Lightning 4 gamecards
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  PDPI Lightning 4 gamecards are supported by the lightning.c module.
+Once the module is loaded, the analog driver can be used to handle the
+joysticks. Digitally communicating joystick will work only on port 0, while
+using Y-cables, you can connect up to 8 analog joysticks to a single L4
+card, 16 in case you have two in your system.
+
+3.11 Trident 4DWave / Aureal Vortex
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  Soundcards with a Trident 4DWave DX/NX or Aureal Vortex/Vortex2 chipsets
+provide an "Enhanced Game Port" mode where the soundcard handles polling the
+joystick.  This mode is supported by the pcigame.c module. Once loaded the
+analog driver can use the enhanced features of these gameports..
+
+3.13 Crystal SoundFusion
+~~~~~~~~~~~~~~~~~~~~~~~~
+  Soundcards with Crystal SoundFusion chipsets provide an "Enhanced Game
+Port", much like the 4DWave or Vortex above. This, and also the normal mode
+for the port of the SoundFusion is supported by the cs461x.c module.
+
+3.14 SoundBlaster Live!
+~~~~~~~~~~~~~~~~~~~~~~~~
+  The Live! has a special PCI gameport, which, although it doesn't provide
+any "Enhanced" stuff like 4DWave and friends, is quite a bit faster than
+it's ISA counterparts. It also requires special support, hence the
+emu10k1-gp.c module for it instead of the normal ns558.c one.
+
+3.15 SoundBlaster 64 and 128 - ES1370 and ES1371, ESS Solo1 and S3 SonicVibes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  These PCI soundcards have specific gameports. They are handled by the
+sound drivers themselves. Make sure you select gameport support in the
+joystick menu and sound card support in the sound menu for your appropriate
+card.
+
+3.16 Amiga
+~~~~~~~~~~
+  Amiga joysticks, connected to an Amiga, are supported by the amijoy.c
+driver. Since they can't be autodetected, the driver has a command line.
+
+	amijoy=a,b
+
+  a and b define the joysticks connected to the JOY0DAT and JOY1DAT ports of
+the Amiga.
+
+	Value | Joystick type
+	---------------------
+	  0   | None
+	  1   | 1-button digital joystick
+
+  No more joystick types are supported now, but that should change in the
+future if I get an Amiga in the reach of my fingers.
+
+3.17 Game console and 8-bit pads and joysticks
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+See joystick-parport.txt for more info.
+
+3.18 SpaceTec/LabTec devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  SpaceTec serial devices communicate using the SpaceWare protocol. It is
+supported by the spaceorb.c and spaceball.c drivers. The devices currently
+supported by spaceorb.c are:
+
+* SpaceTec SpaceBall Avenger
+* SpaceTec SpaceOrb 360
+
+Devices currently supported by spaceball.c are:
+
+* SpaceTec SpaceBall 4000 FLX
+
+  In addition to having the spaceorb/spaceball and serport modules in the
+kernel, you also need to attach a serial port to it. to do that, run the
+inputattach program:
+
+	inputattach --spaceorb /dev/tts/x &
+or
+	inputattach --spaceball /dev/tts/x &
+
+where /dev/tts/x is the serial port which the device is connected to. After
+doing this, the device will be reported and will start working.
+
+  There is one caveat with the SpaceOrb. The button #6, the on the bottom
+side of the orb, although reported as an ordinary button, causes internal
+recentering of the spaceorb, moving the zero point to the position in which
+the ball is at the moment of pressing the button. So, think first before
+you bind it to some other function.
+
+SpaceTec SpaceBall 2003 FLX and 3003 FLX are not supported yet. 
+
+3.19 Logitech SWIFT devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  The SWIFT serial protocol is supported by the warrior.c module. It
+currently supports only the:
+
+* Logitech WingMan Warrior
+
+but in the future, Logitech CyberMan (the original one, not CM2) could be
+supported as well. To use the module, you need to run inputattach after you
+insert/compile the module into your kernel:
+
+	inputattach --warrior /dev/tts/x &
+
+/dev/tts/x is the serial port your Warrior is attached to.
+
+3.20 Magellan / Space Mouse
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  The Magellan (or Space Mouse), manufactured by LogiCad3d (formerly Space
+Systems), for many other companies (Logitech, HP, ...) is supported by the
+joy-magellan module. It currently supports only the:
+
+* Magellan 3D
+* Space Mouse
+
+models, the additional buttons on the 'Plus' versions are not supported yet.
+
+  To use it, you need to attach the serial port to the driver using the
+
+	inputattach --magellan /dev/tts/x &
+
+command. After that the Magellan will be detected, initialized, will beep,
+and the /dev/input/jsX device should become usable.
+
+3.21 I-Force devices 
+~~~~~~~~~~~~~~~~~~~~
+  All I-Force devices are supported by the iforce.c module. This includes:
+
+* AVB Mag Turbo Force
+* AVB Top Shot Pegasus
+* Logitech WingMan Force
+* Logitech WingMan Force 3D
+* Logitech WingMan Force Wheel 
+* Logitech WingMan Strike Force 3D
+* Guillemot Race Leader Force Feedback
+
+  To use it, you need to attach the serial port to the driver using the
+
+	inputattach --iforce /dev/tts/x &
+
+command. After that the I-Force device will be detected, and the
+/dev/input/jsX device should become usable.
+
+  In case you're using the device via the USB port, the inputattach command
+isn't needed.
+
+  The I-Force driver now supports force feedback via the event interface.
+
+3.22 Gravis Stinger gamepad 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  The Gravis Stinger serial port gamepad, designed for use with laptop
+computers, is supported by the stinger.c module. To use it, attach the
+serial port to the driver using:
+
+        inputattach --stinger /dev/tty/x &
+
+where x is the number of the serial port.
+
+4. Troubleshooting
+~~~~~~~~~~~~~~~~~~
+  There is quite a high probability that you run into some problems. For
+testing whether the driver works, if in doubt, use the jstest utility in
+some of its modes. The most useful modes are "normal" - for the 1.x
+interface, and "old" for the "0.x" interface. You run it by typing:
+
+	jstest --normal /dev/input/js0
+	jstest --old    /dev/input/js0
+
+  Additionally you can do a test with the evtest utility:
+
+	evtest /dev/input/event0
+
+  Oh, and read the FAQ! :)
+
+5. FAQ
+~~~~~~
+Q: Running 'jstest /dev/js0' results in "File not found" error. What's the
+   cause?
+A: The device files don't exist. Create them (see section 2.2).
+
+Q: Is it possible to connect my old Atari/Commodore/Amiga/console joystick
+   or pad that uses a 9-pin D-type cannon connector to the serial port of my
+   PC?
+A: Yes, it is possible, but it'll burn your serial port or the pad. It
+   won't work, of course.
+
+Q: My joystick doesn't work with Quake / Quake 2. What's the cause?
+A: Quake / Quake 2 don't support joystick. Use joy2key to simulate keypresses
+   for them.
+
+6. Programming Interface
+~~~~~~~~~~~~~~~~~~~~~~~~
+  The 1.0 driver uses a new, event based approach to the joystick driver.
+Instead of the user program polling for the joystick values, the joystick
+driver now reports only any changes of its state. See joystick-api.txt,
+joystick.h and jstest.c included in the joystick package for more
+information. The joystick device can be used in either blocking or
+nonblocking mode and supports select() calls.
+
+  For backward compatibility the old (v0.x) interface is still included.
+Any call to the joystick driver using the old interface will return values
+that are compatible to the old interface.  This interface is still limited
+to 2 axes, and applications using it usually decode only 2 buttons, although
+the driver provides up to 32.
diff -u --recursive --new-file v2.4.9/linux/Documentation/isdn/README linux/Documentation/isdn/README
--- v2.4.9/linux/Documentation/isdn/README	Sun Aug 13 10:05:32 2000
+++ linux/Documentation/isdn/README	Sun Sep  9 10:52:35 2001
@@ -276,6 +276,8 @@
                                       1 = Add CPN to RING message on
                             Bit 1:    0 = Add CPN to FCON message off
                                       1 = Add CPN to FCON message on
+                            Bit 2:    0 = Add CDN to RING/FCON message off
+                                      1 = Add CDN to RING/FCON message on
 
   Last but not least a (at the moment fairly primitive) device to request
   the line-status (/dev/isdninfo) is made available.
diff -u --recursive --new-file v2.4.9/linux/Documentation/joystick-api.txt linux/Documentation/joystick-api.txt
--- v2.4.9/linux/Documentation/joystick-api.txt	Fri Apr  6 10:42:48 2001
+++ linux/Documentation/joystick-api.txt	Wed Dec 31 16:00:00 1969
@@ -1,315 +0,0 @@
-		      Joystick API Documentation                -*-Text-*-
-
-		        Ragnar Hojland Espinosa
-		          <ragnar@macula.net>
-
-			      7 Aug 1998
-
-
-1. Initialization
-~~~~~~~~~~~~~~~~~
-
-Open the joystick device following the usual semantics (that is, with open).
-Since the driver now reports events instead of polling for changes,
-immediately after the open it will issue a series of synthetic events
-(JS_EVENT_INIT) that you can read to check the initial state of the
-joystick.
-
-By default, the device is opened in blocking mode.
-
-	int fd = open ("/dev/js0", O_RDONLY);
-
-
-2. Event Reading
-~~~~~~~~~~~~~~~~
-
-	struct js_event e;
-	read (fd, &e, sizeof(struct js_event));
-
-where js_event is defined as
-
-	struct js_event {
-		__u32 time;     /* event timestamp in milliseconds */
-		__s16 value;    /* value */
-		__u8 type;      /* event type */
-		__u8 number;    /* axis/button number */
-	};
-
-If the read is successful, it will return sizeof(struct js_event), unless
-you wanted to read more than one event per read as described in section 3.1.
-
-
-2.1 js_event.type
-~~~~~~~~~~~~~~~~~
-
-The possible values of ``type'' are
-
-	#define JS_EVENT_BUTTON         0x01    /* button pressed/released */
-	#define JS_EVENT_AXIS           0x02    /* joystick moved */
-	#define JS_EVENT_INIT           0x80    /* initial state of device */
-
-As mentioned above, the driver will issue synthetic JS_EVENT_INIT ORed
-events on open. That is, if it's issuing a INIT BUTTON event, the
-current type value will be
-
-	int type = JS_EVENT_BUTTON | JS_EVENT_INIT;	/* 0x81 */
-
-If you choose not to differentiate between synthetic or real events
-you can turn off the JS_EVENT_INIT bits
-
-	type &= ~JS_EVENT_INIT;				/* 0x01 */
-
-
-2.2 js_event.number
-~~~~~~~~~~~~~~~~~~~
-
-The values of ``number'' correspond to the axis or button that
-generated the event. Note that they carry separate numeration (that
-is, you have both an axis 0 and a button 0). Generally,
-
-			number
-	1st Axis X	0
-	1st Axis Y	1
-	2nd Axis X	2
-	2nd Axis Y	3
-	...and so on
-
-Hats vary from one joystick type to another. Some can be moved in 8
-directions, some only in 4, The driver, however, always reports a hat as two
-independent axis, even if the hardware doesn't allow independent movement.
-
-
-2.3 js_event.value
-~~~~~~~~~~~~~~~~~~
-
-For an axis, ``value'' is a signed integer between -32767 and +32767
-representing the position of the joystick along that axis. If you
-don't read a 0 when the joystick is `dead', or if it doesn't span the
-full range, you should recalibrate it (with, for example, jscal).
-
-For a button, ``value'' for a press button event is 1 and for a release
-button event is 0.
-
-Though this
-
-	if (js_event.type == JS_EVENT_BUTTON) {
-		buttons_state ^= (1 << js_event.number);
-	}
-
-may work well if you handle JS_EVENT_INIT events separately,
-
-	if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) {
-		if (js_event.value)
-	        	buttons_state |= (1 << js_event.number);
-	   	else
-	      		buttons_state &= ~(1 << js_event.number);
-	}
-
-is much safer since it can't lose sync with the driver. As you would
-have to write a separate handler for JS_EVENT_INIT events in the first
-snippet, this ends up being shorter.
-
-
-2.4 js_event.time
-~~~~~~~~~~~~~~~~~
-
-The time an event was generated is stored in ``js_event.time''. It's a time
-in milliseconds since ... well, since sometime in the past.  This eases the
-task of detecting double clicks, figuring out if movement of axis and button
-presses happened at the same time, and similar.
-
-
-3. Reading
-~~~~~~~~~~
-
-If you open the device in blocking mode, a read will block (that is,
-wait) forever until an event is generated and effectively read. There
-are two alternatives if you can't afford to wait forever (which is,
-admittedly, a long time;)
-
-	a) use select to wait until there's data to be read on fd, or
-	   until it timeouts. There's a good example on the select(2)
-	   man page.
-
-	b) open the device in non-blocking mode (O_NONBLOCK)
-
-
-3.1 O_NONBLOCK
-~~~~~~~~~~~~~~
-
-If read returns -1 when reading in O_NONBLOCK mode, this isn't
-necessarily a "real" error (check errno(3)); it can just mean there
-are no events pending to be read on the driver queue. You should read
-all events on the queue (that is, until you get a -1).
-
-For example,
-
-	while (1) {
-		while (read (fd, &e, sizeof(struct js_event)) > 0) {
-	        	process_event (e);
-	   	}
-	   	/* EAGAIN is returned when the queue is empty */
-	   	if (errno != EAGAIN) {
-	      		/* error */
-	   	}
-	   	/* do something interesting with processed events */
-	}
-
-One reason for emptying the queue is that if it gets full you'll start
-missing events since the queue is finite, and older events will get
-overwritten.
-
-The other reason is that you want to know all what happened, and not
-delay the processing till later.
-
-Why can get the queue full? Because you don't empty the queue as
-mentioned, or because too much time elapses from one read to another
-and too many events to store in the queue get generated. Note that
-high system load may contribute to space those reads even more.
-
-If time between reads is enough to fill the queue and loose an event,
-the driver will switch to startup mode and next time you read it,
-synthetic events (JS_EVENT_INIT) will be generated to inform you of
-the actual state of the joystick.
-
-[As for version 1.2.8, the queue is circular and able to hold 64
- events. You can increment this size bumping up JS_BUFF_SIZE in
- joystick.h and recompiling the driver.]
-
-
-In the above code, you might as well want to read more than one event
-at a time using the typical read(2) functionality. For that, you would
-replace the read above with something like
-
-	struct js_event mybuffer[0xff];
-	int i = read (fd, mybuffer, sizeof(struct mybuffer));
-
-In this case, read would return -1 if the queue was empty, or some
-other value in which the number of events read would be i /
-sizeof(js_event)  Again, if the buffer was full, it's a good idea to
-process the events and keep reading it until you empty the driver queue.
-
-
-4. IOCTLs
-~~~~~~~~~
-
-The joystick driver defines the following ioctl(2) operations.
-
-				/* function			3rd arg  */
-	#define JSIOCGAXES	/* get number of axes		char	 */
-	#define JSIOCGBUTTONS	/* get number of buttons	char	 */
-	#define JSIOCGVERSION	/* get driver version		int	 */
-	#define JSIOCGNAME(len) /* get identifier string	char	 */
-	#define JSIOCSCORR	/* set correction values	&js_corr */
-	#define JSIOCGCORR	/* get correction values	&js_corr */
-
-For example, to read the number of axes
-
-	char number_of_axes;
-	ioctl (fd, JSIOCGAXES, &number_of_axes);
-
-
-4.1 JSIOGCVERSION
-~~~~~~~~~~~~~~~~~
-
-JSIOGCVERSION is a good way to check in run-time whether the running
-driver is 1.0+ and supports the event interface. If it is not, the
-IOCTL will fail. For a compile-time decision, you can test the
-JS_VERSION symbol
-
-	#ifdef JS_VERSION
-	#if JS_VERSION > 0xsomething
-
-
-4.2 JSIOCGNAME
-~~~~~~~~~~~~~~
-
-JSIOCGNAME(len) allows you to get the name string of the joystick - the same
-as is being printed at boot time. The 'len' argument is the length of the
-buffer provided by the application asking for the name. It is used to avoid
-possible overrun should the name be too long.
-
-	char name[128];
-	if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
-		strncpy(name, "Unknown", sizeof(name));
-	printf("Name: %s\n", name);
-
-
-4.3 JSIOC[SG]CORR
-~~~~~~~~~~~~~~~~~
-
-For usage on JSIOC[SG]CORR I suggest you to look into jscal.c  They are
-not needed in a normal program, only in joystick calibration software
-such as jscal or kcmjoy. These IOCTLs and data types aren't considered
-to be in the stable part of the API, and therefore may change without
-warning in following releases of the driver.
-
-Both JSIOCSCORR and JSIOCGCORR expect &js_corr to be able to hold
-information for all axis. That is, struct js_corr corr[MAX_AXIS];
-
-struct js_corr is defined as
-
-	struct js_corr {
-		__s32 coef[8];
-		__u16 prec;
-		__u16 type;
-	};
-
-and ``type''
-
-	#define JS_CORR_NONE            0x00    /* returns raw values */
-	#define JS_CORR_BROKEN          0x01    /* broken line */
-
-
-5. Backward compatibility
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The 0.x joystick driver API is quite limited and its usage is deprecated.
-The driver offers backward compatibility, though. Here's a quick summary:
-
-	struct JS_DATA_TYPE js;
-	while (1) {
-		if (read (fd, &js, JS_RETURN) != JS_RETURN) {
-	      		/* error */
-	   	}
-	   	usleep (1000);
-	}
-
-As you can figure out from the example, the read returns immediately,
-with the actual state of the joystick.
-
-	struct JS_DATA_TYPE {
-		int buttons;    /* immediate button state */
-		int x;          /* immediate x axis value */
-		int y;          /* immediate y axis value */
-	};
-
-and JS_RETURN is defined as
-
-	#define JS_RETURN       sizeof(struct JS_DATA_TYPE)
-
-To test the state of the buttons,
-
-	first_button_state  = js.buttons & 1;
-	second_button_state = js.buttons & 2;
-
-The axis values do not have a defined range in the original 0.x driver,
-except for that the values are non-negative. The 1.2.8+ drivers use a
-fixed range for reporting the values, 1 being the minimum, 128 the
-center, and 255 maximum value.
-
-The v0.8.0.2 driver also had an interface for 'digital joysticks', (now
-called Multisystem joysticks in this driver), under /dev/djsX. This driver
-doesn't try to be compatible with that interface.
-
-
-6. Final Notes
-~~~~~~~~~~~~~~
-
-____/|	Comments, additions, and specially corrections are welcome.
-\ o.O|	Documentation valid for at least version 1.2.8 of the joystick
- =(_)=	driver and as usual, the ultimate source for documentation is
-   U	to "Use The Source Luke" or, at your convenience, Vojtech ;)
-
-					- Ragnar
-EOF
diff -u --recursive --new-file v2.4.9/linux/Documentation/joystick-parport.txt linux/Documentation/joystick-parport.txt
--- v2.4.9/linux/Documentation/joystick-parport.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/joystick-parport.txt	Wed Dec 31 16:00:00 1969
@@ -1,521 +0,0 @@
-		    Linux Joystick parport drivers v2.0
-	       (c) 1998-2000 Vojtech Pavlik <vojtech@suse.cz>
-	       (c) 1998 Andree Borrmann <a.borrmann@tu-bs.de>
-			     Sponsored by SuSE
-----------------------------------------------------------------------------
-
-0. Disclaimer
-~~~~~~~~~~~~~
-  Any information in this file is provided as-is, without any guarantee that
-it will be true. So, use it at your own risk. The possible damages that can
-happen include burning your parallel port, and/or the sticks and joystick
-and maybe even more. Like when a lightning kills you it is not our problem.
-
-1. Intro
-~~~~~~~~
-  The joystick parport drivers are used for joysticks and gamepads not
-originally designed for PCs and other computers Linux runs on. Because of
-that, PCs usually lack the right ports to connect these devices to. Parallel
-port, because of its ability to change single bits at will, and providing
-both output and input bits is the most suitable port on the PC for
-connecting such devices.
-
-2. Devices supported
-~~~~~~~~~~~~~~~~~~~~
-  Many console and 8-bit computer gamepads and joysticks are supported. The
-following subsections discuss usage of each.
-
-2.1 NES and SNES
-~~~~~~~~~~~~~~~~
-  The Nintendo Entertainment System and Super Nintendo Entertainment System
-gamepads are widely available, and easy to get. Also, they are quite easy to
-connect to a PC, and don't need much processing speed (108 us for NES and
-165 us for SNES, compared to about 1000 us for PC gamepads) to communicate
-with them.
-
-  All NES and SNES use the same synchronous serial protocol, clocked from
-the computer's side (and thus timing insensitive). To allow up to 5 NES
-and/or SNES gamepads connected to the parallel port at once, the output
-lines of the parallel port are shared, while one of 5 available input lines
-is assigned to each gamepad.
-
-  This protocol is handled by the gamecon.c driver, so that's the one
-you'll use for NES and SNES gamepads.
-
-  The main problem with PC parallel ports is that they don't have +5V power
-source on any of their pins. So, if you want a reliable source of power
-for your pads, use either keyboard or joystick port, and make a pass-through
-cable. You can also pull the power directly from the power supply (the red
-wire is +5V).
-
-  If you want to use the parallel port only, you can take the power is from
-some data pin. For most gamepad and parport implementations only one pin is
-needed, and I'd recommend pin 9 for that, the highest data bit. On the other
-hand, if you are not planning to use anything else than NES / SNES on the
-port, anything between and including pin 4 and pin 9 will work.
-
-(pin 9) -----> Power
-
-  Unfortunately, there are pads that need a lot more of power, and parallel
-ports that can't give much current through the data pins. If this is your
-case, you'll need to use diodes (as a prevention of destroying your parallel
-port), and combine the currents of two or more data bits together.
-
-	   Diodes
-(pin 9) ----|>|-------+------> Power
-		      |
-(pin 8) ----|>|-------+
-		      |
-(pin 7) ----|>|-------+
-		      |
- <and so on>          :
-		      |
-(pin 4) ----|>|-------+
-
-  Ground is quite easy. On PC's parallel port the ground is on any of the
-pins from pin 18 to pin 25. So use any pin of these you like for the ground.
-
-(pin 18) -----> Ground
-
-  NES and SNES pads have two input bits, Clock and Latch, which drive the
-serial transfer. These are connected to pins 2 and 3 of the parallel port,
-respectively.
-
-(pin 2) -----> Clock
-(pin 3) -----> Latch
-
-  And the last thing is the NES / SNES data wire. Only that isn't shared and
-each pad needs its own data pin. The parallel port pins are:
-
-(pin 10) -----> Pad 1 data
-(pin 11) -----> Pad 2 data
-(pin 12) -----> Pad 3 data
-(pin 13) -----> Pad 4 data
-(pin 15) -----> Pad 5 data
-
-  Note that pin 14 is not used, since it is not an input pin on the parallel
-port.
-
-  This is everything you need on the PC's side of the connection, now on to
-the gamepads side. The NES and SNES have different connectors. Also, there
-are quite a lot of NES clones, and because Nintendo used proprietary
-connectors for their machines, the cloners couldn't and used standard D-Cannon
-connectors. Anyway, if you've got a gamepad, and it has buttons A, B, Turbo
-A, Turbo B, Select and Start, and is connected through 5 wires, then it is
-either a NES or NES clone and will work with this connection. SNES gamepads
-also use 5 wires, but have more buttons. They will work as well, of course.
-
-Pinout for NES gamepads                 Pinout for SNES gamepads
-
-	   +----> Power                   +-----------------------\
-	   |                            7 | o  o  o  o |  x  x  o  | 1
- 5 +---------+  7                         +-----------------------/
-   | x  x  o   \                            |  |  |  |          |
-   | o  o  o  o |                           |  |  |  |          +-> Ground
- 4 +------------+ 1                         |  |  |  +------------> Data
-     |  |  |  |                             |  |  +---------------> Latch
-     |  |  |  +-> Ground                    |  +------------------> Clock
-     |  |  +----> Clock                     +---------------------> Power
-     |  +-------> Latch
-     +----------> Data
-
-Pinout for NES clone (db9) gamepads     Pinout for NES clone (db15) gamepads
-
-	+---------> Clock                    +-----------------> Data
-	| +-------> Latch                    |             +---> Ground
-	| | +-----> Data                     |             |
-	| | |                              ___________________
-    _____________                        8 \ o x x x x x x o / 1
-  5 \ x o o o x / 1                         \ o x x o x x o /
-     \ x o x o /                          15 `~~~~~~~~~~~~~' 9
-    9 `~~~~~~~' 6                             |     |     |
-	 |   |                                |     |     +----> Clock
-	 |   +----> Power                     |     +----------> Latch
-	 +--------> Ground                    +----------------> Power
-
-2.2 Multisystem joysticks
-~~~~~~~~~~~~~~~~~~~~~~~~~
-  In the era of 8-bit machines, there was something like de-facto standard
-for joystick ports. They were all digital, and all used D-Cannon 9 pin
-connectors (db9). Because of that, a single joystick could be used without
-hassle on Atari (130, 800XE, 800XL, 2600, 7200), Amiga, Commodore C64,
-Amstrad CPC, Sinclair ZX Spectrum and many other machines. That's why these
-joysticks are called "Multisystem".
-
-  Now their pinout:
-
-      +---------> Right
-      | +-------> Left
-      | | +-----> Down
-      | | | +---> Up
-      | | | |
-  _____________
-5 \ x o o o o / 1
-   \ x o x o /
-  9 `~~~~~~~' 6
-       |   |
-       |   +----> Button
-       +--------> Ground
-
-  However, as time passed, extension to this standard developed, and these
-were not compatible with each other:
-
-
-  Atari 130, 800(XL/XE)                    MSX
-
-					 +-----------> Power
-      +---------> Right                  | +---------> Right
-      | +-------> Left                   | | +-------> Left
-      | | +-----> Down                   | | | +-----> Down
-      | | | +---> Up                     | | | | +---> Up
-      | | | |                            | | | | |
-  _____________                        _____________
-5 \ x o o o o / 1                    5 \ o o o o o / 1
-   \ x o o o /                          \ o o o o /
-  9 `~~~~~~~' 6                        9 `~~~~~~~' 6
-       | | |                              | | | |
-       | | +----> Button                  | | | +----> Button 1
-       | +------> Power                   | | +------> Button 2
-       +--------> Ground                  | +--------> Output 3
-					  +----------> Ground
-
-       Amstrad CPC                         Commodore C64
-
-					 +-----------> Analog Y
-      +---------> Right                  | +---------> Right
-      | +-------> Left                   | | +-------> Left
-      | | +-----> Down                   | | | +-----> Down
-      | | | +---> Up                     | | | | +---> Up
-      | | | |                            | | | | |
-  _____________                        _____________
-5 \ x o o o o / 1                    5 \ o o o o o / 1
-   \ x o o o /                          \ o o o o /
-  9 `~~~~~~~' 6                        9 `~~~~~~~' 6
-       | | |                              | | | |
-       | | +----> Button 1                | | | +----> Button
-       | +------> Button 2                | | +------> Power
-       +--------> Ground                  | +--------> Ground
-					  +----------> Analog X
-
-  And there were many others.
-
-2.2.1 Multisystem joysticks using db9.c
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  For the Multisystem joysticks, and their derivatives, the db9.c driver
-was written. It allows only one joystick / gamepad per parallel port, but
-the interface is easy to build and works with almost anything.
-
-  For the basic 1-button Multisystem joystick you connect its wires to the
-parallel port like this:
-
-(pin  1) -----> Power
-(pin 18) -----> Ground
-
-(pin  2) -----> Up
-(pin  3) -----> Down
-(pin  4) -----> Left
-(pin  5) -----> Right
-(pin  6) -----> Button 1
-
-  However, if the joystick is switch based (eg. clicks when you move it),
-you might or might not, depending on your parallel port, need 10 kOhm pullup
-resistors on each of the direction and button signals, like this:
-
-(pin 2) ------------+------> Up
-	  Resistor  |
-(pin 1) --[10kOhm]--+
-
-  Try without, and if it doesn't work, add them. For TTL based joysticks /
-gamepads the pullups are not needed.
-
-  For joysticks with two buttons you connect the second button to pin 7 on
-the parallel port.
-
-(pin 7) -----> Button 2
-
-  And that's it.
-
-  On a side note, if you have already built a different adapter for use with
-the digital joystick driver 0.8.0.2, this is also supported by the db9.c
-driver, as device type 8. (See section 3.2)
-
-2.2.2 Multisystem joysticks using gamecon.c
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  For some people just one joystick per parallel port is not enough, and/or
-want to use them on one parallel port together with NES/SNES/PSX pads. This is
-possible using the gamecon.c. It supports up to 5 devices of the above types,
-including 1 and 2 buttons Multisystem joysticks.
-
-  However, there is nothing for free. To allow more sticks to be used at
-once, you need the sticks to be purely switch based (that is non-TTL), and
-not to need power. Just a plain simple six switches inside. If your
-joystick can do more (eg. turbofire) you'll need to disable it totally first
-if you want to use gamecon.c.
-
-  Also, the connection is a bit more complex. You'll need a bunch of diodes,
-and one pullup resistor. First, you connect the Directions and the button
-the same as for db9, however with the diodes inbetween.
-
-	    Diodes
-(pin 2) -----|<|----> Up
-(pin 3) -----|<|----> Down
-(pin 4) -----|<|----> Left
-(pin 5) -----|<|----> Right
-(pin 6) -----|<|----> Button 1
-
-  For two button sticks you also connect the other button.
-
-(pin 7) -----|<|----> Button 2
-
-  And finally, you connect the Ground wire of the joystick, like done in
-this little schematic to Power and Data on the parallel port, as described
-for the NES / SNES pads in section 2.1 of this file - that is, one data pin
-for each joystick. The power source is shared.
-
-Data    ------------+-----> Ground
-	  Resistor  |
-Power   --[10kOhm]--+
-
-  And that's all, here we go!
-
-2.2.3 Multisystem joysticks using turbografx.c
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  The TurboGraFX interface, designed by
-
-	Steffen Schwenke <schwenke@burg-halle.de>
-
-  allows up to 7 Multisystem joysticks connected to the parallel port. In
-Steffen's version, there is support for up to 5 buttons per joystick.  However,
-since this doesn't work reliably on all parallel ports, the turbografx.c driver
-supports only one button per joystick. For more information on how to build the
-interface, see
-
-	http://www2.burg-halle.de/~schwenke/parport.html
-
-2.3 Sony Playstation
-~~~~~~~~~~~~~~~~~~~~
-
-  WARNING: PSX support is experimental, and at the moment doesn't seem to
-work for most people. If you like adventure, you can try yourself.
-
-  The PSX controller is supported by the gamecon.c.
-
-Pinout of the PSX controller (compatible with DirectPadPro):
-
-  +---------+---------+---------+
-9 | o  o  o | o  o  o | o  o  o | 1               parallel
-   \________|_________|________/                  port pins
-    |  |      |  |  |   |
-    |  |      |  |  |   +-------->  Clock    ---  (4)
-    |  |      |  |  +------------>  Select   ---  (3)
-    |  |      |  +--------------->  Power    ---  (5-9)
-    |  |      +------------------>  Ground   ---  (18-25)
-    |  +------------------------->  Command  ---  (2)
-    +---------------------------->  Data     ---  (10,11,12,13,15) one only...
-
-  You may have to add pull up/down resistors. Maybe your pad also won't like
-the 5V (PSX uses 3.7V).
-
-  Currently the driver supports only one psx pad per parallel port, and these
-controllers:
-
- * Standard PSX Pad
- * NegCon PSX Pad
- * Analog PSX Pad (red mode)
- * Analog PSX Pad (green mode)
-
-2.4 Sega
-~~~~~~~~
-  All the Sega controllers are more or less based on the standard 2-button
-Multisystem joystick. However, since they don't use switches and use TTL
-logic, the only driver usable with them is the db9.c driver.
-
-2.4.1 Sega Master System
-~~~~~~~~~~~~~~~~~~~~~~~~
-  The SMS gamepads are almost exactly the same as normal 2-button
-Multisystem joysticks. Set the driver to Multi2 mode, use the corresponding
-parallel port pins, and the following schematic:
-
-    +-----------> Power
-    | +---------> Right
-    | | +-------> Left
-    | | | +-----> Down
-    | | | | +---> Up
-    | | | | |
-  _____________
-5 \ o o o o o / 1
-   \ o o x o /
-  9 `~~~~~~~' 6
-     | |   |
-     | |   +----> Button 1
-     | +--------> Ground
-     +----------> Button 2
-
-2.4.2 Sega Genesis aka MegaDrive
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  The Sega Genesis (in Europe sold as Sega MegaDrive) pads are an extension
-to the Sega Master System pads. They use more buttons (3+1, 5+1, 6+1).  Use
-the following schematic:
-
-    +-----------> Power
-    | +---------> Right
-    | | +-------> Left
-    | | | +-----> Down
-    | | | | +---> Up
-    | | | | |
-  _____________
-5 \ o o o o o / 1
-   \ o o o o /
-  9 `~~~~~~~' 6
-     | | | |
-     | | | +----> Button 1
-     | | +------> Select
-     | +--------> Ground
-     +----------> Button 2
-
-  The Select pin goes to pin 14 on the parallel port.
-
-(pin 14) -----> Select
-
-  The rest is the same as for Multi2 joysticks using db9.c
-
-2.4.3 Sega Saturn
-~~~~~~~~~~~~~~~~~
-  Sega Saturn has eight buttons, and to transfer that, without hacks like
-Genesis 6 pads use, it needs one more select pin. Anyway, it is still
-handled by the db9.c driver. Its pinout is very different from anything
-else.  Use this schematic:
-
-    +-----------> Select 1
-    | +---------> Power
-    | | +-------> Up
-    | | | +-----> Down
-    | | | | +---> Ground
-    | | | | |
-  _____________
-5 \ o o o o o / 1
-   \ o o o o /
-  9 `~~~~~~~' 6
-     | | | |
-     | | | +----> Select 2
-     | | +------> Right
-     | +--------> Left
-     +----------> Power
-
-  Select 1 is pin 14 on the parallel port, Select 2 is pin 16 on the
-parallel port.
-
-(pin 14) -----> Select 1
-(pin 16) -----> Select 2
-
-  The other pins (Up, Down, Right, Left, Power, Ground) are the same as for
-Multi joysticks using db9.c
-
-3. The drivers
-~~~~~~~~~~~~~~
-  There are three drivers for the parallel port interfaces. Each, as
-described above, allows to connect a different group of joysticks and pads.
-Here are described their command lines:
-
-3.1 gamecon.c
-~~~~~~~~~~~~~
-  Using gamecon.c you can connect up to five devices to one parallel port. It
-uses the following kernel/module command line:
-
-	gc=port,pad1,pad2,pad3,pad4,pad5
-
-  Where 'port' the number of the parport interface (eg. 0 for parport0).
-
-  And 'pad1' to 'pad5' are pad types connected to different data input pins
-(10,11,12,13,15), as described in section 2.1 of this file.
-
-  The types are:
-
-	Type | Joystick/Pad
-	--------------------
-	  0  | None
-	  1  | SNES pad
-	  2  | NES pad
-	  4  | Multisystem 1-button joystick
-	  5  | Multisystem 2-button joystick
-	  6  | Sony PSX controller
-	  7  | N64 pad
-
-  The exact type of the PSX controller type is autoprobed, so you must have
-your controller plugged in before initializing.
-
-  Should you want to use more than one of parallel ports at once, you can use
-gc_2 and gc_3 as additional command line parameters for two more parallel
-ports.
-
-3.2 db9.c
-~~~~~~~~~
-  Apart from making an interface, there is nothing difficult on using the
-db9.c driver. It uses the following kernel/module command line:
-
-	db9=port,type
-
-  Where 'port' is the number of the parport interface (eg. 0 for parport0).
-
-  Caveat here: This driver only works on bidirectional parallel ports. If
-your parallel port is recent enough, you should have no trouble with this.
-Old parallel ports may not have this feature.
-
-  'Type' is the type of joystick or pad attached:
-
-	Type | Joystick/Pad
-	--------------------
-	  0  | None
-	  1  | Multisystem 1-button joystick
-	  2  | Multisystem 2-button joystick
-	  3  | Genesis pad (3+1 buttons)
-	  5  | Genesis pad (5+1 buttons)
-	  6  | Genesis pad (6+2 buttons)
-	  7  | Saturn pad (8 buttons)
-	  8  | Multisystem 1-button joystick (v0.8.0.2 pin-out)
-	  9  | Two Multisystem 1-button joysticks (v0.8.0.2 pin-out) 
-	 10  | Amiga CD32 pad
-
-  Should you want to use more than one of these joysticks/pads at once, you
-can use db9_2 and db9_3 as additional command line parameters for two
-more joysticks/pads.
-
-3.3 turbografx.c
-~~~~~~~~~~~~~~~~
-  The turbografx.c driver uses a very simple kernel/module command line:
-
-	tgfx=port,js1,js2,js3,js4,js5,js6,js7
-
-  Where 'port' is the number of the parport interface (eg. 0 for parport0).
-
-  'jsX' is the number of buttons the Multisystem joysticks connected to the
-interface ports 1-7 have. For a standard multisystem joystick, this is 1.
-
-  Should you want to use more than one of these interfaces at once, you can
-use tgfx_2 and tgfx_3 as additional command line parameters for two more
-interfaces.
-
-3.4 PC parallel port pinout
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-		  .----------------------------------------.
-   At the PC:     \ 13 12 11 10  9  8  7  6  5  4  3  2  1 /
-                   \  25 24 23 22 21 20 19 18 17 16 15 14 /
-                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	  Pin | Name    | Description
-	~~~~~~|~~~~~~~~~|~~~~~~~~~~
-	    1 | /STROBE | Strobe
-	  2-9 | D0-D7   | Data Bit 0-7
-	   10 | /ACK    | Acknowledge
-	   11 | BUSY    | Busy
-	   12 | PE      | Paper End
-	   13 | SELIN   | Select In
-	   14 | /AUTOFD | Autofeed
-	   15 | /ERROR  | Error
-	   16 | /INIT   | Initialize
-	   17 | /SEL    | Select
-	18-25 | GND     | Signal Ground
-
-3.5 End
-~~~~~~~
-  That's all, folks! Have fun!
diff -u --recursive --new-file v2.4.9/linux/Documentation/joystick.txt linux/Documentation/joystick.txt
--- v2.4.9/linux/Documentation/joystick.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/joystick.txt	Wed Dec 31 16:00:00 1969
@@ -1,582 +0,0 @@
-		       Linux Joystick driver v2.0.0
-	       (c) 1996-2000 Vojtech Pavlik <vojtech@suse.cz>
-			     Sponsored by SuSE
-----------------------------------------------------------------------------
-
-0. Disclaimer
-~~~~~~~~~~~~~
-  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
-
-  Should you need to contact me, the author, you can do so either by e-mail
-- mail your message to <vojtech@suse.cz>, or by paper mail: Vojtech Pavlik,
-Ucitelska 1576, Prague 8, 182 00 Czech Republic
-
-  For your convenience, the GNU General Public License version 2 is included
-in the package: See the file COPYING.
-
-1. Intro
-~~~~~~~~
-  The joystick driver for Linux provides support for a variety of joysticks
-and similar devices. It is based on a larger project aiming to support all
-input devices in Linux.
-
-  Should you encounter any problems while using the driver, or joysticks
-this driver can't make complete use of, I'm very interested in hearing about
-them. Bug reports and success stories are also welcome.
-
-  The input project website is at:
-
-	http://www.suse.cz/development/input/
-	http://atrey.karlin.mff.cuni.cz/~vojtech/input/
-
-  There is also a mailing list for the driver at:
-
-	listproc@atrey.karlin.mff.cuni.cz
-
-send "subscribe linux-joystick Your Name" to subscribe to it.
-
-2. Usage
-~~~~~~~~
-  For basic usage you just choose the right options in kernel config and
-you should be set.
-
-2.1 inpututils
-~~~~~~~~~~~~~~
-For testing and other purposes (for example serial devices), a set of
-utilities is available at the abovementioned website. I suggest you download
-and install it before going on.
-
-2.2 Device nodes
-~~~~~~~~~~~~~~~~
-For applications to be able to use the joysticks, in you don't use devfs,
-you'll have to manually create these nodes in /dev:
-
-cd /dev
-rm js*
-mkdir input
-mknod input/js0 c 13 0
-mknod input/js1 c 13 1
-mknod input/js2 c 13 2
-mknod input/js3 c 13 3
-ln -s input/js0 js0
-ln -s input/js1 js1
-ln -s input/js2 js2
-ln -s input/js3 js3
-
-For testing with inpututils it's also convenient to create these:
-
-mknod input/event0 c 13 64
-mknod input/event1 c 13 65
-mknod input/event2 c 13 66
-mknod input/event3 c 13 67
-
-2.4 Modules needed 
-~~~~~~~~~~~~~~~~~~
-  For all joystick drivers to function, you'll need the userland interface
-module in kernel, either loaded or compiled in:
-
-	modprobe joydev
-
-  For gameport joysticks, you'll have to load the gameport driver as well;
-
-	modprove ns558
-
-  And for serial port joysticks, you'll need the serial input line
-discipline module loaded and the inputattach utility started:
-
-	modprobe serport
-	inputattach -xxx /dev/tts/X &
-
-  In addition to that, you'll need the joystick driver module itself, most
-usually you'll have an analog joystick:
-
-	modprobe analog
-	
-  For automatic module loading, something like this might work:
-
-	alias tty-ldisc-2 serport
-	alias char-major-13 joydev ns558 analog
-
-2.5 Verifying that it works
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  For testing the joystick driver functionality, there is the jstest
-program in the utilities package. You run it by typing:
-
-	jstest /dev/js0
-
-  And it should show a line with the joystick values, which update as you
-move the stick, and press its buttons. The axes should all be zero when the
-joystick is in the center position. They should not jitter by themselves to
-other close values, and they also should be steady in any other position of
-the stick. They should have the full range from -32767 to 32767. If all this
-is met, then it's all fine, and you can play the games. :)
-
-  If it's not, then there might be a problem. Try to calibrate the joystick,
-and if it still doesn't work, read the drivers section of this file, the
-troubleshooting section, and the FAQ.
-
-2.6. Calibration
-~~~~~~~~~~~~~~~~
-  For most joysticks you won't need any manual calibration, since the
-joystick should be autocalibrated by the driver automagically. However, with
-some analog joysticks, that either do not use linear resistors, or if you
-want better precision, you can use the jscal program
-
-	jscal -c /dev/js0
-
- included in the joystick package to set better correction coefficients than
-what the driver would choose itself.
-
-  After calibrating the joystick you can verify if you like the new
-calibration using the jstest command, and if you do, you then can save the
-correction coefficients into a file
-
-	jscal -p /dev/js0 > /etc/joystick.cal
-
-  And add a line to your rc script executing that file
-
-	source /etc/joystick.cal
-
-  This way, after the next reboot your joystick will remain calibrated. You
-can also add the jscal -p line to your shutdown script.
-
-
-3. HW specific driver information
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In this section each of the separate hardware specific drivers is described.
-
-3.1 Analog joysticks
-~~~~~~~~~~~~~~~~~~~~
-  The analog.c uses the standard analog inputs of the gameport, and thus
-supports all standard joysticks and gamepads. It uses a very advanced
-routine for this, allowing for data precision that can't be found on any
-other system.
-
-  It also supports extensions like additional hats and buttons compatible
-with CH Flightstick Pro, ThrustMaster FCS or 6 and 8 button gamepads. Saitek
-Cyborg 'digital' joysticks are also supported by this driver, because
-they're basically souped up CHF sticks.
-
-  However the only types that can be autodetected are:
-
-* 2-axis, 4-button joystick
-* 3-axis, 4-button joystick
-* 4-axis, 4-button joystick
-* Saitek Cyborg 'digital' joysticks
-
-  For other joystick types (more/less axes, hats, and buttons) support
-you'll need to specify the types either on the kernel command line or on the
-module command line, when inserting analog.o into the kernel. The
-parameters are:
-
-	js=type,type,type,....
-
-  'type' is type of the joystick from the table below, defining joysticks
-present on gameports in the system, starting with gameport0, second 'type'
-entry defining joystick on gameport1 and so on.
-
-	Type     | Meaning
-	-----------------------------------
-	none     | No analog joystick on that port
-	auto     | Autodetect joystick
-	2btn     | 2-button n-axis joystick
-	y-joy    | Two 2-button 2-axis joysticks on an Y-cable
-	y-pad    | Two 2-button 2-axis gamepads on an Y-cable
-	fcs      | Thrustmaster FCS compatible joystick
-	chf      | Joystick with a CH Flightstick compatible hat
-	fullchf  | CH Flightstick compatible with two hats and 6 buttons
-	gamepad  | 4/6-button n-axis gamepad
-	gamepad8 | 8-button 2-axis gamepad
-
-  In case your joystick doesn't fit in any of the above categories, you can
-specify the type as a number by combining the bits in the table below. This
-is not recommended unless you really know what are you doing. It's not
-dangerous, but not simple either.
-
-	Bit | Meaning
-	--------------------------
-	 0  | Axis X1
-	 1  | Axis Y1
-	 2  | Axis X2
-	 3  | Axis Y2
-	 4  | Button A
-	 5  | Button B
-	 6  | Button C
-	 7  | Button D
-	 8  | CHF Buttons X and Y
-	 9  | CHF Hat 1
-	10  | CHF Hat 2
-	11  | FCS Hat
-	12  | Pad Button X
-	13  | Pad Button Y
-	14  | Pad Button U
-	15  | Pad Button V
-	16  | Saitek F1-F4 Buttons
-	17  | Saitek Digital Mode
-	19  | GamePad
-	20  | Joy2 Axis X1
-	21  | Joy2 Axis Y1
-	22  | Joy2 Axis X2
-	23  | Joy2 Axis Y2
-	24  | Joy2 Button A
-	25  | Joy2 Button B
-	26  | Joy2 Button C
-	27  | Joy2 Button D
-	31  | Joy2 GamePad
-
-3.2 Microsoft SideWinder joysticks
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  Microsoft 'Digital Overdrive' protocol is supported by the sidewinder.c
-module. All currently supported joysticks:
-
-* Microsoft SideWinder 3D Pro
-* Microsoft SideWinder Force Feedback Pro
-* Microsoft SideWinder Force Feedback Wheel
-* Microsoft SideWinder FreeStyle Pro 
-* Microsoft SideWinder GamePad (up to four, chained)
-* Microsoft SideWinder Precision Pro 
-* Microsoft SideWinder Precision Pro USB 
-
-  are autodetected, and thus no module parameters are needed.
-
-  There is one caveat with the 3D Pro. There are 9 buttons reported,
-although the joystick has only 8. The 9th button is the mode switch on the
-rear side of the joystick. However, moving it, you'll reset the joystick,
-and make it unresponsive for about a one third of a second. Furthermore, the
-joystick will also re-center itself, taking the position it was in during
-this time as a new center position. Use it if you want, but think first.
-
-  The SideWinder Standard is not a digital joystick, and thus is supported
-by the analog driver described above. 
-
-3.3 Logitech ADI devices
-~~~~~~~~~~~~~~~~~~~~~~~~
-  Logitech ADI protocol is supported by the adi.c module. It should support
-any Logitech device using this protocol. This includes, but is not limited
-to:
-
-* Logitech CyberMan 2
-* Logitech ThunderPad Digital
-* Logitech WingMan Extreme Digital
-* Logitech WingMan Formula
-* Logitech WingMan Interceptor
-* Logitech WingMan GamePad
-* Logitech WingMan GamePad USB
-* Logitech WingMan GamePad Extreme
-* Logitech WingMan Extreme Digital 3D
-
-  ADI devices are autodetected, and the driver supports up to two (any
-combination of) devices on a single gameport, using an Y-cable or chained
-together.
-
-  Logitech WingMan Joystick, Logitech WingMan Attack, Logitech WingMan
-Extreme and Logitech WingMan ThunderPad are not digital joysticks and are
-handled by the analog driver described above. Logitech WingMan Warrior and
-Logitech Magellan are supported by serial drivers described below.  Logitech
-WingMan Force and Logitech WingMan Formula Force are supported by the
-I-Force driver described below. Logitech CyberMan is not supported yet.
-
-3.4 Gravis GrIP
-~~~~~~~~~~~~~~~
-  Gravis GrIP protocol is supported by the grip.c module. It currently
-supports:
-
-* Gravis GamePad Pro
-* Gravis BlackHawk Digital
-* Gravis Xterminator
-* Gravis Xterminator DualControl
-
-  All these devices are autodetected, and you can even use any combination
-of up to two of these pads either chained together or using an Y-cable on a
-single gameport.
-
-GrIP MultiPort isn't supported yet. Gravis Stinger is a serial device and
-hopefully will be supported soon. Other Gravis joysticks are supported by
-the analog driver.
-
-3.5 FPGaming A3D and MadCatz A3D
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  The Assassin 3D protocol created by FPGaming, is used both by FPGaming
-themselves and is licensed to MadCatz. A3D devices are supported by the
-a3d.c module. It currently supports:
-
-* FPGaming Assassin 3D
-* MadCatz Panther
-* MadCatz Panther XL
-
-  All these devices are autodetected. Because the Assassin 3D and the Panther
-allow connecting analog joysticks to them, you'll need to load the analog
-driver as well to handle the attached joysticks.
-
-  The trackball should work with USB mousedev module as a normal mouse. See
-the USB documentation for how to setup an USB mouse.
-
-3.6 ThrustMaster DirectConnect (BSP)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  The TM DirectConnect (BSP) protocol is supported by the tmdc.c
-module. This includes, but is not limited to:
-
-* ThrustMaster Millenium 3D Inceptor
-* ThrustMaster 3D Rage Pad
-* ThrustMaster Fusion Digital Game Pad
-
-  Devices not directly supported, but hopefully working are:
-
-* ThrustMaster FragMaster
-* ThrustMaster Attack Throttle
-
-  If you have one of these, contact me.
-
-  BSP devices are autodetected, and thus no parameters to the module
-are needed. Up to two TMDC devices can be connected to one gameport, using
-an Y-cable.
-
-3.7 Creative Labs Blaster
-~~~~~~~~~~~~~~~~~~~~~~~~~
-  The Blaster protocol is supported by the cobra.c module. It supports only
-the:
-
-* Creative Blaster GamePad Cobra
-
-  Up to two of these can be used on a single gameport, using an Y-cable.
-
-3.8 Genius Digital joysticks 
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  The Genius digitally communicating joysticks are supported by the gf2k.c
-module. This includes:
-
-* Genius Flight2000 F-23 joystick 
-* Genius Flight2000 F-31 joystick 
-* Genius G-09D gamepad
-
-  Other Genius digital joysticks are not supported yet, but support can be
-added fairly easily.
-
-3.9 InterAct Digital joysticks
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  The InterAct digitally communicating joysticks are supported by the
-interact.c module. This includes:
-
-* InterAct HammerHead/FX gamepad
-* InterAct ProPad8 gamepad 
-
-  Other InterAct digital joysticks are not supported yet, but support can be 
-added fairly easily.
-
-3.10 PDPI Lightning 4 gamecards
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  PDPI Lightning 4 gamecards are supported by the lightning.c module.
-Once the module is loaded, the analog driver can be used to handle the
-joysticks. Digitally communicating joystick will work only on port 0, while
-using Y-cables, you can connect up to 8 analog joysticks to a single L4
-card, 16 in case you have two in your system.
-
-3.11 Trident 4DWave / Aureal Vortex
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  Soundcards with a Trident 4DWave DX/NX or Aureal Vortex/Vortex2 chipsets
-provide an "Enhanced Game Port" mode where the soundcard handles polling the
-joystick.  This mode is supported by the pcigame.c module. Once loaded the
-analog driver can use the enhanced features of these gameports..
-
-3.12 Amiga
-~~~~~~~~~~
-  Amiga joysticks, connected to an Amiga, are supported by the amijoy.c
-driver. Since they can't be autodetected, the driver has a command line.
-
-	amijoy=a,b
-
-  a and b define the joysticks connected to the JOY0DAT and JOY1DAT ports of
-the Amiga.
-
-	Value | Joystick type
-	---------------------
-	  0   | None
-	  1   | 1-button digital joystick
-
-  No more joystick types are supported now, but that should change in the
-future if I get an Amiga in the reach of my fingers.
-
-3.13 Game console and 8-bit pads and joysticks
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-See joystick-parport.txt for more info.
-
-3.14 SpaceTec/LabTec devices
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  SpaceTec serial devices communicate using the SpaceWare protocol. It is
-supported by the spaceorb.c and spaceball.c drivers. The devices currently
-supported by spaceorb.c are:
-
-* SpaceTec SpaceBall Avenger
-* SpaceTec SpaceOrb 360
-
-Devices currently supported by spaceball.c are:
-
-* SpaceTec SpaceBall 4000 FLX
-
-  In addition to having the spaceorb/spaceball and serport modules in the
-kernel, you also need to attach a serial port to it. to do that, run the
-jsattach program:
-
-	inputattach --spaceorb /dev/tts/x &
-or
-	jsattach --spaceball /dev/tts/x &
-
-where /dev/tts/x is the serial port which the device is connected to. After
-doing this, the device will be reported and will start working.
-
-  There is one caveat with the SpaceOrb. The button #6, the on the bottom
-side of the orb, although reported as an ordinary button, causes internal
-recentering of the spaceorb, moving the zero point to the position in which
-the ball is at the moment of pressing the button. So, think first before
-you bind it to some other function.
-
-SpaceTec SpaceBall 2003 FLX and 3003 FLX are not supported yet. 
-
-3.15 Logitech SWIFT devices
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  The SWIFT serial protocol is supported by the warrior.c module. It
-currently supports only the:
-
-* Logitech WingMan Warrior
-
-but in the future, Logitech CyberMan (the original one, not CM2) could be
-supported as well. To use the module, you need to run jsattach after you
-insert/compile the module into your kernel:
-
-	inputattach --warrior /dev/tts/x &
-
-/dev/tts/x is the serial port your Warrior is attached to.
-
-3.16 Magellan / Space Mouse
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  The Magellan (or Space Mouse), manufactured by LogiCad3d (formerly Space
-Systems), for many other companies (Logitech, HP, ...) is supported by the
-joy-magellan module. It currently supports only the:
-
-* Magellan 3D
-* Space Mouse
-
-models, the additional buttons on the 'Plus' versions are not supported yet.
-
-  To use it, you need to attach the serial port to the driver using the
-
-	inputattach --magellan /dev/tts/x &
-
-command. After that the Magellan will be detected, initialized, will beep,
-and the /dev/input/jsX device should become usable.
-
-3.17 I-Force devices 
-~~~~~~~~~~~~~~~~~~~~
-  All I-Force devices ale supported by the iforce.c module. This includes,
-but is not limited to:
-
-* Logitech WingMan Force
-* Logitech WingMan Force Wheel 
-* Guillemot Race Leader wheel 
-
-  To use it, you need to attach the serial port to the driver using the
-
-	inputattach --iforce /dev/tts/x &
-
-command. After that the I-Force device will be detected, and the
-/dev/input/jsX device should become usable.
-
-  In case you're using the device via the USB port, the inputattach command
-isn't needed.
-
-4. Troubleshooting
-~~~~~~~~~~~~~~~~~~
-  There is quite a high probability that you run into some problems. For
-testing whether the driver works, if in doubt, use the jstest utility in
-some of its modes. The most useful modes are "normal" - for the 1.x
-interface, and "old" for the "0.x" interface. You run it by typing:
-
-	jstest --normal /dev/input/js0
-	jstest --old    /dev/input/js0
-
-  Additionally you can do a test with the evtest utility:
-
-	evtest /dev/input/event0
-
-  Oh, and read the FAQ! :)
-
-5. FAQ
-~~~~~~
-Q: Running 'jstest /dev/js0' results in "File not found" error. What's the
-   cause?
-A: The device files don't exist. Create them (see section 2.2).
-
-Q: Is it possible to connect my old Atari/Commodore/Amiga/console joystick
-   or pad that uses a 9-pin D-type cannon connector to the serial port of my
-   PC?
-A: Yes, it is possible, but it'll burn your serial port or the pad. It
-   won't work, of course.
-
-Q: My joystick doesn't work with Quake / Quake 2. What's the cause?
-A: Quake / Quake 2 don't support joystick. Use joy2key to simulate keypresses
-   for them.
-
-6. Programming Interface
-~~~~~~~~~~~~~~~~~~~~~~~~
-  The 1.0 driver uses a new, event based approach to the joystick driver.
-Instead of the user program polling for the joystick values, the joystick
-driver now reports only any changes of its state. See joystick-api.txt,
-joystick.h and jstest.c included in the joystick package for more
-information. The joystick device can be used in either blocking or
-nonblocking mode and supports select() calls.
-
-  For backward compatibility the old (v0.x) interface is still included.
-Any call to the joystick driver using the old interface will return values
-that are compatible to the old interface.  This interface is still limited
-to 2 axes, and applications using it usually decode only 2 buttons, although
-the driver provides up to 32.
-
-7. Credits
-~~~~~~~~~~
-  Thanks to the following people who contributed code, ideas or specifications
-to the joystick driver development:
-
-	Arthur C. Smith		<asmith@cbnewsd.att.com>
-	Eyal Lebedinsky		<eyal@eyal.emu.id.au>
-	Jeff Tranter		<tranter@software.mitel.com>
-	Carlos Puchol		<cpg@cs.utexas.edu>
-	Matt Rhoten		<mrhoten@oz.net>
-	Dan Fandrich		<dan@fch.wimsey.bc.ca>
-	Sverker Wilberg		<sverkerw@manila.docs.uu.se>
-	Hal Maney		<maney@norden.com>
-	Bernd Schmidt		<crux@pool.informatik.rwth-aachen.de>
-	Alan Cox		<alan@lxorguk.ukuu.org.uk>
-	John Markus Bjorndalen	<johnm@cs.uit.no>
-	Boris Muehmer		<mhs@cybernet-ag.de>
-	Robert W. Grubbs	<rwgrubbs@vt.edu>
-	Pete Chown		<pete.chown@skygate.co.uk>
-	Benji York		<benji@cookeville.com>
-	Leslie F. Donaldson	<donaldlf@cs.rose-hulman.edu>
-	Eng-Jon Ong		<ongej@dcs.qmw.ac.uk>
-	Ragnar Hojland Espinosa	<ragnar@macula.net>
-	Brian Gerst		<bgerst@quark.vpplus.com>
-	Andree Borrmann		<a.borrmann@tu-bs.de>
-	Martin Giguere		<zefrench@hotmail.com>
-	David Thompson		<dcthomp@mail.utexas.edu>
-	Justin Wake		<spectre@telefragged.com>
-	Benoit Triquet		<benoit@adsl-216-100-248-201.dsl.pacbell.net>
-	John Dahlstrom		<jodaman@bradley.edu>
-	Dan Gohman		<gohmandj@mrs.umn.edu>
-	Joe Krahn		<krahn@niehs.nih.gov>
-	David Kuder		<alphagod@penguinpowered.com>
-	Raymond Ingles		<sorceror@tir.com>
-
-  If you think you should be in this list and are not, it's possible that
-I forgot to include you - contact me and I'll correct the error. :)
diff -u --recursive --new-file v2.4.9/linux/Documentation/kernel-doc-nano-HOWTO.txt linux/Documentation/kernel-doc-nano-HOWTO.txt
--- v2.4.9/linux/Documentation/kernel-doc-nano-HOWTO.txt	Fri Mar  2 18:43:11 2001
+++ linux/Documentation/kernel-doc-nano-HOWTO.txt	Fri Sep  7 18:15:17 2001
@@ -35,9 +35,9 @@
 
 - Makefile
 
-  The targets 'sgmldocs', 'psdocs', and 'pdfdocs' are used to build
-  DocBook files, PostScript files, and PDF files in
-  Documentation/DocBook.
+  The targets 'sgmldocs', 'psdocs', 'pdfdocs', and 'htmldocs' are used
+  to build DocBook files, PostScript files, PDF files, and html files
+  in Documentation/DocBook.
 
 - Documentation/DocBook/Makefile
 
@@ -49,10 +49,11 @@
 
 If you just want to read the ready-made books on the various
 subsystems (see Documentation/DocBook/*.tmpl), just type 'make
-psdocs', or 'make pdfdocs', depending on your preference.  If you
-would rather read a different format, you can type 'make sgmldocs' and
-then use DocBook tools to convert Documentation/DocBook/*.sgml to a
-format of your choice (for example, 'db2html ...').
+psdocs', or 'make pdfdocs', or 'make htmldocs', depending on your 
+preference.  If you would rather read a different format, you can type 
+'make sgmldocs' and then use DocBook tools to convert 
+Documentation/DocBook/*.sgml to a format of your choice (for example, 
+'db2html ...' if 'make htmldocs' was not defined).
 
 If you want to see man pages instead, you can do this:
 
@@ -111,7 +112,9 @@
 (*)?*/
 
 The short function description cannot be multiline, but the other
-descriptions can be.
+descriptions can be (and they can contain blank lines). Avoid putting a
+spurious blank line after the function name, or else the description will
+be repeated!
 
 All descriptive text is further processed, scanning for the following special
 patterns, which are highlighted appropriately.
diff -u --recursive --new-file v2.4.9/linux/Documentation/mips/pci/pci.README linux/Documentation/mips/pci/pci.README
--- v2.4.9/linux/Documentation/mips/pci/pci.README	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/mips/pci/pci.README	Mon Aug 27 08:56:31 2001
@@ -0,0 +1,67 @@
+
+Pete Popov, ppopov@pacbell.net
+07/11/2001
+
+This README briefly explains how to use the pci and pci_auto
+code in arch/mips/kernel.  The code was ported from PowerPC and
+modified slightly. It has been tested pretty well on PPC on some
+rather complex systems with multiple bridges and devices behind
+each bridge. However, at the time this README was written, the
+mips port was tested only on boards with a single pci bus and
+no P2P bridges.  It's very possible that on boards with P2P
+bridges some modifications have to be made. The code will 
+evolve, no doubt, but currently every single mips board
+is doing its own pcibios thing and it has become a big
+mess.  This generic pci code is meant to clean up the mips
+pci mess and make it easier to add pci support to new boards.
+
+arch/mips/kernel/pci_auto.c has the pci bus enumeration code.
+This code scans the pci bus(es) and assigns all of the resources.
+Thus, you don't need the boot code to that, and many boot codes
+don't do it correctly anyway.  To enable the pci_auto code, add
+
+define_bool CONFIG_PCI_AUTO y 
+
+inside the define for your board in arch/mips/config.in. 
+For example, the Galileo EV96100 board  looks like this:
+
+if [ "$CONFIG_MIPS_EV96100" = "y" ]; then
+	define_bool CONFIG_PCI y
+	define_bool CONFIG_MIPS_GT96100 y
+	define_bool CONFIG_NEW_PCI y
+	define_bool CONFIG_PCI_AUTO y
+	define_bool CONFIG_SWAP_IO_SPACE y
+fi 
+
+
+Next, if you want to use the arch/mips/kernel/pci code, which has the
+pcibios_init() function, add
+
+define_bool CONFIG_NEW_PCI y
+ 
+inside the define for your board. Again, the EV96100 example above
+show NEW_PCI turned on.
+
+Note that you can enable CONFIG_NEW_PCI code without enabling 
+CONFIG_PCI_AUTO. But you can't do the opposite because the pci_auto
+routines are called from pcibios_init(), which is part of the 
+CONFIG_NEW_PCI code.
+
+
+Now you need to add your files to hook in your pci configuration
+cycles.  Usually you'll need only a couple of files named something
+like pci_fixups.c and pci_ops.c.  You can copy the templates
+provided and fill in the code.
+
+The file pci_ops.c should contain the pci configuration cycles routines.
+It also has the mips_pci_channels[] array which contains the descriptors
+of each pci controller.
+
+The file pci_fixups.c contains a few routines to do interrupt fixups,
+resources fixups, and, if needed, pci bios fixups.
+
+Usually you'll put your pci_fixups.c file in your board specific directory, 
+since the functions in that file are board specific.  The functions in
+pci_ops.c, on the other hand, are usually pci controller specific so that
+file could be shared among a few different boards using the same
+pci controller.
diff -u --recursive --new-file v2.4.9/linux/Documentation/networking/dl2k.txt linux/Documentation/networking/dl2k.txt
--- v2.4.9/linux/Documentation/networking/dl2k.txt	Wed Jul 25 17:10:17 2001
+++ linux/Documentation/networking/dl2k.txt	Thu Sep 20 20:56:31 2001
@@ -187,15 +187,11 @@
 				  10mbps_fd	10Mbps full duplex.
 				  100mbps_hd	100Mbps half duplex.
 				  100mbps_fd	100Mbps full duplex.
-				  1000mbps_fd	1000Mbps full duplex.
-				  1000mbps_hd	1000Mbps half duplex.
 				  0		Autosensing active media.
 				  1		10Mbps half duplex.
 				  2		10Mbps full duplex.
 				  3		100Mbps half duplex.
 				  4		100Mbps full duplex.
-				  5		1000Mbps full duplex.
-				  6		1000Mbps half duplex.
 				  By default, the NIC operates at autosense.
 
 vlan=x				- Specifies the VLAN ID. If vlan=0, the
@@ -205,7 +201,16 @@
 jumbo=x				- Specifies the jumbo frame support. If jumbo=1,
 				  the NIC accept jumbo frames. By default, this
 				  function is disabled.
-
+				  Jumbo frame usually improve the performance
+				  int gigabit.
+				  
+int_count			- Rx frame count each interrupt.
+int_timeout			- Rx DMA wait time for an interrupt. Proper 
+				  values of int_count and int_timeout bring 
+				  a conspicuous performance in the fast machine. 
+				  For P4 1.5GHz systems, a setting of 
+				  int_count=5 and int_timeout=750 is
+				  recommendable.
 Configuration Script Sample
 ===========================
 Here is a sample of a simple configuration script:
@@ -222,7 +227,7 @@
 
 Troubleshooting
 ===============
-Q1. Source files contain behind every line.
+Q1. Source files contain ^ M behind every line.
 	Make sure all files are Unix file format (no LF). Try the following
     shell command to convert files.
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/nmi_watchdog.txt linux/Documentation/nmi_watchdog.txt
--- v2.4.9/linux/Documentation/nmi_watchdog.txt	Mon Aug 21 08:57:35 2000
+++ linux/Documentation/nmi_watchdog.txt	Mon Sep 17 23:03:09 2001
@@ -1,19 +1,27 @@
 
-Is your SMP system locking up unpredictably? No keyboard activity, just
+Is your ix86 system locking up unpredictably? No keyboard activity, just
 a frustrating complete hard lockup? Do you want to help us debugging
 such lockups? If all yes then this document is definitely for you.
 
-on Intel SMP hardware there is a feature that enables us to generate
-'watchdog NMI interrupts'. (NMI: Non Maskable Interrupt - these get
-executed even if the system is otherwise locked up hard) This can be
-used to debug hard kernel lockups. By executing periodic NMI interrupts,
-the kernel can monitor whether any CPU has locked up, and print out
-debugging messages if so.  You can enable/disable the NMI watchdog at boot
-time with the 'nmi_watchdog=1' boot parameter. Eg. the relevant
-lilo.conf entry:
+On Intel and similar ix86 type hardware there is a feature that enables
+us to generate 'watchdog NMI interrupts'.  (NMI: Non Maskable Interrupt
+which get executed even if the system is otherwise locked up hard).
+This can be used to debug hard kernel lockups.  By executing periodic
+NMI interrupts, the kernel can monitor whether any CPU has locked up,
+and print out debugging messages if so.  You must enable the NMI
+watchdog at boot time with the 'nmi_watchdog=n' boot parameter.  Eg.
+the relevant lilo.conf entry:
 
         append="nmi_watchdog=1"
 
+For SMP machines and UP machines with an IO-APIC use nmi_watchdog=1.
+For UP machines without an IO-APIC use nmi_watchdog=2, this only works
+for some processor types.  If in doubt, boot with nmi_watchdog=1 and
+check the NMI count in /proc/interrupts; if the count is zero then
+reboot with nmi_watchdog=2 and check the NMI count.  If it is still
+zero then log a problem, you probably have a processor that needs to be
+added to the nmi code.
+
 A 'lockup' is the following scenario: if any CPU in the system does not
 execute the period local timer interrupt for more than 5 seconds, then
 the NMI handler generates an oops and kills the process. This
@@ -24,8 +32,9 @@
 cannot even accept NMI interrupts, or the crash has made the kernel
 unable to print messages.
 
-NOTE: currently the NMI-oopser is enabled unconditionally on x86 SMP
-boxes.
+NOTE: starting with 2.4.2-ac18 the NMI-oopser is disabled by default,
+you have to enable it with a boot time parameter.  Prior to 2.4.2-ac18
+the NMI-oopser is enabled unconditionally on x86 SMP boxes.
 
 [ feel free to send bug reports, suggestions and patches to
   Ingo Molnar <mingo@redhat.com> or the Linux SMP mailing
diff -u --recursive --new-file v2.4.9/linux/Documentation/parisc/registers linux/Documentation/parisc/registers
--- v2.4.9/linux/Documentation/parisc/registers	Tue Dec  5 12:29:38 2000
+++ linux/Documentation/parisc/registers	Fri Sep 14 14:04:06 2001
@@ -16,17 +16,17 @@
 CR11				as specified by ABI
 CR14 (interruption vector)	initialized to fault_vector
 CR15 (EIEM)			initialized to all ones*
-CR16 (Interval Timer)		timer interrupt
+CR16 (Interval Timer)		read for cycle count/write starts Interval Tmr
 CR17-CR22			interruption parameters
-CR23 (EIRR)			read for pending interrupts
+CR23 (EIRR)			read for pending interrupts/write clears bits
 CR24 (TR 0)			Kernel Space Page Directory Pointer
 CR25 (TR 1)			User   Space Page Directory Pointer
-CR26 (TR 2)
-CR27 (TR 3)
-CR28 (TR 4)			used by interruption handlers
-CR29 (TR 5)			used by interruption handlers
+CR26 (TR 2)			not used
+CR27 (TR 3)			Thread descriptor pointer
+CR28 (TR 4)			not used
+CR29 (TR 5)			not used
 CR30 (TR 6)			current / 0
-CR31 (TR 7)			used by interruption handlers
+CR31 (TR 7)			Temporary register, used in various places
 
 	Space Registers (kernel mode)
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/s390/3270.txt linux/Documentation/s390/3270.txt
--- v2.4.9/linux/Documentation/s390/3270.txt	Thu May 24 15:14:08 2001
+++ linux/Documentation/s390/3270.txt	Fri Sep  7 09:28:38 2001
@@ -34,17 +34,6 @@
 dialed-in x3270.
 
 
-HELP !!!
-
-The device name of e.g. /dev/3270/tty620 noted below is at variance
-with "standard" Linux device names.  What should it be?  The portion
-"/dev/3270" was recommended by H. Peter Anvin, maintainer of the
-official Linux major-numbers list; the portion "tty620" was recommended
-by me.  Please send your thoughts on this issue at least to me at
-rbh00@utsglobal.com.  Even if you think it's okay as is, please let me
-know.  Thanks.
-
-
 INSTALLATION.
 
 You install the driver by installing a patch, doing a kernel build, and
@@ -60,9 +49,14 @@
 
 If you have chosen to make tub3270 a module, you add a line to
 /etc/modules.conf.  If you are working on a VM virtual machine, you
-can use DEF GRAF to define virtual 3270 devices.  If you generate 3270
-console support, the driver automatically converts your console at boot
-time to a 3270 if it is a 3215.
+can use DEF GRAF to define virtual 3270 devices.
+
+You may generate both 3270 and 3215 console support, or one or the
+other, or neither.  If you generate both, the console type under VM is
+not changed.  Use #CP Q TERM to see what the current console type is.
+Use #CP TERM CONMODE 3270 to change it to 3270.  If you generate only
+3270 console support, then the driver automatically converts your console
+at boot time to a 3270 if it is a 3215.
 
 In brief, these are the steps:
 	1. Install the tub3270 patch
@@ -78,21 +72,17 @@
 
 Here are the installation steps in detail:
 
-	0.  Retrieve the patch file via anonymous ftp from
-	ftp://ftp.utsglobal.com/pub/tub3270.  The patch is designed
-	to apply smoothly to an IBM 2.4.0 system with no other
-	UTS-Global patches applied.  We know of some easily resolvable
-	conflicts between this and other of our patches.
-
-	1. Apply the patch.  Then do
+	1.  The 3270 driver is a part of the official Linux kernel
+	source.  Build a tree with the kernel source and any necessary
+	patches.  Then do
 		make oldconfig
-			(Reply "y" or "m" for CONFIG_3270; if "y",
-			reply "y" or "n" for CONFIG_3270_CONSOLE)
+		(If you wish to disable 3215 console support, edit
+		.config; change CONFIG_TN3215's value to "n";
+		and rerun "make oldconfig".)
 		make dep
 		make image
 		make modules
 		make modules_install
-		<run silo in the usual way>
 
 	2. (Perform this step only if you have configured tub3270 as a
 	module.)  Add a line to /etc/modules.conf to automatically
@@ -122,12 +112,17 @@
 	config3270.sh.	Inspect the output script it produces,
 	/tmp/mkdev3270, and then run that script.  This will create the
 	necessary character special device files and make the necessary
-	changes to /etc/inittab.  Then notify /sbin/init that /etc/inittab
-	has changed, by issuing the telinit command with the q operand:
+	changes to /etc/inittab.  If you have selected DEVFS, the driver
+	itself creates the device files, and /tmp/mkdev3270 only changes
+	/etc/inittab.
+
+	Then notify /sbin/init that /etc/inittab has changed, by issuing
+	the telinit command with the q operand:
 		cd /usr/src/linux/Documentation/s390
 		sh config3270.sh
 		sh /tmp/mkdev3270
 		telinit q
+
 	This should be sufficient for your first time.	If your 3270
 	configuration has changed and you're reusing config3270, you
 	should follow these steps:
diff -u --recursive --new-file v2.4.9/linux/Documentation/s390/config3270.sh linux/Documentation/s390/config3270.sh
--- v2.4.9/linux/Documentation/s390/config3270.sh	Wed Apr 11 19:02:27 2001
+++ linux/Documentation/s390/config3270.sh	Fri Sep  7 09:28:38 2001
@@ -37,10 +37,14 @@
 echo "#!/bin/sh" > $SCR || exit 1
 echo " " >> $SCR
 echo "# Script built by /sbin/config3270" >> $SCR
-echo rm -rf "$D/$SUBD/*" >> $SCR
+if [ ! -d /dev/dasd ]; then
+	echo rm -rf "$D/$SUBD/*" >> $SCR
+fi
 echo "grep -v $TTY $INITTAB > $NINITTAB" > $SCRTMP || exit 1
 echo "echo $ADDNOTE >> $NINITTAB" >> $SCRTMP
-echo mkdir -p $D/$SUBD >> $SCR
+if [ ! -d /dev/dasd ]; then
+	echo mkdir -p $D/$SUBD >> $SCR
+fi
 
 # Now query the tub3270 driver for 3270 device information
 # and add appropriate mknod and mingetty lines to our files
@@ -48,13 +52,19 @@
 while read devno maj min;do
 	if [ $min = 0 ]; then
 		fsmaj=$maj
-		echo mknod $D/$TUB c $fsmaj 0 >> $SCR
-		echo chmod 666 $D/$TUB >> $SCR
+		if [ ! -d /dev/dasd ]; then
+			echo mknod $D/$TUB c $fsmaj 0 >> $SCR
+			echo chmod 666 $D/$TUB >> $SCR
+		fi
 	elif [ $maj = CONSOLE ]; then
-		echo mknod $D/$TUB$devno c $fsmaj $min >> $SCR
+		if [ ! -d /dev/dasd ]; then
+			echo mknod $D/$TUB$devno c $fsmaj $min >> $SCR
+		fi
 	else
-		echo mknod $D/$TTY$devno c $maj $min >>$SCR
-		echo mknod $D/$TUB$devno c $fsmaj $min >> $SCR
+		if [ ! -d /dev/dasd ]; then
+			echo mknod $D/$TTY$devno c $maj $min >>$SCR
+			echo mknod $D/$TUB$devno c $fsmaj $min >> $SCR
+		fi
 		echo "echo t$min$GETTYLINE $TTY$devno >> $NINITTAB" >> $SCRTMP
 	fi
 done < $P
diff -u --recursive --new-file v2.4.9/linux/Documentation/sound/CMI8338 linux/Documentation/sound/CMI8338
--- v2.4.9/linux/Documentation/sound/CMI8338	Wed Jul 25 17:10:17 2001
+++ linux/Documentation/sound/CMI8338	Fri Sep  7 09:28:38 2001
@@ -69,8 +69,8 @@
   Some functions for the cm8738 can be configured in Kernel Configuration
   or modules parameters. Set these parameters to 1 to enable.
 
-  mpu_io:	I/O ports base for MPU-401, 0 if disabled.
-  fm_io:	I/O ports base for OPL-3, 0 if disabled.
+  mpuio:	I/O ports base for MPU-401, 0 if disabled.
+  fmio:		I/O ports base for OPL-3, 0 if disabled.
   spdif_inverse:Inverse the S/PDIF-in signal, this depends on your
 		CD-ROM or DVD-ROM.
   spdif_loop:   Enable S/PDIF loop, this route S/PDIF-in to S/PDIF-out
@@ -80,8 +80,6 @@
                 rear-out.
   use_line_as_bass:Enable this if you want to use line-in as
                 bass-out.
-  modem:	You will need to set this parameter if you want to use
-		the HSP modem. You need install the pctel.o, the modem
-		driver itself.
   joystick:	Enable joystick. You will need to install Linux joystick
 		driver.
+
diff -u --recursive --new-file v2.4.9/linux/Documentation/sound/WaveArtist linux/Documentation/sound/WaveArtist
--- v2.4.9/linux/Documentation/sound/WaveArtist	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/WaveArtist	Fri Sep  7 09:28:38 2001
@@ -0,0 +1,170 @@
+
+ (the following is from the armlinux CVS)
+
+ WaveArtist mixer and volume levels can be accessed via these commands:
+
+  nn30	read registers nn, where nn = 00 - 09 for mixer settings
+		                              0a - 13 for channel volumes
+  mm31	write the volume setting in pairs, where mm = (nn - 10) / 2
+  rr32	write the mixer settings in pairs, where rr = nn/2
+  xx33	reset all settings to default
+  0y34	select mono source, y=0 = left, y=1 = right
+
+                                           bits
+ nn  15  14 13 12 11   10    9     8     7    6     5     4     3     2     1     0
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 00 | 0 | 0  0  1  1 | left line mixer gain       | left aux1 mixer gain        |lmute|
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 01 | 0 | 0  1  0  1 | left aux2 mixer gain       | right 2 left mic gain       |mmute|
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 02 | 0 | 0  1  1  1 | left mic mixer gain        | left mic  | left mixer gain |dith |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 03 | 0 | 1  0  0  1 | left mixer input select                |lrfg | left ADC gain   |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 04 | 0 | 1  0  1  1 | right line mixer gain      | right aux1 mixer gain       |rmute|
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 05 | 0 | 1  1  0  1 | right aux2 mixer gain      | left 2 right mic gain       |test |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 06 | 0 | 1  1  1  1 | right mic mixer gain       | right mic |right mixer gain |rbyps|
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 07 | 1 | 0  0  0  1 | right mixer select                     |rrfg | right ADC gain  |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 08 | 1 | 0  0  1  1 | mono mixer gain            |right ADC mux sel|left ADC mux sel |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 09 | 1 | 0  1  0  1 |loopb|left linout|loop|ADCch|TxFch|OffCD|test |loopb|loopb|osamp|
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 0a | 0 | left PCM channel volume                                                     |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 0b | 0 | right PCM channel volume                                                    |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 0c | 0 | left FM channel volume                                                      |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 0d | 0 | right FM channel volume                                                     |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 0e | 0 | left wavetable channel volume                                               |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 0f | 0 | right wavetable channel volume                                              |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 10 | 0 | left PCM expansion channel volume                                           |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 11 | 0 | right PCM expansion channel volume                                          |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 12 | 0 | left FM expansion channel volume                                            |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+ 13 | 0 | right FM expansion channel volume                                           |
+----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
+
+ lmute: left mute
+ mmute: mono mute
+ dith: dithds
+ lrfg:
+ rmute: right mute
+ rbyps: right bypass
+ rrfg:
+ ADCch:
+ TxFch:
+ OffCD:
+ osamp:
+
+ And the following diagram is derived from the description in the CVS archive:
+
+ MIC L (mouthpiece)
+   +------+
+ -->PreAmp>-\
+   +--^---+ |
+      |     |
+    r2b4-5  |                                +--------+
+       /----*-------------------------------->5       |
+       |                                     |        |
+       | /----------------------------------->4       |
+       | |                                   |        |
+       | | /--------------------------------->3 1of5  |  +---+
+       | | |                                 |  mux   >-->AMP>--> ADC L
+       | | | /------------------------------->2       |  +-^-+
+       | | | |                               |        |    |
+ Line  | | | | +----+  +------+  +---+  /---->1       |  r3b3-0
+ ------------*->mute>--> Gain >-->   |  |    |        |
+  L    | | |   +----+  +------+  |   |  |  *->0       |
+       | | |                     |   |  |    +---^----+
+ Aux2  | | |   +----+  +------+  |   |  |        |
+ ----------*--->mute>--> Gain >--> M |  |     r8b0-2
+  L    | |     +----+  +------+  |   |  |
+       | |                       |   |  \------\
+ Aux1  | |     +----+  +------+  |   |         |
+ --------*----->mute>--> Gain >--> I |         |
+  L    |       +----+  +------+  |   |         |
+       |                         |   |         |
+       |       +----+  +------+  |   |  +---+  |
+       *------->mute>--> Gain >--> X >-->AMP>--*
+       |       +----+  +------+  |   |  +-^-+  |
+       |                         |   |    |    |
+       |       +----+  +------+  |   |  r2b1-3 |  
+       | /----->mute>--> Gain >--> E |         |
+       | |     +----+  +------+  |   |         |
+       | |                       |   |         |
+       | |     +----+  +------+  |   |         |
+       | | /--->mute>--> Gain >--> R |         |
+       | | |   +----+  +------+  |   |         |
+       | | |                     |   |         |   r9b8-9
+       | | |   +----+  +------+  |   |         |     |
+       | | | /->mute>--> Gain >-->   |         | +---v---+
+       | | | | +----+  +------+  +---+       /-*->0      |
+ DAC   | | | |                               |   |       |
+ ------------*----------------------------------->?      |  +----+
+  L    | | |                                 |   |  Mux  >-->mute>--> L output
+       | | |                                 | /->?      |  +--^-+
+       | | |                                 | | |       |     |
+       | | |                           /--------->?      |   r0b0
+       | | |                           |     | | +-------+
+       | | |                           |     | |
+ Mono  | | |                           |     | | +-------+
+ ----------*                           |     \--->       |  +----+
+       | | |                           |       | |  Mix  >-->mute>--> Mono output
+       | | |                           |       *->       |  +--^-+
+       | | |                           |       | +-------+     |
+       | | |                           |       |             r1b0
+ DAC   | | |                           |       | +-------+
+ ------------*-------------------------*--------->1      |  +----+
+  R    | | | |                                 | |  Mux  >-->mute>--> R output
+       | | | | +----+  +------+  +---+         *->0      |  +--^-+
+       | | | \->mute>--> Gain >-->   |         | +---^---+     |
+       | | |   +----+  +------+  |   |         |     |       r5b0
+       | | |                     |   |         |   r6b0
+       | | |   +----+  +------+  |   |         |
+       | | \--->mute>--> Gain >--> M |         |
+       | |     +----+  +------+  |   |         |
+       | |                       |   |         |
+       | |     +----+  +------+  |   |         |
+       | *----->mute>--> Gain >--> I |         |
+       | |     +----+  +------+  |   |         |
+       | |                       |   |         |
+       | |     +----+  +------+  |   |  +---+  |
+       \------->mute>--> Gain >--> X >-->AMP>--*
+         |     +----+  +------+  |   |  +-^-+  |
+      /--/                       |   |    |    |
+ Aux1 |        +----+  +------+  |   |  r6b1-3 |
+ -------*------>mute>--> Gain >--> E |         |
+  R   | |      +----+  +------+  |   |         |
+      | |                        |   |         |
+ Aux2 | |      +----+  +------+  |   |  /------/
+ ---------*---->mute>--> Gain >--> R |  |
+  R   | | |    +----+  +------+  |   |  |
+      | | |                      |   |  |    +--------+
+ Line | | |    +----+  +------+  |   |  |  *->0       |
+ -----------*-->mute>--> Gain >-->   |  |    |        |
+  R   | | | |  +----+  +------+  +---+  \---->1       |
+      | | | |                                |        |
+      | | | \-------------------------------->2       |  +---+
+      | | |                                  |  Mux   >-->AMP>--> ADC R
+      | | \---------------------------------->3       |  +-^-+
+      | |                                    |        |    |
+      | \------------------------------------>4       |  r7b3-0
+      |                                      |        |
+      \-----*-------------------------------->5       |
+            |                                +---^----+
+    r6b4-5  |                                    |
+      |     |                                  r8b3-5
+   +--v---+ |
+ -->PreAmp>-/
+   +------+
+ MIC R (electret mic)
diff -u --recursive --new-file v2.4.9/linux/Documentation/sound/btaudio linux/Documentation/sound/btaudio
--- v2.4.9/linux/Documentation/sound/btaudio	Sun Aug 12 13:27:58 2001
+++ linux/Documentation/sound/btaudio	Tue Sep 18 14:25:27 2001
@@ -31,23 +31,28 @@
 should'nt crash your box.  It might not work as expected, have bugs,
 not being fully OSS API compilant, ...
 
+Latest versions are available from http://bytesex.org/bttv/, the
+driver is in the bttv tarball.  Kernel patches might be available too,
+have a look at http://bytesex.org/bttv/listing.html.
+
+The chip knows two different modes.  btaudio registers two dsp
+devices, one for each mode.  They can not be used at the same time.
+
 
 Digital audio mode
 ==================
 
-The chip knows different modes.  Right now you have to pick the one you
-want to use at insmod time.  Digital audio mode is the default.  The
-chip gives you 16 bit stereo sound with ~32 kHz sample rate.  According
-to the specs it should be possible to get up to 48 kHz, but I havn't
-figured out yet how this works.  The specs are not very verbose :-(
-
-Lower sample rates are possible too, but the code isn't written yet.
-For now you are limited to the fixed 32 kHz.  Mono works throuth, the
-driver will do that in software for you.
-
-With my Hauppauge I get clear sound, but I got also reports saying that
-digital audio mode does'nt work.  Guess Hauppauge connected the msp34xx
-output to the bt878's I2S digital audio input port.
+The chip gives you 16 bit stereo sound.  The sample rate depends on
+the external source which feeds the bt878 with digital sound via I2S
+interface.  There is a insmod option (rate) to tell the driver which
+sample rate the hardware uses (32000 is the default).
+
+One possible source for digital sound is the msp34xx audio processor
+chip which provides digital sound via I2S with 32 kHz sample rate.  My
+Hauppauge board works this way.
+
+The Osprey-200 reportly gives you digital sound with 44100 Hz sample
+rate.  It is also possible that you get no sound at all.
 
 
 analog mode (A/D)
@@ -67,11 +72,17 @@
 by the mixer device).  Others get a useable signal on line1.
 
 
-more hints
-==========
+some examples
+=============
+
+* read audio data from btaudio (dsp2), send to es1730 (dsp,dsp1):
+  $ sox -w -r 32000 -t ossdsp /dev/dsp2 -t ossdsp /dev/dsp
+
+* read audio data from btaudio, send to esound daemon (which might be
+  running on another host):
+  $ sox -c 2 -w -r 32000 -t ossdsp /dev/dsp2 -t sw - | esdcat -r 32000
+  $ sox -c 1 -w -r 32000 -t ossdsp /dev/dsp2 -t sw - | esdcat -m -r 32000
 
-/me uses "sox -w -r 32000 -t ossdsp /dev/dsp2 -t ossdsp /dev/dsp"
-to dump audio data from btaudio (dsp2) to es1730 (dsp,dsp1).
 
 Have fun,
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/sysctl/vm.txt linux/Documentation/sysctl/vm.txt
--- v2.4.9/linux/Documentation/sysctl/vm.txt	Wed Mar 14 14:39:07 2001
+++ linux/Documentation/sysctl/vm.txt	Mon Sep 10 14:36:25 2001
@@ -33,32 +33,29 @@
 This file controls the operation of the bdflush kernel
 daemon. The source code to this struct can be found in
 linux/fs/buffer.c. It currently contains 9 integer values,
-of which 6 are actually used by the kernel.
+of which 4 are actually used by the kernel.
 
 From linux/fs/buffer.c:
 --------------------------------------------------------------
-union bdflush_param{
-    struct {
-        int nfract;      /* Percentage of buffer cache dirty to
-                            activate bdflush */
-        int ndirty;      /* Maximum number of dirty blocks to
-                            write out per wake-cycle */
-        int nrefill;     /* Number of clean buffers to try to
-                            obtain each time we call refill */
-        int nref_dirt;   /* Dirty buffer threshold for activating
-                            bdflush when trying to refill buffers. */
-        int dummy1;      /* unused */
-        int age_buffer;  /* Time for normal buffer to age before
-                            we flush it */
-        int age_super;   /* Time for superblock to age before we
-                            flush it */
-        int dummy2;      /* unused */
-        int dummy3;      /* unused */
-    } b_un;
-    unsigned int data[N_PARAM];
-} bdf_prm = {{40, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}};
+union bdflush_param {
+	struct {
+		int nfract;	/* Percentage of buffer cache dirty to 
+				   activate bdflush */
+		int dummy1;	/* old "ndirty" */
+		int dummy2;	/* old "nrefill" */
+		int dummy3;	/* unused */
+		int interval;	/* jiffies delay between kupdate flushes */
+		int age_buffer;	/* Time for normal buffer to age */
+		int nfract_sync;/* Percentage of buffer cache dirty to 
+				   activate bdflush synchronously */
+		int dummy4;	/* unused */
+		int dummy5;	/* unused */
+	} b_un;
+	unsigned int data[N_PARAM];
+} bdf_prm = {{30, 64, 64, 256, 5*HZ, 30*HZ, 60, 0, 0}};
 --------------------------------------------------------------
 
+int nfract:
 The first parameter governs the maximum number of dirty
 buffers in the buffer cache. Dirty means that the contents
 of the buffer still have to be written to disk (as opposed
@@ -66,32 +63,31 @@
 Setting this to a high value means that Linux can delay disk
 writes for a long time, but it also means that it will have
 to do a lot of I/O at once when memory becomes short. A low
-value will spread out disk I/O more evenly.
-
-The second parameter (ndirty) gives the maximum number of
-dirty buffers that bdflush can write to the disk in one time.
-A high value will mean delayed, bursty I/O, while a small
-value can lead to memory shortage when bdflush isn't woken
-up often enough...
-
-The third parameter (nrefill) is the number of buffers that
-bdflush will add to the list of free buffers when
-refill_freelist() is called. It is necessary to allocate free
-buffers beforehand, since the buffers often are of a different
-size than memory pages and some bookkeeping needs to be done
-beforehand. The higher the number, the more memory will be
-wasted and the less often refill_freelist() will need to run.
-
-When refill_freelist() comes across more than nref_dirt dirty
-buffers, it will wake up bdflush.
-
-Finally, the age_buffer and age_super parameters govern the
-maximum time Linux waits before writing out a dirty buffer
-to disk. The value is expressed in jiffies (clockticks), the
-number of jiffies per second is 100, except on Alpha machines
-(1024). Age_buffer is the maximum age for data blocks, while
-age_super is for filesystem metadata.
-
+value will spread out disk I/O more evenly, at the cost of
+more frequent I/O operations.  The default value is 30%,
+the minimum is 0%, and the maximum is 100%.
+
+int interval:
+The fifth parameter, interval, is the minimum rate at
+which kupdate will wake and flush.  The value is expressed in
+jiffies (clockticks), the number of jiffies per second is
+normally 100 (Alpha is 1024). Thus, x*HZ is x seconds.  The
+default value is 5 seconds, the minimum is 0 seconds, and the
+maximum is 600 seconds.
+
+int age_buffer:
+The sixth parameter, age_buffer, governs the maximum time
+Linux waits before writing out a dirty buffer to disk.  The
+value is in jiffies.  The default value is 30 seconds,
+the minimum is 1 second, and the maximum 6,000 seconds.
+
+int nfract_sync:
+The seventh parameter, nfract_sync, governs the percentage
+of buffer cache that is dirty before bdflush activates
+synchronously.  This can be viewed as the hard limit before
+bdflush forces buffers to disk.  The default is 60%, the
+minimum is 0%, and the maximum is 100%.
+ 
 ==============================================================
 buffermem:
 
diff -u --recursive --new-file v2.4.9/linux/Documentation/sysrq.txt linux/Documentation/sysrq.txt
--- v2.4.9/linux/Documentation/sysrq.txt	Thu May 24 15:03:06 2001
+++ linux/Documentation/sysrq.txt	Mon Sep 17 22:52:35 2001
@@ -1,26 +1,27 @@
+Linux Magic System Request Key Hacks
+Documentation for sysrq.c version 1.15
+Last update: $Date: 2001/01/28 10:15:59 $
 
-                      MAGIC SYSRQ KEY DOCUMENTATION v1.32
-                     ------------------------------------
-                        [Sat Apr  8 22:15:03 CEST 2000]
-
-*  What is the magic SysRQ key?
+*  What is the magic SysRq key?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-It is a 'magical' key combo you can hit which kernel will respond to
+It is a 'magical' key combo you can hit which the kernel will respond to
 regardless of whatever else it is doing, unless it is completely locked up.
 
-*  How do I enable the magic SysRQ key?
+*  How do I enable the magic SysRq key?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
-configuring the kernel. This option is only available in 2.1.x or later
-kernels. Once you boot the new kernel, you need to enable it manually 
-using following command:
+configuring the kernel. When running on a kernel with SysRq compiled in, it
+may be DISABLED at run-time using following command:
+
+        echo "0" > /proc/sys/kernel/sysrq
 
-	 echo "1" > /proc/sys/kernel/sysrq
+Note that previous versions disabled sysrq by default, and you were required
+to specifically enable it at run-time. That is not the case any longer.
 
-*  How do I use the magic SysRQ key?
+*  How do I use the magic SysRq key?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-On x86   - You press the key combo 'ALT-SysRQ-<command key>'. Note - Some
-           (older?) may not have a key labeled 'SysRQ'. The 'SysRQ' key is
+On x86   - You press the key combo 'ALT-SysRq-<command key>'. Note - Some
+           keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is
            also known as the 'Print Screen' key.
 
 On SPARC - You press 'ALT-STOP-<command key>', I believe.
@@ -33,14 +34,14 @@
              Print Screen (or F13) - <command key> may suffice.
 
 On other - If you know of the key combos for other architectures, please
-           let me know so I can add them to this section. 
+           let me know so I can add them to this section.
 
 *  What are the 'command' keys?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 'r'     - Turns off keyboard raw mode and sets it to XLATE.
 
-'k'     - Secure Access Key (SAK) Kills all programs on the current virtual 
-	  console. NOTE: See important comments below in SAK section.
+'k'     - Secure Access Key (SAK) Kills all programs on the current virtual
+          console. NOTE: See important comments below in SAK section.
 
 'b'     - Will immediately reboot the system without syncing or unmounting
           your disks.
@@ -70,8 +71,8 @@
 'l'     - Send a SIGKILL to all processes, INCLUDING init. (Your system
           will be non-functional after this.)
 
-'h'	- Will display help ( actually any other key than those listed
-	  above will display help. but 'h' is easy to remember :-)
+'h'     - Will display help ( actually any other key than those listed
+          above will display help. but 'h' is easy to remember :-)
 
 *  Okay, so what can I use them for?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -83,8 +84,8 @@
 and thus letting you make sure that the login prompt you see is actually
 the one from init, not some trojan program.
 IMPORTANT:In its true form it is not a true SAK like the one in   :IMPORTANT
-IMPORTATN:c2 compliant systems, and it should be mistook as such. :IMPORTANT
-	It seems other find it useful as (System Attention Key) which is
+IMPORTANT:c2 compliant systems, and it should be mistook as such. :IMPORTANT
+       It seems other find it useful as (System Attention Key) which is
 useful when you want to exit a program that will not let you switch consoles.
 (For example, X or a svgalib program.)
 
@@ -93,7 +94,7 @@
 
 'S'ync is great when your system is locked up, it allows you to sync your
 disks and will certainly lessen the chance of data loss and fscking. Note
-that the sync hasn't taken place until you see the "OK" and "Done" appear 
+that the sync hasn't taken place until you see the "OK" and "Done" appear
 on the screen. (If the kernel is really in strife, you may not ever get the
 OK or Done message...)
 
@@ -111,30 +112,72 @@
 are unable to kill any other way, especially if it's spawning other
 processes.
 
-*  Sometimes SysRQ seems to get 'stuck' after using it, what can I do?
+*  Sometimes SysRq seems to get 'stuck' after using it, what can I do?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 That happens to me, also. I've found that tapping shift, alt, and control
 on both sides of the keyboard, and hitting an invalid sysrq sequence again
 will fix the problem. (ie, something like alt-sysrq-z). Switching to another
 virtual console (ALT+Fn) and then back again should also help.
 
-*  I hit SysRQ, but nothing seems to happen, what's wrong?
+*  I hit SysRq, but nothing seems to happen, what's wrong?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There are some keyboards that send different scancodes for SysRQ than the
-pre-defined 0x54. So if SysRQ doesn't work out of the box for a certain 
-keyboard, run 'showkey -s' to find out the proper scancode sequence. Then 
-use 'setkeycodes <sequence> 84' to define this sequence to the usual SysRQ 
+There are some keyboards that send different scancodes for SysRq than the
+pre-defined 0x54. So if SysRq doesn't work out of the box for a certain
+keyboard, run 'showkey -s' to find out the proper scancode sequence. Then
+use 'setkeycodes <sequence> 84' to define this sequence to the usual SysRq
 code (84 is decimal for 0x54). It's probably best to put this command in a
-boot script. Oh, and by the way, you exit 'showkey' by not typing anything 
+boot script. Oh, and by the way, you exit 'showkey' by not typing anything
 for ten seconds.
 
+*  I want to add SysRQ key events to a module, how does it work?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In order to register a basic function with the table, you must first include
+the header 'include/linux/sysrq.h', this will define everything else you need.
+Next, you must create a sysrq_key_op struct, and populate it with A) the key
+handler function you will use, B) a help_msg string, that will print when SysRQ
+prints help, and C) an action_msg string, that will print right before your
+handler is called. Your handler must conform to the protoype in 'sysrq.h'.
+
+After the sysrq_key_op is created, you can call the macro 
+register_sysrq_key(int key, struct sysrq_key_op *op_p) that is defined in
+sysrq.h, this will register the operation pointed to by 'op_p' at table
+key 'key', if that slot in the table is blank. At module unload time, you must
+call the macro unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
+will remove the key op pointed to by 'op_p' from the key 'key', if and only if
+it is currently registered in that slot. This is in case the slot has been
+overwritten since you registered it.
+
+The Magic SysRQ system works by registering key operations against a key op
+lookup table, which is defined in 'drivers/char/sysrq.c'. This key table has
+a number of operations registered into it at compile time, but is mutable,
+and 4 functions are exported for interface to it: __sysrq_lock_table,
+__sysrq_unlock_table, __sysrq_get_key_op, and __sysrq_put_key_op. The
+functions __sysrq_swap_key_ops and __sysrq_swap_key_ops_nolock are defined
+in the header itself, and the REGISTER and UNREGISTER macros are built fromi
+these. More complex (and dangerous!) manipulations of the table are possible
+using these functions, but you must be careful to always lock the table before
+you read or write from it, and to unlock it again when you are done. (And of
+course, to never ever leave an invalid pointer in the table). Null pointers in
+the table are always safe :)
+
+If for some reason you feel the need to call the handle_sysrq function from
+within a function called by handle_sysrq, you must be aware that you are in
+a lock (you are also in an interupt handler, which means don't sleep!), so
+you must call __handle_sysrq_nolock instead.
+
 *  I have more questions, who can I ask?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 You may feel free to send email to myrdraal@deathsdoor.com, and I will
-respond as soon as possible. 
+respond as soon as possible.
  -Myrdraal
 
+And I'll answer any questions about the registration system you got, also
+responding as soon as possible.
+ -Crutcher
+
 *  Credits
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Written by Mydraal <myrdraal@deathsdoor.com>
 Updated by Adam Sulmicki <adam@cfar.umd.edu>
+Updated by Jeremy M. Dolan <jmd@turbogeek.org> 2001/01/28 10:15:59
+Added to by Crutcher Dunnavant <crutcher+kernel@datastacks.com>
diff -u --recursive --new-file v2.4.9/linux/Documentation/usb/hiddev.txt linux/Documentation/usb/hiddev.txt
--- v2.4.9/linux/Documentation/usb/hiddev.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/usb/hiddev.txt	Wed Sep 12 15:34:06 2001
@@ -0,0 +1,162 @@
+Care and feeding of your Human Interface Devices
+
+INTRODUCTION
+
+In addition to the normal input type HID devices, USB also uses the
+human interface device protocols for things that are not really human
+interfaces, but have similar sorts of communication needs. The two big
+examples for this are power devices (especially uninterruptable power
+supplies) and monitor control on higher end monitors.
+
+To support these disparite requirements, the Linux USB system provides
+HID events to two seperate interfaces:
+* the input subsystem, which converts HID events into normal input
+device interfaces (such as keyboard, mouse and joystick) and a
+normalised event interface - see Documentation/input/input.txt
+* the hiddev interface, which provides fairly raw HID events
+
+The data flow for a HID event produced by a device is something like
+the following :
+
+ usb.c ---> hid.c  ----> input.c ----> [keyboard/mouse/joystick/event]
+                    |
+                    |
+                    --> hiddev.c ----> POWER / MONITOR CONTROL 
+
+In addition, other subsystems (apart from USB) can potentially feed
+events into the input subsystem, but these have no effect on the hid
+device interface.
+
+USING THE HID DEVICE INTERFACE
+
+The hiddev interface is a char interface using the normal USB major,
+with the minor numbers starting at 96 and finishing at 111. Therefore,
+you need the following commands:
+mknod /dev/usb/hiddev0 c 180 96
+mknod /dev/usb/hiddev1 c 180 97
+mknod /dev/usb/hiddev2 c 180 98
+mknod /dev/usb/hiddev3 c 180 99
+mknod /dev/usb/hiddev4 c 180 100
+mknod /dev/usb/hiddev5 c 180 101
+mknod /dev/usb/hiddev6 c 180 102
+mknod /dev/usb/hiddev7 c 180 103
+mknod /dev/usb/hiddev8 c 180 104
+mknod /dev/usb/hiddev9 c 180 105
+mknod /dev/usb/hiddev10 c 180 106
+mknod /dev/usb/hiddev11 c 180 107
+mknod /dev/usb/hiddev12 c 180 108
+mknod /dev/usb/hiddev13 c 180 109
+mknod /dev/usb/hiddev14 c 180 110
+mknod /dev/usb/hiddev15 c 180 111
+
+So you point your hiddev compliant user-space program at the correct
+interface for your device, and it all just works.
+
+Assuming that you have a hiddev compliant user-space program, of
+course. If you need to write one, read on.
+
+
+THE HIDDEV API
+This description should be read in conjunction with the HID
+specification, freely available from http://www.usb.org, and
+conveniently linked of http://www.linux-usb.org.
+
+The hiddev API uses a read() interface, and a set of ioctl() calls.
+
+
+read():
+This is the event interface. When the HID device performs an
+interrupt transfer, indicating a change of state, data will be made
+available at the associated hiddev device with the content of a struct
+hiddev_event: 
+
+       struct hiddev_event {
+           unsigned hid;
+           signed int value;
+       };
+
+containing the HID usage identifier for the status that changed, and
+the value that it was changed to. Note that the structure is defined
+within <linux/hiddev.h>, along with some other useful #defines and
+structures. 
+
+
+ioctl(): 
+This is the control interface. There are a number of controls: 
+
+HIDIOCGVERSION - int (read)
+Gets the version code out of the hiddev driver.
+
+HIDIOCAPPLICATION - (none)
+This ioctl call returns the HID application usage associated with the
+hid device. The third argument to ioctl() specifies which application
+index to get. This is useful when the device has more than one
+application collection. If the index is invalid (greater or equal to
+the number of application collections this device has) the ioctl
+returns -1. You can find out beforehand how many application
+collections the device has from the num_applications field from the
+hiddev_devinfo structure. 
+
+HIDIOCGDEVINFO - struct hiddev_devinfo (read)
+Gets a hiddev_devinfo structure which describes the device.
+
+HIDIOCGSTRING - struct struct hiddev_string_descriptor (read/write)
+Gets a string descriptor from the device. The caller must fill in the
+"index" field to indicate which descriptor should be returned.
+
+HIDIOCINITREPORT - (none)
+Instructs the kernel to retrieve all input and feature report values
+from the device. At this point, all the usage structures will contain
+current values for the device, and will maintain it as the device
+changes.
+
+HIDIOCGNAME - string (variable length)
+Gets the device name
+
+HIDIOCGREPORT - struct hiddev_report_info (write)
+Instructs the kernel to get a feature or input report from the device,
+in order to selectively update the usage structures (in contrast to
+INITREPORT). 
+
+HIDIOCSREPORT - struct hiddev_report_info (write)
+Instructs the kernel to send a report to the device. This report can
+be filled in by the user through HIDIOCSUSAGE calls (below) to fill in
+individual usage values in the report beforesending the report in full
+to the device. 
+
+HIDIOCGREPORTINFO - struct hiddev_report_info (read/write)
+Fills in a hiddev_report_info structure for the user. The report is
+looked up by type (input, output or feature) and id, so these fields
+must be filled in by the user. The ID can be absolute -- the actual
+report id as reported by the device -- or relative --
+HID_REPORT_ID_FIRST for the first report, and (HID_REPORT_ID_NEXT |
+report_id) for the next report after report_id. Without a-priori
+information about report ids, the right way to use this ioctl is to
+use the relative IDs above to enumerate the valid IDs. The ioctl
+returns non-zero when there is no more next ID. The real report ID is
+filled into the returned hiddev_report_info structure. 
+
+HIDIOCGFIELDINFO - struct hiddev_field_info (read/write)
+Returns the field information associated with a report in a
+hiddev_field_info structure. The user must fill in report_id and
+report_type in this structure, as above. The field_index should also
+be filled in, which should be a number from 0 and maxfield-1, as
+returned from a previous HIDIOCGREPORTINFO call. 
+
+HIDIOCGUCODE - struct hiddev_usage_ref (read/write)
+Returns the usage_code in a hiddev_usage_ref structure, given that
+given its report type, report id, field index, and index within the
+field have already been filled into the structure.
+
+HIDIOCGUSAGE - struct hiddev_usage_ref (read/write)
+Returns the value of a usage in a hiddev_usage_ref structure. The
+usage to be retrieved can be specified as above, or the user can
+choose to fill in the report_type field and specify the report_id as
+HID_REPORT_ID_UNKNOWN. In this case, the hiddev_usage_ref will be
+filled in with the report and field infomation associated with this
+usage if it is found. 
+
+HIDIOCSUSAGE - struct hiddev_usage_ref (write)
+Sets the value of a usage in an output report.
+
+
diff -u --recursive --new-file v2.4.9/linux/Documentation/usb/input.txt linux/Documentation/usb/input.txt
--- v2.4.9/linux/Documentation/usb/input.txt	Fri Jul 28 12:50:52 2000
+++ linux/Documentation/usb/input.txt	Wed Dec 31 16:00:00 1969
@@ -1,306 +0,0 @@
-			  Linux Input drivers v1.0
-	       (c) 1999-2000 Vojtech Pavlik <vojtech@suse.cz>
-			     Sponsored by SuSE
-	    $Id: input.txt,v 1.4 2000/05/28 17:57:22 vojtech Exp $
-----------------------------------------------------------------------------
-
-0. Disclaimer
-~~~~~~~~~~~~~
-  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
-
-  Should you need to contact me, the author, you can do so either by e-mail
-- mail your message to <vojtech@suse.cz>, or by paper mail: Vojtech Pavlik,
-Ucitelska 1576, Prague 8, 182 00 Czech Republic
-
-  For your convenience, the GNU General Public License version 2 is included
-in the package: See the file COPYING.
-
-1. Introduction
-~~~~~~~~~~~~~~~
-  This is a collection of drivers that is designed to support all input
-devices under Linux. However, in the current kernels, although it's
-possibilities are much bigger, it's limited to USB devices only. This is
-also why it resides in the drivers/usb subdirectory.
-
-  The center of the input drivers is the input.o module, which must be
-loaded before any other of the input modules - it serves as a way of
-communication between two groups of modules:
-
-1.1 Device drivers
-~~~~~~~~~~~~~~~~~~
-  These modules talk to the hardware (for example via USB), and provide
-events (keystrokes, mouse movements) to the input.o module.
-
-1.2 Event handlers
-~~~~~~~~~~~~~~~~~~
-  These modules get events from input.o and pass them where needed via
-various interfaces - keystrokes to the kernel, mouse movements via a
-simulated PS/2 interface to GPM and X and so on.
-
-2. Simple Usage
-~~~~~~~~~~~~~~~
-  For the most usual configuration, with one USB mouse and one USB keyboard,
-you'll have to load the following modules (or have them built in to the
-kernel):
-
-	input.o
-	mousedev.o
-	keybdev.o
-	usbcore.o
-	usb-[uo]hci.o
-	hid.o
-
-  After this, the USB keyboard will work straight away, and the USB mouse
-will be available as a character device on major 13, minor 63:
-
-	crw-r--r--   1 root     root      13,  63 Mar 28 22:45 mice
-
-  This device, has to be created, unless you use devfs, in which case it's
-created automatically. The commands to do that are:
-
-	cd /dev
-	mkdir input
-	mknod input/mice c 13 63
-
-  After that you have to point GPM (the textmode mouse cut&paste tool) and
-XFree to this device to use it - GPM should be called like:
-
-	gpm -t ps2 -m /dev/input/mice
-
-  And in X:
-
-	Section "Pointer"
-	    Protocol    "ImPS/2"
-	    Device      "/dev/input/mice"
-	    ZAxisMapping 4 5
-	EndSection
-
-  When you do all of the above, you can use your USB mouse and keyboard.
-
-3. Detailed Description
-~~~~~~~~~~~~~~~~~~~~~~~
-3.1 Device drivers
-~~~~~~~~~~~~~~~~~~
-  Device drivers are the modules that generate events. The events are
-however not useful without being handled, so you also will need to use some
-of the modules from section 3.2.
-
-3.1.1 hid.c
-~~~~~~~~~~~
-  Hid.c is the largest and most complex driver of the whole suite. It
-handles all HID devices, and because there is a very wide variety of them,
-and because the USB HID specification isn't simple, it needs to be this big.
-
-  Currently, it handles USB mice, joysticks, gamepads, steering wheels
-keyboards, trackballs and digitizers.
-
- However, USB uses HID also for monitor controls, speaker controls, UPSs,
-LCDs and many other purposes.
-
- The monitor and speaker controls should be easy to add to the hid/input
-interface, but for the UPSs and LCDs it doesn't make much sense. The driver
-doesn't support these yet, and a new, non-event interface should be designed
-for them. If you have any of these devices (I don't), feel free to design
-something and if it's good, it'll get into the driver.
-
-  The usage of the hid.o module is very simple, it takes no parameters,
-detects everything automatically and when a HID device is inserted, it
-detects it appropriately.
-
-  However, because the devices vary wildly, you might happen to have a
-device that doesn't work well. In that case #define DEBUG at the beginning
-of hid.c and send me the syslog traces.
-
-3.1.2 usbmouse.c
-~~~~~~~~~~~~~~~~
-  For embedded systems, for mice with broken HID descriptors and just any
-other use when the big hid.c wouldn't be a good choice, there is the
-usbmouse.c driver. It handles USB mice only. It uses a simpler HIDBP
-protocol. This also means the mice must support this simpler protocol. Not
-all do. If you don't have any strong reason to use this module, use hid.c
-instead.
-
-3.1.3 usbkbd.c
-~~~~~~~~~~~~~~
-  Much like usbmouse.c, this module talks to keyboards with a simplified
-HIDBP protocol. It's smaller, but doesn't support any extra special keys.
-Use hid.c instead if there isn't any special reason to use this.
-
-3.1.4 wacom.c
-~~~~~~~~~~~~~
-  This is a driver for Wacom Graphire and Intuos tablets. Not for Wacom
-PenPartner, that one is handled by the HID driver. Although the Intuos and
-Graphire tablets claim that they are HID tablets as well, they are not and
-thus need this specific driver.
-
-3.1.5 wmforce.c
-~~~~~~~~~~~~~~~
-  A driver for the Logitech WingMan Force joysticks, when connected via the
-USB port. It works quite well, but there is no force feedback support yet,
-because the interface to do that is a trade secret of Immersion Corp, and
-even Logitech can't disclose it.
-
-  Support for Logitech WingMan Force Wheel isn't present in this driver, but
-if someone has the device, and is willing to cooperate, it should be a
-matter of a couple days to add it.
-
-3.2 Event handlers
-~~~~~~~~~~~~~~~~~~
-  Event handlers distribute the events from the devices to userland and
-kernel, as needed.
-
-3.2.1 keybdev.c
-~~~~~~~~~~~~~~~
-  Keybdev is currently a rather ugly hack that translates the input events
-into architecture-specific keyboard raw mode (Xlated AT Set2 on x86), and
-passes them into the handle_scancode function of the keyboard.c module. This
-works well enough on all architectures that keybdev can generate rawmode on,
-other architectures can be added to it.
-
-  The right way would be to pass the events to keyboard.c directly, best if
-keyboard.c would itself be an event handler. This is done in the input
-patch, available on the webpage mentioned below.
-
-3.2.2 mousedev.c
-~~~~~~~~~~~~~~~~
-  Mousedev is also a hack to make programs that use mouse input work. It
-takes events from either mice or digitizers/tablets and makes a PS/2-style
-(a la /dev/psaux) mouse device available to the userland. Ideally, the
-programs could use a more reasonable interface, for example evdev.c
-
-  Mousedev devices in /dev/input (as shown above) are:
-
-	crw-r--r--   1 root     root      13,  32 Mar 28 22:45 mouse0
-	crw-r--r--   1 root     root      13,  33 Mar 29 00:41 mouse1
-	crw-r--r--   1 root     root      13,  34 Mar 29 00:41 mouse2
-	crw-r--r--   1 root     root      13,  35 Apr  1 10:50 mouse3
-	...
-	...
-	crw-r--r--   1 root     root      13,  62 Apr  1 10:50 mouse30
-	crw-r--r--   1 root     root      13,  63 Apr  1 10:50 mice
-
-Each 'mouse' device is assigned to a single mouse or digitizer, except the last
-one - 'mice'. This single character device is shared by all mice and
-digitizers, and even if none are connected, the device is present.  This is
-useful for hotplugging USB mice, so that programs can open the device even when
-no mice are present.
-
-  CONFIG_INPUT_MOUSEDEV_SCREEN_[XY] in the kernel configuration are the size
-of your screen (in pixels) in XFree86. This is needed if you want to use
-your digitizer in X, because it's movement is sent to X via a virtual PS/2
-mouse and thus needs to be scaled accordingly. These values won't be used if
-you use a mouse only.
-
-  Mousedev will generate either PS/2, ImPS/2 (Microsoft IntelliMouse) or
-GenPS/2 (Genius NetMouse/NetScroll) protocols, depending on what the program
-reading the data wishes. You can set GPM and X to any of these. You'll need
-ImPS/2 if you want to make use of a wheel on a USB mouse and GenPS/2 if you
-want to use extra (up to 5) buttons. I'm not sure how much is GenPS/2 supported
-in X, though.
-
-3.2.3 joydev.c
-~~~~~~~~~~~~~~
-  Joydev implements v0.x and v1.x Linux joystick api, much like
-drivers/char/joystick/joystick.c. See joystick-api.txt in the Documentation
-subdirectory for details. Joydev does it on top of the input subsystem,
-though. As soon as any USB joystick is connected, it can be accessed in
-/dev/input on:
-
-	crw-r--r--   1 root     root      13,   0 Apr  1 10:50 js0
-	crw-r--r--   1 root     root      13,   1 Apr  1 10:50 js1
-	crw-r--r--   1 root     root      13,   2 Apr  1 10:50 js2
-	crw-r--r--   1 root     root      13,   3 Apr  1 10:50 js3
-	...
-
-And so on up to js31.
-
-3.2.4 evdev.c
-~~~~~~~~~~~~~
-  Evdev is the generic input event interface. It passes the events generated
-in the kernel straight to the program, with timestamps. The API is still
-evolving, but should be usable now. It's described in section 5.
-
-  This should be the way for GPM and X to get keyboard and mouse mouse
-events. It allows for multihead in X without any specific multihead kernel
-support. The event codes are the same on all architectures and are hardware
-independent.
-
-  The devices are in /dev/input:
-
-	crw-r--r--   1 root     root      13,  64 Apr  1 10:49 event0
-	crw-r--r--   1 root     root      13,  65 Apr  1 10:50 event1
-	crw-r--r--   1 root     root      13,  66 Apr  1 10:50 event2
-	crw-r--r--   1 root     root      13,  67 Apr  1 10:50 event3
-	...
-
-3. Contacts
-~~~~~~~~~~~
-  This effort has it's home page at:
-
-	http://www.suse.cz/development/input/
-
-You'll find both the latest HID driver and the complete Input driver there
-as well as information how to access the CVS repository for latest revisions
-of the drivers.
-
-
-  There is also a mailing list for this:
-
-	majordomo@atrey.karlin.mff.cuni.cz
-
-Send "subscribe linux-input" to subscribe to it.
-
-4. Verifying if it works
-~~~~~~~~~~~~~~~~~~~~~~~~
-  Typing a couple keys on the keyboard should be enough to check that a USB
-keyboard works and is correctly connected to the kernel keyboard driver.
-
-  Doing a cat /dev/input/mouse0 (c, 13, 32) will verify that a mouse is also
-emulated, characters should appear if you move it.
-
-  You can test the joystick emulation with the 'jstest' utility, available
-in the joystick package (see Documentation/joystick.txt).
-
-  You can test the event devics with the 'evtest' utility available on the
-input driver homepage (see the URL above).
-
-5. Event interface
-~~~~~~~~~~~~~~~~~~
-  Should you want to add event device support into any application (X, gpm,
-svgalib ...) I <vojtech@suse.cz> will be happy to provide you any help I
-can. Here goes a description of the current state of things, which is going
-to be extended, but not changed incompatibly as time goes:
-
-  You can use blocking and nonblocking reads, also select() on the
-/dev/input/eventX devices, and you'll always get a whole number of input
-events on a read. Their layout is:
-
-struct input_event {
-	struct timeval time;
-	unsigned short type;
-	unsigned short code;
-	unsigned int value;
-};
-
-  'time' is the timestamp, it returns the time at which the event happened.
-Type is for example EV_REL for relative movement, REL_KEY for a keypress or
-release. More types are defined in include/linux/input.h.
-
-  'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
-list is in include/linux/input.h.
-
-  'value' is the value the event carries. Either a relative change for
-EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for
-release, 1 for keypress and 2 for autorepeat.
diff -u --recursive --new-file v2.4.9/linux/Documentation/watchdog.txt linux/Documentation/watchdog.txt
--- v2.4.9/linux/Documentation/watchdog.txt	Fri Aug 11 15:57:57 2000
+++ linux/Documentation/watchdog.txt	Fri Sep  7 09:28:38 2001
@@ -11,6 +11,7 @@
 	ICS	WDT501-P (no fan tachometer)
 	ICS	WDT500-P
 	Software Only
+	SA1100 Internal Watchdog
 	Berkshire Products PC Watchdog Revision A & C (by Ken Hollis)
 
 
@@ -35,6 +36,9 @@
 The wdt card cannot be safely probed for. Instead you need to pass
 wdt=ioaddr,irq as a boot parameter - eg "wdt=0x240,11".
 
+The SA1100 watchdog module can be configured with the "sa1100_margin"
+commandline argument which specifies timeout value in seconds.
+
 The i810 TCO watchdog modules can be configured with the "i810_margin"
 commandline argument which specifies the counter initial value. The counter
 is decremented every 0.6 seconds and default to 50 (30 seconds). Values can
@@ -47,15 +51,15 @@
 
 Features
 --------
-		WDT501P		WDT500P		Software	Berkshire	i810 TCO
-Reboot Timer	   X               X                X		    X               X
-External Reboot	   X	           X                o		    o               o
-I/O Port Monitor   o		   o		    o		    X               o
-Temperature	   X		   o		    o               X               o
-Fan Speed          X		   o		    o               o               o
-Power Under	   X               o                o               o               o
-Power Over         X               o                o               o               o
-Overheat           X               o                o               o               o
+		WDT501P		WDT500P		Software	Berkshire	i810 TCO	SA1100WD
+Reboot Timer	   X               X                X		    X               X               X
+External Reboot	   X	           X                o		    o               o               X
+I/O Port Monitor   o		   o		    o		    X               o               o
+Temperature	   X		   o		    o               X               o               o
+Fan Speed          X		   o		    o               o               o               o
+Power Under	   X               o                o               o               o               o
+Power Over         X               o                o               o               o               o
+Overheat           X               o                o               o               o               o
 
 The external event interfaces on the WDT boards are not currently supported.
 Minor numbers are however allocated for it.
diff -u --recursive --new-file v2.4.9/linux/MAINTAINERS linux/MAINTAINERS
--- v2.4.9/linux/MAINTAINERS	Mon Aug 27 12:41:37 2001
+++ linux/MAINTAINERS	Fri Sep 14 14:26:36 2001
@@ -81,6 +81,12 @@
 L:	linux-net@vger.kernel.org
 S:	Maintained
 
+53C700 AND 53C700-66 SCSI DRIVER
+P:	James E.J. Bottomley
+M:	James.Bottomley@HansenPartnership.com
+L:	linux-scsi@vger.kernel.org
+S:	Maintained
+
 6PACK NETWORK DRIVER FOR AX.25
 P:	Andreas Koensgen
 M:	ajk@iehk.rwth-aachen.de
@@ -182,9 +188,9 @@
 M:	linux@treblig.org
 S:	Maintained
 
-ARM PORT
+ARM/STRONGARM110 PORT
 P:	Russell King
-M:	linux@arm.linux.org.uk
+M:	rmk@arm.linux.org.uk
 L:	linux-arm-kernel@lists.arm.linux.org.uk
 W:	http://www.arm.linux.org.uk/
 S:	Maintained
@@ -337,7 +343,7 @@
 
 CYBERPRO FB DRIVER
 P:	Russell King
-M:	linux@arm.linux.org.uk
+M:	rmk@arm.linux.org.uk
 W:	http://www.arm.linux.org.uk/
 S:	Maintained
 
@@ -689,8 +695,8 @@
 S:	Orphan
 
 IEEE 1394 OHCI DRIVER
-P:	Sebastien Rougeaux
-M:	sebastien.rougeaux@anu.edu.au
+P:	Ben Collins
+M:	bcollins@debian.org
 L:	linux1394-devel@lists.sourceforge.net
 S:	Maintained
 
@@ -774,6 +780,13 @@
 W:	http://www.developer.axis.com/software/jffs/
 S:	Maintained
 
+JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
+P:	David Woodhouse
+M:	dwmw2@infradead.org
+L:	jffs-dev@axis.com
+W:	http://sources.redhat.com/jffs2/
+S:	Maintained
+
 JOYSTICK DRIVER
 P:	Vojtech Pavlik
 M:	vojtech@suse.cz
@@ -823,6 +836,12 @@
 L:	linux-x25@vger.kernel.org
 S:	Maintained
 
+LASI 53c700 driver for PARISC
+P:	James E.J. Bottomley
+M:	James.Bottomley@HansenPartnership.com
+L:	linux-scsi@vger.kernel.org
+S:	Maintained
+
 LINUX FOR IBM pSERIES (RS/6000)
 P:	Paul Mackerras
 M:	paulus@au.ibm.com
@@ -902,9 +921,9 @@
 
 MIPS
 P:	Ralf Baechle
-M:	ralf@gnu.ai.mit.edu
-W:	http://lena.fnet.fr/
-L:	linux-mips@fnet.fr
+M:	ralf@gnu.org
+W:	http://oss.sgi.com/mips/mips-howto.html
+L:	linux-mips@oss.sgi.com
 S:	Maintained
 
 MISCELLANEOUS MCA-SUPPORT
@@ -948,6 +967,12 @@
 L:	linware@sh.cvut.cz
 S:	Maintained
 
+NCR DUAL 700 SCSI DRIVER (MICROCHANNEL)
+P:	James E.J. Bottomley
+M:	James.Bottomley@HansenPartnership.com
+L:	linux-scsi@vger.kernel.org
+S:	Maintained
+
 NETFILTER
 P:	Rusty Russell
 M:	rusty@rustcorp.com.au
@@ -1250,6 +1275,9 @@
 SOFTWARE RAID (Multiple Disks) SUPPORT
 P:	Ingo Molnar
 M:	mingo@redhat.com
+P:	Neil Brown
+M:	neilb@cse.unsw.edu.au
+L:	linux-raid@vger.kernel.org
 S:	Maintained
 
 SONIC NETWORK DRIVER
@@ -1413,15 +1441,6 @@
 W:	http://www.kernel.dk
 S:	Maintained
 
-USB SUBSYSTEM
-P:	Johannes Erdfelt
-M:	jerdfelt@valinux.com
-M:	johannes@erdfelt.com
-L:	linux-usb-users@lists.sourceforge.net
-L:	linux-usb-devel@lists.sourceforge.net
-W:	http://www.linux-usb.org
-S:	Supported
-
 USB ACM DRIVER
 P:	Vojtech Pavlik
 M:	vojtech@suse.cz
@@ -1437,6 +1456,13 @@
 S:	Maintained
 W:	http://www.kroah.com/linux-usb/
 
+USB CDC ETHERNET DRIVER
+P:	Brad Hards
+M:	bhards@bigpond.net.au
+L:	linux-usb-users@lists.sourceforge.net
+L:	linux-usb-devel@lists.sourceforge.net
+S:	Maintained
+
 USB HID/HIDBP/INPUT DRIVERS
 P:	Vojtech Pavlik
 M:	vojtech@suse.cz
@@ -1453,6 +1479,21 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
+USB KAWASAKI LSI DRIVER
+P:	Brad Hards
+M:	bhards@bigpond.net.au
+L:	linux-usb-users@lists.sourceforge.net
+L:	linux-usb-devel@lists.sourceforge.net
+S:	Maintained
+
+USB MASS STORAGE DRIVER
+P:	Matthew Dharm
+M:	mdharm-usb@one-eyed-alien.net
+L:	linux-usb-users@lists.sourceforge.net
+L:	linux-usb-devel@lists.sourceforge.net
+S:	Maintained
+W:	http://www.one-eyed-alien.net/~mdharm/linux-usb/
+
 USB OHCI DRIVER
 P:	Roman Weissgaerber
 M:	weissg@vienna.at
@@ -1482,21 +1523,21 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Supported
 
-USB SERIAL DIGI ACCELEPORT DRIVER
-P:	Peter Berger and Al Borchers
-M:	pberger@brimson.com
-M:	alborchers@steinerpoint.com
+USB SE401 DRIVER
+P:	Jeroen Vreeken
+M:	pe1rxq@amsat.org
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
+W:	http://www.chello.nl/~j.vreeken/se401/
 S:	Maintained
 
-USB SERIAL KEYSPAN DRIVER
-P:	Hugh Blemings
-M:	hugh@misc.nu
+USB SERIAL DIGI ACCELEPORT DRIVER
+P:	Peter Berger and Al Borchers
+M:	pberger@brimson.com
+M:	alborchers@steinerpoint.com
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
-W:	http://misc.nu/hugh/keyspan/
 
 USB SERIAL DRIVER
 P:	Greg Kroah-Hartman
@@ -1514,6 +1555,12 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
+USB SERIAL CYBERJACK PINPAD/E-COM DRIVER
+M:	linux-usb@sii.li
+L:	linux-usb-users@lists.sourceforge.net
+L:	linux-usb-devel@lists.sourceforge.net
+S:	Supported
+
 USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
 P:	Gary Brubaker
 M:	xavyer@ix.netcom.com
@@ -1521,19 +1568,22 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
-USB SERIAL CYBERJACK PINPAD/E-COM DRIVER
-M:  linux-usb@sii.li
-L:  linux-usb-users@lists.sourceforge.net
-L:  linux-usb-devel@lists.sourceforge.net
-S:  Supported
-
-USB MASS STORAGE DRIVER
-P:	Matthew Dharm
-M:	mdharm-usb@one-eyed-alien.net
+USB SERIAL KEYSPAN DRIVER
+P:	Hugh Blemings
+M:	hugh@misc.nu
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
-W:	http://www.one-eyed-alien.net/~mdharm/linux-usb/
+W:	http://misc.nu/hugh/keyspan/
+
+USB SUBSYSTEM
+P:	Johannes Erdfelt
+M:	jerdfelt@valinux.com
+M:	johannes@erdfelt.com
+L:	linux-usb-users@lists.sourceforge.net
+L:	linux-usb-devel@lists.sourceforge.net
+W:	http://www.linux-usb.org
+S:	Supported
 
 USB UHCI DRIVER
 P:	Georg Acher
diff -u --recursive --new-file v2.4.9/linux/Makefile linux/Makefile
--- v2.4.9/linux/Makefile	Mon Aug 27 12:41:37 2001
+++ linux/Makefile	Tue Sep 18 17:44:13 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 9
-EXTRAVERSION =
+SUBLEVEL = 10
+EXTRAVERSION =-pre13
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -146,6 +146,7 @@
 DRIVERS-$(CONFIG_ARCNET) += drivers/net/arcnet/arcnetdrv.o
 DRIVERS-$(CONFIG_ATM) += drivers/atm/atm.o
 DRIVERS-$(CONFIG_IDE) += drivers/ide/idedriver.o
+DRIVERS-$(CONFIG_FC4) += drivers/fc4/fc4.a
 DRIVERS-$(CONFIG_SCSI) += drivers/scsi/scsidrv.o
 DRIVERS-$(CONFIG_FUSION_BOOT) += drivers/message/fusion/fusion.o
 DRIVERS-$(CONFIG_IEEE1394) += drivers/ieee1394/ieee1394drv.o
@@ -197,6 +198,10 @@
 	drivers/zorro/devlist.h drivers/zorro/gen-devlist \
 	drivers/sound/bin2hex drivers/sound/hex2hex \
 	drivers/atm/fore200e_mkfirm drivers/atm/{pca,sba}*{.bin,.bin1,.bin2} \
+	drivers/scsi/aic7xxx/aicasm/aicasm_gram.c \
+	drivers/scsi/aic7xxx/aicasm/aicasm_scan.c \
+	drivers/scsi/aic7xxx/aicasm/y.tab.h \
+	drivers/scsi/aic7xxx/aicasm/aicasm \
 	net/khttpd/make_times_h \
 	net/khttpd/times.h \
 	submenu*
@@ -223,7 +228,9 @@
 	.menuconfig.log \
 	include/asm \
 	.hdepend scripts/mkdep scripts/split-include scripts/docproc \
-	$(TOPDIR)/include/linux/modversions.h
+	$(TOPDIR)/include/linux/modversions.h \
+	kernel.spec
+
 # directories removed with 'make mrproper'
 MRPROPER_DIRS = \
 	include/config \
@@ -247,7 +254,7 @@
 boot: vmlinux
 	@$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot
 
-vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
+vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
 	$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
 		--start-group \
 		$(CORE_FILES) \
@@ -292,11 +299,7 @@
 $(TOPDIR)/include/linux/compile.h: include/linux/compile.h
 
 newversion:
-	@if [ ! -f .version ]; then \
-		echo 1 > .version; \
-	else \
-		expr 0`cat .version` + 1 > .version; \
-	fi
+	. scripts/mkversion > .version
 
 include/linux/compile.h: $(CONFIGURATION) include/linux/version.h newversion
 	@echo -n \#define UTS_VERSION \"\#`cat .version` > .ver
@@ -418,7 +421,8 @@
 	$(MAKE) -C Documentation/DocBook mrproper
 
 distclean: mrproper
-	rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
+	rm -f core `find . \( -not -type d \) -and \
+		\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
 		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
 		-o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f -print` TAGS tags
 
@@ -501,3 +505,30 @@
 
 scripts/split-include: scripts/split-include.c
 	$(HOSTCC) $(HOSTCFLAGS) -o scripts/split-include scripts/split-include.c
+
+#
+# RPM target
+#
+#	If you do a make spec before packing the tarball you can rpm -ta it
+#
+spec:
+	. scripts/mkspec >kernel.spec
+
+#
+#	Build a tar ball, generate an rpm from it and pack the result
+#	There arw two bits of magic here
+#	1) The use of /. to avoid tar packing just the symlink
+#	2) Removing the .dep files as they have source paths in them that
+#	   will become invalid
+#
+rpm:	clean spec
+	find . \( -size 0 -o -name .depend -o -name .hdepend \) -type f -print | xargs rm -f
+	set -e; \
+	cd $(TOPDIR)/.. ; \
+	ln -sf $(TOPDIR) $(KERNELPATH) ; \
+	tar -cvz --exclude CVS -f $(KERNELPATH).tar.gz $(KERNELPATH)/. ; \
+	rm $(KERNELPATH) ; \
+	cd $(TOPDIR) ; \
+	. scripts/mkversion > .version ; \
+	rpm -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \
+	rm $(TOPDIR)/../$(KERNELPATH).tar.gz
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.4.9/linux/arch/alpha/kernel/alpha_ksyms.c	Mon Aug 27 12:41:37 2001
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Thu Sep 13 15:21:32 2001
@@ -77,6 +77,14 @@
 EXPORT_SYMBOL(_writeb);
 EXPORT_SYMBOL(_writew);
 EXPORT_SYMBOL(_writel);
+EXPORT_SYMBOL(___raw_readb); 
+EXPORT_SYMBOL(___raw_readw); 
+EXPORT_SYMBOL(___raw_readl); 
+EXPORT_SYMBOL(___raw_readq); 
+EXPORT_SYMBOL(___raw_writeb); 
+EXPORT_SYMBOL(___raw_writew); 
+EXPORT_SYMBOL(___raw_writel); 
+EXPORT_SYMBOL(___raw_writeq); 
 EXPORT_SYMBOL(_memcpy_fromio);
 EXPORT_SYMBOL(_memcpy_toio);
 EXPORT_SYMBOL(_memset_c_io);
@@ -200,6 +208,8 @@
 EXPORT_SYMBOL(cpu_data);
 EXPORT_SYMBOL(__cpu_number_map);
 EXPORT_SYMBOL(smp_num_cpus);
+EXPORT_SYMBOL(smp_call_function);
+EXPORT_SYMBOL(smp_call_function_on_cpu);
 EXPORT_SYMBOL(global_irq_holder);
 EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_sti);
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c
--- v2.4.9/linux/arch/alpha/kernel/core_cia.c	Tue May 22 16:29:57 2001
+++ linux/arch/alpha/kernel/core_cia.c	Thu Sep 13 15:21:32 2001
@@ -352,13 +352,15 @@
 	   so use them and read at window 3 base exactly 4 times. Reading
 	   more sometimes makes the chip crazy.  -ink */
 
-	bus_addr = cia_ioremap(CIA_BROKEN_TBIA_BASE);
+	bus_addr = cia_ioremap(CIA_BROKEN_TBIA_BASE, 32768 * 4);
 
 	cia_readl(bus_addr + 0x00000);
 	cia_readl(bus_addr + 0x08000);
 	cia_readl(bus_addr + 0x10000);
 	cia_readl(bus_addr + 0x18000);
 
+	cia_iounmap(bus_addr);
+
 	/* Restore normal PCI operation.  */
 	mb();
 	*(vip)CIA_IOC_CIA_CTRL = ctrl;
@@ -396,6 +398,7 @@
 	struct pci_iommu_arena *arena = pci_isa_hose->sg_isa;
 	int ctrl, addr0, tag0, pte0, data0;
 	int temp, use_tbia_try2 = 0;
+	unsigned long bus_addr;
 
 	/* pyxis -- tbia is broken */
 	if (pci_isa_hose->dense_io_base)
@@ -429,6 +432,9 @@
 	*(vip)CIA_IOC_TBn_PAGEm(0,3) = 0;
 	mb();
 
+	/* Get a usable bus address */
+	bus_addr = cia_ioremap(addr0, 8*PAGE_SIZE);
+
 	/* First, verify we can read back what we've written.  If
 	   this fails, we can't be sure of any of the other testing
 	   we're going to do, so bail.  */
@@ -464,7 +470,7 @@
 	mcheck_expected(0) = 1;
 	mcheck_taken(0) = 0;
 	mb();
-	temp = cia_readl(cia_ioremap(addr0));
+	temp = cia_readl(bus_addr);
 	mb();
 	mcheck_expected(0) = 0;
 	mb();
@@ -501,7 +507,7 @@
 	mcheck_expected(0) = 1;
 	mcheck_taken(0) = 0;
 	mb();
-	temp = cia_readl(cia_ioremap(addr0 + 4*PAGE_SIZE));
+	temp = cia_readl(bus_addr + 4*PAGE_SIZE);
 	mb();
 	mcheck_expected(0) = 0;
 	mb();
@@ -525,7 +531,7 @@
 	mcheck_expected(0) = 1;
 	mcheck_taken(0) = 0;
 	mb();
-	temp = cia_readl(cia_ioremap(addr0 + 5*PAGE_SIZE));
+	temp = cia_readl(bus_addr + 5*PAGE_SIZE);
 	mb();
 	mcheck_expected(0) = 0;
 	mb();
@@ -549,7 +555,7 @@
 	mcheck_expected(0) = 1;
 	mcheck_taken(0) = 0;
 	mb();
-	temp = cia_readl(cia_ioremap(addr0 + 6*PAGE_SIZE));
+	temp = cia_readl(bus_addr + 6*PAGE_SIZE);
 	mb();
 	mcheck_expected(0) = 0;
 	mb();
@@ -575,6 +581,9 @@
 	alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
 
 exit:
+	/* unmap the bus addr */
+	cia_iounmap(bus_addr);
+
 	/* Restore normal PCI operation.  */
 	mb();
 	*(vip)CIA_IOC_CIA_CTRL = ctrl;
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/core_irongate.c linux/arch/alpha/kernel/core_irongate.c
--- v2.4.9/linux/arch/alpha/kernel/core_irongate.c	Fri Mar  2 11:12:07 2001
+++ linux/arch/alpha/kernel/core_irongate.c	Thu Sep 13 15:21:32 2001
@@ -30,6 +30,8 @@
 
 #undef DEBUG_IRONGATE 		/* define to enable verbose Irongate debug */
 
+#define IRONGATE_DEFAULT_AGP_APER_SIZE	(256*1024*1024) /* 256MB */
+
 /*
  * BIOS32-style PCI interface:
  */
@@ -374,6 +376,14 @@
 	irongate_register_dump(__FUNCTION__);
 
 	/*
+	 * HACK: set AGP aperture size to 256MB.
+	 * This should really be changed during PCI probe, when the
+	 * size of the aperture the AGP card wants is known.
+	 */
+	printk("irongate_init_arch: AGPVA was 0x%x\n", IRONGATE0->agpva);
+	IRONGATE0->agpva = (IRONGATE0->agpva & ~0x0000000f) | 0x00000007;
+
+	/*
 	 * Create our single hose.
 	 */
 
@@ -396,4 +406,202 @@
 	hose->sg_isa = hose->sg_pci = NULL;
 	__direct_map_base = 0;
 	__direct_map_size = 0xffffffff;
+}
+
+/*
+ * IO map and AGP support
+ */
+#include <linux/vmalloc.h>
+#include <asm/pgalloc.h>
+
+static inline void 
+irongate_remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, 
+		     unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	if (address >= end)
+		BUG();
+	do {
+		if (!pte_none(*pte)) {
+			printk("irongate_remap_area_pte: page already exists\n");
+			BUG();
+		}
+		set_pte(pte, 
+			mk_pte_phys(phys_addr, 
+				    __pgprot(_PAGE_VALID | _PAGE_ASM | 
+					     _PAGE_KRE | _PAGE_KWE | flags)));
+		address += PAGE_SIZE;
+		phys_addr += PAGE_SIZE;
+		pte++;
+	} while (address && (address < end));
+}
+
+static inline int 
+irongate_remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, 
+		     unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	if (address >= end)
+		BUG();
+	do {
+		pte_t * pte = pte_alloc(&init_mm, pmd, address);
+		if (!pte)
+			return -ENOMEM;
+		irongate_remap_area_pte(pte, address, end - address, 
+				     address + phys_addr, flags);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address && (address < end));
+	return 0;
+}
+
+static int
+irongate_remap_area_pages(unsigned long address, unsigned long phys_addr,
+		       unsigned long size, unsigned long flags)
+{
+	pgd_t * dir;
+	unsigned long end = address + size;
+
+	phys_addr -= address;
+	dir = pgd_offset(&init_mm, address);
+	flush_cache_all();
+	if (address >= end)
+		BUG();
+	do {
+		pmd_t *pmd;
+		pmd = pmd_alloc(&init_mm, dir, address);
+		if (!pmd)
+			return -ENOMEM;
+		if (irongate_remap_area_pmd(pmd, address, end - address,
+					 phys_addr + address, flags))
+			return -ENOMEM;
+		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	} while (address && (address < end));
+	return 0;
+}
+
+#include <linux/agp_backend.h>
+#include <linux/agpgart.h>
+
+#define GET_PAGE_DIR_OFF(addr) (addr >> 22)
+#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr))
+
+#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) 
+#define GET_GATT(addr) (gatt_pages[GET_PAGE_DIR_IDX(addr)])
+
+unsigned long
+irongate_ioremap(unsigned long addr, unsigned long size)
+{
+	struct vm_struct *area;
+	unsigned long vaddr;
+	unsigned long baddr, last;
+	u32 *mmio_regs, *gatt_pages, *cur_gatt, pte;
+	unsigned long gart_bus_addr, gart_aper_size;
+
+	gart_bus_addr = (unsigned long)IRONGATE0->bar0 &
+			PCI_BASE_ADDRESS_MEM_MASK; 
+
+	if (!gart_bus_addr) /* FIXME - there must be a better way!!! */
+		return addr + IRONGATE_MEM;
+
+	gart_aper_size = IRONGATE_DEFAULT_AGP_APER_SIZE; /* FIXME */
+
+	/* 
+	 * Check for within the AGP aperture...
+	 */
+	do {
+		/*
+		 * Check the AGP area
+		 */
+		if (addr >= gart_bus_addr && addr + size - 1 < 
+		    gart_bus_addr + gart_aper_size)
+			break;
+
+		/*
+		 * Not found - assume legacy ioremap
+		 */
+		return addr + IRONGATE_MEM;
+	} while(0);
+
+	mmio_regs = (u32 *)(((unsigned long)IRONGATE0->bar1 &
+			PCI_BASE_ADDRESS_MEM_MASK) + IRONGATE_MEM);
+
+	gatt_pages = (u32 *)(phys_to_virt(mmio_regs[1])); /* FIXME */
+
+	/*
+	 * Adjust the limits (mappings must be page aligned)
+	 */
+	if (addr & ~PAGE_MASK) {
+		printk("AGP ioremap failed... addr not page aligned (0x%lx)\n",
+		       addr);
+		return addr + IRONGATE_MEM;
+	}
+	last = addr + size - 1;
+	size = PAGE_ALIGN(last) - addr;
+
+#if 0
+	printk("irongate_ioremap(0x%lx, 0x%lx)\n", addr, size);
+	printk("irongate_ioremap:  gart_bus_addr  0x%lx\n", gart_bus_addr);
+	printk("irongate_ioremap:  gart_aper_size 0x%lx\n", gart_aper_size);
+	printk("irongate_ioremap:  mmio_regs      %p\n", mmio_regs);
+	printk("irongate_ioremap:  gatt_pages     %p\n", gatt_pages);
+	
+	for(baddr = addr; baddr <= last; baddr += PAGE_SIZE)
+	{
+		cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1);
+		pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1;
+		printk("irongate_ioremap:  cur_gatt %p pte 0x%x\n",
+		       cur_gatt, pte);
+	}
+#endif
+
+	/*
+	 * Map it
+	 */
+	area = get_vm_area(size, VM_IOREMAP);
+	if (!area) return (unsigned long)NULL;
+
+	for(baddr = addr, vaddr = (unsigned long)area->addr; 
+	    baddr <= last; 
+	    baddr += PAGE_SIZE, vaddr += PAGE_SIZE)
+	{
+		cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1);
+		pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1;
+
+		if (irongate_remap_area_pages(VMALLOC_VMADDR(vaddr), 
+					   pte, PAGE_SIZE, 0)) {
+			printk("AGP ioremap: FAILED to map...\n");
+			vfree(area->addr);
+			return (unsigned long)NULL;
+		}
+	}
+
+	flush_tlb_all();
+
+	vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
+#if 0
+	printk("irongate_ioremap(0x%lx, 0x%lx) returning 0x%lx\n",
+	       addr, size, vaddr);
+#endif
+	return vaddr;
+}
+
+void
+irongate_iounmap(unsigned long addr)
+{
+	if (((long)addr >> 41) == -2)
+		return;	/* kseg map, nothing to do */
+	if (addr) return vfree((void *)(PAGE_MASK & addr)); 
 }
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.4.9/linux/arch/alpha/kernel/irq.c	Mon Aug 27 12:41:37 2001
+++ linux/arch/alpha/kernel/irq.c	Mon Sep 17 13:16:30 2001
@@ -38,7 +38,7 @@
 
 static void register_irq_proc(unsigned int irq);
 
-unsigned long irq_err_count;
+volatile unsigned long irq_err_count;
 
 /*
  * Special irq handlers.
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/irq_alpha.c linux/arch/alpha/kernel/irq_alpha.c
--- v2.4.9/linux/arch/alpha/kernel/irq_alpha.c	Tue Jul  3 17:08:18 2001
+++ linux/arch/alpha/kernel/irq_alpha.c	Mon Sep 17 13:16:30 2001
@@ -18,8 +18,6 @@
 unsigned long __irq_attempt[NR_IRQS];
 #endif
 
-extern unsigned long irq_err_count;
-
 /* Hack minimum IPL during interrupt processing for broken hardware.  */
 #ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
 int __min_ipl;
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/machvec_impl.h linux/arch/alpha/kernel/machvec_impl.h
--- v2.4.9/linux/arch/alpha/kernel/machvec_impl.h	Wed Jun 21 22:30:59 2000
+++ linux/arch/alpha/kernel/machvec_impl.h	Thu Sep 13 15:21:32 2001
@@ -80,7 +80,8 @@
 	mv_writew:		CAT(low,_writew),			\
 	mv_writel:		CAT(low,_writel),			\
 	mv_writeq:		CAT(low,_writeq),			\
-	mv_ioremap:		CAT(low,_ioremap)			\
+	mv_ioremap:		CAT(low,_ioremap),			\
+	mv_iounmap:		CAT(low,_iounmap)			\
 
 #define IO(UP,low)							\
 	IO_LITE(UP,low),						\
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/pci-noop.c linux/arch/alpha/kernel/pci-noop.c
--- v2.4.9/linux/arch/alpha/kernel/pci-noop.c	Fri Mar  2 11:12:07 2001
+++ linux/arch/alpha/kernel/pci-noop.c	Thu Sep 13 15:21:32 2001
@@ -102,3 +102,38 @@
 	else
 		return -ENODEV;
 }
+/* stubs for the routines in pci_iommu.c */
+void *
+pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp)
+{
+}
+void
+pci_free_consistent(struct pci_dev *pdev, long size, void *cpu_addr,
+		    dma_addr_t dma_addr)
+{
+}
+dma_addr_t
+pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size,
+	       int direction)
+{
+}
+void
+pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size,
+		 int direction)
+{
+}
+int
+pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
+	   int direction)
+{
+}
+void
+pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
+	     int direction)
+{
+}
+int
+pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
+{
+	return 0;
+}
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/pci.c linux/arch/alpha/kernel/pci.c
--- v2.4.9/linux/arch/alpha/kernel/pci.c	Mon May 21 13:38:41 2001
+++ linux/arch/alpha/kernel/pci.c	Thu Sep 13 15:21:32 2001
@@ -76,6 +76,9 @@
 		dev->resource[3].end = dev->resource[3].start + 7;
 }
 
+static void __init
+quirk_cypress(struct pci_dev *dev)
+{
 /*
  * Notorious Cy82C693 chip. One of its numerous bugs: although
  * Cypress IDE controller doesn't support native mode, it has
@@ -85,31 +88,27 @@
  * and floppy controller. Ugh.
  * Fix that.
  */
-static void __init
-quirk_cypress_ide_ports(struct pci_dev *dev)
-{
-	if (dev->class >> 8 != PCI_CLASS_STORAGE_IDE)
+	if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) {
+		dev->resource[0].flags = 0;
+		dev->resource[1].flags = 0;
 		return;
-	dev->resource[0].flags = 0;
-	dev->resource[1].flags = 0;
-}
-
-static void __init
-quirk_vga_enable_rom(struct pci_dev *dev)
-{
-	/* If it's a VGA, enable its BIOS ROM at C0000.
-	   But if its a Cirrus 543x/544x DISABLE it, since
-	   enabling ROM disables the memory... */
-	if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA &&
-	    (dev->vendor != PCI_VENDOR_ID_CIRRUS ||
-	     (dev->device < 0x00a0) || (dev->device > 0x00ac)))
-	{
-		u32 reg;
-
-		pci_read_config_dword(dev, dev->rom_base_reg, &reg);
-		reg |= PCI_ROM_ADDRESS_ENABLE;
-		pci_write_config_dword(dev, dev->rom_base_reg, reg);
-		dev->resource[PCI_ROM_RESOURCE].flags |= PCI_ROM_ADDRESS_ENABLE;
+	}
+/*
+ * Another "feature": Cypress bridge responds on the PCI bus
+ * in the address range 0xffff0000-0xffffffff (conventional
+ * x86 BIOS ROM). No way to turn this off, so if we use
+ * large SG window, we must avoid these addresses.
+ */
+	if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
+		struct pci_controller *hose = dev->sysdata;
+		long overlap;
+
+		if (hose->sg_pci) {
+			overlap = hose->sg_pci->dma_base + hose->sg_pci->size;
+			overlap -= 0xffff0000;
+			if (overlap > 0)
+				hose->sg_pci->size -= overlap;
+		}
 	}
 }
 
@@ -121,8 +120,7 @@
 	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229,
 	  quirk_ali_ide_ports },
 	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
-	  quirk_cypress_ide_ports },
-	{ PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_vga_enable_rom },
+	  quirk_cypress },
 	{ 0 }
 };
 
@@ -148,10 +146,8 @@
 		/*
 		 * Put everything into 0x00-0xff region modulo 0x400
 		 */
-		if (start & 0x300) {
+		if (start & 0x300)
 			start = (start + 0x3ff) & ~0x3ff;
-			res->start = start;
-		}
 	}
 	else if	(res->flags & IORESOURCE_MEM) {
 		/* Make sure we start at our min on all hoses */
@@ -177,13 +173,13 @@
 		/* Align to multiple of size of minimum base.  */
 		alignto = MAX(0x1000, size);
 		start = ALIGN(start, alignto);
-		if (size <= 7 * 16*MB) {
+		if (hose->sparse_mem_base && size <= 7 * 16*MB) {
 			if (((start / (16*MB)) & 0x7) == 0) {
 				start &= ~(128*MB - 1);
 				start += 16*MB;
 				start  = ALIGN(start, alignto);
 			}
-			if (start/(128*MB) != (start + size)/(128*MB)) {
+			if (start/(128*MB) != (start + size - 1)/(128*MB)) {
 				start &= ~(128*MB - 1);
 				start += (128 + 16)*MB;
 				start  = ALIGN(start, alignto);
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/pci_impl.h linux/arch/alpha/kernel/pci_impl.h
--- v2.4.9/linux/arch/alpha/kernel/pci_impl.h	Fri May 25 09:54:50 2001
+++ linux/arch/alpha/kernel/pci_impl.h	Thu Sep 13 15:21:32 2001
@@ -49,7 +49,7 @@
  * APECS and LCA have only 34 bits for physical addresses, thus limiting PCI
  * bus memory addresses for SPARSE access to be less than 128Mb.
  */
-#define APECS_AND_LCA_DEFAULT_MEM_BASE ((32+2)*1024*1024)
+#define APECS_AND_LCA_DEFAULT_MEM_BASE ((16+2)*1024*1024)
 
 /*
  * Because the MCPCIA core logic supports more bits for physical addresses,
@@ -136,6 +136,7 @@
 	spinlock_t lock;
 	struct pci_controller *hose;
 #define IOMMU_INVALID_PTE 0x2 /* 32:63 bits MBZ */
+#define IOMMU_RESERVED_PTE 0xface
 	unsigned long *ptes;
 	dma_addr_t dma_base;
 	unsigned int size;
@@ -161,3 +162,10 @@
 extern const char *const pci_io_names[];
 extern const char *const pci_mem_names[];
 extern const char pci_hae0_name[];
+
+extern int iommu_reserve(struct pci_iommu_arena *, long, long);
+extern int iommu_release(struct pci_iommu_arena *, long, long);
+extern int iommu_bind(struct pci_iommu_arena *, long, long, unsigned long *);
+extern int iommu_unbind(struct pci_iommu_arena *, long, long);
+
+
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/pci_iommu.c linux/arch/alpha/kernel/pci_iommu.c
--- v2.4.9/linux/arch/alpha/kernel/pci_iommu.c	Mon Aug 27 12:41:37 2001
+++ linux/arch/alpha/kernel/pci_iommu.c	Thu Sep 13 15:21:32 2001
@@ -42,24 +42,6 @@
 	return (bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
 }
 
-static void __init
-iommu_arena_fixup(struct pci_iommu_arena * arena)
-{
-	unsigned long base, size;
-
-	/*
-	 * The Cypress chip has a quirk, it get confused by addresses
-	 * above -1M so reserve the pagetables that maps pci addresses
-	 * above -1M.
-	 */
-	base = arena->dma_base;
-	size = arena->size;
-	if (base + size > 0xfff00000) {
-		int i, fixup_start = (0xfff00000 - base) >> PAGE_SHIFT;
-		for (i= 0; i < (0x100000 >> PAGE_SHIFT); i++)
-			arena->ptes[fixup_start+i] = IOMMU_INVALID_PTE;
-	}
-}
 
 struct pci_iommu_arena *
 iommu_arena_new(struct pci_controller *hose, dma_addr_t base,
@@ -90,24 +72,19 @@
 	   unless there are chip bugs.  */
 	arena->align_entry = 1;
 
-	iommu_arena_fixup(arena);
-
 	return arena;
 }
 
-long
-iommu_arena_alloc(struct pci_iommu_arena *arena, long n)
+/* Must be called with the arena lock held */
+static long
+iommu_arena_find_pages(struct pci_iommu_arena *arena, long n, long mask)
 {
-	unsigned long flags;
 	unsigned long *ptes;
-	long i, p, nent, mask;
+	long i, p, nent;
 
-	spin_lock_irqsave(&arena->lock, flags);
-
-	/* Search forward for the first sequence of N empty ptes.  */
+	/* Search forward for the first mask-aligned sequence of N free ptes */
 	ptes = arena->ptes;
 	nent = arena->size >> PAGE_SHIFT;
-	mask = arena->align_entry - 1;
 	p = (arena->next_entry + mask) & ~mask;
 	i = 0;
 	while (i < n && p+i < nent) {
@@ -130,10 +107,31 @@
 				i = i + 1;
 		}
 
-		if (i < n) {
-			spin_unlock_irqrestore(&arena->lock, flags);
+		if (i < n)
 			return -1;
-		}
+	}
+
+	/* Success. It's the responsibility of the caller to mark them
+	   in use before releasing the lock */
+	return p;
+}
+
+long
+iommu_arena_alloc(struct pci_iommu_arena *arena, long n)
+{
+	unsigned long flags;
+	unsigned long *ptes;
+	long i, p, mask;
+
+	spin_lock_irqsave(&arena->lock, flags);
+
+	/* Search for N empty ptes */
+	ptes = arena->ptes;
+	mask = arena->align_entry - 1;
+	p = iommu_arena_find_pages(arena, n, mask);
+	if (p < 0) {
+		spin_unlock_irqrestore(&arena->lock, flags);
+		return -1;
 	}
 
 	/* Success.  Mark them all in use, ie not zero and invalid
@@ -660,6 +658,104 @@
 	arena = hose->sg_pci;
 	if (arena && arena->dma_base + arena->size - 1 <= mask)
 		return 1;
+
+	return 0;
+}
+
+
+/*
+ * AGP GART extensions to the IOMMU
+ */
+int
+iommu_reserve(struct pci_iommu_arena *arena, long pg_count, long align_mask) 
+{
+	unsigned long flags;
+	unsigned long *ptes;
+	long i, p;
+
+	if (!arena) return -EINVAL;
+
+	spin_lock_irqsave(&arena->lock, flags);
+
+	/* Search for N empty ptes.  */
+	ptes = arena->ptes;
+	p = iommu_arena_find_pages(arena, pg_count, align_mask);
+	if (p < 0) {
+		spin_unlock_irqrestore(&arena->lock, flags);
+		return -1;
+	}
+
+	/* Success.  Mark them all reserved (ie not zero and invalid)
+	   for the iommu tlb that could load them from under us.
+	   They will be filled in with valid bits by _bind() */
+	for (i = 0; i < pg_count; ++i)
+		ptes[p+i] = IOMMU_RESERVED_PTE;
+
+	arena->next_entry = p + pg_count;
+	spin_unlock_irqrestore(&arena->lock, flags);
+
+	return p;
+}
+
+int 
+iommu_release(struct pci_iommu_arena *arena, long pg_start, long pg_count)
+{
+	unsigned long *ptes;
+	long i;
+
+	if (!arena) return -EINVAL;
+
+	ptes = arena->ptes;
+
+	/* Make sure they're all reserved first... */
+	for(i = pg_start; i < pg_start + pg_count; i++)
+		if (ptes[i] != IOMMU_RESERVED_PTE)
+			return -EBUSY;
+
+	iommu_arena_free(arena, pg_start, pg_count);
+	return 0;
+}
+
+int
+iommu_bind(struct pci_iommu_arena *arena, long pg_start, long pg_count, 
+	   unsigned long *physaddrs)
+{
+	unsigned long flags;
+	unsigned long *ptes;
+	long i, j;
+
+	if (!arena) return -EINVAL;
+	
+	spin_lock_irqsave(&arena->lock, flags);
+
+	ptes = arena->ptes;
+
+	for(j = pg_start; j < pg_start + pg_count; j++) {
+		if (ptes[j] != IOMMU_RESERVED_PTE) {
+			spin_unlock_irqrestore(&arena->lock, flags);
+			return -EBUSY;
+		}
+	}
+		
+	for(i = 0, j = pg_start; i < pg_count; i++, j++)
+		ptes[j] = mk_iommu_pte(physaddrs[i]);
+
+	spin_unlock_irqrestore(&arena->lock, flags);
+
+	return 0;
+}
+
+int
+iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count)
+{
+	unsigned long *p;
+	long i;
+
+	if (!arena) return -EINVAL;
+
+	p = arena->ptes + pg_start;
+	for(i = 0; i < pg_count; i++)
+		p[i] = IOMMU_RESERVED_PTE;
 
 	return 0;
 }
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.4.9/linux/arch/alpha/kernel/process.c	Tue Jul  3 17:08:18 2001
+++ linux/arch/alpha/kernel/process.c	Mon Sep 17 15:29:09 2001
@@ -50,7 +50,6 @@
  */
 
 unsigned long init_user_stack[1024] = { STACK_MAGIC, };
-static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
@@ -213,7 +212,9 @@
 void
 show_regs(struct pt_regs * regs)
 {
-	printk("\nps: %04lx pc: [<%016lx>]\n", regs->ps, regs->pc);
+	printk("\n");
+	printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
+	printk("ps: %04lx pc: [<%016lx>] CPU %d\n", regs->ps, regs->pc, smp_processor_id());
 	printk("rp: [<%016lx>] sp: %p\n", regs->r26, regs+1);
 	printk(" r0: %016lx  r1: %016lx  r2: %016lx  r3: %016lx\n",
 	       regs->r0, regs->r1, regs->r2, regs->r3);
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
--- v2.4.9/linux/arch/alpha/kernel/ptrace.c	Wed Jul 25 17:10:17 2001
+++ linux/arch/alpha/kernel/ptrace.c	Tue Sep 18 17:03:51 2001
@@ -233,6 +233,16 @@
 	return (nsaved != 0);
 }
 
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{ 
+	ptrace_cancel_bpt(child);
+}
+
 asmlinkage long
 sys_ptrace(long request, long pid, long addr, long data,
 	   int a4, int a5, struct pt_regs regs)
@@ -362,21 +372,8 @@
 		ret = 0;
 		goto out;
 
-	case PTRACE_DETACH: /* detach a process that was attached. */
-		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
-			goto out;
-		child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
-		wake_up_process(child);
-		child->exit_code = data;
-		write_lock_irq(&tasklist_lock);
-		REMOVE_LINKS(child);
-		child->p_pptr = child->p_opptr;
-		SET_LINKS(child);
-		write_unlock_irq(&tasklist_lock);
-		/* make sure single-step breakpoint is gone. */
-		ptrace_cancel_bpt(child);
-		ret = 0;
+	case PTRACE_DETACH:	 /* detach a process that was attached. */
+		ret = ptrace_detach(child, data);
 		goto out;
 
 	default:
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.4.9/linux/arch/alpha/kernel/smp.c	Mon Aug 27 12:41:38 2001
+++ linux/arch/alpha/kernel/smp.c	Thu Sep 13 15:21:32 2001
@@ -1,5 +1,13 @@
 /*
  *	linux/arch/alpha/kernel/smp.c
+ *
+ *      2001-07-09 Phil Ezolt (Phillip.Ezolt@compaq.com)
+ *            Renamed modified smp_call_function to smp_call_function_on_cpu()
+ *            Created an function that conforms to the old calling convention
+ *            of smp_call_function().
+ *
+ *            This is helpful for DCPI.
+ *
  */
 
 #include <linux/errno.h>
@@ -867,23 +875,31 @@
  */
 
 int
-smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
+smp_call_function_on_cpu (void (*func) (void *info), void *info, int retry,
+			  int wait, unsigned long to_whom)
 {
-	unsigned long to_whom = cpu_present_mask ^ (1UL << smp_processor_id());
 	struct smp_call_struct data;
 	long timeout;
+	int num_cpus_to_call;
+	long i,j;
 	
 	data.func = func;
 	data.info = info;
 	data.wait = wait;
-	atomic_set(&data.unstarted_count, smp_num_cpus - 1);
-	atomic_set(&data.unfinished_count, smp_num_cpus - 1);
+
+	to_whom &= ~(1L << smp_processor_id());
+	for (i = 0, j = 1, num_cpus_to_call = 0; i < NR_CPUS; ++i, j <<= 1)
+		if (to_whom & j)
+			num_cpus_to_call++;
+
+	atomic_set(&data.unstarted_count, num_cpus_to_call);
+	atomic_set(&data.unfinished_count, num_cpus_to_call);
 
 	/* Acquire the smp_call_function_data mutex.  */
 	if (pointer_lock(&smp_call_function_data, &data, retry))
 		return -EBUSY;
 
-	/* Send a message to all other CPUs.  */
+	/* Send a message to the requested CPUs.  */
 	send_ipi_message(to_whom, IPI_CALL_FUNC);
 
 	/* Wait for a minimal response.  */
@@ -905,6 +921,13 @@
 	}
 
 	return 0;
+}
+
+int
+smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
+{
+	return smp_call_function_on_cpu (func, info, retry, wait,
+					 cpu_present_mask);
 }
 
 static void
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/sys_jensen.c linux/arch/alpha/kernel/sys_jensen.c
--- v2.4.9/linux/arch/alpha/kernel/sys_jensen.c	Fri Mar  2 11:12:07 2001
+++ linux/arch/alpha/kernel/sys_jensen.c	Thu Sep 13 15:21:32 2001
@@ -35,14 +35,16 @@
 
 /*
  * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
- * 0x9X0 for the local motherboard interrupts..
+ * 0x9X0 for the local motherboard interrupts.
+ *
+ * Note especially that those local interrupts CANNOT be masked,
+ * which causes much of the pain below...
  *
  *	0x660 - NMI
  *
  *	0x800 - IRQ0  interval timer (not used, as we use the RTC timer)
  *	0x810 - IRQ1  line printer (duh..)
  *	0x860 - IRQ6  floppy disk
- *	0x8E0 - IRQ14 SCSI controller
  *
  *	0x900 - COM1
  *	0x920 - COM2
@@ -52,27 +54,77 @@
  * PCI-based systems are more sane: they don't have the local
  * interrupts at all, and have only normal PCI interrupts from
  * devices.  Happily it's easy enough to do a sane mapping from the
- * Jensen..  Note that this means that we may have to do a hardware
- * "ack" to a different interrupt than we report to the rest of the
+ * Jensen.
+ * 
+ * Note that this means that we may have to do a hardware
+ * "local_op" to a different interrupt than we report to the rest of the
  * world.
  */
 
+static unsigned int
+jensen_local_startup(unsigned int irq)
+{
+	/* the parport is really hw IRQ 1, silly Jensen.  */
+	if (irq == 7)
+		i8259a_startup_irq(1);
+	else
+		/*
+		 * For all true local interrupts, set the flag that prevents
+		 * the IPL from being dropped during handler processing.
+		 */
+		if (irq_desc[irq].action)
+			irq_desc[irq].action->flags |= SA_INTERRUPT;
+	return 0;
+}
+
+static void
+jensen_local_shutdown(unsigned int irq)
+{
+	/* the parport is really hw IRQ 1, silly Jensen.  */
+	if (irq == 7)
+		i8259a_disable_irq(1);
+}
+
+static void
+jensen_local_enable(unsigned int irq)
+{
+	/* the parport is really hw IRQ 1, silly Jensen.  */
+	if (irq == 7)
+		i8259a_enable_irq(1);
+}
+
+static void
+jensen_local_disable(unsigned int irq)
+{
+	/* the parport is really hw IRQ 1, silly Jensen.  */
+	if (irq == 7)
+		i8259a_disable_irq(1);
+}
+
 static void
 jensen_local_ack(unsigned int irq)
 {
-	/* irq1 is supposed to be the keyboard, silly Jensen.  */
+	/* the parport is really hw IRQ 1, silly Jensen.  */
 	if (irq == 7)
 		i8259a_mask_and_ack_irq(1);
 }
 
+static void
+jensen_local_end(unsigned int irq)
+{
+	/* the parport is really hw IRQ 1, silly Jensen.  */
+	if (irq == 7)
+		i8259a_end_irq(1);
+}
+
 static struct hw_interrupt_type jensen_local_irq_type = {
 	typename:	"LOCAL",
-	startup:	i8259a_startup_irq,
-	shutdown:	i8259a_disable_irq,
-	enable:		i8259a_enable_irq,
-	disable:	i8259a_disable_irq,
+	startup:	jensen_local_startup,
+	shutdown:	jensen_local_shutdown,
+	enable:		jensen_local_enable,
+	disable:	jensen_local_disable,
 	ack:		jensen_local_ack,
-	end:		i8259a_end_irq,
+	end:		jensen_local_end,
 };
 
 static void 
@@ -104,6 +156,47 @@
 		break;
 	}
 
+	/* If there is no handler yet... */
+	if (irq_desc[irq].action == NULL) {
+	    /* If it is a local interrupt that cannot be masked... */
+	    if (vector >= 0x900)
+	    {
+	        /* Clear keyboard/mouse state */
+	    	inb(0x64);
+		inb(0x60);
+		/* Reset serial ports */
+		inb(0x3fa);
+		inb(0x2fa);
+		outb(0x0c, 0x3fc);
+		outb(0x0c, 0x2fc);
+		/* Clear NMI */
+		outb(0,0x61);
+		outb(0,0x461);
+	    }
+	}
+
+#if 0
+        /* A useful bit of code to find out if an interrupt is going wild.  */
+        {
+          static unsigned int last_msg = 0, last_cc = 0;
+          static int last_irq = -1, count = 0;
+          unsigned int cc;
+
+          __asm __volatile("rpcc %0" : "=r"(cc));
+          ++count;
+#define JENSEN_CYCLES_PER_SEC	(150000000)
+          if (cc - last_msg > ((JENSEN_CYCLES_PER_SEC) * 3) ||
+	      irq != last_irq) {
+                printk(KERN_CRIT " irq %d count %d cc %u @ %lx\n",
+                       irq, count, cc-last_cc, regs->pc);
+                count = 0;
+                last_msg = cc;
+                last_irq = irq;
+          }
+          last_cc = cc;
+        }
+#endif
+
 	handle_irq(irq, regs);
 }
 
@@ -164,7 +257,7 @@
 	BUS(jensen),
 	machine_check:		jensen_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
-	rtc_port: 0x170,
+	rtc_port:		0x170,
 
 	nr_irqs:		16,
 	device_interrupt:	jensen_device_interrupt,
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.4.9/linux/arch/alpha/kernel/traps.c	Mon Aug 27 12:41:38 2001
+++ linux/arch/alpha/kernel/traps.c	Mon Sep 17 13:16:30 2001
@@ -19,9 +19,37 @@
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <asm/sysinfo.h>
+#include <asm/hwrpb.h>
 
 #include "proto.h"
 
+/* data/code implementing a work-around for some SRMs which
+   mishandle opDEC faults
+*/
+static int opDEC_testing = 0;
+static int opDEC_fix = 0;
+static unsigned long opDEC_test_pc = 0;
+
+static void
+opDEC_check(void)
+{
+	unsigned long test_pc;
+
+	lock_kernel();
+	opDEC_testing = 1;
+
+	__asm__ __volatile__(
+		"       br      %0,1f\n"
+		"1:     addq    %0,8,%0\n"
+		"       stq     %0,%1\n"
+		"       cvttq/svm $f31,$f31\n"
+		: "=&r"(test_pc), "=m"(opDEC_test_pc)
+		: );
+
+	opDEC_testing = 0;
+	unlock_kernel();
+}
+
 void
 dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
 {
@@ -56,10 +84,12 @@
 #endif
 }
 
+#if 0
 static char * ireg_name[] = {"v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
 			   "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6",
 			   "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
 			   "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"};
+#endif
 
 static void
 dik_show_code(unsigned int *pc)
@@ -98,6 +128,18 @@
 	printk("\n");
 }
 
+void show_trace_task(struct task_struct * tsk)
+{
+	struct thread_struct * thread = &tsk->thread;
+	unsigned long fp, sp = thread->ksp, base = (unsigned long) thread;
+ 
+	if (sp > base && sp+6*8 < base + 16*1024) {
+		fp = ((unsigned long*)sp)[6];
+		if (fp > sp && fp < base + 16*1024)
+			dik_show_trace((unsigned long *)fp);
+	}
+}
+
 int kstack_depth_to_print = 24;
 
 void show_stack(unsigned long *sp)
@@ -188,8 +230,10 @@
 	 unsigned long a2, unsigned long a3, unsigned long a4,
 	 unsigned long a5, struct pt_regs regs)
 {
-	die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
+	if (!opDEC_testing || type != 4) {
+		die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
 		      &regs, type, 0);
+	}
 
 	switch (type) {
 	      case 0: /* breakpoint */
@@ -242,6 +286,21 @@
 
 	      case 4: /* opDEC */
 		if (implver() == IMPLVER_EV4) {
+			/* The some versions of SRM do not handle
+			   the opDEC properly - they return the PC of the
+			   opDEC fault, not the instruction after as the
+			   Alpha architecture requires.  Here we fix it up.
+			   We do this by intentionally causing an opDEC
+			   fault during the boot sequence and testing if
+			   we get the correct PC.  If not, we set a flag
+			   to correct it every time through.
+			*/
+			if (opDEC_testing && regs.pc == opDEC_test_pc) {
+				opDEC_fix = 4;
+				printk("opDEC fixup enabled.\n");
+			}
+			regs.pc += opDEC_fix; 
+			
 			/* EV4 does not implement anything except normal
 			   rounding.  Everything else will come here as
 			   an illegal instruction.  Emulate them.  */
@@ -252,12 +311,13 @@
 	      case 3: /* FEN fault */
 	      case 5: /* illoc */
 	      default: /* unexpected instruction-fault type */
+		      ;
 	}
 	send_sig(SIGILL, current, 1);
 }
 
 /* There is an ifdef in the PALcode in MILO that enables a 
-   "kernel debugging entry point" as an unprivilaged call_pal.
+   "kernel debugging entry point" as an unpriviledged call_pal.
 
    We don't want to have anything to do with it, but unfortunately
    several versions of MILO included in distributions have it enabled,
@@ -933,4 +993,11 @@
 	wrent(entUna, 4);
 	wrent(entSys, 5);
 	wrent(entDbg, 6);
+
+	/* Hack for Multia (UDB) and JENSEN: some of their SRMs have
+	 * a bug in the handling of the opDEC fault.  Fix it up if so.
+	 */
+	if (implver() == IMPLVER_EV4) {
+		opDEC_check();
+	}
 }
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- v2.4.9/linux/arch/alpha/mm/fault.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/alpha/mm/fault.c	Mon Sep 17 16:15:02 2001
@@ -140,6 +140,7 @@
 			goto bad_area;
 	}
 
+ survive:
 	/*
 	 * If for any reason at all we couldn't handle the fault,
 	 * make sure we exit gracefully rather than endlessly redo
@@ -194,6 +195,12 @@
  * us unable to handle the page fault gracefully.
  */
 out_of_memory:
+	if (current->pid == 1) {
+		current->policy |= SCHED_YIELD;
+		schedule();
+		down_read(&mm->mmap_sem);
+		goto survive;
+	}
 	printk(KERN_ALERT "VM: killing process %s(%d)\n",
 	       current->comm, current->pid);
 	if (!user_mode(regs))
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c
--- v2.4.9/linux/arch/alpha/mm/init.c	Thu May 24 15:20:18 2001
+++ linux/arch/alpha/mm/init.c	Thu Sep 20 20:02:03 2001
@@ -32,6 +32,9 @@
 #include <asm/dma.h>
 #include <asm/mmu_context.h>
 #include <asm/console.h>
+#include <asm/tlb.h>
+
+mmu_gather_t mmu_gathers[NR_CPUS];
 
 unsigned long totalram_pages;
 
diff -u --recursive --new-file v2.4.9/linux/arch/arm/kernel/arthur.c linux/arch/arm/kernel/arthur.c
--- v2.4.9/linux/arch/arm/kernel/arthur.c	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/kernel/arthur.c	Mon Sep 10 13:04:33 2001
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/arthur.c
  *
- *  Copyright (C) 1998, 1999, 2000 Philip Blundell
+ *  Copyright (C) 1998, 1999, 2000, 2001 Philip Blundell
  *
  * Arthur personality
  */
@@ -58,14 +58,14 @@
 {
 	struct siginfo info;
 	info.si_signo = SIGSWI;
-	info.si_code = nr;
+	info.si_errno = nr;
 	/* Bounce it to the emulator */
 	send_sig_info(SIGSWI, &info, current);
 }
 
 static struct exec_domain arthur_exec_domain = {
 	"Arthur",	/* name */
-	(lcall7_func)arthur_lcall7,
+	arthur_lcall7,
 	PER_RISCOS, PER_RISCOS,
 	arthur_to_linux_signals,
 	linux_to_arthur_signals,
diff -u --recursive --new-file v2.4.9/linux/arch/arm/kernel/init_task.c linux/arch/arm/kernel/init_task.c
--- v2.4.9/linux/arch/arm/kernel/init_task.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/kernel/init_task.c	Mon Sep 17 15:29:09 2001
@@ -9,7 +9,6 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
-static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
diff -u --recursive --new-file v2.4.9/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c
--- v2.4.9/linux/arch/arm/kernel/process.c	Mon Aug 27 12:41:38 2001
+++ linux/arch/arm/kernel/process.c	Fri Sep  7 09:28:38 2001
@@ -124,7 +124,7 @@
 		pm_power_off();
 }
 
-void machine_restart(void * __unused)
+void machine_restart(char * __unused)
 {
 	/*
 	 * Clean and disable cache, and turn off interrupts
diff -u --recursive --new-file v2.4.9/linux/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c
--- v2.4.9/linux/arch/arm/kernel/ptrace.c	Mon Aug 27 12:41:38 2001
+++ linux/arch/arm/kernel/ptrace.c	Tue Sep 18 17:03:51 2001
@@ -386,6 +386,16 @@
 	}
 }
 
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	__ptrace_cancel_bpt(child);
+}
+
 static int do_ptrace(int request, struct task_struct *child, long addr, long data)
 {
 	unsigned long tmp;
@@ -491,20 +501,7 @@
 		 * detach a process that was attached.
 		 */
 		case PTRACE_DETACH:
-			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
-				break;
-			child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
-			child->exit_code = data;
-			write_lock_irq(&tasklist_lock);
-			REMOVE_LINKS(child);
-			child->p_pptr = child->p_opptr;
-			SET_LINKS(child);
-			write_unlock_irq(&tasklist_lock);
-			/* make sure single-step breakpoint is gone. */
-			__ptrace_cancel_bpt(child);
-			wake_up_process (child);
-			ret = 0;
+			ret = ptrace_detach(child, data);
 			break;
 
 		/*
diff -u --recursive --new-file v2.4.9/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.4.9/linux/arch/arm/kernel/traps.c	Mon Aug 27 12:41:38 2001
+++ linux/arch/arm/kernel/traps.c	Mon Sep 10 13:04:33 2001
@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
+#include <linux/personality.h>
 #include <linux/ptrace.h>
 #include <linux/elf.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.9/linux/arch/arm/lib/io-readsl-armv4.S linux/arch/arm/lib/io-readsl-armv4.S
--- v2.4.9/linux/arch/arm/lib/io-readsl-armv4.S	Mon Aug 27 12:41:38 2001
+++ linux/arch/arm/lib/io-readsl-armv4.S	Fri Sep  7 09:28:38 2001
@@ -63,8 +63,8 @@
 		strne	ip, [r1], #4
 		movne	ip, r3, lsr #8
 		bne	7b
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
 		strh	ip, [r1], #2
+		mov	ip, ip, lsr #16
+		strb	ip, [r1]
 		mov	pc, lr
 
diff -u --recursive --new-file v2.4.9/linux/arch/arm/lib/io-writesl.S linux/arch/arm/lib/io-writesl.S
--- v2.4.9/linux/arch/arm/lib/io-writesl.S	Mon Aug 27 12:41:38 2001
+++ linux/arch/arm/lib/io-writesl.S	Fri Sep  7 09:28:38 2001
@@ -25,31 +25,30 @@
 
 2:		bic	r1, r1, #3
 		cmp	ip, #2
-		ldr	ip, [r1], #4
-		mov	ip, ip, lsr #16
-		blt	4f
-		bgt	5f
+		ldr	r3, [r1], #4
+		bgt	4f
+		blt	5f
 
-3:		ldr	r3, [r1], #4
+3:		mov	ip, r3, lsr #16
+		ldr	r3, [r1], #4
 		orr	ip, ip, r3, lsl #16
 		str	ip, [r0]
-		mov	ip, r3, lsr #16
 		subs	r2, r2, #1
 		bne	3b
 		mov	pc, lr
 
-4:		ldr	r3, [r1], #4
+4:		mov	ip, r3, lsr #24
+		ldr	r3, [r1], #4
 		orr	ip, ip, r3, lsl #8
 		str	ip, [r0]
-		mov	ip, r3, lsr #24
 		subs	r2, r2, #1
 		bne	4b
 		mov	pc, lr
 
-5:		ldr	r3, [r1], #4
+5:		mov	ip, r3, lsr #8
+		ldr	r3, [r1], #4
 		orr	ip, ip, r3, lsl #24
 		str	ip, [r0]
-		mov	ip, r3, lsr #8
 		subs	r2, r2, #1
 		bne	5b
 		mov	pc, lr
diff -u --recursive --new-file v2.4.9/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
--- v2.4.9/linux/arch/arm/mm/fault-armv.c	Mon Aug 27 12:41:38 2001
+++ linux/arch/arm/mm/fault-armv.c	Fri Sep  7 09:28:38 2001
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
+#include <linux/bitops.h>
 #include <linux/init.h>
 
 #include <asm/system.h>
@@ -366,8 +367,7 @@
 	ai_multi += 1;
 
 	/* count the number of registers in the mask to be transferred */
-	for (regbits = REGMASK_BITS(instr), nr_regs = 0; regbits; regbits >>= 1)
-		nr_regs += 4;
+	nr_regs = hweight16(REGMASK_BITS(instr)) * 4;
 
 	rn = RN_BITS(instr);
 	newaddr = eaddr = regs->uregs[rn];
@@ -385,10 +385,12 @@
 	 * This is a "hint" - we already have eaddr worked out by the
 	 * processor for us.
 	 */
-	if (addr != eaddr)
+	if (addr != eaddr) {
 		printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, "
 			"addr = %08lx, eaddr = %08lx\n",
 			 instruction_pointer(regs), instr, addr, eaddr);
+		show_regs(regs);
+	}
 
 	for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1)
 		if (regbits & 1) {
diff -u --recursive --new-file v2.4.9/linux/arch/arm/tools/Makefile linux/arch/arm/tools/Makefile
--- v2.4.9/linux/arch/arm/tools/Makefile	Tue Jul  3 17:08:18 2001
+++ linux/arch/arm/tools/Makefile	Fri Sep  7 09:28:38 2001
@@ -26,7 +26,8 @@
 # directories
 
 dep:
-	$(TOPDIR)/scripts/mkdep getconstants.c | sed s,getconstants.o,$(TOPDIR)/include/asm-arm/constants.h, > .depend
+	$(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS) -- getconstants.c |\
+	 sed s,getconstants.o,$(TOPDIR)/include/asm-arm/constants.h, > .depend
 	$(MAKE) all
 
 .PHONY:	all dep
diff -u --recursive --new-file v2.4.9/linux/arch/arm/tools/mach-types linux/arch/arm/tools/mach-types
--- v2.4.9/linux/arch/arm/tools/mach-types	Mon Aug 27 12:41:38 2001
+++ linux/arch/arm/tools/mach-types	Fri Sep  7 09:28:38 2001
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Thu Aug 9 22:46:02 2001
+# Last update: Thu Aug 23 12:38:13 2001
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -31,7 +31,7 @@
 l7200			ARCH_L7200		L7200			19
 pleb			SA1100_PLEB		PLEB			20
 integrator		ARCH_INTEGRATOR		INTEGRATOR		21
-bitsy			SA1100_BITSY		BITSY			22
+h3600			SA1100_H3600		H3600			22
 ixp1200			ARCH_IXP1200		IXP1200			23
 p720t			ARCH_P720T		P720T			24
 assabet			SA1100_ASSABET		ASSABET			25
@@ -89,7 +89,7 @@
 tardis			ARCH_TARDIS		TARDIS			77
 mercury			ARCH_MERCURY		MERCURY			78
 empeg			SA1100_EMPEG		EMPEG			79
-adi_eb			ARCH_I80200FCC		I80200FCC		80
+adi_evb			ARCH_I80200FCC		I80200FCC		80
 itt_cpb			SA1100_ITT_CPB		ITT_CPB			81
 svc			SA1100_SVC		SVC			82
 alpha2			SA1100_ALPHA2		ALPHA2			84
@@ -115,3 +115,10 @@
 granite			ARCH_GRANITE		GRANITE			104
 consus			SA1100_CONSUS		CONSUS			105
 aaec2000_aaed20		ARCH_AAEC2000_AAED2000	AAEC2000_AAED2000	106
+cdb89712		ARCH_CDB89712		CDB89712		107
+graphicsmaster		SA1100_GRAPHICSMASTER	GRAPHICSMASTER		108
+adsbitsy		SA1100_ADSBITSY		ADSBITSY		109
+cotulla_idp		ARCH_COTULLA_IDP	COTULLA_IDP		110
+plce			ARCH_PLCE		PLCE			111
+pt_system3		SA1100_PT_SYSTEM3	PT_SYSTEM3		112
+medalb			ARCH_MEDALB		MEDALB			113
diff -u --recursive --new-file v2.4.9/linux/arch/cris/drivers/parport.c linux/arch/cris/drivers/parport.c
--- v2.4.9/linux/arch/cris/drivers/parport.c	Sun Aug 12 13:27:58 2001
+++ linux/arch/cris/drivers/parport.c	Fri Sep 14 14:04:06 2001
@@ -23,7 +23,7 @@
 #include <linux/major.h>
 #include <linux/sched.h>
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 
 #include <asm/setup.h>
diff -u --recursive --new-file v2.4.9/linux/arch/cris/drivers/usb-host.c linux/arch/cris/drivers/usb-host.c
--- v2.4.9/linux/arch/cris/drivers/usb-host.c	Mon Aug 27 12:41:39 2001
+++ linux/arch/cris/drivers/usb-host.c	Mon Sep 10 09:04:53 2001
@@ -2258,11 +2258,11 @@
 	case RH_GET_DESCRIPTOR:
 		switch ((wValue & 0xff00) >> 8) {
 		case (0x01):	/* device descriptor */
-			len = min(unsigned int, leni, min(unsigned int, sizeof (root_hub_dev_des), wLength));
+			len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_dev_des), wLength));
 			memcpy (data, root_hub_dev_des, len);
 			OK (len);
 		case (0x02):	/* configuration descriptor */
-			len = min(unsigned int, leni, min(unsigned int, sizeof (root_hub_config_des), wLength));
+			len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_config_des), wLength));
 			memcpy (data, root_hub_config_des, len);
 			OK (len);
 		case (0x03):	/* string descriptors */
@@ -2270,7 +2270,7 @@
 						   0xff, "ETRAX 100LX",
 						   data, wLength);
 			if (len > 0) {
-				OK(min(int, leni, len));
+				OK(min_t(int, leni, len));
 			} else 
 				stat = -EPIPE;
 		}
@@ -2278,7 +2278,7 @@
 		
 	case RH_GET_DESCRIPTOR | RH_CLASS:
 		root_hub_hub_des[2] = hc->rh.numports;
-		len = min(unsigned int, leni, min(unsigned int, sizeof (root_hub_hub_des), wLength));
+		len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_hub_des), wLength));
 		memcpy (data, root_hub_hub_des, len);
 		OK (len);
 		
diff -u --recursive --new-file v2.4.9/linux/arch/cris/kernel/process.c linux/arch/cris/kernel/process.c
--- v2.4.9/linux/arch/cris/kernel/process.c	Sun Aug 12 13:27:58 2001
+++ linux/arch/cris/kernel/process.c	Mon Sep 17 15:29:09 2001
@@ -65,7 +65,6 @@
  * setup.
  */
 
-static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
diff -u --recursive --new-file v2.4.9/linux/arch/cris/kernel/ptrace.c linux/arch/cris/kernel/ptrace.c
--- v2.4.9/linux/arch/cris/kernel/ptrace.c	Sun Aug 12 13:27:58 2001
+++ linux/arch/cris/kernel/ptrace.c	Tue Sep 18 17:03:51 2001
@@ -82,6 +82,16 @@
 	return 0;
 }
 
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	/* Todo - pending singlesteps? */
+}
+
 /* Note that this implementation of ptrace behaves differently from vanilla
  * ptrace.  Contrary to what the man page says, in the PTRACE_PEEKTEXT,
  * PTRACE_PEEKDATA, and PTRACE_PEEKUSER requests the data variable is not
@@ -245,24 +255,9 @@
 			break;
 		}
 
-		case PTRACE_DETACH: { /* detach a process that was attached. */
-			long tmp;
-
-			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
-				break;
-			child->ptrace &= ~(PT_PTRACED | PT_TRACESYS);
-			child->exit_code = data;
-			write_lock_irq(&tasklist_lock);
-			REMOVE_LINKS(child);
-			child->p_pptr = child->p_opptr;
-			SET_LINKS(child);
-			write_unlock_irq(&tasklist_lock);
-			/* TODO: make sure any pending breakpoint is killed */
-			wake_up_process(child);
-			ret = 0;
+		case PTRACE_DETACH:
+			ret = ptrace_detach(child, data);
 			break;
-		}
 
 		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
 		  	int i;
diff -u --recursive --new-file v2.4.9/linux/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S
--- v2.4.9/linux/arch/i386/boot/bootsect.S	Mon Jan 29 16:19:41 2001
+++ linux/arch/i386/boot/bootsect.S	Fri Sep 14 14:04:08 2001
@@ -5,8 +5,12 @@
  *	modified by Bruce Evans (bde)
  *	modified by Chris Noe (May 1999) (as86 -> gas)
  *
- * bootsect is loaded at 0x7c00 by the bios-startup routines, and moves
- * itself out of the way to address 0x90000, and jumps there.
+ * 360k/720k disk support: Andrzej Krzysztofowicz <ankry@green.mif.pg.gda.pl>
+ *
+ * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
+ * addresses must be multiplied by 16 to obtain their respective linear
+ * addresses. To avoid confusion, linear addresses are written using leading
+ * hex while segment addresses are written as segment:offset.
  *
  * bde - should not jump blindly, there may be systems with only 512K low
  * memory.  Use int 0x12 to get the top of memory, etc.
@@ -43,7 +47,7 @@
 
 #ifndef RAMDISK
 #define RAMDISK 0
-#endif 
+#endif
 
 #ifndef ROOT_RDONLY
 #define ROOT_RDONLY 1
@@ -55,14 +59,12 @@
 .global _start
 _start:
 
-#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
-	int	$0x3
-#endif
+# First things first. Move ourself from 0x7C00 -> 0x90000 and jump there.
 
 	movw	$BOOTSEG, %ax
-	movw	%ax, %ds
+	movw	%ax, %ds		# %ds = BOOTSEG
 	movw	$INITSEG, %ax
-	movw	%ax, %es
+	movw	%ax, %es		# %ax = %es = INITSEG
 	movw	$256, %cx
 	subw	%si, %si
 	subw	%di, %di
@@ -81,7 +83,7 @@
 					# length of bootsect + length of
 					# setup + room for stack;
 					# 12 is disk parm size.
-	movw	%ax, %ds		# ax and es already contain INITSEG
+	movw	%ax, %ds		# %ax and %es already contain INITSEG
 	movw	%ax, %ss
 	movw	%di, %sp		# put stack at INITSEG:0x4000-12.
 
@@ -97,52 +99,29 @@
 #
 # High doesn't hurt.  Low does.
 #
-# Segments are as follows: ds = es = ss = cs - INITSEG, fs = 0,
-# and gs is unused.
+# Segments are as follows: %cs = %ds = %es = %ss = INITSEG, %fs = 0,
+# and %gs is unused.
 
-	movw	%cx, %fs		# set fs to 0
-	movw	$0x78, %bx		# fs:bx is parameter table address
+	movw	%cx, %fs		# %fs = 0
+	movw	$0x78, %bx		# %fs:%bx is parameter table address
 	pushw	%ds
-	ldsw	%fs:(%bx), %si		# ds:si is source
+	ldsw	%fs:(%bx), %si		# %ds:%si is source
 	movb	$6, %cl			# copy 12 bytes
-	pushw	%di			# di = 0x4000-12.
-	rep				# don't need cld -> done on line 66
-	movsw
+	pushw	%di			# %di = 0x4000-12.
+	rep				# don't worry about cld
+	movsw				# already done above
 	popw	%di
 	popw	%ds
 	movb	$36, 0x4(%di)		# patch sector count
 	movw	%di, %fs:(%bx)
 	movw	%es, %fs:2(%bx)
 
-# Load the setup-sectors directly after the bootblock.
-# Note that 'es' is already set up.
-# Also, cx = 0 from rep movsw above.
-
-load_setup:
-	xorb	%ah, %ah		# reset FDC 
-	xorb	%dl, %dl
-	int 	$0x13	
-	xorw	%dx, %dx		# drive 0, head 0
-	movb	$0x02, %cl		# sector 2, track 0
-	movw	$0x0200, %bx		# address = 512, in INITSEG
-	movb	$0x02, %ah		# service 2, "read sector(s)"
-	movb	setup_sects, %al	# (assume all on head 0, track 0)
-	int	$0x13			# read it
-	jnc	ok_load_setup		# ok - continue
-
-	pushw	%ax			# dump error code
-	call	print_nl
-	movw	%sp, %bp
-	call	print_hex
-	popw	%ax	
-	jmp	load_setup
-
-ok_load_setup:
 # Get disk drive parameters, specifically number of sectors/track.
 
 # It seems that there is no BIOS call to get the number of sectors.
 # Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18
 # can be read, 15 if sector 15 can be read.  Otherwise guess 9.
+# Note that %cx = 0 from rep movsw above.
 
 	movw	$disksizes, %si		# table of sizes to try
 probe_loop:
@@ -151,30 +130,56 @@
 	movw	%ax, sectors
 	cmpw	$disksizes+4, %si
 	jae	got_sectors		# If all else fails, try 9
-	
-	xchgw	%cx, %ax		# cx = track and sector
+
+	xchgw	%cx, %ax		# %cx = track and sector
 	xorw	%dx, %dx		# drive 0, head 0
-	xorb	%bl, %bl
-	movb	setup_sects, %bh
-	incb	%bh
-	shlb	%bh			# address after setup (es = cs) 
+	movw	$0x0200, %bx		# address = 512, in INITSEG (%es = %cs)
 	movw	$0x0201, %ax		# service 2, 1 sector
 	int	$0x13
 	jc	probe_loop		# try next value
 
 got_sectors:
-	movw	$INITSEG, %ax
-	movw	%ax, %es		# set up es
 	movb	$0x03, %ah		# read cursor pos
 	xorb	%bh, %bh
 	int	$0x10
 	movw	$9, %cx
-	movw	$0x0007, %bx		# page 0, attribute 7 (normal)
-	movw    $msg1, %bp
-	movw    $0x1301, %ax		# write string, move cursor
+	movb	$0x07, %bl		# page 0, attribute 7 (normal)
+					# %bh is set above; int10 doesn't
+					# modify it
+	movw	$msg1, %bp
+	movw	$0x1301, %ax		# write string, move cursor
 	int	$0x10			# tell the user we're loading..
-	movw	$SYSSEG, %ax		# ok, we've written the message, now
-	movw	%ax, %es		# we want to load system (at 0x10000)
+
+# Load the setup-sectors directly after the moved bootblock (at 0x90200).
+# We should know the drive geometry to do it, as setup may exceed first
+# cylinder (for 9-sector 360K and 720K floppies).
+
+	movw	$0x0001, %ax		# set sread (sector-to-read) to 1 as
+	movw	$sread, %si		# the boot sector has already been read
+	movw	%ax, (%si)
+
+	xorw	%ax, %ax		# reset FDC
+	xorb	%dl, %dl
+	int	$0x13
+	movw	$0x0200, %bx		# address = 512, in INITSEG
+next_step:
+	movb	setup_sects, %al
+	movw	sectors, %cx
+	subw	(%si), %cx		# (%si) = sread
+	cmpb	%cl, %al
+	jbe	no_cyl_crossing
+	movw	sectors, %ax
+	subw	(%si), %ax		# (%si) = sread
+no_cyl_crossing:
+	call	read_track
+	pushw	%ax			# save it
+	call	set_next		# set %bx properly; it uses %ax,%cx,%dx
+	popw	%ax			# restore
+	subb	%al, setup_sects	# rest - for next step
+	jnz	next_step
+
+	pushw	$SYSSEG
+	popw	%es			# %es = SYSSEG
 	call	read_it
 	call	kill_motor
 	call	print_nl
@@ -184,23 +189,26 @@
 # Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8)
 # depending on the number of sectors we pretend to know we have.
 
+# Segments are as follows: %cs = %ds = %ss = INITSEG,
+#	%es = SYSSEG, %fs = 0, %gs is unused.
+
 	movw	root_dev, %ax
 	orw	%ax, %ax
 	jne	root_defined
-	
+
 	movw	sectors, %bx
 	movw	$0x0208, %ax		# /dev/ps0 - 1.2Mb
 	cmpw	$15, %bx
 	je	root_defined
-	
+
 	movb	$0x1c, %al		# /dev/PS0 - 1.44Mb
 	cmpw	$18, %bx
 	je	root_defined
-	
+
 	movb	$0x20, %al		# /dev/fd0H2880 - 2.88Mb
 	cmpw	$36, %bx
 	je	root_defined
-	
+
 	movb	$0, %al			# /dev/fd0 - autodetect
 root_defined:
 	movw	%ax, root_dev
@@ -210,46 +218,45 @@
 
 	ljmp	$SETUPSEG, $0
 
-# This routine loads the system at address 0x10000, making sure
-# no 64kB boundaries are crossed. We try to load it as fast as
-# possible, loading whole tracks whenever we can.
-
-# es = starting address segment (normally 0x1000)
+# These variables are addressed via %si register as it gives shorter code.
 
 sread:	.word 0				# sectors read of current track
 head:	.word 0				# current head
 track:	.word 0				# current track
 
+# This routine loads the system at address SYSSEG, making sure
+# no 64kB boundaries are crossed. We try to load it as fast as
+# possible, loading whole tracks whenever we can.
+
 read_it:
-	movb	setup_sects, %al
-	incb	%al
-	movb	%al, sread
-	movw	%es, %ax
+	movw	%es, %ax		# %es = SYSSEG when called
 	testw	$0x0fff, %ax
-die:	jne	die			# es must be at 64kB boundary
-
-	xorw	%bx, %bx		# bx is starting address within segment
+die:	jne	die			# %es must be at 64kB boundary
+	xorw	%bx, %bx		# %bx is starting address within segment
 rp_read:
-#ifdef __BIG_KERNEL__
-	bootsect_kludge = 0x220		# 0x200 (size of bootsector) + 0x20 (offset
-	lcall	bootsect_kludge		# of bootsect_kludge in setup.S)
+#ifdef __BIG_KERNEL__			# look in setup.S for bootsect_kludge
+	bootsect_kludge = 0x220		# 0x200 + 0x20 which is the size of the
+	lcall	bootsect_kludge		# bootsector + bootsect_kludge offset
 #else
 	movw	%es, %ax
 	subw	$SYSSEG, %ax
+	movw	%bx, %cx
+	shr	$4, %cx
+	add	%cx, %ax		# check offset
 #endif
-	cmpw	syssize, %ax		# have we loaded all yet?
+	cmpw	syssize, %ax		# have we loaded everything yet?
 	jbe	ok1_read
 
 	ret
 
 ok1_read:
 	movw	sectors, %ax
-	subw	sread, %ax
+	subw	(%si), %ax		# (%si) = sread
 	movw	%ax, %cx
 	shlw	$9, %cx
 	addw	%bx, %cx
 	jnc	ok2_read
-	
+
 	je	ok2_read
 
 	xorw	%ax, %ax
@@ -257,60 +264,64 @@
 	shrw	$9, %ax
 ok2_read:
 	call	read_track
-	movw	%ax, %cx
-	addw	sread, %ax
-	cmpw	sectors, %ax
-	jne	ok3_read
-	
-	movw	$1, %ax
-	subw	head, %ax
-	jne	ok4_read
-	
-	incw	track
-ok4_read:
-	movw	%ax, head
-	xorw	%ax, %ax
-ok3_read:
-	movw	%ax, sread
-	shlw	$9, %cx
-	addw	%cx, %bx
-	jnc	rp_read
-	
-	movw	%es, %ax
-	addb	$0x10, %ah
-	movw	%ax, %es
-	xorw	%bx, %bx
+	call	set_next
 	jmp	rp_read
 
 read_track:
 	pusha
 	pusha	
-	movw	$0xe2e, %ax 			# loading... message 2e = .
+	movw	$0xe2e, %ax 		# loading... message 2e = .
 	movw	$7, %bx
  	int	$0x10
 	popa		
-	movw	track, %dx
-	movw	sread, %cx
+
+# Accessing head, track, sread via %si gives shorter code.
+
+	movw	4(%si), %dx		# 4(%si) = track
+	movw	(%si), %cx		# (%si)  = sread
 	incw	%cx
 	movb	%dl, %ch
-	movw	head, %dx
+	movw	2(%si), %dx		# 2(%si) = head
 	movb	%dl, %dh
 	andw	$0x0100, %dx
 	movb	$2, %ah
-	pushw	%dx				# save for error dump
+	pushw	%dx			# save for error dump
 	pushw	%cx
 	pushw	%bx
 	pushw	%ax
 	int	$0x13
 	jc	bad_rt
-	
+
 	addw	$8, %sp
 	popa
 	ret
 
+set_next:
+	movw	%ax, %cx
+	addw	(%si), %ax		# (%si) = sread
+	cmp	sectors, %ax
+	jne	ok3_set
+	movw	$0x0001, %ax
+	xorw	%ax, 2(%si)		# change head
+	jne	ok4_set
+	incw	4(%si)			# next track
+ok4_set:
+	xorw	%ax, %ax
+ok3_set:
+	movw	%ax, (%si)		# set sread
+	shlw	$9, %cx
+	addw	%cx, %bx
+	jnc	set_next_fin
+	movw	%es, %ax
+	addb	$0x10, %ah
+	movw	%ax, %es
+	xorw	%bx, %bx
+set_next_fin:
+	ret
+
 bad_rt:
-	pushw	%ax				# save error code
-	call	print_all			# ah = error, al = read
+	pushw	%ax			# save error code
+	call	print_all		# %ah = error, %al = read
 	xorb	%ah, %ah
 	xorb	%dl, %dl
 	int	$0x13
@@ -331,13 +342,13 @@
 #	ret <- %sp
  
 print_all:
-	movw	$5, %cx				# error code + 4 registers
+	movw	$5, %cx			# error code + 4 registers
 	movw	%sp, %bp
 print_loop:
-	pushw	%cx				# save count left
-	call	print_nl			# nl for readability
+	pushw	%cx			# save count remaining
+	call	print_nl		# <-- for readability
 	cmpb	$5, %cl
-	jae	no_reg				# see if register name is needed
+	jae	no_reg			# see if register name is needed
 	
 	movw	$0xe05 + 'A' - 1, %ax
 	subb	%cl, %al
@@ -347,31 +358,31 @@
 	movb	$':', %al
 	int	$0x10
 no_reg:
-	addw	$2, %bp				# next register
-	call	print_hex			# print it
+	addw	$2, %bp			# next register
+	call	print_hex		# print it
 	popw	%cx
 	loop	print_loop
 	ret
 
 print_nl:
-	movw	$0xe0d, %ax			# CR
+	movw	$0xe0d, %ax		# CR
 	int	$0x10
-	movb	$0xa, %al			# LF
+	movb	$0xa, %al		# LF
 	int 	$0x10
 	ret
 
 # print_hex is for debugging purposes, and prints the word
-# pointed to by ss:bp in hexadecimal.
+# pointed to by %ss:%bp in hexadecimal.
 
 print_hex:
-	movw	$4, %cx				# 4 hex digits
-	movw	(%bp), %dx			# load word into dx
+	movw	$4, %cx			# 4 hex digits
+	movw	(%bp), %dx		# load word into %dx
 print_digit:
-	rolw	$4, %dx				# rotate to use low 4 bits
-	movw	$0xe0f, %ax			# ah = request
-	andb	%dl, %al			# al = mask for nybble
-	addb	$0x90, %al			# convert al to ascii hex
-	daa					# in only four instructions!
+	rolw	$4, %dx			# rotate to use low 4 bits
+	movw	$0xe0f, %ax		# %ah = request
+	andb	%dl, %al		# %al = mask for nybble
+	addb	$0x90, %al		# convert %al to ascii hex
+	daa				# in only four instructions!
 	adc	$0x40, %al
 	daa
 	int	$0x10
@@ -381,6 +392,7 @@
 # This procedure turns off the floppy drive motor, so
 # that we enter the kernel in a known state, and
 # don't have to worry about it later.
+# NOTE: Doesn't save %ax or %dx; do it yourself if you need to.
 
 kill_motor:
 	movw	$0x3f2, %dx
diff -u --recursive --new-file v2.4.9/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile
--- v2.4.9/linux/arch/i386/boot/compressed/Makefile	Tue Mar  7 11:04:12 2000
+++ linux/arch/i386/boot/compressed/Makefile	Tue Sep 11 23:08:12 2001
@@ -9,7 +9,6 @@
 
 OBJECTS = $(HEAD) misc.o
 
-CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS
 ZLDFLAGS = -e startup_32
 
 #
diff -u --recursive --new-file v2.4.9/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c
--- v2.4.9/linux/arch/i386/boot/compressed/misc.c	Tue Feb 13 13:15:04 2001
+++ linux/arch/i386/boot/compressed/misc.c	Tue Sep 11 23:02:02 2001
@@ -12,6 +12,7 @@
 #include <linux/vmalloc.h>
 #include <linux/tty.h>
 #include <asm/io.h>
+
 /*
  * gzip declarations
  */
@@ -21,6 +22,14 @@
 
 #undef memset
 #undef memcpy
+
+/*
+ * Why do we do this? Don't ask me..
+ *
+ * Incomprehensible are the ways of bootloaders.
+ */
+static void* memset(void *, int, size_t);
+static void* memcpy(void *, __const void *, size_t);
 #define memzero(s, n)     memset ((s), 0, (n))
 
 typedef unsigned char  uch;
@@ -194,7 +203,7 @@
 	outb_p(0xff & (pos >> 1), vidport+1);
 }
 
-void* memset(void* s, int c, size_t n)
+static void* memset(void* s, int c, size_t n)
 {
 	int i;
 	char *ss = (char*)s;
@@ -203,7 +212,7 @@
 	return s;
 }
 
-void* memcpy(void* __dest, __const void* __src,
+static void* memcpy(void* __dest, __const void* __src,
 			    size_t __n)
 {
 	int i;
diff -u --recursive --new-file v2.4.9/linux/arch/i386/boot/install.sh linux/arch/i386/boot/install.sh
--- v2.4.9/linux/arch/i386/boot/install.sh	Tue Jan  3 03:57:26 1995
+++ linux/arch/i386/boot/install.sh	Fri Sep 14 14:04:06 2001
@@ -21,6 +21,7 @@
 
 # User may have a custom install script
 
+if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
 if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
 
 # Default install - same as make zlilo
diff -u --recursive --new-file v2.4.9/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.4.9/linux/arch/i386/config.in	Wed Jul 25 17:10:17 2001
+++ linux/arch/i386/config.in	Mon Sep 17 22:52:35 2001
@@ -186,7 +186,10 @@
 comment 'General setup'
 
 bool 'Networking support' CONFIG_NET
-bool 'SGI Visual Workstation support' CONFIG_VISWS
+
+# Visual Workstation support is utterly broken.
+# If you want to see it working mail an VW540 to hch@infradead.org 8)
+#bool 'SGI Visual Workstation support' CONFIG_VISWS
 if [ "$CONFIG_VISWS" = "y" ]; then
    define_bool CONFIG_X86_VISWS_APIC y
    define_bool CONFIG_X86_LOCAL_APIC y
@@ -388,6 +391,13 @@
 mainmenu_option next_comment
 comment 'Kernel hacking'
 
-#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
-bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
+if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
+   bool '  Debug memory allocations' CONFIG_DEBUG_SLAB
+   bool '  Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
+   bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
+   bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+   bool '  Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE
+fi
+
 endmenu
diff -u --recursive --new-file v2.4.9/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.4.9/linux/arch/i386/defconfig	Mon Aug 27 12:41:39 2001
+++ linux/arch/i386/defconfig	Tue Sep 18 11:15:11 2001
@@ -65,7 +65,6 @@
 # General setup
 #
 CONFIG_NET=y
-# CONFIG_VISWS is not set
 CONFIG_X86_IO_APIC=y
 CONFIG_X86_LOCAL_APIC=y
 CONFIG_PCI=y
@@ -136,6 +135,7 @@
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
 # CONFIG_BLK_DEV_LVM is not set
 
 #
@@ -175,6 +175,7 @@
 #
 # CONFIG_PHONE is not set
 # CONFIG_PHONE_IXJ is not set
+# CONFIG_PHONE_IXJ_PCMCIA is not set
 
 #
 # ATA/IDE/MFM/RLL support
@@ -253,6 +254,9 @@
 # CONFIG_IDEDMA_IVB is not set
 # CONFIG_DMA_NONPCI is not set
 CONFIG_BLK_DEV_IDE_MODES=y
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
 
 #
 # SCSI support
@@ -288,6 +292,7 @@
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -306,6 +311,7 @@
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR_D700 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_NCR53C8XX is not set
 CONFIG_SCSI_SYM53C8XX=y
@@ -374,7 +380,6 @@
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_ARM_AM79C961A is not set
 # CONFIG_SUNLANCE is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNBMAC is not set
@@ -396,8 +401,6 @@
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
 # CONFIG_TULIP is not set
-# CONFIG_TULIP_MWI is not set
-# CONFIG_TULIP_MMIO is not set
 # CONFIG_DE4X5 is not set
 # CONFIG_DGRS is not set
 # CONFIG_DM9102 is not set
@@ -424,9 +427,9 @@
 # Ethernet (1000 Mbit)
 #
 # CONFIG_ACENIC is not set
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
 # CONFIG_DL2K is not set
 # CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
@@ -464,6 +467,7 @@
 # CONFIG_PCMCIA_XIRC2PS is not set
 # CONFIG_ARCNET_COM20020_CS is not set
 # CONFIG_PCMCIA_IBMTR is not set
+# CONFIG_PCMCIA_XIRCOM is not set
 # CONFIG_PCMCIA_XIRTULIP is not set
 CONFIG_NET_PCMCIA_RADIO=y
 CONFIG_PCMCIA_RAYCS=y
@@ -495,6 +499,10 @@
 # Input core support
 #
 # CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
 
 #
 # Character devices
@@ -525,7 +533,11 @@
 #
 # Joysticks
 #
-# CONFIG_JOYSTICK is not set
+# CONFIG_INPUT_GAMEPORT is not set
+
+#
+# Input core support is needed for gameports
+#
 
 #
 # Input core support is needed for joysticks
@@ -705,6 +717,7 @@
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
 # CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
@@ -738,10 +751,10 @@
 #
 # USB Network adaptors
 #
-# CONFIG_USB_PLUSB is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_CATC is not set
-# CONFIG_USB_NET1080 is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_USBNET is not set
 
 #
 # USB port drivers
@@ -761,4 +774,4 @@
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.4.9/linux/arch/i386/kernel/Makefile	Fri Dec 29 14:35:47 2000
+++ linux/arch/i386/kernel/Makefile	Mon Sep 17 23:03:09 2001
@@ -30,15 +30,15 @@
 endif
 endif
 
-obj-$(CONFIG_MCA)	+= mca.o
-obj-$(CONFIG_MTRR)	+= mtrr.o
-obj-$(CONFIG_X86_MSR)	+= msr.o
-obj-$(CONFIG_X86_CPUID)	+= cpuid.o
-obj-$(CONFIG_MICROCODE)	+= microcode.o
-obj-$(CONFIG_APM)	+= apm.o
-obj-$(CONFIG_SMP)	+= smp.o smpboot.o trampoline.o
-obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o
-obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o
+obj-$(CONFIG_MCA)		+= mca.o
+obj-$(CONFIG_MTRR)		+= mtrr.o
+obj-$(CONFIG_X86_MSR)		+= msr.o
+obj-$(CONFIG_X86_CPUID)		+= cpuid.o
+obj-$(CONFIG_MICROCODE)		+= microcode.o
+obj-$(CONFIG_APM)		+= apm.o
+obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
+obj-$(CONFIG_X86_LOCAL_APIC)	+= mpparse.o apic.o nmi.o
+obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
 obj-$(CONFIG_X86_VISWS_APIC)	+= visws_apic.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c
--- v2.4.9/linux/arch/i386/kernel/apic.c	Tue Jul  3 17:08:18 2001
+++ linux/arch/i386/kernel/apic.c	Mon Sep 17 23:03:09 2001
@@ -9,6 +9,7 @@
  *					and Rolf G. Tews
  *					for testing these extensively.
  *	Maciej W. Rozycki	:	Various updates and fixes.
+ *	Mikael Pettersson	:	Power Management for UP-APIC.
  */
 
 #include <linux/config.h>
@@ -29,6 +30,9 @@
 #include <asm/mpspec.h>
 #include <asm/pgalloc.h>
 
+/* Using APIC to generate smp_local_timer_interrupt? */
+int using_apic_timer = 0;
+
 int prof_multiplier[NR_CPUS] = { 1, };
 int prof_old_multiplier[NR_CPUS] = { 1, };
 int prof_counter[NR_CPUS] = { 1, };
@@ -90,10 +94,10 @@
 		 */
 		clear_local_APIC();
 		/*
-		 * PIC mode, enable symmetric IO mode in the IMCR,
-		 * i.e. connect BSP's local APIC to INT and NMI lines.
+		 * PIC mode, enable APIC mode in the IMCR, i.e.
+		 * connect BSP's local APIC to INT and NMI lines.
 		 */
-		printk("leaving PIC mode, enabling symmetric IO mode.\n");
+		printk("leaving PIC mode, enabling APIC mode.\n");
 		outb(0x70, 0x22);
 		outb(0x01, 0x23);
 	}
@@ -108,7 +112,7 @@
 		 * interrupts, including IPIs, won't work beyond
 		 * this point!  The only exception are INIT IPIs.
 		 */
-		printk("disabling symmetric IO mode, entering PIC mode.\n");
+		printk("disabling APIC mode, entering PIC mode.\n");
 		outb(0x70, 0x22);
 		outb(0x00, 0x23);
 	}
@@ -125,7 +129,7 @@
 	 * for 82489DX!).
 	 */
 	value = apic_read(APIC_SPIV);
-	value &= ~(1<<8);
+	value &= ~APIC_SPIV_APIC_ENABLED;
 	apic_write_around(APIC_SPIV, value);
 }
 
@@ -204,6 +208,48 @@
 
 extern void __error_in_apic_c (void);
 
+/*
+ * An initial setup of the virtual wire mode.
+ */
+void __init init_bsp_APIC(void)
+{
+	unsigned long value, ver;
+
+	/*
+	 * Don't do the setup now if we have a SMP BIOS as the
+	 * through-I/O-APIC virtual wire mode might be active.
+	 */
+	if (smp_found_config || !cpu_has_apic)
+		return;
+
+	value = apic_read(APIC_LVR);
+	ver = GET_APIC_VERSION(value);
+
+	/*
+	 * Do not trust the local APIC being empty at bootup.
+	 */
+	clear_local_APIC();
+
+	/*
+	 * Enable APIC.
+	 */
+	value = apic_read(APIC_SPIV);
+	value &= ~APIC_VECTOR_MASK;
+	value |= APIC_SPIV_APIC_ENABLED;
+	value |= APIC_SPIV_FOCUS_DISABLED;
+	value |= SPURIOUS_APIC_VECTOR;
+	apic_write_around(APIC_SPIV, value);
+
+	/*
+	 * Set up the virtual wire mode.
+	 */
+	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
+	value = APIC_DM_NMI;
+	if (!APIC_INTEGRATED(ver))		/* 82489DX */
+		value |= APIC_LVT_LEVEL_TRIGGER;
+	apic_write_around(APIC_LVT1, value);
+}
+
 void __init setup_local_APIC (void)
 {
 	unsigned long value, ver, maxlvt;
@@ -256,7 +302,7 @@
 	/*
 	 * Enable APIC
 	 */
-	value |= (1<<8);
+	value |= APIC_SPIV_APIC_ENABLED;
 
 	/*
 	 * Some unknown Intel IO/APIC (or APIC) errata is biting us with
@@ -279,10 +325,10 @@
 	 */
 #if 1
 	/* Enable focus processor (bit==0) */
-	value &= ~(1<<9);
+	value &= ~APIC_SPIV_FOCUS_DISABLED;
 #else
 	/* Disable focus processor (bit==1) */
-	value |= (1<<9);
+	value |= APIC_SPIV_FOCUS_DISABLED;
 #endif
 	/*
 	 * Set spurious IRQ vector
@@ -339,24 +385,250 @@
 		printk("ESR value after enabling vector: %08lx\n", value);
 	} else
 		printk("No ESR for 82489DX.\n");
+
+	if (nmi_watchdog == NMI_LOCAL_APIC)
+		setup_apic_nmi_watchdog();
 }
 
-void __init init_apic_mappings(void)
+#ifdef CONFIG_PM
+
+#include <linux/slab.h>
+#include <linux/pm.h>
+
+static struct {
+	/* 'active' is true if the local APIC was enabled by us and
+	   not the BIOS; this signifies that we are also responsible
+	   for disabling it before entering apm/acpi suspend */
+	int active;
+	/* 'perfctr_pmdev' is here because the current (2.4.1) PM
+	   callback system doesn't handle hierarchical dependencies */
+	struct pm_dev *perfctr_pmdev;
+	/* r/w apic fields */
+	unsigned int apic_id;
+	unsigned int apic_taskpri;
+	unsigned int apic_ldr;
+	unsigned int apic_dfr;
+	unsigned int apic_spiv;
+	unsigned int apic_lvtt;
+	unsigned int apic_lvtpc;
+	unsigned int apic_lvt0;
+	unsigned int apic_lvt1;
+	unsigned int apic_lvterr;
+	unsigned int apic_tmict;
+	unsigned int apic_tdcr;
+} apic_pm_state;
+
+static void apic_pm_suspend(void *data)
 {
-	unsigned long apic_phys;
+	unsigned int l, h;
+	unsigned long flags;
 
-	if (smp_found_config) {
-		apic_phys = mp_lapic_addr;
-	} else {
+	if (apic_pm_state.perfctr_pmdev)
+		pm_send(apic_pm_state.perfctr_pmdev, PM_SUSPEND, data);
+	apic_pm_state.apic_id = apic_read(APIC_ID);
+	apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
+	apic_pm_state.apic_ldr = apic_read(APIC_LDR);
+	apic_pm_state.apic_dfr = apic_read(APIC_DFR);
+	apic_pm_state.apic_spiv = apic_read(APIC_SPIV);
+	apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);
+	apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
+	apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);
+	apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);
+	apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
+	apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
+	apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
+	__save_flags(flags);
+	__cli();
+	disable_local_APIC();
+	rdmsr(MSR_IA32_APICBASE, l, h);
+	l &= ~MSR_IA32_APICBASE_ENABLE;
+	wrmsr(MSR_IA32_APICBASE, l, h);
+	__restore_flags(flags);
+}
+
+static void apic_pm_resume(void *data)
+{
+	unsigned int l, h;
+	unsigned long flags;
+
+	__save_flags(flags);
+	__cli();
+	rdmsr(MSR_IA32_APICBASE, l, h);
+	l &= ~MSR_IA32_APICBASE_BASE;
+	l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+	wrmsr(MSR_IA32_APICBASE, l, h);
+	apic_write(APIC_ID, apic_pm_state.apic_id);
+	apic_write(APIC_DFR, apic_pm_state.apic_dfr);
+	apic_write(APIC_LDR, apic_pm_state.apic_ldr);
+	apic_write(APIC_TASKPRI, apic_pm_state.apic_taskpri);
+	apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
+	apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
+	apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
+	apic_write(APIC_ESR, 0);
+	apic_read(APIC_ESR);
+	apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr);
+	apic_write(APIC_ESR, 0);
+	apic_read(APIC_ESR);
+	apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
+	apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
+	apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
+	apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
+	__restore_flags(flags);
+	if (apic_pm_state.perfctr_pmdev)
+		pm_send(apic_pm_state.perfctr_pmdev, PM_RESUME, data);
+}
+
+static int apic_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+	switch (rqst) {
+	case PM_SUSPEND:
+		apic_pm_suspend(data);
+		break;
+	case PM_RESUME:
+		apic_pm_resume(data);
+		break;
+	}
+	return 0;
+}
+
+/* perfctr driver should call this instead of pm_register() */
+struct pm_dev *apic_pm_register(pm_dev_t type,
+				unsigned long id,
+				pm_callback callback)
+{
+	struct pm_dev *dev;
+
+	if (!apic_pm_state.active)
+		return pm_register(type, id, callback);
+	if (apic_pm_state.perfctr_pmdev)
+		return NULL;	/* we're busy */
+	dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL);
+	if (dev) {
+		memset(dev, 0, sizeof(*dev));
+		dev->type = type;
+		dev->id = id;
+		dev->callback = callback;
+		apic_pm_state.perfctr_pmdev = dev;
+	}
+	return dev;
+}
+
+/* perfctr driver should call this instead of pm_unregister() */
+void apic_pm_unregister(struct pm_dev *dev)
+{
+	if (!apic_pm_state.active) {
+		pm_unregister(dev);
+	} else if (dev == apic_pm_state.perfctr_pmdev) {
+		apic_pm_state.perfctr_pmdev = NULL;
+		kfree(dev);
+	}
+}
+
+static void __init apic_pm_init1(void)
+{
+	/* can't pm_register() at this early stage in the boot process
+	   (causes an immediate reboot), so just set the flag */
+	apic_pm_state.active = 1;
+}
+
+static void __init apic_pm_init2(void)
+{
+	if (apic_pm_state.active)
+		pm_register(PM_SYS_DEV, 0, apic_pm_callback);
+}
+
+#else	/* CONFIG_PM */
+
+static inline void apic_pm_init1(void) { }
+static inline void apic_pm_init2(void) { }
+
+#endif	/* CONFIG_PM */
+
+/*
+ * Detect and enable local APICs on non-SMP boards.
+ * Original code written by Keir Fraser.
+ */
+
+static int __init detect_init_APIC (void)
+{
+	u32 h, l, features;
+	int needs_pm = 0;
+	extern void get_cpu_vendor(struct cpuinfo_x86*);
+
+	/* Workaround for us being called before identify_cpu(). */
+	get_cpu_vendor(&boot_cpu_data);
+
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_AMD:
+		if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1)
+			break;
+		goto no_apic;
+	case X86_VENDOR_INTEL:
+		if (boot_cpu_data.x86 == 6 ||
+		    (boot_cpu_data.x86 == 5 && cpu_has_apic))
+			break;
+		goto no_apic;
+	default:
+		goto no_apic;
+	}
+
+	if (!cpu_has_apic) {
 		/*
-		 * set up a fake all zeroes page to simulate the
-		 * local APIC and another one for the IO-APIC. We
-		 * could use the real zero-page, but it's safer
-		 * this way if some buggy code writes to this page ...
+		 * Some BIOSes disable the local APIC in the
+		 * APIC_BASE MSR. This can only be done in
+		 * software for Intel P6 and AMD K7 (Model > 1).
 		 */
+		rdmsr(MSR_IA32_APICBASE, l, h);
+		if (!(l & MSR_IA32_APICBASE_ENABLE)) {
+			printk("Local APIC disabled by BIOS -- reenabling.\n");
+			l &= ~MSR_IA32_APICBASE_BASE;
+			l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+			wrmsr(MSR_IA32_APICBASE, l, h);
+			needs_pm = 1;
+		}
+	}
+	/*
+	 * The APIC feature bit should now be enabled
+	 * in `cpuid'
+	 */
+	features = cpuid_edx(1);
+	if (!(features & (1 << X86_FEATURE_APIC))) {
+		printk("Could not enable APIC!\n");
+		return -1;
+	}
+	set_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability);
+	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+	boot_cpu_id = 0;
+	if (nmi_watchdog != NMI_NONE)
+		nmi_watchdog = NMI_LOCAL_APIC;
+
+	printk("Found and enabled local APIC!\n");
+
+	if (needs_pm)
+		apic_pm_init1();
+
+	return 0;
+
+no_apic:
+	printk("No local APIC present or hardware disabled\n");
+	return -1;
+}
+
+void __init init_apic_mappings(void)
+{
+	unsigned long apic_phys;
+
+	/*
+	 * If no local APIC can be found then set up a fake all
+	 * zeroes page to simulate the local APIC and another
+	 * one for the IO-APIC.
+	 */
+	if (!smp_found_config && detect_init_APIC()) {
 		apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
 		apic_phys = __pa(apic_phys);
-	}
+	} else
+		apic_phys = mp_lapic_addr;
+
 	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
 	Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
 
@@ -603,6 +875,9 @@
 
 void __init setup_APIC_clocks (void)
 {
+	printk("Using local APIC timer interrupts.\n");
+	using_apic_timer = 1;
+
 	__cli();
 
 	calibration_result = calibrate_APIC_clock();
@@ -790,3 +1065,43 @@
 	        smp_processor_id(), v , v1);
 }
 
+/*
+ * This initializes the IO-APIC and APIC hardware if this is
+ * a UP kernel.
+ */
+int __init APIC_init_uniprocessor (void)
+{
+	if (!smp_found_config && !cpu_has_apic)
+		return -1;
+
+	/*
+	 * Complain if the BIOS pretends there is one.
+	 */
+	if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_id])) {
+		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+			boot_cpu_id);
+		return -1;
+	}
+
+	verify_local_APIC();
+
+	connect_bsp_APIC();
+
+	phys_cpu_present_map = 1;
+	apic_write_around(APIC_ID, boot_cpu_id);
+
+	apic_pm_init2();
+
+	setup_local_APIC();
+
+	if (nmi_watchdog == NMI_LOCAL_APIC)
+		check_nmi_watchdog();
+#ifdef CONFIG_X86_IO_APIC
+	if (smp_found_config)
+		if (!skip_ioapic_setup && nr_ioapics)
+			setup_IO_APIC();
+#endif
+	setup_APIC_clocks();
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.4.9/linux/arch/i386/kernel/apm.c	Mon Aug 27 12:41:39 2001
+++ linux/arch/i386/kernel/apm.c	Mon Sep 17 22:52:35 2001
@@ -148,6 +148,10 @@
  *   1.14: Make connection version persist across module unload/load.
  *         Enable and engage power management earlier.
  *         Disengage power management on module unload.
+ *         Changed to use the sysrq-register hack for registering the
+ *         power off function called by magic sysrq based upon discussions
+ *         in irc://irc.openprojects.net/#kernelnewbies
+ *         (Crutcher Dunnavant <crutcher+kernel@datastacks.com>).
  *         Make CONFIG_APM_REAL_MODE_POWER_OFF run time configurable.
  *         (Arjan van de Ven <arjanv@redhat.com>) modified by sfr.
  *         Work around byte swap bug in one of the Vaio's BIOS's
@@ -197,12 +201,11 @@
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 
+#include <linux/sysrq.h>
+
 extern unsigned long get_cmos_time(void);
 extern void machine_real_restart(unsigned char *, int);
 
-#ifdef CONFIG_MAGIC_SYSRQ
-extern void (*sysrq_power_off)(void);
-#endif
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
 extern int (*console_blank_hook)(int);
 #endif
@@ -686,6 +689,23 @@
 		(void) apm_set_power_state(APM_STATE_OFF);
 }
 
+#ifdef CONFIG_MAGIC_SYSRQ
+/*
+ * Magic sysrq key and handler for the power off function
+ */
+
+void handle_poweroff (int key, struct pt_regs *pt_regs,
+		                        struct kbd_struct *kbd, struct tty_struct *tty) {
+	        apm_power_off();
+}
+struct sysrq_key_op sysrq_poweroff_op = {
+	handler:        handle_poweroff,
+	help_msg:       "Off",
+	action_msg:     "Power Off\n"
+};
+#endif
+
+
 #ifdef CONFIG_APM_DO_ENABLE
 static int apm_enable_power_management(int enable)
 {
@@ -1544,9 +1564,8 @@
 	/* Install our power off handler.. */
 	if (power_off)
 		pm_power_off = apm_power_off;
-#ifdef CONFIG_MAGIC_SYSRQ
-	sysrq_power_off = apm_power_off;
-#endif
+	register_sysrq_key('o',&sysrq_poweroff_op);
+
 	if (smp_num_cpus == 1) {
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
 		console_blank_hook = apm_console_blank;
@@ -1761,9 +1780,7 @@
 	}
 	misc_deregister(&apm_device);
 	remove_proc_entry("apm", NULL);
-#ifdef CONFIG_MAGIC_SYSRQ
-	sysrq_power_off = NULL;
-#endif
+	unregister_sysrq_key('o',&sysrq_poweroff_op);
 	if (power_off)
 		pm_power_off = NULL;
 	exit_kapmd = 1;
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c
--- v2.4.9/linux/arch/i386/kernel/bluesmoke.c	Tue Jul  3 17:08:18 2001
+++ linux/arch/i386/kernel/bluesmoke.c	Sat Sep  8 12:23:14 2001
@@ -19,7 +19,7 @@
 	u32 mcgstl, mcgsth;
 	int i;
 	
-	rdmsr(0x17a, mcgstl, mcgsth);
+	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
 	if(mcgstl&(1<<0))	/* Recoverable ? */
 		recover=0;
 
@@ -27,7 +27,7 @@
 	
 	for(i=0;i<banks;i++)
 	{
-		rdmsr(0x401+i*4,low, high);
+		rdmsr(MSR_IA32_MC0_STATUS+i*4,low, high);
 		if(high&(1<<31))
 		{
 			if(high&(1<<29))
@@ -38,18 +38,18 @@
 			high&=~(1<<31);
 			if(high&(1<<27))
 			{
-				rdmsr(0x402+i*4, alow, ahigh);
+				rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
 				printk("[%08x%08x]", alow, ahigh);
 			}
 			if(high&(1<<26))
 			{
-				rdmsr(0x402+i*4, alow, ahigh);
+				rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
 				printk(" at %08x%08x", 
 					high, low);
 			}
 			printk("\n");
 			/* Clear it */
-			wrmsr(0x401+i*4, 0UL, 0UL);
+			wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
 			/* Serialize */
 			wmb();
 		}
@@ -61,7 +61,7 @@
 		panic("Unable to continue");
 	printk(KERN_EMERG "Attempting to continue.\n");
 	mcgstl&=~(1<<2);
-	wrmsr(0x17a,mcgstl, mcgsth);
+	wrmsr(MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
 }
 
 /*
@@ -71,8 +71,8 @@
 static void pentium_machine_check(struct pt_regs * regs, long error_code)
 {
 	u32 loaddr, hi, lotype;
-	rdmsr(0x0, loaddr, hi);
-	rdmsr(0x1, lotype, hi);
+	rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
+	rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
 	printk(KERN_EMERG "CPU#%d: Machine Check Exception:  0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
 	if(lotype&(1<<5))
 		printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
@@ -133,8 +133,8 @@
 		machine_check_vector = pentium_machine_check;
 		wmb();
 		/* Read registers before enabling */
-		rdmsr(0x0, l, h);
-		rdmsr(0x1, l, h);
+		rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
+		rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
 		if(done==0)
 			printk(KERN_INFO "Intel old style machine check architecture supported.\n");
 		/* Enable MCE */		
@@ -161,17 +161,17 @@
 	
 	if(done==0)
 		printk(KERN_INFO "Intel machine check architecture supported.\n");
-	rdmsr(0x179, l, h);
+	rdmsr(MSR_IA32_MCG_CAP, l, h);
 	if(l&(1<<8))
-		wrmsr(0x17b, 0xffffffff, 0xffffffff);
+		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
 	banks = l&0xff;
 	for(i=1;i<banks;i++)
 	{
-		wrmsr(0x400+4*i, 0xffffffff, 0xffffffff); 
+		wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
 	}
 	for(i=0;i<banks;i++)
 	{
-		wrmsr(0x401+4*i, 0x0, 0x0); 
+		wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
 	}
 	set_in_cr4(X86_CR4_MCE);
 	printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
@@ -191,10 +191,10 @@
 	/* Winchip C6 */
 	machine_check_vector = winchip_machine_check;
 	wmb();
-	rdmsr(0x107, lo, hi);
+	rdmsr(MSR_IDT_FCR1, lo, hi);
 	lo|= (1<<2);	/* Enable EIERRINT (int 18 MCE) */
 	lo&= ~(1<<4);	/* Enable MCE */
-	wrmsr(0x107, lo, hi);
+	wrmsr(MSR_IDT_FCR1, lo, hi);
 	__asm__ __volatile__ (
 		"movl %%cr4, %%eax\n\t"
 		"orl $0x40, %%eax\n\t"
@@ -236,6 +236,6 @@
 static int __init mcheck_disable(char *str)
 {
 	mce_disabled = 1;
-	return 1;
+	return 0;
 }
 __setup("nomce", mcheck_disable);
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/dmi_scan.c linux/arch/i386/kernel/dmi_scan.c
--- v2.4.9/linux/arch/i386/kernel/dmi_scan.c	Mon Aug 27 12:41:39 2001
+++ linux/arch/i386/kernel/dmi_scan.c	Mon Sep 17 22:52:35 2001
@@ -6,6 +6,9 @@
 #include <linux/apm_bios.h>
 #include <linux/slab.h>
 #include <asm/io.h>
+#include <linux/pm.h>
+#include <linux/keyboard.h>
+#include <asm/keyboard.h>
 
 struct dmi_header
 {
@@ -87,7 +90,15 @@
 	unsigned char buf[20];
 	long fp=0xE0000L;
 	fp -= 16;
-	
+
+#ifdef CONFIG_SIMNOW
+	/*
+ 	 *	Skip on x86/64 with simnow. Will eventually go away
+ 	 *	If you see this ifdef in 2.6pre mail me !
+ 	 */
+	return;
+#endif
+ 	
 	while( fp < 0xFFFFF)
 	{
 		fp+=16;
@@ -191,6 +202,11 @@
 }
 
 /* 
+ * Reboot options and system auto-detection code provided by
+ * Dell Computer Corporation so their systems "just work". :-)
+ */
+
+/* 
  * Some machines require the "reboot=b"  commandline option, this quirk makes that automatic.
  */
 static __init int set_bios_reboot(struct dmi_blacklist *d)
@@ -205,6 +221,32 @@
 }
 
 /*
+ * Some machines require the "reboot=s"  commandline option, this quirk makes that automatic.
+ */
+static __init int set_smp_reboot(struct dmi_blacklist *d)
+{
+#ifdef CONFIG_SMP
+	extern int reboot_smp;
+	if (reboot_smp == 0)
+	{
+		reboot_smp = 1;
+		printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
+	}
+#endif
+	return 0;
+}
+
+/*
+ * Some machines require the "reboot=b,s"  commandline option, this quirk makes that automatic.
+ */
+static __init int set_smp_bios_reboot(struct dmi_blacklist *d)
+{
+	set_smp_reboot(d);
+	set_bios_reboot(d);
+	return 0;
+}
+
+/*
  * Some bioses have a broken protected mode poweroff and need to use realmode
  */
 
@@ -271,6 +313,27 @@
 	return 0;
 }		
 
+#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE)
+/*
+ * Check for a Sony Vaio system in order to enable the use of
+ * the sonypi driver (we don't want this driver to be used on
+ * other systems, even if they have the good PCI IDs).
+ *
+ * This one isn't a bug detect for those who asked, we simply want to
+ * activate Sony specific goodies like the camera and jogdial..
+ */
+int is_sony_vaio_laptop;
+
+static __init int sony_vaio_laptop(struct dmi_blacklist *d)
+{
+	if (is_sony_vaio_laptop == 0)
+	{
+		is_sony_vaio_laptop = 1;
+		printk(KERN_INFO "%s laptop detected.\n", d->ident);
+	}
+	return 0;
+}
+#endif
 
 /*
  * This bios swaps the APM minute reporting bytes over (Many sony laptops
@@ -283,6 +346,46 @@
 	printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.\n");
 	return 0;
 }
+
+/*
+ * The Intel 440GX hall of shame. 
+ *
+ * On many (all we have checked) of these boxes the $PIRQ table is wrong.
+ * The MP1.4 table is right however and so SMP kernels tend to work. 
+ */
+ 
+static __init int broken_pirq(struct dmi_blacklist *d)
+{
+	printk(KERN_INFO " *** Possibly defective BIOS detected (irqtable)\n");
+	printk(KERN_INFO " *** Many BIOSes matching this signature have incorrect IRQ routing tables.\n");
+	printk(KERN_INFO " *** If you see IRQ problems, in paticular SCSI resets and hangs at boot\n");
+	printk(KERN_INFO " *** contact your vendor and ask about updates.\n");
+	printk(KERN_INFO " *** Building an SMP kernel may evade the bug some of the time.\n");
+	return 0;
+}
+
+/*
+ * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it
+ * was disabled before the suspend. Linux gets terribly confused by that.
+ */
+
+typedef void (pm_kbd_func) (void);
+extern pm_kbd_func *pm_kbd_request_override;
+
+static __init int broken_ps2_resume(struct dmi_blacklist *d)
+{
+#ifdef CONFIG_VT
+	if (pm_kbd_request_override == NULL)
+	{
+		pm_kbd_request_override = pckbd_pm_resume;
+		printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround enabled.\n", d->ident);
+	}
+#endif	
+	return 0;
+}
+
+
+
 /*
  *	Process the DMI blacklists
  */
@@ -300,6 +403,11 @@
 			NO_MATCH, NO_MATCH, NO_MATCH
 			} },
 #endif			
+	{ broken_ps2_resume, "Dell Latitude C600", {	/* Handle problems with APM on the C600 */
+		        MATCH(DMI_SYS_VENDOR, "Dell"),
+			MATCH(DMI_PRODUCT_NAME, "Latitude C600"),
+			NO_MATCH, NO_MATCH
+	                } },
 	{ broken_apm_power, "Dell Inspiron 5000e", {	/* Handle problems with APM on Inspiron 5000e */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 			MATCH(DMI_BIOS_VERSION, "A04"),
@@ -310,14 +418,14 @@
 			MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
 			MATCH(DMI_BIOS_DATE, "134526184"), NO_MATCH
 			} },
-	{ set_bios_reboot, "PowerEdge 1300/500", {	/* Handle problems with rebooting on Dell 1300's */
+	{ set_smp_bios_reboot, "Dell PowerEdge 1300", {	/* Handle problems with rebooting on Dell 1300's */
 			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/500"),
+			MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
 			NO_MATCH, NO_MATCH
 			} },
-	{ set_bios_reboot, "PowerEdge 1300/550", {	/* Handle problems with rebooting on Dell 1300's */
+	{ set_bios_reboot, "Dell PowerEdge 300", {	/* Handle problems with rebooting on Dell 1300's */
 			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/550"),
+			MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
 			NO_MATCH, NO_MATCH
 			} },
 	{ set_apm_ints, "IBM", {	/* Allow interrupts during suspend on IBM laptops */
@@ -329,6 +437,12 @@
 			MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
 			NO_MATCH, NO_MATCH
 			} },
+	{ set_apm_ints, "Compaq 12XL125", {	/* Allow interrupts during suspend on Compaq Laptops*/
+			MATCH(DMI_SYS_VENDOR, "Compaq"),
+			MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION,"4.06")
+			} },
 	{ set_apm_ints, "ASUSTeK", {   /* Allow interrupts during APM or the clock goes slow */
 			MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 			MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"),
@@ -339,21 +453,97 @@
 			MATCH(DMI_PRODUCT_NAME, "Delhi3"),
 			NO_MATCH, NO_MATCH,
 			} },
-	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
+	{ apm_is_horked, "Sharp PC-PJ/AX", { /* APM crashes */
+			MATCH(DMI_SYS_VENDOR, "SHARP"),
+			MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
+			MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
+			MATCH(DMI_BIOS_VERSION,"Version R2.08")
+			} },
+#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE)
+	{ sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */
+			MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+			MATCH(DMI_PRODUCT_NAME, "PCG-"),
+			NO_MATCH, NO_MATCH,
+			} },
+#endif
+	{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			MATCH(DMI_BIOS_VERSION, "R0203Z3"),
-			MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH
+			MATCH(DMI_BIOS_VERSION, "R0206H"),
+			MATCH(DMI_BIOS_DATE, "08/23/99"), NO_MATCH
+	} },
+
+	{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505VX */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "W2K06H0"),
+			MATCH(DMI_BIOS_DATE, "02/03/00"), NO_MATCH
 			} },
-	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
+			
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-XG29 */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			MATCH(DMI_BIOS_VERSION, "R0203D0"),
-			MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH
+			MATCH(DMI_BIOS_VERSION, "R0117A0"),
+			MATCH(DMI_BIOS_DATE, "04/25/00"), NO_MATCH
 			} },
+
 	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z600NE */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 			MATCH(DMI_BIOS_VERSION, "R0121Z1"),
 			MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
 			} },
+
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "R0203D0"),
+			MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH
+			} },
+
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "R0203Z3"),
+			MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH
+			} },
+	
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-F104K */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "R0204K2"),
+			MATCH(DMI_BIOS_DATE, "08/28/00"), NO_MATCH
+			} },
+	
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "R0208P1"),
+			MATCH(DMI_BIOS_DATE, "11/09/00"), NO_MATCH
+			} },
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-C1VE */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "R0204P1"),
+			MATCH(DMI_BIOS_DATE, "09/12/00"), NO_MATCH
+			} },
+
+	/* Problem Intel 440GX bioses */
+
+	{ broken_pirq, "SABR1 Bios", {			/* Bad $PIR */
+			MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
+			MATCH(DMI_BIOS_VERSION,"SABR1"),
+			NO_MATCH, NO_MATCH
+			} },
+	{ broken_pirq, "l44GX Bios", {        		/* Bad $PIR */
+			MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
+			MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0094.P10"),
+			NO_MATCH, NO_MATCH
+                        } },
+	{ broken_pirq, "l44GX Bios", {		/* Bad $PIR */
+			MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
+			MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0125.P13"),
+			NO_MATCH, NO_MATCH
+			} },
+                        
+	/* Intel in disgiuse - In this case they can't hide and they don't run
+	   too well either... */
+	{ broken_pirq, "Dell PowerEdge 8450", {		/* Bad $PIR */
+			MATCH(DMI_PRODUCT_NAME, "Dell PowerEdge 8450"),
+			NO_MATCH, NO_MATCH, NO_MATCH
+			} },
+
 	{ NULL, }
 };
 	
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.4.9/linux/arch/i386/kernel/entry.S	Tue Jul  3 17:08:18 2001
+++ linux/arch/i386/kernel/entry.S	Sat Sep  8 12:02:32 2001
@@ -621,12 +621,6 @@
 	.long SYMBOL_NAME(sys_fcntl64)
 	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved for TUX */
 
-	/*
-	 * NOTE!! This doesn't have to be exact - we just have
-	 * to make sure we have _enough_ of the "sys_ni_syscall"
-	 * entries. Don't panic if you notice that this hasn't
-	 * been shrunk every time we add a new system call.
-	 */
-	.rept NR_syscalls-221
+	.rept NR_syscalls-(.-sys_call_table)/4
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.4.9/linux/arch/i386/kernel/i386_ksyms.c	Mon Aug 27 12:41:39 2001
+++ linux/arch/i386/kernel/i386_ksyms.c	Mon Sep 17 22:52:35 2001
@@ -72,7 +72,7 @@
 EXPORT_SYMBOL(apm_info);
 EXPORT_SYMBOL(gdt);
 
-#ifdef CONFIG_IO_DEBUG
+#ifdef CONFIG_DEBUG_IOVIRT
 EXPORT_SYMBOL(__io_virt_debug);
 #endif
 
@@ -165,3 +165,13 @@
 #ifdef CONFIG_HAVE_DEC_LOCK
 EXPORT_SYMBOL(atomic_dec_and_lock);
 #endif
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+EXPORT_SYMBOL(do_BUG);
+#endif
+
+#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE)
+extern int is_sony_vaio_laptop;
+EXPORT_SYMBOL(is_sony_vaio_laptop);
+#endif
+
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c
--- v2.4.9/linux/arch/i386/kernel/i8259.c	Tue Jul  3 17:08:18 2001
+++ linux/arch/i386/kernel/i8259.c	Mon Sep 17 23:03:09 2001
@@ -20,6 +20,7 @@
 #include <asm/pgtable.h>
 #include <asm/delay.h>
 #include <asm/desc.h>
+#include <asm/apic.h>
 
 #include <linux/irq.h>
 
@@ -415,6 +416,9 @@
 {
 	int i;
 
+#ifdef CONFIG_X86_LOCAL_APIC
+	init_bsp_APIC();
+#endif
 	init_8259A(0);
 
 	for (i = 0; i < NR_IRQS; i++) {
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/init_task.c linux/arch/i386/kernel/init_task.c
--- v2.4.9/linux/arch/i386/kernel/init_task.c	Tue Aug  3 10:32:57 1999
+++ linux/arch/i386/kernel/init_task.c	Mon Sep 17 15:29:09 2001
@@ -6,7 +6,6 @@
 #include <asm/pgtable.h>
 #include <asm/desc.h>
 
-static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.4.9/linux/arch/i386/kernel/io_apic.c	Tue Jul  3 17:08:18 2001
+++ linux/arch/i386/kernel/io_apic.c	Mon Sep 17 23:03:09 2001
@@ -33,25 +33,17 @@
 #include <asm/smp.h>
 #include <asm/desc.h>
 
+#undef APIC_LOCKUP_DEBUG
+
 #define APIC_LOCKUP_DEBUG
 
 static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
 
 /*
- * # of IO-APICs and # of IRQ routing registers
+ * # of IRQ routing registers
  */
-int nr_ioapics;
 int nr_ioapic_registers[MAX_IO_APICS];
 
-/* I/O APIC entries */
-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
-
-/* # of MP IRQ source entries */
-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
-
-/* MP IRQ source entries */
-int mp_irq_entries;
-
 #if CONFIG_SMP
 # define TARGET_CPUS cpu_online_map
 #else
@@ -154,14 +146,17 @@
 void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
 {
 	struct IO_APIC_route_entry entry;
+	unsigned long flags;
 
 	/*
 	 * Disable it in the IO-APIC irq-routing table:
 	 */
 	memset(&entry, 0, sizeof(entry));
 	entry.mask = 1;
+	spin_lock_irqsave(&ioapic_lock, flags);
 	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
 	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 static void clear_IO_APIC (void)
@@ -595,6 +590,7 @@
 {
 	struct IO_APIC_route_entry entry;
 	int apic, pin, idx, irq, first_notcon = 1, vector;
+	unsigned long flags;
 
 	printk(KERN_DEBUG "init IO_APIC IRQs\n");
 
@@ -650,8 +646,10 @@
 			if (!apic && (irq < 16))
 				disable_8259A_irq(irq);
 		}
+		spin_lock_irqsave(&ioapic_lock, flags);
 		io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
 		io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 	}
 	}
 
@@ -666,6 +664,7 @@
 void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
 {
 	struct IO_APIC_route_entry entry;
+	unsigned long flags;
 
 	memset(&entry,0,sizeof(entry));
 
@@ -695,8 +694,10 @@
 	/*
 	 * Add it to the IO-APIC irq-routing table:
 	 */
+	spin_lock_irqsave(&ioapic_lock, flags);
 	io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
 	io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	enable_8259A_irq(0);
 }
@@ -713,6 +714,7 @@
 	struct IO_APIC_reg_00 reg_00;
 	struct IO_APIC_reg_01 reg_01;
 	struct IO_APIC_reg_02 reg_02;
+	unsigned long flags;
 
  	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
 	for (i = 0; i < nr_ioapics; i++)
@@ -727,10 +729,12 @@
 
 	for (apic = 0; apic < nr_ioapics; apic++) {
 
+	spin_lock_irqsave(&ioapic_lock, flags);
 	*(int *)&reg_00 = io_apic_read(apic, 0);
 	*(int *)&reg_01 = io_apic_read(apic, 1);
 	if (reg_01.version >= 0x10)
 		*(int *)&reg_02 = io_apic_read(apic, 2);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	printk("\n");
 	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
@@ -742,11 +746,9 @@
 	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
 	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.entries);
 	if (	(reg_01.entries != 0x0f) && /* older (Neptune) boards */
-		(reg_01.entries != 0x11) &&
 		(reg_01.entries != 0x17) && /* typical ISA+PCI boards */
 		(reg_01.entries != 0x1b) && /* Compaq Proliant boards */
 		(reg_01.entries != 0x1f) && /* dual Xeon boards */
-		(reg_01.entries != 0x20) &&
 		(reg_01.entries != 0x22) && /* bigger Xeon boards */
 		(reg_01.entries != 0x2E) &&
 		(reg_01.entries != 0x3F)
@@ -757,7 +759,8 @@
 	if (	(reg_01.version != 0x01) && /* 82489DX IO-APICs */
 		(reg_01.version != 0x10) && /* oldest IO-APICs */
 		(reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */
-		(reg_01.version != 0x13)    /* Xeon IO-APICs */
+		(reg_01.version != 0x13) && /* Xeon IO-APICs */
+		(reg_01.entries != 0x20)    /* Intel P64H (82806 AA) */
 	)
 		UNEXPECTED_IO_APIC();
 	if (reg_01.__reserved_1 || reg_01.__reserved_2)
@@ -778,8 +781,10 @@
 	for (i = 0; i <= reg_01.entries; i++) {
 		struct IO_APIC_route_entry entry;
 
+		spin_lock_irqsave(&ioapic_lock, flags);
 		*(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
 		*(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		printk(KERN_DEBUG " %02x %03X %02X  ",
 			i,
@@ -806,7 +811,7 @@
 			continue;
 		printk(KERN_DEBUG "IRQ%d ", i);
 		for (;;) {
-			printk("-> %d", entry->pin);
+			printk("-> %d:%d", entry->apic, entry->pin);
 			if (!entry->next)
 				break;
 			entry = irq_2_pin + entry->next;
@@ -956,6 +961,7 @@
 {
 	struct IO_APIC_reg_01 reg_01;
 	int i;
+	unsigned long flags;
 
 	for (i = 0; i < PIN_MAP_SIZE; i++) {
 		irq_2_pin[i].pin = -1;
@@ -969,7 +975,9 @@
 	 * The number of IO-APIC IRQ registers (== #pins):
 	 */
 	for (i = 0; i < nr_ioapics; i++) {
+		spin_lock_irqsave(&ioapic_lock, flags);
 		*(int *)&reg_01 = io_apic_read(i, 1);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 		nr_ioapic_registers[i] = reg_01.entries+1;
 	}
 
@@ -1006,6 +1014,7 @@
 	int apic;
 	int i;
 	unsigned char old_id;
+	unsigned long flags;
 
 	/*
 	 * Set the IOAPIC ID to the value stored in the MPC table.
@@ -1013,7 +1022,9 @@
 	for (apic = 0; apic < nr_ioapics; apic++) {
 
 		/* Read the register 0 value */
+		spin_lock_irqsave(&ioapic_lock, flags);
 		*(int *)&reg_00 = io_apic_read(apic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 		
 		old_id = mp_ioapics[apic].mpc_apicid;
 
@@ -1062,12 +1073,16 @@
 					mp_ioapics[apic].mpc_apicid);
 
 		reg_00.ID = mp_ioapics[apic].mpc_apicid;
+		spin_lock_irqsave(&ioapic_lock, flags);
 		io_apic_write(apic, 0, *(int *)&reg_00);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		/*
 		 * Sanity check
 		 */
+		spin_lock_irqsave(&ioapic_lock, flags);
 		*(int *)&reg_00 = io_apic_read(apic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 		if (reg_00.ID != mp_ioapics[apic].mpc_apicid)
 			panic("could not set ID!\n");
 		else
@@ -1104,25 +1119,6 @@
 	return 0;
 }
 
-static int __init nmi_irq_works(void)
-{
-	irq_cpustat_t tmp[NR_CPUS];
-	int j, cpu;
-
-	memcpy(tmp, irq_stat, sizeof(tmp));
-	sti();
-	mdelay(50);
-
-	for (j = 0; j < smp_num_cpus; j++) {
-		cpu = cpu_logical_map(j);
-		if (nmi_count(cpu) - tmp[cpu].__nmi_count <= 3) {
-			printk(KERN_WARNING "CPU#%d NMI appears to be stuck.\n", cpu);
-			return 0;
-		}
-	}
-	return 1;
-}
-
 /*
  * In the SMP+IOAPIC case it might happen that there are an unspecified
  * number of pending IRQ events unhandled. These cases are very rare,
@@ -1212,6 +1208,7 @@
 static void end_level_ioapic_irq (unsigned int irq)
 {
 	unsigned long v;
+	int i;
 
 /*
  * It appears there is an erratum which affects at least version 0x11
@@ -1232,11 +1229,12 @@
  * operation to prevent an edge-triggered interrupt escaping meanwhile.
  * The idea is from Manfred Spraul.  --macro
  */
-	v = apic_read(APIC_TMR + ((IO_APIC_VECTOR(irq) & ~0x1f) >> 1));
+	i = IO_APIC_VECTOR(irq);
+	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
 
 	ack_APIC_irq();
 
-	if (!(v & (1 << (IO_APIC_VECTOR(irq) & 0x1f)))) {
+	if (!(v & (1 << (i & 0x1f)))) {
 #ifdef APIC_MISMATCH_DEBUG
 		atomic_inc(&irq_mis_count);
 #endif
@@ -1416,13 +1414,16 @@
 	int pin, i;
 	struct IO_APIC_route_entry entry0, entry1;
 	unsigned char save_control, save_freq_select;
+	unsigned long flags;
 
 	pin = find_isa_irq_pin(8, mp_INT);
 	if (pin == -1)
 		return;
 
+	spin_lock_irqsave(&ioapic_lock, flags);
 	*(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin);
 	*(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 	clear_IO_APIC_pin(0, pin);
 
 	memset(&entry1, 0, sizeof(entry1));
@@ -1435,8 +1436,10 @@
 	entry1.trigger = 0;
 	entry1.vector = 0;
 
+	spin_lock_irqsave(&ioapic_lock, flags);
 	io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
 	io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	save_control = CMOS_READ(RTC_CONTROL);
 	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
@@ -1455,8 +1458,10 @@
 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
 	clear_IO_APIC_pin(0, pin);
 
+	spin_lock_irqsave(&ioapic_lock, flags);
 	io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
 	io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 /*
@@ -1493,7 +1498,7 @@
 	pin1 = find_isa_irq_pin(0, mp_INT);
 	pin2 = find_isa_irq_pin(0, mp_ExtINT);
 
-	printk(KERN_INFO "..TIMER: vector=%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
+	printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
 
 	if (pin1 != -1) {
 		/*
@@ -1501,11 +1506,11 @@
 		 */
 		unmask_IO_APIC_irq(0);
 		if (timer_irq_works()) {
-			if (nmi_watchdog) {
+			if (nmi_watchdog == NMI_IO_APIC) {
 				disable_8259A_irq(0);
 				setup_nmi();
 				enable_8259A_irq(0);
-				nmi_irq_works();
+				check_nmi_watchdog();
 			}
 			return;
 		}
@@ -1522,9 +1527,9 @@
 		setup_ExtINT_IRQ0_pin(pin2, vector);
 		if (timer_irq_works()) {
 			printk("works.\n");
-			if (nmi_watchdog) {
+			if (nmi_watchdog == NMI_IO_APIC) {
 				setup_nmi();
-				nmi_irq_works();
+				check_nmi_watchdog();
 			}
 			return;
 		}
@@ -1605,19 +1610,3 @@
 	check_timer();
 	print_IO_APIC();
 }
-
-#ifndef CONFIG_SMP
-/*
- * This initializes the IO-APIC and APIC hardware if this is
- * a UP kernel.
- */
-void IO_APIC_init_uniprocessor (void)
-{
-	if (!smp_found_config)
-		return;
-	connect_bsp_APIC();
-	setup_local_APIC();
-	setup_IO_APIC();
-	setup_APIC_clocks();
-}
-#endif
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.4.9/linux/arch/i386/kernel/irq.c	Tue Jul  3 17:08:18 2001
+++ linux/arch/i386/kernel/irq.c	Mon Sep 17 23:03:09 2001
@@ -166,7 +166,7 @@
 		p += sprintf(p, "%10u ",
 			nmi_count(cpu_logical_map(j)));
 	p += sprintf(p, "\n");
-#if CONFIG_SMP
+#if CONFIG_X86_LOCAL_APIC
 	p += sprintf(p, "LOC: ");
 	for (j = 0; j < smp_num_cpus; j++)
 		p += sprintf(p, "%10u ",
@@ -471,14 +471,15 @@
  *	disable_irq_nosync - disable an irq without waiting
  *	@irq: Interrupt to disable
  *
- *	Disable the selected interrupt line. Disables of an interrupt
- *	stack. Unlike disable_irq(), this function does not ensure existing
+ *	Disable the selected interrupt line.  Disables and Enables are
+ *	nested.
+ *	Unlike disable_irq(), this function does not ensure existing
  *	instances of the IRQ handler have completed before returning.
  *
  *	This function may be called from IRQ context.
  */
  
-void inline disable_irq_nosync(unsigned int irq)
+inline void disable_irq_nosync(unsigned int irq)
 {
 	irq_desc_t *desc = irq_desc + irq;
 	unsigned long flags;
@@ -495,9 +496,9 @@
  *	disable_irq - disable an irq and wait for completion
  *	@irq: Interrupt to disable
  *
- *	Disable the selected interrupt line. Disables of an interrupt
- *	stack. That is for two disables you need two enables. This
- *	function waits for any pending IRQ handlers for this interrupt
+ *	Disable the selected interrupt line.  Enables and Disables are
+ *	nested.
+ *	This function waits for any pending IRQ handlers for this interrupt
  *	to complete before returning. If you use this function while
  *	holding a resource the IRQ handler may need you will deadlock.
  *
@@ -516,11 +517,12 @@
 }
 
 /**
- *	enable_irq - enable interrupt handling on an irq
+ *	enable_irq - enable handling of an irq
  *	@irq: Interrupt to enable
  *
- *	Re-enables the processing of interrupts on this IRQ line
- *	providing no disable_irq calls are now in effect.
+ *	Undoes the effect of one call to disable_irq().  If this
+ *	matches the last disable, processing of interrupts on this
+ *	IRQ line is re-enabled.
  *
  *	This function may be called from IRQ context.
  */
@@ -1027,20 +1029,9 @@
 
 static struct proc_dir_entry * root_irq_dir;
 static struct proc_dir_entry * irq_dir [NR_IRQS];
-static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
-
-static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
 
 #define HEX_DIGITS 8
 
-static int irq_affinity_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	if (count < HEX_DIGITS+1)
-		return -EINVAL;
-	return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
-}
-
 static unsigned int parse_hex_value (const char *buffer,
 		unsigned long count, unsigned long *ret)
 {
@@ -1078,6 +1069,19 @@
 	return 0;
 }
 
+#if CONFIG_SMP
+
+static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
+
+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
+static int irq_affinity_read_proc (char *page, char **start, off_t off,
+			int count, int *eof, void *data)
+{
+	if (count < HEX_DIGITS+1)
+		return -EINVAL;
+	return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
+}
+
 static int irq_affinity_write_proc (struct file *file, const char *buffer,
 					unsigned long count, void *data)
 {
@@ -1089,7 +1093,6 @@
 
 	err = parse_hex_value(buffer, count, &new_value);
 
-#if CONFIG_SMP
 	/*
 	 * Do not allow disabling IRQs completely - it's a too easy
 	 * way to make the system unusable accidentally :-) At least
@@ -1097,7 +1100,6 @@
 	 */
 	if (!(new_value & cpu_online_map))
 		return -EINVAL;
-#endif
 
 	irq_affinity[irq] = new_value;
 	irq_desc[irq].handler->set_affinity(irq, new_value);
@@ -1105,6 +1107,8 @@
 	return full_count;
 }
 
+#endif
+
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
@@ -1132,7 +1136,6 @@
 
 static void register_irq_proc (unsigned int irq)
 {
-	struct proc_dir_entry *entry;
 	char name [MAX_NAMELEN];
 
 	if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
@@ -1145,15 +1148,23 @@
 	/* create /proc/irq/1234 */
 	irq_dir[irq] = proc_mkdir(name, root_irq_dir);
 
-	/* create /proc/irq/1234/smp_affinity */
-	entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
+#if CONFIG_SMP
+	{
+		struct proc_dir_entry *entry;
 
-	entry->nlink = 1;
-	entry->data = (void *)(long)irq;
-	entry->read_proc = irq_affinity_read_proc;
-	entry->write_proc = irq_affinity_write_proc;
+		/* create /proc/irq/1234/smp_affinity */
+		entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
 
-	smp_affinity_entry[irq] = entry;
+		if (entry) {
+			entry->nlink = 1;
+			entry->data = (void *)(long)irq;
+			entry->read_proc = irq_affinity_read_proc;
+			entry->write_proc = irq_affinity_write_proc;
+		}
+
+		smp_affinity_entry[irq] = entry;
+	}
+#endif
 }
 
 unsigned long prof_cpu_mask = -1;
@@ -1168,6 +1179,9 @@
 
 	/* create /proc/irq/prof_cpu_mask */
 	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
+
+	if (!entry)
+	    return;
 
 	entry->nlink = 1;
 	entry->data = (void *)&prof_cpu_mask;
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/microcode.c linux/arch/i386/kernel/microcode.c
--- v2.4.9/linux/arch/i386/kernel/microcode.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/i386/kernel/microcode.c	Fri Sep 14 14:04:08 2001
@@ -126,6 +126,7 @@
 		printk(KERN_ERR "microcode: failed to devfs_register()\n");
 		goto out;
 	}
+	error = 0;
 	printk(KERN_INFO 
 		"IA-32 Microcode Update Driver: v%s <tigran@veritas.com>\n", 
 		MICROCODE_VERSION);
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/mpparse.c linux/arch/i386/kernel/mpparse.c
--- v2.4.9/linux/arch/i386/kernel/mpparse.c	Sun Aug 12 13:27:58 2001
+++ linux/arch/i386/kernel/mpparse.c	Mon Sep 17 23:03:09 2001
@@ -38,6 +38,18 @@
 int mp_bus_id_to_type [MAX_MP_BUSSES];
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 int mp_current_pci_id;
+
+/* I/O APIC entries */
+struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+
+/* # of MP IRQ source entries */
+struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+
+/* MP IRQ source entries */
+int mp_irq_entries;
+
+int nr_ioapics;
+
 int pic_mode;
 unsigned long mp_lapic_addr;
 
@@ -225,6 +237,11 @@
 			MAX_IO_APICS, nr_ioapics);
 		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
 	}
+	if (!m->mpc_apicaddr) {
+		printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
+			" found in MP table, skipping!\n");
+		return;
+	}
 	mp_ioapics[nr_ioapics] = *m;
 	nr_ioapics++;
 }
@@ -365,10 +382,19 @@
 	return num_processors;
 }
 
+static int __init ELCR_trigger(unsigned int irq)
+{
+	unsigned int port;
+
+	port = 0x4d0 + (irq >> 3);
+	return (inb(port) >> (irq & 7)) & 1;
+}
+
 static void __init construct_default_ioirq_mptable(int mpc_default_type)
 {
 	struct mpc_config_intsrc intsrc;
 	int i;
+	int ELCR_fallback = 0;
 
 	intsrc.mpc_type = MP_INTSRC;
 	intsrc.mpc_irqflag = 0;			/* conforming */
@@ -376,6 +402,26 @@
 	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
 
 	intsrc.mpc_irqtype = mp_INT;
+
+	/*
+	 *  If true, we have an ISA/PCI system with no IRQ entries
+	 *  in the MP table. To prevent the PCI interrupts from being set up
+	 *  incorrectly, we try to use the ELCR. The sanity check to see if
+	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
+	 *  never be level sensitive, so we simply see if the ELCR agrees.
+	 *  If it does, we assume it's valid.
+	 */
+	if (mpc_default_type == 5) {
+		printk("ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
+
+		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
+			printk("ELCR contains invalid data... not using ELCR\n");
+		else {
+			printk("Using ELCR to identify PCI interrupts\n");
+			ELCR_fallback = 1;
+		}
+	}
+
 	for (i = 0; i < 16; i++) {
 		switch (mpc_default_type) {
 		case 2:
@@ -387,6 +433,18 @@
 				continue;	/* IRQ2 is never connected */
 		}
 
+		if (ELCR_fallback) {
+			/*
+			 *  If the ELCR indicates a level-sensitive interrupt, we
+			 *  copy that information over to the MP table in the
+			 *  irqflag field (level sensitive, active high polarity).
+			 */
+			if (ELCR_trigger(i))
+				intsrc.mpc_irqflag = 13;
+			else
+				intsrc.mpc_irqflag = 0;
+		}
+
 		intsrc.mpc_srcbusirq = i;
 		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
 		MP_intsrc_info(&intsrc);
@@ -641,7 +699,7 @@
  */
 void __init find_smp_config (void)
 {
-#ifdef CONFIG_X86_IO_APIC
+#ifdef CONFIG_X86_LOCAL_APIC
 	find_intel_smp();
 #endif
 #ifdef CONFIG_VISWS
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.4.9/linux/arch/i386/kernel/mtrr.c	Thu May 24 15:14:08 2001
+++ linux/arch/i386/kernel/mtrr.c	Sat Sep  1 11:05:16 2001
@@ -389,21 +389,19 @@
 	 return;
 
     /*  Save value of CR4 and clear Page Global Enable (bit 7)  */
-    if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) )
-	asm volatile ("movl  %%cr4, %0\n\t"
-		      "movl  %0, %1\n\t"
-		      "andb  $0x7f, %b1\n\t"
-		      "movl  %1, %%cr4\n\t"
-		      : "=r" (ctxt->cr4val), "=q" (tmp) : : "memory");
+    if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) {
+	ctxt->cr4val = read_cr4();
+	write_cr4(ctxt->cr4val & (unsigned char) ~(1<<7));
+    }
 
     /*  Disable and flush caches. Note that wbinvd flushes the TLBs as
 	a side-effect  */
-    asm volatile ("movl  %%cr0, %0\n\t"
-		  "orl   $0x40000000, %0\n\t"
-		  "wbinvd\n\t"
-		  "movl  %0, %%cr0\n\t"
-		  "wbinvd\n\t"
-		  : "=r" (tmp) : : "memory");
+    {
+	unsigned int cr0 = read_cr0() | 0x40000000;
+	wbinvd();
+	write_cr0( cr0 );
+	wbinvd();
+    }
 
     if ( mtrr_if == MTRR_IF_INTEL ) {
 	/*  Disable MTRRs, and set the default type to uncached  */
@@ -420,15 +418,13 @@
 /*  Restore the processor after a set_mtrr_prepare  */
 static void set_mtrr_done (struct set_mtrr_context *ctxt)
 {
-    unsigned long tmp;
-
     if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR ) {
 	 __restore_flags (ctxt->flags);
 	 return;
     }
 
     /*  Flush caches and TLBs  */
-    asm volatile ("wbinvd" : : : "memory" );
+    wbinvd();
 
     /*  Restore MTRRdefType  */
     if ( mtrr_if == MTRR_IF_INTEL ) {
@@ -440,15 +436,11 @@
     }
 
     /*  Enable caches  */
-    asm volatile ("movl  %%cr0, %0\n\t"
-		  "andl  $0xbfffffff, %0\n\t"
-		  "movl  %0, %%cr0\n\t"
-		  : "=r" (tmp) : : "memory");
+    write_cr0( read_cr0() & 0xbfffffff );
 
     /*  Restore value of CR4  */
     if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) )
-	asm volatile ("movl  %0, %%cr4"
-		      : : "r" (ctxt->cr4val) : "memory");
+	write_cr4(ctxt->cr4val);
 
     /*  Re-enable interrupts locally (if enabled previously)  */
     __restore_flags (ctxt->flags);
@@ -607,7 +599,7 @@
 {
     unsigned long low, high;
 
-    rdmsr (0xC0000085, low, high);
+    rdmsr (MSR_K6_UWCCR, low, high);
     /*  Upper dword is region 1, lower is region 0  */
     if (reg == 1) low = high;
     /*  The base masks off on the right alignment  */
@@ -771,7 +763,7 @@
     /*
      *	Low is MTRR0 , High MTRR 1
      */
-    rdmsr (0xC0000085, regs[0], regs[1]);
+    rdmsr (MSR_K6_UWCCR, regs[0], regs[1]);
     /*
      *	Blank to disable
      */
@@ -792,8 +784,8 @@
      *	The writeback rule is quite specific. See the manual. Its
      *	disable local interrupts, write back the cache, set the mtrr
      */
-    __asm__ __volatile__ ("wbinvd" : : : "memory");
-    wrmsr (0xC0000085, regs[0], regs[1]);
+	wbinvd();
+	wrmsr (MSR_K6_UWCCR, regs[0], regs[1]);
     if (do_safe) set_mtrr_done (&ctxt);
 }   /*  End Function amd_set_mtrr_up  */
 
@@ -826,7 +818,7 @@
     }
     centaur_mcr[reg].high = high;
     centaur_mcr[reg].low = low;
-    wrmsr (0x110 + reg, low, high);
+    wrmsr (MSR_IDT_MCR0 + reg, low, high);
     if (do_safe) set_mtrr_done( &ctxt );
 }   /*  End Function centaur_set_mtrr_up  */
 
@@ -2012,12 +2004,12 @@
      * find out what the bios might have done.
      */
      
-    rdmsr(0x120, lo, hi);
+    rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
     if(((lo>>17)&7)==1)		/* Type 1 Winchip2 MCR */
     {
     	lo&= ~0x1C0;		/* clear key */
     	lo|= 0x040;		/* set key to 1 */
-	wrmsr(0x120, lo, hi);	/* unlock MCR */
+	wrmsr(MSR_IDT_MCR_CTRL, lo, hi);	/* unlock MCR */
     }    
     
     centaur_mcr_type = 1;
@@ -2031,7 +2023,7 @@
     	if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)
     	{
     		if(!(lo & (1<<(9+i))))
-			wrmsr (0x110 + i , 0, 0);
+			wrmsr (MSR_IDT_MCR0 + i , 0, 0);
 		else
 			/*
 			 *	If the BIOS set up an MCR we cannot see it
@@ -2047,7 +2039,7 @@
      */
 
     lo |= 15;			/* Write combine enables */
-    wrmsr(0x120, lo, hi);
+    wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
 }   /*  End Function centaur_mcr1_init  */
 
 /*
@@ -2071,10 +2063,10 @@
     for (i = 0; i < 8; ++i)
     {
     	if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)
-		wrmsr (0x110 + i , 0, 0);
+		wrmsr (MSR_IDT_MCR0 + i , 0, 0);
     }
 
-    wrmsr(0x120, 0x01F0001F, 0);	/* Write only */
+    wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0);	/* Write only */
 }   /*  End Function centaur_mcr0_init  */
 
 /*
@@ -2230,6 +2222,8 @@
 	 *  :-)
 	 */
 	cyrix_arr_init_secondary ();
+	break;
+    case MTRR_IF_NONE:
 	break;
     default:
 	/* I see no MTRRs I can support in SMP mode... */
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/nmi.c linux/arch/i386/kernel/nmi.c
--- v2.4.9/linux/arch/i386/kernel/nmi.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/kernel/nmi.c	Thu Sep 20 20:55:24 2001
@@ -0,0 +1,300 @@
+/*
+ *  linux/arch/i386/nmi.c
+ *
+ *  NMI watchdog support on APIC systems
+ *
+ *  Started by Ingo Molnar <mingo@redhat.com>
+ *
+ *  Fixes:
+ *  Mikael Pettersson	: AMD K7 support for local APIC NMI watchdog.
+ *  Mikael Pettersson	: Power Management for local APIC NMI watchdog.
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/mc146818rtc.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/smp.h>
+#include <asm/mtrr.h>
+#include <asm/mpspec.h>
+
+unsigned int nmi_watchdog = NMI_NONE;
+static unsigned int nmi_hz = HZ;
+unsigned int nmi_perfctr_msr;	/* the MSR to reset in NMI handler */
+extern void show_registers(struct pt_regs *regs);
+
+#define K7_EVNTSEL_ENABLE	(1 << 22)
+#define K7_EVNTSEL_INT		(1 << 20)
+#define K7_EVNTSEL_OS		(1 << 17)
+#define K7_EVNTSEL_USR		(1 << 16)
+#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING	0x76
+#define K7_NMI_EVENT		K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
+
+#define P6_EVNTSEL0_ENABLE	(1 << 22)
+#define P6_EVNTSEL_INT		(1 << 20)
+#define P6_EVNTSEL_OS		(1 << 17)
+#define P6_EVNTSEL_USR		(1 << 16)
+#define P6_EVENT_CPU_CLOCKS_NOT_HALTED	0x79
+#define P6_NMI_EVENT		P6_EVENT_CPU_CLOCKS_NOT_HALTED
+
+int __init check_nmi_watchdog (void)
+{
+	irq_cpustat_t tmp[NR_CPUS];
+	int j, cpu;
+
+	printk(KERN_INFO "testing NMI watchdog ... ");
+
+	memcpy(tmp, irq_stat, sizeof(tmp));
+	sti();
+	mdelay((10*1000)/nmi_hz); // wait 10 ticks
+
+	for (j = 0; j < smp_num_cpus; j++) {
+		cpu = cpu_logical_map(j);
+		if (nmi_count(cpu) - tmp[cpu].__nmi_count <= 5) {
+			printk("CPU#%d: NMI appears to be stuck!\n", cpu);
+			return -1;
+		}
+	}
+	printk("OK.\n");
+
+	/* now that we know it works we can reduce NMI frequency to
+	   something more reasonable; makes a difference in some configs */
+	if (nmi_watchdog == NMI_LOCAL_APIC)
+		nmi_hz = 1;
+
+	return 0;
+}
+
+static int __init setup_nmi_watchdog(char *str)
+{
+	int nmi;
+
+	get_option(&str, &nmi);
+
+	if (nmi >= NMI_INVALID)
+		return 0;
+	if (nmi == NMI_NONE)
+		nmi_watchdog = nmi;
+	/*
+	 * If any other x86 CPU has a local APIC, then
+	 * please test the NMI stuff there and send me the
+	 * missing bits. Right now Intel P6 and AMD K7 only.
+	 */
+	if ((nmi == NMI_LOCAL_APIC) &&
+			(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+			(boot_cpu_data.x86 == 6))
+		nmi_watchdog = nmi;
+	if ((nmi == NMI_LOCAL_APIC) &&
+			(boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
+			(boot_cpu_data.x86 == 6))
+		nmi_watchdog = nmi;
+	/*
+	 * We can enable the IO-APIC watchdog
+	 * unconditionally.
+	 */
+	if (nmi == NMI_IO_APIC)
+		nmi_watchdog = nmi;
+	return 1;
+}
+
+__setup("nmi_watchdog=", setup_nmi_watchdog);
+
+#ifdef CONFIG_PM
+
+#include <linux/pm.h>
+
+struct pm_dev *nmi_pmdev;
+
+static void disable_apic_nmi_watchdog(void)
+{
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_AMD:
+		wrmsr(MSR_K7_EVNTSEL0, 0, 0);
+		break;
+	case X86_VENDOR_INTEL:
+		wrmsr(MSR_IA32_EVNTSEL0, 0, 0);
+		break;
+	}
+}
+
+static int nmi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+	switch (rqst) {
+	case PM_SUSPEND:
+		disable_apic_nmi_watchdog();
+		break;
+	case PM_RESUME:
+		setup_apic_nmi_watchdog();
+		break;
+	}
+	return 0;
+}
+
+static void nmi_pm_init(void)
+{
+	if (!nmi_pmdev)
+		nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback);
+}
+
+#define __pminit	/*empty*/
+
+#else	/* CONFIG_PM */
+
+static inline void nmi_pm_init(void) { }
+
+#define __pminit	__init
+
+#endif	/* CONFIG_PM */
+
+/*
+ * Activate the NMI watchdog via the local APIC.
+ * Original code written by Keith Owens.
+ */
+
+static void __pminit setup_k7_watchdog(void)
+{
+	int i;
+	unsigned int evntsel;
+
+	nmi_perfctr_msr = MSR_K7_PERFCTR0;
+
+	for(i = 0; i < 4; ++i) {
+		wrmsr(MSR_K7_EVNTSEL0+i, 0, 0);
+		wrmsr(MSR_K7_PERFCTR0+i, 0, 0);
+	}
+
+	evntsel = K7_EVNTSEL_INT
+		| K7_EVNTSEL_OS
+		| K7_EVNTSEL_USR
+		| K7_NMI_EVENT;
+
+	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
+	Dprintk("setting K7_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
+	wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
+	evntsel |= K7_EVNTSEL_ENABLE;
+	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
+}
+
+static void __pminit setup_p6_watchdog(void)
+{
+	int i;
+	unsigned int evntsel;
+
+	nmi_perfctr_msr = MSR_IA32_PERFCTR0;
+
+	for(i = 0; i < 2; ++i) {
+		wrmsr(MSR_IA32_EVNTSEL0+i, 0, 0);
+		wrmsr(MSR_IA32_PERFCTR0+i, 0, 0);
+	}
+
+	evntsel = P6_EVNTSEL_INT
+		| P6_EVNTSEL_OS
+		| P6_EVNTSEL_USR
+		| P6_NMI_EVENT;
+
+	wrmsr(MSR_IA32_EVNTSEL0, evntsel, 0);
+	Dprintk("setting IA32_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
+	wrmsr(MSR_IA32_PERFCTR0, -(cpu_khz/nmi_hz*1000), 0);
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
+	evntsel |= P6_EVNTSEL0_ENABLE;
+	wrmsr(MSR_IA32_EVNTSEL0, evntsel, 0);
+}
+
+void __pminit setup_apic_nmi_watchdog (void)
+{
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_AMD:
+		if (boot_cpu_data.x86 != 6)
+			return;
+		setup_k7_watchdog();
+		break;
+	case X86_VENDOR_INTEL:
+		if (boot_cpu_data.x86 != 6)
+			return;
+		setup_p6_watchdog();
+		break;
+	default:
+		return;
+	}
+	nmi_pm_init();
+}
+
+static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * the best way to detect whether a CPU has a 'hard lockup' problem
+ * is to check it's local APIC timer IRQ counts. If they are not
+ * changing then that CPU has some problem.
+ *
+ * as these watchdog NMI IRQs are generated on every CPU, we only
+ * have to check the current processor.
+ *
+ * since NMIs dont listen to _any_ locks, we have to be extremely
+ * careful not to rely on unsafe variables. The printk might lock
+ * up though, so we have to break up any console locks first ...
+ * [when there will be more tty-related locks, break them up
+ *  here too!]
+ */
+
+static unsigned int
+	last_irq_sums [NR_CPUS],
+	alert_counter [NR_CPUS];
+
+void touch_nmi_watchdog (void)
+{
+	int i;
+
+	/*
+	 * Just reset the alert counters, (other CPUs might be
+	 * spinning on locks we hold):
+	 */
+	for (i = 0; i < smp_num_cpus; i++)
+		alert_counter[i] = 0;
+}
+
+void nmi_watchdog_tick (struct pt_regs * regs)
+{
+
+	/*
+	 * Since current-> is always on the stack, and we always switch
+	 * the stack NMI-atomically, it's safe to use smp_processor_id().
+	 */
+	int sum, cpu = smp_processor_id();
+
+	sum = apic_timer_irqs[cpu];
+
+	if (last_irq_sums[cpu] == sum) {
+		/*
+		 * Ayiee, looks like this CPU is stuck ...
+		 * wait a few IRQs (5 seconds) before doing the oops ...
+		 */
+		alert_counter[cpu]++;
+		if (alert_counter[cpu] == 5*nmi_hz) {
+			spin_lock(&nmi_print_lock);
+			/*
+			 * We are in trouble anyway, lets at least try
+			 * to get a message out.
+			 */
+			bust_spinlocks(1);
+			printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu);
+			show_registers(regs);
+			printk("console shuts up ...\n");
+			console_silent();
+			spin_unlock(&nmi_print_lock);
+			bust_spinlocks(0);
+			do_exit(SIGSEGV);
+		}
+	} else {
+		last_irq_sums[cpu] = sum;
+		alert_counter[cpu] = 0;
+	}
+	if (nmi_perfctr_msr)
+		wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+}
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.4.9/linux/arch/i386/kernel/pci-pc.c	Mon Aug 27 12:41:39 2001
+++ linux/arch/i386/kernel/pci-pc.c	Sat Sep  1 11:01:28 2001
@@ -20,65 +20,145 @@
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
 
 int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus;
-struct pci_ops *pci_root_ops;
+struct pci_bus *pci_root_bus = NULL;
+struct pci_ops *pci_root_ops = NULL;
+
+int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL;
+int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL;
 
 /*
- * Direct access to PCI hardware...
+ * This interrupt-safe spinlock protects all accesses to PCI
+ * configuration space.
  */
+spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
 
-#ifdef CONFIG_PCI_DIRECT
 
 /*
  * Functions for accessing PCI configuration space with type 1 accesses
  */
 
-#define CONFIG_CMD(dev, where)   (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3))
+#ifdef CONFIG_PCI_DIRECT
+
+#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \
+	(0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
+
+static int pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
+{
+	unsigned long flags;
+
+	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+		return -EINVAL;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
+
+	switch (len) {
+	case 1:
+		*value = inb(0xCFC + (reg & 3));
+		break;
+	case 2:
+		*value = inw(0xCFC + (reg & 2));
+		break;
+	case 4:
+		*value = inl(0xCFC);
+		break;
+	}
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return 0;
+}
+
+static int pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+{
+	unsigned long flags;
+
+	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) 
+		return -EINVAL;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
+
+	switch (len) {
+	case 1:
+		outb((u8)value, 0xCFC + (reg & 3));
+		break;
+	case 2:
+		outw((u16)value, 0xCFC + (reg & 2));
+		break;
+	case 4:
+		outl((u32)value, 0xCFC);
+		break;
+	}
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return 0;
+}
+
+#undef PCI_CONF1_ADDRESS
 
 static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);
-	*value = inb(0xCFC + (where&3));
-	return PCIBIOS_SUCCESSFUL;
+	int result; 
+	u32 data;
+
+	if (!value) 
+		return -EINVAL;
+
+	result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, &data);
+
+	*value = (u8)data;
+
+	return result;
 }
 
 static int pci_conf1_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);    
-	*value = inw(0xCFC + (where&2));
-	return PCIBIOS_SUCCESSFUL;    
+	int result; 
+	u32 data;
+
+	if (!value) 
+		return -EINVAL;
+
+	result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, &data);
+
+	*value = (u16)data;
+
+	return result;
 }
 
 static int pci_conf1_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);
-	*value = inl(0xCFC);
-	return PCIBIOS_SUCCESSFUL;    
+	if (!value) 
+		return -EINVAL;
+
+	return pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, value);
 }
 
 static int pci_conf1_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);    
-	outb(value, 0xCFC + (where&3));
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, value);
 }
 
 static int pci_conf1_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);
-	outw(value, 0xCFC + (where&2));
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, value);
 }
 
 static int pci_conf1_write_config_dword(struct pci_dev *dev, int where, u32 value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);
-	outl(value, 0xCFC);
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, value);
 }
 
-#undef CONFIG_CMD
-
 static struct pci_ops pci_direct_conf1 = {
 	pci_conf1_read_config_byte,
 	pci_conf1_read_config_word,
@@ -88,68 +168,131 @@
 	pci_conf1_write_config_dword
 };
 
+
 /*
  * Functions for accessing PCI configuration space with type 2 accesses
  */
 
-#define IOADDR(devfn, where)	((0xC000 | ((devfn & 0x78) << 5)) + where)
-#define FUNC(devfn)		(((devfn & 7) << 1) | 0xf0)
-#define SET(dev)		if (dev->devfn & 0x80) return PCIBIOS_DEVICE_NOT_FOUND;		\
-				outb(FUNC(dev->devfn), 0xCF8);					\
-				outb(dev->bus->number, 0xCFA);
+#define PCI_CONF2_ADDRESS(dev, reg)	(u16)(0xC000 | (dev << 8) | reg)
 
-static int pci_conf2_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+static int pci_conf2_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
 {
-	SET(dev);
-	*value = inb(IOADDR(dev->devfn,where));
+	unsigned long flags;
+
+	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+		return -EINVAL;
+
+	if (dev & 0x10) 
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	outb((u8)(0xF0 | (fn << 1)), 0xCF8);
+	outb((u8)bus, 0xCFA);
+
+	switch (len) {
+	case 1:
+		*value = inb(PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	case 2:
+		*value = inw(PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	case 4:
+		*value = inl(PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	}
+
 	outb (0, 0xCF8);
-	return PCIBIOS_SUCCESSFUL;
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return 0;
+}
+
+static int pci_conf2_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+{
+	unsigned long flags;
+
+	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) 
+		return -EINVAL;
+
+	if (dev & 0x10) 
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	outb((u8)(0xF0 | (fn << 1)), 0xCF8);
+	outb((u8)bus, 0xCFA);
+
+	switch (len) {
+	case 1:
+		outb ((u8)value, PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	case 2:
+		outw ((u16)value, PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	case 4:
+		outl ((u32)value, PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	}
+
+	outb (0, 0xCF8);    
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return 0;
+}
+
+#undef PCI_CONF2_ADDRESS
+
+static int pci_conf2_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+{
+	int result; 
+	u32 data;
+	result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, &data);
+	*value = (u8)data;
+	return result;
 }
 
 static int pci_conf2_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	SET(dev);
-	*value = inw(IOADDR(dev->devfn,where));
-	outb (0, 0xCF8);
-	return PCIBIOS_SUCCESSFUL;
+	int result; 
+	u32 data;
+	result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, &data);
+	*value = (u8)data;
+	return result;
 }
 
 static int pci_conf2_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	SET(dev);
-	*value = inl (IOADDR(dev->devfn,where));    
-	outb (0, 0xCF8);    
-	return PCIBIOS_SUCCESSFUL;
+	int result; 
+	u32 data;
+	result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, &data);
+	*value = (u8)data;
+	return result;
 }
 
 static int pci_conf2_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	SET(dev);
-	outb (value, IOADDR(dev->devfn,where));
-	outb (0, 0xCF8);    
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, value);
 }
 
 static int pci_conf2_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	SET(dev);
-	outw (value, IOADDR(dev->devfn,where));
-	outb (0, 0xCF8);    
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, value);
 }
 
 static int pci_conf2_write_config_dword(struct pci_dev *dev, int where, u32 value)
 {
-	SET(dev);
-	outl (value, IOADDR(dev->devfn,where));    
-	outb (0, 0xCF8);    
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, value);
 }
 
-#undef SET
-#undef IOADDR
-#undef FUNC
-
 static struct pci_ops pci_direct_conf2 = {
 	pci_conf2_read_config_byte,
 	pci_conf2_read_config_word,
@@ -159,6 +302,7 @@
 	pci_conf2_write_config_dword
 };
 
+
 /*
  * Before we decide to use direct hardware access mechanisms, we try to do some
  * trivial checks to ensure it at least _seems_ to be working -- we just test
@@ -420,114 +564,176 @@
 	return (int) (ret & 0xff00) >> 8;
 }
 
+static int pci_bios_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
+{
+	unsigned long result = 0;
+	unsigned long flags;
+	unsigned long bx = ((bus << 8) | (dev << 3) | fn);
+
+	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+		return -EINVAL;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	switch (len) {
+	case 1:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=c" (*value),
+			  "=a" (result)
+			: "1" (PCIBIOS_READ_CONFIG_BYTE),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	case 2:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=c" (*value),
+			  "=a" (result)
+			: "1" (PCIBIOS_READ_CONFIG_WORD),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	case 4:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=c" (*value),
+			  "=a" (result)
+			: "1" (PCIBIOS_READ_CONFIG_DWORD),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	}
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return (int)((result & 0xff00) >> 8);
+}
+
+static int pci_bios_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+{
+	unsigned long result = 0;
+	unsigned long flags;
+	unsigned long bx = ((bus << 8) | (dev << 3) | fn);
+
+	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) 
+		return -EINVAL;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	switch (len) {
+	case 1:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=a" (result)
+			: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
+			  "c" (value),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	case 2:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=a" (result)
+			: "0" (PCIBIOS_WRITE_CONFIG_WORD),
+			  "c" (value),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	case 4:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=a" (result)
+			: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
+			  "c" (value),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	}
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return (int)((result & 0xff00) >> 8);
+}
+
 static int pci_bios_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
+	int result; 
+	u32 data;
 
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=c" (*value),
-		  "=a" (ret)
-		: "1" (PCIBIOS_READ_CONFIG_BYTE),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	if (!value) 
+		return -EINVAL;
+
+	result = pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, &data);
+
+	*value = (u8)data;
+
+	return result;
 }
 
 static int pci_bios_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
+	int result; 
+	u32 data;
 
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=c" (*value),
-		  "=a" (ret)
-		: "1" (PCIBIOS_READ_CONFIG_WORD),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	if (!value) 
+		return -EINVAL;
+
+	result = pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, &data);
+
+	*value = (u16)data;
+
+	return result;
 }
 
 static int pci_bios_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=c" (*value),
-		  "=a" (ret)
-		: "1" (PCIBIOS_READ_CONFIG_DWORD),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	if (!value) 
+		return -EINVAL;
+	
+	return pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, value);
 }
 
 static int pci_bios_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=a" (ret)
-		: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
-		  "c" (value),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, value);
 }
 
 static int pci_bios_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=a" (ret)
-		: "0" (PCIBIOS_WRITE_CONFIG_WORD),
-		  "c" (value),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, value);
 }
 
 static int pci_bios_write_config_dword(struct pci_dev *dev, int where, u32 value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=a" (ret)
-		: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
-		  "c" (value),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, value);
 }
 
+
 /*
  * Function table for BIOS32 access
  */
@@ -981,34 +1187,47 @@
 	pci_read_bridge_bases(b);
 }
 
-/*
- * Initialization. Try all known PCI access methods. Note that we support
- * using both PCI BIOS and direct access: in such cases, we use I/O ports
- * to access config space, but we still keep BIOS order of cards to be
- * compatible with 2.0.X. This should go away some day.
- */
 
-void __init pcibios_init(void)
+void __init pcibios_config_init(void)
 {
-	struct pci_ops *bios = NULL;
-	struct pci_ops *dir = NULL;
+	/*
+	 * Try all known PCI access methods. Note that we support using 
+	 * both PCI BIOS and direct access, with a preference for direct.
+	 */
 
 #ifdef CONFIG_PCI_BIOS
-	if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
+	if ((pci_probe & PCI_PROBE_BIOS) 
+		&& ((pci_root_ops = pci_find_bios()))) {
 		pci_probe |= PCI_BIOS_SORT;
 		pci_bios_present = 1;
+		pci_config_read = pci_bios_read;
+		pci_config_write = pci_bios_write;
 	}
 #endif
+
 #ifdef CONFIG_PCI_DIRECT
-	if (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))
-		dir = pci_check_direct();
+	if ((pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2)) 
+		&& (pci_root_ops = pci_check_direct())) {
+		if (pci_root_ops == &pci_direct_conf1) {
+			pci_config_read = pci_conf1_read;
+			pci_config_write = pci_conf1_write;
+		}
+		else {
+			pci_config_read = pci_conf2_read;
+			pci_config_write = pci_conf2_write;
+		}
+	}
 #endif
-	if (dir)
-		pci_root_ops = dir;
-	else if (bios)
-		pci_root_ops = bios;
-	else {
-		printk("PCI: No PCI bus detected\n");
+
+	return;
+}
+
+void __init pcibios_init(void)
+{
+	if (!pci_root_ops)
+		pcibios_config_init();
+	if (!pci_root_ops) {
+		printk("PCI: System does not support PCI\n");
 		return;
 	}
 
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.4.9/linux/arch/i386/kernel/process.c	Sun Aug 12 13:27:58 2001
+++ linux/arch/i386/kernel/process.c	Mon Sep 17 22:52:35 2001
@@ -154,6 +154,12 @@
 static int reboot_mode;
 int reboot_thru_bios;
 
+#ifdef CONFIG_SMP
+int reboot_smp = 0;
+static int reboot_cpu = -1;
+/* shamelessly grabbed from lib/vsprintf.c for readability */
+#define is_digit(c)	((c) >= '0' && (c) <= '9')
+#endif
 static int __init reboot_setup(char *str)
 {
 	while(1) {
@@ -170,6 +176,19 @@
 		case 'h': /* "hard" reboot by toggling RESET and/or crashing the CPU */
 			reboot_thru_bios = 0;
 			break;
+#ifdef CONFIG_SMP
+		case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
+			reboot_smp = 1;
+			if (is_digit(*(str+1))) {
+				reboot_cpu = (int) (*(str+1) - '0');
+				if (is_digit(*(str+2))) 
+					reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
+			}
+				/* we will leave sorting out the final value 
+				when we are ready to reboot, since we might not
+ 				have set up boot_cpu_id or smp_num_cpu */
+			break;
+#endif
 		}
 		if((str = strchr(str,',')) != NULL)
 			str++;
@@ -346,6 +365,34 @@
 void machine_restart(char * __unused)
 {
 #if CONFIG_SMP
+	int cpuid;
+	
+	cpuid = GET_APIC_ID(apic_read(APIC_ID));
+
+	if (reboot_smp) {
+
+		/* check to see if reboot_cpu is valid 
+		   if its not, default to the BSP */
+		if ((reboot_cpu == -1) ||  
+		      (reboot_cpu > (NR_CPUS -1))  || 
+		      !(phys_cpu_present_map & (1<<cpuid))) 
+			reboot_cpu = boot_cpu_id;
+
+		reboot_smp = 0;  /* use this as a flag to only go through this once*/
+		/* re-run this function on the other CPUs
+		   it will fall though this section since we have 
+		   cleared reboot_smp, and do the reboot if it is the
+		   correct CPU, otherwise it halts. */
+		if (reboot_cpu != cpuid)
+			smp_call_function((void *)machine_restart , NULL, 1, 0);
+	}
+
+	/* if reboot_cpu is still -1, then we want a tradional reboot, 
+	   and if we are not running on the reboot_cpu,, halt */
+	if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) {
+		for (;;)
+		__asm__ __volatile__ ("hlt");
+	}
 	/*
 	 * Stop all CPUs and turn off local APICs and the IO-APIC, so
 	 * other OSs see a clean IRQ state.
@@ -391,6 +438,7 @@
 	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
 
 	printk("\n");
+	printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
 	printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs,regs->eip, smp_processor_id());
 	if (regs->xcs & 3)
 		printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.4.9/linux/arch/i386/kernel/ptrace.c	Wed Jul 25 17:10:17 2001
+++ linux/arch/i386/kernel/ptrace.c	Tue Sep 18 17:04:23 2001
@@ -134,6 +134,19 @@
 	return retval;
 }
 
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{ 
+	long tmp;
+
+	tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+	put_stack_long(child, EFL_OFFSET, tmp);
+}
+
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -202,7 +215,7 @@
 			break;
 
 		tmp = 0;  /* Default return condition */
-		if(addr < 17*sizeof(long))
+		if(addr < FRAME_SIZE*sizeof(long))
 			tmp = getreg(child, addr);
 		if(addr >= (long) &dummy->u_debugreg[0] &&
 		   addr <= (long) &dummy->u_debugreg[7]){
@@ -229,7 +242,7 @@
 		    addr > sizeof(struct user) - 3)
 			break;
 
-		if (addr < 17*sizeof(long)) {
+		if (addr < FRAME_SIZE*sizeof(long)) {
 			ret = putreg(child, addr, data);
 			break;
 		}
@@ -320,33 +333,17 @@
 		break;
 	}
 
-	case PTRACE_DETACH: { /* detach a process that was attached. */
-		long tmp;
-
-		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
-			break;
-		child->ptrace = 0;
-		child->exit_code = data;
-		write_lock_irq(&tasklist_lock);
-		REMOVE_LINKS(child);
-		child->p_pptr = child->p_opptr;
-		SET_LINKS(child);
-		write_unlock_irq(&tasklist_lock);
-		/* make sure the single step bit is not set. */
-		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
-		put_stack_long(child, EFL_OFFSET, tmp);
-		wake_up_process(child);
-		ret = 0;
+	case PTRACE_DETACH:
+		/* detach a process that was attached. */
+		ret = ptrace_detach(child, data);
 		break;
-	}
 
 	case PTRACE_GETREGS: { /* Get all gp regs from the child. */
-	  	if (!access_ok(VERIFY_WRITE, (unsigned *)data, 17*sizeof(long))) {
+	  	if (!access_ok(VERIFY_WRITE, (unsigned *)data, FRAME_SIZE*sizeof(long))) {
 			ret = -EIO;
 			break;
 		}
-		for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) {
+		for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
 			__put_user(getreg(child, i),(unsigned long *) data);
 			data += sizeof(long);
 		}
@@ -356,11 +353,11 @@
 
 	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
 		unsigned long tmp;
-	  	if (!access_ok(VERIFY_READ, (unsigned *)data, 17*sizeof(long))) {
+	  	if (!access_ok(VERIFY_READ, (unsigned *)data, FRAME_SIZE*sizeof(long))) {
 			ret = -EIO;
 			break;
 		}
-		for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) {
+		for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
 			__get_user(tmp, (unsigned long *) data);
 			putreg(child, i, tmp);
 			data += sizeof(long);
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.4.9/linux/arch/i386/kernel/setup.c	Wed Jul 25 17:10:17 2001
+++ linux/arch/i386/kernel/setup.c	Mon Sep 17 23:03:09 2001
@@ -64,6 +64,9 @@
  *
  *  VIA C3 Support.
  *  Dave Jones <davej@suse.de>, March 2001
+ *
+ *  AMD Athlon/Duron/Thunderbird bluesmoke support.
+ *  Dave Jones <davej@suse.de>, April 2001.
  */
 
 /*
@@ -93,6 +96,7 @@
 #include <linux/bootmem.h>
 #include <asm/processor.h>
 #include <linux/console.h>
+#include <asm/mtrr.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -145,9 +149,9 @@
 
 unsigned char aux_device_present;
 
+extern void mcheck_init(struct cpuinfo_x86 *c);
 extern int root_mountflags;
 extern char _text, _etext, _edata, _end;
-extern unsigned long cpu_khz;
 
 static int disable_x86_serial_nr __initdata = 1;
 static int disable_x86_fxsr __initdata = 0;
@@ -937,27 +941,14 @@
 	 * trampoline before removing it. (see the GDT stuff)
 	 */
 	reserve_bootmem(PAGE_SIZE, PAGE_SIZE);
-	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
 #endif
 
-#ifdef CONFIG_X86_IO_APIC
+#ifdef CONFIG_X86_LOCAL_APIC
 	/*
 	 * Find and reserve possible boot-time SMP configuration:
 	 */
 	find_smp_config();
 #endif
-	paging_init();
-#ifdef CONFIG_X86_IO_APIC
-	/*
-	 * get boot-time SMP configuration:
-	 */
-	if (smp_found_config)
-		get_smp_config();
-#endif
-#ifdef CONFIG_X86_LOCAL_APIC
-	init_apic_mappings();
-#endif
-
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (LOADER_TYPE && INITRD_START) {
 		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
@@ -977,6 +968,25 @@
 #endif
 
 	/*
+	 * NOTE: before this point _nobody_ is allowed to allocate
+	 * any memory using the bootmem allocator.
+	 */
+
+#ifdef CONFIG_SMP
+	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
+#endif
+	paging_init();
+#ifdef CONFIG_X86_LOCAL_APIC
+	/*
+	 * get boot-time SMP configuration:
+	 */
+	if (smp_found_config)
+		get_smp_config();
+	init_apic_mappings();
+#endif
+
+
+	/*
 	 * Request address space for all standard RAM and ROM resources
 	 * and also for regions reported as reserved by the e820.
 	 */
@@ -1088,11 +1098,18 @@
 	l2size = ecx >> 16;
 
 	/* AMD errata T13 (order #21922) */
-	if (c->x86_vendor == X86_VENDOR_AMD &&
-	    c->x86 == 6 &&
-	    c->x86_model == 3 &&
-	    c->x86_mask == 0) {
-		l2size = 64;
+	if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
+		if (c->x86_model == 3 && c->x86_mask == 0)	/* Duron Rev A0 */
+			l2size = 64;
+		if (c->x86_model == 4 &&
+			(c->x86_mask==0 || c->x86_mask==1))	/* Tbird rev A1/A2 */
+			l2size = 256;
+	}
+
+	/* VIA C3 CPUs (670-68F) need further shifting. */
+	if (c->x86_vendor == X86_VENDOR_CENTAUR && (c->x86 == 6) &&
+		((c->x86_model == 7) || (c->x86_model == 8))) {
+		l2size = l2size >> 8;
 	}
 
 	if ( l2size == 0 )
@@ -1109,7 +1126,7 @@
  *	misexecution of code under Linux. Owners of such processors should
  *	contact AMD for precise details and a CPU swap.
  *
- *	See	http://www.mygale.com/~poulot/k6bug.html
+ *	See	http://www.multimania.com/poulot/k6bug.html
  *		http://www.amd.com/K6/k6docs/revgd.html
  *
  *	The following test is erm.. interesting. AMD neglected to up
@@ -1126,6 +1143,12 @@
 	int mbytes = max_mapnr >> (20-PAGE_SHIFT);
 	int r;
 
+	/*
+	 *	FIXME: We should handle the K5 here. Set up the write
+	 *	range and also turn on MSR 83 bits 4 and 31 (write alloc,
+	 *	no bus pipeline)
+	 */
+
 	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
 	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
 	clear_bit(0*32+31, &c->x86_capability);
@@ -1185,13 +1208,13 @@
 				if(mbytes>508)
 					mbytes=508;
 					
-				rdmsr(0xC0000082, l, h);
+				rdmsr(MSR_K6_WHCR, l, h);
 				if ((l&0x0000FFFF)==0) {
 					unsigned long flags;
 					l=(1<<0)|((mbytes/4)<<1);
 					local_irq_save(flags);
-					__asm__ __volatile__ ("wbinvd": : :"memory");
-					wrmsr(0xC0000082, l, h);
+					wbinvd();
+					wrmsr(MSR_K6_WHCR, l, h);
 					local_irq_restore(flags);
 					printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n",
 						mbytes);
@@ -1206,13 +1229,13 @@
 				if(mbytes>4092)
 					mbytes=4092;
 
-				rdmsr(0xC0000082, l, h);
+				rdmsr(MSR_K6_WHCR, l, h);
 				if ((l&0xFFFF0000)==0) {
 					unsigned long flags;
 					l=((mbytes>>2)<<22)|(1<<16);
 					local_irq_save(flags);
-					__asm__ __volatile__ ("wbinvd": : :"memory");
-					wrmsr(0xC0000082, l, h);
+					wbinvd();
+					wrmsr(MSR_K6_WHCR, l, h);
 					local_irq_restore(flags);
 					printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n",
 						mbytes);
@@ -1226,10 +1249,10 @@
 					set_bit(X86_FEATURE_K6_MTRR, &c->x86_capability);
 				break;
 			}
-
 			break;
 
 		case 6:	/* An Athlon/Duron. We can trust the BIOS probably */
+			mcheck_init(c);
 			break;		
 	}
 
@@ -1312,9 +1335,10 @@
 
 static void __init check_cx686_slop(struct cpuinfo_x86 *c)
 {
+	unsigned long flags;
+
 	if (Cx86_dir0_msb == 3) {
 		unsigned char ccr3, ccr5;
-		unsigned long flags;
 
 		local_irq_save(flags);
 		ccr3 = getCx86(CX86_CCR3);
@@ -1551,14 +1575,12 @@
 				name="??";
 			}
 
-			/* get FCR  */
-			rdmsr(0x107, lo, hi);
-
+			rdmsr(MSR_IDT_FCR1, lo, hi);
 			newlo=(lo|fcr_set) & (~fcr_clr);
 
 			if (newlo!=lo) {
 				printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n", lo, newlo );
-				wrmsr(0x107, newlo, hi );
+				wrmsr(MSR_IDT_FCR1, newlo, hi );
 			} else {
 				printk(KERN_INFO "Centaur FCR is 0x%X\n",lo);
 			}
@@ -1577,14 +1599,15 @@
 				c->x86_cache_size = (cc>>24)+(dd>>24);
 			}
 			sprintf( c->x86_model_id, "WinChip %s", name );
+			mcheck_init(c);
 			break;
 
 		case 6:
 			switch (c->x86_model) {
 				case 6 ... 7:		/* Cyrix III or C3 */
-					rdmsr (0x1107, lo, hi);
+					rdmsr (MSR_VIA_FCR, lo, hi);
 					lo |= (1<<1 | 1<<7);	/* Report CX8 & enable PGE */
-					wrmsr (0x1107, lo, hi);
+					wrmsr (MSR_VIA_FCR, lo, hi);
 
 					set_bit(X86_FEATURE_CX8, &c->x86_capability);
 					set_bit(X86_FEATURE_3DNOW, &c->x86_capability);
@@ -1595,7 +1618,6 @@
 			}
 			break;
 	}
-
 }
 
 
@@ -1668,7 +1690,6 @@
 	if (c->x86_model > 2)
 		printk(" II");
 	printk("\n");
-	printk("If you have one of these please email davej@suse.de\n");
 
 	/* Unhide possibly hidden capability flags
 	   The mp6 iDragon family don't have MSRs.
@@ -1694,7 +1715,6 @@
 #ifndef CONFIG_M686
 	static int f00f_workaround_enabled = 0;
 #endif
-	extern void mcheck_init(struct cpuinfo_x86 *c);
 	char *p = NULL;
 	unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
 
@@ -1989,9 +2009,9 @@
 	    disable_x86_serial_nr ) {
 		/* Disable processor serial number */
 		unsigned long lo,hi;
-		rdmsr(0x119,lo,hi);
+		rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
 		lo |= 0x200000;
-		wrmsr(0x119,lo,hi);
+		wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
 		printk(KERN_NOTICE "CPU serial number disabled.\n");
 		clear_bit(X86_FEATURE_PN, &c->x86_capability);
 
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.4.9/linux/arch/i386/kernel/signal.c	Wed Jul 25 17:10:17 2001
+++ linux/arch/i386/kernel/signal.c	Fri Sep 14 14:15:40 2001
@@ -19,6 +19,7 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/tty.h>
+#include <linux/personality.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/i387.h>
@@ -665,13 +666,16 @@
 					continue;
 				/* FALLTHRU */
 
-			case SIGSTOP:
+			case SIGSTOP: {
+				struct signal_struct *sig;
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
-				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+				sig = current->p_pptr->sig;
+				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
 				continue;
+			}
 
 			case SIGQUIT: case SIGILL: case SIGTRAP:
 			case SIGABRT: case SIGFPE: case SIGSEGV:
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.4.9/linux/arch/i386/kernel/smp.c	Mon Aug 27 12:41:39 2001
+++ linux/arch/i386/kernel/smp.c	Mon Sep 17 23:03:09 2001
@@ -429,9 +429,10 @@
 	atomic_t started;
 	atomic_t finished;
 	int wait;
-};
+} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
 
 static struct call_data_struct * call_data;
+static struct call_data_struct call_data_array[NR_CPUS];
 
 /*
  * this function sends a 'generic call function' IPI to all other CPUs
@@ -453,32 +454,45 @@
  * hardware interrupt handler, you may call it from a bottom half handler.
  */
 {
-	struct call_data_struct data;
-	int cpus = smp_num_cpus-1;
+	struct call_data_struct *data;
+	int cpus = (cpu_online_map & ~(1 << smp_processor_id()));
 
 	if (!cpus)
 		return 0;
 
-	data.func = func;
-	data.info = info;
-	atomic_set(&data.started, 0);
-	data.wait = wait;
+	data = &call_data_array[smp_processor_id()];
+	
+	data->func = func;
+	data->info = info;
+	data->wait = wait;
 	if (wait)
-		atomic_set(&data.finished, 0);
-
-	spin_lock_bh(&call_lock);
-	call_data = &data;
+		atomic_set(&data->finished, 0);
+	/* We have do to this one last to make sure that the IPI service
+	 * code desn't get confused if it gets an unexpected repeat
+	 * trigger of an old IPI while we're still setting up the new
+	 * one. */
+	atomic_set(&data->started, 0);
+
+	local_bh_disable();
+	spin_lock(&call_lock);
+	call_data = data;
 	/* Send a message to all other CPUs and wait for them to respond */
 	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
 
 	/* Wait for response */
-	while (atomic_read(&data.started) != cpus)
+	while (atomic_read(&data->started) != cpus)
 		barrier();
 
+	/* It is now safe to reuse the "call_data" global, but we need
+	 * to keep local bottom-halves disabled until after waiters have
+	 * been acknowledged to prevent reuse of the per-cpu call data
+	 * entry. */
+	spin_unlock(&call_lock);
+
 	if (wait)
-		while (atomic_read(&data.finished) != cpus)
+		while (atomic_read(&data->finished) != cpus)
 			barrier();
-	spin_unlock_bh(&call_lock);
+	local_bh_enable();
 
 	return 0;
 }
@@ -528,15 +542,17 @@
 
 	ack_APIC_irq();
 	/*
-	 * Notify initiating CPU that I've grabbed the data and am
-	 * about to execute the function
+	 * Notify initiating CPU that I've grabbed the data and am about
+	 * to execute the function (and avoid servicing any single IPI
+	 * twice)
 	 */
-	atomic_inc(&call_data->started);
+	if (test_and_set_bit(smp_processor_id(), &call_data->started))
+		return;
 	/*
 	 * At this point the info structure may be out of scope unless wait==1
 	 */
 	(*func)(info);
 	if (wait)
-		atomic_inc(&call_data->finished);
+		set_bit(smp_processor_id(), &call_data->finished);
 }
 
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- v2.4.9/linux/arch/i386/kernel/smpboot.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/i386/kernel/smpboot.c	Mon Sep 17 23:03:09 2001
@@ -66,7 +66,7 @@
 static volatile unsigned long cpu_callout_map;
 
 /* Per CPU bogomips and other parameters */
-struct cpuinfo_x86 cpu_data[NR_CPUS];
+struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
 
 /* Set when the idlers are all forked */
 int smp_threads_ready;
@@ -780,7 +780,6 @@
 }
 
 cycles_t cacheflush_time;
-extern unsigned long cpu_khz;
 
 static void smp_tune_scheduling (void)
 {
@@ -870,12 +869,15 @@
 	 * get out of here now!
 	 */
 	if (!smp_found_config) {
-		printk(KERN_NOTICE "SMP motherboard not detected. Using dummy APIC emulation.\n");
+		printk(KERN_NOTICE "SMP motherboard not detected.\n");
 #ifndef CONFIG_VISWS
 		io_apic_irqs = 0;
 #endif
 		cpu_online_map = phys_cpu_present_map = 1;
 		smp_num_cpus = 1;
+		if (APIC_init_uniprocessor())
+			printk(KERN_NOTICE "Local APIC not detected."
+					   " Using dummy APIC emulation.\n");
 		goto smp_done;
 	}
 
@@ -1003,7 +1005,7 @@
 	 * Here we can be sure that there is an IO-APIC in the system. Let's
 	 * go and set it up:
 	 */
-	if (!skip_ioapic_setup)
+	if (!skip_ioapic_setup && nr_ioapics)
 		setup_IO_APIC();
 #endif
 
@@ -1021,4 +1023,3 @@
 smp_done:
 	zap_low_mappings();
 }
-
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.4.9/linux/arch/i386/kernel/time.c	Fri Dec 29 14:07:57 2000
+++ linux/arch/i386/kernel/time.c	Mon Sep 17 23:03:09 2001
@@ -178,6 +178,15 @@
  	jiffies_t = jiffies;
 
 	count |= inb_p(0x40) << 8;
+	
+        /* VIA686a test code... reset the latch if count > max + 1 */
+        if (count > LATCH) {
+                outb_p(0x34, 0x43);
+                outb_p(LATCH & 0xff, 0x40);
+                outb(LATCH >> 8, 0x40);
+                count = LATCH - 1;
+        }
+	
 	spin_unlock(&i8253_lock);
 
 	/*
@@ -413,7 +422,7 @@
 	if (!user_mode(regs))
 		x86_do_profile(regs->eip);
 #else
-	if (!smp_found_config)
+	if (!using_apic_timer)
 		smp_local_timer_interrupt(regs);
 #endif
 
diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.4.9/linux/arch/i386/kernel/traps.c	Mon Aug 27 12:41:39 2001
+++ linux/arch/i386/kernel/traps.c	Tue Sep 18 13:39:51 2001
@@ -64,8 +64,6 @@
  */
 struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
 
-extern void bust_spinlocks(void);
-
 asmlinkage void divide_error(void);
 asmlinkage void debug(void);
 asmlinkage void nmi(void);
@@ -188,7 +186,7 @@
 	show_trace(esp);
 }
 
-static void show_registers(struct pt_regs *regs)
+void show_registers(struct pt_regs *regs)
 {
 	int i;
 	int in_kernel = 1;
@@ -245,9 +243,10 @@
 {
 	console_verbose();
 	spin_lock_irq(&die_lock);
+	bust_spinlocks(1);
 	printk("%s: %04lx\n", str, err & 0xffff);
 	show_registers(regs);
-
+	bust_spinlocks(0);
 	spin_unlock_irq(&die_lock);
 	do_exit(SIGSEGV);
 }
@@ -419,83 +418,14 @@
 	printk("Do you have a strange power saving mode enabled?\n");
 }
 
-#if CONFIG_X86_IO_APIC
-
-int nmi_watchdog = 0;
-
-static int __init setup_nmi_watchdog(char *str)
-{
-        get_option(&str, &nmi_watchdog);
-        return 1;
-}
-
-__setup("nmi_watchdog=", setup_nmi_watchdog);
-
-static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
-
-inline void nmi_watchdog_tick(struct pt_regs * regs)
-{
-	/*
-	 * the best way to detect wether a CPU has a 'hard lockup' problem
-	 * is to check it's local APIC timer IRQ counts. If they are not
-	 * changing then that CPU has some problem.
-	 *
-	 * as these watchdog NMI IRQs are broadcasted to every CPU, here
-	 * we only have to check the current processor.
-	 *
-	 * since NMIs dont listen to _any_ locks, we have to be extremely
-	 * careful not to rely on unsafe variables. The printk might lock
-	 * up though, so we have to break up console_lock first ...
-	 * [when there will be more tty-related locks, break them up
-	 *  here too!]
-	 */
-
-	static unsigned int last_irq_sums [NR_CPUS],
-				alert_counter [NR_CPUS];
-
-	/*
-	 * Since current-> is always on the stack, and we always switch
-	 * the stack NMI-atomically, it's safe to use smp_processor_id().
-	 */
-	int sum, cpu = smp_processor_id();
-
-	sum = apic_timer_irqs[cpu];
-
-	if (last_irq_sums[cpu] == sum) {
-		/*
-		 * Ayiee, looks like this CPU is stuck ...
-		 * wait a few IRQs (5 seconds) before doing the oops ...
-		 */
-		alert_counter[cpu]++;
-		if (alert_counter[cpu] == 5*HZ) {
-			spin_lock(&nmi_print_lock);
-			/*
-			 * We are in trouble anyway, lets at least try
-			 * to get a message out.
-			 */
-			bust_spinlocks();
-			printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu);
-			show_registers(regs);
-			printk("console shuts up ...\n");
-			console_silent();
-			spin_unlock(&nmi_print_lock);
-			do_exit(SIGSEGV);
-		}
-	} else {
-		last_irq_sums[cpu] = sum;
-		alert_counter[cpu] = 0;
-	}
-}
-#endif
-
 asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
 {
 	unsigned char reason = inb(0x61);
 
-
 	++nmi_count(smp_processor_id());
+
 	if (!(reason & 0xc0)) {
-#if CONFIG_X86_IO_APIC
+#if CONFIG_X86_LOCAL_APIC
 		/*
 		 * Ok, so this is none of the documented NMI sources,
 		 * so it must be the NMI watchdog.
@@ -503,11 +433,9 @@
 		if (nmi_watchdog) {
 			nmi_watchdog_tick(regs);
 			return;
-		} else
-			unknown_nmi_error(reason, regs);
-#else
-		unknown_nmi_error(reason, regs);
+		}
 #endif
+		unknown_nmi_error(reason, regs);
 		return;
 	}
 	if (reason & 0x80)
diff -u --recursive --new-file v2.4.9/linux/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile
--- v2.4.9/linux/arch/i386/lib/Makefile	Tue Jul  3 17:08:18 2001
+++ linux/arch/i386/lib/Makefile	Mon Sep 10 07:31:30 2001
@@ -13,5 +13,6 @@
 
 obj-$(CONFIG_X86_USE_3DNOW) += mmx.o
 obj-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
+obj-$(CONFIG_DEBUG_IOVIRT)  += iodebug.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.9/linux/arch/i386/lib/usercopy.c linux/arch/i386/lib/usercopy.c
--- v2.4.9/linux/arch/i386/lib/usercopy.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/i386/lib/usercopy.c	Tue Sep 18 14:10:43 2001
@@ -44,6 +44,7 @@
 unsigned long
 __generic_copy_to_user(void *to, const void *from, unsigned long n)
 {
+	prefetch(from);
 	if (access_ok(VERIFY_WRITE, to, n))
 		__copy_user(to,from,n);
 	return n;
@@ -52,6 +53,7 @@
 unsigned long
 __generic_copy_from_user(void *to, const void *from, unsigned long n)
 {
+	prefetchw(to);
 	if (access_ok(VERIFY_READ, from, n))
 		__copy_user_zeroing(to,from,n);
 	else
diff -u --recursive --new-file v2.4.9/linux/arch/i386/mm/extable.c linux/arch/i386/mm/extable.c
--- v2.4.9/linux/arch/i386/mm/extable.c	Fri Mar  2 11:12:07 2001
+++ linux/arch/i386/mm/extable.c	Mon Sep 17 13:16:30 2001
@@ -37,13 +37,13 @@
 search_exception_table(unsigned long addr)
 {
 	unsigned long ret = 0;
-	unsigned long flags;
 	
 #ifndef CONFIG_MODULES
 	/* There is only the kernel to search.  */
 	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
 	return ret;
 #else
+	unsigned long flags;
 	/* The kernel is the last "module" -- no need to treat it special.  */
 	struct module *mp;
 
diff -u --recursive --new-file v2.4.9/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- v2.4.9/linux/arch/i386/mm/fault.c	Tue May 15 00:16:51 2001
+++ linux/arch/i386/mm/fault.c	Mon Sep 17 22:52:35 2001
@@ -17,6 +17,7 @@
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/vt_kern.h>		/* For unblank_screen() */
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -25,6 +26,8 @@
 
 extern void die(const char *,struct pt_regs *,long);
 
+extern int console_loglevel;
+
 /*
  * Ugly, ugly, but the goto's result in better assembly..
  */
@@ -51,8 +54,14 @@
 	start &= PAGE_MASK;
 
 	for (;;) {
-		if (handle_mm_fault(current->mm, vma, start, 1) <= 0)
-			goto bad_area;
+	survive:
+		{
+			int fault = handle_mm_fault(current->mm, vma, start, 1);
+			if (!fault)
+				goto bad_area;
+			if (fault < 0)
+				goto out_of_memory;
+		}
 		if (!size)
 			break;
 		size--;
@@ -75,19 +84,52 @@
 
 bad_area:
 	return 0;
+
+out_of_memory:
+	if (current->pid == 1) {
+		current->policy |= SCHED_YIELD;
+		schedule();
+		goto survive;
+	}
+	goto bad_area;
 }
 
-extern spinlock_t console_lock, timerlist_lock;
+extern spinlock_t timerlist_lock;
 
 /*
  * Unlock any spinlocks which will prevent us from getting the
  * message out (timerlist_lock is acquired through the
  * console unblank code)
  */
-void bust_spinlocks(void)
+void bust_spinlocks(int yes)
 {
-	spin_lock_init(&console_lock);
 	spin_lock_init(&timerlist_lock);
+	if (yes) {
+		oops_in_progress = 1;
+#ifdef CONFIG_SMP
+		global_irq_lock = 0;	/* Many serial drivers do __global_cli() */
+#endif
+	} else {
+		int loglevel_save = console_loglevel;
+#ifdef CONFIG_VT
+		unblank_screen();
+#endif
+		oops_in_progress = 0;
+		/*
+		 * OK, the message is on the console.  Now we call printk()
+		 * without oops_in_progress set so that printk will give klogd
+		 * a poke.  Hold onto your hats...
+		 */
+		console_loglevel = 15;		/* NMI oopser may have shut the console up */
+		printk(" ");
+		console_loglevel = loglevel_save;
+	}
+}
+
+void do_BUG(const char *file, int line)
+{
+	bust_spinlocks(1);
+	printk("kernel BUG at %s:%d!\n", file, line);
 }
 
 asmlinkage void do_invalid_op(struct pt_regs *, unsigned long);
@@ -196,6 +238,7 @@
 				goto bad_area;
 	}
 
+ survive:
 	/*
 	 * If for any reason at all we couldn't handle the fault,
 	 * make sure we exit gracefully rather than endlessly redo
@@ -271,7 +314,7 @@
  * terminate things with extreme prejudice.
  */
 
-	bust_spinlocks();
+	bust_spinlocks(1);
 
 	if (address < PAGE_SIZE)
 		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
@@ -290,6 +333,7 @@
 		printk(KERN_ALERT "*pte = %08lx\n", page);
 	}
 	die("Oops", regs, error_code);
+	bust_spinlocks(0);
 	do_exit(SIGKILL);
 
 /*
@@ -298,6 +342,12 @@
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
+	if (tsk->pid == 1) {
+		tsk->policy |= SCHED_YIELD;
+		schedule();
+		down_read(&mm->mmap_sem);
+		goto survive;
+	}
 	printk("VM: killing process %s\n", tsk->comm);
 	if (error_code & 4)
 		do_exit(SIGKILL);
@@ -313,7 +363,7 @@
 	tsk->thread.cr2 = address;
 	tsk->thread.error_code = error_code;
 	tsk->thread.trap_no = 14;
-	info.si_code = SIGBUS;
+	info.si_signo = SIGBUS;
 	info.si_errno = 0;
 	info.si_code = BUS_ADRERR;
 	info.si_addr = (void *)address;
diff -u --recursive --new-file v2.4.9/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.4.9/linux/arch/i386/mm/init.c	Fri Apr 20 16:15:20 2001
+++ linux/arch/i386/mm/init.c	Thu Sep 20 19:59:20 2001
@@ -35,7 +35,9 @@
 #include <asm/fixmap.h>
 #include <asm/e820.h>
 #include <asm/apic.h>
+#include <asm/tlb.h>
 
+mmu_gather_t mmu_gathers[NR_CPUS];
 unsigned long highstart_pfn, highend_pfn;
 static unsigned long totalram_pages;
 static unsigned long totalhigh_pages;
diff -u --recursive --new-file v2.4.9/linux/arch/ia64/kernel/init_task.c linux/arch/ia64/kernel/init_task.c
--- v2.4.9/linux/arch/ia64/kernel/init_task.c	Sun Feb  6 18:42:40 2000
+++ linux/arch/ia64/kernel/init_task.c	Mon Sep 17 15:29:09 2001
@@ -13,7 +13,6 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
-static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
diff -u --recursive --new-file v2.4.9/linux/arch/ia64/kernel/ptrace.c linux/arch/ia64/kernel/ptrace.c
--- v2.4.9/linux/arch/ia64/kernel/ptrace.c	Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/kernel/ptrace.c	Tue Sep 18 17:03:51 2001
@@ -789,6 +789,21 @@
 	return 0;
 }
 
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	/* make sure the single step/take-branch tra bits are not set: */
+	ia64_psr(pt)->ss = 0;
+	ia64_psr(pt)->tb = 0;
+
+	/* Turn off flag indicating that the KRBS is sync'd with child's VM: */
+	child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED;
+}
+
 asmlinkage long
 sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,
 	    long arg4, long arg5, long arg6, long arg7, long stack)
@@ -965,27 +980,7 @@
 		goto out_tsk;
 
 	      case PTRACE_DETACH:		/* detach a process that was attached. */
-		ret = -EIO;
-		if (data > _NSIG)
-			goto out_tsk;
-
-		child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
-		child->exit_code = data;
-		write_lock_irqsave(&tasklist_lock, flags);
-		REMOVE_LINKS(child);
-		child->p_pptr = child->p_opptr;
-		SET_LINKS(child);
-		write_unlock_irqrestore(&tasklist_lock, flags);
-
-		/* make sure the single step/take-branch tra bits are not set: */
-		ia64_psr(pt)->ss = 0;
-		ia64_psr(pt)->tb = 0;
-
-		/* Turn off flag indicating that the KRBS is sync'd with child's VM: */
-		child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED;
-
-		wake_up_process(child);
-		ret = 0;
+		ret = ptrace_detach(child, data);
 		goto out_tsk;
 
 	      default:
diff -u --recursive --new-file v2.4.9/linux/arch/ia64/mm/init.c linux/arch/ia64/mm/init.c
--- v2.4.9/linux/arch/ia64/mm/init.c	Sun Aug 12 13:27:58 2001
+++ linux/arch/ia64/mm/init.c	Thu Sep 20 20:02:03 2001
@@ -24,6 +24,9 @@
 #include <asm/sal.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/tlb.h>
+
+mmu_gather_t mmu_gathers[NR_CPUS];
 
 /* References to section boundaries: */
 extern char _stext, _etext, _edata, __init_begin, __init_end;
diff -u --recursive --new-file v2.4.9/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c
--- v2.4.9/linux/arch/m68k/amiga/config.c	Tue Jul  3 17:08:18 2001
+++ linux/arch/m68k/amiga/config.c	Thu Sep 13 15:21:32 2001
@@ -44,22 +44,22 @@
 unsigned char amiga_psfreq;
 struct amiga_hw_present amiga_hw_present;
 
-static const char s_a500[] __initdata = "A500";
-static const char s_a500p[] __initdata = "A500+";
-static const char s_a600[] __initdata = "A600";
-static const char s_a1000[] __initdata = "A1000";
-static const char s_a1200[] __initdata = "A1200";
-static const char s_a2000[] __initdata = "A2000";
-static const char s_a2500[] __initdata = "A2500";
-static const char s_a3000[] __initdata = "A3000";
-static const char s_a3000t[] __initdata = "A3000T";
-static const char s_a3000p[] __initdata = "A3000+";
-static const char s_a4000[] __initdata = "A4000";
-static const char s_a4000t[] __initdata = "A4000T";
-static const char s_cdtv[] __initdata = "CDTV";
-static const char s_cd32[] __initdata = "CD32";
-static const char s_draco[] __initdata = "Draco";
-static const char *amiga_models[] __initdata = {
+static char s_a500[] __initdata = "A500";
+static char s_a500p[] __initdata = "A500+";
+static char s_a600[] __initdata = "A600";
+static char s_a1000[] __initdata = "A1000";
+static char s_a1200[] __initdata = "A1200";
+static char s_a2000[] __initdata = "A2000";
+static char s_a2500[] __initdata = "A2500";
+static char s_a3000[] __initdata = "A3000";
+static char s_a3000t[] __initdata = "A3000T";
+static char s_a3000p[] __initdata = "A3000+";
+static char s_a4000[] __initdata = "A4000";
+static char s_a4000t[] __initdata = "A4000T";
+static char s_cdtv[] __initdata = "CDTV";
+static char s_cd32[] __initdata = "CD32";
+static char s_draco[] __initdata = "Draco";
+static char *amiga_models[] __initdata = {
     s_a500, s_a500p, s_a600, s_a1000, s_a1200, s_a2000, s_a2500, s_a3000,
     s_a3000t, s_a3000p, s_a4000, s_a4000t, s_cdtv, s_cd32, s_draco,
 };
diff -u --recursive --new-file v2.4.9/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c
--- v2.4.9/linux/arch/m68k/kernel/process.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/m68k/kernel/process.c	Mon Sep 17 15:29:09 2001
@@ -38,7 +38,6 @@
  * alignment requirements and potentially different initial
  * setup.
  */
-static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
diff -u --recursive --new-file v2.4.9/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c
--- v2.4.9/linux/arch/m68k/kernel/ptrace.c	Wed Jul 25 17:10:18 2001
+++ linux/arch/m68k/kernel/ptrace.c	Tue Sep 18 17:03:51 2001
@@ -87,6 +87,19 @@
 	return 0;
 }
 
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	unsigned long tmp;
+	/* make sure the single step bit is not set. */
+	tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
+	put_reg(child, PT_SR, tmp);
+}
+
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -279,26 +292,9 @@
 			break;
 		}
 
-		case PTRACE_DETACH: { /* detach a process that was attached. */
-			long tmp;
-
-			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
-				break;
-			child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
-			child->exit_code = data;
-			write_lock_irqsave(&tasklist_lock, flags);
-			REMOVE_LINKS(child);
-			child->p_pptr = child->p_opptr;
-			SET_LINKS(child);
-			write_unlock_irqrestore(&tasklist_lock, flags);
-			/* make sure the single step bit is not set. */
-			tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
-			put_reg(child, PT_SR, tmp);
-			wake_up_process(child);
-			ret = 0;
+		case PTRACE_DETACH:	/* detach a process that was attached. */
+			ret = ptrace_detach(child, data);
 			break;
-		}
 
 		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
 		  	int i;
diff -u --recursive --new-file v2.4.9/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c
--- v2.4.9/linux/arch/m68k/mm/init.c	Tue Jul  3 17:08:18 2001
+++ linux/arch/m68k/mm/init.c	Thu Sep 20 20:02:03 2001
@@ -31,6 +31,9 @@
 #ifdef CONFIG_ATARI
 #include <asm/atari_stram.h>
 #endif
+#include <asm/tlb.h>
+
+mmu_gather_t mmu_gathers[NR_CPUS];
 
 unsigned long totalram_pages = 0;
 
diff -u --recursive --new-file v2.4.9/linux/arch/mips/Makefile linux/arch/mips/Makefile
--- v2.4.9/linux/arch/mips/Makefile	Tue Jul  3 17:08:18 2001
+++ linux/arch/mips/Makefile	Sun Sep  9 10:43:02 2001
@@ -36,8 +36,9 @@
 # crossformat linking we rely on the elf2ecoff tool for format conversion.
 #
 GCCFLAGS	:= -G 0 -mno-abicalls -fno-pic
-LINKFLAGS	+= -static -G 0
+LINKFLAGS	+= -static
 MODFLAGS	+= -mlong-calls
+LD		:= $(LD) -G 0
 
 ifdef CONFIG_REMOTE_DEBUG
 CFLAGS		:= $(CFLAGS) -g
@@ -55,12 +56,18 @@
 ifdef CONFIG_CPU_R4300
 GCCFLAGS	+= -mcpu=r4300 -mips2 -Wa,--trap
 endif
+ifdef CONFIG_CPU_VR41XX
+GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
+endif
 ifdef CONFIG_CPU_R4X00
 GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_MIPS32
 GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 endif
+ifdef CONFIG_CPU_MIPS64
+GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
+endif
 ifdef CONFIG_CPU_R5000
 GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap
 endif
@@ -68,7 +75,8 @@
 GCCFLAGS        += -mcpu=r5000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_NEVADA
-GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap -mmad
+# Cannot use -mmad with currently recommended tools
+GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_RM7000
 GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap
@@ -77,11 +85,6 @@
 GCCFLAGS	+= -mcpu=sb1 -mips2 -Wa,--trap
 endif
 
-ifdef CONFIG_MIPS_FPU_EMULATOR
-CORE_FILES	+=arch/mips/math-emu/fpu_emulator.o
-SUBDIRS		+=arch/mips/math-emu
-endif
-
 GCCFLAGS	+= -pipe
 
 CFLAGS		:= -I $(TOPDIR)/include/asm/gcc $(CFLAGS) $(GCCFLAGS)
@@ -89,6 +92,12 @@
 ASFLAGS		+= $(GCCFLAGS)
 
 #
+# We unconditionally build the math emulator
+#
+CORE_FILES	+=arch/mips/math-emu/fpu_emulator.o
+SUBDIRS		+=arch/mips/math-emu
+
+#
 # Board-dependent options and extra files
 #
 ifdef CONFIG_ALGOR_P4032
@@ -229,11 +238,27 @@
 # ITE 8172 eval board with QED 5231 CPU
 #
 ifdef CONFIG_MIPS_ITE8172
-LIBS		+= arch/mips/ite-boards/qed-4n-s01b/ite.o		     \
-		   arch/mips/ite-boards/generic/it8172.o
-SUBDIRS		+= arch/mips/ite-boards/generic				     \
-		   arch/mips/ite-boards/qed-4n-s01b
-LOADADDR	+= 0x80100000
+LIBS          += arch/mips/ite-boards/qed-4n-s01b/ite.o arch/mips/ite-boards/generic/it8172.o
+SUBDIRS       += arch/mips/ite-boards/generic arch/mips/ite-boards/qed-4n-s01b
+LOADADDR      += 0x80100000
+endif
+
+#
+# Globespan IVR eval board with QED 5231 CPU
+#
+ifdef CONFIG_MIPS_IVR
+LIBS          += arch/mips/ite-boards/ivr/ivr.o arch/mips/ite-boards/generic/it8172.o
+SUBDIRS       += arch/mips/ite-boards/generic arch/mips/ite-boards/ivr
+LOADADDR      += 0x80100000
+endif
+
+#
+# Au1000 eval board
+#
+ifdef CONFIG_MIPS_PB1000
+LIBS          += arch/mips/au1000/pb1000/pb1000.o arch/mips/au1000/common/au1000.o
+SUBDIRS       += arch/mips/au1000/pb1000 arch/mips/au1000/common
+LOADADDR      += 0x80100000
 endif
 
 #
@@ -273,14 +298,6 @@
 
 vmlinux.ecoff: vmlinux
 	@$(MAKEBOOT) $@
-
-zImage: vmlinux
-	@$(MAKEBOOT) zImage
-
-compressed: zImage
-
-zdisk: vmlinux
-	@$(MAKEBOOT) zdisk
 
 archclean:
 	@$(MAKEBOOT) clean
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/Makefile linux/arch/mips/au1000/common/Makefile
--- v2.4.9/linux/arch/mips/au1000/common/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/common/Makefile	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,31 @@
+#
+#  Copyright 2000 MontaVista Software Inc.
+#  Author: MontaVista Software, Inc.
+#     	ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Au1000 CPU, generic files.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: au1000.o
+
+O_TARGET := au1000.o
+
+obj-y := prom.o dbg_io.o int-handler.o irq.o puts.o time.o reset.o
+
+obj-$(CONFIG_AU1000_UART) += serial.o             
+obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o             
+obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o
+
+ramdisk.o: 
+	mkramobj ramdisk ramdisk.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/dbg_io.c linux/arch/mips/au1000/common/dbg_io.c
--- v2.4.9/linux/arch/mips/au1000/common/dbg_io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/common/dbg_io.c	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,118 @@
+
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/au1000.h>
+
+#ifdef CONFIG_REMOTE_DEBUG
+
+/*
+ * FIXME the user should be able to select the
+ * uart to be used for debugging.
+ */
+#define	DEBUG_BASE  UART2_ADDR
+/**/
+
+/* we need uint32 uint8 */
+/* #include "types.h" */
+typedef         unsigned char uint8;
+typedef         unsigned int  uint32;
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+
+#define UART_RX		0	/* Receive buffer */
+#define UART_TX		4	/* Transmit buffer */
+#define UART_IER	8	/* Interrupt Enable Register */
+#define UART_IIR	0xC	/* Interrupt ID Register */
+#define UART_FCR	0x10	/* FIFO Control Register */
+#define UART_LCR	0x14	/* Line Control Register */
+#define UART_MCR	0x18	/* Modem Control Register */
+#define UART_LSR	0x1C	/* Line Status Register */
+#define UART_MSR	0x20	/* Modem Status Register */
+#define UART_CLK	0x28	/* Baud Rat4e Clock Divider */
+#define UART_MOD_CNTRL	0x100	/* Module Control */
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y)    (inl(DEBUG_BASE + y) & 0xff)
+#define UART16550_WRITE(y,z) (outl(z&0xff, DEBUG_BASE + y))
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+
+	if (UART16550_READ(UART_MOD_CNTRL) != 0x3) {
+		UART16550_WRITE(UART_MOD_CNTRL, 3);
+	}
+	cal_r4koff();
+
+	/* disable interrupts */
+	UART16550_WRITE(UART_IER, 0);
+
+	/* set up baud rate */
+	{ 
+		uint32 divisor;
+
+		/* set divisor */
+		divisor = get_au1000_uart_baud() / baud;
+		UART16550_WRITE(UART_CLK, divisor & 0xffff);
+	}
+
+	/* set data format */
+	UART16550_WRITE(UART_LCR, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(UART16550_BAUD_115200,
+			  UART16550_DATA_8BIT,
+			  UART16550_PARITY_NONE,
+			  UART16550_STOP_1BIT);
+	}
+
+	while((UART16550_READ(UART_LSR) & 0x1) == 0);
+	return UART16550_READ(UART_RX);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+	int i;
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(UART16550_BAUD_115200,
+			  UART16550_DATA_8BIT,
+			  UART16550_PARITY_NONE,
+			  UART16550_STOP_1BIT);
+	}
+
+	while ((UART16550_READ(UART_LSR)&0x40) == 0);
+	UART16550_WRITE(UART_TX, byte);
+	//for (i=0;i<0xfff;i++);
+
+	return 1;
+}
+
+#endif
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/int-handler.S linux/arch/mips/au1000/common/int-handler.S
--- v2.4.9/linux/arch/mips/au1000/common/int-handler.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/common/int-handler.S	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: ppopov@mvista.com
+ *
+ * Interrupt dispatcher for Au1000 boards.
+ *
+ * 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.
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+	.text
+	.set	macro
+	.set	noat
+	.align	5
+
+NESTED(au1000_IRQ, PT_SIZE, sp)
+	SAVE_ALL
+	CLI				# Important: mark KERNEL mode !
+
+	mfc0	t0,CP0_CAUSE		# get pending interrupts
+	mfc0	t1,CP0_STATUS		# get enabled interrupts
+	and	t0,t1			# isolate allowed ones
+
+	andi	t0,0xff00		# isolate pending bits
+	beqz	t0, 3f			# spurious interrupt
+
+	andi	a0, t0, CAUSEF_IP7
+	beq	a0, zero, 1f
+	move	a0, sp
+	jal	mips_timer_interrupt
+	j	ret_from_irq
+
+1:
+	andi	a0, t0, CAUSEF_IP2	# Interrupt Controller 0, Request 0
+	beq	a0, zero, 2f	        
+	move	a0,sp  
+	jal	intc0_req0_irqdispatch
+	j	ret_from_irq
+2:
+	andi	a0, t0, CAUSEF_IP3	# Interrupt Controller 0, Request 1
+	beq	a0, zero, 3f	       
+	move	a0,sp  
+	jal	intc0_req1_irqdispatch
+	j	ret_from_irq
+3:
+	andi	a0, t0, CAUSEF_IP4	# Interrupt Controller 1, Request 0
+	beq	a0, zero, 4f	       
+	move	a0,sp  
+	jal	intc1_req0_irqdispatch
+	j	ret_from_irq
+4:
+	andi	a0, t0, CAUSEF_IP5	# Interrupt Controller 1, Request 1
+	beq	a0, zero, 5f	       
+	move	a0, sp  
+	jal	intc1_req1_irqdispatch
+	j	ret_from_irq
+
+5:	
+	move	a0, sp
+	jal	mips_spurious_interrupt
+done:
+	j	ret_from_irq
+END(au1000_IRQ)
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/irq.c linux/arch/mips/au1000/common/irq.c
--- v2.4.9/linux/arch/mips/au1000/common/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/common/irq.c	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,471 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1000 interrupt routines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *		ppopov@mvista.com or source@mvista.com
+ *
+ *  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  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+
+#undef DEBUG_IRQ
+#ifdef DEBUG_IRQ
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define EXT_INTC0_REQ0 2 /* IP 2 */
+#define EXT_INTC0_REQ1 3 /* IP 3 */
+#define EXT_INTC1_REQ0 4 /* IP 4 */
+#define EXT_INTC1_REQ1 5 /* IP 5 */
+#define MIPS_TIMER_IP  7 /* IP 7 */
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void breakpoint(void);
+#endif
+
+extern asmlinkage void au1000_IRQ(void);
+
+extern void set_debug_traps(void);
+extern irq_cpustat_t irq_stat [];
+extern irq_desc_t irq_desc[NR_IRQS];
+
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+
+static void setup_local_irq(unsigned int irq, int type, int int_req);
+static unsigned int startup_irq(unsigned int irq);
+static void end_irq(unsigned int irq_nr);
+static inline void mask_and_ack_level_irq(unsigned int irq_nr);
+static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr);
+static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr);
+static inline void local_enable_irq(unsigned int irq_nr);
+static inline void local_disable_irq(unsigned int irq_nr);
+
+unsigned long spurious_interrupts;
+extern unsigned int do_IRQ(int irq, struct pt_regs *regs);
+extern void __init init_generic_irq(void);
+
+static inline void sync(void)
+{
+	__asm volatile ("sync");
+}
+
+
+/* Function for careful CP0 interrupt mask access */
+static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
+{
+	unsigned long status = read_32bit_cp0_register(CP0_STATUS);
+	status &= ~((clr_mask & 0xFF) << 8);
+	status |=   (set_mask & 0xFF) << 8;
+	write_32bit_cp0_register(CP0_STATUS, status);
+}
+
+
+static inline void mask_cpu_irq_input(unsigned int irq_nr)
+{
+	modify_cp0_intmask(irq_nr, 0);
+}
+
+
+static inline void unmask_cpu_irq_input(unsigned int irq_nr)
+{
+	modify_cp0_intmask(0, irq_nr);
+}
+
+
+static void disable_cpu_irq_input(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	mask_cpu_irq_input(irq_nr);
+	restore_flags(flags);
+}
+
+
+static void enable_cpu_irq_input(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	unmask_cpu_irq_input(irq_nr);
+	restore_flags(flags);
+}
+
+
+static void setup_local_irq(unsigned int irq_nr, int type, int int_req)
+{
+	/* Config2[n], Config1[n], Config0[n] */
+	if (irq_nr > AU1000_LAST_INTC0_INT) {
+		switch (type) {
+			case INTC_INT_RISE_EDGE: /* 0:0:1 */
+				outl(1<<irq_nr,INTC1_CONFIG2_CLEAR);
+				outl(1<<irq_nr, INTC1_CONFIG1_CLEAR);
+				outl(1<<irq_nr, INTC1_CONFIG0_SET);
+				break;
+			case INTC_INT_FALL_EDGE: /* 0:1:0 */
+				outl(1<<irq_nr, INTC1_CONFIG2_CLEAR);
+				outl(1<<irq_nr, INTC1_CONFIG1_SET);
+				outl(1<<irq_nr, INTC1_CONFIG0_CLEAR);
+				break;
+			case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
+				outl(1<<irq_nr, INTC1_CONFIG2_SET);
+				outl(1<<irq_nr, INTC1_CONFIG1_CLEAR);
+				outl(1<<irq_nr, INTC1_CONFIG0_SET);
+				break;
+			case INTC_INT_LOW_LEVEL: /* 1:1:0 */
+				outl(1<<irq_nr, INTC1_CONFIG2_SET);
+				outl(1<<irq_nr, INTC1_CONFIG1_SET);
+				outl(1<<irq_nr, INTC1_CONFIG0_CLEAR);
+				break;
+			case INTC_INT_DISABLED: /* 0:0:0 */
+				outl(1<<irq_nr, INTC1_CONFIG0_CLEAR);
+				outl(1<<irq_nr, INTC1_CONFIG1_CLEAR);
+				outl(1<<irq_nr, INTC1_CONFIG2_CLEAR);
+				break;
+			default: /* disable the interrupt */
+				printk("unexpected int type %d (irq %d)\n", type, irq_nr);
+				outl(1<<irq_nr, INTC1_CONFIG0_CLEAR);
+				outl(1<<irq_nr, INTC1_CONFIG1_CLEAR);
+				outl(1<<irq_nr, INTC1_CONFIG2_CLEAR);
+				return;
+		}
+		if (int_req) /* assign to interrupt request 1 */
+			outl(1<<irq_nr, INTC1_ASSIGN_REQ_CLEAR);
+		else	     /* assign to interrupt request 0 */
+			outl(1<<irq_nr, INTC1_ASSIGN_REQ_SET);
+		outl(1<<irq_nr, INTC1_SOURCE_SET);
+		outl(1<<irq_nr, INTC1_MASK_CLEAR);
+	}
+	else {
+		switch (type) {
+			case INTC_INT_RISE_EDGE: /* 0:0:1 */
+				outl(1<<irq_nr,INTC0_CONFIG2_CLEAR);
+				outl(1<<irq_nr, INTC0_CONFIG1_CLEAR);
+				outl(1<<irq_nr, INTC0_CONFIG0_SET);
+				break;
+			case INTC_INT_FALL_EDGE: /* 0:1:0 */
+				outl(1<<irq_nr, INTC0_CONFIG2_CLEAR);
+				outl(1<<irq_nr, INTC0_CONFIG1_SET);
+				outl(1<<irq_nr, INTC0_CONFIG0_CLEAR);
+				break;
+			case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
+				outl(1<<irq_nr, INTC0_CONFIG2_SET);
+				outl(1<<irq_nr, INTC0_CONFIG1_CLEAR);
+				outl(1<<irq_nr, INTC0_CONFIG0_SET);
+				break;
+			case INTC_INT_LOW_LEVEL: /* 1:1:0 */
+				outl(1<<irq_nr, INTC0_CONFIG2_SET);
+				outl(1<<irq_nr, INTC0_CONFIG1_SET);
+				outl(1<<irq_nr, INTC0_CONFIG0_CLEAR);
+				break;
+			case INTC_INT_DISABLED: /* 0:0:0 */
+				outl(1<<irq_nr, INTC0_CONFIG0_CLEAR);
+				outl(1<<irq_nr, INTC0_CONFIG1_CLEAR);
+				outl(1<<irq_nr, INTC0_CONFIG2_CLEAR);
+				break;
+			default: /* disable the interrupt */
+				printk("unexpected int type %d (irq %d)\n", type, irq_nr);
+				outl(1<<irq_nr, INTC0_CONFIG0_CLEAR);
+				outl(1<<irq_nr, INTC0_CONFIG1_CLEAR);
+				outl(1<<irq_nr, INTC0_CONFIG2_CLEAR);
+				return;
+		}
+		if (int_req) /* assign to interrupt request 1 */
+			outl(1<<irq_nr, INTC0_ASSIGN_REQ_CLEAR);
+		else	     /* assign to interrupt request 0 */
+			outl(1<<irq_nr, INTC0_ASSIGN_REQ_SET);
+		outl(1<<irq_nr, INTC0_SOURCE_SET);
+		outl(1<<irq_nr, INTC0_MASK_CLEAR);
+	}
+	sync();
+}
+
+
+static unsigned int startup_irq(unsigned int irq_nr)
+{
+	local_enable_irq(irq_nr);
+	return 0; 
+}
+
+
+static void shutdown_irq(unsigned int irq_nr)
+{
+	local_disable_irq(irq_nr);
+	return;
+}
+
+
+static inline void local_enable_irq(unsigned int irq_nr)
+{
+	if (irq_nr > AU1000_LAST_INTC0_INT) {
+		outl(1<<irq_nr, INTC1_MASK_SET);
+	}
+	else {
+		outl(1<<irq_nr, INTC0_MASK_SET);
+	}
+	sync();
+}
+
+
+static inline void local_disable_irq(unsigned int irq_nr)
+{
+	if (irq_nr > AU1000_LAST_INTC0_INT) {
+		outl(1<<irq_nr, INTC1_MASK_CLEAR);
+	}
+	else {
+		outl(1<<irq_nr, INTC0_MASK_CLEAR);
+	}
+	sync();
+}
+
+
+static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
+{
+	if (irq_nr > AU1000_LAST_INTC0_INT) {
+		outl(1<<irq_nr, INTC1_R_EDGE_DETECT_CLEAR);
+		outl(1<<irq_nr, INTC1_MASK_CLEAR);
+	}
+	else {
+		outl(1<<irq_nr, INTC0_R_EDGE_DETECT_CLEAR);
+		outl(1<<irq_nr, INTC0_MASK_CLEAR);
+	}
+	sync();
+}
+
+
+static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr)
+{
+	if (irq_nr > AU1000_LAST_INTC0_INT) {
+		outl(1<<irq_nr, INTC1_F_EDGE_DETECT_CLEAR);
+		outl(1<<irq_nr, INTC1_MASK_CLEAR);
+	}
+	else {
+		outl(1<<irq_nr, INTC0_F_EDGE_DETECT_CLEAR);
+		outl(1<<irq_nr, INTC0_MASK_CLEAR);
+	}
+}
+
+
+static inline void mask_and_ack_level_irq(unsigned int irq_nr)
+{
+	local_disable_irq(irq_nr);
+	sync();
+	return;
+}
+
+
+static void end_irq(unsigned int irq_nr)
+{
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		local_enable_irq(irq_nr);
+	else
+		printk("warning: end_irq %d did not enable\n", irq_nr);
+}
+
+
+static struct hw_interrupt_type rise_edge_irq_type = {
+	"Au1000 Rise Edge",
+	startup_irq,
+	shutdown_irq,
+	local_enable_irq,
+	local_disable_irq,
+	mask_and_ack_rise_edge_irq,
+	end_irq,
+	NULL
+};
+
+
+static struct hw_interrupt_type fall_edge_irq_type = {
+	"Au1000 Fall Edge",
+	startup_irq,
+	shutdown_irq,
+	local_enable_irq,
+	local_disable_irq,
+	mask_and_ack_fall_edge_irq,
+	end_irq,
+	NULL
+};
+
+
+static struct hw_interrupt_type level_irq_type = {
+	"Au1000 Level",
+	startup_irq,
+	shutdown_irq,
+	local_enable_irq,
+	local_disable_irq,
+	mask_and_ack_level_irq,
+	end_irq,
+	NULL
+};
+
+
+void enable_cpu_timer(void)
+{
+	enable_cpu_irq_input(1<<MIPS_TIMER_IP); /* timer interrupt */
+}
+
+
+void __init init_IRQ(void)
+{
+	int i;
+	unsigned long cp0_status;
+
+	cp0_status = read_32bit_cp0_register(CP0_STATUS);
+	memset(irq_desc, 0, sizeof(irq_desc));
+	set_except_vector(0, au1000_IRQ);
+
+	init_generic_irq();
+	
+	/* 
+	 * Setup high priority interrupts on int_request0; low priority on
+	 * int_request1
+	 */
+	for (i = 0; i <= NR_IRQS; i++) {
+		switch (i) {
+			case AU1000_MAC0_DMA_INT:
+			case AU1000_MAC1_DMA_INT:
+				setup_local_irq(i, INTC_INT_HIGH_LEVEL, 0);
+				irq_desc[i].handler = &level_irq_type;
+				break;
+			default: /* active high, level interrupt */
+				setup_local_irq(i, INTC_INT_HIGH_LEVEL, 1);
+				irq_desc[i].handler = &level_irq_type;
+				break;
+		}
+	}
+
+	set_cp0_status(ALLINTS);
+#ifdef CONFIG_REMOTE_DEBUG
+	/* If local serial I/O used for debug port, enter kgdb at once */
+	puts("Waiting for kgdb to connect...");
+	set_debug_traps();
+	breakpoint(); 
+#endif
+}
+
+
+void mips_spurious_interrupt(struct pt_regs *regs)
+{
+	spurious_interrupts++;
+}
+
+
+void intc0_req0_irqdispatch(struct pt_regs *regs)
+{
+	int irq = 0, i;
+	unsigned long int_request;
+
+	int_request = inl(INTC0_REQ0_INT);
+
+	if (!int_request) return;
+
+	for (i=0; i<32; i++) {
+		if ((int_request & 0x1)) {
+			do_IRQ(irq, regs);
+		}
+		irq++;
+		int_request >>= 1;
+	}
+}
+
+
+void intc0_req1_irqdispatch(struct pt_regs *regs)
+{
+	int irq = 0, i;
+	unsigned long int_request;
+
+	int_request = inl(INTC0_REQ1_INT);
+
+	if (!int_request) return;
+
+	for (i=0; i<32; i++) {
+		if ((int_request & 0x1)) {
+			do_IRQ(irq, regs);
+		}
+		irq++;
+		int_request >>= 1;
+	}
+}
+
+
+void intc1_req0_irqdispatch(struct pt_regs *regs)
+{
+	int irq = 0, i;
+	unsigned long int_request;
+
+	int_request = inl(INTC1_REQ0_INT);
+
+	if (!int_request) return;
+
+	for (i=0; i<32; i++) {
+		if ((int_request & 0x1)) {
+			do_IRQ(irq, regs);
+		}
+		irq++;
+		int_request >>= 1;
+	}
+}
+
+
+void intc1_req1_irqdispatch(struct pt_regs *regs)
+{
+	int irq = 0, i;
+	unsigned long int_request;
+
+	int_request = inl(INTC1_REQ1_INT);
+
+	if (!int_request) return;
+
+	for (i=0; i<32; i++) {
+		if ((int_request & 0x1)) {
+			do_IRQ(irq, regs);
+		}
+		irq++;
+		int_request >>= 1;
+	}
+}
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/prom.c linux/arch/mips/au1000/common/prom.c
--- v2.4.9/linux/arch/mips/au1000/common/prom.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/common/prom.c	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,120 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *    PROM library initialisation code, assuming a version of
+ *    pmon is the boot code.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's 
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+/* #define DEBUG_CMDLINE */
+
+char arcs_cmdline[COMMAND_LINE_SIZE];
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+typedef struct {
+	char *name;
+/*	char *val; */
+} t_env_var;
+
+
+char * __init prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+
+void  __init prom_init_cmdline(void)
+{
+	char *cp;
+	int actr;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while(actr < prom_argc) {
+	        strcpy(cp, prom_argv[actr]);
+		cp += strlen(prom_argv[actr]);
+		*cp++ = ' ';
+		actr++;
+	}
+	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+		--cp;
+	*cp = '\0';
+
+}
+
+
+char *prom_getenv(char *envname)
+{
+	/*
+	 * Return a pointer to the given environment variable.
+	 * Environment variables are stored in the form of "memsize=64".
+	 */
+
+	t_env_var *env = (t_env_var *)prom_envp;
+	int i;
+
+	i = strlen(envname);
+
+	while(env->name) {
+		if(strncmp(envname, env->name, i) == 0) {
+			return(env->name + strlen(envname) + 1);
+		}
+		env++;
+	}
+	return(NULL);
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+	if(c >= '0' && c <= '9')
+	return c - '0';
+	if(c >= 'a' && c <= 'f')
+	return c - 'a' + 10;
+	return 0; /* foo */
+}
+
+int __init page_is_ram(unsigned long pagenr)
+{
+	return 1;
+}
+
+void prom_free_prom_memory (void)
+{
+}
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/puts.c linux/arch/mips/au1000/common/puts.c
--- v2.4.9/linux/arch/mips/au1000/common/puts.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/common/puts.c	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,144 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Low level uart routines to directly access a 16550 uart.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+
+#define SERIAL_BASE   0xB1100000 /* au1000, uart 0 */
+#define SER_CMD       0x7
+#define SER_DATA      0x1
+#define TX_BUSY       0x20
+
+#define TIMEOUT       0xffffff
+#define SLOW_DOWN
+
+static const char digits[16] = "0123456789abcdef";
+static volatile unsigned long * const com1 = (unsigned char *)SERIAL_BASE;
+
+
+#ifdef SLOW_DOWN
+static inline void slow_down()
+{
+    int k;
+    for (k=0; k<10000; k++);
+}
+#else
+#define slow_down()
+#endif
+
+void
+putch(const unsigned char c)
+{
+    unsigned char ch;
+    int i = 0;
+
+    do {
+        ch = com1[SER_CMD];
+        slow_down();
+        i++;
+        if (i>TIMEOUT) {
+            break;
+        }
+    } while (0 == (ch & TX_BUSY));
+    com1[SER_DATA] = c;
+}
+
+void
+puts(unsigned char *cp)
+{
+    unsigned char ch;
+    int i = 0;
+
+    while (*cp) {
+        do {
+             ch = com1[SER_CMD];
+            slow_down();
+            i++;
+            if (i>TIMEOUT) {
+                break;
+            }
+        } while (0 == (ch & TX_BUSY));
+        com1[SER_DATA] = *cp++;
+    }
+    putch('\r');
+    putch('\n');
+}
+
+void
+fputs(unsigned char *cp)
+{
+    unsigned char ch;
+    int i = 0;
+
+    while (*cp) {
+
+        do {
+             ch = com1[SER_CMD];
+             slow_down();
+            i++;
+            if (i>TIMEOUT) {
+                break;
+            }
+        } while (0 == (ch & TX_BUSY));
+        com1[SER_DATA] = *cp++;
+    }
+}
+
+
+void
+put64(uint64_t ul)
+{
+    int cnt;
+    unsigned ch;
+
+    cnt = 16;            /* 16 nibbles in a 64 bit long */
+    putch('0');
+    putch('x');
+    do {
+        cnt--;
+        ch = (unsigned char)(ul >> cnt * 4) & 0x0F;
+                putch(digits[ch]);
+    } while (cnt > 0);
+}
+
+void
+put32(unsigned u)
+{
+    int cnt;
+    unsigned ch;
+
+    cnt = 8;            /* 8 nibbles in a 32 bit long */
+    putch('0');
+    putch('x');
+    do {
+        cnt--;
+        ch = (unsigned char)(u >> cnt * 4) & 0x0F;
+                putch(digits[ch]);
+    } while (cnt > 0);
+}
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/reset.c linux/arch/mips/au1000/common/reset.c
--- v2.4.9/linux/arch/mips/au1000/common/reset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/common/reset.c	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,60 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Au1000 reset routines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void au1000_restart(char *command)
+{
+	set_cp0_status(ST0_BEV | ST0_ERL);
+	set_cp0_config(CONF_CM_UNCACHED);
+	flush_cache_all();
+	write_32bit_cp0_register(CP0_WIRED, 0);
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void au1000_halt(void)
+{
+	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+	while (1)
+		__asm__(".set\tmips3\n\t"
+	                "wait\n\t"
+			".set\tmips0");
+}
+
+void au1000_power_off(void)
+{
+	au1000_halt();
+}
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/serial.c linux/arch/mips/au1000/common/serial.c
--- v2.4.9/linux/arch/mips/au1000/common/serial.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/common/serial.c	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,3100 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Au1000 serial port driver.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  Derived almost entirely from drivers/char/serial.c:
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 
+ * 		1998, 1999  Theodore Ts'o
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+static char *serial_version = "1.01";
+static char *serial_revdate = "2001-02-08";
+
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#undef SERIAL_PARANOIA_CHECK
+#define CONFIG_SERIAL_NOPAUSE_IO
+#define SERIAL_DO_RESTART
+
+
+/* Set of debugging defines */
+
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+#undef SERIAL_DEBUG_PCI
+#undef SERIAL_DEBUG_AUTOCONF
+
+#ifdef MODULE
+#undef CONFIG_AU1000_SERIAL_CONSOLE
+#endif
+
+#define CONFIG_SERIAL_RSA
+
+#define RS_STROBE_TIME (10*HZ)
+#define RS_ISR_PASS_LIMIT 256
+  
+/*
+ * End of serial driver configuration section.
+ */
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+
+#include <linux/types.h>
+#ifdef LOCAL_HEADERS
+#include "serial_local.h"
+#else
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <asm/au1000.h>
+#include <asm/serial.h>
+#define LOCAL_VERSTRING ""
+#endif
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/delay.h>
+#ifdef CONFIG_AU1000_SERIAL_CONSOLE
+#include <linux/console.h>
+#endif
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#endif
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+
+#ifdef CONFIG_MAC_SERIAL
+#define SERIAL_DEV_OFFSET	2
+#else
+#define SERIAL_DEV_OFFSET	0
+#endif
+
+#ifdef SERIAL_INLINE
+#define _INLINE_ inline
+#else
+#define _INLINE_
+#endif
+
+static char *serial_name = "Serial driver";
+
+static DECLARE_TASK_QUEUE(tq_serial);
+
+static struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+
+static struct timer_list serial_timer;
+
+extern unsigned long get_au1000_uart_baud(void);
+
+/* serial subtype definitions */
+#ifndef SERIAL_TYPE_NORMAL
+#define SERIAL_TYPE_NORMAL	1
+#define SERIAL_TYPE_CALLOUT	2
+#endif
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+/*
+ * IRQ_timeout		- How long the timeout should be for each IRQ
+ * 				should be after the IRQ has been active.
+ */
+
+static struct async_struct *IRQ_ports[NR_IRQS];
+static int IRQ_timeout[NR_IRQS];
+#ifdef CONFIG_AU1000_SERIAL_CONSOLE
+static struct console sercons;
+static int lsr_break_flag;
+#endif
+#if defined(CONFIG_AU1000_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+static unsigned long break_pressed; /* break, really ... */
+#endif
+
+static void autoconfig(struct serial_state * state);
+static void change_speed(struct async_struct *info, struct termios *old);
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
+
+/*
+ * Here we define the default xmit fifo size used for each type of
+ * UART
+ */
+static struct serial_uart_config uart_config[] = {
+	{ "unknown", 1, 0 }, 
+	{ "8250", 1, 0 }, 
+	{ "16450", 1, 0 }, 
+	{ "16550", 1, 0 }, 
+	{ 0, 0}
+};
+
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+	SERIAL_PORT_DFNS	/* Defined in serial.h */
+};
+
+#define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
+
+#ifndef PREPARE_FUNC
+#define PREPARE_FUNC(dev)  (dev->prepare)
+#define ACTIVATE_FUNC(dev)  (dev->activate)
+#define DEACTIVATE_FUNC(dev)  (dev->deactivate)
+#endif
+
+#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
+
+static struct tty_struct *serial_table[NR_PORTS];
+static struct termios *serial_termios[NR_PORTS];
+static struct termios *serial_termios_locked[NR_PORTS];
+
+
+#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
+#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
+ kdevname(tty->device), (info->flags), serial_refcount,info->count,tty->count,s)
+#else
+#define DBG_CNT(s)
+#endif
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write.  We need to
+ * lock it in case the copy_from_user blocks while swapping in a page,
+ * and some other program tries to do a serial write at the same time.
+ * Since the lock will only come under contention when the system is
+ * swapping and available memory is low, it makes sense to share one
+ * buffer across all the serial ports, since it significantly saves
+ * memory if large numbers of serial ports are open.
+ */
+static unsigned char *tmp_buf;
+#ifdef DECLARE_MUTEX
+static DECLARE_MUTEX(tmp_buf_sem);
+#else
+static struct semaphore tmp_buf_sem = MUTEX;
+#endif
+
+
+static inline int serial_paranoia_check(struct async_struct *info,
+					kdev_t device, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+	static const char *badmagic =
+		"Warning: bad magic number for serial struct (%s) in %s\n";
+	static const char *badinfo =
+		"Warning: null async_struct for (%s) in %s\n";
+
+	if (!info) {
+		printk(badinfo, kdevname(device), routine);
+		return 1;
+	}
+	if (info->magic != SERIAL_MAGIC) {
+		printk(badmagic, kdevname(device), routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+
+static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset)
+{
+	return (inl(info->port+offset) & 0xff);
+}
+
+static _INLINE_ void serial_out(struct async_struct *info, int offset, int value)
+{
+	outl(value & 0xff, info->port+offset);
+}
+
+
+/*
+ * We used to support using pause I/O for certain machines.  We
+ * haven't supported this for a while, but just in case it's badly
+ * needed for certain old 386 machines, I've left these #define's
+ * in....
+ */
+#define serial_inp(info, offset)		serial_in(info, offset)
+#define serial_outp(info, offset, value)	serial_out(info, offset, value)
+
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void rs_stop(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "rs_stop"))
+		return;
+	
+	save_flags(flags); cli();
+	if (info->IER & UART_IER_THRI) {
+		info->IER &= ~UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+	}
+	restore_flags(flags);
+}
+
+static void rs_start(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_start"))
+		return;
+	
+	save_flags(flags); cli();
+	if (info->xmit.head != info->xmit.tail
+	    && info->xmit.buf
+	    && !(info->IER & UART_IER_THRI)) {
+		info->IER |= UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+	}
+	restore_flags(flags);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines.  All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt().  They were separated out for readability's sake.
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off.  People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible.  After you are done making modifications, it is not a bad
+ * idea to do:
+ * 
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void rs_sched_event(struct async_struct *info,
+				  int event)
+{
+	info->event |= 1 << event;
+	queue_task(&info->tqueue, &tq_serial);
+	mark_bh(SERIAL_BH);
+}
+
+static _INLINE_ void receive_chars(struct async_struct *info,
+				 int *status, struct pt_regs * regs)
+{
+	struct tty_struct *tty = info->tty;
+	unsigned char ch;
+	int ignored = 0;
+	struct	async_icount *icount;
+
+	icount = &info->state->icount;
+	do {
+		ch = serial_inp(info, UART_RX);
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+			goto ignore_char;
+		*tty->flip.char_buf_ptr = ch;
+		icount->rx++;
+		
+#ifdef SERIAL_DEBUG_INTR
+		printk("DR%02x:%02x...", ch, *status);
+#endif
+		*tty->flip.flag_buf_ptr = 0;
+		if (*status & (UART_LSR_BI | UART_LSR_PE |
+			       UART_LSR_FE | UART_LSR_OE)) {
+			/*
+			 * For statistics only
+			 */
+			if (*status & UART_LSR_BI) {
+				*status &= ~(UART_LSR_FE | UART_LSR_PE);
+				icount->brk++;
+				/*
+				 * We do the SysRQ and SAK checking
+				 * here because otherwise the break
+				 * may get masked by ignore_status_mask
+				 * or read_status_mask.
+				 */
+#if defined(CONFIG_AU1000_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+				if (info->line == sercons.index) {
+					if (!break_pressed) {
+						break_pressed = jiffies;
+						goto ignore_char;
+					}
+					break_pressed = 0;
+				}
+#endif
+				if (info->flags & ASYNC_SAK)
+					do_SAK(tty);
+			} else if (*status & UART_LSR_PE)
+				icount->parity++;
+			else if (*status & UART_LSR_FE)
+				icount->frame++;
+			if (*status & UART_LSR_OE)
+				icount->overrun++;
+
+			/*
+			 * Now check to see if character should be
+			 * ignored, and mask off conditions which
+			 * should be ignored.
+			 */
+			if (*status & info->ignore_status_mask) {
+				if (++ignored > 100)
+					break;
+				goto ignore_char;
+			}
+			*status &= info->read_status_mask;
+
+#ifdef CONFIG_AU1000_SERIAL_CONSOLE
+			if (info->line == sercons.index) {
+				/* Recover the break flag from console xmit */
+				*status |= lsr_break_flag;
+				lsr_break_flag = 0;
+			}
+#endif
+			if (*status & (UART_LSR_BI)) {
+#ifdef SERIAL_DEBUG_INTR
+				printk("handling break....");
+#endif
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+			} else if (*status & UART_LSR_PE)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (*status & UART_LSR_FE)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+			if (*status & UART_LSR_OE) {
+				/*
+				 * Overrun is special, since it's
+				 * reported immediately, and doesn't
+				 * affect the current character
+				 */
+				tty->flip.count++;
+				tty->flip.flag_buf_ptr++;
+				tty->flip.char_buf_ptr++;
+				*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+				if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+					goto ignore_char;
+			}
+		}
+#if defined(CONFIG_AU1000_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+		if (break_pressed && info->line == sercons.index) {
+			if (ch != 0 &&
+			    time_before(jiffies, break_pressed + HZ*5)) {
+				handle_sysrq(ch, regs, NULL, NULL);
+				break_pressed = 0;
+				goto ignore_char;
+			}
+			break_pressed = 0;
+		}
+#endif
+		tty->flip.flag_buf_ptr++;
+		tty->flip.char_buf_ptr++;
+		tty->flip.count++;
+	ignore_char:
+		*status = serial_inp(info, UART_LSR);
+	} while (*status & UART_LSR_DR);
+	tty_flip_buffer_push(tty);
+}
+
+static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
+{
+	int count;
+
+	if (info->x_char) {
+		serial_outp(info, UART_TX, info->x_char);
+		info->state->icount.tx++;
+		info->x_char = 0;
+		if (intr_done)
+			*intr_done = 0;
+		return;
+	}
+	if (info->xmit.head == info->xmit.tail
+	    || info->tty->stopped
+	    || info->tty->hw_stopped) {
+		info->IER &= ~UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+		return;
+	}
+	
+	count = info->xmit_fifo_size;
+	do {
+		serial_out(info, UART_TX, info->xmit.buf[info->xmit.tail]);
+		info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1);
+		info->state->icount.tx++;
+		if (info->xmit.head == info->xmit.tail)
+			break;
+	} while (--count > 0);
+	
+	if (CIRC_CNT(info->xmit.head,
+		     info->xmit.tail,
+		     SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
+		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("THRE...");
+#endif
+	if (intr_done)
+		*intr_done = 0;
+
+	if (info->xmit.head == info->xmit.tail) {
+		info->IER &= ~UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+	}
+}
+
+static _INLINE_ void check_modem_status(struct async_struct *info)
+{
+	int	status;
+	struct	async_icount *icount;
+	
+	status = serial_in(info, UART_MSR);
+
+	if (status & UART_MSR_ANY_DELTA) {
+		icount = &info->state->icount;
+		/* update input line counters */
+		if (status & UART_MSR_TERI)
+			icount->rng++;
+		if (status & UART_MSR_DDSR)
+			icount->dsr++;
+		if (status & UART_MSR_DDCD) {
+			icount->dcd++;
+#ifdef CONFIG_HARD_PPS
+			if ((info->flags & ASYNC_HARDPPS_CD) &&
+			    (status & UART_MSR_DCD))
+				hardpps();
+#endif
+		}
+		if (status & UART_MSR_DCTS)
+			icount->cts++;
+		wake_up_interruptible(&info->delta_msr_wait);
+	}
+
+	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+		printk("ttys%d CD now %s...", info->line,
+		       (status & UART_MSR_DCD) ? "on" : "off");
+#endif		
+		if (status & UART_MSR_DCD)
+			wake_up_interruptible(&info->open_wait);
+		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+			   (info->flags & ASYNC_CALLOUT_NOHUP))) {
+#ifdef SERIAL_DEBUG_OPEN
+			printk("doing serial hangup...");
+#endif
+			if (info->tty)
+				tty_hangup(info->tty);
+		}
+	}
+	if (info->flags & ASYNC_CTS_FLOW) {
+		if (info->tty->hw_stopped) {
+			if (status & UART_MSR_CTS) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx start...");
+#endif
+				info->tty->hw_stopped = 0;
+				info->IER |= UART_IER_THRI;
+				serial_out(info, UART_IER, info->IER);
+				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+				return;
+			}
+		} else {
+			if (!(status & UART_MSR_CTS)) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx stop...");
+#endif
+				info->tty->hw_stopped = 1;
+				info->IER &= ~UART_IER_THRI;
+				serial_out(info, UART_IER, info->IER);
+			}
+		}
+	}
+}
+
+
+
+/*
+ * This is the serial driver's interrupt routine for a single port
+ */
+static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
+{
+	int status;
+	int pass_counter = 0;
+	struct async_struct * info;
+	
+#ifdef SERIAL_DEBUG_INTR
+	printk("rs_interrupt_single(%d)...", irq);
+#endif
+
+	info = IRQ_ports[irq];
+	if (!info || !info->tty)
+		return;
+
+	do {
+		status = serial_inp(info, UART_LSR);
+#ifdef SERIAL_DEBUG_INTR
+		printk("status = %x...", status);
+#endif
+		if (status & UART_LSR_DR)
+			receive_chars(info, &status, regs);
+		check_modem_status(info);
+		if (status & UART_LSR_THRE)
+			transmit_chars(info, 0);
+		if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+#if 0
+			printk("rs_single loop break.\n");
+#endif
+			break;
+		}
+	} while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT));
+	info->last_active = jiffies;
+#ifdef SERIAL_DEBUG_INTR
+	printk("end.\n");
+#endif
+}
+
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void do_serial_bh(void)
+{
+	run_task_queue(&tq_serial);
+}
+
+static void do_softint(void *private_)
+{
+	struct async_struct	*info = (struct async_struct *) private_;
+	struct tty_struct	*tty;
+	
+	tty = info->tty;
+	if (!tty)
+		return;
+
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+		    tty->ldisc.write_wakeup)
+			(tty->ldisc.write_wakeup)(tty);
+		wake_up_interruptible(&tty->write_wait);
+#ifdef SERIAL_HAVE_POLL_WAIT
+		wake_up_interruptible(&tty->poll_wait);
+#endif
+	}
+}
+
+/*
+ * This subroutine is called when the RS_TIMER goes off.  It is used
+ * by the serial driver to handle ports that do not have an interrupt
+ * (irq=0).  This doesn't work very well for 16450's, but gives barely
+ * passable results for a 16550A.  (Although at the expense of much
+ * CPU overhead).
+ */
+static void rs_timer(unsigned long dummy)
+{
+	static unsigned long last_strobe;
+	struct async_struct *info;
+	unsigned int	i;
+	unsigned long flags;
+
+	if ((jiffies - last_strobe) >= RS_STROBE_TIME) {
+		for (i=0; i < NR_IRQS; i++) {
+			info = IRQ_ports[i];
+			if (!info)
+				continue;
+			save_flags(flags); cli();
+				rs_interrupt_single(i, NULL, NULL);
+			restore_flags(flags);
+		}
+	}
+	last_strobe = jiffies;
+	mod_timer(&serial_timer, jiffies + RS_STROBE_TIME);
+
+#if 0
+	if (IRQ_ports[0]) {
+		save_flags(flags); cli();
+		rs_interrupt_single(0, NULL, NULL);
+		restore_flags(flags);
+
+		mod_timer(&serial_timer, jiffies + IRQ_timeout[0]);
+	}
+#endif
+}
+
+/*
+ * ---------------------------------------------------------------
+ * Low level utility subroutines for the serial driver:  routines to
+ * figure out the appropriate timeout for an interrupt chain, routines
+ * to initialize and startup a serial port, and routines to shutdown a
+ * serial port.  Useful stuff like that.
+ * ---------------------------------------------------------------
+ */
+
+/*
+ * This routine figures out the correct timeout for a particular IRQ.
+ * It uses the smallest timeout of all of the serial ports in a
+ * particular interrupt chain.  Now only used for IRQ 0....
+ */
+static void figure_IRQ_timeout(int irq)
+{
+	struct	async_struct	*info;
+	int	timeout = 60*HZ;	/* 60 seconds === a long time :-) */
+
+	info = IRQ_ports[irq];
+	if (!info) {
+		IRQ_timeout[irq] = 60*HZ;
+		return;
+	}
+	while (info) {
+		if (info->timeout < timeout)
+			timeout = info->timeout;
+		info = info->next_port;
+	}
+	if (!irq)
+		timeout = timeout / 2;
+	IRQ_timeout[irq] = (timeout > 3) ? timeout-2 : 1;
+}
+
+
+static int startup(struct async_struct * info)
+{
+	unsigned long flags;
+	int	retval=0;
+	void (*handler)(int, void *, struct pt_regs *);
+	struct serial_state *state= info->state;
+	unsigned long page;
+
+	page = get_zeroed_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	save_flags(flags); cli();
+
+	if (info->flags & ASYNC_INITIALIZED) {
+		free_page(page);
+		goto errout;
+	}
+
+	if (!CONFIGURED_SERIAL_PORT(state) || !state->type) {
+		if (info->tty)
+			set_bit(TTY_IO_ERROR, &info->tty->flags);
+		free_page(page);
+		goto errout;
+	}
+	if (info->xmit.buf)
+		free_page(page);
+	else
+		info->xmit.buf = (unsigned char *) page;
+
+
+	if (inl(UART_MOD_CNTRL + state->port) != 0x3) {
+		outl(3, UART_MOD_CNTRL + state->port);
+	}
+#ifdef SERIAL_DEBUG_OPEN
+	printk("starting up ttys%d (irq %d)...", info->line, state->irq);
+#endif
+
+
+	/*
+	 * Clear the FIFO buffers and disable them
+	 * (they will be reenabled in change_speed())
+	 */
+	if (uart_config[state->type].flags & UART_CLEAR_FIFO) {
+		serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+		serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO |
+					     UART_FCR_CLEAR_RCVR |
+					     UART_FCR_CLEAR_XMIT));
+		serial_outp(info, UART_FCR, 0);
+	}
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+	(void) serial_inp(info, UART_LSR);
+	(void) serial_inp(info, UART_RX);
+	(void) serial_inp(info, UART_IIR);
+	(void) serial_inp(info, UART_MSR);
+
+	/*
+	 * At this point there's no way the LSR could still be 0xFF;
+	 * if it is, then bail out, because there's likely no UART
+	 * here.
+	 */
+	if (!(info->flags & ASYNC_BUGGY_UART) &&
+	    (serial_inp(info, UART_LSR) == 0xff)) {
+		printk("LSR safety check engaged!\n");
+		if (capable(CAP_SYS_ADMIN)) {
+			if (info->tty)
+				set_bit(TTY_IO_ERROR, &info->tty->flags);
+		} else
+			retval = -ENODEV;
+		goto errout;
+	}
+	
+	/*
+	 * Allocate the IRQ if necessary
+	 */
+#if 0
+	/* au1000, uart0 irq is 0 */
+	if (state->irq && (!IRQ_ports[state->irq] || !IRQ_ports[state->irq]->next_port)) {
+#endif
+	if ((!IRQ_ports[state->irq] || !IRQ_ports[state->irq]->next_port)) {
+		if (IRQ_ports[state->irq]) {
+			retval = -EBUSY;
+			goto errout;
+		} else 
+			handler = rs_interrupt_single;
+
+		retval = request_irq(state->irq, handler, SA_SHIRQ,
+				     "serial", &IRQ_ports[state->irq]);
+		if (retval) {
+			if (capable(CAP_SYS_ADMIN)) {
+				if (info->tty)
+					set_bit(TTY_IO_ERROR,
+						&info->tty->flags);
+				retval = 0;
+			}
+			goto errout;
+		}
+	}
+
+	/*
+	 * Insert serial port into IRQ chain.
+	 */
+	info->prev_port = 0;
+	info->next_port = IRQ_ports[state->irq];
+	if (info->next_port)
+		info->next_port->prev_port = info;
+	IRQ_ports[state->irq] = info;
+	figure_IRQ_timeout(state->irq);
+
+	/*
+	 * Now, initialize the UART 
+	 */
+	serial_outp(info, UART_LCR, UART_LCR_WLEN8);
+
+	info->MCR = 0;
+	if (info->tty->termios->c_cflag & CBAUD)
+		info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+	{
+		if (state->irq != 0)
+			info->MCR |= UART_MCR_OUT2;
+	}
+	info->MCR |= ALPHA_KLUDGE_MCR; 		/* Don't ask */
+	serial_outp(info, UART_MCR, info->MCR);
+	
+	/*
+	 * Finally, enable interrupts
+	 */
+	info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
+	serial_outp(info, UART_IER, info->IER);	/* enable interrupts */
+	
+
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	(void)serial_inp(info, UART_LSR);
+	(void)serial_inp(info, UART_RX);
+	(void)serial_inp(info, UART_IIR);
+	(void)serial_inp(info, UART_MSR);
+
+	if (info->tty)
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	info->xmit.head = info->xmit.tail = 0;
+
+	/*
+	 * Set up serial timers...
+	 */
+	mod_timer(&serial_timer, jiffies + 2*HZ/100);
+
+	/*
+	 * Set up the tty->alt_speed kludge
+	 */
+	if (info->tty) {
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			info->tty->alt_speed = 57600;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			info->tty->alt_speed = 115200;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			info->tty->alt_speed = 230400;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			info->tty->alt_speed = 460800;
+	}
+	
+	/*
+	 * and set the speed of the serial port
+	 */
+	change_speed(info, 0);
+
+	info->flags |= ASYNC_INITIALIZED;
+	restore_flags(flags);
+	return 0;
+	
+errout:
+	restore_flags(flags);
+	return retval;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(struct async_struct * info)
+{
+	unsigned long	flags;
+	struct serial_state *state;
+	int		retval;
+
+	if (!(info->flags & ASYNC_INITIALIZED))
+		return;
+
+	state = info->state;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("Shutting down serial port %d (irq %d)....", info->line,
+	       state->irq);
+#endif
+	
+	save_flags(flags); cli(); /* Disable interrupts */
+
+	/*
+	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+	 * here so the queue might never be waken up
+	 */
+	wake_up_interruptible(&info->delta_msr_wait);
+	
+	/*
+	 * First unlink the serial port from the IRQ chain...
+	 */
+	if (info->next_port)
+		info->next_port->prev_port = info->prev_port;
+	if (info->prev_port)
+		info->prev_port->next_port = info->next_port;
+	else
+		IRQ_ports[state->irq] = info->next_port;
+	figure_IRQ_timeout(state->irq);
+	
+	/*
+	 * Free the IRQ, if necessary
+	 */
+//	if (state->irq && (!IRQ_ports[state->irq] ||
+	if ((!IRQ_ports[state->irq] ||
+			  !IRQ_ports[state->irq]->next_port)) {
+		if (IRQ_ports[state->irq]) {
+			free_irq(state->irq, &IRQ_ports[state->irq]);
+			retval = request_irq(state->irq, rs_interrupt_single,
+					     SA_SHIRQ, "serial",
+					     &IRQ_ports[state->irq]);
+			
+			if (retval)
+				printk("serial shutdown: request_irq: error %d"
+				       "  Couldn't reacquire IRQ.\n", retval);
+		} else
+			free_irq(state->irq, &IRQ_ports[state->irq]);
+	}
+
+	if (info->xmit.buf) {
+		unsigned long pg = (unsigned long) info->xmit.buf;
+		info->xmit.buf = 0;
+		free_page(pg);
+	}
+
+	info->IER = 0;
+	serial_outp(info, UART_IER, 0x00);	/* disable all intrs */
+		info->MCR &= ~UART_MCR_OUT2;
+	info->MCR |= ALPHA_KLUDGE_MCR; 		/* Don't ask */
+	
+	/* disable break condition */
+	serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC);
+	
+	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
+		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+	serial_outp(info, UART_MCR, info->MCR);
+
+	/* disable FIFO's */	
+	serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO |
+				     UART_FCR_CLEAR_RCVR |
+				     UART_FCR_CLEAR_XMIT));
+	serial_outp(info, UART_FCR, 0);
+
+	(void)serial_in(info, UART_RX);    /* read data port to reset things */
+	
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	info->flags &= ~ASYNC_INITIALIZED;
+	restore_flags(flags);
+}
+
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(struct async_struct *info,
+			 struct termios *old_termios)
+{
+	int	quot = 0, baud_base, baud;
+	unsigned cflag, cval, fcr = 0;
+	int	bits;
+	unsigned long	flags;
+
+	if (!info->tty || !info->tty->termios)
+		return;
+	cflag = info->tty->termios->c_cflag;
+	if (!CONFIGURED_SERIAL_PORT(info))
+		return;
+
+	/* byte size and parity */
+	switch (cflag & CSIZE) {
+	      case CS5: cval = 0x00; bits = 7; break;
+	      case CS6: cval = 0x01; bits = 8; break;
+	      case CS7: cval = 0x02; bits = 9; break;
+	      case CS8: cval = 0x03; bits = 10; break;
+	      /* Never happens, but GCC is too dumb to figure it out */
+	      default:  cval = 0x00; bits = 7; break;
+	      }
+	if (cflag & CSTOPB) {
+		cval |= 0x04;
+		bits++;
+	}
+	if (cflag & PARENB) {
+		cval |= UART_LCR_PARITY;
+		bits++;
+	}
+	if (!(cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+#ifdef CMSPAR
+	if (cflag & CMSPAR)
+		cval |= UART_LCR_SPAR;
+#endif
+
+	/* Determine divisor based on baud rate */
+	baud = tty_get_baud_rate(info->tty);
+	if (!baud) {
+		baud = 9600;	/* B0 transition handled in rs_set_termios */
+	}
+	baud_base = info->state->baud_base;
+	//if (baud == 38400 &&
+	if (((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
+		quot = info->state->custom_divisor;
+	}
+	else {
+		if (baud == 134)
+			/* Special case since 134 is really 134.5 */
+			quot = (2*baud_base / 269);
+		else if (baud)
+			quot = baud_base / baud;
+	}
+	/* If the quotient is zero refuse the change */
+	if (!quot && old_termios) {
+		info->tty->termios->c_cflag &= ~CBAUD;
+		info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
+		baud = tty_get_baud_rate(info->tty);
+		if (!baud)
+			baud = 9600;
+		if (baud == 38400 &&
+		    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+			quot = info->state->custom_divisor;
+		else {
+			if (baud == 134)
+				/* Special case since 134 is really 134.5 */
+				quot = (2*baud_base / 269);
+			else if (baud)
+				quot = baud_base / baud;
+		}
+	}
+	/* As a last resort, if the quotient is zero, default to 9600 bps */
+	if (!quot)
+		quot = baud_base / 9600;
+	
+	info->quot = quot;
+	info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
+	info->timeout += HZ/50;		/* Add .02 seconds of slop */
+
+	/* Set up FIFO's */
+	if (uart_config[info->state->type].flags & UART_USE_FIFO) {
+		if ((info->state->baud_base / quot) < 2400)
+			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1;
+		else
+			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8;
+	}
+	
+	/* CTS flow control flag and modem status interrupts */
+	info->IER &= ~UART_IER_MSI;
+	if (info->flags & ASYNC_HARDPPS_CD)
+		info->IER |= UART_IER_MSI;
+	if (cflag & CRTSCTS) {
+		info->flags |= ASYNC_CTS_FLOW;
+		info->IER |= UART_IER_MSI;
+	} else
+		info->flags &= ~ASYNC_CTS_FLOW;
+	if (cflag & CLOCAL)
+		info->flags &= ~ASYNC_CHECK_CD;
+	else {
+		info->flags |= ASYNC_CHECK_CD;
+		info->IER |= UART_IER_MSI;
+	}
+	serial_out(info, UART_IER, info->IER);
+
+	/*
+	 * Set up parity check flag
+	 */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+	if (I_INPCK(info->tty))
+		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+		info->read_status_mask |= UART_LSR_BI;
+	
+	/*
+	 * Characters to ignore
+	 */
+	info->ignore_status_mask = 0;
+	if (I_IGNPAR(info->tty))
+		info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+	if (I_IGNBRK(info->tty)) {
+		info->ignore_status_mask |= UART_LSR_BI;
+		/*
+		 * If we're ignore parity and break indicators, ignore 
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(info->tty))
+			info->ignore_status_mask |= UART_LSR_OE;
+	}
+	/*
+	 * !!! ignore all characters if CREAD is not set
+	 */
+	if ((cflag & CREAD) == 0)
+		info->ignore_status_mask |= UART_LSR_DR;
+	save_flags(flags); cli();
+
+	serial_outp(info, UART_CLK, quot & 0xffff);
+	serial_outp(info, UART_LCR, cval);
+	info->LCR = cval;				/* Save LCR */
+	restore_flags(flags);
+}
+
+static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "rs_put_char"))
+		return;
+
+	if (!tty || !info->xmit.buf)
+		return;
+
+	save_flags(flags); cli();
+	if (CIRC_SPACE(info->xmit.head,
+		       info->xmit.tail,
+		       SERIAL_XMIT_SIZE) == 0) {
+		restore_flags(flags);
+		return;
+	}
+
+	info->xmit.buf[info->xmit.head] = ch;
+	info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
+	restore_flags(flags);
+}
+
+static void rs_flush_chars(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+				
+	if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
+		return;
+
+	if (info->xmit.head == info->xmit.tail
+	    || tty->stopped
+	    || tty->hw_stopped
+	    || !info->xmit.buf)
+		return;
+
+	save_flags(flags); cli();
+	info->IER |= UART_IER_THRI;
+	serial_out(info, UART_IER, info->IER);
+	restore_flags(flags);
+}
+
+static int rs_write(struct tty_struct * tty, int from_user,
+		    const unsigned char *buf, int count)
+{
+	int	c, ret = 0;
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+				
+	if (serial_paranoia_check(info, tty->device, "rs_write"))
+		return 0;
+
+	if (!tty || !info->xmit.buf || !tmp_buf)
+		return 0;
+
+	save_flags(flags);
+	if (from_user) {
+		down(&tmp_buf_sem);
+		while (1) {
+			int c1;
+			c = CIRC_SPACE_TO_END(info->xmit.head,
+					      info->xmit.tail,
+					      SERIAL_XMIT_SIZE);
+			if (count < c)
+				c = count;
+			if (c <= 0)
+				break;
+
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!ret)
+					ret = -EFAULT;
+				break;
+			}
+			cli();
+			c1 = CIRC_SPACE_TO_END(info->xmit.head,
+					       info->xmit.tail,
+					       SERIAL_XMIT_SIZE);
+			if (c1 < c)
+				c = c1;
+			memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
+			info->xmit.head = ((info->xmit.head + c) &
+					   (SERIAL_XMIT_SIZE-1));
+			restore_flags(flags);
+			buf += c;
+			count -= c;
+			ret += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		cli();
+		while (1) {
+			c = CIRC_SPACE_TO_END(info->xmit.head,
+					      info->xmit.tail,
+					      SERIAL_XMIT_SIZE);
+			if (count < c)
+				c = count;
+			if (c <= 0) {
+				break;
+			}
+			memcpy(info->xmit.buf + info->xmit.head, buf, c);
+			info->xmit.head = ((info->xmit.head + c) &
+					   (SERIAL_XMIT_SIZE-1));
+			buf += c;
+			count -= c;
+			ret += c;
+		}
+		restore_flags(flags);
+	}
+	if (info->xmit.head != info->xmit.tail
+	    && !tty->stopped
+	    && !tty->hw_stopped
+	    && !(info->IER & UART_IER_THRI)) {
+		info->IER |= UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+	}
+	return ret;
+}
+
+static int rs_write_room(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "rs_write_room"))
+		return 0;
+	return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+}
+
+static int rs_chars_in_buffer(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+				
+	if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
+		return 0;
+	return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+}
+
+static void rs_flush_buffer(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
+		return;
+	save_flags(flags); cli();
+	info->xmit.head = info->xmit.tail = 0;
+	restore_flags(flags);
+	wake_up_interruptible(&tty->write_wait);
+#ifdef SERIAL_HAVE_POLL_WAIT
+	wake_up_interruptible(&tty->poll_wait);
+#endif
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+}
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ */
+static void rs_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "rs_send_char"))
+		return;
+
+	info->x_char = ch;
+	if (ch) {
+		/* Make sure transmit interrupts are on */
+		info->IER |= UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+	}
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ * 
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_throttle(struct tty_struct * tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+	
+	printk("throttle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "rs_throttle"))
+		return;
+	
+	if (I_IXOFF(tty))
+		rs_send_xchar(tty, STOP_CHAR(tty));
+
+	if (tty->termios->c_cflag & CRTSCTS)
+		info->MCR &= ~UART_MCR_RTS;
+
+	save_flags(flags); cli();
+	serial_out(info, UART_MCR, info->MCR);
+	restore_flags(flags);
+}
+
+static void rs_unthrottle(struct tty_struct * tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+	
+	printk("unthrottle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
+		return;
+	
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			rs_send_xchar(tty, START_CHAR(tty));
+	}
+	if (tty->termios->c_cflag & CRTSCTS)
+		info->MCR |= UART_MCR_RTS;
+	save_flags(flags); cli();
+	serial_out(info, UART_MCR, info->MCR);
+	restore_flags(flags);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+static int get_serial_info(struct async_struct * info,
+			   struct serial_struct * retinfo)
+{
+	struct serial_struct tmp;
+	struct serial_state *state = info->state;
+   
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = state->type;
+	tmp.line = state->line;
+	tmp.port = state->port;
+	if (HIGH_BITS_OFFSET)
+		tmp.port_high = state->port >> HIGH_BITS_OFFSET;
+	else
+		tmp.port_high = 0;
+	tmp.irq = state->irq;
+	tmp.flags = state->flags;
+	tmp.xmit_fifo_size = state->xmit_fifo_size;
+	tmp.baud_base = state->baud_base;
+	tmp.close_delay = state->close_delay;
+	tmp.closing_wait = state->closing_wait;
+	tmp.custom_divisor = state->custom_divisor;
+	tmp.hub6 = state->hub6;
+	tmp.io_type = state->io_type;
+	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_serial_info(struct async_struct * info,
+			   struct serial_struct * new_info)
+{
+	struct serial_struct new_serial;
+ 	struct serial_state old_state, *state;
+	unsigned int		i,change_irq,change_port;
+	int 			retval = 0;
+	unsigned long		new_port;
+
+	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+		return -EFAULT;
+	state = info->state;
+	old_state = *state;
+
+	new_port = new_serial.port;
+	if (HIGH_BITS_OFFSET)
+		new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
+
+	change_irq = new_serial.irq != state->irq;
+	change_port = (new_port != ((int) state->port)) ||
+		(new_serial.hub6 != state->hub6);
+  
+	if (!capable(CAP_SYS_ADMIN)) {
+		if (change_irq || change_port ||
+		    (new_serial.baud_base != state->baud_base) ||
+		    (new_serial.type != state->type) ||
+		    (new_serial.close_delay != state->close_delay) ||
+		    (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
+		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (state->flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		state->flags = ((state->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		state->custom_divisor = new_serial.custom_divisor;
+		goto check_and_exit;
+	}
+
+	new_serial.irq = irq_cannonicalize(new_serial.irq);
+
+	if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || 
+	    (new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) ||
+	    (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) ||
+	    (new_serial.type == PORT_STARTECH)) {
+		return -EINVAL;
+	}
+
+	if ((new_serial.type != state->type) ||
+	    (new_serial.xmit_fifo_size <= 0))
+		new_serial.xmit_fifo_size =
+			uart_config[new_serial.type].dfl_xmit_fifo_size;
+
+	/* Make sure address is not already in use */
+	if (new_serial.type) {
+		for (i = 0 ; i < NR_PORTS; i++)
+			if ((state != &rs_table[i]) &&
+			    (rs_table[i].port == new_port) &&
+			    rs_table[i].type)
+				return -EADDRINUSE;
+	}
+
+	if ((change_port || change_irq) && (state->count > 1))
+		return -EBUSY;
+
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
+
+	state->baud_base = new_serial.baud_base;
+	state->flags = ((state->flags & ~ASYNC_FLAGS) |
+			(new_serial.flags & ASYNC_FLAGS));
+	info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
+		       (info->flags & ASYNC_INTERNAL_FLAGS));
+	state->custom_divisor = new_serial.custom_divisor;
+	state->close_delay = new_serial.close_delay * HZ/100;
+	state->closing_wait = new_serial.closing_wait * HZ/100;
+	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+	info->xmit_fifo_size = state->xmit_fifo_size =
+		new_serial.xmit_fifo_size;
+
+	if ((state->type != PORT_UNKNOWN) && state->port) {
+		release_region(state->port,8);
+	}
+	state->type = new_serial.type;
+	if (change_port || change_irq) {
+		/*
+		 * We need to shutdown the serial port at the old
+		 * port/irq combination.
+		 */
+		shutdown(info);
+		state->irq = new_serial.irq;
+		info->port = state->port = new_port;
+		info->hub6 = state->hub6 = new_serial.hub6;
+		if (info->hub6)
+			info->io_type = state->io_type = SERIAL_IO_HUB6;
+		else if (info->io_type == SERIAL_IO_HUB6)
+			info->io_type = state->io_type = SERIAL_IO_PORT;
+	}
+	if ((state->type != PORT_UNKNOWN) && state->port) {
+			request_region(state->port,8,"serial(set)");
+	}
+
+	
+check_and_exit:
+	if (!state->port || !state->type)
+		return 0;
+	if (info->flags & ASYNC_INITIALIZED) {
+		if (((old_state.flags & ASYNC_SPD_MASK) !=
+		     (state->flags & ASYNC_SPD_MASK)) ||
+		    (old_state.custom_divisor != state->custom_divisor)) {
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+				info->tty->alt_speed = 57600;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+				info->tty->alt_speed = 115200;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+				info->tty->alt_speed = 230400;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+				info->tty->alt_speed = 460800;
+			change_speed(info, 0);
+		}
+	} else {
+		retval = startup(info);
+	}
+	return retval;
+}
+
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * 	    is emptied.  On bus types like RS485, the transmitter must
+ * 	    release the bus after transmitting. This must be done when
+ * 	    the transmit shift register is empty, not be done when the
+ * 	    transmit holding register is empty.  This functionality
+ * 	    allows an RS485 driver to be written in user space. 
+ */
+static int get_lsr_info(struct async_struct * info, unsigned int *value)
+{
+	unsigned char status;
+	unsigned int result;
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	status = serial_in(info, UART_LSR);
+	restore_flags(flags);
+	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+
+	/*
+	 * If we're about to load something into the transmit
+	 * register, we'll pretend the transmitter isn't empty to
+	 * avoid a race condition (depending on when the transmit
+	 * interrupt happens).
+	 */
+	if (info->x_char || 
+	    ((CIRC_CNT(info->xmit.head, info->xmit.tail,
+		       SERIAL_XMIT_SIZE) > 0) &&
+	     !info->tty->stopped && !info->tty->hw_stopped))
+		result &= TIOCSER_TEMT;
+
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
+}
+
+
+static int get_modem_info(struct async_struct * info, unsigned int *value)
+{
+	unsigned char control, status;
+	unsigned int result;
+	unsigned long flags;
+
+	control = info->MCR;
+	save_flags(flags); cli();
+	status = serial_in(info, UART_MSR);
+	restore_flags(flags);
+	result =  ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
+#ifdef TIOCM_OUT1
+		| ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
+		| ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
+#endif
+		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
+		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)
+		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
+		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
+
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_modem_info(struct async_struct * info, unsigned int cmd,
+			  unsigned int *value)
+{
+	unsigned int arg;
+	unsigned long flags;
+
+	if (copy_from_user(&arg, value, sizeof(int)))
+		return -EFAULT;
+
+	switch (cmd) {
+	case TIOCMBIS: 
+		if (arg & TIOCM_RTS)
+			info->MCR |= UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			info->MCR |= UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+		if (arg & TIOCM_OUT1)
+			info->MCR |= UART_MCR_OUT1;
+		if (arg & TIOCM_OUT2)
+			info->MCR |= UART_MCR_OUT2;
+#endif
+		if (arg & TIOCM_LOOP)
+			info->MCR |= UART_MCR_LOOP;
+		break;
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS)
+			info->MCR &= ~UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			info->MCR &= ~UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+		if (arg & TIOCM_OUT1)
+			info->MCR &= ~UART_MCR_OUT1;
+		if (arg & TIOCM_OUT2)
+			info->MCR &= ~UART_MCR_OUT2;
+#endif
+		if (arg & TIOCM_LOOP)
+			info->MCR &= ~UART_MCR_LOOP;
+		break;
+	case TIOCMSET:
+		info->MCR = ((info->MCR & ~(UART_MCR_RTS |
+#ifdef TIOCM_OUT1
+					    UART_MCR_OUT1 |
+					    UART_MCR_OUT2 |
+#endif
+					    UART_MCR_LOOP |
+					    UART_MCR_DTR))
+			     | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
+#ifdef TIOCM_OUT1
+			     | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
+			     | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
+#endif
+			     | ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0)
+			     | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
+		break;
+	default:
+		return -EINVAL;
+	}
+	save_flags(flags); cli();
+	info->MCR |= ALPHA_KLUDGE_MCR; 		/* Don't ask */
+	serial_out(info, UART_MCR, info->MCR);
+	restore_flags(flags);
+	return 0;
+}
+
+static int do_autoconfig(struct async_struct * info)
+{
+	int retval;
+	
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	
+	if (info->state->count > 1)
+		return -EBUSY;
+	
+	shutdown(info);
+
+	autoconfig(info->state);
+	retval = startup(info);
+	if (retval)
+		return retval;
+	return 0;
+}
+
+/*
+ * rs_break() --- routine which turns the break handling on or off
+ */
+static void rs_break(struct tty_struct *tty, int break_state)
+{
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_break"))
+		return;
+
+	if (!CONFIGURED_SERIAL_PORT(info))
+		return;
+	save_flags(flags); cli();
+	if (break_state == -1)
+		info->LCR |= UART_LCR_SBC;
+	else
+		info->LCR &= ~UART_LCR_SBC;
+	serial_out(info, UART_LCR, info->LCR);
+	restore_flags(flags);
+}
+
+
+static int rs_ioctl(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg)
+{
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	struct async_icount cprev, cnow;	/* kernel counter temps */
+	struct serial_icounter_struct icount;
+	unsigned long flags;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+		return -ENODEV;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+	
+	switch (cmd) {
+		case TIOCMGET:
+			return get_modem_info(info, (unsigned int *) arg);
+		case TIOCMBIS:
+		case TIOCMBIC:
+		case TIOCMSET:
+			return set_modem_info(info, cmd, (unsigned int *) arg);
+		case TIOCGSERIAL:
+			return get_serial_info(info,
+					       (struct serial_struct *) arg);
+		case TIOCSSERIAL:
+			return set_serial_info(info,
+					       (struct serial_struct *) arg);
+		case TIOCSERCONFIG:
+			return do_autoconfig(info);
+
+		case TIOCSERGETLSR: /* Get line status register */
+			return get_lsr_info(info, (unsigned int *) arg);
+
+		case TIOCSERGSTRUCT:
+			if (copy_to_user((struct async_struct *) arg,
+					 info, sizeof(struct async_struct)))
+				return -EFAULT;
+			return 0;
+				
+			
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+		 * - mask passed in arg for lines of interest
+ 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+		case TIOCMIWAIT:
+			save_flags(flags); cli();
+			/* note the counters on entry */
+			cprev = info->state->icount;
+			restore_flags(flags);
+			/* Force modem status interrupts on */
+			info->IER |= UART_IER_MSI;
+			serial_out(info, UART_IER, info->IER);
+			while (1) {
+				interruptible_sleep_on(&info->delta_msr_wait);
+				/* see if a signal did it */
+				if (signal_pending(current))
+					return -ERESTARTSYS;
+				save_flags(flags); cli();
+				cnow = info->state->icount; /* atomic copy */
+				restore_flags(flags);
+				if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 
+				    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+					return -EIO; /* no change => error */
+				if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+				     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+				     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+				     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+					return 0;
+				}
+				cprev = cnow;
+			}
+			/* NOTREACHED */
+
+		/* 
+		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+		 * Return: write counters to the user passed counter struct
+		 * NB: both 1->0 and 0->1 transitions are counted except for
+		 *     RI where only 0->1 is counted.
+		 */
+		case TIOCGICOUNT:
+			save_flags(flags); cli();
+			cnow = info->state->icount;
+			restore_flags(flags);
+			icount.cts = cnow.cts;
+			icount.dsr = cnow.dsr;
+			icount.rng = cnow.rng;
+			icount.dcd = cnow.dcd;
+			icount.rx = cnow.rx;
+			icount.tx = cnow.tx;
+			icount.frame = cnow.frame;
+			icount.overrun = cnow.overrun;
+			icount.parity = cnow.parity;
+			icount.brk = cnow.brk;
+			icount.buf_overrun = cnow.buf_overrun;
+			
+			if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+				return -EFAULT;
+			return 0;
+		case TIOCSERGWILD:
+		case TIOCSERSWILD:
+			/* "setserial -W" is called in Debian boot */
+			printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
+			return 0;
+
+		default:
+			return -ENOIOCTLCMD;
+		}
+	return 0;
+}
+
+static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+	unsigned int cflag = tty->termios->c_cflag;
+	
+	if (   (cflag == old_termios->c_cflag)
+	    && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
+		== RELEVANT_IFLAG(old_termios->c_iflag)))
+	  return;
+
+	change_speed(info, old_termios);
+
+	/* Handle transition to B0 status */
+	if ((old_termios->c_cflag & CBAUD) &&
+	    !(cflag & CBAUD)) {
+		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+		save_flags(flags); cli();
+		serial_out(info, UART_MCR, info->MCR);
+		restore_flags(flags);
+	}
+	
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) &&
+	    (cflag & CBAUD)) {
+		info->MCR |= UART_MCR_DTR;
+		if (!(tty->termios->c_cflag & CRTSCTS) || 
+		    !test_bit(TTY_THROTTLED, &tty->flags)) {
+			info->MCR |= UART_MCR_RTS;
+		}
+		save_flags(flags); cli();
+		serial_out(info, UART_MCR, info->MCR);
+		restore_flags(flags);
+	}
+	
+	/* Handle turning off CRTSCTS */
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		rs_start(tty);
+	}
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ * 
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	struct serial_state *state;
+	unsigned long flags;
+
+	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
+		return;
+
+	state = info->state;
+	
+	save_flags(flags); cli();
+	
+	if (tty_hung_up_p(filp)) {
+		DBG_CNT("before DEC-hung");
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+	
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_close ttys%d, count = %d\n", info->line, state->count);
+#endif
+	if ((tty->count == 1) && (state->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  state->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		printk("rs_close: bad serial port count; tty->count is 1, "
+		       "state->count is %d\n", state->count);
+		state->count = 1;
+	}
+	if (--state->count < 0) {
+		printk("rs_close: bad serial port count for ttys%d: %d\n",
+		       info->line, state->count);
+		state->count = 0;
+	}
+	if (state->count) {
+		DBG_CNT("before DEC-2");
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+	info->flags |= ASYNC_CLOSING;
+	restore_flags(flags);
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+	if (info->flags & ASYNC_NORMAL_ACTIVE)
+		info->state->normal_termios = *tty->termios;
+	if (info->flags & ASYNC_CALLOUT_ACTIVE)
+		info->state->callout_termios = *tty->termios;
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, info->closing_wait);
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+	info->IER &= ~UART_IER_RLSI;
+	info->read_status_mask &= ~UART_LSR_DR;
+	if (info->flags & ASYNC_INITIALIZED) {
+		serial_out(info, UART_IER, info->IER);
+		/*
+		 * Before we drop DTR, make sure the UART transmitter
+		 * has completely drained; this is especially
+		 * important if there is a transmit FIFO!
+		 */
+		rs_wait_until_sent(tty, info->timeout);
+	}
+	shutdown(info);
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+	tty->closing = 0;
+	info->event = 0;
+	info->tty = 0;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(info->close_delay);
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+			 ASYNC_CLOSING);
+	wake_up_interruptible(&info->close_wait);
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+	int lsr;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+		return;
+
+	if (info->state->type == PORT_UNKNOWN)
+		return;
+
+	if (info->xmit_fifo_size == 0)
+		return; /* Just in case.... */
+
+	orig_jiffies = jiffies;
+	/*
+	 * Set the check interval to be 1/5 of the estimated time to
+	 * send a single character, and make it at least 1.  The check
+	 * interval should also be less than the timeout.
+	 * 
+	 * Note: we have to use pretty tight timings here to satisfy
+	 * the NIST-PCTS.
+	 */
+	char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+	char_time = char_time / 5;
+	if (char_time == 0)
+		char_time = 1;
+	if (timeout && timeout < char_time)
+		char_time = timeout;
+	/*
+	 * If the transmitter hasn't cleared in twice the approximate
+	 * amount of time to send the entire FIFO, it probably won't
+	 * ever clear.  This assumes the UART isn't doing flow
+	 * control, which is currently the case.  Hence, if it ever
+	 * takes longer than info->timeout, this is probably due to a
+	 * UART bug of some kind.  So, we clamp the timeout parameter at
+	 * 2*info->timeout.
+	 */
+	if (!timeout || timeout > 2*info->timeout)
+		timeout = 2*info->timeout;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
+	printk("jiff=%lu...", jiffies);
+#endif
+	while (!((lsr = serial_inp(info, UART_LSR)) & UART_LSR_TEMT)) {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(char_time);
+		if (signal_pending(current))
+			break;
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
+			break;
+	}
+	set_current_state(TASK_RUNNING);
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void rs_hangup(struct tty_struct *tty)
+{
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	struct serial_state *state = info->state;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_hangup"))
+		return;
+
+	state = info->state;
+	
+	rs_flush_buffer(tty);
+	if (info->flags & ASYNC_CLOSING)
+		return;
+	shutdown(info);
+	info->event = 0;
+	state->count = 0;
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+	info->tty = 0;
+	wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+			   struct async_struct *info)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct serial_state *state = info->state;
+	int		retval;
+	int		do_clocal = 0, extra_count = 0;
+	unsigned long	flags;
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		if (info->flags & ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_SESSION_LOCKOUT) &&
+		    (info->session != current->session))
+		    return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_PGRP_LOCKOUT) &&
+		    (info->pgrp != current->pgrp))
+		    return -EBUSY;
+		info->flags |= ASYNC_CALLOUT_ACTIVE;
+		return 0;
+	}
+	
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		if (info->flags & ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
+		info->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (info->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (state->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
+	
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, state->count is dropped by one, so that
+	 * rs_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+	add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready before block: ttys%d, count = %d\n",
+	       state->line, state->count);
+#endif
+	save_flags(flags); cli();
+	if (!tty_hung_up_p(filp)) {
+		extra_count = 1;
+		state->count--;
+	}
+	restore_flags(flags);
+	info->blocked_open++;
+	while (1) {
+		save_flags(flags); cli();
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (tty->termios->c_cflag & CBAUD))
+			serial_out(info, UART_MCR,
+				   serial_inp(info, UART_MCR) |
+				   (UART_MCR_DTR | UART_MCR_RTS));
+		restore_flags(flags);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (tty_hung_up_p(filp) ||
+		    !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+			if (info->flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;	
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    !(info->flags & ASYNC_CLOSING) &&
+		    (do_clocal || (serial_in(info, UART_MSR) &
+				   UART_MSR_DCD)))
+			break;
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+#ifdef SERIAL_DEBUG_OPEN
+		printk("block_til_ready blocking: ttys%d, count = %d\n",
+		       info->line, state->count);
+#endif
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&info->open_wait, &wait);
+	if (extra_count)
+		state->count++;
+	info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	       info->line, state->count);
+#endif
+	if (retval)
+		return retval;
+	info->flags |= ASYNC_NORMAL_ACTIVE;
+	return 0;
+}
+
+static int get_async_struct(int line, struct async_struct **ret_info)
+{
+	struct async_struct *info;
+	struct serial_state *sstate;
+
+	sstate = rs_table + line;
+	sstate->count++;
+	if (sstate->info) {
+		*ret_info = sstate->info;
+		return 0;
+	}
+	info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);
+	if (!info) {
+		sstate->count--;
+		return -ENOMEM;
+	}
+	memset(info, 0, sizeof(struct async_struct));
+	init_waitqueue_head(&info->open_wait);
+	init_waitqueue_head(&info->close_wait);
+	init_waitqueue_head(&info->delta_msr_wait);
+	info->magic = SERIAL_MAGIC;
+	info->port = sstate->port;
+	info->flags = sstate->flags;
+	info->io_type = sstate->io_type;
+	info->iomem_base = sstate->iomem_base;
+	info->iomem_reg_shift = sstate->iomem_reg_shift;
+	info->xmit_fifo_size = sstate->xmit_fifo_size;
+	info->line = line;
+	info->tqueue.routine = do_softint;
+	info->tqueue.data = info;
+	info->state = sstate;
+	if (sstate->info) {
+		kfree(info);
+		*ret_info = sstate->info;
+		return 0;
+	}
+	*ret_info = sstate->info = info;
+	return 0;
+}
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain.   It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int rs_open(struct tty_struct *tty, struct file * filp)
+{
+	struct async_struct	*info;
+	int 			retval, line;
+	unsigned long		page;
+
+	MOD_INC_USE_COUNT;
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	if ((line < 0) || (line >= NR_PORTS)) {
+		MOD_DEC_USE_COUNT;
+		return -ENODEV;
+	}
+	retval = get_async_struct(line, &info);
+	if (retval) {
+		MOD_DEC_USE_COUNT;
+		return retval;
+	}
+	tty->driver_data = info;
+	info->tty = tty;
+	if (serial_paranoia_check(info, tty->device, "rs_open")) {
+		MOD_DEC_USE_COUNT;		
+		return -ENODEV;
+	}
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+	       info->state->count);
+#endif
+	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+	if (!tmp_buf) {
+		page = get_zeroed_page(GFP_KERNEL);
+		if (!page) {
+			MOD_DEC_USE_COUNT;
+			return -ENOMEM;
+		}
+		if (tmp_buf)
+			free_page(page);
+		else
+			tmp_buf = (unsigned char *) page;
+	}
+
+	/*
+	 * If the port is the middle of closing, bail out now
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+		MOD_DEC_USE_COUNT;
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * Start up serial port
+	 */
+	retval = startup(info);
+	if (retval) {
+		MOD_DEC_USE_COUNT;
+		return retval;
+	}
+
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+		printk("rs_open returning after block_til_ready with %d\n",
+		       retval);
+#endif
+		MOD_DEC_USE_COUNT;
+		return retval;
+	}
+
+	if ((info->state->count == 1) &&
+	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = info->state->normal_termios;
+		else 
+			*tty->termios = info->state->callout_termios;
+		change_speed(info, 0);
+	}
+#ifdef CONFIG_AU1000_SERIAL_CONSOLE
+	if (sercons.cflag && sercons.index == line) {
+		tty->termios->c_cflag = sercons.cflag;
+		sercons.cflag = 0;
+		change_speed(info, 0);
+	}
+#endif
+	info->session = current->session;
+	info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open ttys%d successful...", info->line);
+#endif
+	return 0;
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static inline int line_info(char *buf, struct serial_state *state)
+{
+	struct async_struct *info = state->info, scr_info;
+	char	stat_buf[30], control, status;
+	int	ret;
+	unsigned long flags;
+
+	ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d",
+		      state->line, uart_config[state->type].name, 
+		      state->port, state->irq);
+
+	if (!state->port || (state->type == PORT_UNKNOWN)) {
+		ret += sprintf(buf+ret, "\n");
+		return ret;
+	}
+
+	/*
+	 * Figure out the current RS-232 lines
+	 */
+	if (!info) {
+		info = &scr_info;	/* This is just for serial_{in,out} */
+
+		info->magic = SERIAL_MAGIC;
+		info->port = state->port;
+		info->flags = state->flags;
+		info->quot = 0;
+		info->tty = 0;
+	}
+	save_flags(flags); cli();
+	status = serial_in(info, UART_MSR);
+	control = info != &scr_info ? info->MCR : serial_in(info, UART_MCR);
+	restore_flags(flags); 
+
+	stat_buf[0] = 0;
+	stat_buf[1] = 0;
+	if (control & UART_MCR_RTS)
+		strcat(stat_buf, "|RTS");
+	if (status & UART_MSR_CTS)
+		strcat(stat_buf, "|CTS");
+	if (control & UART_MCR_DTR)
+		strcat(stat_buf, "|DTR");
+	if (status & UART_MSR_DSR)
+		strcat(stat_buf, "|DSR");
+	if (status & UART_MSR_DCD)
+		strcat(stat_buf, "|CD");
+	if (status & UART_MSR_RI)
+		strcat(stat_buf, "|RI");
+
+	if (info->quot) {
+		ret += sprintf(buf+ret, " baud:%d",
+			       state->baud_base / info->quot);
+	}
+
+	ret += sprintf(buf+ret, " tx:%d rx:%d",
+		      state->icount.tx, state->icount.rx);
+
+	if (state->icount.frame)
+		ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
+	
+	if (state->icount.parity)
+		ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
+	
+	if (state->icount.brk)
+		ret += sprintf(buf+ret, " brk:%d", state->icount.brk);	
+
+	if (state->icount.overrun)
+		ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
+
+	/*
+	 * Last thing is the RS-232 status lines
+	 */
+	ret += sprintf(buf+ret, " %s\n", stat_buf+1);
+	return ret;
+}
+
+int rs_read_proc(char *page, char **start, off_t off, int count,
+		 int *eof, void *data)
+{
+	int i, len = 0, l;
+	off_t	begin = 0;
+
+	len += sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n",
+		       serial_version, LOCAL_VERSTRING, serial_revdate);
+	for (i = 0; i < NR_PORTS && len < 4000; i++) {
+		l = line_info(page + len, &rs_table[i]);
+		len += l;
+		if (len+begin > off+count)
+			goto done;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+	*eof = 1;
+done:
+	if (off >= len+begin)
+		return 0;
+	*start = page + (off-begin);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * rs_init() and friends
+ *
+ * rs_init() is called at boot-time to initialize the serial driver.
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * This routine prints out the appropriate serial driver version
+ * number, and identifies which options were configured into this
+ * driver.
+ */
+static char serial_options[] __initdata =
+       " no serial options enabled\n";
+#undef SERIAL_OPT
+
+static _INLINE_ void show_serial_version(void)
+{
+ 	printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name,
+	       serial_version, LOCAL_VERSTRING, serial_revdate,
+	       serial_options);
+}
+
+
+/*
+ * This routine is called by rs_init() to initialize a specific serial
+ * port.  It determines what type of UART chip this serial port is
+ * using: 8250, 16450, 16550, 16550A.  The important question is
+ * whether or not this UART is a 16550A or not, since this will
+ * determine whether or not we can use its FIFO features or not.
+ */
+static void autoconfig(struct serial_state * state)
+{
+	struct async_struct *info, scr_info;
+	unsigned long flags;
+
+
+#ifdef SERIAL_DEBUG_AUTOCONF
+	printk("Testing ttyS%d (0x%04lx, 0x%04x)...\n", state->line,
+	       state->port, (unsigned) state->iomem_base);
+#endif
+	
+	if (!CONFIGURED_SERIAL_PORT(state))
+		return;
+
+	if (inl(UART_MOD_CNTRL + state->port) != 0x3) {
+		outl(3, UART_MOD_CNTRL + state->port);
+	}
+		
+	state->type = PORT_16550;
+	info = &scr_info;	/* This is just for serial_{in,out} */
+
+	info->magic = SERIAL_MAGIC;
+	info->state = state;
+	info->port = state->port;
+	info->flags = state->flags;
+	info->io_type = state->io_type;
+	info->iomem_base = state->iomem_base;
+	info->iomem_reg_shift = state->iomem_reg_shift;
+
+
+	save_flags(flags); cli();
+	state->xmit_fifo_size =	uart_config[state->type].dfl_xmit_fifo_size;
+
+	if (info->port) {
+			request_region(info->port,8,"serial(auto)");
+	}
+
+	/*
+	 * Reset the UART.
+	 */
+	serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO |
+				     UART_FCR_CLEAR_RCVR |
+				     UART_FCR_CLEAR_XMIT));
+	serial_outp(info, UART_FCR, 0);
+	(void)serial_in(info, UART_RX);
+	serial_outp(info, UART_IER, 0);
+	
+	restore_flags(flags);
+}
+
+int register_serial(struct serial_struct *req);
+void unregister_serial(int line);
+
+EXPORT_SYMBOL(register_serial);
+EXPORT_SYMBOL(unregister_serial);
+
+
+/*
+ * The serial driver boot-time initialization code!
+ */
+static int __init rs_init(void)
+{
+	int i;
+	struct serial_state * state;
+
+	init_bh(SERIAL_BH, do_serial_bh);
+	init_timer(&serial_timer);
+	serial_timer.function = rs_timer;
+	mod_timer(&serial_timer, jiffies + RS_STROBE_TIME);
+
+	for (i = 0; i < NR_IRQS; i++) {
+		IRQ_ports[i] = 0;
+		IRQ_timeout[i] = 0;
+	}
+#ifdef CONFIG_AU1000_SERIAL_CONSOLE
+	/*
+	 *	The interrupt of the serial console port
+	 *	can't be shared.
+	 */
+	if (sercons.flags & CON_CONSDEV) {
+		for(i = 0; i < NR_PORTS; i++)
+			if (i != sercons.index &&
+			    rs_table[i].irq == rs_table[sercons.index].irq)
+				rs_table[i].irq = 0;
+	}
+#endif
+	show_serial_version();
+
+	/* Initialize the tty_driver structure */
+	
+	memset(&serial_driver, 0, sizeof(struct tty_driver));
+	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.driver_name = "serial";
+#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
+	serial_driver.name = "tts/%d";
+#else
+	serial_driver.name = "ttyS";
+#endif
+	serial_driver.major = TTY_MAJOR;
+	serial_driver.minor_start = 64 + SERIAL_DEV_OFFSET;
+	serial_driver.num = NR_PORTS;
+	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver.subtype = SERIAL_TYPE_NORMAL;
+	serial_driver.init_termios = tty_std_termios;
+	serial_driver.init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	serial_driver.refcount = &serial_refcount;
+	serial_driver.table = serial_table;
+	serial_driver.termios = serial_termios;
+	serial_driver.termios_locked = serial_termios_locked;
+
+	serial_driver.open = rs_open;
+	serial_driver.close = rs_close;
+	serial_driver.write = rs_write;
+	serial_driver.put_char = rs_put_char;
+	serial_driver.flush_chars = rs_flush_chars;
+	serial_driver.write_room = rs_write_room;
+	serial_driver.chars_in_buffer = rs_chars_in_buffer;
+	serial_driver.flush_buffer = rs_flush_buffer;
+	serial_driver.ioctl = rs_ioctl;
+	serial_driver.throttle = rs_throttle;
+	serial_driver.unthrottle = rs_unthrottle;
+	serial_driver.set_termios = rs_set_termios;
+	serial_driver.stop = rs_stop;
+	serial_driver.start = rs_start;
+	serial_driver.hangup = rs_hangup;
+	serial_driver.break_ctl = rs_break;
+	serial_driver.send_xchar = rs_send_xchar;
+	serial_driver.wait_until_sent = rs_wait_until_sent;
+	serial_driver.read_proc = rs_read_proc;
+	
+	/*
+	 * The callout device is just like normal device except for
+	 * major number and the subtype code.
+	 */
+	callout_driver = serial_driver;
+#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
+	callout_driver.name = "cua/%d";
+#else
+	callout_driver.name = "cua";
+#endif
+	callout_driver.major = TTYAUX_MAJOR;
+	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+	callout_driver.read_proc = 0;
+	callout_driver.proc_entry = 0;
+
+	if (tty_register_driver(&serial_driver))
+		panic("Couldn't register serial driver\n");
+	if (tty_register_driver(&callout_driver))
+		panic("Couldn't register callout driver\n");
+	
+	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+		state->baud_base = get_au1000_uart_baud();
+		state->magic = SSTATE_MAGIC;
+		state->line = i;
+		state->type = PORT_UNKNOWN;
+		state->custom_divisor = 0;
+		state->close_delay = 5*HZ/10;
+		state->closing_wait = 30*HZ;
+		state->callout_termios = callout_driver.init_termios;
+		state->normal_termios = serial_driver.init_termios;
+		state->icount.cts = state->icount.dsr = 
+			state->icount.rng = state->icount.dcd = 0;
+		state->icount.rx = state->icount.tx = 0;
+		state->icount.frame = state->icount.parity = 0;
+		state->icount.overrun = state->icount.brk = 0;
+		state->irq = irq_cannonicalize(state->irq);
+		if (state->hub6)
+			state->io_type = SERIAL_IO_HUB6;
+		if (state->port && check_region(state->port,8)) {
+			continue;
+		}
+
+		if (state->flags & ASYNC_BOOT_AUTOCONF) {
+			autoconfig(state);
+		}
+	}
+	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+		if (state->type == PORT_UNKNOWN) {
+			continue;
+		}
+		printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n",
+		       state->line + SERIAL_DEV_OFFSET,
+		       (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
+		       state->port, state->irq,
+		       uart_config[state->type].name);
+		tty_register_devfs(&serial_driver, 0,
+				   serial_driver.minor_start + state->line);
+		tty_register_devfs(&callout_driver, 0,
+				   callout_driver.minor_start + state->line);
+	}
+	return 0;
+}
+
+/*
+ * register_serial and unregister_serial allows for 16x50 serial ports to be
+ * configured at run-time, to support PCMCIA modems.
+ */
+ 
+/**
+ *	register_serial - configure a 16x50 serial port at runtime
+ *	@req: request structure
+ *
+ *	Configure the serial port specified by the request. If the
+ *	port exists and is in use an error is returned. If the port
+ *	is not currently in the table it is added.
+ *
+ *	The port is then probed and if neccessary the IRQ is autodetected
+ *	If this fails an error is returned.
+ *
+ *	On success the port is ready to use and the line number is returned.
+ */
+ 
+int register_serial(struct serial_struct *req)
+{
+	int i;
+	unsigned long flags;
+	struct serial_state *state;
+	struct async_struct *info;
+	unsigned long port;
+
+	port = req->port;
+	if (HIGH_BITS_OFFSET)
+		port += (unsigned long) req->port_high << HIGH_BITS_OFFSET;
+
+	save_flags(flags); cli();
+	for (i = 0; i < NR_PORTS; i++) {
+		if ((rs_table[i].port == port) &&
+		    (rs_table[i].iomem_base == req->iomem_base))
+			break;
+	}
+	if (i == NR_PORTS) {
+		for (i = 0; i < NR_PORTS; i++)
+			if ((rs_table[i].type == PORT_UNKNOWN) &&
+			    (rs_table[i].count == 0))
+				break;
+	}
+	if (i == NR_PORTS) {
+		restore_flags(flags);
+		return -1;
+	}
+	state = &rs_table[i];
+	if (rs_table[i].count) {
+		restore_flags(flags);
+		printk("Couldn't configure serial #%d (port=%ld,irq=%d): "
+		       "device already open\n", i, port, req->irq);
+		return -1;
+	}
+	state->irq = req->irq;
+	state->port = port;
+	state->flags = req->flags;
+	state->io_type = req->io_type;
+	state->iomem_base = req->iomem_base;
+	state->iomem_reg_shift = req->iomem_reg_shift;
+	if (req->baud_base)
+		state->baud_base = req->baud_base;
+	if ((info = state->info) != NULL) {
+		info->port = port;
+		info->flags = req->flags;
+		info->io_type = req->io_type;
+		info->iomem_base = req->iomem_base;
+		info->iomem_reg_shift = req->iomem_reg_shift;
+	}
+	autoconfig(state);
+	if (state->type == PORT_UNKNOWN) {
+		restore_flags(flags);
+		printk("register_serial(): autoconfig failed\n");
+		return -1;
+	}
+	restore_flags(flags);
+
+       printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n",
+	      state->line + SERIAL_DEV_OFFSET,
+	      state->iomem_base ? "iomem" : "port",
+	      state->iomem_base ? (unsigned long)state->iomem_base :
+	      state->port, state->irq, uart_config[state->type].name);
+	tty_register_devfs(&serial_driver, 0,
+			   serial_driver.minor_start + state->line); 
+	tty_register_devfs(&callout_driver, 0,
+			   callout_driver.minor_start + state->line);
+	return state->line + SERIAL_DEV_OFFSET;
+}
+
+/**
+ *	unregister_serial - deconfigure a 16x50 serial port
+ *	@line: line to deconfigure
+ *
+ *	The port specified is deconfigured and its resources are freed. Any
+ *	user of the port is disconnected as if carrier was dropped. Line is
+ *	the port number returned by register_serial().
+ */
+
+void unregister_serial(int line)
+{
+	unsigned long flags;
+	struct serial_state *state = &rs_table[line];
+
+	save_flags(flags); cli();
+	if (state->info && state->info->tty)
+		tty_hangup(state->info->tty);
+	state->type = PORT_UNKNOWN;
+	printk(KERN_INFO "tty%02d unloaded\n", state->line);
+	/* These will be hidden, because they are devices that will no longer
+	 * be available to the system. (ie, PCMCIA modems, once ejected)
+	 */
+	tty_unregister_devfs(&serial_driver,
+			     serial_driver.minor_start + state->line);
+	tty_unregister_devfs(&callout_driver,
+			     callout_driver.minor_start + state->line);
+	restore_flags(flags);
+}
+
+static void __exit rs_fini(void) 
+{
+	unsigned long flags;
+	int e1, e2;
+	int i;
+	struct async_struct *info;
+
+	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
+	del_timer_sync(&serial_timer);
+	save_flags(flags); cli();
+        remove_bh(SERIAL_BH);
+	if ((e1 = tty_unregister_driver(&serial_driver)))
+		printk("serial: failed to unregister serial driver (%d)\n",
+		       e1);
+	if ((e2 = tty_unregister_driver(&callout_driver)))
+		printk("serial: failed to unregister callout driver (%d)\n", 
+		       e2);
+	restore_flags(flags);
+
+	for (i = 0; i < NR_PORTS; i++) {
+		if ((info = rs_table[i].info)) {
+			rs_table[i].info = NULL;
+			kfree(info);
+		}
+		if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port) {
+				release_region(rs_table[i].port, 8);
+		}
+	}
+	if (tmp_buf) {
+		unsigned long pg = (unsigned long) tmp_buf;
+		tmp_buf = NULL;
+		free_page(pg);
+	}
+}
+
+module_init(rs_init);
+module_exit(rs_fini);
+MODULE_DESCRIPTION("Au1000 serial driver");
+
+
+/*
+ * ------------------------------------------------------------
+ * Serial console driver
+ * ------------------------------------------------------------
+ */
+#ifdef CONFIG_AU1000_SERIAL_CONSOLE
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static struct async_struct async_sercons;
+
+/*
+ *	Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct async_struct *info)
+{
+	unsigned int status, tmout = 0xffffff;
+
+	do {
+		status = serial_in(info, UART_LSR);
+
+		if (status & UART_LSR_BI)
+			lsr_break_flag = UART_LSR_BI;
+		
+		if (--tmout == 0)
+			break;
+	} while((status & BOTH_EMPTY) != BOTH_EMPTY);
+}
+
+
+/*
+ *	Print a string to the serial port trying not to disturb
+ *	any possible real use of the port...
+ *
+ *	The console_lock must be held when we get here.
+ */
+static void serial_console_write(struct console *co, const char *s,
+				unsigned count)
+{
+	static struct async_struct *info = &async_sercons;
+	int ier;
+	unsigned i;
+
+	/*
+	 *	First save the IER then disable the interrupts
+	 */
+	ier = serial_in(info, UART_IER);
+	serial_out(info, UART_IER, 0x00);
+
+	/*
+	 *	Now, do each character
+	 */
+	for (i = 0; i < count; i++, s++) {
+		wait_for_xmitr(info);
+
+		/*
+		 *	Send the character out.
+		 *	If a LF, also do CR...
+		 */
+		serial_out(info, UART_TX, *s);
+		if (*s == 10) {
+			wait_for_xmitr(info);
+			serial_out(info, UART_TX, 13);
+		}
+	}
+
+	/*
+	 *	Finally, Wait for transmitter & holding register to empty
+	 * 	and restore the IER
+	 */
+	wait_for_xmitr(info);
+	serial_out(info, UART_IER, ier);
+}
+
+/*
+ *	Receive character from the serial port
+ */
+static int serial_console_wait_key(struct console *co)
+{
+	static struct async_struct *info;
+	int ier, c;
+
+	info = &async_sercons;
+
+	/*
+	 *	First save the IER then disable the interrupts so
+	 *	that the real driver for the port does not get the
+	 *	character.
+	 */
+	ier = serial_in(info, UART_IER);
+	serial_out(info, UART_IER, 0x00);
+ 
+	while ((serial_in(info, UART_LSR) & UART_LSR_DR) == 0);
+	c = serial_in(info, UART_RX);
+
+	/*
+	 *	Restore the interrupts
+	 */
+	serial_out(info, UART_IER, ier);
+
+	return c;
+}
+
+static kdev_t serial_console_device(struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+/*
+ *	Setup initial baud/bits/parity. We do two things here:
+ *	- construct a cflag setting for the first rs_open()
+ *	- initialize the serial port
+ *	Return non-zero if we didn't find a serial port.
+ */
+static int __init serial_console_setup(struct console *co, char *options)
+{
+	static struct async_struct *info;
+	struct serial_state *state;
+	unsigned cval;
+	int	baud = 9600;
+	int	bits = 8;
+	int	parity = 'n';
+	int	cflag = CREAD | HUPCL | CLOCAL;
+	int	quot = 0;
+	char	*s;
+
+	if (options) {
+		baud = simple_strtoul(options, NULL, 10);
+		s = options;
+		while(*s >= '0' && *s <= '9')
+			s++;
+		if (*s) parity = *s++;
+		if (*s) bits   = *s - '0';
+	}
+
+	/*
+	 *	Now construct a cflag setting.
+	 */
+	switch(baud) {
+		case 1200:
+			cflag |= B1200;
+			break;
+		case 2400:
+			cflag |= B2400;
+			break;
+		case 4800:
+			cflag |= B4800;
+			break;
+		case 19200:
+			cflag |= B19200;
+			break;
+		case 38400:
+			cflag |= B38400;
+			break;
+		case 57600:
+			cflag |= B57600;
+			break;
+		case 115200:
+			cflag |= B115200;
+			break;
+		case 9600:
+		default:
+			cflag |= B9600;
+			break;
+	}
+	switch(bits) {
+		case 7:
+			cflag |= CS7;
+			break;
+		default:
+		case 8:
+			cflag |= CS8;
+			break;
+	}
+	switch(parity) {
+		case 'o': case 'O':
+			cflag |= PARODD;
+			break;
+		case 'e': case 'E':
+			cflag |= PARENB;
+			break;
+	}
+	co->cflag = cflag;
+
+	/*
+	 *	Divisor, bytesize and parity
+	 */
+	state = rs_table + co->index;
+	info = &async_sercons;
+	info->magic = SERIAL_MAGIC;
+	info->state = state;
+	info->port = state->port;
+	info->flags = state->flags;
+	info->io_type = state->io_type;
+	info->iomem_base = state->iomem_base;
+	info->iomem_reg_shift = state->iomem_reg_shift;
+	state->baud_base = get_au1000_uart_baud();
+	quot = state->baud_base / baud;
+
+	cval = cflag & (CSIZE | CSTOPB);
+	cval >>= 4;
+	if (cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+
+	/*
+	 *	Disable UART interrupts, set DTR and RTS high
+	 *	and set speed.
+	 */
+	serial_out(info, UART_CLK, quot & 0xffff);
+	serial_out(info, UART_IER, 0);
+	serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
+
+	/*
+	 *	If we read 0xff from the LSR, there is no UART here.
+	 */
+	if (serial_in(info, UART_LSR) == 0xff)
+		return -1;
+
+	return 0;
+}
+
+static struct console sercons = {
+	name:		"ttyS",
+	write:		serial_console_write,
+	device:		serial_console_device,
+	wait_key:	serial_console_wait_key,
+	setup:		serial_console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		-1,
+};
+
+/*
+ *	Register console.
+ */
+void __init au1000_serial_console_init(void)
+{
+	register_console(&sercons);
+}
+#endif
+
+/*
+  Local variables:
+  compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i586 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h   -DEXPORT_SYMTAB -c serial.c"
+  End:
+*/
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/time.c linux/arch/mips/au1000/common/time.c
--- v2.4.9/linux/arch/mips/au1000/common/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/common/time.c	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2001 MontaVista Software, ppopov@mvista.com
+ * Copied and modified Carsten Langgaard's time.c
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope 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.
+ *
+ * ########################################################################
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/div64.h>
+#include <asm/au1000.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+extern volatile unsigned long wall_jiffies;
+unsigned long missed_heart_beats = 0;
+unsigned long uart_baud_base;
+
+static unsigned long r4k_offset; /* Amount to increment compare reg each time */
+static unsigned long r4k_cur;    /* What counter should be at next timer irq */
+extern rwlock_t xtime_lock;
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+
+static inline void ack_r4ktimer(unsigned long newval)
+{
+	write_32bit_cp0_register(CP0_COMPARE, newval);
+}
+
+
+/*
+ * There are a lot of conceptually broken versions of the MIPS timer interrupt
+ * handler floating around.  This one is rather different, but the algorithm
+ * is provably more robust.
+ */
+unsigned long wtimer;
+void mips_timer_interrupt(struct pt_regs *regs)
+{
+	int irq = 7;
+
+	if (r4k_offset == 0)
+		goto null;
+
+	do {
+		kstat.irqs[0][irq]++;
+		do_timer(regs);
+		r4k_cur += r4k_offset;
+		ack_r4ktimer(r4k_cur);
+
+	} while (((unsigned long)read_32bit_cp0_register(CP0_COUNT)
+	         - r4k_cur) < 0x7fffffff);
+
+	return;
+
+null:
+	ack_r4ktimer(0);
+}
+
+/* 
+ * Figure out the r4k offset, the amount to increment the compare
+ * register for each time tick. 
+ * Use the Programmable Counter 1 to do this.
+ */
+unsigned long cal_r4koff(void)
+{
+	unsigned long count;
+	unsigned long cpu_pll;
+	unsigned long cpu_speed;
+	unsigned long start, end;
+	unsigned long counter;
+	int i;
+	int trim_divide = 16;
+
+	counter = inl(PC_COUNTER_CNTRL);
+	outl(counter | PC_CNTRL_EN1, PC_COUNTER_CNTRL);
+
+	while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_T1S);
+	outl(trim_divide-1, PC1_TRIM);    /* RTC now ticks at 32.768/16 kHz */
+	while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_T1S);
+
+	while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_C1S);
+	outl (0, PC1_COUNTER_WRITE);
+	while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_C1S);
+
+	start = inl(PC1_COUNTER_READ);
+	start += 2;
+	/* wait for the beginning of a new tick */
+	while (inl(PC1_COUNTER_READ) < start);
+
+	/* Start r4k counter. */
+	write_32bit_cp0_register(CP0_COUNT, 0);
+	end = start + (32768 / trim_divide)/2; /* wait 0.5 seconds */
+
+	while (end > inl(PC1_COUNTER_READ));
+
+	count = read_32bit_cp0_register(CP0_COUNT);
+	cpu_speed = count * 2;
+	uart_baud_base = (((cpu_speed) / 4) / 16);
+	return (cpu_speed / HZ);
+}
+
+static unsigned long __init get_mips_time(void)
+{
+	return inl(PC0_COUNTER_READ);
+}
+
+void __init time_init(void)
+{
+        unsigned int est_freq, flags;
+
+	printk("calculating r4koff... ");
+	r4k_offset = cal_r4koff();
+	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
+
+	//est_freq = 2*r4k_offset*HZ;	
+	est_freq = r4k_offset*HZ;	
+	est_freq += 5000;    /* round */
+	est_freq -= est_freq%10000;
+	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, 
+	       (est_freq%1000000)*100/1000000);
+	r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
+
+	write_32bit_cp0_register(CP0_COMPARE, r4k_cur);
+	set_cp0_status(ALLINTS);
+
+	/* Read time from the RTC chipset. */
+	write_lock_irqsave (&xtime_lock, flags);
+	xtime.tv_sec = get_mips_time();
+	xtime.tv_usec = 0;
+	write_unlock_irqrestore(&xtime_lock, flags);
+}
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+#define USECS_PER_JIFFY_FRAC ((1000000ULL << 32) / HZ & 0xffffffff)
+
+/* Cycle counter value at the previous timer interrupt.. */
+
+static unsigned int timerhi = 0, timerlo = 0;
+
+static unsigned long
+div64_32(unsigned long v1, unsigned long v2, unsigned long v3)
+{
+	unsigned long r0;
+	do_div64_32(r0, v1, v2, v3);
+	return r0;
+}
+
+
+/*
+ * FIXME: Does playing with the RP bit in c0_status interfere with this code?
+ */
+static unsigned long do_fast_gettimeoffset(void)
+{
+	u32 count;
+	unsigned long res, tmp;
+	unsigned long r0;
+
+	/* Last jiffy when do_fast_gettimeoffset() was called. */
+	static unsigned long last_jiffies=0;
+	unsigned long quotient;
+
+	/*
+	 * Cached "1/(clocks per usec)*2^32" value.
+	 * It has to be recalculated once each jiffy.
+	 */
+	static unsigned long cached_quotient=0;
+
+	tmp = jiffies;
+
+	quotient = cached_quotient;
+
+	if (tmp && last_jiffies != tmp) {
+		last_jiffies = tmp;
+		if (last_jiffies != 0) {
+			r0 = div64_32(timerhi, timerlo, tmp);
+			quotient = div64_32(USECS_PER_JIFFY, USECS_PER_JIFFY_FRAC, r0);
+			cached_quotient = quotient;
+		}
+	}
+
+	/* Get last timer tick in absolute kernel time */
+	count = read_32bit_cp0_register(CP0_COUNT);
+
+	/* .. relative to previous jiffy (32 bits is enough) */
+	count -= timerlo;
+
+	__asm__("multu\t%1,%2\n\t"
+		"mfhi\t%0"
+		:"=r" (res)
+		:"r" (count),
+		 "r" (quotient));
+
+	/*
+ 	 * Due to possible jiffies inconsistencies, we need to check 
+	 * the result so that we'll get a timer that is monotonic.
+	 */
+	if (res >= USECS_PER_JIFFY)
+		res = USECS_PER_JIFFY-1;
+
+	return res;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned int flags;
+
+	read_lock_irqsave (&xtime_lock, flags);
+	*tv = xtime;
+	tv->tv_usec += do_fast_gettimeoffset();
+
+	/*
+	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+	 * is nonzero if the timer bottom half hasnt executed yet.
+	 */
+	if (jiffies - wall_jiffies)
+		tv->tv_usec += USECS_PER_JIFFY;
+
+	read_unlock_irqrestore (&xtime_lock, flags);
+
+	if (tv->tv_usec >= 1000000) {
+		tv->tv_usec -= 1000000;
+		tv->tv_sec++;
+	}
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+	write_lock_irq (&xtime_lock);
+
+	/* This is revolting. We need to set the xtime.tv_usec correctly.
+	 * However, the value in this location is is value at the last tick.
+	 * Discover what correction gettimeofday would have done, and then
+	 * undo it!
+	 */
+	tv->tv_usec -= do_fast_gettimeoffset();
+
+	if (tv->tv_usec < 0) {
+		tv->tv_usec += 1000000;
+		tv->tv_sec--;
+	}
+
+	xtime = *tv;
+	time_adjust = 0;		/* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+
+	write_unlock_irq (&xtime_lock);
+}
+
+/*
+ * The UART baud base is not known at compile time ... if
+ * we want to be able to use the same code on different
+ * speed CPUs.
+ */
+unsigned long get_au1000_uart_baud()
+{
+	return uart_baud_base;
+}
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/pb1000/Makefile linux/arch/mips/au1000/pb1000/Makefile
--- v2.4.9/linux/arch/mips/au1000/pb1000/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/pb1000/Makefile	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,24 @@
+#
+#  Copyright 2000 MontaVista Software Inc.
+#  Author: MontaVista Software, Inc.
+#     	ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Semiconductor PB1000 board.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: pb1000.o
+
+O_TARGET := pb1000.o
+
+obj-y := init.o setup.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/pb1000/init.c linux/arch/mips/au1000/pb1000/init.c
--- v2.4.9/linux/arch/mips/au1000/pb1000/init.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/pb1000/init.c	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,59 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	PB1000 board setup
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+extern int prom_argc;
+extern char **prom_argv, **prom_envp;
+extern void  __init prom_init_cmdline(void);
+
+int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+{
+	prom_argc = argc;
+	prom_argv = argv;
+	prom_envp = envp;
+
+	mips_machgroup = MACH_GROUP_ALCHEMY;
+	mips_machtype = MACH_PB1000;  
+
+	prom_init_cmdline();
+
+	add_memory_region(1, 64 << 20, BOOT_MEM_RAM);
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/pb1000/setup.c linux/arch/mips/au1000/pb1000/setup.c
--- v2.4.9/linux/arch/mips/au1000/pb1000/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/au1000/pb1000/setup.c	Sun Sep  9 10:43:01 2001
@@ -0,0 +1,117 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Au1000-based board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/au1000.h>
+
+#if defined(CONFIG_AU1000_SERIAL_CONSOLE)
+extern void console_setup(char *, int *);
+char serial_console[20];
+#endif
+
+void (*__wbflush) (void);
+extern struct rtc_ops no_rtc_ops;
+extern char * __init prom_getcmdline(void);
+extern void au1000_restart(void);
+extern void au1000_halt(void);
+extern void au1000_power_off(void);
+
+struct {
+    struct resource ram;
+    struct resource io;
+    struct resource sram;
+    struct resource flash;
+    struct resource boot;
+    struct resource pcmcia;
+    struct resource lcd;
+} au1000_resources = {
+    { "RAM",           0,          0x3FFFFFF,  IORESOURCE_MEM },
+    { "I/O",           0x10000000, 0x119FFFFF                 },
+    { "SRAM",          0x1e000000, 0x1E03FFFF                 },
+    { "System Flash",  0x1F800000, 0x1FBFFFFF                 },
+    { "Boot ROM",      0x1FC00000, 0x1FFFFFFF                 },
+    { "PCMCIA",        0x20000000, 0x27FFFFFF                 },
+    { "LCD",           0x60000000, 0x603FFFFF                 },
+};
+
+void au1000_wbflush(void)
+{
+	__asm__ volatile ("sync");
+}
+
+void __init au1000_setup(void)
+{
+	char *argptr;
+
+	argptr = prom_getcmdline();
+
+#ifdef CONFIG_AU1000_SERIAL_CONSOLE
+	if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) {
+		argptr = prom_getcmdline();
+		strcat(argptr, " console=ttyS0,115200");
+	}
+#endif	  
+
+	//set_cp0_status(ST0_FR,0);
+	rtc_ops = &no_rtc_ops;
+        __wbflush = au1000_wbflush;
+	_machine_restart = au1000_restart;
+	_machine_halt = au1000_halt;
+	_machine_power_off = au1000_power_off;
+
+	/*
+	 * IO/MEM resources. 
+	 */
+	mips_io_port_base = KSEG1;
+	ioport_resource.start = au1000_resources.io.start;
+	ioport_resource.end = au1000_resources.lcd.end;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+#endif
+
+	outl(PC_CNTRL_E0 | PC_CNTRL_EN0 | PC_CNTRL_EN0, PC_COUNTER_CNTRL);
+	while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_T0S);
+	outl(0x8000-1, PC0_TRIM);
+
+	printk("Alchemy Semi PB1000 Board\n");
+	printk("Au1000/PB1000 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
diff -u --recursive --new-file v2.4.9/linux/arch/mips/baget/irq.c linux/arch/mips/baget/irq.c
--- v2.4.9/linux/arch/mips/baget/irq.c	Tue Mar  6 19:44:36 2001
+++ linux/arch/mips/baget/irq.c	Sun Sep  9 10:43:01 2001
@@ -4,8 +4,6 @@
  * Copyright (C) 1998 Vladimir Roganov & Gleb Raiko
  *      Code (mostly sleleton and comments) derived from DECstation IRQ
  *      handling.
- *
- * $Id: irq.c,v 1.6 2000/02/04 07:40:23 ralf Exp $
  */
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -180,7 +178,7 @@
 	int do_random, cpu;
 
 	cpu = smp_processor_id();
-	irq_enter(cpu);
+	irq_enter(cpu, irq);
 	kstat.irqs[cpu][irq]++;
 
 	mask_irq(irq);  
@@ -202,7 +200,7 @@
 		printk("do_IRQ: Unregistered IRQ (0x%X) oc  struQ (0Vp8,7 @@
mrt numI-  strc  strul_oQ: sole5  0x1FHEre F35Hmachine_restart = auUB;
 	ks you can d9stereurces.lcB;
 	/setup.c
_BN2=FNUcB;
 	/setup.c
_BN2=FNUcB;
 	/setup.c
_BN2=FNUcB;
>FU HWr **pgk7rt is ready the xIE6/02/AD_Vp8,7 @mIE6/02.1(+ *ps
+
+	mip LI
>FU HW Dteor: M+);  
statoid)
+rq.Plished @@ /,sta Software I=Ihed @i@ /,sta Software I=Soff;
8nit.h>
+#s31 1id)
Toff;
Dff;
8nco.h>
8OWEVEced bretware I=== NR_1(+ .,v 1.6 tCc0	ROOT_DEI=== 
+		if 2;
 af 1oy(struct consoegirus(S 2;
 e us 1id8,7 @@s7 @@s7 @@s7 @@s7 @@s7 @@s7 @@s7 @@u%7 @@s7 @@s1r_
+	ack_r4ktimer(0);
+}SERVICES; LOet/irq.c l9u +}
+
+/s7 @@s7 @@s7 @@u%7 @@s7 @@s1r_
+	ack_c l9ux/archFBFmach2;
 e r, thG', cpu;
 
 	cpu BPO9u +}
+cE GOOD@@sOe are a lnt.r,N2(3%LIED
+- 	c 
 5;sole=;/,sta Soft
+{     0x1FC00000, 0x1FFFFFFF                 2ouldn't @aGOF
+ *  THCES; LOetem_base)e I->line M)ine HS; LOe_e I-IdmM_random, cpu;
v:100rips/au cpu;
v:10baget/irq.c	S,0U 	c 
 5;soleS10baget/irq.cmM_Dioc /au100cick.10baget/istr be m
etimer bottCPnfig.a lnt. */
<C port      }3l_Dioc eHyoegirus(S
+}6 I@@s7 @@sv0rom, cp
Toff;r2Lrxec,0 +1,24 @@
+RbR @@
+RbRbR @@foP cpu;
7_
+
+vo.
+vo.trc  stI@@s@mvista.com O+	retu10bc2Fc0	E/, SPECIAL,M_Dioc Frs4ng r= au100I
>e.trc  g.a lnt. */
<C por veoftware Fou,;
8nit.h>
+#s31 1id)
DaL);
+r(gL);

+	_m#m 7 @are 
<C po0Sep  9 10:43:01 20 lnt.T0_regiU,ux/init.h>
@@ -180,7 +178,42m O+ O+	retu1 rs_ 10:43isteresourceGNU Getk("d	 *3 aE  { ng r= aF	save_f+    st3,FFOlIt3,FFOlI:.FOlI:(gL);

+	_m#m>port,r0nt re  st3,FFOlIt3,rFc0	E%@D/bagiaetup.c
U_f+ Doft
EOe0	.PFOlIt3,rrt(voFOlI:(g178**pgk7rt is readC0d78**_I-s7 @@s2fin 5empt7 @IS 2ouldn'4ime(vrch/LCt = st:sourcemachine_pagiaL:t3,rrt(voFOlI:(g178**pgk7rt is readC0d7%c0	EI}PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+
+	wCONSEZc +}LOetAAb@mIESa
.7I,rrter(C | HU	@cC0d7%1ff;
8ral Pu3,FT_DEI=== /setup.1(+ .,v 1.odo_set
+	write_unlock_irqr-1OT_D+	sDockN:.FT_DEI=== /se4,;
8nit.h>
+#t40ckN:.FK eacu58nit.+#t40ckNl_T_D+%s\n",SSSSSSSSSSSSEq.c l9Hm is pOoite t.
+	 */
+	if (jiffies - wl}]\n",S 2oes - wl}]\n",S =w+}
+
v*/
+	x603F>
+#inclXlude aL);
+r(gL);

+		sDFOlI:(g178**pg>
 #in"serial: fac.h>
+#incpiOvI_  THSTAT
<C po0Sep  9teFn5D
+		sm/au1000.h>
+
9teFn5D
  WARRA5D
+		sm/au1000.hegiU,u.E #in2oes --1Fo4CI 
 	/au1+ *	PB10v*/:    {O2 | ItaVia.
+  4 - wl}]\n",S 2oesA_UNSYNC;
+	timeash", 0000(ie not F *	PB10v*/:    {O2rq);
 	_driveX5ock on the MIPS boards.
+ **NC;
O2rq)timeash", 00000000000/: inl(PC7seUSE, DATA,  E FOR A inl(P)h", 0000(ie noa5D
d_OR c_ton.
+ *
 = rs_put_, 0000(ie not F *	PB10v*/:  m_reg_shifaileed2PUR)p0reg_shifl(PC7srs_put_,)h",=r LOes_put_,,,,,EIU)c->iO prom_getcmdrmdr,EIU)c->
r@D/bs *rv, 0000000a)M noa5D
.PlisdPR:+	time_e CACT,u7ead 0xff from tp8,7 @mIEot FIOdrv,0", 00valusDN(,4fv,0", Erv,0", 00valu	 * HoeFK e`k on Olu	 *m$eEoR#+
+#irrmios;
+ @;in 5em' 969  A+
+#irin 5emDcbaget/irq.c
--- v2.4.9/linux/arch/mips/baget/ir
 	_dri+#ir(p, int * = s_0M-Hm`D 0d7%c0;
+
}r6 tCc0	Rc0;
+
}rNSOLE
+
c in+
}r6 tCc0	Rc0;
0I	ti0PM_| ItaVia.7ead 0xff from tp8,7 @mIEot FIOdrv+++ lhed by t: failed to unregis8**pgk7a(RM7 @mIEo_reg_sundation;  eithec0;
 ",
+	the  G_CNTRLI on;  a WARRA5D
+		sm/au1000.hegiU,u.nseare Fou,;
8nit.h>
+#s3, timerlo = 0;
+
+st
+st
+ - w+
+st
+st
ff frw
+	tu);
+mo
ff fL_T1S) w+
++
++
++
++969  A+
+#irin 5emDES; LOetem_basHS; LOe_e endom, cpuTERRUPTION) HOWEVER rfesHS; LOe_e2.4.9/linux/arch/mirfesHS 2oSYNC;
EI=== 
+FOlIt3,rrt(voFOlI:(g1Ko3,rrt(T,24 @@
EHS; LOe_e2.4.9/linux/arch/mirfesHS 2oSYNC;
EI=== 
+FOlIt3,rrt(vo TxlkB,, +
+Flags)dM3FFFFFF,  IORESOURCr = NTP_PHASE_LIMIT;
+
+	write_uOSE_LIMaMs_pulo;
+
+x1HOW42:.FOlI:(gSIMaM;n--- v2.,70B-1Fo4ed  USOFo4tUNut_,,,d	S,l0 +x1HOW42:.F-T, ST+x1HOocst =dUSOF     f?
_ti7s_write;
+	E1_t =dU) w+
++
++
++
++969  A+
+#irin 5eS ier);
+
+	info;  A+
pI00/init.c	Sun Sep  7 @@s7 @@s7 @@s7 @@s7 @@s1Foet%c0;
+Imt =r =r t.c	Sunx+70B-1Fo4eun Selnx+7U}ti7s_write;
CmachiLcmSelnx+7U1lt:@@s7 @ruct resource pcmcia;
+    struRN_INFOT+			cf     seriPR)
+	         - r4k_cur) < 0x7fffffff);BlMP00/pb1ar * __init p(g1Kf);Bl auUB;
 g,long r4k_offset; /* Amount to inoffs0.trc  stI@@s@mvista.com O+	retu10bc2Fc0	E/, S18rs3f:1x60000);(Aileed2PUR)p0reg_shifl(PC7mcia;
+   jiffies - wall_jiffies
+	  .mouiP+	statw
<C yi_puerd's gall_0tart(void);
+ext)de -Wall - DAUR+	 * is nonzero if thepcce boot;
+    strurt_resource;
+prom_ 
 esouro )C;
EI===cp0_recot FIOdrv+++ st
+st
+ - w+
rv+++RCE_MEM },
k/ w+
rst
+st
+ -,Fto C;
ECmachiLcmD&ca(v0M-Hm`D 0d7%c0;
+,om`D 0ndom, s31 1
+#inclXluddM3Frh>
 7%c0;
D
+		sm/au+st
+st 7%c_irqoU,qoU,;(Ai:UHm`D 0/Fs );
+XluddM3Me7 @@s7H2pimu+st
+st 7%c_irqoL );
to ia, m`D $
  */
 remooption) any lasP0O
++
++
++969  A+
+#irin 5eS ier);rm1Irin 5eS ier),fig.h> readC0d pooSYNE5_
+#inc:+#incpiOM .mouiP+	stS,tate _-*  THCor4k_1,shie-	callo0(+
+#iricountg.h> rv*  THCor/irsv);
+
+rv* h> rv LOes_put_,,,,,EIU)c->iO prom_gett
+ -,FtrfeEf?A)m_base;
+		info--,FtrfeEf?A)m_bas1EI+3U ins proc0;
+,om`D 0ndomYo rd
++
++ 7%c0;
D
+		sm/au+st
+st 7%c_irqoU,qoU,;(Ai:UHm`D 0/Fs );
+XluddM3Me7 @@s7H2pimu+st
+st 7%c_irqoL );
to ia, m`D $
  */
 remooption) any lasP0O
++
++
++969  A+
+#irin 5eS ier);rm1Irin 5eS ier),fig.h> readC0d pooSYNE5_
+#inc:+#incpiOM .mouiP+	stS,tate _-*  THC_cn5D
  l    - r4kurceGNU G8S,tate _-*  THC_cn5D
 0ncludk_1m_getcmdline();
+
+#ifdef /        })a)An Selnx+7U}ti7s_write;
CmachiLcmSelnx+_1m_6rite;
CmachiLcmiLcmiLceconfigC9,cmiLceconf+_1m_6 0p wan0Sep T_MCR_DTR | UART_MCR_RTS);
+
+9
+
+9
+
tr(info);
+	ser3E,3E,3E,3}h}rqoL );
t0miLceconf+ower_o @@s7 /ME,3E,30p waMrn 0;
Z
+#irrmi	Return	tu);
+mo
ff fL_T1S) w+
++
++
++
++9
+XboS) w+
V_e2.41S) w_++
++
++.cTUrent
+ *Q do twQL ENon;  epn voide resul+
+, S18r L_CONSOLODD;
+		t
++ 7%c0;UL/* ..T?
_ti&r_dec) w_++sar(staMs_pw+
V_e2);
+}
I#ende boo MIPSr 7%c0;
D
+0r 7
V_e2);config3nt) {
+		resto+#inclusec)*2^32" val 35 pr  = 0; i < NR_POYnfigC9,cmiLcec7Inc.
+ *  		restorU,;(+
++
+:es.lcd.>
 7dlineceGNU G8S,tatepr  GNUYw]
 #iaMIPSr  <linaneceG ,mI- o--,	/*
+ w_+r  6 ++
	+
++ 7%c0;
D
+	a+
+FlaEeS ier),fig.h> readC0d pooSYNE5_,
+S iN++ fdef9lesourcIbKk("Au"RAM",  $.nn UART_1DC) EYBvMDISK_MAJOR, 0);
UN= MACH_GROUfl(PC[ LSR, == 
+FOlIt3#incnx+_1m_6r(Pr_
te;
CmMT | G++ +
+	return;
 aninuR-R7+
+x1E)NSOLEUCfset);gwQL 2000/02/04 07:40:23 rak	sm/6r(Pr_
te;
CmMT | G+PFYnfigIle=ttyS0nf+_ig.h> readC0d pooSYNE5_
+#inc:+#incpiOM .3lU+iN++0(+
+#iricouUeC/E FOc:23 ranfigIle=
iN++0(+
+h cset);gwQL 2000/02/04+SOLEcd.>:,/E FOc23 raO_
+#inc:L Start r4k coeq = r4R/E0 | PC_CNTRLNR_PO| PC^confignclusec)*2^3rR_PO| PCSu w+
+stpmC^cdpooSYNE5_upuUB;
 	ks you can f=ov1u| PC^conf3I=SE5_s sv cpu +
+:es.lcd.>
 7dlineceGNU ieC_COUNTER_rxec,0 +1,24 @@
+RbR @@
+RbRbR u	tmpc1v for eS9PTFnfigIle=/ is noff;ev cpl9u fTAT
<CS),0 +1,+++
+++
+#ifdef SSSSIle=/ f=ov1uegs,:T
<CSDESCD-fil5O=/ isp++
+D++
+#mdvm; Ol(E/et);s you can f=ov1u| PC^con5cc 0+
+++
+#Pet/irsE^con5cR_Pw+
rv+++RCE_MEM 0s inconsistencieIt.+#   ``AS T_D+	sDockN:.FT_DEI=== /se4,;
8nit.h>
+#t4lags(m_6r(PrOE}
rv+++RCE_MEM oronsist#   ``A0T0OFo4tUNut_,,,d	S +
+	return;
 aninuR-#inc:+_milp#inc:+_milp#inc:+__Pw+
rv++lp#inc:+_case 9eq += 5000;    /* round */
+	est_freqCNTRLNR_PO6 ++E3mips/baeU+;
+	+#t4mipsSe3Ere F3.o setSr +E3,s e ++E3mips/baeUIed last timer ticD
+i&r_dec) w_++sarH
+	+#t4mipsSe32139, rh>Isist#   e,4mipsSe32139, rh2_D
+ec0a,l5eS0ckkN:.FT+	stshift;
+	}
+	autoconfig(state);
+	if (state->type TxlkB,eS0ckTER_rxep<mung uCOUNH_PHA0OFo4tUN(i =		brase)e  	Aep<EUCfs9'E0x1FCVGe _-*  ,
te;
CmMT | G++ +
+	retuRs;
Z
+#ia1UN(i t);s you
rv++lOFo4tNOI
8/ isp++
+D+0WPs,1N=fferenvuRs;
conmem_baset);Toff++969  A+
	int	atart += Mrt(voFOlI:GAc- o-MT | G++ +
+	rFv when hr	rFvt9+ +
+	 MuherenvuRrE6\$< -o ard.
+uRrEo;
EIr	rFVEU+++
+202,nn bpau1ibugr	rFvt9+ +
+	 PF9+ +
+	%c_i Blud  9+  Ohine_haleP"d	 *3bpau1ibugrrrrrrr1e += Mr>y grrval >>= 4;
+	if (cflag & PARENBFFFFF      :i/cmdrmdr,EIU)c->
r@D/bs *rv, 0000000a)M noaRrEo;
EIr	rFVEeRrin 5eS ierf (RENBFFFFF TeS iep:iRrE)0ckTER_r+	}
+	srogram; if not, write  toVpoin Arial_console[20)h", 0000(ie noa5D
d_OR c_toGN/+
++969  SUcc_toGNline/G3Erops_mat);s00a)M noaRrEo;
EIdd_mdlineceGN7H2piDd"register_serial()<g.
+	 */);
+}
+
+/*
+ * The UART baud base is not known ais rea,`D 0/O, timerlo = 0;
+
+st
+st
+ - w+
+b >= Unrace.-LUD0F =MNwn aisprrt(vo3 ao_init)ine HS; LOe_e ,istered IRQ (0x%X) o3Cfs.c	Wed Dec 31 16:00:00 1969
++m) o3ed Dec 3a`v_CBSSdlinea0Y te;
C+}
+
turn ckTERout even the implied NTP_P@@
+/*witeTP_P@@
+/*witeTP_P@@
+/cxsPN_void)id)id):P@@
+/*witeTP_(0S1s notm%o,i off=ov1u|DwaMan t40cks loQ (0Vp8(=00, 0x119FFFFF                 },
+    { "SRAM",          0x1e0,CF        119FFF0MT | G++ +
+	retuF       -rOPiLce) w_/80 L00, 0x119F80 L00, 0x119F8 |=Ef n++
+D+0WP,FeTP_P          Gtcgc+l%8(=00,pau1ibug(H	f S TechnolasF
Oe) w_/80 L00, 0x119F80r|=Ef n++
+D+0WP	ifclvoid)
+{
+	char
D+0WPn",S| PC^cotfhvr(Pr-ae    -rOPiLer_DYt = auUB;
 	ks k      e ieC_COUo-sive --nen bpaE    ua 
ca0Y 
basH_-_R) == 0);
+apaE   m 80 9F80r5cR_PP:ibug(&;
+		neP"d	 *3bpau1ibugrrrrrrr1e3ISING IN ANY WAY OUT OF THE S);
+	outl(trimX->im`Dks k  rsN.M(Pr-aOUT OF THE S);
+	outl(tDENTALtl(triW+x1 ,c  stIT_DEIu1ibug(a int flags;
+
+	read_A(UcaANLCabSe _-*  TErp 0c2*eceGNU PCdlUART_MCRoc F6R .IhwY OUT OF THE IGul 196Er OUTSYfo->iomem_base l 196Er OUTSYfosnF3.o setSr +E3,s e ++E6M
D+0Wi%aiU r4k_offset; /* Amou:b	if (l >>=0ffset;Ff;vr|=Ef/*
+ * The UadC0d78**_I-s7 @@s2fin 5emp0CMCRotRs k      e i@@s2finceGOF [ast
+st,, BOE
+
c ,+
+D+0E
+
c ,+
+D+0E
+
c ,+
+D6 I:  m_reg_l >> [ast
+st,, BOE
W DTMatus, tm003 BOE
+
3v)++ +
+	ret(BOEtIT_DEIu1ibug(a int fSr+}
CabSe _-URsSe3Er,(Rc3(te_32bit_pSr+}
C23pswitc
k/ w+
r3pswist
+ -  7dlineceGNU iEC   119FFF0MFo4tUN
2baeUIeaCkiomem_base l 1lUNatiou}
CabS,,,prom_init(int arc,9FFF0MF/oft
+{    RL00 ies != tmp) rfesFFF0MFcft
+{,t
+hEMelx'v 2F(rc,9FF s,DFOle,
 d2bit_pSr+}
g |= B115200;
+			bF_irqh",=e,
signed 1tmp)119FFF0MT a,l5DaOle,
 d2bol5DaOle, m`D $
  */
7H2piD2 1tmthe     PE0 
10hgGsn	e,
 d2bol5DaOlewrite;
CmachiLcmSelnx+7U1lt:oidst
+a, d2bit7lo{P/EUN
2bait_pSr+n&inl,  :i/cmdrmdr,EIU)c->
r@Dv,CIAL, EXEMtUN
2baeUIeaCkiomem_base l 1lUNatiou}
CabS,,,prom_init(int ar" u drom_AL, EXUas1000.hegiN;
+	}
+	co->cfla<ublic Lec,0 TErp oE}6ul 196Er OUT)1lUN(courom3Ral_consm3`AS  IS'' ANDi} /P;
+	}
+	co_.T)1lUN(col0x1	}
+	co_.T)1lUN(>OSE_*Melant->cfla<(>OSE33*59LODf);
+	P@mvista.com
+ * Copied and modified Carsten Langgaard's time.c
+ *
+ * CarstelUN(1lUrmouiP+	staS,tateTEffset; /ceFEud later veicense, T80 9F80t;Ff;vr|_rDanggaard's time.c
+ *
+ oSYNE5_,
+S iNp#inc:+__Pw+
rv++lp#inc:+P;
+	}
+	co_.T)1 s=+ *
+ oSYNE5_,
+S iNp#inc:+__PwFFFFF         
+   ,, EXEAMaCtr/baget/irq.c
--nfi1lUrmoui fset; /ceFEud lat2+	/* T	em_basHS; ITUTc,8@mvistc3(pb1000/setup.c linux/archSU+;
 ,
rv++lp#inc:+P;
+	}
+	co(4s);
+D    6ce) wrOrc3(pbE:es.lcd1 s=+ce) Trv:sec)*2+ **kOpc3(
+{
+	cflag>Ys.lcd1time_adjust = 0;		/* stop}ION)cmt+,aO pc_ops = &no_rtd: = &no_rtd: = &no_rtd: = &no_rtd:r]000/:+{
+	cfublicE/*
+	4)t+ struRrtd:ock;
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | I+	ret(BOeh2jce) wrOHbare F}_PwFFFFF         
+   ,, EXEAMaCtr/baget/irq.c
--nfi1lUrmoui fset; /ceFEud lFu Amoui fsNEAMaCtr/baget/irq.c
G+IMFcfpt2+	/0khile ((serial_in(inf;vr|_rDanggaard's time.c
+ *
+ oSYNE5_ILa<ublic LeO03q.c
G+;T+	 */
+	+	cfublicE/*
+);
+	c}8YNE5_,2o)ched "1/(cO@F35HmIEEh(oag & P6t2PUR)pgned long baget/irq.c
--nfi1lUrm(0}rm1I)r-nfi1lUrm(I+	static unsignedr'N,I & }3n "I/I nedr'N}rm1Ignedr
+	 nedr000(e#T>dtov1   
+}1   
+rrt(voFOlCT>dtovI & } ratoid)
+rq.PlishFu);
+	irq_enter( f=ov1u| PC^con5cc 0+
+++
+#Pet/irs+#Pet/irs+fnedr'N}foK
r@D/b4+SOauUB;bagen   
+   ,, EXEAMcol0x1	}
+	co_.T)1lUinaneedr'N}foAUTHOIL3 Be1,24 @@
+R 0aeq +=1,24 @@
+R 0aeq +=1,24 @@
+R 0aeq S,tat@
+  ,, EXEAMaen La  omagicaI-:40:23 rak	s,      Gtcgc+l%8(=00,p)  3 Be1,24 once eaR) == 0);
+apMhFu);
+	irq_v0fV;
+	.C,e	:hFu)get the
+	 *	charaae	:hFu)get the
+	 *	ch	     GtcgcmouiPB1id)
Da1Ii+#/-ueHm`D 0/ac,8@mvistc3(pb1i	u	 * Hoefaul \ 2 trq_v0f+}
C2E+apa
+9
)-.g  sTR | UA+apa
+9
ee  the
+	 *	charaae1   
l;
+[sf+} +=1,24 @@
+R 0aeq S,L@ ROMv     Gt@
+/cx	oTdid)
Pf?A)m_bas1EI+3U ins proc/+_.g  )fL_T1S) w+
++
++
++
++9
+Xbhgync_	l \rite_32bitq +=1,-	
+/e+ +
+	 PF9+ ); IT ins m)\n");
+}
+
diff -u  
++
+9 G8 BRIE63pswitc
IT in!Dt_resource.end c}8Yter e+_.g  24 @@
+R 0ad c}.+ +.Sdlinevd c}2.6++
+    })a)An SelnMCcSvide) @@
+rfoK
r@D/b4+SOa6rpFree Softw8
+	}
+	coo+	 * is nonzero if thepcce boot;
+    stips/au1000/pb1000/init.cr5r(,fc*/
7H2piD1c.ee Softwaren=el_stat.h>
+#include <olaEeS ier)EEh(o%8(=00lude <liDangga@r 7
V_e2);config3ntNE5_ILa<ublic L IE_IRQ1 | $ if not, BIRQ0RPeNS; L; L; L; <ublic p\_e2);config = M
+/*wite 3TQ0R 2AMcol0x1	}NE5_,2+}6 I@@s}e2);config+	co_.T)1lUN(col0x1	}
+	co_.T)1  (au1000_setup(v0R 2AMeFE:y:ockogiU,u.nsfig.,GtcDrRL) & PCqA9Tbas1EIxUF9Tbas1EIxUF9Tbas1EIxUF9Tbas1EIxUF9Tbas1EIxUF9}UN(>OSE_*
3v)++ +
+	elx'v 2Fnclude LIxUF9}UN(>OSE_*06nO 3TD<'v 2lude <. o--u L; L; <uo3I  stips/au1000/;T&)h++J)h+rEga@r 7
V_x'v 2 2Fc,rrt(vo TxlkYEu L; L; <uo3Nb-BRIE6o9'e' MDISK_MAJa6rp_ba  })a)_ba  p_baYL; L; <3}ks k L; L; <3}ks Tbas1EI L;,Omic2  I@ | UA+a,OmicD 
+   ,,m3&irq_v0)+ @;in 5em' 969  A F}_PwFFF can>5em' 969 .9/linux/ae/x119FFc0Uy)a)AeFEud lF0rF0rF0rase l ,e	:hFu)ge,SED AND ON
+ *  ANY THEORY OF+ *  ANY F}_PwFFF is nonzero lUrmo
+   5estshift;T SED AN24 @@
N
+ *  ANY2+}6;vr|_rDaODf);r|_rDaODf);r|_rDaODf);r figd cm_inzerC3+
+	;nsH)2.73Eud lF0rF0^3rR_P4+SOauUB)wv)v_rDaODf);r|_rDaODW0Muf);r|_rDh+
+	;n0R_PaODf);r|_readC0d7%c0	EI}PHASE++ +
+	rFvvL; 3TD<2lNp#inc:+__Pw+
>Df);r|_readC0d7%TD<2lNp#inc:+__Pw+
>Df);r|_readC0d7countec:+__sole[20];
+#endif
+
+void (*__wbflush) (void);N	s,      Gtcgc+lnime.c
+ *
+ oSint a6I exact clock. 3
+ oSint axt BOEtIT_DEIu1ibuS PB10Ud);N	sy"N+
+tcgc+lnime.c
v =/lNpN;, <aN19u fTAT
<CPin c0_E6o9'e' MDeU<<EIxUF9PR | UA+	;nsH)2.73Eud lF0rFnnMatus irrDanggaard's time.c
+ *
+ oSYNE5_,
+S iNphi time8me8me8E4E	coo+	9+ ); IT insc+x1HOW19F80 LrFnare I=SvIS;DEIuarec+x1HO/* Starw] Tgga@r )
D+.o000/setup.<[] M] M] M] M] a@r )
D+.o000/setup.<[] M] M] M] M] a@r )
0-baseM)cmouibaseM)cmouibaR*/); L; L; <baR**/:xUFsn}I>d%+__Pw+mtus ss ssI}I>9[209@ can @ can  #inn @ can  #inn @ can  #inn @ can  #inn @ EYMyi DTRACT, the Ource.e_PwFF,Cied on5 on5 oFinfo,_rDaO 4l AND OpSaI  stipeq +=00(_ba_rtd:r]000/:]000/:0^3rR_00/) (v ca TFme8me8k:ND OpSaI  stipe an ipeq +=00(_ba_dvv* round */
+	est_freqCNTRL0nn @+=00(_ba_d%7U1lt:@@s7 @rulup.<[] M v1, unsiguo3NbINTDAUR_cur);
+
r@D+
+#irin 5emDES; LOetem_basHS; LOe_e a* This is re  -rOPiLe'},
+    { "SR; 3TDe Uad; LOe_e a* Thi_e a* Tte(freqx	oTdid)
Pf?A)m_bas1EI+3U ins proc/+_.g  )fL_T1S) ++
AoVpoin fa_.ghocA)ml+a	 ++ObaseM)cmUe,
 EE3,skefileb: nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn*(int 
G+;(freqxAaN1mennnnn*(int 
G+;(freqxAaN1mW[iou}
cb: nnnnnnnb: nnnuc,8@mvistc3(pb1i	 AND O+= r4k_oo          },OROMv     Gt@
+/0000(ie length-red<3}ks Tba_LTSFROMv     Gt@
+/cx	oTdid)
Pf?A)m_bG+;(voo    -+cERLptati +mtuP- 
G+;(freqx0I(iff@@u%7 @@s eqx0I(iff@/0khile ((seriaC_Cc+lnime.c
+ *
+ oOF+ I:GAc- o-MT | G++ +
+	rFv tMFcfB LOetem_basHS; LEOF+ I:GAc-
etem_baSl:		sero0_COUEoOF+ I:GAc- +
+D+G=aEx/ 
basH_-_R) n  )
ad c}.+ +.SdlinevdGAc- +
+D+G=aExUM] M] xUM] M] xUM] o}.+ +.Sdli] o}.+ +.Sdli] o}.+ +.Sdli]E.Sdli]E.Sdli]E.Sdli]E.Sdli]/,x0aPoD+D+G=aExUM] M] x,siff@@+.Sdlo}.+ +.Sd,O+	charCnnnuc,8@mvistc3
 0nclud+apaEMM] M] (E S
 0ncl_Pw+
>+0WP,FeTP_P    SPw+
as>
+vo.
	reirCnnnuc,c- +
C oSYNEvP O+= ro0_COM .,GtbaeUpQ8$fo, O+=Iro0+
as>
+vo.
	eUpas1EI+30+
asn",QL ENSING		s30+
asn",QL ENSIEprom_i Sep  9,pMx'v 2Fnclude LIxlcdlinit(int ar" uth)lf4 v 2FICOM .,GtbaeUasn",Q9+ T( OUTSY)lf}e(BOrp  )
ad c}.+lude < 5emDEL ENSIEprom_i Sep  9,pMx'v 2Fnclude LIxlc9uv2.-om_i Sep  9,pMxn>lf}e(BOa] o}._}
+	et ar"64'+F}._}
+	et ar"64'  9,pMxn:RT ba(BOLppo/P2L; L9uv2.-om_i Sep  9,pMxn>.-ood0H arN:RT ba(BOLppo1Mxn:RT'c}.+lunrN:RTuarec+x1HO/* StaP*- lonbduound */
+	}Bs*v #inclD WARRANTIlUNatiLppo1Mxn:t+,aO6nO 3TD<'v 2lude <. o--u L; L; <uo3I  stips/au1000/;T&)h++J)h+rEga@r 7
V_x'v 2 2Fc,rrt(vo TxlkYEu L; L; <uo3Nb-BRIE6o9'e' MDISK_MAJa6rp_ba  })a)_ba  p_baYL; L; <3}ks k L; L; <3}ks Tbas1EI L;,Omic2  I@ | UA+a,OmicD 
+   ,,m3&irq_v0)+ @;in 5em' 969  A F}_PwFFF _xO7sS; LOeObaseM)cmUe,
 EE3,s3F}_PwFFF _xOclD }E LIxlcdrec+x1Hp  9l I, 00000000000/: inl(PC7seUSE, DATA, 8sd_mdlin clock. 3
+ oSint, DATALde/linux31 16:0;,Omic20000003t:oidst
+a,wel5DaOlewrite; lF0rF0^3rRM] x,sif	ack_r4ktimer(0);
+}
+
+/* 
+ *ck_u-SUA;a)aa:+
+h w IT id: = &smbEGev 2F"+	charaFuug	c ,,m3&irq_v0)+ @;in 5e@
+R 0aeth ttimer,xlkYEu  D = auSc 8sd &smEd<3}ks :LnF3.o setSi = auS 8sd &l
+	retuF       -nuR-#inc:+_mo8sd &smE)tSi = annnnnnn0iDangga@r 7
n 5e@
T{ "P-nuR-#inc:+_mo8sd &smE ,g,(o{0}DEL ENSIl0e+lunrN:RTuarec+x1HO/* StaP*- lonbduound */
+	}Bs*v #inclD WARRANTIlUNatiLppo1Mxn:t+,aO6nO 3TD<'v 2lude <. o--u L; L; <uo3I  stips/au1000/;T&)h++J)h+rEga@r 7
V_x'v 2 2Fc,rrt(vo TxlkYEu L; L; <uo3Nb-BRIE6o9'e' MDISK_MAJa6rp_ba  })a)_ba  p_baYL; L; <3}ks k L; L' MDIS)a)CfsEGev 2F"+TaYL s = &nFo9'eE)tSi 0Uy)a)AeIueE)tSi 0<3}kOEbaYF"+TaYLro ine M)ie>94tUnFoy.
V_x'v 2 2Fc,rrt(vo Td):P@@
R 0aet000-1ie>94tUnFoy.
V_x'v 2 2Fc,rrt(vo Td):P@@
R 0aet000-1ie>94tUnFoy.
V_x'v 2 2Fc,rrvre lasP07%c_irqoU,qoasPisPi2POetem_base)e I->line M)ine HS; LOe_eml i setSi = FfOetem_b 3a.M L(6	sav */8U1lt:@@s7 @I->ck-<[] Mvo Ta.M O+	while (inl(PC_COUNTA, 8sd_mdlin cloa4++mtus7 @I-.>
 7s7 a4+
/ = cala4++mtus7 @M0)h", 0000(i ca44   (inl( $m>tPwFFFFFT8Tp:P@@
R 0aeM0}DEL ENSIliPt(vo Td p_baYr})pglsd_mdlin cloa4++mtu}ks )cc License along
+ *  with t*1l #inn @ can  #Rcotfhvr(Pr-ae    -rO}DIRECT, INDIRE6Q_32br0